firebase-tools 9.17.0 → 9.21.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 (95) hide show
  1. package/CHANGELOG.md +3 -7
  2. package/lib/api.js +1 -0
  3. package/lib/apiv2.js +5 -3
  4. package/lib/appdistribution/client.js +84 -72
  5. package/lib/appdistribution/distribution.js +8 -26
  6. package/lib/appdistribution/options-parser-util.js +51 -0
  7. package/lib/command.js +1 -1
  8. package/lib/commands/appdistribution-distribute.js +74 -91
  9. package/lib/commands/appdistribution-testers-add.js +18 -0
  10. package/lib/commands/appdistribution-testers-remove.js +32 -0
  11. package/lib/commands/crashlytics-symbols-upload.js +146 -0
  12. package/lib/commands/ext-configure.js +9 -1
  13. package/lib/commands/ext-dev-extension-delete.js +2 -1
  14. package/lib/commands/ext-dev-publish.js +11 -4
  15. package/lib/commands/ext-dev-unpublish.js +12 -4
  16. package/lib/commands/ext-install.js +115 -48
  17. package/lib/commands/ext-uninstall.js +6 -0
  18. package/lib/commands/ext-update.js +61 -18
  19. package/lib/commands/functions-config-export.js +115 -0
  20. package/lib/commands/functions-delete.js +45 -25
  21. package/lib/commands/functions-list.js +54 -0
  22. package/lib/commands/functions-log.js +5 -22
  23. package/lib/commands/hosting-channel-deploy.js +6 -4
  24. package/lib/commands/index.js +12 -0
  25. package/lib/deploy/functions/backend.js +118 -121
  26. package/lib/deploy/functions/checkIam.js +8 -8
  27. package/lib/deploy/functions/containerCleaner.js +5 -1
  28. package/lib/deploy/functions/deploy.js +11 -15
  29. package/lib/deploy/functions/functionsDeployHelper.js +3 -68
  30. package/lib/deploy/functions/prepare.js +67 -33
  31. package/lib/deploy/functions/pricing.js +17 -17
  32. package/lib/deploy/functions/prompts.js +24 -41
  33. package/lib/deploy/functions/release/executor.js +39 -0
  34. package/lib/deploy/functions/release/fabricator.js +362 -0
  35. package/lib/deploy/functions/release/index.js +69 -0
  36. package/lib/deploy/functions/release/planner.js +159 -0
  37. package/lib/deploy/functions/release/reporter.js +162 -0
  38. package/lib/deploy/functions/release/sourceTokenScraper.js +28 -0
  39. package/lib/deploy/functions/release/timer.js +14 -0
  40. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +102 -126
  41. package/lib/deploy/functions/runtimes/node/parseTriggers.js +34 -50
  42. package/lib/deploy/functions/triggerRegionHelper.js +40 -0
  43. package/lib/deploy/functions/validate.js +1 -24
  44. package/lib/downloadUtils.js +37 -0
  45. package/lib/emulator/auth/apiSpec.js +1788 -403
  46. package/lib/emulator/auth/handlers.js +6 -5
  47. package/lib/emulator/auth/operations.js +439 -40
  48. package/lib/emulator/auth/server.js +32 -11
  49. package/lib/emulator/auth/state.js +205 -5
  50. package/lib/emulator/auth/widget_ui.js +2 -2
  51. package/lib/emulator/download.js +2 -31
  52. package/lib/emulator/downloadableEmulators.js +7 -7
  53. package/lib/emulator/emulatorLogger.js +0 -3
  54. package/lib/emulator/events/types.js +16 -0
  55. package/lib/emulator/functionsEmulator.js +117 -20
  56. package/lib/emulator/functionsEmulatorRuntime.js +46 -121
  57. package/lib/emulator/functionsEmulatorShared.js +51 -7
  58. package/lib/emulator/functionsEmulatorShell.js +1 -1
  59. package/lib/emulator/pubsubEmulator.js +61 -40
  60. package/lib/emulator/storage/cloudFunctions.js +37 -7
  61. package/lib/extensions/askUserForConsent.js +16 -13
  62. package/lib/extensions/askUserForParam.js +72 -3
  63. package/lib/extensions/billingMigrationHelper.js +1 -11
  64. package/lib/extensions/changelog.js +2 -1
  65. package/lib/extensions/displayExtensionInfo.js +35 -33
  66. package/lib/extensions/emulator/optionsHelper.js +3 -3
  67. package/lib/extensions/emulator/triggerHelper.js +2 -32
  68. package/lib/extensions/extensionsApi.js +67 -94
  69. package/lib/extensions/extensionsHelper.js +49 -35
  70. package/lib/extensions/paramHelper.js +79 -36
  71. package/lib/extensions/refs.js +59 -0
  72. package/lib/extensions/secretsUtils.js +58 -0
  73. package/lib/extensions/updateHelper.js +21 -45
  74. package/lib/extensions/warnings.js +1 -7
  75. package/lib/functional.js +64 -0
  76. package/lib/functions/env.js +26 -13
  77. package/lib/functions/functionslog.js +40 -0
  78. package/lib/functions/runtimeConfigExport.js +137 -0
  79. package/lib/gcp/cloudfunctions.js +46 -38
  80. package/lib/gcp/cloudfunctionsv2.js +47 -47
  81. package/lib/gcp/cloudlogging.js +27 -21
  82. package/lib/gcp/cloudscheduler.js +22 -16
  83. package/lib/gcp/pubsub.js +1 -9
  84. package/lib/gcp/secretManager.js +111 -0
  85. package/lib/gcp/storage.js +16 -0
  86. package/lib/previews.js +1 -1
  87. package/lib/requireInteractive.js +12 -0
  88. package/lib/utils.js +30 -1
  89. package/package.json +5 -4
  90. package/lib/deploy/functions/deploymentPlanner.js +0 -113
  91. package/lib/deploy/functions/deploymentTimer.js +0 -23
  92. package/lib/deploy/functions/errorHandler.js +0 -75
  93. package/lib/deploy/functions/release.js +0 -116
  94. package/lib/deploy/functions/tasks.js +0 -324
  95. package/lib/functionsDelete.js +0 -60
