/** * Port Allocator * * Finds the next available port for the gateway. * Only called once when the gateway first starts — subsequent previews * reuse the same gateway port. */ import { createServer } from 'node:net'; import { createModuleLogger } from '../logger/index.js'; const log = createModuleLogger('preview:port'); /** Starting port for preview deployments */ const BASE_PORT = 9100; /** Maximum port to try before giving up */ const MAX_PORT = 9200; /** * Allocate the next available port by performing a bind test. * * @returns An available port number * @throws If no port is available in the range */ export async function allocatePort(): Promise { for (let port = BASE_PORT; port < MAX_PORT; port++) { if (await isPortAvailable(port)) { log.info({ port }, 'allocated port'); return port; } } throw new Error(`No available ports in range ${BASE_PORT}-${MAX_PORT}`); } /** * Test if a port is available by attempting to bind to it. */ async function isPortAvailable(port: number): Promise { return new Promise((resolve) => { const server = createServer(); server.once('error', () => { resolve(false); }); server.listen(port, '127.0.0.1', () => { server.close(() => { resolve(true); }); }); }); }