@@ -42,7 +42,7 @@ function openBrowser(url: string) {
4242}
4343
4444export async function startStudio ( options : { port : number ; dir : string , open ?: boolean } ) {
45- const port = options . port || 3000 ;
45+ const startPort = options . port || 5555 ;
4646 const rootDir = path . resolve ( process . cwd ( ) , options . dir || '.' ) ;
4747
4848 console . log ( chalk . blue ( 'Starting ObjectQL Studio...' ) ) ;
@@ -297,13 +297,35 @@ export async function startStudio(options: { port: number; dir: string, open?: b
297297 res . end ( 'Not Found' ) ;
298298 } ) ;
299299
300- server . listen ( port , ( ) => {
301- const url = `http://localhost:${ port } /studio` ;
302- console . log ( chalk . green ( `\n🚀 Studio running at: ${ chalk . bold ( url ) } ` ) ) ;
303- console . log ( chalk . gray ( ` API endpoint: http://localhost:${ port } /api` ) ) ;
304-
305- if ( options . open ) {
306- openBrowser ( url ) ;
307- }
308- } ) ;
300+ const tryListen = ( port : number ) => {
301+ server . removeAllListeners ( 'error' ) ;
302+ server . removeAllListeners ( 'listening' ) ; // Prevent stacking callbacks
303+
304+ server . on ( 'error' , ( e : any ) => {
305+ if ( e . code === 'EADDRINUSE' ) {
306+ if ( port - startPort < 10 ) {
307+ console . log ( chalk . yellow ( `Port ${ port } is in use, trying ${ port + 1 } ...` ) ) ;
308+ server . close ( ) ;
309+ tryListen ( port + 1 ) ;
310+ } else {
311+ console . error ( chalk . red ( `❌ Unable to find a free port.` ) ) ;
312+ process . exit ( 1 ) ;
313+ }
314+ } else {
315+ console . error ( chalk . red ( '❌ Server error:' ) , e ) ;
316+ }
317+ } ) ;
318+
319+ server . listen ( port , ( ) => {
320+ const url = `http://localhost:${ port } /studio` ;
321+ console . log ( chalk . green ( `\n🚀 Studio running at: ${ chalk . bold ( url ) } ` ) ) ;
322+ console . log ( chalk . gray ( ` API endpoint: http://localhost:${ port } /api` ) ) ;
323+
324+ if ( options . open ) {
325+ openBrowser ( url ) ;
326+ }
327+ } ) ;
328+ } ;
329+
330+ tryListen ( startPort ) ;
309331}
0 commit comments