@@ -20,6 +20,12 @@ export const DEFAULT_PROGRAM = 'ionic-app-scripts';
20
20
export const DEFAULT_SERVE_SCRIPT_VALUE = `${ DEFAULT_PROGRAM } serve` ;
21
21
const APP_SCRIPTS_SERVE_CONNECTIVITY_TIMEOUT = 20000 ; // ms
22
22
23
+ interface Ports {
24
+ port : number ;
25
+ livereloadPort : number ;
26
+ notificationPort : number ;
27
+ }
28
+
23
29
interface ServeCmdDetails {
24
30
program : string ;
25
31
}
@@ -75,15 +81,17 @@ export class ServeRunner extends BaseServeRunner<IonicAngularServeOptions> {
75
81
}
76
82
77
83
async serveProject ( options : IonicAngularServeOptions ) : Promise < ServeDetails > {
78
- const { findClosestOpenPort , isHostConnectable } = await import ( '../../utils/network' ) ;
84
+ const { isHostConnectable } = await import ( '../../utils/network' ) ;
79
85
const [ externalIP , availableInterfaces ] = await this . selectExternalIP ( options ) ;
86
+ const { port, livereloadPort, notificationPort } = await this . findOpenPorts ( options . address , options ) ;
80
87
81
- const port = await findClosestOpenPort ( options . port , '0.0.0.0' ) ;
82
88
options . port = port ;
89
+ options . livereloadPort = livereloadPort ;
90
+ options . notificationPort = notificationPort ;
83
91
84
92
const { program } = await this . serveCommandWrapper ( options ) ;
85
93
86
- debug ( ' waiting for connectivity with app-scripts (%dms timeout)' , APP_SCRIPTS_SERVE_CONNECTIVITY_TIMEOUT ) ;
94
+ debug ( ` waiting for connectivity with ${ program } ( ${ APP_SCRIPTS_SERVE_CONNECTIVITY_TIMEOUT } ms timeout)` ) ;
87
95
await isHostConnectable ( 'localhost' , port , APP_SCRIPTS_SERVE_CONNECTIVITY_TIMEOUT ) ;
88
96
89
97
return {
@@ -202,4 +210,39 @@ export class ServeRunner extends BaseServeRunner<IonicAngularServeOptions> {
202
210
203
211
return [ ...unparseArgs ( args , { useEquals : false } ) , ...options [ '--' ] ] ;
204
212
}
213
+
214
+ private async findOpenPorts ( address : string , ports : Ports ) : Promise < Ports > {
215
+ const { ERROR_NETWORK_ADDRESS_NOT_AVAIL , findClosestOpenPort } = await import ( '../../utils/network' ) ;
216
+
217
+ try {
218
+ const [ port , livereloadPort , notificationPort ] = await Promise . all ( [
219
+ findClosestOpenPort ( ports . port , '0.0.0.0' ) ,
220
+ findClosestOpenPort ( ports . livereloadPort , '0.0.0.0' ) ,
221
+ findClosestOpenPort ( ports . notificationPort , '0.0.0.0' ) ,
222
+ ] ) ;
223
+
224
+ if ( ports . port !== port ) {
225
+ debug ( `Port ${ chalk . bold ( String ( ports . port ) ) } taken, using ${ chalk . bold ( String ( port ) ) } .` ) ;
226
+ ports . port = port ;
227
+ }
228
+
229
+ if ( ports . livereloadPort !== livereloadPort ) {
230
+ debug ( `Port ${ chalk . bold ( String ( ports . livereloadPort ) ) } taken, using ${ chalk . bold ( String ( livereloadPort ) ) } .` ) ;
231
+ ports . livereloadPort = livereloadPort ;
232
+ }
233
+
234
+ if ( ports . notificationPort !== notificationPort ) {
235
+ debug ( `Port ${ chalk . bold ( String ( ports . notificationPort ) ) } taken, using ${ chalk . bold ( String ( notificationPort ) ) } .` ) ;
236
+ ports . notificationPort = notificationPort ;
237
+ }
238
+
239
+ return { port, livereloadPort, notificationPort } ;
240
+ } catch ( e ) {
241
+ if ( e !== ERROR_NETWORK_ADDRESS_NOT_AVAIL ) {
242
+ throw e ;
243
+ }
244
+
245
+ throw new FatalException ( `${ chalk . green ( address ) } is not available--cannot bind.` ) ;
246
+ }
247
+ }
205
248
}
0 commit comments