firebase-tools 10.2.2 → 10.3.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.
Files changed (54) hide show
  1. package/lib/commands/ext-configure.js +58 -4
  2. package/lib/commands/ext-export.js +4 -9
  3. package/lib/commands/ext-install.js +63 -4
  4. package/lib/commands/ext-uninstall.js +9 -0
  5. package/lib/commands/ext-update.js +55 -2
  6. package/lib/config.js +6 -3
  7. package/lib/deploy/extensions/planner.js +6 -6
  8. package/lib/deploy/functions/backend.js +10 -1
  9. package/lib/deploy/functions/checkIam.js +4 -4
  10. package/lib/deploy/functions/prepare.js +2 -1
  11. package/lib/deploy/functions/release/fabricator.js +4 -4
  12. package/lib/deploy/functions/release/planner.js +34 -20
  13. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +6 -1
  14. package/lib/deploy/functions/runtimes/node/index.js +27 -0
  15. package/lib/deploy/functions/runtimes/node/parseTriggers.js +24 -8
  16. package/lib/deploy/functions/services/firebaseAlerts.js +30 -0
  17. package/lib/deploy/functions/services/index.js +9 -1
  18. package/lib/deploy/functions/services/storage.js +10 -4
  19. package/lib/deploy/functions/triggerRegionHelper.js +1 -1
  20. package/lib/emulator/constants.js +1 -0
  21. package/lib/emulator/controller.js +9 -7
  22. package/lib/emulator/extensions/validation.js +37 -2
  23. package/lib/emulator/extensionsEmulator.js +44 -9
  24. package/lib/emulator/functionsEmulator.js +13 -8
  25. package/lib/emulator/functionsEmulatorShared.js +17 -10
  26. package/lib/emulator/storage/apis/firebase.js +312 -335
  27. package/lib/emulator/storage/apis/gcloud.js +238 -113
  28. package/lib/emulator/storage/crc.js +5 -1
  29. package/lib/emulator/storage/errors.js +9 -0
  30. package/lib/emulator/storage/files.js +161 -304
  31. package/lib/emulator/storage/index.js +27 -73
  32. package/lib/emulator/storage/metadata.js +63 -49
  33. package/lib/emulator/storage/multipart.js +62 -0
  34. package/lib/emulator/storage/persistence.js +78 -0
  35. package/lib/emulator/storage/rules/config.js +33 -0
  36. package/lib/emulator/storage/rules/manager.js +81 -0
  37. package/lib/emulator/storage/rules/utils.js +48 -0
  38. package/lib/emulator/storage/server.js +2 -2
  39. package/lib/emulator/storage/upload.js +106 -0
  40. package/lib/extensions/emulator/optionsHelper.js +35 -3
  41. package/lib/extensions/extensionsHelper.js +19 -10
  42. package/lib/extensions/manifest.js +109 -13
  43. package/lib/extensions/paramHelper.js +5 -4
  44. package/lib/functions/env.js +4 -6
  45. package/lib/functions/events/v2.js +11 -0
  46. package/lib/gcp/cloudfunctions.js +18 -6
  47. package/lib/gcp/cloudfunctionsv2.js +30 -12
  48. package/lib/gcp/resourceManager.js +4 -4
  49. package/lib/serve/functions.js +2 -1
  50. package/lib/utils.js +14 -1
  51. package/npm-shrinkwrap.json +2 -2
  52. package/package.json +1 -1
  53. package/lib/deploy/extensions/params.js +0 -42
  54. package/lib/deploy/functions/eventTypes.js +0 -10
@@ -15,6 +15,9 @@ const paramHelper = require("../extensions/paramHelper");
15
15
  const requirePermissions_1 = require("../requirePermissions");
16
16
  const utils = require("../utils");
17
17
  const logger_1 = require("../logger");
18
+ const refs = require("../extensions/refs");
19
+ const manifest = require("../extensions/manifest");
20
+ const functional_1 = require("../functional");
18
21
  marked.setOptions({
19
22
  renderer: new TerminalRenderer(),
20
23
  });
@@ -22,6 +25,7 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
22
25
  .description("configure an existing extension instance")
23
26
  .withForce()
