11import fs from 'fs' ;
2+ import net from 'net' ;
23import path from 'path' ;
34
45import {
@@ -10,6 +11,7 @@ import {
1011} from '@sesamecare-oss/confit' ;
1112
1213import { findPort } from '../development/port-finder' ;
14+ import { isTest } from '../env' ;
1315
1416import type { ConfigurationSchema } from './schema' ;
1517
@@ -55,6 +57,28 @@ async function addDefaultConfiguration<Config extends ConfigurationSchema = Conf
5557 }
5658}
5759
60+ async function getEphemeralPort ( ) : Promise < number > {
61+ return new Promise ( ( resolve , reject ) => {
62+ const server = net . createServer ( ) ;
63+
64+ server . listen ( 0 , ( ) => {
65+ const address = server . address ( ) ;
66+ if ( typeof address === 'string' || ! address ) {
67+ reject ( new Error ( 'Invalid address' ) ) ;
68+ return ;
69+ }
70+ const port = address . port ; // Retrieve the ephemeral port
71+ server . close ( ( err ) => {
72+ if ( err ) {
73+ reject ( err ) ;
74+ } else {
75+ resolve ( port ) ;
76+ }
77+ } ) ;
78+ } ) ;
79+ } ) ;
80+ }
81+
5882export interface ServiceConfigurationSpec {
5983 // The LAST configuration is the most "specific" - if a configuration value
6084 // exists in all directories, the last one wins
@@ -93,7 +117,8 @@ export async function loadConfiguration<Config extends ConfigurationSchema>({
93117 // configured to auto-select
94118 const serverConfig = loaded . get ( ) . server ;
95119 if ( serverConfig . port === 0 ) {
96- const port = ( await findPort ( 8001 ) ) as number ;
120+ const portPromise : Promise < number > = isTest ( ) ? getEphemeralPort ( ) : findPort ( 8001 ) ;
121+ const port = await portPromise ;
97122 const store = loaded . get ( ) ;
98123 store . server = store . server || { } ;
99124 store . server . port = port ;
0 commit comments