@@ -22,6 +22,7 @@ import * as request from 'request';
22
22
import { base64 } from '@firebase/util' ;
23
23
import { setLogLevel , LogLevel } from '@firebase/logger' ;
24
24
import { Component , ComponentType } from '@firebase/component' ;
25
+ import { option } from 'yargs' ;
25
26
26
27
const { firestore, database } = firebase ;
27
28
export { firestore , database } ;
@@ -38,7 +39,7 @@ const FIRESTORE_ADDRESS_DEFAULT: string = 'localhost:8080';
38
39
39
40
/** Environment variable to locate the Emulator Hub */
40
41
const HUB_HOST_ENV : string = 'FIREBASE_EMULATOR_HUB' ;
41
- /** The default address for the Emulator hub */
42
+ /** The default address for the Emulator Hub */
42
43
const HUB_HOST_DEFAULT : string = 'localhost:4400' ;
43
44
44
45
/** The actual address for the database emulator */
@@ -47,6 +48,9 @@ let _databaseHost: string | undefined = undefined;
47
48
/** The actual address for the Firestore emulator */
48
49
let _firestoreHost : string | undefined = undefined ;
49
50
51
+ /** The actual address for the Emulator Hub */
52
+ let _hubHost : string | undefined = undefined ;
53
+
50
54
export type Provider =
51
55
| 'custom'
52
56
| 'email'
@@ -118,6 +122,24 @@ export type FirebaseIdToken = {
118
122
// new users should prefer 'sub' instead.
119
123
export type TokenOptions = Partial < FirebaseIdToken > & { uid ?: string } ;
120
124
125
+ /**
126
+ * Host/port configuration for applicable Firebase Emulators.
127
+ */
128
+ export type FirebaseEmulatorOptions = {
129
+ firestore ?: {
130
+ host : string ;
131
+ port : number ;
132
+ } ;
133
+ database ?: {
134
+ host : string ;
135
+ port : number ;
136
+ } ;
137
+ hub ?: {
138
+ host : string ;
139
+ port : number ;
140
+ } ;
141
+ } ;
142
+
121
143
function createUnsecuredJwt ( token : TokenOptions , projectId ?: string ) : string {
122
144
// Unsecured JWTs use "none" as the algorithm.
123
145
const header = {
@@ -206,6 +228,98 @@ export function initializeAdminApp(options: AdminAppOptions): firebase.app.App {
206
228
return app ;
207
229
}
208
230
231
+ /**
232
+ * Set the host and port configuration for applicable emulators. This will override any values
233
+ * found in environment variables. Must be called before initializeAdminApp or initializeTestApp.
234
+ *
235
+ * @param options options object.
236
+ */
237
+ export function useEmulators ( options : FirebaseEmulatorOptions ) : void {
238
+ if ( ! ( options . database || options . firestore || options . hub ) ) {
239
+ throw new Error (
240
+ "Argument to useEmulators must contain at least one of 'database', 'firestore', or 'hub'."
241
+ ) ;
242
+ }
243
+
244
+ if ( options . database ) {
245
+ _databaseHost = getAddress ( options . database . host , options . database . port ) ;
246
+ }
247
+
248
+ if ( options . firestore ) {
249
+ _firestoreHost = getAddress ( options . firestore . host , options . firestore . port ) ;
250
+ }
251
+
252
+ if ( options . hub ) {
253
+ _hubHost = getAddress ( options . hub . host , options . hub . port ) ;
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Use the Firebase Emulator hub to discover other running emulators. Call useEmulators() with
259
+ * the result to configure the library to use the discovered emulators.
260
+ *
261
+ * @param hubHost the host where the Emulator Hub is running (ex: 'localhost')
262
+ * @param hubPort the port where the Emulator Hub is running (ex: 4400)
263
+ */
264
+ export async function discoverEmulators (
265
+ hubHost ?: string ,
266
+ hubPort ?: number
267
+ ) : Promise < FirebaseEmulatorOptions > {
268
+ if ( ( hubHost && ! hubPort ) || ( ! hubHost && hubPort ) ) {
269
+ throw new Error (
270
+ `Invalid configuration hubHost=${ hubHost } and hubPort=${ hubPort } . If either parameter is supplied, both must be defined.`
271
+ ) ;
272
+ }
273
+
274
+ const hubAddress =
275
+ hubHost && hubPort ? getAddress ( hubHost , hubPort ) : getHubHost ( ) ;
276
+
277
+ const res = await requestPromise ( request . get , {
278
+ method : 'GET' ,
279
+ uri : `http://${ hubAddress } /emulators`
280
+ } ) ;
281
+ if ( res . statusCode !== 200 ) {
282
+ throw new Error (
283
+ `HTTP Error ${ res . statusCode } when attempting to reach Emulator Hub at ${ hubAddress } , are you sure it is running?`
284
+ ) ;
285
+ }
286
+
287
+ const options : FirebaseEmulatorOptions = { } ;
288
+
289
+ const data = JSON . parse ( res . body ) ;
290
+
291
+ if ( data . database ) {
292
+ options . database = {
293
+ host : data . database . host ,
294
+ port : data . database . port
295
+ } ;
296
+ }
297
+
298
+ if ( data . firestore ) {
299
+ options . firestore = {
300
+ host : data . firestore . host ,
301
+ port : data . firestore . port
302
+ } ;
303
+ }
304
+
305
+ if ( data . hub ) {
306
+ options . hub = {
307
+ host : data . hub . host ,
308
+ port : data . hub . port
309
+ } ;
310
+ }
311
+
312
+ return options ;
313
+ }
314
+
315
+ function getAddress ( host : string , port : number ) {
316
+ if ( host . includes ( '::' ) ) {
317
+ return `[${ host } ]:${ port } ` ;
318
+ } else {
319
+ return `${ host } :${ port } ` ;
320
+ }
321
+ }
322
+
209
323
function getDatabaseHost ( ) {
210
324
if ( ! _databaseHost ) {
211
325
const fromEnv = process . env [ DATABASE_ADDRESS_ENV ] ;
@@ -238,6 +352,22 @@ function getFirestoreHost() {
238
352
return _firestoreHost ;
239
353
}
240
354
355
+ function getHubHost ( ) {
356
+ if ( ! _hubHost ) {
357
+ const fromEnv = process . env [ HUB_HOST_ENV ] ;
358
+ if ( fromEnv ) {
359
+ _hubHost = fromEnv ;
360
+ } else {
361
+ console . warn (
362
+ `Warning: ${ HUB_HOST_ENV } not set, using default value ${ HUB_HOST_DEFAULT } `
363
+ ) ;
364
+ _hubHost = HUB_HOST_DEFAULT ;
365
+ }
366
+ }
367
+
368
+ return _hubHost ;
369
+ }
370
+
241
371
function getRandomAppName ( ) : string {
242
372
return 'app-' + new Date ( ) . getTime ( ) + '-' + Math . random ( ) ;
243
373
}
@@ -406,13 +536,7 @@ export async function clearFirestoreData(
406
536
export async function withFunctionTriggersDisabled < TResult > (
407
537
fn : ( ) => TResult | Promise < TResult >
408
538
) : Promise < TResult > {
409
- let hubHost = process . env [ HUB_HOST_ENV ] ;
410
- if ( ! hubHost ) {
411
- console . warn (
412
- `${ HUB_HOST_ENV } is not set, assuming the Emulator hub is running at ${ HUB_HOST_DEFAULT } `
413
- ) ;
414
- hubHost = HUB_HOST_DEFAULT ;
415
- }
539
+ const hubHost = getHubHost ( ) ;
416
540
417
541
// Disable background triggers
418
542
const disableRes = await requestPromise ( request . put , {
0 commit comments