24
27
  .option("--params <paramsFile>", "path of params file with .env format.")
28
+ .option("--local", "save to firebase.json rather than directly install to a Firebase project")
25
29
  .before(requirePermissions_1.requirePermissions, [
26
30
  "firebaseextensions.instances.update",
27
31
  "firebaseextensions.instances.get",
@@ -29,9 +33,46 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
29
33
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
30
34
  .before(extensionsHelper_1.diagnoseAndFixProject)
31
35
  .action(async (instanceId, options) => {
36
+ var _a;
37
+ const projectId = (0, projectUtils_1.needProjectId)(options);
38
+ if (options.local) {
39
+ if (options.nonInteractive) {
40
+ throw new error_1.FirebaseError(`Command not supported in non-interactive mode, edit ./extensions/${instanceId}.env directly instead`);
41
+ }
42
+ const config = manifest.loadConfig(options);
43
+ const targetRef = manifest.getInstanceRef(instanceId, config);
44
+ const extensionVersion = await extensionsApi.getExtensionVersion(refs.toExtensionVersionRef(targetRef));
45
+ const oldParamValues = manifest.readInstanceParam({
46
+ instanceId,
47
+ projectDir: config.projectDir,
48
+ });
49
+ const [immutableParams, tbdParams] = (0, functional_1.partition)(extensionVersion.spec.params, (param) => { var _a; return (_a = param.immutable) !== null && _a !== void 0 ? _a : false; });
50
+ infoImmutableParams(immutableParams, oldParamValues);
51
+ paramHelper.setNewDefaults(tbdParams, oldParamValues);
52
+ const mutableParamsValues = await paramHelper.getParams({
53
+ projectId,
54
+ paramSpecs: tbdParams,
55
+ nonInteractive: false,
56
+ paramsEnvPath: ((_a = options.params) !== null && _a !== void 0 ? _a : ""),
57
+ instanceId,
58
+ reconfiguring: true,
59
+ });
60
+ const newParamValues = Object.assign(Object.assign({}, oldParamValues), mutableParamsValues);
61
+ await manifest.writeToManifest([
62
+ {
63
+ instanceId,
64
+ ref: targetRef,
65
+ params: newParamValues,
66
+ },
67
+ ], config, {
68
+ nonInteractive: false,
69
+ force: true,
70
+ });
71
+ manifest.showPreviewWarning();
72
+ return;
73
+ }
32
74
  const spinner = ora(`Configuring ${clc.bold(instanceId)}. This usually takes 3 to 5 minutes...`);
33
75
  try {
34
- const projectId = (0, projectUtils_1.needProjectId)(options);
35
76
  let existingInstance;
36
77
  try {
37
78
  existingInstance = await extensionsApi.getInstance(projectId, instanceId);
@@ -45,9 +86,7 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
45
86
  throw err;
46
87
  }
47
88
  const paramSpecWithNewDefaults = paramHelper.getParamsWithCurrentValuesAsDefaults(existingInstance);
48
- const immutableParams = _.remove(paramSpecWithNewDefaults, (param) => {
49
- return param.immutable || param.param === "LOCATION";
50
- });
89
+ const immutableParams = _.remove(paramSpecWithNewDefaults, (param) => param.immutable);
51
90
  const params = await paramHelper.getParams({
52
91
  projectId,
53
92
  paramSpecs: paramSpecWithNewDefaults,
@@ -74,6 +113,7 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
74
113
  spinner.stop();
75
114
  utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `successfully configured ${clc.bold(instanceId)}.`);
76
115
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`You can view your reconfigured instance in the Firebase console: ${utils.consoleUrl(projectId, `/extensions/instances/${instanceId}?tab=config`)}`));
116
+ manifest.showDeprecationWarning();
77
117
  return res;
78
118
  }
79
119
  catch (err) {
@@ -88,3 +128,17 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
88
128
  throw err;
89
129
  }
90
130
  });
131
+ function infoImmutableParams(immutableParams, paramValues) {
132
+ if (!immutableParams.length) {
133
+ return;
134
+ }
135
+ const plural = immutableParams.length > 1;
136
+ utils.logLabeledWarning(extensionsHelper_1.logPrefix, marked(`The following param${plural ? "s are" : " is"} immutable and won't be changed:`));
137
+ for (const { param } of immutableParams) {
138
+ logger_1.logger.info(`param: ${param}, value: ${paramValues[param]}`);
139
+ }
140
+ logger_1.logger.info((plural
141
+ ? "To set different values for these params"
142
+ : "To set a different value for this param") +
143
+ ", uninstall the extension, then install a new instance of this extension.");
144
+ }
@@ -2,12 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
4
4
  const command_1 = require("../command");
5
- const config_1 = require("../config");
6
5
  const planner = require("../deploy/extensions/planner");
7
- const error_1 = require("../error");
8
6
  const export_1 = require("../extensions/export");
9
7
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
10
- const manifest_1 = require("../extensions/manifest");
8
+ const manifest = require("../extensions/manifest");
11
9
  const functional_1 = require("../functional");
12
10
  const getProjectNumber_1 = require("../getProjectNumber");
13
11
  const logger_1 = require("../logger");
@@ -43,12 +41,9 @@ module.exports = new command_1.Command("ext:export")
43
41
  logger_1.logger.info("Exiting. No changes made.");
44
42
  return;
45
43
  }
