1
1
import fs from 'fs' ;
2
+ import net from 'net' ;
2
3
import path from 'path' ;
3
4
4
5
import {
@@ -10,6 +11,7 @@ import {
10
11
} from '@sesamecare-oss/confit' ;
11
12
12
13
import { findPort } from '../development/port-finder' ;
14
+ import { isTest } from '../env' ;
13
15
14
16
import type { ConfigurationSchema } from './schema' ;
15
17
@@ -55,6 +57,28 @@ async function addDefaultConfiguration<Config extends ConfigurationSchema = Conf
55
57
}
56
58
}
57
59
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
+
58
82
export interface ServiceConfigurationSpec {
59
83
// The LAST configuration is the most "specific" - if a configuration value
60
84
// exists in all directories, the last one wins
@@ -93,7 +117,8 @@ export async function loadConfiguration<Config extends ConfigurationSchema>({
93
117
// configured to auto-select
94
118
const serverConfig = loaded . get ( ) . server ;
95
119
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 ;
97
122
const store = loaded . get ( ) ;
98
123
store . server = store . server || { } ;
99
124
store . server . port = port ;
0 commit comments