firebase-tools 10.1.5 → 10.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/lib/api.js +1 -0
  2. package/lib/apiv2.js +3 -0
  3. package/lib/appdistribution/options-parser-util.js +1 -1
  4. package/lib/auth.js +62 -25
  5. package/lib/command.js +1 -1
  6. package/lib/commands/apps-android-sha-create.js +2 -2
  7. package/lib/commands/apps-sdkconfig.js +1 -1
  8. package/lib/commands/auth-import.js +1 -1
  9. package/lib/commands/database-rules-list.js +2 -2
  10. package/lib/commands/emulators-start.js +1 -1
  11. package/lib/commands/ext-configure.js +1 -0
  12. package/lib/commands/ext-dev-init.js +49 -49
  13. package/lib/commands/ext-export.js +12 -2
  14. package/lib/commands/ext-install.js +104 -103
  15. package/lib/commands/ext-uninstall.js +9 -8
  16. package/lib/commands/ext-update.js +10 -9
  17. package/lib/commands/functions-config-clone.js +1 -1
  18. package/lib/commands/functions-config-export.js +1 -1
  19. package/lib/commands/functions-secrets-access.js +17 -0
  20. package/lib/commands/functions-secrets-destroy.js +40 -0
  21. package/lib/commands/functions-secrets-get.js +21 -0
  22. package/lib/commands/functions-secrets-prune.js +50 -0
  23. package/lib/commands/functions-secrets-set.js +46 -0
  24. package/lib/commands/hosting-clone.js +3 -3
  25. package/lib/commands/index.js +7 -3
  26. package/lib/commands/login.js +1 -1
  27. package/lib/commands/remoteconfig-get.js +1 -1
  28. package/lib/deploy/extensions/deploymentSummary.js +3 -3
  29. package/lib/deploy/extensions/params.js +3 -0
  30. package/lib/deploy/extensions/planner.js +2 -1
  31. package/lib/deploy/extensions/tasks.js +1 -1
  32. package/lib/deploy/functions/backend.js +20 -5
  33. package/lib/deploy/functions/checkIam.js +1 -1
  34. package/lib/deploy/functions/containerCleaner.js +3 -3
  35. package/lib/deploy/functions/ensure.js +112 -0
  36. package/lib/deploy/functions/ensureCloudBuildEnabled.js +0 -49
  37. package/lib/deploy/functions/functionsDeployHelper.js +2 -2
  38. package/lib/deploy/functions/prepare.js +15 -20
  39. package/lib/deploy/functions/pricing.js +1 -1
  40. package/lib/deploy/functions/prompts.js +2 -2
  41. package/lib/deploy/functions/release/fabricator.js +3 -3
  42. package/lib/deploy/functions/release/index.js +1 -1
  43. package/lib/deploy/functions/release/planner.js +11 -8
  44. package/lib/deploy/functions/release/reporter.js +3 -0
  45. package/lib/deploy/functions/runtimes/discovery/index.js +6 -6
  46. package/lib/deploy/functions/runtimes/discovery/parsing.js +1 -1
  47. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +17 -11
  48. package/lib/deploy/functions/runtimes/golang/index.js +2 -2
  49. package/lib/deploy/functions/runtimes/node/index.js +26 -0
  50. package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +2 -2
  51. package/lib/deploy/functions/runtimes/node/parseTriggers.js +40 -7
  52. package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
  53. package/lib/deploy/functions/validate.js +58 -3
  54. package/lib/deploy/hosting/client.js +9 -0
  55. package/lib/deploy/hosting/convertConfig.js +6 -0
  56. package/lib/deploy/hosting/deploy.js +2 -2
  57. package/lib/deploy/hosting/hashcache.js +21 -19
  58. package/lib/deploy/hosting/index.js +5 -5
  59. package/lib/deploy/hosting/prepare.js +25 -25
  60. package/lib/deploy/hosting/release.js +21 -24
  61. package/lib/deploy/hosting/uploader.js +5 -5
  62. package/lib/deploy/remoteconfig/functions.js +2 -2
  63. package/lib/emulator/auth/cloudFunctions.js +1 -1
  64. package/lib/emulator/auth/operations.js +1 -1
  65. package/lib/emulator/commandUtils.js +5 -1
  66. package/lib/emulator/constants.js +3 -0
  67. package/lib/emulator/controller.js +48 -18
  68. package/lib/emulator/download.js +18 -1
  69. package/lib/emulator/downloadableEmulators.js +30 -13
  70. package/lib/emulator/emulatorLogger.js +19 -1
  71. package/lib/emulator/extensions/validation.js +35 -0
  72. package/lib/emulator/extensionsEmulator.js +140 -0
  73. package/lib/emulator/functionsEmulator.js +175 -86
  74. package/lib/emulator/functionsEmulatorRuntime.js +108 -83
  75. package/lib/emulator/functionsEmulatorShared.js +51 -1
  76. package/lib/emulator/functionsEmulatorShell.js +1 -2
  77. package/lib/emulator/functionsEmulatorUtils.js +4 -4
  78. package/lib/emulator/functionsRuntimeWorker.js +3 -3
  79. package/lib/emulator/hub.js +4 -3
  80. package/lib/emulator/loggingEmulator.js +1 -1
  81. package/lib/emulator/pubsubEmulator.js +1 -1
  82. package/lib/emulator/registry.js +10 -2
  83. package/lib/emulator/storage/apis/firebase.js +31 -26
  84. package/lib/emulator/storage/apis/gcloud.js +7 -12
  85. package/lib/emulator/storage/files.js +36 -34
  86. package/lib/emulator/storage/index.js +2 -2
  87. package/lib/emulator/storage/metadata.js +2 -2
  88. package/lib/emulator/storage/rules/runtime.js +8 -7
  89. package/lib/emulator/types.js +3 -0
  90. package/lib/ensureApiEnabled.js +5 -1
  91. package/lib/error.js +1 -1
  92. package/lib/extensions/askUserForParam.js +2 -2
  93. package/lib/extensions/changelog.js +3 -1
  94. package/lib/extensions/checkProjectBilling.js +1 -1
  95. package/lib/extensions/diagnose.js +56 -0
  96. package/lib/extensions/displayExtensionInfo.js +1 -1
  97. package/lib/extensions/emulator/optionsHelper.js +24 -8
  98. package/lib/extensions/emulator/specHelper.js +10 -23
  99. package/lib/extensions/export.js +1 -51
  100. package/lib/extensions/extensionsApi.js +1 -1
  101. package/lib/extensions/extensionsHelper.js +23 -10
  102. package/lib/extensions/listExtensions.js +2 -0
  103. package/lib/extensions/manifest.js +48 -0
  104. package/lib/extensions/metricsUtils.js +4 -4
  105. package/lib/extensions/paramHelper.js +4 -4
  106. package/lib/extensions/refs.js +1 -1
  107. package/lib/extensions/secretsUtils.js +4 -4
  108. package/lib/functional.js +1 -1
  109. package/lib/functions/env.js +7 -8
  110. package/lib/functions/secrets.js +112 -0
  111. package/lib/gcp/cloudfunctions.js +24 -5
  112. package/lib/gcp/cloudfunctionsv2.js +18 -5
  113. package/lib/gcp/cloudtasks.js +1 -1
  114. package/lib/gcp/docker.js +2 -2
  115. package/lib/gcp/run.js +2 -2
  116. package/lib/gcp/secretManager.js +128 -46
  117. package/lib/gcp/storage.js +1 -0
  118. package/lib/hosting/api.js +1 -1
  119. package/lib/hosting/functionsProxy.js +15 -5
  120. package/lib/hosting/proxy.js +2 -2
  121. package/lib/init/features/account.js +1 -1
  122. package/lib/management/database.js +1 -1
  123. package/lib/previews.js +1 -1
  124. package/lib/responseToError.js +16 -7
  125. package/lib/serve/functions.js +2 -2
  126. package/lib/serve/hosting.js +1 -1
  127. package/lib/utils.js +7 -2
  128. package/npm-shrinkwrap.json +904 -412
  129. package/package.json +3 -3
  130. package/schema/firebase-config.json +32 -0
  131. package/templates/init/functions/javascript/package.lint.json +3 -3
  132. package/templates/init/functions/javascript/package.nolint.json +2 -2
  133. package/templates/init/functions/typescript/package.lint.json +7 -7
  134. package/templates/init/functions/typescript/package.nolint.json +3 -3
