firebase-tools 9.18.0 → 9.22.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 (114) hide show
  1. package/CHANGELOG.md +3 -6
  2. package/lib/api.js +3 -0
  3. package/lib/apiv2.js +8 -5
  4. package/lib/command.js +1 -1
  5. package/lib/commands/crashlytics-symbols-upload.js +146 -0
  6. package/lib/commands/deploy.js +9 -1
  7. package/lib/commands/ext-configure.js +9 -2
  8. package/lib/commands/ext-dev-deprecate.js +63 -0
  9. package/lib/commands/ext-dev-extension-delete.js +2 -1
  10. package/lib/commands/ext-dev-publish.js +10 -4
  11. package/lib/commands/ext-dev-undeprecate.js +56 -0
  12. package/lib/commands/ext-dev-unpublish.js +12 -4
  13. package/lib/commands/ext-export.js +44 -0
  14. package/lib/commands/ext-install.js +50 -13
  15. package/lib/commands/ext-uninstall.js +6 -0
  16. package/lib/commands/ext-update.js +60 -18
  17. package/lib/commands/functions-config-export.js +115 -0
  18. package/lib/commands/functions-delete.js +47 -25
  19. package/lib/commands/functions-list.js +12 -12
  20. package/lib/commands/index.js +9 -0
  21. package/lib/commands/init.js +3 -0
  22. package/lib/config.js +3 -2
  23. package/lib/deploy/extensions/args.js +2 -0
  24. package/lib/deploy/extensions/deploy.js +49 -0
  25. package/lib/deploy/extensions/deploymentSummary.js +52 -0
  26. package/lib/deploy/extensions/errors.js +31 -0
  27. package/lib/deploy/extensions/index.js +8 -0
  28. package/lib/deploy/extensions/planner.js +95 -0
  29. package/lib/deploy/extensions/prepare.js +103 -0
  30. package/lib/deploy/extensions/release.js +43 -0
  31. package/lib/deploy/extensions/secrets.js +150 -0
  32. package/lib/deploy/extensions/tasks.js +98 -0
  33. package/lib/deploy/extensions/validate.js +17 -0
  34. package/lib/deploy/functions/backend.js +93 -115
  35. package/lib/deploy/functions/checkIam.js +8 -8
  36. package/lib/deploy/functions/containerCleaner.js +82 -22
  37. package/lib/deploy/functions/deploy.js +4 -10
  38. package/lib/deploy/functions/functionsDeployHelper.js +3 -68
  39. package/lib/deploy/functions/prepare.js +62 -27
  40. package/lib/deploy/functions/pricing.js +17 -17
  41. package/lib/deploy/functions/prompts.js +22 -21
  42. package/lib/deploy/functions/release/executor.js +39 -0
  43. package/lib/deploy/functions/release/fabricator.js +422 -0
  44. package/lib/deploy/functions/release/index.js +73 -0
  45. package/lib/deploy/functions/release/planner.js +162 -0
  46. package/lib/deploy/functions/release/reporter.js +165 -0
  47. package/lib/deploy/functions/release/sourceTokenScraper.js +28 -0
  48. package/lib/deploy/functions/release/timer.js +14 -0
  49. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +129 -126
  50. package/lib/deploy/functions/runtimes/node/parseTriggers.js +41 -45
  51. package/lib/deploy/functions/triggerRegionHelper.js +40 -0
  52. package/lib/deploy/functions/validate.js +1 -24
  53. package/lib/deploy/index.js +1 -0
  54. package/lib/downloadUtils.js +37 -0
  55. package/lib/emulator/auth/apiSpec.js +1788 -403
  56. package/lib/emulator/auth/handlers.js +6 -5
  57. package/lib/emulator/auth/operations.js +439 -40
  58. package/lib/emulator/auth/server.js +32 -11
  59. package/lib/emulator/auth/state.js +205 -5
  60. package/lib/emulator/auth/widget_ui.js +2 -2
  61. package/lib/emulator/download.js +2 -31
  62. package/lib/emulator/downloadableEmulators.js +7 -7
  63. package/lib/emulator/emulatorLogger.js +0 -3
  64. package/lib/emulator/events/types.js +16 -0
  65. package/lib/emulator/functionsEmulator.js +120 -21
  66. package/lib/emulator/functionsEmulatorRuntime.js +46 -121
  67. package/lib/emulator/functionsEmulatorShared.js +51 -7
  68. package/lib/emulator/functionsEmulatorShell.js +1 -1
  69. package/lib/emulator/pubsubEmulator.js +61 -40
  70. package/lib/emulator/storage/cloudFunctions.js +37 -7
  71. package/lib/extensions/askUserForConsent.js +14 -1
  72. package/lib/extensions/askUserForParam.js +81 -4
  73. package/lib/extensions/billingMigrationHelper.js +1 -11
  74. package/lib/extensions/changelog.js +2 -1
  75. package/lib/extensions/checkProjectBilling.js +7 -7
  76. package/lib/extensions/displayExtensionInfo.js +35 -33
  77. package/lib/extensions/emulator/optionsHelper.js +3 -3
  78. package/lib/extensions/emulator/triggerHelper.js +2 -32
  79. package/lib/extensions/export.js +107 -0
  80. package/lib/extensions/extensionsApi.js +149 -97
  81. package/lib/extensions/extensionsHelper.js +36 -32
  82. package/lib/extensions/listExtensions.js +16 -11
  83. package/lib/extensions/paramHelper.js +73 -40
  84. package/lib/extensions/provisioningHelper.js +16 -3
  85. package/lib/extensions/refs.js +67 -0
  86. package/lib/extensions/secretsUtils.js +59 -0
  87. package/lib/extensions/updateHelper.js +33 -47
  88. package/lib/extensions/versionHelper.js +14 -0
  89. package/lib/extensions/warnings.js +33 -1
  90. package/lib/functional.js +64 -0
  91. package/lib/functions/env.js +26 -13
  92. package/lib/functions/runtimeConfigExport.js +137 -0
  93. package/lib/gcp/artifactregistry.js +16 -0
  94. package/lib/gcp/cloudfunctions.js +65 -35
  95. package/lib/gcp/cloudfunctionsv2.js +56 -43
  96. package/lib/gcp/cloudscheduler.js +22 -16
  97. package/lib/gcp/cloudtasks.js +143 -0
  98. package/lib/gcp/docker.js +7 -1
  99. package/lib/gcp/proto.js +2 -2
  100. package/lib/gcp/pubsub.js +1 -9
  101. package/lib/gcp/secretManager.js +132 -0
  102. package/lib/gcp/storage.js +16 -0
  103. package/lib/previews.js +1 -1
  104. package/lib/requireInteractive.js +12 -0
  105. package/lib/utils.js +30 -1
  106. package/package.json +6 -4
  107. package/schema/firebase-config.json +9 -0
  108. package/lib/deploy/functions/deploymentPlanner.js +0 -113
  109. package/lib/deploy/functions/deploymentTimer.js +0 -23
  110. package/lib/deploy/functions/errorHandler.js +0 -75
  111. package/lib/deploy/functions/release.js +0 -116
  112. package/lib/deploy/functions/tasks.js +0 -324
  113. package/lib/functions/listFunctions.js +0 -10
  114. package/lib/functionsDelete.js +0 -60
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.confirmUpdate = exports.inferUpdateSource = exports.updateFromPublisherSource = exports.updateToVersionFromPublisherSource = exports.updateFromUrlSource = exports.updateFromLocalSource = exports.update = exports.retryUpdate = exports.displayChanges = exports.warningUpdateToOtherSource = exports.getExistingSourceOrigin = void 0;
3
+ exports.inferUpdateSource = exports.updateFromPublisherSource = exports.updateToVersionFromPublisherSource = exports.updateFromUrlSource = exports.updateFromLocalSource = exports.update = exports.displayChanges = exports.warningUpdateToOtherSource = exports.getExistingSourceOrigin = void 0;
4
4
  const clc = require("cli-color");