46
- const existingConfig = config_1.Config.load(options, true);
47
- if (!existingConfig) {
48
- throw new error_1.FirebaseError("Not currently in a Firebase directory. Please run `firebase init` to create a Firebase directory.");
49
- }
50
- await (0, manifest_1.writeToManifest)(withRef, existingConfig, {
44
+ const existingConfig = manifest.loadConfig(options);
45
+ await manifest.writeToManifest(withRef, existingConfig, {
51
46
  nonInteractive: options.nonInteractive,
52
47
  force: options.force,
53
- });
48
+ }, true);
54
49
  });
@@ -27,6 +27,7 @@ const utils = require("../utils");
27
27
  const track_1 = require("../track");
28
28
  const logger_1 = require("../logger");
29
29
  const previews_1 = require("../previews");
30
+ const manifest = require("../extensions/manifest");
30
31
  marked.setOptions({
31
32
  renderer: new TerminalRenderer(),
32
33
  });
@@ -38,13 +39,15 @@ exports.default = new command_1.Command("ext:install [extensionName]")
38
39
  "or run with `-i` to see all available extensions.")
39
40
  .withForce()
40
41
  .option("--params <paramsFile>", "name of params variables file with .env format.")
42
+ .option("--local", "save to firebase.json rather than directly install to a Firebase project")
41
43
  .before(requirePermissions_1.requirePermissions, ["firebaseextensions.instances.create"])
42
44
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
43
45
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
44
46
  .before(extensionsHelper_1.diagnoseAndFixProject)
