11import { Config } from '@oclif/core' ;
22import cors from 'cors' ;
33import express , { json } from 'express' ;
4+ import killPort from 'kill-port' ;
45import { randomBytes } from 'node:crypto' ;
6+ import { Server } from 'node:http' ;
57import open from 'open' ;
68
79import { config } from '../config.js' ;
810import router from '../connect/http-routes/router.js' ;
911import { LoginHelper } from '../connect/login-helper.js' ;
1012import { SocketServer } from '../connect/socket-server.js' ;
13+ import { ProcessName , ctx } from '../events/context.js' ;
14+ import { Reporter } from '../ui/reporters/reporter.js' ;
1115import { LoginOrchestrator } from './login.js' ;
1216
1317export class ConnectOrchestrator {
1418 static rootCommand : string ;
1519 static nodeBinary : string ;
1620
17- static async run ( oclifConfig : Config , openBrowser = true , onOpen ?: ( connectionCode : string ) => void ) {
21+ static async run ( oclifConfig : Config , reporter : Reporter , openBrowser = true , onOpen ?: ( connectionCode : string ) => void ) {
1822 const login = LoginHelper . get ( ) ?. isLoggedIn ;
1923 if ( ! login ) {
20- console . log ( 'User is not logged in. Attempting to log in...' )
24+ ctx . log ( 'User is not logged in. Attempting to log in...' )
2125 await LoginOrchestrator . run ( ) ;
2226 }
2327
@@ -31,16 +35,7 @@ export class ConnectOrchestrator {
3135 app . use ( json ( ) )
3236 app . use ( router ) ;
3337
34- const server = app . listen ( config . connectServerPort , ( error ) => {
35- if ( error ) {
36- if ( error . message . includes ( 'EADDRINUSE' ) ) {
37- console . error ( 'An instance of \'codify connect\' is already running.\n\nExiting...' )
38- return ;
39- }
40-
41- throw error ;
42- }
43-
38+ const server = await ConnectOrchestrator . listen ( app , reporter , ( ) => {
4439 if ( openBrowser ) {
4540 open ( `${ config . dashboardUrl } /connection/success?code=${ connectionSecret } ` )
4641 console . log ( `Open browser window to store code.
@@ -55,6 +50,38 @@ ${connectionSecret}`)
5550 SocketServer . init ( server , connectionSecret ) ;
5651 }
5752
53+ private static listen ( app : express . Application , reporter : Reporter , onOpen : ( ) => void ) : Promise < Server > {
54+ return new Promise ( ( resolve ) => {
55+ const server = app . listen ( config . connectServerPort , async ( error ) => {
56+ if ( error ) {
57+ if ( error . message . includes ( 'EADDRINUSE' ) ) {
58+ const ifTerminate = await reporter . promptConfirmation ( 'An instance of \'codify connect\' is already running. Do you want to terminate the existing instance and continue?' ) ;
59+
60+ if ( ! ifTerminate ) {
61+ console . error ( '\n\nExiting...' )
62+ process . exit ( 1 ) ;
63+ }
64+
65+ ctx . processStarted ( ProcessName . TERMINATE )
66+ await reporter . displayProgress ( ) ;
67+ await killPort ( config . connectServerPort ) ;
68+ ctx . processFinished ( ProcessName . TERMINATE ) ;
69+ await reporter . hide ( ) ;
70+
71+ setTimeout ( ( ) => {
72+ ctx . log ( 'Retrying connection...' )
73+ ConnectOrchestrator . listen ( app , reporter , onOpen ) . then ( ( server ) => resolve ( server ) ) ;
74+ } , 300 ) ;
75+
76+ }
77+ } else {
78+ resolve ( server ) ;
79+ onOpen ( ) ;
80+ }
81+ } ) ;
82+ } ) ;
83+ }
84+
5885 private static tokenGenerate ( bytes = 4 ) : string {
5986 return Buffer . from ( randomBytes ( bytes ) ) . toString ( 'hex' )
6087 }
0 commit comments