5
5
  const semver = require("semver");
6
+ const marked = require("marked");
6
7
  const error_1 = require("../error");
7
8
  const logger_1 = require("../logger");
8
9
  const resolveSource = require("./resolveSource");
9
10
  const extensionsApi = require("./extensionsApi");
10
- const prompt_1 = require("../prompt");
11
- const marked = require("marked");
11
+ const refs = require("./refs");
12
12
  const extensionsHelper_1 = require("./extensionsHelper");
13
13
  const utils = require("../utils");
14
14
  const displayExtensionInfo_1 = require("./displayExtensionInfo");
@@ -25,7 +25,7 @@ async function getExistingSourceOrigin(projectId, instanceId, extensionName, exi
25
25
  : extensionsHelper_1.SourceOrigin.LOCAL;
26
26
  }
27
27
  exports.getExistingSourceOrigin = getExistingSourceOrigin;
28
- async function showUpdateVersionInfo(instanceId, from, to, source) {
28
+ function showUpdateVersionInfo(instanceId, from, to, source) {
29
29
  if (source) {
30
30
  source = clc.bold(source);
31
31
  }
@@ -34,8 +34,7 @@ async function showUpdateVersionInfo(instanceId, from, to, source) {
34
34
  }
35
35
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `Updating ${clc.bold(instanceId)} from version ${clc.bold(from)} to ${source} (${clc.bold(to)})`);
36
36
  if (semver.lt(to, from)) {
37
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, "The version you are updating to is less than the current version for this extension. This extension may not be backwards compatible.");
38
- return await displayExtensionInfo_1.getConsent("version", "Do you wish to continue?");
37
+ utils.logLabeledWarning(extensionsHelper_1.logPrefix, "The version you are updating to is less than the current version for this extension. This extension may not be backwards compatible.");
39
38
  }