@@ -1,18 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseExtensionVersionName = exports.parseRef = exports.getExtension = exports.deleteExtension = exports.unpublishExtension = exports.publishExtensionVersion = exports.registerPublisherProfile = exports.listExtensionVersions = exports.listExtensions = exports.getExtensionVersion = exports.getSource = exports.createSource = exports.updateInstanceFromRegistry = exports.updateInstance = exports.configureInstance = exports.listInstances = exports.getInstance = exports.deleteInstance = exports.createInstanceFromExtensionVersion = exports.createInstanceFromSource = exports.createInstance = exports.ParamType = exports.Visibility = exports.RegistryLaunchStage = void 0;
4
- const semver = require("semver");
3
+ exports.getExtension = exports.deleteExtension = exports.unpublishExtension = exports.publishExtensionVersion = exports.registerPublisherProfile = exports.listExtensionVersions = exports.listExtensions = exports.getExtensionVersion = exports.getSource = exports.createSource = exports.updateInstanceFromRegistry = exports.updateInstance = exports.configureInstance = exports.listInstances = exports.getInstance = exports.deleteInstance = exports.createInstance = exports.ParamType = exports.Visibility = exports.RegistryLaunchStage = void 0;
5
4
  const yaml = require("js-yaml");
6
5
  const _ = require("lodash");
7
6
  const clc = require("cli-color");
8
7
  const marked = require("marked");
9
8
  const api = require("../api");
9
+ const refs = require("./refs");
10
10
  const logger_1 = require("../logger");
11
11
  const operationPoller = require("../operation-poller");
12
12
  const error_1 = require("../error");
13
13
  const VERSION = "v1beta";
14
14
  const PAGE_SIZE_MAX = 100;
15
- const refRegex = new RegExp(/^([^/@\n]+)\/{1}([^/@\n]+)(@{1}([a-z0-9.-]+)|)$/);
16
15
  var RegistryLaunchStage;
17
16
  (function (RegistryLaunchStage) {
18
17
  RegistryLaunchStage["EXPERIMENTAL"] = "EXPERIMENTAL";
@@ -31,8 +30,9 @@ var ParamType;
31
30
  ParamType["STRING"] = "STRING";
32
31
  ParamType["SELECT"] = "SELECT";
33
32
  ParamType["MULTISELECT"] = "MULTISELECT";
33
+ ParamType["SECRET"] = "SECRET";
34
34
  })(ParamType = exports.ParamType || (exports.ParamType = {}));