45
47
  .action(async (extensionName, options) => {
48
+ var _a;
46
49
  const projectId = (0, projectUtils_1.needProjectId)(options);
47
- const paramsEnvPath = options.params;
50
+ const paramsEnvPath = ((_a = options.params) !== null && _a !== void 0 ? _a : "");
48
51
  let learnMore = false;
49
52
  if (!extensionName) {
50
53
  if (options.interactive) {
@@ -59,12 +62,18 @@ exports.default = new command_1.Command("ext:install [extensionName]")
59
62
  }
60
63
  let source;
61
64
  let extVersion;
65
+ if ((0, extensionsHelper_1.isUrlPath)(extensionName)) {
66
+ void (0, track_1.track)("Extension Install", "Install by url path", options.interactive ? 1 : 0);
67
+ }
62
68
  if ((0, extensionsHelper_1.isLocalOrURLPath)(extensionName)) {
63
- (0, track_1.track)("Extension Install", "Install by Source", options.interactive ? 1 : 0);
69
+ void (0, track_1.track)("Extension Install", "Install by Source", options.interactive ? 1 : 0);
70
+ if (options.local) {
71
+ throw new error_1.FirebaseError("Installing a local source locally is not supported yet, please use ext:dev:emulator commands");
72
+ }
64
73
  source = await infoInstallBySource(projectId, extensionName);
65
74
  }
66
75
  else {
67
- (0, track_1.track)("Extension Install", "Install by Extension Ref", options.interactive ? 1 : 0);
76
+ void (0, track_1.track)("Extension Install", "Install by Extension Ref", options.interactive ? 1 : 0);
68
77
  extVersion = await infoInstallByReference(extensionName, options.interactive);
69
78
  }
70
79
  if (!(await (0, extensionsHelper_1.confirm)({
@@ -86,6 +95,27 @@ exports.default = new command_1.Command("ext:install [extensionName]")
86
95
  `${spec.description}\n` +
87
96
  `View details: https://firebase.google.com/products/extensions/${spec.name}\n`);
88
97
  }
98
+ if (options.local) {
99
+ try {
100
+ return installToManifest({
101
+ paramsEnvPath,
102
+ projectId,
103
+ extensionName,
104
+ source,
105
+ extVersion,
106
+ nonInteractive: options.nonInteractive,
107
+ force: options.force,
108
+ });
109
+ }
110
+ catch (err) {
111
+ if (!(err instanceof error_1.FirebaseError)) {
112
+ throw new error_1.FirebaseError(`Error occurred saving the extension to manifest: ${err.message}`, {
113
+ original: err,
114
+ });
115
+ }
116
+ throw err;
117
+ }
118
+ }
89
119
  try {
90
120
  return installExtension({
91
121
  paramsEnvPath,
@@ -126,7 +156,7 @@ async function infoInstallByReference(extensionName, interactive) {
126
156
  const ref = refs.parse(extensionName);
127
157
  const extension = await extensionsApi.getExtension(refs.toExtensionRef(ref));
128
158
  if (!ref.version) {
129
- (0, track_1.track)("Extension Install", "Install by Extension Version Ref", interactive ? 1 : 0);
159
+ void (0, track_1.track)("Extension Install", "Install by Extension Version Ref", interactive ? 1 : 0);
130
160
  extensionName = `${extensionName}@latest`;
131
161
  }
132
162
  const extVersion = await extensionsApi.getExtensionVersion(extensionName);
@@ -134,6 +164,34 @@ async function infoInstallByReference(extensionName, interactive) {
134
164
  await (0, warnings_1.displayWarningPrompts)(ref.publisherId, extension.registryLaunchStage, extVersion);
135
165
  return extVersion;
136
166
  }
167
+ async function installToManifest(options) {
168
+ const { projectId, extensionName, extVersion, paramsEnvPath, nonInteractive, force } = options;
169
+ const spec = extVersion === null || extVersion === void 0 ? void 0 : extVersion.spec;
170
+ if (!spec) {
171
+ throw new error_1.FirebaseError(`Could not find the extension.yaml for ${extensionName}. Please make sure this is a valid extension and try again.`);
172
+ }
173
+ const config = manifest.loadConfig(options);
174
+ let instanceId = spec.name;
175
+ while (manifest.instanceExists(instanceId, config)) {
176
+ instanceId = await (0, extensionsHelper_1.promptForValidInstanceId)(`${spec.name}-${(0, utils_1.getRandomString)(4)}`);
177
+ }
178
+ const params = await paramHelper.getParams({
179
+ projectId,
180
+ paramSpecs: spec.params,
181
+ nonInteractive,
182
+ paramsEnvPath,
183
+ instanceId,
184
+ });
185
+ const ref = refs.parse(extVersion.ref);
186
+ await manifest.writeToManifest([
187
+ {
188
+ instanceId,
189
+ ref,
190
+ params,
191
+ },
192
+ ], config, { nonInteractive, force: force !== null && force !== void 0 ? force : false });
193
+ manifest.showPreviewWarning();
194
+ }
137
195
  async function installExtension(options) {
138
196
  const { projectId, extensionName, source, extVersion, paramsEnvPath, nonInteractive, force } = options;
139
197
  const spec = (source === null || source === void 0 ? void 0 : source.spec) || (extVersion === null || extVersion === void 0 ? void 0 : extVersion.spec);
@@ -253,6 +311,7 @@ async function installExtension(options) {
253
311
  `which may include some required post-installation tasks: ${utils.consoleUrl(projectId, `/extensions/instances/${instanceId}?tab=usage`)}`));
254
312
  logger_1.logger.info(marked("You can run `firebase ext` to view available Firebase Extensions commands, " +
255
313
  "including those to update, reconfigure, or delete your installed extension."));
314
+ manifest.showDeprecationWarning();
256
315
  }
257
316
  catch (err) {
258
317
  if (spinner.isSpinning) {
@@ -16,17 +16,25 @@ const prompt_1 = require("../prompt");
16
16
  const requirePermissions_1 = require("../requirePermissions");
17
17
  const utils = require("../utils");
18
18
  const logger_1 = require("../logger");
19
+ const manifest = require("../extensions/manifest");
19
20
  marked.setOptions({
20
21
  renderer: new TerminalRenderer(),
21
22
  });
22
23
  exports.default = new command_1.Command("ext:uninstall <extensionInstanceId>")
23
24
  .description("uninstall an extension that is installed in your Firebase project by instance ID")
24
25
  .withForce()
26
+ .option("--local", "remove from firebase.json rather than directly uninstall from a Firebase project")
25
27
  .before(requirePermissions_1.requirePermissions, ["firebaseextensions.instances.delete"])
26
28
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
27
29
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
28
30
  .before(extensionsHelper_1.diagnoseAndFixProject)
29
31
  .action(async (instanceId, options) => {
32
+ if (options.local) {
33
+ const config = manifest.loadConfig(options);
34
+ manifest.removeFromManifest(instanceId, config);
35
+ manifest.showPreviewWarning();
36
+ return;
37
+ }
30
38
  const projectId = (0, projectUtils_1.needProjectId)(options);
31
39
  let instance;
32
40
  try {
@@ -93,6 +101,7 @@ exports.default = new command_1.Command("ext:uninstall <extensionInstanceId>")
93
101
  return utils.reject(`Error occurred uninstalling extension ${instanceId}`, { original: err });
94
102
  }
95
103
  utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `uninstalled ${clc.bold(instanceId)}`);
104
+ manifest.showDeprecationWarning();
96
105
  });
97
106
  function consoleUninstallOnly(projectId, instanceId) {
98
107
  const instanceURL = `https://console.firebase.google.com/project/${projectId}/extensions/instances/${instanceId}`;
@@ -22,6 +22,7 @@ const projectUtils_1 = require("../projectUtils");
22
22
  const requirePermissions_1 = require("../requirePermissions");
23
23
  const utils = require("../utils");
24
24
  const previews_1 = require("../previews");
25
+ const manifest = require("../extensions/manifest");
25
26
  marked.setOptions({
26
27
  renderer: new TerminalRenderer(),
27
28
  });
@@ -38,10 +39,61 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
38
39
  .before(extensionsHelper_1.diagnoseAndFixProject)
39
40
  .withForce()
40
41
  .option("--params <paramsFile>", "name of params variables file with .env format.")
42
+ .option("--local", "save the update to firebase.json rather than directly update an existing Extension instance on a Firebase project")
41
43
  .action(async (instanceId, updateSource, options) => {
44
+ var _a, _b;
45
+ const projectId = (0, projectUtils_1.needProjectId)(options);
46
+ if (options.local) {
47
+ const config = manifest.loadConfig(options);
48
+ const oldRef = manifest.getInstanceRef(instanceId, config);
49
+ const oldExtensionVersion = await extensionsApi.getExtensionVersion(refs.toExtensionVersionRef(oldRef));
50
+ updateSource = (0, updateHelper_1.inferUpdateSource)(updateSource, refs.toExtensionRef(oldRef));
51
+ const newSourceOrigin = (0, extensionsHelper_1.getSourceOrigin)(updateSource);
52
+ if (![extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION, extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION_VERSION].includes(newSourceOrigin)) {
53
+ throw new error_1.FirebaseError(`Only updating to a published extension version is allowed`);
54
+ }
55
+ const newExtensionVersion = await extensionsApi.getExtensionVersion(updateSource);
56
+ if (oldExtensionVersion.ref === newExtensionVersion.ref) {
57
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, `${clc.bold(instanceId)} is already up to date. Its version is ${clc.bold(newExtensionVersion.ref)}.`);
58
+ return;
59
+ }
60
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, `Updating ${clc.bold(instanceId)} from version ${clc.bold(oldExtensionVersion.ref)} to version ${clc.bold(newExtensionVersion.ref)}.`);
61
+ if (!(await (0, extensionsHelper_1.confirm)({
62
+ nonInteractive: options.nonInteractive,
63
+ force: options.force,
64
+ default: false,
65
+ }))) {
66
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, "Update aborted.");
67
+ return;
68
+ }
69
+ const oldParamValues = manifest.readInstanceParam({
70
+ instanceId,
71
+ projectDir: config.projectDir,
72
+ });
73
+ const newParams = await paramHelper.getParamsForUpdate({
74
+ spec: oldExtensionVersion.spec,
75
+ newSpec: newExtensionVersion.spec,
76
+ currentParams: oldParamValues,
77
+ projectId,
78
+ paramsEnvPath: ((_a = options.params) !== null && _a !== void 0 ? _a : ""),
79
+ nonInteractive: options.nonInteractive,
80
+ instanceId,
81
+ });
82
+ await manifest.writeToManifest([
83
+ {
84
+ instanceId,
85
+ ref: refs.parse(newExtensionVersion.ref),
86
+ params: newParams,
87
+ },
88
+ ], config, {
89
+ nonInteractive: options.nonInteractive,
90
+ force: true,
91
+ });
92
+ manifest.showPreviewWarning();
93
+ return;
94
+ }
42
95
  const spinner = ora(`Updating ${clc.bold(instanceId)}. This usually takes 3 to 5 minutes...`);
43
96
  try {
44
- const projectId = (0, projectUtils_1.needProjectId)(options);
45
97
  let existingInstance;
46
98
  try {
47
99
  existingInstance = await extensionsApi.getInstance(projectId, instanceId);
@@ -148,7 +200,7 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
148
200
  newSpec,
149
201
  currentParams: existingParams,
150
202
  projectId,
151
- paramsEnvPath: options.params,
203
+ paramsEnvPath: ((_b = options.params) !== null && _b !== void 0 ? _b : ""),
152
204
  nonInteractive: options.nonInteractive,
153
205
  instanceId,
154
206
  });
@@ -170,6 +222,7 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
170
222
  spinner.stop();
171
223
  utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `successfully updated ${clc.bold(instanceId)}.`);
172
224
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`You can view your updated instance in the Firebase console: ${utils.consoleUrl(projectId, `/extensions/instances/${instanceId}?tab=usage`)}`));
225
+ manifest.showDeprecationWarning();
173
226
  }
174
227
  catch (err) {
175
228
  if (spinner.isSpinning) {
package/lib/config.js CHANGED
@@ -17,12 +17,12 @@ const logger_1 = require("./logger");
17
17
  const loadCJSON = require("./loadCJSON");
18
18
  const parseBoltRules = require("./parseBoltRules");
19
19
  class Config {
20
- constructor(src, options) {
20
+ constructor(src, options = {}) {
21
21
  this.data = {};
22
22
  this.defaults = {};
23
23
  this.notes = {};
24
- this.options = options || {};
25
- this.projectDir = options.projectDir || (0, detectProjectRoot_1.detectProjectRoot)(options);
24
+ this.options = options;
25
+ this.projectDir = this.options.projectDir || (0, detectProjectRoot_1.detectProjectRoot)(this.options);
26
26
  this._src = src;
27
27
  if (this._src.firebase) {
28
28
  this.defaults.project = this._src.firebase;
@@ -144,6 +144,9 @@ class Config {
144
144
  fs.ensureFileSync(this.path(p));
145
145
  fs.writeFileSync(this.path(p), content, "utf8");
146
146
  }
147
+ deleteProjectFile(p) {
148
+ fs.removeSync(this.path(p));
149
+ }
147
150
  askWriteProjectFile(p, content, force) {
148
151
  const writeTo = this.path(p);
149
152
  let next;
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveVersion = exports.want = exports.have = exports.getExtension = exports.getExtensionVersion = void 0;
4
4
  const semver = require("semver");
5
- const error_1 = require("../../error");
6
5
  const extensionsApi = require("../../extensions/extensionsApi");
7
- const extensionsHelper_1 = require("../../extensions/extensionsHelper");
8
6
  const refs = require("../../extensions/refs");
9
- const params_1 = require("./params");
7
+ const error_1 = require("../../error");
8
+ const extensionsHelper_1 = require("../../extensions/extensionsHelper");
10
9
  const logger_1 = require("../../logger");
10
+ const manifest_1 = require("../../extensions/manifest");
11
11
  async function getExtensionVersion(i) {
12
12
  if (!i.extensionVersion) {
13
13
  if (!i.ref) {
@@ -52,15 +52,15 @@ async function want(args) {
52
52
  const instanceId = e[0];
53
53
  const ref = refs.parse(e[1]);
54
54
  ref.version = await resolveVersion(ref);
55
- const params = (0, params_1.readParams)({
55
+ const params = (0, manifest_1.readInstanceParam)({
56
56
  projectDir: args.projectDir,
57
57
  instanceId,
58
58
  projectId: args.projectId,
59
59
  projectNumber: args.projectNumber,
60
60
  aliases: args.aliases,
61
- checkLocal: args.checkLocal,
61
+ checkLocal: args.emulatorMode,
62
62
  });
63
- const autoPopulatedParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId);
63
+ const autoPopulatedParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId, args.emulatorMode);
64
64
  const subbedParams = (0, extensionsHelper_1.substituteParams)(params, autoPopulatedParams);
65
65
  instanceSpecs.push({
66
66
  instanceId,
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.compareFunctions = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.of = exports.empty = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.SCHEDULED_FUNCTION_LABEL = exports.MIN_MEMORY_FOR_CONCURRENCY = exports.DEFAULT_MEMORY = exports.memoryOptionDisplayName = exports.endpointTriggerType = void 0;
3
+ exports.compareFunctions = exports.findEventFilter = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.of = exports.empty = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.secretVersionName = exports.SCHEDULED_FUNCTION_LABEL = exports.MIN_MEMORY_FOR_CONCURRENCY = exports.DEFAULT_MEMORY = exports.memoryOptionDisplayName = exports.endpointTriggerType = void 0;
4
4
  const gcf = require("../../gcp/cloudfunctions");
5
5
  const gcfV2 = require("../../gcp/cloudfunctionsv2");
6
6
  const utils = require("../../utils");
@@ -42,6 +42,11 @@ exports.memoryOptionDisplayName = memoryOptionDisplayName;
42
42
  exports.DEFAULT_MEMORY = 256;
43
43
  exports.MIN_MEMORY_FOR_CONCURRENCY = 2048;
44
44
  exports.SCHEDULED_FUNCTION_LABEL = Object.freeze({ deployment: "firebase-schedule" });
45
+ function secretVersionName(s) {
46
+ var _a;
47
+ return `projects/${s.projectId}/secrets/${s.secret}/versions/${(_a = s.version) !== null && _a !== void 0 ? _a : "latest"}`;
48
+ }
49
+ exports.secretVersionName = secretVersionName;
45
50
  function isHttpsTriggered(triggered) {
46
51
  return {}.hasOwnProperty.call(triggered, "httpsTrigger");
47
52
  }
@@ -225,6 +230,10 @@ const missingEndpoint = (backend) => (endpoint) => {
225
230
  return !(0, exports.hasEndpoint)(backend)(endpoint);
226
231
  };
227
232
  exports.missingEndpoint = missingEndpoint;
233
+ function findEventFilter(endpoint, attribute) {
234
+ return endpoint.eventTrigger.eventFilters.find((ef) => ef.attribute === attribute);
235
+ }
236
+ exports.findEventFilter = findEventFilter;
228
237
  function compareFunctions(left, right) {
229
238
  if (left.platform !== right.platform) {
230
239
  return right.platform < left.platform ? -1 : 1;
@@ -87,7 +87,7 @@ function mergeBindings(policy, allRequiredBindings) {
87
87
  }
88
88
  }
89
89
  exports.mergeBindings = mergeBindings;
90
- async function ensureServiceAgentRoles(projectId, want, have) {
90
+ async function ensureServiceAgentRoles(projectNumber, want, have) {
91
91
  const wantServices = backend.allEndpoints(want).reduce(reduceEventsToServices, []);
92
92
  const haveServices = backend.allEndpoints(have).reduce(reduceEventsToServices, []);
93
93
  const newServices = wantServices.filter((wantS) => !haveServices.find((haveS) => wantS.name === haveS.name));
@@ -96,7 +96,7 @@ async function ensureServiceAgentRoles(projectId, want, have) {
96
96
  }
97
97
  let policy;
98
98
  try {
99
- policy = await (0, resourceManager_1.getIamPolicy)(projectId);
99
+ policy = await (0, resourceManager_1.getIamPolicy)(projectNumber);
100
100
  }
101
101
  catch (err) {
102
102
  utils.logLabeledBullet("functions", "Could not verify the necessary IAM configuration for the following newly-integrated services: " +
@@ -105,11 +105,11 @@ async function ensureServiceAgentRoles(projectId, want, have) {
105
105
  return;
106
106
  }
107
107
  const findRequiredBindings = [];
108
- newServices.forEach((service) => findRequiredBindings.push(service.requiredProjectBindings(projectId, policy)));
108
+ newServices.forEach((service) => findRequiredBindings.push(service.requiredProjectBindings(projectNumber, policy)));
109
109
  const allRequiredBindings = await Promise.all(findRequiredBindings);
110
110
  mergeBindings(policy, allRequiredBindings);
111
111
  try {
112
- await (0, resourceManager_1.setIamPolicy)(projectId, policy, "bindings");
112
+ await (0, resourceManager_1.setIamPolicy)(projectNumber, policy, "bindings");
113
113
  }
114
114
  catch (err) {
115
115
  throw new error_1.FirebaseError("We failed to modify the IAM policy for the project. The functions " +
@@ -27,6 +27,7 @@ function hasDotenv(opts) {
27
27
  }
28
28
  async function prepare(context, options, payload) {
29
29
  const projectId = (0, projectUtils_1.needProjectId)(options);
30
+ const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
30
31
  const sourceDirName = options.config.get("functions.source");
31
32
  if (!sourceDirName) {
32
33
  throw new error_1.FirebaseError(`No functions code detected at default location (./functions), and no functions.source defined in firebase.json`);
@@ -111,7 +112,7 @@ async function prepare(context, options, payload) {
111
112
  return (0, functionsDeployHelper_1.functionMatchesAnyGroup)(endpoint, context.filters);
112
113
  });
113
114
  const haveBackend = await backend.existingBackend(context);
114
- await (0, checkIam_1.ensureServiceAgentRoles)(projectId, wantBackend, haveBackend);
115
+ await (0, checkIam_1.ensureServiceAgentRoles)(projectNumber, wantBackend, haveBackend);
115
116
  inferDetailsFromExisting(wantBackend, haveBackend, usedDotenv);
116
117
  await (0, triggerRegionHelper_1.ensureTriggerRegions)(wantBackend);
117
118
  await (0, prompts_1.promptForFailurePolicies)(options, matchingBackend, haveBackend);
@@ -51,12 +51,12 @@ class Fabricator {
51
51
  totalTime: 0,
52
52
  results: [],
53
53
  };
54
- const deployRegions = Object.values(plan).map(async (changes) => {
55
- const results = await this.applyRegionalChanges(changes);
54
+ const deployChangesets = Object.values(plan).map(async (changes) => {
55
+ const results = await this.applyChangeset(changes);
56
56
  summary.results.push(...results);
57
57
  return;
58
58
  });
59
- const promiseResults = await utils.allSettled(deployRegions);
59
+ const promiseResults = await utils.allSettled(deployChangesets);
60
60
  const errs = promiseResults
61
61
  .filter((r) => r.status === "rejected")
62
62
  .map((r) => r.reason);
@@ -66,7 +66,7 @@ class Fabricator {
66
66
  summary.totalTime = timer.stop();
67
67
  return summary;
68
68
  }
69
- async applyRegionalChanges(changes) {
69
+ async applyChangeset(changes) {
70
70
  const deployResults = [];
71
71
  const handle = async (op, endpoint, fn) => {
72
72
  const timer = new timer_1.Timer();