40
39
  return;
41
40
  }
@@ -54,33 +53,34 @@ function warningUpdateToOtherSource(sourceOrigin) {
54
53
  logger_1.logger.info(marked(warning));
55
54
  }
56
55
  exports.warningUpdateToOtherSource = warningUpdateToOtherSource;
57
- async function displayChanges(spec, newSpec) {
58
- logger_1.logger.info("This update contains the following changes (in green and red). " +
59
- "If at any point you choose not to continue, the extension will not be updated and the changes will be discarded:\n");
60
- displayExtensionInfo_1.displayUpdateChangesNoInput(spec, newSpec);
61
- await displayExtensionInfo_1.displayUpdateChangesRequiringConfirmation(spec, newSpec);
56
+ async function displayChanges(args) {
57
+ utils.logLabeledBullet("extensions", "This update contains the following changes:");
58
+ displayExtensionInfo_1.displayUpdateChangesNoInput(args.spec, args.newSpec);
59
+ await displayExtensionInfo_1.displayUpdateChangesRequiringConfirmation(args);
62
60
  }
63
61
  exports.displayChanges = displayChanges;
64
- async function retryUpdate() {
65
- return prompt_1.promptOnce({
66
- type: "confirm",
67
- message: "Are you sure you wish to continue with updating anyways?",
68
- default: false,
69
- });
70
- }
71
- exports.retryUpdate = retryUpdate;
72
62
  async function update(updateOptions) {
73
63
  const { projectId, instanceId, source, extRef, params } = updateOptions;
74
64
  if (extRef) {
75
- return await extensionsApi.updateInstanceFromRegistry(projectId, instanceId, extRef, params);
65
+ return await extensionsApi.updateInstanceFromRegistry({
66
+ projectId,
67
+ instanceId,
68
+ extRef,
69
+ params,
70
+ });
76
71
  }
77
72
  else if (source) {
78
- return await extensionsApi.updateInstance(projectId, instanceId, source, params);
73
+ return await extensionsApi.updateInstance({
74
+ projectId,
75
+ instanceId,
76
+ extensionSource: source,
77
+ params,
78
+ });
79
79
  }
80
80
  throw new error_1.FirebaseError(`Neither a source nor a version of the extension was supplied for ${instanceId}. Please make sure this is a valid extension and try again.`);
81
81
  }
82
82
  exports.update = update;
83
- async function updateFromLocalSource(projectId, instanceId, localSource, existingSpec, existingSource) {
83
+ async function updateFromLocalSource(projectId, instanceId, localSource, existingSpec) {
84
84
  displayExtensionInfo_1.displayExtInfo(instanceId, "", existingSpec, false);
85
85
  let source;
86
86
  try {
@@ -90,13 +90,12 @@ async function updateFromLocalSource(projectId, instanceId, localSource, existin
90
90
  throw new error_1.FirebaseError(invalidSourceErrMsgTemplate(instanceId, localSource));
91
91
  }
92
92
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `${clc.bold("You are updating this extension instance to a local source.")}`);
93
- await showUpdateVersionInfo(instanceId, existingSpec.version, source.spec.version, localSource);
93
+ showUpdateVersionInfo(instanceId, existingSpec.version, source.spec.version, localSource);
94
94
  warningUpdateToOtherSource(extensionsHelper_1.SourceOrigin.LOCAL);
95
- await confirmUpdate();
96
95
  return source.name;
97
96
  }
98
97
  exports.updateFromLocalSource = updateFromLocalSource;
99
- async function updateFromUrlSource(projectId, instanceId, urlSource, existingSpec, existingSource) {
98
+ async function updateFromUrlSource(projectId, instanceId, urlSource, existingSpec) {
100
99
  displayExtensionInfo_1.displayExtInfo(instanceId, "", existingSpec, false);
101
100
  let source;
102
101
  try {
@@ -106,18 +105,17 @@ async function updateFromUrlSource(projectId, instanceId, urlSource, existingSpe
106
105
  throw new error_1.FirebaseError(invalidSourceErrMsgTemplate(instanceId, urlSource));
107
106
  }
108
107
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `${clc.bold("You are updating this extension instance to a URL source.")}`);
109
- await showUpdateVersionInfo(instanceId, existingSpec.version, source.spec.version, urlSource);
108
+ showUpdateVersionInfo(instanceId, existingSpec.version, source.spec.version, urlSource);
110
109
  warningUpdateToOtherSource(extensionsHelper_1.SourceOrigin.URL);
111
- await confirmUpdate();
112
110
  return source.name;
113
111
  }
114
112
  exports.updateFromUrlSource = updateFromUrlSource;
115
- async function updateToVersionFromPublisherSource(projectId, instanceId, extVersionRef, existingSpec, existingSource) {
113
+ async function updateToVersionFromPublisherSource(projectId, instanceId, extVersionRef, existingSpec) {
116
114
  let source;
117
- const refObj = extensionsApi.parseRef(extVersionRef);
118
- const version = refObj.version;
119
- const extensionRef = `${refObj.publisherId}/${refObj.extensionId}`;
120
- displayExtensionInfo_1.displayExtInfo(instanceId, refObj.publisherId, existingSpec, true);
115
+ const ref = refs.parse(extVersionRef);
116
+ const version = ref.version;
117
+ const extensionRef = refs.toExtensionRef(ref);
118
+ displayExtensionInfo_1.displayExtInfo(instanceId, ref.publisherId, existingSpec, true);
121
119
  const extension = await extensionsApi.getExtension(extensionRef);
122
120
  try {
123
121
  source = await extensionsApi.getExtensionVersion(extVersionRef);
@@ -138,7 +136,7 @@ async function updateToVersionFromPublisherSource(projectId, instanceId, extVers
138
136
  throw new error_1.FirebaseError(`The version you are trying to update to (${clc.bold(source.spec.version)}) is less than the minimum version required (${clc.bold(minVer)}) to use this extension.`);
139
137
  }
140
138
  }
141
- await showUpdateVersionInfo(instanceId, existingSpec.version, source.spec.version, extVersionRef);
139
+ showUpdateVersionInfo(instanceId, existingSpec.version, source.spec.version, extVersionRef);
142
140
  warningUpdateToOtherSource(extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION);
143
141
  const releaseNotes = await changelog.getReleaseNotesForUpdate({
144
142
  extensionRef,
@@ -148,12 +146,11 @@ async function updateToVersionFromPublisherSource(projectId, instanceId, extVers
148
146
  if (Object.keys(releaseNotes).length) {
149
147
  changelog.displayReleaseNotes(releaseNotes, existingSpec.version);
150
148
  }
151
- await confirmUpdate();
152
149
  return source.name;
153
150
  }
154
151
  exports.updateToVersionFromPublisherSource = updateToVersionFromPublisherSource;
155
- async function updateFromPublisherSource(projectId, instanceId, extRef, existingSpec, existingSource) {
156
- return updateToVersionFromPublisherSource(projectId, instanceId, `${extRef}@latest`, existingSpec, existingSource);
152
+ async function updateFromPublisherSource(projectId, instanceId, extRef, existingSpec) {
153
+ return updateToVersionFromPublisherSource(projectId, instanceId, `${extRef}@latest`, existingSpec);
157
154
  }
158
155
  exports.updateFromPublisherSource = updateFromPublisherSource;
159
156
  function inferUpdateSource(updateSource, existingRef) {
@@ -174,14 +171,3 @@ function inferUpdateSource(updateSource, existingRef) {
174
171
  return updateSource;
175
172
  }
176
173
  exports.inferUpdateSource = inferUpdateSource;
177
- async function confirmUpdate() {
178
- const continueUpdate = await prompt_1.promptOnce({
179
- type: "confirm",
180
- message: "Do you wish to continue with this update?",
181
- default: false,
182
- });
183
- if (!continueUpdate) {
184
- throw new error_1.FirebaseError(`Update cancelled.`);
185
- }
186
- }
187
- exports.confirmUpdate = confirmUpdate;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseVersionPredicate = void 0;
4
+ const error_1 = require("../error");
5
+ function parseVersionPredicate(versionPredicate) {
6
+ const versionPredicateRegex = "^(?<comparator>>=|<=|>|<)?(?<targetSemVer>.*)";
7
+ const matches = versionPredicate.match(versionPredicateRegex);
8
+ if (!matches || !matches.groups.targetSemVer) {
9
+ throw new error_1.FirebaseError("Invalid version predicate.");
10
+ }
11
+ const comparator = matches.groups.comparator || "=";
12
+ return { comparator, targetSemVer: matches.groups.targetSemVer };
13
+ }
14
+ exports.parseVersionPredicate = parseVersionPredicate;
@@ -1,12 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.displayWarningPrompts = void 0;
3
+ exports.displayWarningsForDeploy = exports.displayWarningPrompts = void 0;
4
4
  const marked = require("marked");
5
5
  const clc = require("cli-color");
6
6
  const extensionsApi_1 = require("./extensionsApi");
7
7
  const displayExtensionInfo_1 = require("./displayExtensionInfo");
8
8
  const extensionsHelper_1 = require("./extensionsHelper");
9
9
  const resolveSource_1 = require("./resolveSource");
10
+ const deploymentSummary_1 = require("../deploy/extensions/deploymentSummary");
11
+ const planner_1 = require("../deploy/extensions/planner");
12
+ const functional_1 = require("../functional");
10
13
  const utils = require("../utils");
11
14
  function displayEAPWarning({ publisherId, sourceDownloadUri, githubLink, }) {
12
15
  const publisherNameLink = githubLink ? `[${publisherId}](${githubLink})` : publisherId;
@@ -35,3 +38,32 @@ async function displayWarningPrompts(publisherId, launchStage, extensionVersion)
35
38
  }
36
39
  }
37
40
  exports.displayWarningPrompts = displayWarningPrompts;
41
+ const toListEntry = (i) => {
42
+ var _a, _b, _c, _d;
43
+ const idAndRef = deploymentSummary_1.humanReadable(i);
44
+ const sourceCodeLink = `\n\t[Source Code](${(_a = i.extensionVersion) === null || _a === void 0 ? void 0 : _a.sourceDownloadUri})`;
45
+ const githubLink = ((_c = (_b = i.extensionVersion) === null || _b === void 0 ? void 0 : _b.spec) === null || _c === void 0 ? void 0 : _c.sourceUrl) ? `\n\t[Publisher Contact](${(_d = i.extensionVersion) === null || _d === void 0 ? void 0 : _d.spec.sourceUrl})`
46
+ : "";
47
+ return `${idAndRef}${sourceCodeLink}${githubLink}`;
48
+ };
49
+ async function displayWarningsForDeploy(instancesToCreate) {
50
+ const trustedPublishers = await resolveSource_1.getTrustedPublishers();
51
+ for (const i of instancesToCreate) {
52
+ await planner_1.getExtension(i);
53
+ await planner_1.getExtensionVersion(i);
54
+ }
55
+ const [eapExtensions, nonEapExtensions] = functional_1.partition(instancesToCreate, (i) => { var _a, _b; return !trustedPublishers.includes((_b = (_a = i.ref) === null || _a === void 0 ? void 0 : _a.publisherId) !== null && _b !== void 0 ? _b : ""); });
56
+ const experimental = nonEapExtensions.filter((i) => i.extension.registryLaunchStage === extensionsApi_1.RegistryLaunchStage.EXPERIMENTAL);
57
+ if (experimental.length) {
58
+ const humanReadableList = experimental.map((i) => `\t${deploymentSummary_1.humanReadable(i)}`).join("\n");
59
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`The following are instances of ${clc.bold("experimental")} extensions.They may not be production-ready. Their functionality may change in backward-incompatible ways before their official release, or they may be discontinued.\n${humanReadableList}\n`));
60
+ }
61
+ if (eapExtensions.length) {
62
+ const humanReadableList = eapExtensions.map(toListEntry).join("\n");
63
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`These extensions are in preview and are built by a developer in the Extensions Publisher Early Access Program (http://bit.ly/firex-provider. Their functionality might change in backwards-incompatible ways. Since these extensions aren't built by Firebase, reach out to their publisher with questions about them.` +
64
+ ` They are provided “AS IS”, without any warranty, express or implied, from Google.` +
65
+ ` Google disclaims all liability for any damages, direct or indirect, resulting from the use of these extensions\n${humanReadableList}`));
66
+ }
67
+ return experimental.length > 0 || eapExtensions.length > 0;
68
+ }
69
+ exports.displayWarningsForDeploy = displayWarningsForDeploy;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.partition = exports.assertExhaustive = exports.zipIn = exports.zip = exports.reduceFlat = exports.flatten = exports.flattenArray = exports.flattenObject = void 0;
4
+ function* flattenObject(obj) {
5
+ function* helper(path, obj) {
6
+ for (const [k, v] of Object.entries(obj)) {
7
+ if (typeof v !== "object" || v === null) {
8
+ yield [[...path, k].join("."), v];
9
+ }
10
+ else {
11
+ yield* helper([...path, k], v);
12
+ }
13
+ }
14
+ }
15
+ yield* helper([], obj);
16
+ }
17
+ exports.flattenObject = flattenObject;
18
+ function* flattenArray(arr) {
19
+ for (const val of arr) {
20
+ if (Array.isArray(val)) {
21
+ yield* flattenArray(val);
22
+ }
23
+ else {
24
+ yield val;
25
+ }
26
+ }
27
+ }
28
+ exports.flattenArray = flattenArray;
29
+ function flatten(objOrArr) {
30
+ if (Array.isArray(objOrArr)) {
31
+ return flattenArray(objOrArr);
32
+ }
33
+ else {
34
+ return flattenObject(objOrArr);
35
+ }
36
+ }
37
+ exports.flatten = flatten;
38
+ function reduceFlat(accum, next) {
39
+ return [...(accum || []), ...flatten([next])];
40
+ }
41
+ exports.reduceFlat = reduceFlat;
42
+ function* zip(left, right) {
43
+ if (left.length != right.length) {
44
+ throw new Error("Cannot zip between two lists of differen lengths");
45
+ }
46
+ for (let i = 0; i < left.length; i++) {
47
+ yield [left[i], right[i]];
48
+ }
49
+ }
50
+ exports.zip = zip;
51
+ exports.zipIn = (other) => (elem, ndx) => {
52
+ return [elem, other[ndx]];
53
+ };
54
+ function assertExhaustive(val) {
55
+ throw new Error(`Never has a value (${val}). This should be impossible`);
56
+ }
57
+ exports.assertExhaustive = assertExhaustive;
58
+ function partition(arr, callbackFn) {
59
+ return arr.reduce((acc, elem) => {
60
+ acc[callbackFn(elem) ? 0 : 1].push(elem);
61
+ return acc;
62
+ }, [[], []]);
63
+ }
64
+ exports.partition = partition;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadFirebaseEnvs = exports.loadUserEnvs = exports.hasUserEnvs = exports.validateKey = exports.parse = void 0;
3
+ exports.loadFirebaseEnvs = exports.loadUserEnvs = exports.hasUserEnvs = exports.validateKey = exports.KeyValidationError = exports.parse = void 0;
4
4
  const clc = require("cli-color");
5
5
  const fs = require("fs");
6
6
  const path = require("path");
@@ -8,6 +8,7 @@ const error_1 = require("../error");
8
8
  const logger_1 = require("../logger");
9
9
  const previews_1 = require("../previews");
10
10
  const utils_1 = require("../utils");
11
+ const FUNCTIONS_EMULATOR_DOTENV = ".env.local";
11
12
  const RESERVED_KEYS = [
12
13
  "FIREBASE_CONFIG",
13
14
  "CLOUD_RUNTIME_CONFIG",
@@ -35,7 +36,7 @@ const LINE_RE = new RegExp("^" +
35
36
  "(" +
36
37
  "\\s*'(?:\\\\'|[^'])*'|" +
37
38
  '\\s*"(?:\\\\"|[^"])*"|' +
38
- "[^\\#\\r\\n]+" +
39
+ "[^#\\r\\n]+" +
39
40
  ")?" +
40
41
  "\\s*" +
41
42
  "(?:#[^\\n]*)?" +
@@ -71,17 +72,23 @@ function parse(data) {
71
72
  }
72
73
  exports.parse = parse;
73
74
  class KeyValidationError extends Error {
75
+ constructor(key, message) {
76
+ super(`Failed to validate key ${key}: ${message}`);
77
+ this.key = key;
78
+ this.message = message;
79
+ }
74
80
  }
81
+ exports.KeyValidationError = KeyValidationError;
75
82
  function validateKey(key) {
76
83
  if (RESERVED_KEYS.includes(key)) {
77
- throw new KeyValidationError(`Key ${key} is reserved for internal use.`);
84
+ throw new KeyValidationError(key, `Key ${key} is reserved for internal use.`);
78
85
  }
79
86
  if (!/^[A-Z_][A-Z0-9_]*$/.test(key)) {
80
- throw new KeyValidationError(`Key ${key} must start with an uppercase ASCII letter or underscore` +
87
+ throw new KeyValidationError(key, `Key ${key} must start with an uppercase ASCII letter or underscore` +
81
88
  ", and then consist of uppercase ASCII letters, digits, and underscores.");
82
89
  }
83
90
  if (key.startsWith("X_GOOGLE_") || key.startsWith("FIREBASE_")) {
84
- throw new KeyValidationError(`Key ${key} starts with a reserved prefix (X_GOOGLE_ or FIREBASE_)`);
91
+ throw new KeyValidationError(key, `Key ${key} starts with a reserved prefix (X_GOOGLE_ or FIREBASE_)`);
85
92
  }
86
93
  }
87
94
  exports.validateKey = validateKey;
@@ -110,26 +117,32 @@ function parseStrict(data) {
110
117
  }
111
118
  return envs;
112
119
  }
113
- function findEnvfiles(functionsSource, projectId, projectAlias) {
114
- const files = [".env", `.env.${projectId}`];
115
- if (projectAlias && projectAlias.length) {
116
- files.push(`.env.${projectAlias}`);
120
+ function findEnvfiles(functionsSource, projectId, projectAlias, isEmulator) {
121
+ const files = [".env"];
122
+ if (isEmulator) {
123
+ files.push(FUNCTIONS_EMULATOR_DOTENV);
124
+ }
125
+ else {
126
+ files.push(`.env.${projectId}`);
127
+ if (projectAlias && projectAlias.length) {
128
+ files.push(`.env.${projectAlias}`);
129
+ }
117
130
  }
118
131
  return files
119
132
  .map((f) => path.join(functionsSource, f))
120
133
  .filter(fs.existsSync)
121
134
  .map((p) => path.basename(p));
122
135
  }
123
- function hasUserEnvs({ functionsSource, projectId, projectAlias }) {
124
- return findEnvfiles(functionsSource, projectId, projectAlias).length > 0;
136
+ function hasUserEnvs({ functionsSource, projectId, projectAlias, isEmulator, }) {
137
+ return findEnvfiles(functionsSource, projectId, projectAlias, isEmulator).length > 0;
125
138
  }
126
139
  exports.hasUserEnvs = hasUserEnvs;
127
- function loadUserEnvs({ functionsSource, projectId, projectAlias, }) {
140
+ function loadUserEnvs({ functionsSource, projectId, projectAlias, isEmulator, }) {
128
141
  var _a;
129
142
  if (!previews_1.previews.dotenv) {
130
143
  return {};
131
144
  }
132
- const envFiles = findEnvfiles(functionsSource, projectId, projectAlias);
145
+ const envFiles = findEnvfiles(functionsSource, projectId, projectAlias, isEmulator);
133
146
  if (envFiles.length == 0) {
134
147
  return {};
135
148
  }
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateDotenvFilename = exports.toDotenvFormat = exports.hydrateEnvs = exports.configToEnv = exports.convertKey = exports.hydrateConfigs = exports.getProjectInfos = void 0;
4
+ const clc = require("cli-color");
5
+ const env = require("./env");
6
+ const functionsConfig = require("../functionsConfig");
7
+ const error_1 = require("../error");
8
+ const logger_1 = require("../logger");
9
+ const projectUtils_1 = require("../projectUtils");
10
+ const rc_1 = require("../rc");
11
+ const utils_1 = require("../utils");
12
+ const functional_1 = require("../functional");
13
+ function getProjectInfos(options) {
14
+ const result = {};
15
+ const rc = rc_1.loadRC(options);
16
+ if (rc.projects) {
17
+ for (const [alias, projectId] of Object.entries(rc.projects)) {
18
+ if (Object.keys(result).includes(projectId)) {
19
+ utils_1.logWarning(`Multiple aliases found for ${clc.bold(projectId)}. ` +
20
+ `Preferring alias (${clc.bold(result[projectId])}) over (${clc.bold(alias)}).`);
21
+ continue;
22
+ }
23
+ result[projectId] = alias;
24
+ }
25
+ }
26
+ const projectId = projectUtils_1.getProjectId(options);
27
+ if (projectId && !Object.keys(result).includes(projectId)) {
28
+ result[projectId] = projectId;
29
+ }
30
+ return Object.entries(result).map(([k, v]) => {
31
+ const result = { projectId: k };
32
+ if (k !== v) {
33
+ result.alias = v;
34
+ }
35
+ return result;
36
+ });
37
+ }
38
+ exports.getProjectInfos = getProjectInfos;
39
+ async function hydrateConfigs(pInfos) {
40
+ const hydrate = pInfos.map((info) => {
41
+ return functionsConfig
42
+ .materializeAll(info.projectId)
43
+ .then((config) => {
44
+ info.config = config;
45
+ return;
46
+ })
47
+ .catch((err) => {
48
+ logger_1.logger.debug(`Failed to fetch runtime config for project ${info.projectId}: ${err.message}`);
49
+ });
50
+ });
51
+ await Promise.all(hydrate);
52
+ }
53
+ exports.hydrateConfigs = hydrateConfigs;
54
+ function convertKey(configKey, prefix) {
55
+ const baseKey = configKey
56
+ .toUpperCase()
57
+ .replace(/\./g, "_")
58
+ .replace(/-/g, "_");
59
+ let envKey = baseKey;
60
+ try {
61
+ env.validateKey(envKey);
62
+ }
63
+ catch (err) {
64
+ if (err instanceof env.KeyValidationError) {
65
+ envKey = prefix + envKey;
66
+ env.validateKey(envKey);
67
+ }
68
+ }
69
+ return envKey;
70
+ }
71
+ exports.convertKey = convertKey;
72
+ function configToEnv(configs, prefix) {
73
+ const success = [];
74
+ const errors = [];
75
+ for (const [configKey, value] of functional_1.flatten(configs)) {
76
+ try {
77
+ const envKey = convertKey(configKey, prefix);
78
+ success.push({ origKey: configKey, newKey: envKey, value: value });
79
+ }
80
+ catch (err) {
81
+ if (err instanceof env.KeyValidationError) {
82
+ errors.push({
83
+ origKey: configKey,
84
+ newKey: err.key,
85
+ err: err.message,
86
+ value: value,
87
+ });
88
+ }
89
+ else {
90
+ throw new error_1.FirebaseError("Unexpected error while converting config", {
91
+ exit: 2,
92
+ original: err,
93
+ });
94
+ }
95
+ }
96
+ }
97
+ return { success, errors };
98
+ }
99
+ exports.configToEnv = configToEnv;
100
+ function hydrateEnvs(pInfos, prefix) {
101
+ let errMsg = "";
102
+ for (const pInfo of pInfos) {
103
+ const { success, errors } = configToEnv(pInfo.config, prefix);
104
+ if (errors.length > 0) {
105
+ const msg = `${pInfo.projectId} ` +
106
+ `${pInfo.alias ? "(" + pInfo.alias + ")" : ""}:\n` +
107
+ errors.map((err) => `\t${err.origKey} => ${clc.bold(err.newKey)} (${err.err})`).join("\n") +
108
+ "\n";
109
+ errMsg += msg;
110
+ }
111
+ else {
112
+ pInfo.envs = success;
113
+ }
114
+ }
115
+ return errMsg;
116
+ }
117
+ exports.hydrateEnvs = hydrateEnvs;
118
+ function escape(s) {
119
+ const result = s
120
+ .replace("\n", "\\n")
121
+ .replace("\r", "\\r")
122
+ .replace("\t", "\\t")
123
+ .replace("\v", "\\v");
124
+ return result.replace(/(['"])/g, "\\$1");
125
+ }
126
+ function toDotenvFormat(envs, header = "") {
127
+ const lines = envs.map(({ newKey, value }) => `${newKey}="${escape(value)}"`);
128
+ const maxLineLen = Math.max(...lines.map((l) => l.length));
129
+ return (`${header}\n` +
130
+ lines.map((line, idx) => `${line.padEnd(maxLineLen)} # from ${envs[idx].origKey}`).join("\n"));
131
+ }
132
+ exports.toDotenvFormat = toDotenvFormat;
133
+ function generateDotenvFilename(pInfo) {
134
+ var _a;
135
+ return `.env.${(_a = pInfo.alias) !== null && _a !== void 0 ? _a : pInfo.projectId}`;
136
+ }
137
+ exports.generateDotenvFilename = generateDotenvFilename;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deletePackage = exports.API_VERSION = void 0;
4
+ const apiv2_1 = require("../apiv2");
5
+ const api_1 = require("../api");
6
+ exports.API_VERSION = "v1beta2";
7
+ const client = new apiv2_1.Client({
8
+ urlPrefix: api_1.artifactRegistryDomain,
9
+ auth: true,
10
+ apiVersion: exports.API_VERSION,
11
+ });
12
+ async function deletePackage(name) {
13
+ const res = await client.delete(name);
14
+ return res.body;
15
+ }
16
+ exports.deletePackage = deletePackage;