35
- async function createInstance(projectId, instanceId, config) {
35
+ async function createInstanceHelper(projectId, instanceId, config) {
36
36
  const createRes = await api.request("POST", `/${VERSION}/projects/${projectId}/instances/`, {
37
37
  auth: true,
38
38
  origin: api.extensionsOrigin,
@@ -49,25 +49,28 @@ async function createInstance(projectId, instanceId, config) {
49
49
  });
50
50
  return pollRes;
51
51
  }
52
- exports.createInstance = createInstance;
53
- async function createInstanceFromSource(projectId, instanceId, extensionSource, params) {
54
- const config = {
55
- source: { name: extensionSource.name },
56
- params,
57
- };
58
- return createInstance(projectId, instanceId, config);
59
- }
60
- exports.createInstanceFromSource = createInstanceFromSource;
61
- async function createInstanceFromExtensionVersion(projectId, instanceId, extensionVersion, params) {
62
- const { publisherId, extensionId, version } = parseRef(extensionVersion.ref);
52
+ async function createInstance(args) {
53
+ var _a, _b;
63
54
  const config = {
64
- extensionRef: `${publisherId}/${extensionId}`,
65
- extensionVersion: version || "",
66
- params,
55
+ params: args.params,
67
56
  };
68
- return createInstance(projectId, instanceId, config);
57
+ if (args.extensionSource && args.extensionVersionRef) {
58
+ throw new error_1.FirebaseError("ExtensionSource and ExtensionVersion both provided, but only one should be.");
59
+ }
60
+ else if (args.extensionSource) {
61
+ config.source = { name: (_a = args.extensionSource) === null || _a === void 0 ? void 0 : _a.name };
62
+ }
63
+ else if (args.extensionVersionRef) {
64
+ const ref = refs.parse(args.extensionVersionRef);
65
+ config.extensionRef = refs.toExtensionRef(ref);
66
+ config.extensionVersion = (_b = ref.version) !== null && _b !== void 0 ? _b : "";
67
+ }
68
+ else {
69
+ throw new error_1.FirebaseError("No ExtensionVersion or ExtensionSource provided but one is required.");
70
+ }
71
+ return createInstanceHelper(args.projectId, args.instanceId, config);
69
72
  }
70
- exports.createInstanceFromExtensionVersion = createInstanceFromExtensionVersion;
73
+ exports.createInstance = createInstance;
71
74
  async function deleteInstance(projectId, instanceId) {
72
75
  const deleteRes = await api.request("DELETE", `/${VERSION}/projects/${projectId}/instances/${instanceId}`, {
73
76
  auth: true,
@@ -129,23 +132,23 @@ async function updateInstance(projectId, instanceId, extensionSource, params) {
129
132
  };
130
133
  let updateMask = "config.source.name";
131
134
  if (params) {
132
- body.params = params;
135
+ body.config.params = params;
133
136
  updateMask += ",config.params";
134
137
  }
135
138
  return await patchInstance(projectId, instanceId, updateMask, body);
136
139
  }
137
140
  exports.updateInstance = updateInstance;
138
141
  async function updateInstanceFromRegistry(projectId, instanceId, extRef, params) {
139
- const { publisherId, extensionId, version } = parseRef(extRef);
142
+ const ref = refs.parse(extRef);
140
143
  const body = {
141
144
  config: {
142
- extensionRef: `${publisherId}/${extensionId}`,
143
- extensionVersion: version,
145
+ extensionRef: refs.toExtensionRef(ref),
146
+ extensionVersion: ref.version,
144
147
  },
145
148
  };
146
149
  let updateMask = "config.extension_ref,config.extension_version";
147
150
  if (params) {
148
- body.params = params;
151
+ body.config.params = params;
149
152
  updateMask += ",config.params";
150
153
  }
151
154
  return await patchInstance(projectId, instanceId, updateMask, body);
@@ -217,13 +220,13 @@ function getSource(sourceName) {
217
220
  });
218
221
  }
219
222
  exports.getSource = getSource;
220
- async function getExtensionVersion(ref) {
221
- const { publisherId, extensionId, version } = parseRef(ref);
222
- if (!version) {
223
- throw new error_1.FirebaseError(`ExtensionVersion ref "${ref}" must supply a version.`);
223
+ async function getExtensionVersion(extensionVersionRef) {
224
+ const ref = refs.parse(extensionVersionRef);
225
+ if (!ref.version) {
226
+ throw new error_1.FirebaseError(`ExtensionVersion ref "${extensionVersionRef}" must supply a version.`);
224
227
  }
225
228
  try {
226
- const res = await api.request("GET", `/${VERSION}/publishers/${publisherId}/extensions/${extensionId}/versions/${version}`, {
229
+ const res = await api.request("GET", `/${VERSION}/${refs.toExtensionVersionName(ref)}`, {
227
230
  auth: true,
228
231
  origin: api.extensionsOrigin,
229
232
  });
@@ -234,12 +237,12 @@ async function getExtensionVersion(ref) {
234
237
  }
235
238
  catch (err) {
236
239
  if (err.status === 404) {
237
- throw refNotFoundError(publisherId, extensionId, version);
240
+ throw refNotFoundError(ref);
238
241
  }
239
242
  else if (err instanceof error_1.FirebaseError) {
240
243
  throw err;
241
244
  }
242
- throw new error_1.FirebaseError(`Failed to query the extension version '${clc.bold(ref)}': ${err}`);
245
+ throw new error_1.FirebaseError(`Failed to query the extension version '${clc.bold(extensionVersionRef)}': ${err}`);
243
246
  }
244
247
  }
245
248
  exports.getExtensionVersion = getExtensionVersion;
@@ -267,7 +270,7 @@ async function listExtensions(publisherId) {
267
270
  }
268
271
  exports.listExtensions = listExtensions;
269
272
  async function listExtensionVersions(ref, filter) {
270
- const { publisherId, extensionId } = parseRef(ref);
273
+ const { publisherId, extensionId } = refs.parse(ref);
271
274
  const extensionVersions = [];
272
275
  const getNextPage = async (pageToken) => {
273
276
  const res = await api.request("GET", `/${VERSION}/publishers/${publisherId}/extensions/${extensionId}/versions`, {
@@ -299,18 +302,18 @@ async function registerPublisherProfile(projectId, publisherId) {
299
302
  return res.body;
300
303
  }
301
304
  exports.registerPublisherProfile = registerPublisherProfile;
302
- async function publishExtensionVersion(ref, packageUri, extensionRoot) {
303
- const { publisherId, extensionId, version } = parseRef(ref);
304
- if (!version) {
305
- throw new error_1.FirebaseError(`ExtensionVersion ref "${ref}" must supply a version.`);
305
+ async function publishExtensionVersion(extensionVersionRef, packageUri, extensionRoot) {
306
+ const ref = refs.parse(extensionVersionRef);
307
+ if (!ref.version) {
308
+ throw new error_1.FirebaseError(`ExtensionVersion ref "${extensionVersionRef}" must supply a version.`);
306
309
  }
307
- const publishRes = await api.request("POST", `/${VERSION}/publishers/${publisherId}/extensions/${extensionId}/versions:publish`, {
310
+ const publishRes = await api.request("POST", `/${VERSION}/${refs.toExtensionName(ref)}/versions:publish`, {
308
311
  auth: true,
309
312
  origin: api.extensionsOrigin,
310
313
  data: {
311
- versionId: version,
314
+ versionId: ref.version,
312
315
  packageUri,
313
- extensionRoot: extensionRoot || "/",
316
+ extensionRoot: extensionRoot !== null && extensionRoot !== void 0 ? extensionRoot : "/",
314
317
  },
315
318
  });
316
319
  const pollRes = await operationPoller.pollOperation({
@@ -322,12 +325,12 @@ async function publishExtensionVersion(ref, packageUri, extensionRoot) {
322
325
  return pollRes;
323
326
  }
324
327
  exports.publishExtensionVersion = publishExtensionVersion;
325
- async function unpublishExtension(ref) {
326
- const { publisherId, extensionId, version } = parseRef(ref);
327
- if (version) {
328
- throw new error_1.FirebaseError(`Extension reference "${ref}" must not contain a version.`);
328
+ async function unpublishExtension(extensionRef) {
329
+ const ref = refs.parse(extensionRef);
330
+ if (ref.version) {
331
+ throw new error_1.FirebaseError(`Extension reference "${extensionRef}" must not contain a version.`);
329
332
  }
330
- const url = `/${VERSION}/publishers/${publisherId}/extensions/${extensionId}:unpublish`;
333
+ const url = `/${VERSION}/${refs.toExtensionName(ref)}:unpublish`;
331
334
  try {
332
335
  await api.request("POST", url, {
333
336
  auth: true,
@@ -336,23 +339,23 @@ async function unpublishExtension(ref) {
336
339
  }
337
340
  catch (err) {
338
341
  if (err.status === 403) {
339
- throw new error_1.FirebaseError(`You are not the owner of extension '${clc.bold(ref)}' and don’t have the correct permissions to unpublish this extension.`, { status: err.status });
342
+ throw new error_1.FirebaseError(`You are not the owner of extension '${clc.bold(extensionRef)}' and don’t have the correct permissions to unpublish this extension.`, { status: err.status });
340
343
  }
341
344
  else if (err instanceof error_1.FirebaseError) {
342
345
  throw err;
343
346
  }
344
- throw new error_1.FirebaseError(`Error occurred unpublishing extension '${ref}': ${err}`, {
347
+ throw new error_1.FirebaseError(`Error occurred unpublishing extension '${extensionRef}': ${err}`, {
345
348
  status: err.status,
346
349
  });
347
350
  }
348
351
  }
349
352
  exports.unpublishExtension = unpublishExtension;
350
- async function deleteExtension(ref) {
351
- const { publisherId, extensionId, version } = parseRef(ref);
352
- if (version) {
353
- throw new error_1.FirebaseError(`Extension reference "${ref}" must not contain a version.`);
353
+ async function deleteExtension(extensionRef) {
354
+ const ref = refs.parse(extensionRef);
355
+ if (ref.version) {
356
+ throw new error_1.FirebaseError(`Extension reference "${extensionRef}" must not contain a version.`);
354
357
  }
355
- const url = `/${VERSION}/publishers/${publisherId}/extensions/${extensionId}`;
358
+ const url = `/${VERSION}/${refs.toExtensionName(ref)}`;
356
359
  try {
357
360
  await api.request("DELETE", url, {
358
361
  auth: true,
@@ -361,24 +364,24 @@ async function deleteExtension(ref) {
361
364
  }
362
365
  catch (err) {
363
366
  if (err.status === 403) {
364
- throw new error_1.FirebaseError(`You are not the owner of extension '${clc.bold(ref)}' and don’t have the correct permissions to delete this extension.`, { status: err.status });
367
+ throw new error_1.FirebaseError(`You are not the owner of extension '${clc.bold(extensionRef)}' and don’t have the correct permissions to delete this extension.`, { status: err.status });
365
368
  }
366
369
  else if (err.status === 404) {
367
- throw new error_1.FirebaseError(`Extension ${clc.bold(ref)} was not found.`);
370
+ throw new error_1.FirebaseError(`Extension ${clc.bold(extensionRef)} was not found.`);
368
371
  }
369
372
  else if (err instanceof error_1.FirebaseError) {
370
373
  throw err;
371
374
  }
372
- throw new error_1.FirebaseError(`Error occurred delete extension '${ref}': ${err}`, {
375
+ throw new error_1.FirebaseError(`Error occurred delete extension '${extensionRef}': ${err}`, {
373
376
  status: err.status,
374
377
  });
375
378
  }
376
379
  }
377
380
  exports.deleteExtension = deleteExtension;
378
- async function getExtension(ref) {
379
- const { publisherId, extensionId } = parseRef(ref);
381
+ async function getExtension(extensionRef) {
382
+ const ref = refs.parse(extensionRef);
380
383
  try {
381
- const res = await api.request("GET", `/${VERSION}/publishers/${publisherId}/extensions/${extensionId}`, {
384
+ const res = await api.request("GET", `/${VERSION}/${refs.toExtensionName(ref)}`, {
382
385
  auth: true,
383
386
  origin: api.extensionsOrigin,
384
387
  });
@@ -386,50 +389,20 @@ async function getExtension(ref) {
386
389
  }
387
390
  catch (err) {
388
391
  if (err.status === 404) {
389
- throw refNotFoundError(publisherId, extensionId);
392
+ throw refNotFoundError(ref);
390
393
  }
391
394
  else if (err instanceof error_1.FirebaseError) {
392
395
  throw err;
393
396
  }
394
- throw new error_1.FirebaseError(`Failed to query the extension '${clc.bold(ref)}': ${err}`, {
397
+ throw new error_1.FirebaseError(`Failed to query the extension '${clc.bold(extensionRef)}': ${err}`, {
395
398
  status: err.status,
396
399
  });
397
400
  }
398
401
  }
399
402
  exports.getExtension = getExtension;
400
- function refNotFoundError(publisherId, extensionId, versionId) {
401
- const versionRef = `${publisherId}/${extensionId}@${versionId}`;
402
- const extensionRef = `${publisherId}/${extensionId}`;
403
- return new error_1.FirebaseError(`The extension reference '${clc.bold(versionId ? versionRef : extensionRef)}' doesn't exist. This could happen for two reasons:\n` +
404
- ` -The publisher ID '${clc.bold(publisherId)}' doesn't exist or could be misspelled\n` +
405
- ` -The name of the ${versionId ? "extension version" : "extension"} '${clc.bold(versionId ? `${extensionId}@${versionId}` : extensionId)}' doesn't exist or could be misspelled\n\n` +
403
+ function refNotFoundError(ref) {
404
+ return new error_1.FirebaseError(`The extension reference '${clc.bold(ref.version ? refs.toExtensionVersionRef(ref) : refs.toExtensionRef(ref))}' doesn't exist. This could happen for two reasons:\n` +
405
+ ` -The publisher ID '${clc.bold(ref.publisherId)}' doesn't exist or could be misspelled\n` +
406
+ ` -The name of the ${ref.version ? "extension version" : "extension"} '${clc.bold(ref.version ? `${ref.extensionId}@${ref.version}` : ref.extensionId)}' doesn't exist or could be misspelled\n\n` +
406
407
  `Please correct the extension reference and try again. If you meant to install an extension from a local source, please provide a relative path prefixed with '${clc.bold("./")}', '${clc.bold("../")}', or '${clc.bold("~/")}'. Learn more about local extension installation at ${marked("[https://firebase.google.com/docs/extensions/alpha/install-extensions_community#install](https://firebase.google.com/docs/extensions/alpha/install-extensions_community#install).")}`, { status: 404 });
407
408
  }
408
- function parseRef(ref) {
409
- const parts = refRegex.exec(ref);
410
- if (parts && (parts.length == 5 || parts.length == 7)) {
411
- const publisherId = parts[1];
412
- const extensionId = parts[2];
413
- const version = parts[4];
414
- if (version && !semver.valid(version) && version !== "latest") {
415
- throw new error_1.FirebaseError(`Extension reference ${ref} contains an invalid version ${version}.`);
416
- }
417
- return { publisherId, extensionId, version };
418
- }
419
- throw new error_1.FirebaseError("Extension reference must be in format '{publisher}/{extension}(@{version})'.");
420
- }
421
- exports.parseRef = parseRef;
422
- function parseExtensionVersionName(extensionVersionName) {
423
- const parts = extensionVersionName.split("/");
424
- if (parts.length !== 6 ||
425
- parts[0] !== "publishers" ||
426
- parts[2] !== "extensions" ||
427
- parts[4] !== "versions") {
428
- throw new error_1.FirebaseError("Extension version name must be in the format `publishers/<publisherID>/extensions/<extensionID>/versions/<versionID>`.");
429
- }
430
- const publisherId = parts[1];
431
- const extensionId = parts[3];
432
- const version = parts[5];
433
- return { publisherId, extensionId, version };
434
- }
435
- exports.parseExtensionVersionName = parseExtensionVersionName;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.confirmInstallInstance = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.confirmExtensionVersion = exports.getExtensionSourceFromName = exports.createSourceFromLocation = exports.publishExtensionVersionFromLocalSource = exports.ensureExtensionsApiEnabled = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
3
+ exports.confirm = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.displayReleaseNotes = exports.getExtensionSourceFromName = exports.createSourceFromLocation = exports.publishExtensionVersionFromLocalSource = exports.ensureExtensionsApiEnabled = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
4
4
  const _ = require("lodash");
5
5
  const clc = require("cli-color");
6
6
  const ora = require("ora");
@@ -21,6 +21,7 @@ const ensureApiEnabled_1 = require("../ensureApiEnabled");
21
21
  const storage_1 = require("../gcp/storage");
22
22
  const projectUtils_1 = require("../projectUtils");
23
23
  const extensionsApi_1 = require("./extensionsApi");
24
+ const refs = require("./refs");
24
25
  const localHelper_1 = require("./localHelper");
25
26
  const prompt_1 = require("../prompt");
26
27
  const logger_1 = require("../logger");
@@ -32,6 +33,7 @@ var SpecParamType;
32
33
  SpecParamType["MULTISELECT"] = "multiSelect";
33
34
  SpecParamType["STRING"] = "string";
34
35
  SpecParamType["SELECTRESOURCE"] = "selectResource";
36
+ SpecParamType["SECRET"] = "secret";
35
37
  })(SpecParamType = exports.SpecParamType || (exports.SpecParamType = {}));
36
38
  var SourceOrigin;
37
39
  (function (SourceOrigin) {
@@ -260,23 +262,23 @@ async function archiveAndUploadSource(extPath, bucketName) {
260
262
  const res = await storage_1.uploadObject(zippedSource, bucketName);
261
263
  return `/${res.bucket}/${res.object}`;
262
264
  }
263
- async function publishExtensionVersionFromLocalSource(publisherId, extensionId, rootDirectory) {
264
- const extensionSpec = await localHelper_1.getLocalExtensionSpec(rootDirectory);
265
- if (extensionSpec.name != extensionId) {
266
- throw new error_1.FirebaseError(`Extension ID '${clc.bold(extensionId)}' does not match the name in extension.yaml '${clc.bold(extensionSpec.name)}'.`);
265
+ async function publishExtensionVersionFromLocalSource(args) {
266
+ const extensionSpec = await localHelper_1.getLocalExtensionSpec(args.rootDirectory);
267
+ if (extensionSpec.name != args.extensionId) {
268
+ throw new error_1.FirebaseError(`Extension ID '${clc.bold(args.extensionId)}' does not match the name in extension.yaml '${clc.bold(extensionSpec.name)}'.`);
267
269
  }
268
270
  const subbedSpec = JSON.parse(JSON.stringify(extensionSpec));
269
271
  subbedSpec.params = substituteParams(extensionSpec.params || [], exports.AUTOPOULATED_PARAM_PLACEHOLDERS);
270
272
  validateSpec(subbedSpec);
271
273
  let extension;
272
274
  try {
273
- extension = await extensionsApi_1.getExtension(`${publisherId}/${extensionId}`);
275
+ extension = await extensionsApi_1.getExtension(`${args.publisherId}/${args.extensionId}`);
274
276
  }
275
277
  catch (err) {
276
278
  }
277
279
  let notes;
278
280
  try {
279
- const changes = changelog_1.getLocalChangelog(rootDirectory);
281
+ const changes = changelog_1.getLocalChangelog(args.rootDirectory);
280
282
  notes = changes[extensionSpec.version];
281
283
  }
282
284
  catch (err) {
@@ -289,27 +291,31 @@ async function publishExtensionVersionFromLocalSource(publisherId, extensionId,
289
291
  "Please add one so users know what has changed in this version. " +
290
292
  marked("See https://firebase.google.com/docs/extensions/alpha/create-user-docs#writing-changelog for more details."));
291
293
  }
292
- const consent = await confirmExtensionVersion(publisherId, extensionId, extensionSpec.version, notes);
293
- if (!consent) {
294
+ displayReleaseNotes(args.publisherId, args.extensionId, extensionSpec.version, notes);
295
+ if (!(await confirm({
296
+ nonInteractive: args.nonInteractive,
297
+ force: args.force,
298
+ default: false,
299
+ }))) {
294
300
  return;
295
301
  }
296
302
  if (extension &&
297
303
  extension.latestVersion &&
298
304
  semver.lt(extensionSpec.version, extension.latestVersion)) {
299
- throw new error_1.FirebaseError(`The version you are trying to publish (${clc.bold(extensionSpec.version)}) is lower than the current version (${clc.bold(extension.latestVersion)}) for the extension '${clc.bold(`${publisherId}/${extensionId}`)}'. Please make sure this version is greater than the current version (${clc.bold(extension.latestVersion)}) inside of extension.yaml.\n`);
305
+ throw new error_1.FirebaseError(`The version you are trying to publish (${clc.bold(extensionSpec.version)}) is lower than the current version (${clc.bold(extension.latestVersion)}) for the extension '${clc.bold(`${args.publisherId}/${args.extensionId}`)}'. Please make sure this version is greater than the current version (${clc.bold(extension.latestVersion)}) inside of extension.yaml.\n`);
300
306
  }
301
307
  else if (extension &&
302
308
  extension.latestVersion &&
303
309
  semver.eq(extensionSpec.version, extension.latestVersion)) {
304
- throw new error_1.FirebaseError(`The version you are trying to publish (${clc.bold(extensionSpec.version)}) already exists for the extension '${clc.bold(`${publisherId}/${extensionId}`)}'. Please increment the version inside of extension.yaml.\n`);
310
+ throw new error_1.FirebaseError(`The version you are trying to publish (${clc.bold(extensionSpec.version)}) already exists for the extension '${clc.bold(`${args.publisherId}/${args.extensionId}`)}'. Please increment the version inside of extension.yaml.\n`, { exit: 103 });
305
311
  }
306
- const ref = `${publisherId}/${extensionId}@${extensionSpec.version}`;
312
+ const ref = `${args.publisherId}/${args.extensionId}@${extensionSpec.version}`;
307
313
  let packageUri;
308
314
  let objectPath = "";
309
315
  const uploadSpinner = ora.default(" Archiving and uploading extension source code");
310
316
  try {
311
317
  uploadSpinner.start();
312
- objectPath = await archiveAndUploadSource(rootDirectory, exports.EXTENSIONS_BUCKET_NAME);
318
+ objectPath = await archiveAndUploadSource(args.rootDirectory, exports.EXTENSIONS_BUCKET_NAME);
313
319
  uploadSpinner.succeed(" Uploaded extension source code");
314
320
  packageUri = api_1.storageOrigin + objectPath + "?alt=media";
315
321
  }
@@ -327,7 +333,7 @@ async function publishExtensionVersionFromLocalSource(publisherId, extensionId,
327
333
  catch (err) {
328
334
  publishSpinner.fail();
329
335
  if (err.status == 404) {
330
- throw new error_1.FirebaseError(marked(`Couldn't find publisher ID '${clc.bold(publisherId)}'. Please ensure that you have registered this ID. To register as a publisher, you can check out the [Firebase documentation](https://firebase.google.com/docs/extensions/alpha/share#register_as_an_extensions_publisher) for step-by-step instructions.`));
336
+ throw new error_1.FirebaseError(marked(`Couldn't find publisher ID '${clc.bold(args.publisherId)}'. Please ensure that you have registered this ID. To register as a publisher, you can check out the [Firebase documentation](https://firebase.google.com/docs/extensions/alpha/share#register_as_an_extensions_publisher) for step-by-step instructions.`));
331
337
  }
332
338
  throw err;
333
339
  }
@@ -389,20 +395,15 @@ async function getExtensionSourceFromName(extensionName) {
389
395
  throw new error_1.FirebaseError(`Could not find an extension named '${extensionName}'. `);
390
396
  }
391
397
  exports.getExtensionSourceFromName = getExtensionSourceFromName;
392
- async function confirmExtensionVersion(publisherId, extensionId, versionId, releaseNotes) {
398
+ function displayReleaseNotes(publisherId, extensionId, versionId, releaseNotes) {
393
399
  const releaseNotesMessage = releaseNotes
394
400
  ? ` Release notes for this version:\n${marked(releaseNotes)}\n`
395
401
  : "\n";
396
402
  const message = `You are about to publish version ${clc.green(versionId)} of ${clc.green(`${publisherId}/${extensionId}`)} to Firebase's registry of extensions.${releaseNotesMessage}` +
397
- "Once an extension version is published, it cannot be changed. If you wish to make changes after publishing, you will need to publish a new version.\n\n" +
398
- "Do you wish to continue?";
399
- return await prompt_1.promptOnce({
400
- type: "confirm",
401
- message,
402
- default: false,
403
- });
403
+ "Once an extension version is published, it cannot be changed. If you wish to make changes after publishing, you will need to publish a new version.\n\n";
404
+ logger_1.logger.info(message);
404
405
  }
405
- exports.confirmExtensionVersion = confirmExtensionVersion;
406
+ exports.displayReleaseNotes = displayReleaseNotes;
406
407
  async function promptForOfficialExtension(message) {
407
408
  const officialExts = await resolveSource_1.getExtensionRegistry(true);
408
409
  return await prompt_1.promptOnce({
@@ -415,11 +416,16 @@ async function promptForOfficialExtension(message) {
415
416
  }
416
417
  exports.promptForOfficialExtension = promptForOfficialExtension;
417
418
  async function promptForRepeatInstance(projectName, extensionName) {
418
- const message = `An extension with the ID '${clc.bold(extensionName)}' already exists in the project '${clc.bold(projectName)}'.\n` +
419
- `Do you want to proceed with installing another instance of extension '${clc.bold(extensionName)}' in this project?`;
419
+ const message = `An extension with the ID '${clc.bold(extensionName)}' already exists in the project '${clc.bold(projectName)}'. What would you like to do?`;
420
+ const choices = [
421
+ { name: "Update or reconfigure the existing instance", value: "updateExisting" },
422
+ { name: "Install a new instance with a different ID", value: "installNew" },
423
+ { name: "Cancel extension installation", value: "cancel" },
424
+ ];
420
425
  return await prompt_1.promptOnce({
421
- type: "confirm",
426
+ type: "list",
422
427
  message,
428
+ choices,
423
429
  });
424
430
  }
425
431
  exports.promptForRepeatInstance = promptForRepeatInstance;
@@ -467,7 +473,7 @@ function getSourceOrigin(sourceOrVersion) {
467
473
  if (sourceOrVersion.includes("/")) {
468
474
  let ref;
469
475
  try {
470
- ref = extensionsApi_1.parseRef(sourceOrVersion);
476
+ ref = refs.parse(sourceOrVersion);
471
477
  }
472
478
  catch (err) {
473
479
  }
@@ -481,12 +487,20 @@ function getSourceOrigin(sourceOrVersion) {
481
487
  throw new error_1.FirebaseError(`Could not find source '${clc.bold(sourceOrVersion)}'. Check to make sure the source is correct, and then please try again.`);
482
488
  }
483
489
  exports.getSourceOrigin = getSourceOrigin;
484
- async function confirmInstallInstance(defaultOption) {
485
- const message = `Would you like to continue installing this extension?`;
486
- return await prompt_1.promptOnce({
487
- type: "confirm",
488
- message,
489
- default: defaultOption,
490
- });
490
+ async function confirm(args) {
491
+ if (!args.nonInteractive && !args.force) {
492
+ const message = `Do you wish to continue?`;
493
+ return await prompt_1.promptOnce({
494
+ type: "confirm",
495
+ message,
496
+ default: args.default,
497
+ });
498
+ }
499
+ else if (args.nonInteractive && !args.force) {
500
+ throw new error_1.FirebaseError("Pass the --force flag to use this command in non-interactive mode");
501
+ }
502
+ else {
503
+ return true;
504
+ }
491
505
  }
492
- exports.confirmInstallInstance = confirmInstallInstance;
506
+ exports.confirm = confirm;