firebase-tools 11.18.0 → 11.19.0

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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveCpuAndConcurrency = exports.inferBlockingDetails = exports.updateEndpointTargetedStatus = exports.inferDetailsFromExisting = exports.prepare = exports.EVENTARC_SOURCE_ENV = void 0;
3
+ exports.loadCodebases = exports.resolveCpuAndConcurrency = exports.inferBlockingDetails = exports.updateEndpointTargetedStatus = exports.inferDetailsFromExisting = exports.prepare = exports.EVENTARC_SOURCE_ENV = void 0;
4
4
  const clc = require("colorette");
5
5
  const backend = require("./backend");
6
6
  const build = require("./build");
@@ -31,7 +31,7 @@ function hasUserConfig(config) {
31
31
  return Object.keys(config).length > 1;
32
32
  }
33
33
  async function prepare(context, options, payload) {
34
- var _a;
34
+ var _a, _b;
35
35
  const projectId = (0, projectUtils_1.needProjectId)(options);
36
36
  const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
37
37
  context.config = (0, projectConfig_1.normalizeAndValidate)(options.config.src.functions);
@@ -40,6 +40,9 @@ async function prepare(context, options, payload) {
40
40
  if (codebases.length === 0) {
41
41
  throw new error_1.FirebaseError("No function matches given --only filters. Aborting deployment.");
42
42
  }
43
+ for (const codebase of codebases) {
44
+ (0, utils_1.logLabeledBullet)("functions", `preparing codebase ${clc.bold(codebase)} for deployment`);
45
+ }
43
46
  const checkAPIsEnabled = await Promise.all([
44
47
  ensureApiEnabled.ensure(projectId, "cloudfunctions.googleapis.com", "functions"),
45
48
  ensureApiEnabled.check(projectId, "runtimeconfig.googleapis.com", "runtimeconfig", true),
@@ -52,45 +55,28 @@ async function prepare(context, options, payload) {
52
55
  if (checkAPIsEnabled[1]) {
53
56
  runtimeConfig = Object.assign(Object.assign({}, runtimeConfig), (await (0, prepareFunctionsUpload_1.getFunctionsConfig)(projectId)));
54
57
  }
55
- context.sources = {};
58
+ const wantBuilds = await loadCodebases(context.config, options, firebaseConfig, runtimeConfig, context.filters);
56
59
  const codebaseUsesEnvs = [];
57
60
  const wantBackends = {};
58
- for (const codebase of codebases) {
59
- (0, utils_1.logLabeledBullet)("functions", `preparing codebase ${clc.bold(codebase)} for deployment`);
61
+ for (const [codebase, wantBuild] of Object.entries(wantBuilds)) {
60
62
  const config = (0, projectConfig_1.configForCodebase)(context.config, codebase);
61
- const sourceDirName = config.source;
62
- if (!sourceDirName) {
63
- throw new error_1.FirebaseError(`No functions code detected at default location (./functions), and no functions source defined in firebase.json`);
64
- }
65
- const sourceDir = options.config.path(sourceDirName);
66
- const delegateContext = {
67
- projectId,
68
- sourceDir,
69
- projectDir: options.config.projectDir,
70
- runtime: config.runtime || "",
71
- };
72
- const runtimeDelegate = await runtimes.getRuntimeDelegate(delegateContext);
73
- logger_1.logger.debug(`Validating ${runtimeDelegate.name} source`);
74
- await runtimeDelegate.validate();
75
- logger_1.logger.debug(`Building ${runtimeDelegate.name} source`);
76
- await runtimeDelegate.build();
77
63
  const firebaseEnvs = functionsEnv.loadFirebaseEnvs(firebaseConfig, projectId);
78
64
  const userEnvOpt = {
79
- functionsSource: sourceDir,
65
+ functionsSource: options.config.path(config.source),
80
66
  projectId: projectId,
81
67
  projectAlias: options.projectAlias,
82
68
  };
83
69
  const userEnvs = functionsEnv.loadUserEnvs(userEnvOpt);
84
70
  const envs = Object.assign(Object.assign({}, userEnvs), firebaseEnvs);
85
- const wantBuild = await runtimeDelegate.discoverBuild(runtimeConfig, firebaseEnvs);
86
71
  const { backend: wantBackend, envs: resolvedEnvs } = await build.resolveBackend(wantBuild, firebaseConfig, userEnvOpt, userEnvs, options.nonInteractive);
87
72
  let hasEnvsFromParams = false;
88
73
  wantBackend.environmentVariables = envs;
89
74
  for (const envName of Object.keys(resolvedEnvs)) {
90
- const envValue = (_a = resolvedEnvs[envName]) === null || _a === void 0 ? void 0 : _a.toString();
75
+ const isList = (_a = resolvedEnvs[envName]) === null || _a === void 0 ? void 0 : _a.legalList;
76
+ const envValue = (_b = resolvedEnvs[envName]) === null || _b === void 0 ? void 0 : _b.toSDK();
91
77
  if (envValue &&
92
78
  !resolvedEnvs[envName].internal &&
93
- !Object.prototype.hasOwnProperty.call(wantBackend.environmentVariables, envName)) {
79
+ (!Object.prototype.hasOwnProperty.call(wantBackend.environmentVariables, envName) || isList)) {
94
80
  wantBackend.environmentVariables[envName] = envValue;
95
81
  hasEnvsFromParams = true;
96
82
  }
@@ -127,6 +113,7 @@ async function prepare(context, options, payload) {
127
113
  }
128
114
  }
129
115
  validate.endpointsAreUnique(wantBackends);
116
+ context.sources = {};
130
117
  for (const [codebase, wantBackend] of Object.entries(wantBackends)) {
131
118
  const config = (0, projectConfig_1.configForCodebase)(context.config, codebase);
132
119
  const sourceDirName = config.source;
@@ -291,3 +278,31 @@ function resolveCpuAndConcurrency(want) {
291
278
  }
292
279
  }
293
280
  exports.resolveCpuAndConcurrency = resolveCpuAndConcurrency;
281
+ async function loadCodebases(config, options, firebaseConfig, runtimeConfig, filters) {
282
+ const codebases = (0, functionsDeployHelper_1.targetCodebases)(config, filters);
283
+ const projectId = (0, projectUtils_1.needProjectId)(options);
284
+ const wantBuilds = {};
285
+ for (const codebase of codebases) {
286
+ const codebaseConfig = (0, projectConfig_1.configForCodebase)(config, codebase);
287
+ const sourceDirName = codebaseConfig.source;
288
+ if (!sourceDirName) {
289
+ throw new error_1.FirebaseError(`No functions code detected at default location (./functions), and no functions source defined in firebase.json`);
290
+ }
291
+ const sourceDir = options.config.path(sourceDirName);
292
+ const delegateContext = {
293
+ projectId,
294
+ sourceDir,
295
+ projectDir: options.config.projectDir,
296
+ runtime: codebaseConfig.runtime || "",
297
+ };
298
+ const runtimeDelegate = await runtimes.getRuntimeDelegate(delegateContext);
299
+ logger_1.logger.debug(`Validating ${runtimeDelegate.name} source`);
300
+ await runtimeDelegate.validate();
301
+ logger_1.logger.debug(`Building ${runtimeDelegate.name} source`);
302
+ await runtimeDelegate.build();
303
+ const firebaseEnvs = functionsEnv.loadFirebaseEnvs(firebaseConfig, projectId);
304
+ wantBuilds[codebase] = await runtimeDelegate.discoverBuild(runtimeConfig, firebaseEnvs);
305
+ }
306
+ return wantBuilds;
307
+ }
308
+ exports.loadCodebases = loadCodebases;
@@ -14,6 +14,7 @@ const cloudtasks = require("../../../gcp/cloudtasks");
14
14
  const deploymentTool = require("../../../deploymentTool");
15
15
  const gcf = require("../../../gcp/cloudfunctions");
16
16
  const gcfV2 = require("../../../gcp/cloudfunctionsv2");
17
+ const eventarc = require("../../../gcp/eventarc");
17
18
  const helper = require("../functionsDeployHelper");
18
19
  const poller = require("../../../operation-poller");
19
20
  const pubsub = require("../../../gcp/pubsub");
@@ -36,6 +37,12 @@ const gcfV2PollerOptions = {
36
37
  masterTimeout: 25 * 60 * 1000,
37
38
  maxBackoff: 10000,
38
39
  };
40
+ const eventarcPollerOptions = {
41
+ apiOrigin: api_1.eventarcOrigin,
42
+ apiVersion: "v1",
43
+ masterTimeout: 25 * 60 * 1000,
44
+ maxBackoff: 10000,
45
+ };
39
46
  const rethrowAs = (endpoint, op) => (err) => {
40
47
  logger_1.logger.error(err.message);
41
48
  throw new reporter.DeploymentError(endpoint, op, err);
@@ -212,7 +219,7 @@ class Fabricator {
212
219
  }
213
220
  }
214
221
  async createV2Function(endpoint) {
215
- var _a, _b;
222
+ var _a, _b, _c;
216
223
  const storage = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
217
224
  if (!storage) {
218
225
  logger_1.logger.debug("Precondition failed. Cannot create a GCFv2 function without storage");
@@ -237,6 +244,25 @@ class Fabricator {
237
244
  })
238
245
  .catch(rethrowAs(endpoint, "create topic"));
239
246
  }
247
+ const channel = (_c = apiFunction.eventTrigger) === null || _c === void 0 ? void 0 : _c.channel;
248
+ if (channel) {
249
+ await this.executor
250
+ .run(async () => {
251
+ try {
252
+ const op = await eventarc.createChannel({ name: channel });
253
+ return await poller.pollOperation(Object.assign(Object.assign({}, eventarcPollerOptions), { pollerName: `create-${channel}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
254
+ }
255
+ catch (err) {
256
+ if (err.status === 409) {
257
+ return;
258
+ }
259
+ throw new error_1.FirebaseError("Unexpected error creating Eventarc channel", {
260
+ original: err,
261
+ });
262
+ }
263
+ })
264
+ .catch(rethrowAs(endpoint, "upsert eventarc channel"));
265
+ }
240
266
  const resultFunction = await this.functionExecutor
241
267
  .run(async () => {
242
268
  const op = await gcfV2.createFunction(apiFunction);
@@ -8,7 +8,7 @@ function requireKeys(prefix, yaml, ...keys) {
8
8
  }
9
9
  for (const key of keys) {
10
10
  if (!yaml[key]) {
11
- throw new error_1.FirebaseError(`Expected key ${prefix + key}`);
11
+ throw new error_1.FirebaseError(`Expected key ${prefix + key.toString()}`);
12
12
  }
13
13
  }
14
14
  }
@@ -47,6 +47,12 @@ function assertKeyTypes(prefix, yaml, schema) {
47
47
  }
48
48
  continue;
49
49
  }
50
+ if (schemaType === "List") {
51
+ if (typeof value !== "string" && !Array.isArray(value)) {
52
+ throw new error_1.FirebaseError(`Expected ${fullKey} to be a field list (array or list expression); was ${typeof value}`);
53
+ }
54
+ continue;
55
+ }
50
56
  if (value === null) {
51
57
  if (schemaType.endsWith("?")) {
52
58
  continue;
@@ -48,7 +48,7 @@ function parseRequiredAPIs(manifest) {
48
48
  function assertBuildEndpoint(ep, id) {
49
49
  const prefix = `endpoints[${id}]`;
50
50
  (0, parsing_1.assertKeyTypes)(prefix, ep, {
51
- region: "array",
51
+ region: "List",
52
52
  platform: (platform) => build.AllFunctionsPlatforms.includes(platform),
53
53
  entryPoint: "string",
54
54
  omit: "Field<boolean>?",
@@ -38,10 +38,10 @@ class Delegate {
38
38
  this.sourceDir = sourceDir;
39
39
  this.runtime = runtime;
40
40
  this.name = "nodejs";
41
- this._sdkVersion = "";
41
+ this._sdkVersion = undefined;
42
42
  }
43
43
  get sdkVersion() {
44
- if (!this._sdkVersion) {
44
+ if (this._sdkVersion === undefined) {
45
45
  this._sdkVersion = versioning.getFunctionsSDKVersion(this.sourceDir) || "";
46
46
  }
47
47
  return this._sdkVersion;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkFunctionsSDKVersion = exports.getLatestSDKVersion = exports.getFunctionsSDKVersion = exports.FUNCTIONS_SDK_VERSION_TOO_OLD_WARNING = void 0;
4
- const _ = require("lodash");
3
+ exports.checkFunctionsSDKVersion = exports.getLatestSDKVersion = exports.getFunctionsSDKVersion = exports.findModuleVersion = exports.FUNCTIONS_SDK_VERSION_TOO_OLD_WARNING = void 0;
4
+ const fs = require("fs");
5
+ const path = require("path");
5
6
  const clc = require("colorette");
6
7
  const semver = require("semver");
7
8
  const spawn = require("cross-spawn");
@@ -15,26 +16,41 @@ exports.FUNCTIONS_SDK_VERSION_TOO_OLD_WARNING = clc.bold(clc.yellow("functions:
15
16
  " version that is at least 2.0.0. Please run " +
16
17
  clc.bold("npm i --save firebase-functions@latest") +
17
18
  " in the functions folder.";
18
- function getFunctionsSDKVersion(sourceDir) {
19
- try {
20
- const child = spawn.sync("npm", ["list", "firebase-functions", "--json=true"], {
21
- cwd: sourceDir,
22
- encoding: "utf8",
23
- });
24
- if (child.error) {
25
- logger_1.logger.debug("getFunctionsSDKVersion encountered error:", child.error.stack);
19
+ function findModuleVersion(name, resolvedPath) {
20
+ let searchPath = path.dirname(resolvedPath);
21
+ while (true) {
22
+ if (searchPath === "/" || path.basename(searchPath) === "node_modules") {
23
+ logger_1.logger.debug(`Failed to find version of module ${name}: reached end of search path ${searchPath}`);
26
24
  return;
27
25
  }
28
- const output = JSON.parse(child.stdout);
29
- return _.get(output, ["dependencies", "firebase-functions", "version"]);
26
+ const maybePackageJson = path.join(searchPath, "package.json");
27
+ if (fs.existsSync(maybePackageJson)) {
28
+ const pkg = require(maybePackageJson);
29
+ if (pkg.name === name) {
30
+ return pkg.version;
31
+ }
32
+ logger_1.logger.debug(`Failed to find version of module ${name}: instead found ${pkg.name} at ${searchPath}`);
33
+ return;
34
+ }
35
+ searchPath = path.dirname(searchPath);
36
+ }
37
+ }
38
+ exports.findModuleVersion = findModuleVersion;
39
+ function getFunctionsSDKVersion(sourceDir) {
40
+ try {
41
+ return findModuleVersion("firebase-functions", require.resolve("firebase-functions", { paths: [sourceDir] }));
30
42
  }
31
43
  catch (e) {
44
+ if (e.code === "MODULE_NOT_FOUND") {
45
+ utils.logLabeledWarning("functions", "Couldn't find firebase-functions package in your source code. Have you run 'npm install'?");
46
+ }
32
47
  logger_1.logger.debug("getFunctionsSDKVersion encountered error:", e);
33
48
  return;
34
49
  }
35
50
  }
36
51
  exports.getFunctionsSDKVersion = getFunctionsSDKVersion;
37
52
  function getLatestSDKVersion() {
53
+ var _a;
38
54
  const child = spawn.sync("npm", ["show", "firebase-functions", "--json=true"], {
39
55
  encoding: "utf8",
40
56
  });
@@ -43,10 +59,10 @@ function getLatestSDKVersion() {
43
59
  return;
44
60
  }
45
61
  const output = JSON.parse(child.stdout);
46
- if (_.isEmpty(output)) {
62
+ if (Object.keys(output).length === 0) {
47
63
  return;
48
64
  }
49
- return _.get(output, ["dist-tags", "latest"]);
65
+ return (_a = output["dist-tags"]) === null || _a === void 0 ? void 0 : _a["latest"];
50
66
  }
51
67
  exports.getLatestSDKVersion = getLatestSDKVersion;
52
68
  function checkFunctionsSDKVersion(currentVersion) {
@@ -219,7 +219,8 @@ exports.shutdownWhenKilled = shutdownWhenKilled;
219
219
  async function runScript(script, extraEnv) {
220
220
  utils.logBullet(`Running script: ${clc.bold(script)}`);
221
221
  const env = Object.assign(Object.assign({}, process.env), extraEnv);
222
- (0, env_1.setEnvVarsForEmulators)(env);
222
+ const emulatorInfos = registry_1.EmulatorRegistry.listRunningWithInfo();
223
+ (0, env_1.setEnvVarsForEmulators)(env, emulatorInfos);
223
224
  const proc = childProcess.spawn(script, {
224
225
  stdio: ["inherit", "inherit", "inherit"],
225
226
  shell: true,
@@ -28,9 +28,9 @@ const EMULATOR_UPDATE_DETAILS = {
28
28
  expectedChecksum: "4f41d24a3c0f3b55ea22804a424cc0ee",
29
29
  },
30
30
  storage: {
31
- version: "1.1.1",
32
- expectedSize: 46448285,
33
- expectedChecksum: "691982db4019d49d345a97151bdea7e2",
31
+ version: "1.1.2",
32
+ expectedSize: 47028740,
33
+ expectedChecksum: "983b4415b1e72b109864f1b8e7ea7546",
34
34
  },
35
35
  ui: experiments.isEnabled("emulatoruisnapshot")
36
36
  ? { version: "SNAPSHOT", expectedSize: -1, expectedChecksum: "" }
@@ -3,33 +3,35 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setEnvVarsForEmulators = void 0;
4
4
  const constants_1 = require("./constants");
5
5
  const types_1 = require("./types");
6
- const registry_1 = require("./registry");
7
- function setEnvVarsForEmulators(env) {
8
- if (registry_1.EmulatorRegistry.isRunning(types_1.Emulators.DATABASE)) {
9
- env[constants_1.Constants.FIREBASE_DATABASE_EMULATOR_HOST] = registry_1.EmulatorRegistry.url(types_1.Emulators.DATABASE).host;
10
- }
11
- if (registry_1.EmulatorRegistry.isRunning(types_1.Emulators.FIRESTORE)) {
12
- const { host } = registry_1.EmulatorRegistry.url(types_1.Emulators.FIRESTORE);
13
- env[constants_1.Constants.FIRESTORE_EMULATOR_HOST] = host;
14
- env[constants_1.Constants.FIRESTORE_EMULATOR_ENV_ALT] = host;
15
- }
16
- if (registry_1.EmulatorRegistry.isRunning(types_1.Emulators.STORAGE)) {
17
- const { host } = registry_1.EmulatorRegistry.url(types_1.Emulators.STORAGE);
18
- env[constants_1.Constants.FIREBASE_STORAGE_EMULATOR_HOST] = host;
19
- env[constants_1.Constants.CLOUD_STORAGE_EMULATOR_HOST] = `http://${host}`;
20
- }
21
- if (registry_1.EmulatorRegistry.isRunning(types_1.Emulators.AUTH)) {
22
- env[constants_1.Constants.FIREBASE_AUTH_EMULATOR_HOST] = registry_1.EmulatorRegistry.url(types_1.Emulators.AUTH).host;
23
- }
24
- if (registry_1.EmulatorRegistry.isRunning(types_1.Emulators.HUB)) {
25
- env[constants_1.Constants.FIREBASE_EMULATOR_HUB] = registry_1.EmulatorRegistry.url(types_1.Emulators.HUB).host;
26
- }
27
- const pubsubEmulator = registry_1.EmulatorRegistry.isRunning(types_1.Emulators.PUBSUB);
28
- if (pubsubEmulator) {
29
- env[constants_1.Constants.PUBSUB_EMULATOR_HOST] = registry_1.EmulatorRegistry.url(types_1.Emulators.PUBSUB).host;
30
- }
31
- if (registry_1.EmulatorRegistry.isRunning(types_1.Emulators.EVENTARC)) {
32
- env[constants_1.Constants.CLOUD_EVENTARC_EMULATOR_HOST] = `http://${registry_1.EmulatorRegistry.url(types_1.Emulators.EVENTARC).host}`;
6
+ const functionsEmulatorShared_1 = require("./functionsEmulatorShared");
7
+ function setEnvVarsForEmulators(env, emulators) {
8
+ for (const emu of emulators) {
9
+ const host = (0, functionsEmulatorShared_1.formatHost)(emu);
10
+ switch (emu.name) {
11
+ case types_1.Emulators.FIRESTORE:
12
+ env[constants_1.Constants.FIRESTORE_EMULATOR_HOST] = host;
13
+ env[constants_1.Constants.FIRESTORE_EMULATOR_ENV_ALT] = host;
14
+ break;
15
+ case types_1.Emulators.DATABASE:
16
+ env[constants_1.Constants.FIREBASE_DATABASE_EMULATOR_HOST] = host;
17
+ break;
18
+ case types_1.Emulators.STORAGE:
19
+ env[constants_1.Constants.FIREBASE_STORAGE_EMULATOR_HOST] = host;
20
+ env[constants_1.Constants.CLOUD_STORAGE_EMULATOR_HOST] = `http://${host}`;
21
+ break;
22
+ case types_1.Emulators.AUTH:
23
+ env[constants_1.Constants.FIREBASE_AUTH_EMULATOR_HOST] = host;
24
+ break;
25
+ case types_1.Emulators.HUB:
26
+ env[constants_1.Constants.FIREBASE_EMULATOR_HUB] = host;
27
+ break;
28
+ case types_1.Emulators.PUBSUB:
29
+ env[constants_1.Constants.PUBSUB_EMULATOR_HOST] = host;
30
+ break;
31
+ case types_1.Emulators.EVENTARC:
32
+ env[constants_1.Constants.CLOUD_EVENTARC_EMULATOR_HOST] = `http://${host}`;
33
+ break;
34
+ }
33
35
  }
34
36
  }
35
37
  exports.setEnvVarsForEmulators = setEnvVarsForEmulators;
@@ -107,9 +107,11 @@ class FunctionsEmulator {
107
107
  const httpsFunctionRoutes = [httpsFunctionRoute, `${httpsFunctionRoute}/*`];
108
108
  const listBackendsRoute = `/backends`;
109
109
  const httpsHandler = (req, res) => {
110
- this.workQueue.submit(() => {
110
+ const work = () => {
111
111
  return this.handleHttpsTrigger(req, res);
112
- });
112
+ };
113
+ work.type = `${req.path}-${new Date().toISOString()}`;
114
+ this.workQueue.submit(work);
113
115
  };
114
116
  const multicastHandler = (req, res) => {
115
117
  var _a;
@@ -129,7 +131,7 @@ class FunctionsEmulator {
129
131
  const triggers = this.multicastTriggers[triggerKey] || [];
130
132
  const { host, port } = this.getInfo();
131
133
  triggers.forEach((triggerId) => {
132
- this.workQueue.submit(() => {
134
+ const work = () => {
133
135
  return new Promise((resolve, reject) => {
134
136
  const trigReq = http.request({
135
137
  host: (0, utils_1.connectableHostname)(host),
@@ -143,7 +145,9 @@ class FunctionsEmulator {
143
145
  trigReq.end();
144
146
  resolve();
145
147
  });
146
- });
148
+ };
149
+ work.type = `${triggerId}-${new Date().toISOString()}`;
150
+ this.workQueue.submit(work);
147
151
  });
148
152
  res.json({ status: "multicast_acknowledged" });
149
153
  };
@@ -262,7 +266,6 @@ class FunctionsEmulator {
262
266
  await runtimeDelegate.validate();
263
267
  logger_1.logger.debug(`Building ${runtimeDelegate.name} source`);
264
268
  await runtimeDelegate.build();
265
- logger_1.logger.debug(`Analyzing ${runtimeDelegate.name} backend spec`);
266
269
  const firebaseConfig = this.getFirebaseConfig();
267
270
  const environment = Object.assign(Object.assign(Object.assign(Object.assign({}, this.getSystemEnvs()), this.getEmulatorEnvs()), { FIREBASE_CONFIG: firebaseConfig }), emulatableBackend.env);
268
271
  const userEnvOpt = {
@@ -270,8 +273,9 @@ class FunctionsEmulator {
270
273
  projectId: this.args.projectId,
271
274
  projectAlias: this.args.projectAlias,
272
275
  };
276
+ const userEnvs = functionsEnv.loadUserEnvs(userEnvOpt);
273
277
  const discoveredBuild = await runtimeDelegate.discoverBuild(runtimeConfig, environment);
274
- const resolution = await (0, build_1.resolveBackend)(discoveredBuild, JSON.parse(firebaseConfig), userEnvOpt, environment);
278
+ const resolution = await (0, build_1.resolveBackend)(discoveredBuild, JSON.parse(firebaseConfig), userEnvOpt, userEnvs);
275
279
  const discoveredBackend = resolution.backend;
276
280
  const endpoints = backend.allEndpoints(discoveredBackend);
277
281
  (0, functionsEmulatorShared_1.prepareEndpoints)(endpoints);
@@ -717,7 +721,11 @@ class FunctionsEmulator {
717
721
  skipTokenVerification: true,
718
722
  enableCors: true,
719
723
  });
720
- (0, env_1.setEnvVarsForEmulators)(envs);
724
+ let emulatorInfos = registry_1.EmulatorRegistry.listRunningWithInfo();
725
+ if (this.args.remoteEmulators) {
726
+ emulatorInfos = emulatorInfos.concat(Object.values(this.args.remoteEmulators));
727
+ }
728
+ (0, env_1.setEnvVarsForEmulators)(envs, emulatorInfos);
721
729
  if (this.args.debugPort) {
722
730
  envs["FUNCTION_DEBUG_MODE"] = "true";
723
731
  }
@@ -283,7 +283,7 @@ function toExpressionValue(obj) {
283
283
  }
284
284
  if (obj == null) {
285
285
  return {
286
- null_value: 0,
286
+ null_value: null,
287
287
  };
288
288
  }
289
289
  if (typeof obj === "object") {
@@ -339,7 +339,7 @@ function createRequestExpressionValue(opts) {
339
339
  },
340
340
  time: toExpressionValue(new Date()),
341
341
  resource: toExpressionValue(opts.file.after ? opts.file.after : null),
342
- auth: opts.token ? createAuthExpressionValue(opts) : { null_value: 0 },
342
+ auth: opts.token ? createAuthExpressionValue(opts) : { null_value: null },
343
343
  };
344
344
  return {
345
345
  map_value: {
@@ -11,7 +11,7 @@ class WorkQueue {
11
11
  this.maxParallelWork = maxParallelWork;
12
12
  this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS);
13
13
  this.queue = [];
14
- this.workRunningCount = 0;
14
+ this.running = [];
15
15
  this.notifyQueue = () => {
16
16
  };
17
17
  this.notifyWorkFinish = () => {
@@ -37,8 +37,8 @@ class WorkQueue {
37
37
  this.notifyQueue = res;
38
38
  });
39
39
  }
40
- if (this.workRunningCount >= this.maxParallelWork) {
41
- this.logger.logLabeled("DEBUG", "work-queue", `waiting for work to finish (running=${this.workRunningCount})`);
40
+ if (this.running.length >= this.maxParallelWork) {
41
+ this.logger.logLabeled("DEBUG", "work-queue", `waiting for work to finish (running=${this.running})`);
42
42
  await new Promise((res) => {
43
43
  this.notifyWorkFinish = res;
44
44
  });
@@ -74,8 +74,10 @@ class WorkQueue {
74
74
  }
75
75
  getState() {
76
76
  return {
77
+ queuedWork: this.queue.map((work) => work.type),
77
78
  queueLength: this.queue.length,
78
- workRunningCount: this.workRunningCount,
79
+ runningWork: this.running,
80
+ workRunningCount: this.running.length,
79
81
  };
80
82
  }
81
83
  isWorking() {
@@ -85,7 +87,7 @@ class WorkQueue {
85
87
  async runNext() {
86
88
  const next = this.queue.shift();
87
89
  if (next) {
88
- this.workRunningCount++;
90
+ this.running.push(next.type || "anonymous");
89
91
  this.logState();
90
92
  try {
91
93
  await next();
@@ -94,7 +96,10 @@ class WorkQueue {
94
96
  this.logger.log("DEBUG", e);
95
97
  }
96
98
  finally {
97
- this.workRunningCount--;
99
+ const index = this.running.indexOf(next.type || "anonymous");
100
+ if (index !== -1) {
101
+ this.running.splice(index, 1);
102
+ }
98
103
  this.notifyWorkFinish();
99
104
  this.logState();
100
105
  }
@@ -74,6 +74,12 @@ exports.ALL_EXPERIMENTS = experiments({
74
74
  crossservicerules: {
75
75
  shortDescription: "Allow Firebase Rules to reference resources in other services",
76
76
  },
77
+ internaltesting: {
78
+ shortDescription: "Exposes Firebase CLI commands intended for internal testing purposes.",
79
+ fullDescription: "Exposes Firebase CLI commands intended for internal testing purposes. " +
80
+ "These commands are not meant for public consumption and may break or disappear " +
81
+ "without a notice.",
82
+ },
77
83
  });
78
84
  function isValidExperiment(name) {
79
85
  return Object.keys(exports.ALL_EXPERIMENTS).includes(name);
@@ -230,7 +230,10 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
230
230
  const { build, ɵcodegenPublicDirectory, ɵcodegenFunctionsDirectory: codegenProdModeFunctionsDirectory, getDevModeHandle, name, support, } = exports.WebFrameworks[framework];
231
231
  console.log(`Detected a ${name} codebase. ${SupportLevelWarnings[support] || ""}\n`);
232
232
  const isDevMode = context._name === "serve" || context._name === "emulators:start";
233
- const devModeHandle = isDevMode && getDevModeHandle && (await getDevModeHandle(getProjectPath()));
233
+ const hostingEmulatorInfo = emulators.find((e) => e.name === types_1.Emulators.HOSTING);
234
+ const devModeHandle = isDevMode &&
235
+ getDevModeHandle &&
236
+ (await getDevModeHandle(getProjectPath(), hostingEmulatorInfo));
234
237
  let codegenFunctionsDirectory;
235
238
  if (devModeHandle) {
236
239
  config.public = (0, path_1.relative)(projectRoot, publicDirectory);
@@ -326,6 +329,9 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
326
329
  ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\n` : ""}`);
327
330
  await (0, promises_1.copyFile)(getProjectPath("package-lock.json"), (0, path_1.join)(functionsDist, "package-lock.json")).catch(() => {
328
331
  });
332
+ if (await (0, fs_extra_1.pathExists)(getProjectPath(".npmrc"))) {
333
+ await (0, promises_1.copyFile)(getProjectPath(".npmrc"), (0, path_1.join)(functionsDist, ".npmrc"));
334
+ }
329
335
  (0, child_process_1.execSync)(`${NPM_COMMAND} i --omit dev --no-audit`, {
330
336
  cwd: functionsDist,
331
337
  stdio: "inherit",
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ROUTES_MANIFEST = exports.PRERENDER_MANIFEST = exports.PAGES_MANIFEST = exports.MIDDLEWARE_MANIFEST = exports.IMAGES_MANIFEST = exports.EXPORT_MARKER = exports.APP_PATH_ROUTES_MANIFEST = void 0;
4
+ exports.APP_PATH_ROUTES_MANIFEST = "app-path-routes-manifest.json";
5
+ exports.EXPORT_MARKER = "export-marker.json";
6
+ exports.IMAGES_MANIFEST = "images-manifest.json";
7
+ exports.MIDDLEWARE_MANIFEST = "middleware-manifest.json";
8
+ exports.PAGES_MANIFEST = "pages-manifest.json";
9
+ exports.PRERENDER_MANIFEST = "prerender-manifest.json";
10
+ exports.ROUTES_MANIFEST = "routes-manifest.json";