@@ -1,15 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const fs = require("fs");
4
- const types_1 = require("./types");
5
- const functionsEmulatorShared_1 = require("./functionsEmulatorShared");
6
- const functionsEmulatorUtils_1 = require("./functionsEmulatorUtils");
7
4
  const express = require("express");
8
5
  const path = require("path");
9
6
  const bodyParser = require("body-parser");
10
7
  const url_1 = require("url");
11
8
  const _ = require("lodash");
12
- let triggers;
9
+ const types_1 = require("./types");
10
+ const constants_1 = require("./constants");
11
+ const functionsEmulatorShared_1 = require("./functionsEmulatorShared");
12
+ const functionsEmulatorUtils_1 = require("./functionsEmulatorUtils");
13
+ let functionModule;
14
+ let FUNCTION_TARGET_NAME;
15
+ let FUNCTION_SIGNATURE;
16
+ let FUNCTION_DEBUG_MODE;
13
17
  let developerPkgJSON;
14
18
  const dynamicImport = new Function("modulePath", "return import(modulePath)");
15
19
  function isFeatureEnabled(frb, feature) {
@@ -112,7 +116,7 @@ async function resolveDeveloperNodeModule(frb, name) {
112
116
  if (!isInPackageJSON) {
113
117
  return { declared: false, installed: false };
114
118
  }
115
- const resolveResult = await requireResolveAsync(name, { paths: [frb.cwd] }).catch(noOp);
119
+ const resolveResult = await requireResolveAsync(name, { paths: [process.cwd()] }).catch(noOp);
116
120
  if (!resolveResult) {
117
121
  return { declared: true, installed: false };
118
122
  }
@@ -160,7 +164,7 @@ function requirePackageJson(frb) {
160
164
  return developerPkgJSON;
161
165
  }
162
166
  try {
163
- const pkg = require(`${frb.cwd}/package.json`);
167
+ const pkg = require(`${process.cwd()}/package.json`);
164
168
  developerPkgJSON = {
165
169
  engines: pkg.engines || {},
166
170
  dependencies: pkg.dependencies || {},
@@ -321,7 +325,7 @@ function getDefaultConfig() {
321
325
  }
322
326
  function initializeRuntimeConfig(frb) {
323
327
  if (!process.env.CLOUD_RUNTIME_CONFIG) {
324
- const configPath = `${frb.cwd}/.runtimeconfig.json`;
328
+ const configPath = `${process.cwd()}/.runtimeconfig.json`;
325
329
  try {
326
330
  const configContent = fs.readFileSync(configPath, "utf8");
327
331
  if (configContent) {
@@ -359,7 +363,7 @@ async function initializeFirebaseAdminStubs(frb) {
359
363
  const defaultApp = makeProxiedFirebaseApp(frb, adminModuleTarget.initializeApp(defaultAppOptions));
360
364
  logDebug("initializeApp(DEFAULT)", defaultAppOptions);
361
365
  localFunctionsModule.app.setEmulatedAdminApp(defaultApp);
362
- if (frb.emulators.auth) {
366
+ if (process.env[constants_1.Constants.FIREBASE_AUTH_EMULATOR_HOST]) {
363
367
  if ((0, functionsEmulatorUtils_1.compareVersionStrings)(adminResolution.version, "9.3.0") < 0) {
364
368
  new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Firebase Authentication emulator is running, but your 'firebase-admin' dependency is below version 9.3.0, so calls to Firebase Authentication will affect production.").log();
365
369
  }
@@ -377,16 +381,20 @@ async function initializeFirebaseAdminStubs(frb) {
377
381
  return defaultApp;
378
382
  })
379
383
  .when("firestore", (target) => {
380
- warnAboutFirestoreProd(frb);
384
+ warnAboutFirestoreProd();
381
385
  return Proxied.getOriginal(target, "firestore");
382
386
  })
383
387
  .when("database", (target) => {
384
- warnAboutDatabaseProd(frb);
388
+ warnAboutDatabaseProd();
385
389
  return Proxied.getOriginal(target, "database");
386
390
  })
387
391
  .when("auth", (target) => {
388
- warnAboutAuthProd(frb);
392
+ warnAboutAuthProd();
389
393
  return Proxied.getOriginal(target, "auth");
394
+ })
395
+ .when("storage", (target) => {
396
+ warnAboutStorageProd();
397
+ return Proxied.getOriginal(target, "storage");
390
398
  })
391
399
  .finalize();
392
400
  require.cache[adminResolution.resolution] = Object.assign(require.cache[adminResolution.resolution], {
@@ -401,37 +409,47 @@ function makeProxiedFirebaseApp(frb, original) {
401
409
  const appProxy = new Proxied(original);
402
410
  return appProxy
403
411
  .when("firestore", (target) => {
404
- warnAboutFirestoreProd(frb);
412
+ warnAboutFirestoreProd();
405
413
  return Proxied.getOriginal(target, "firestore");
406
414
  })
407
415
  .when("database", (target) => {
408
- warnAboutDatabaseProd(frb);
416
+ warnAboutDatabaseProd();
409
417
  return Proxied.getOriginal(target, "database");
410
418
  })
411
419
  .when("auth", (target) => {
412
- warnAboutAuthProd(frb);
420
+ warnAboutAuthProd();
413
421
  return Proxied.getOriginal(target, "auth");
422
+ })
423
+ .when("storage", (target) => {
424
+ warnAboutStorageProd();
425
+ return Proxied.getOriginal(target, "storage");
414
426
  })
415
427
  .finalize();
416
428
  }
417
- function warnAboutFirestoreProd(frb) {
418
- if (frb.emulators.firestore) {
429
+ function warnAboutFirestoreProd() {
430
+ if (process.env[constants_1.Constants.FIRESTORE_EMULATOR_HOST]) {
419
431
  return;
420
432
  }
421
433
  new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Cloud Firestore emulator is not running, so calls to Firestore will affect production.").log();
422
434
  }
423
- function warnAboutDatabaseProd(frb) {
424
- if (frb.emulators.database) {
435
+ function warnAboutDatabaseProd() {
436
+ if (process.env[constants_1.Constants.FIREBASE_DATABASE_EMULATOR_HOST]) {
425
437
  return;
426
438
  }
427
439
  new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Realtime Database emulator is not running, so calls to Realtime Database will affect production.").log();
428
440
  }
429
- function warnAboutAuthProd(frb) {
430
- if (frb.emulators.auth) {
441
+ function warnAboutAuthProd() {
442
+ if (process.env[constants_1.Constants.FIREBASE_AUTH_EMULATOR_HOST]) {
431
443
  return;
432
444
  }
433
445
  new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Firebase Authentication emulator is not running, so calls to Firebase Authentication will affect production.").log();
434
446
  }
447
+ function warnAboutStorageProd() {
448
+ if (process.env[constants_1.Constants.FIREBASE_STORAGE_EMULATOR_HOST]) {
449
+ return;
450
+ }
451
+ new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Firebase Storage emulator is not running, so calls to Firebase Storage will affect production.").log();
452
+ }
435
453
  async function initializeFunctionsConfigHelper(frb) {
436
454
  const functionsResolution = await assertResolveDeveloperNodeModule(frb, "firebase-functions");
437
455
  const localFunctionsModule = require(functionsResolution.resolution);
@@ -467,7 +485,7 @@ async function initializeFunctionsConfigHelper(frb) {
467
485
  function rawBodySaver(req, res, buf) {
468
486
  req.rawBody = buf;
469
487
  }
470
- async function processHTTPS(frb, trigger) {
488
+ async function processHTTPS(trigger, frb) {
471
489
  const ephemeralServer = express();
472
490
  const functionRouter = express.Router();
473
491
  const socketPath = frb.socketPath;
@@ -479,7 +497,6 @@ async function processHTTPS(frb, trigger) {
479
497
  const handler = async (req, res) => {
480
498
  try {
481
499
  logDebug(`Ephemeral server handling ${req.method} request`);
482
- const func = trigger.getRawFunction();
483
500
  res.on("finish", () => {
484
501
  instance.close((err) => {
485
502
  if (err) {
@@ -490,7 +507,7 @@ async function processHTTPS(frb, trigger) {
490
507
  }
491
508
  });
492
509
  });
493
- await runHTTPS([req, res], func);
510
+ await runHTTPS(trigger, [req, res]);
494
511
  }
495
512
  catch (err) {
496
513
  rejectEphemeralServer(err);
@@ -524,11 +541,11 @@ async function processHTTPS(frb, trigger) {
524
541
  instance.on("error", rejectEphemeralServer);
525
542
  });
526
543
  }
527
- async function processBackground(frb, trigger, signature) {
544
+ async function processBackground(trigger, frb, signature) {
528
545
  const proto = frb.proto;
529
546
  logDebug("ProcessBackground", proto);
530
547
  if (signature === "cloudevent") {
531
- return runCloudEvent(proto, trigger.getRawFunction());
548
+ return runCloudEvent(trigger, proto);
532
549
  }
533
550
  const data = proto.data;
534
551
  delete proto.data;
@@ -539,7 +556,7 @@ async function processBackground(frb, trigger, signature) {
539
556
  context.resource = context.resource.name;
540
557
  }
541
558
  }
542
- await runBackground({ data, context }, trigger.getRawFunction());
559
+ await runBackground(trigger, { data, context });
543
560
  }
544
561
  async function runFunction(func) {
545
562
  let caughtErr;
@@ -554,30 +571,30 @@ async function runFunction(func) {
554
571
  throw caughtErr;
555
572
  }
556
573
  }
557
- async function runBackground(proto, func) {
574
+ async function runBackground(trigger, proto) {
558
575
  logDebug("RunBackground", proto);
559
576
  await runFunction(() => {
560
- return func(proto.data, proto.context);
577
+ return trigger(proto.data, proto.context);
561
578
  });
562
579
  }
563
- async function runCloudEvent(event, func) {
580
+ async function runCloudEvent(trigger, event) {
564
581
  logDebug("RunCloudEvent", event);
565
582
  await runFunction(() => {
566
- return func(event);
583
+ return trigger(event);
567
584
  });
568
585
  }
569
- async function runHTTPS(args, func) {
586
+ async function runHTTPS(trigger, args) {
570
587
  if (args.length < 2) {
571
588
  throw new Error("Function must be passed 2 args.");
572
589
  }
573
590
  await runFunction(() => {
574
- return func(args[0], args[1]);
591
+ return trigger(args[0], args[1]);
575
592
  });
576
593
  }
577
594
  async function moduleResolutionDetective(frb, error) {
578
595
  const clues = {
579
- tsconfigJSON: await requireAsync("./tsconfig.json", { paths: [frb.cwd] }).catch(noOp),
580
- packageJSON: await requireAsync("./package.json", { paths: [frb.cwd] }).catch(noOp),
596
+ tsconfigJSON: await requireAsync("./tsconfig.json", { paths: [process.cwd()] }).catch(noOp),
597
+ packageJSON: await requireAsync("./package.json", { paths: [process.cwd()] }).catch(noOp),
581
598
  };
582
599
  const isPotentially = {
583
600
  typescript: false,
@@ -595,45 +612,57 @@ async function moduleResolutionDetective(frb, error) {
595
612
  function logDebug(msg, data) {
596
613
  new types_1.EmulatorLog("DEBUG", "runtime-status", `[${process.pid}] ${msg}`, data).log();
597
614
  }
598
- async function invokeTrigger(frb, triggers) {
599
- if (!frb.triggerId) {
600
- throw new Error("frb.triggerId unexpectedly null");
601
- }
602
- new types_1.EmulatorLog("INFO", "runtime-status", `Beginning execution of "${frb.triggerId}"`, {
615
+ async function invokeTrigger(trigger, frb) {
616
+ new types_1.EmulatorLog("INFO", "runtime-status", `Beginning execution of "${FUNCTION_TARGET_NAME}"`, {
603
617
  frb,
604
618
  }).log();
605
- const trigger = triggers[frb.triggerId];
606
- logDebug("triggerDefinition", trigger.definition);
607
- const signature = (0, functionsEmulatorShared_1.getSignatureType)(trigger.definition);
608
- logDebug(`Running ${frb.triggerId} in signature ${signature}`);
619
+ logDebug(`Running ${FUNCTION_TARGET_NAME} in signature ${FUNCTION_SIGNATURE}`);
609
620
  let seconds = 0;
610
621
  const timerId = setInterval(() => {
611
622
  seconds++;
612
623
  }, 1000);
613
624
  let timeoutId;
614
625
  if (isFeatureEnabled(frb, "timeout")) {
626
+ let timeout = process.env.FUNCTIONS_EMULATOR_TIMEOUT_SECONDS || "60";
627
+ if (timeout.endsWith("s")) {
628
+ timeout = timeout.slice(0, -1);
629
+ }
630
+ const timeoutMs = parseInt(timeout, 10) * 1000;
615
631
  timeoutId = setTimeout(() => {
616
- new types_1.EmulatorLog("WARN", "runtime-status", `Your function timed out after ~${trigger.definition.timeout || "60s"}. To configure this timeout, see
632
+ new types_1.EmulatorLog("WARN", "runtime-status", `Your function timed out after ~${timeout}s. To configure this timeout, see
617
633
  https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation.`).log();
618
634
  throw new Error("Function timed out.");
619
- }, trigger.timeoutMs);
635
+ }, timeoutMs);
620
636
  }
621
- switch (signature) {
637
+ switch (FUNCTION_SIGNATURE) {
622
638
  case "event":
623
639
  case "cloudevent":
624
- await processBackground(frb, triggers[frb.triggerId], signature);
640
+ await processBackground(trigger, frb, FUNCTION_SIGNATURE);
625
641
  break;
626
642
  case "http":
627
- await processHTTPS(frb, triggers[frb.triggerId]);
643
+ await processHTTPS(trigger, frb);
628
644
  break;
629
645
  }
630
646
  if (timeoutId) {
631
647
  clearTimeout(timeoutId);
632
648
  }
633
649
  clearInterval(timerId);
634
- new types_1.EmulatorLog("INFO", "runtime-status", `Finished "${frb.triggerId}" in ~${Math.max(seconds, 1)}s`).log();
635
- }
636
- async function initializeRuntime(frb, serializedFunctionTrigger, extensionTriggers) {
650
+ new types_1.EmulatorLog("INFO", "runtime-status", `Finished "${FUNCTION_TARGET_NAME}" in ~${Math.max(seconds, 1)}s`).log();
651
+ }
652
+ async function initializeRuntime(frb) {
653
+ FUNCTION_DEBUG_MODE = process.env.FUNCTION_DEBUG_MODE || "";
654
+ if (!FUNCTION_DEBUG_MODE) {
655
+ FUNCTION_TARGET_NAME = process.env.FUNCTION_TARGET || "";
656
+ if (!FUNCTION_TARGET_NAME) {
657
+ new types_1.EmulatorLog("FATAL", "runtime-status", `Environment variable FUNCTION_TARGET cannot be empty. This shouldn't happen.`).log();
658
+ await flushAndExit(1);
659
+ }
660
+ FUNCTION_SIGNATURE = process.env.FUNCTION_SIGNATURE_TYPE || "";
661
+ if (!FUNCTION_SIGNATURE) {
662
+ new types_1.EmulatorLog("FATAL", "runtime-status", `Environment variable FUNCTION_SIGNATURE_TYPE cannot be empty. This shouldn't happen.`).log();
663
+ await flushAndExit(1);
664
+ }
665
+ }
637
666
  logDebug(`Disabled runtime features: ${JSON.stringify(frb.disabled_features)}`);
638
667
  const verified = await verifyDeveloperNodeModules(frb);
639
668
  if (!verified) {
@@ -645,35 +674,27 @@ async function initializeRuntime(frb, serializedFunctionTrigger, extensionTrigge
645
674
  await initializeFunctionsConfigHelper(frb);
646
675
  await initializeFirebaseFunctionsStubs(frb);
647
676
  await initializeFirebaseAdminStubs(frb);
648
- let parsedDefinitions = [];
677
+ }
678
+ async function loadTriggers(frb, serializedFunctionTrigger) {
649
679
  let triggerModule;
650
680
  if (serializedFunctionTrigger) {
651
681
  triggerModule = eval(serializedFunctionTrigger)();
652
682
  }
653
683
  else {
654
684
  try {
655
- triggerModule = require(frb.cwd);
685
+ triggerModule = require(process.cwd());
656
686
  }
657
687
  catch (err) {
658
688
  if (err.code !== "ERR_REQUIRE_ESM") {
659
689
  await moduleResolutionDetective(frb, err);
660
- return;
690
+ throw err;
661
691
  }
662
- const modulePath = require.resolve(frb.cwd);
692
+ const modulePath = require.resolve(process.cwd());
663
693
  const moduleURL = (0, url_1.pathToFileURL)(modulePath).href;
664
694
  triggerModule = await dynamicImport(moduleURL);
665
695
  }
666
696
  }
667
- if (extensionTriggers) {
668
- parsedDefinitions = extensionTriggers;
669
- }
670
- else {
671
- require("../deploy/functions/runtimes/node/extractTriggers")(triggerModule, parsedDefinitions);
672
- }
673
- const triggerDefinitions = (0, functionsEmulatorShared_1.emulatedFunctionsByRegion)(parsedDefinitions);
674
- const triggers = (0, functionsEmulatorShared_1.getEmulatedTriggersFromDefinitions)(triggerDefinitions, triggerModule);
675
- new types_1.EmulatorLog("SYSTEM", "triggers-parsed", "", { triggers, triggerDefinitions }).log();
676
- return triggers;
697
+ return triggerModule;
677
698
  }
678
699
  async function flushAndExit(code) {
679
700
  await types_1.EmulatorLog.waitForFlush();
@@ -693,28 +714,32 @@ async function handleMessage(message) {
693
714
  await flushAndExit(1);
694
715
  return;
695
716
  }
696
- if (!triggers) {
697
- const serializedTriggers = runtimeArgs.opts ? runtimeArgs.opts.serializedTriggers : undefined;
698
- const extensionTriggers = runtimeArgs.opts ? runtimeArgs.opts.extensionTriggers : undefined;
699
- triggers = await initializeRuntime(runtimeArgs.frb, serializedTriggers, extensionTriggers);
700
- }
701
- if (!triggers) {
702
- await flushAndExit(1);
703
- return;
704
- }
705
- if (!runtimeArgs.frb.triggerId) {
706
- await goIdle();
707
- return;
717
+ if (!functionModule) {
718
+ try {
719
+ await initializeRuntime(runtimeArgs.frb);
720
+ const serializedTriggers = runtimeArgs.opts ? runtimeArgs.opts.serializedTriggers : undefined;
721
+ functionModule = await loadTriggers(runtimeArgs.frb, serializedTriggers);
722
+ }
723
+ catch (e) {
724
+ logDebug(e);
725
+ new types_1.EmulatorLog("FATAL", "runtime-status", `Failed to initialize and load triggers. This shouldn't happen: ${e.message}`).log();
726
+ await flushAndExit(1);
727
+ return;
728
+ }
708
729
  }
709
- if (!triggers[runtimeArgs.frb.triggerId]) {
710
- new types_1.EmulatorLog("FATAL", "runtime-status", `Could not find trigger "${runtimeArgs.frb.triggerId}" in your functions directory.`).log();
711
- return;
730
+ if (FUNCTION_DEBUG_MODE) {
731
+ FUNCTION_TARGET_NAME = runtimeArgs.frb.debug.functionTarget;
732
+ FUNCTION_SIGNATURE = runtimeArgs.frb.debug.functionSignature;
712
733
  }
713
- else {
714
- logDebug(`Trigger "${runtimeArgs.frb.triggerId}" has been found, beginning invocation!`);
734
+ const trigger = FUNCTION_TARGET_NAME.split(".").reduce((mod, functionTargetPart) => {
735
+ return mod === null || mod === void 0 ? void 0 : mod[functionTargetPart];
736
+ }, functionModule);
737
+ if (!trigger) {
738
+ throw new Error(`Failed to find function ${FUNCTION_TARGET_NAME} in the loaded module`);
715
739
  }
740
+ logDebug(`Beginning invocation function ${FUNCTION_TARGET_NAME}!`);
716
741
  try {
717
- await invokeTrigger(runtimeArgs.frb, triggers);
742
+ await invokeTrigger(trigger, runtimeArgs.frb);
718
743
  if (runtimeArgs.opts && runtimeArgs.opts.serializedTriggers) {
719
744
  await flushAndExit(0);
720
745
  }
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSignatureType = exports.formatHost = exports.findModuleRoot = exports.waitForBody = exports.getServiceFromEventType = exports.getFunctionService = exports.getTemporarySocketPath = exports.getEmulatedTriggersFromDefinitions = exports.emulatedFunctionsByRegion = exports.EmulatedTrigger = exports.HttpConstants = void 0;
3
+ exports.getSignatureType = exports.formatHost = exports.findModuleRoot = exports.waitForBody = exports.getServiceFromEventType = exports.getFunctionService = exports.getTemporarySocketPath = exports.getEmulatedTriggersFromDefinitions = exports.emulatedFunctionsByRegion = exports.emulatedFunctionsFromEndpoints = exports.EmulatedTrigger = exports.HttpConstants = void 0;
4
4
  const _ = require("lodash");
5
5
  const os = require("os");
6
6
  const path = require("path");
7
7
  const fs = require("fs");
8
8
  const constants_1 = require("./constants");
9
+ const backend_1 = require("../deploy/functions/backend");
10
+ const proto_1 = require("../gcp/proto");
9
11
  const memoryLookup = {
10
12
  "128MB": 128,
11
13
  "256MB": 256,
@@ -44,6 +46,54 @@ class EmulatedTrigger {
44
46
  }
45
47
  }
46
48
  exports.EmulatedTrigger = EmulatedTrigger;
49
+ function emulatedFunctionsFromEndpoints(endpoints) {
50
+ const regionDefinitions = [];
51
+ for (const endpoint of endpoints) {
52
+ if (!endpoint.region) {
53
+ endpoint.region = "us-central1";
54
+ }
55
+ const def = {
56
+ entryPoint: endpoint.entryPoint,
57
+ platform: endpoint.platform,
58
+ region: endpoint.region,
59
+ name: endpoint.id,
60
+ id: `${endpoint.region}-${endpoint.id}`,
61
+ };
62
+ (0, proto_1.copyIfPresent)(def, endpoint, "timeout", "availableMemoryMb", "labels", "platform", "secretEnvironmentVariables");
63
+ if ((0, backend_1.isHttpsTriggered)(endpoint)) {
64
+ def.httpsTrigger = endpoint.httpsTrigger;
65
+ }
66
+ else if ((0, backend_1.isEventTriggered)(endpoint)) {
67
+ const eventTrigger = endpoint.eventTrigger;
68
+ if (endpoint.platform === "gcfv1") {
69
+ def.eventTrigger = {
70
+ eventType: eventTrigger.eventType,
71
+ resource: eventTrigger.eventFilters.resource,
72
+ };
73
+ }
74
+ else {
75
+ const { resource, topic, bucket } = endpoint.eventTrigger.eventFilters;
76
+ const eventResource = resource || topic || bucket;
77
+ if (!eventResource) {
78
+ continue;
79
+ }
80
+ def.eventTrigger = {
81
+ eventType: eventTrigger.eventType,
82
+ resource: eventResource,
83
+ };
84
+ }
85
+ }
86
+ else if ((0, backend_1.isScheduleTriggered)(endpoint)) {
87
+ def.eventTrigger = { eventType: "pubsub", resource: "" };
88
+ def.schedule = endpoint.scheduleTrigger;
89
+ }
90
+ else {
91
+ }
92
+ regionDefinitions.push(def);
93
+ }
94
+ return regionDefinitions;
95
+ }
96
+ exports.emulatedFunctionsFromEndpoints = emulatedFunctionsFromEndpoints;
47
97
  function emulatedFunctionsByRegion(definitions) {
48
98
  const regionDefinitions = [];
49
99
  for (const def of definitions) {
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FunctionsEmulatorShell = void 0;
4
4
  const uuid = require("uuid");
5
5
  const functionsEmulator_1 = require("./functionsEmulator");
6
- const functionsEmulatorShared_1 = require("./functionsEmulatorShared");
7
6
  const utils = require("../utils");
8
7
  const logger_1 = require("../logger");
9
8
  const error_1 = require("../error");
@@ -43,7 +42,7 @@ class FunctionsEmulatorShell {
43
42
  auth: opts.auth,
44
43
  data,
45
44
  };
46
- this.emu.startFunctionRuntime(this.backend, trigger.id, trigger.name, (0, functionsEmulatorShared_1.getSignatureType)(trigger), proto);
45
+ this.emu.invokeTrigger(this.backend, trigger, proto);
47
46
  }
48
47
  getTrigger(name) {
49
48
  const result = this.triggers.find((trigger) => {
@@ -52,7 +52,7 @@ function parseRuntimeVersion(runtime) {
52
52
  return undefined;
53
53
  }
54
54
  const runtimeRe = /(nodejs)?([0-9]+)/;
55
- const match = runtime.match(runtimeRe);
55
+ const match = runtimeRe.exec(runtime);
56
56
  if (match) {
57
57
  return Number.parseInt(match[2]);
58
58
  }
@@ -73,13 +73,13 @@ exports.parseVersionString = parseVersionString;
73
73
  function compareVersionStrings(a, b) {
74
74
  const versionA = parseVersionString(a);
75
75
  const versionB = parseVersionString(b);
76
- if (versionA.major != versionB.major) {
76
+ if (versionA.major !== versionB.major) {
77
77
  return versionA.major - versionB.major;
78
78
  }
79
- if (versionA.minor != versionB.minor) {
79
+ if (versionA.minor !== versionB.minor) {
80
80
  return versionA.minor - versionB.minor;
81
81
  }
82
- if (versionA.patch != versionB.patch) {
82
+ if (versionA.patch !== versionB.patch) {
83
83
  return versionA.patch - versionB.patch;
84
84
  }
85
85
  return 0;
@@ -43,7 +43,7 @@ class RuntimeWorker {
43
43
  execute(frb, opts) {
44
44
  const execFrb = Object.assign({}, frb);
45
45
  if (!execFrb.socketPath) {
46
- execFrb.socketPath = (0, functionsEmulatorShared_1.getTemporarySocketPath)(this.runtime.pid, execFrb.cwd);
46
+ execFrb.socketPath = (0, functionsEmulatorShared_1.getTemporarySocketPath)(this.runtime.pid, this.runtime.cwd);
47
47
  this.log(`Assigning socketPath: ${execFrb.socketPath}`);
48
48
  }
49
49
  const args = { frb: execFrb, opts };
@@ -170,14 +170,14 @@ class RuntimeWorkerPool {
170
170
  }
171
171
  return;
172
172
  }
173
- addWorker(triggerId, runtime) {
173
+ addWorker(triggerId, runtime, extensionLogInfo) {
174
174
  const worker = new RuntimeWorker(this.getKey(triggerId), runtime);
175
175
  this.log(`addWorker(${worker.key})`);
176
176
  const keyWorkers = this.getTriggerWorkers(triggerId);
177
177
  keyWorkers.push(worker);
178
178
  this.setTriggerWorkers(triggerId, keyWorkers);
179
179
  const logger = triggerId
180
- ? emulatorLogger_1.EmulatorLogger.forFunction(triggerId)
180
+ ? emulatorLogger_1.EmulatorLogger.forFunction(triggerId, extensionLogInfo)
181
181
  : emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS);
182
182
  worker.onLogs((log) => {
183
183
  logger.handleRuntimeLog(log);
@@ -25,9 +25,10 @@ class EmulatorHub {
25
25
  });
26
26
  this.hub.get(EmulatorHub.PATH_EMULATORS, (req, res) => {
27
27
  const body = {};
28
- registry_1.EmulatorRegistry.listRunning().forEach((name) => {
29
- body[name] = registry_1.EmulatorRegistry.get(name).getInfo();
30
- });
28
+ for (const emulator of registry_1.EmulatorRegistry.listRunning()) {
29
+ const info = registry_1.EmulatorRegistry.getInfo(emulator);
30
+ body[emulator] = info;
31
+ }
31
32
  res.json(body);
32
33
  });
33
34
  this.hub.post(EmulatorHub.PATH_EXPORT, async (req, res) => {
@@ -82,7 +82,7 @@ class WebSocketTransport extends TransportStream {
82
82
  };
83
83
  const splat = [info.message, ...(info[triple_beam_1.SPLAT] || [])]
84
84
  .map((value) => {
85
- if (typeof value == "string") {
85
+ if (typeof value === "string") {
86
86
  try {
87
87
  bundle.data = Object.assign(Object.assign({}, bundle.data), JSON.parse(value));
88
88
  return null;
@@ -88,7 +88,7 @@ class PubsubEmulator {
88
88
  this.subscriptionForTopic.set(topicName, sub);
89
89
  }
90
90
  ensureFunctionsClient() {
91
- if (this.client != undefined)
91
+ if (this.client !== undefined)
92
92
  return;
93
93
  const funcEmulator = registry_1.EmulatorRegistry.get(types_1.Emulators.FUNCTIONS);
94
94
  if (!funcEmulator) {
@@ -17,6 +17,9 @@ class EmulatorRegistry {
17
17
  const info = instance.getInfo();
18
18
  await portUtils.waitForPortClosed(info.port, info.host);
19
19
  }
20
+ static registerExtensionsEmulator() {
21
+ this.extensionsEmulatorRegistered = true;
22
+ }
20
23
  static async stop(name) {
21
24
  emulatorLogger_1.EmulatorLogger.forEmulator(name).logLabeled("BULLET", name, `Stopping ${constants_1.Constants.description(name)}`);
22
25
  const instance = this.get(name);
@@ -29,7 +32,8 @@ class EmulatorRegistry {
29
32
  static async stopAll() {
30
33
  const stopPriority = {
31
34
  ui: 0,
32
- functions: 1,
35
+ extensions: 1,
36
+ functions: 1.1,
33
37
  hosting: 2,
34
38
  database: 3.0,
35
39
  firestore: 3.1,
@@ -52,6 +56,9 @@ class EmulatorRegistry {
52
56
  }
53
57
  }
54
58
  static isRunning(emulator) {
59
+ if (emulator === types_1.Emulators.EXTENSIONS) {
60
+ return this.extensionsEmulatorRegistered && this.isRunning(types_1.Emulators.FUNCTIONS);
61
+ }
55
62
  const instance = this.INSTANCES.get(emulator);
56
63
  return instance !== undefined;
57
64
  }
@@ -67,7 +74,7 @@ class EmulatorRegistry {
67
74
  return this.INSTANCES.get(emulator);
68
75
  }
69
76
  static getInfo(emulator) {
70
- const instance = this.INSTANCES.get(emulator);
77
+ const instance = this.INSTANCES.get(emulator === types_1.Emulators.EXTENSIONS ? types_1.Emulators.FUNCTIONS : emulator);
71
78
  if (!instance) {
72
79
  return undefined;
73
80
  }
@@ -97,4 +104,5 @@ class EmulatorRegistry {
97
104
  }
98
105
  }
99
106
  exports.EmulatorRegistry = EmulatorRegistry;
107
+ EmulatorRegistry.extensionsEmulatorRegistered = false;
100
108
  EmulatorRegistry.INSTANCES = new Map();