auto-select available port in dev mode

In dev mode (NODE_ENV !== 'production'), defaults getter automatically
finds an available port if the requested one is taken.
This commit is contained in:
Claude 2026-01-07 19:04:20 +00:00
parent 861a024a1f
commit 82a13a3768
No known key found for this signature in database
2 changed files with 68 additions and 1 deletions

View File

@ -161,14 +161,37 @@ export class Hype<
get defaults() {
this.registerRoutes()
const isDev = process.env.NODE_ENV !== 'production'
let port = process.env.PORT ? Number(process.env.PORT) : 3000
if (isDev) {
port = findAvailablePortSync(port)
}
return {
port: process.env.PORT ?? '3000',
port,
fetch: this.fetch,
idleTimeout: 255
}
}
}
/**
* Synchronously find an available port starting from the given port
*/
function findAvailablePortSync(startPort: number, maxAttempts = 100): number {
for (let port = startPort; port < startPort + maxAttempts; port++) {
try {
const server = Bun.serve({ port, fetch: () => new Response() })
server.stop(true)
return port
} catch {
continue
}
}
throw new Error(`Could not find an available port after ${maxAttempts} attempts starting from ${startPort}`)
}
function render404(c: Context) {
return c.text('File not found', 404)
}

View File

@ -0,0 +1,44 @@
import { test, expect } from "bun:test"
import { Hype } from "./index.tsx"
test("defaults returns next available port in dev mode", () => {
// Start a server on port 4000 to block it
const blocker = Bun.serve({
port: 4000,
fetch: () => new Response("blocker"),
})
// Set NODE_ENV to development and PORT to 4000
const originalNodeEnv = process.env.NODE_ENV
const originalPort = process.env.PORT
process.env.NODE_ENV = "development"
process.env.PORT = "4000"
const app = new Hype({})
const config = app.defaults
// Should have found port 4001 since 4000 is taken
expect(config.port).toBe(4001)
// Clean up
blocker.stop(true)
process.env.NODE_ENV = originalNodeEnv
process.env.PORT = originalPort
})
test("defaults uses exact port in production mode", () => {
const originalNodeEnv = process.env.NODE_ENV
const originalPort = process.env.PORT
process.env.NODE_ENV = "production"
process.env.PORT = "4002"
const app = new Hype({})
const config = app.defaults
// Should use exact port in production
expect(config.port).toBe(4002)
// Clean up
process.env.NODE_ENV = originalNodeEnv
process.env.PORT = originalPort
})