@@ -24,11 +24,12 @@ import * as spawn from "cross-spawn";
24
24
import { ChildProcess , spawnSync } from "child_process" ;
25
25
import {
26
26
EmulatedTriggerDefinition ,
27
+ ParsedTriggerDefinition ,
27
28
EmulatedTriggerType ,
28
29
FunctionsRuntimeArgs ,
29
30
FunctionsRuntimeBundle ,
30
31
FunctionsRuntimeFeatures ,
31
- getFunctionRegion ,
32
+ emulatedFunctionsByRegion ,
32
33
getFunctionService ,
33
34
HttpConstants ,
34
35
EventTrigger ,
@@ -75,7 +76,7 @@ export interface FunctionsEmulatorArgs {
75
76
debugPort ?: number ;
76
77
env ?: { [ key : string ] : string } ;
77
78
remoteEmulators ?: { [ key : string ] : EmulatorInfo } ;
78
- predefinedTriggers ?: EmulatedTriggerDefinition [ ] ;
79
+ predefinedTriggers ?: ParsedTriggerDefinition [ ] ;
79
80
nodeMajorVersion ?: number ; // Lets us specify the node version when emulating extensions.
80
81
}
81
82
@@ -99,7 +100,7 @@ export interface FunctionsRuntimeInstance {
99
100
export interface InvokeRuntimeOpts {
100
101
nodeBinary : string ;
101
102
serializedTriggers ?: string ;
102
- extensionTriggers ?: EmulatedTriggerDefinition [ ] ;
103
+ extensionTriggers ?: ParsedTriggerDefinition [ ] ;
103
104
env ?: { [ key : string ] : string } ;
104
105
ignore_warnings ?: boolean ;
105
106
}
@@ -221,8 +222,10 @@ export class FunctionsEmulator implements EmulatorInstance {
221
222
const httpsFunctionRoutes = [ httpsFunctionRoute , `${ httpsFunctionRoute } /*` ] ;
222
223
223
224
const backgroundHandler : express . RequestHandler = ( req , res ) => {
225
+ const region = req . params . region ;
224
226
const triggerId = req . params . trigger_name ;
225
227
const projectId = req . params . project_id ;
228
+
226
229
const reqBody = ( req as RequestWithRawBody ) . rawBody ;
227
230
const proto = JSON . parse ( reqBody . toString ( ) ) ;
228
231
@@ -282,6 +285,7 @@ export class FunctionsEmulator implements EmulatorInstance {
282
285
283
286
startFunctionRuntime (
284
287
triggerId : string ,
288
+ targetName : string ,
285
289
triggerType : EmulatedTriggerType ,
286
290
proto ?: any ,
287
291
runtimeOpts ?: InvokeRuntimeOpts
@@ -299,6 +303,7 @@ export class FunctionsEmulator implements EmulatorInstance {
299
303
nodeMajorVersion : this . args . nodeMajorVersion ,
300
304
proto,
301
305
triggerId,
306
+ targetName,
302
307
triggerType,
303
308
} ;
304
309
const opts = runtimeOpts || {
@@ -395,7 +400,7 @@ export class FunctionsEmulator implements EmulatorInstance {
395
400
*
396
401
* TODO(abehaskins): Gracefully handle removal of deleted function definitions
397
402
*/
398
- async loadTriggers ( force : boolean = false ) {
403
+ async loadTriggers ( force = false ) : Promise < void > {
399
404
// Before loading any triggers we need to make sure there are no 'stale' workers
400
405
// in the pool that would cause us to run old code.
401
406
this . workerPool . refresh ( ) ;
@@ -411,8 +416,13 @@ export class FunctionsEmulator implements EmulatorInstance {
411
416
"SYSTEM" ,
412
417
"triggers-parsed"
413
418
) ;
414
- const triggerDefinitions = triggerParseEvent . data
415
- . triggerDefinitions as EmulatedTriggerDefinition [ ] ;
419
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
420
+ const parsedDefinitions = triggerParseEvent . data
421
+ . triggerDefinitions as ParsedTriggerDefinition [ ] ;
422
+
423
+ const triggerDefinitions : EmulatedTriggerDefinition [ ] = emulatedFunctionsByRegion (
424
+ parsedDefinitions
425
+ ) ;
416
426
417
427
// When force is true we set up all triggers, otherwise we only set up
418
428
// triggers which have a unique function name
@@ -434,17 +444,14 @@ export class FunctionsEmulator implements EmulatorInstance {
434
444
let url : string | undefined = undefined ;
435
445
436
446
if ( definition . httpsTrigger ) {
437
- // TODO(samstern): Right now we only emulate each function in one region, but it's possible
438
- // that a developer is running the same function in multiple regions.
439
- const region = getFunctionRegion ( definition ) ;
440
447
const { host, port } = this . getInfo ( ) ;
441
448
added = true ;
442
449
url = FunctionsEmulator . getHttpFunctionUrl (
443
450
host ,
444
451
port ,
445
452
this . args . projectId ,
446
453
definition . name ,
447
- region
454
+ definition . region
448
455
) ;
449
456
} else if ( definition . eventTrigger ) {
450
457
const service : string = getFunctionService ( definition ) ;
@@ -499,12 +506,12 @@ export class FunctionsEmulator implements EmulatorInstance {
499
506
500
507
if ( ignored ) {
501
508
const msg = `function ignored because the ${ type } emulator does not exist or is not running.` ;
502
- this . logger . logLabeled ( "BULLET" , `functions[${ definition . name } ]` , msg ) ;
509
+ this . logger . logLabeled ( "BULLET" , `functions[${ definition . id } ]` , msg ) ;
503
510
} else {
504
511
const msg = url
505
512
? `${ clc . bold ( type ) } function initialized (${ url } ).`
506
513
: `${ clc . bold ( type ) } function initialized.` ;
507
- this . logger . logLabeled ( "SUCCESS" , `functions[${ definition . name } ]` , msg ) ;
514
+ this . logger . logLabeled ( "SUCCESS" , `functions[${ definition . id } ]` , msg ) ;
508
515
}
509
516
}
510
517
}
@@ -683,14 +690,9 @@ export class FunctionsEmulator implements EmulatorInstance {
683
690
return record . def ;
684
691
}
685
692
686
- getTriggerDefinitionByName ( triggerName : string ) : EmulatedTriggerDefinition | undefined {
687
- const record = Object . values ( this . triggers ) . find ( ( r ) => r . def . name === triggerName ) ;
688
- return record ?. def ;
689
- }
690
-
691
693
getTriggerKey ( def : EmulatedTriggerDefinition ) : string {
692
694
// For background triggers we attach the current generation as a suffix
693
- return def . eventTrigger ? def . name + "-" + this . triggerGeneration : def . name ;
695
+ return def . eventTrigger ? ` ${ def . id } - ${ this . triggerGeneration } ` : def . id ;
694
696
}
695
697
696
698
addTriggerRecord (
@@ -713,6 +715,7 @@ export class FunctionsEmulator implements EmulatorInstance {
713
715
cwd : this . args . functionsDir ,
714
716
projectId : this . args . projectId ,
715
717
triggerId : "" ,
718
+ targetName : "" ,
716
719
triggerType : undefined ,
717
720
emulators : {
718
721
firestore : EmulatorRegistry . getInfo ( Emulators . FIRESTORE ) ,
@@ -922,7 +925,12 @@ export class FunctionsEmulator implements EmulatorInstance {
922
925
923
926
const trigger = this . getTriggerDefinitionByKey ( triggerKey ) ;
924
927
const service = getFunctionService ( trigger ) ;
925
- const worker = this . startFunctionRuntime ( trigger . name , EmulatedTriggerType . BACKGROUND , proto ) ;
928
+ const worker = this . startFunctionRuntime (
929
+ trigger . id ,
930
+ trigger . name ,
931
+ EmulatedTriggerType . BACKGROUND ,
932
+ proto
933
+ ) ;
926
934
927
935
return new Promise ( ( resolve , reject ) => {
928
936
if ( projectId !== this . args . projectId ) {
@@ -1018,7 +1026,9 @@ export class FunctionsEmulator implements EmulatorInstance {
1018
1026
1019
1027
private async handleHttpsTrigger ( req : express . Request , res : express . Response ) {
1020
1028
const method = req . method ;
1021
- const triggerId = req . params . trigger_name ;
1029
+ const region = req . params . region ;
1030
+ const triggerName = req . params . trigger_name ;
1031
+ const triggerId = `${ region } -${ triggerName } ` ;
1022
1032
1023
1033
if ( ! this . triggers [ triggerId ] ) {
1024
1034
res
@@ -1057,8 +1067,12 @@ export class FunctionsEmulator implements EmulatorInstance {
1057
1067
) ;
1058
1068
}
1059
1069
}
1060
-
1061
- const worker = this . startFunctionRuntime ( trigger . name , EmulatedTriggerType . HTTPS , undefined ) ;
1070
+ const worker = this . startFunctionRuntime (
1071
+ trigger . id ,
1072
+ trigger . name ,
1073
+ EmulatedTriggerType . HTTPS ,
1074
+ undefined
1075
+ ) ;
1062
1076
1063
1077
worker . onLogs ( ( el : EmulatorLog ) => {
1064
1078
if ( el . level === "FATAL" ) {
@@ -1087,7 +1101,7 @@ export class FunctionsEmulator implements EmulatorInstance {
1087
1101
// req.url = /:projectId/:region/:trigger_name/*
1088
1102
const url = new URL ( `${ req . protocol } ://${ req . hostname } ${ req . url } ` ) ;
1089
1103
const path = `${ url . pathname } ${ url . search } ` . replace (
1090
- new RegExp ( `\/${ this . args . projectId } \/[^\/]*\/${ triggerId } \/?` ) ,
1104
+ new RegExp ( `\/${ this . args . projectId } \/[^\/]*\/${ triggerName } \/?` ) ,
1091
1105
"/"
1092
1106
) ;
1093
1107
0 commit comments