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.
- package/CHANGELOG.md +3 -6
- package/lib/api.js +3 -0
- package/lib/apiv2.js +8 -5
- package/lib/command.js +1 -1
- package/lib/commands/crashlytics-symbols-upload.js +146 -0
- package/lib/commands/deploy.js +9 -1
- package/lib/commands/ext-configure.js +9 -2
- package/lib/commands/ext-dev-deprecate.js +63 -0
- package/lib/commands/ext-dev-extension-delete.js +2 -1
- package/lib/commands/ext-dev-publish.js +10 -4
- package/lib/commands/ext-dev-undeprecate.js +56 -0
- package/lib/commands/ext-dev-unpublish.js +12 -4
- package/lib/commands/ext-export.js +44 -0
- package/lib/commands/ext-install.js +50 -13
- package/lib/commands/ext-uninstall.js +6 -0
- package/lib/commands/ext-update.js +60 -18
- package/lib/commands/functions-config-export.js +115 -0
- package/lib/commands/functions-delete.js +47 -25
- package/lib/commands/functions-list.js +12 -12
- package/lib/commands/index.js +9 -0
- package/lib/commands/init.js +3 -0
- package/lib/config.js +3 -2
- package/lib/deploy/extensions/args.js +2 -0
- package/lib/deploy/extensions/deploy.js +49 -0
- package/lib/deploy/extensions/deploymentSummary.js +52 -0
- package/lib/deploy/extensions/errors.js +31 -0
- package/lib/deploy/extensions/index.js +8 -0
- package/lib/deploy/extensions/planner.js +95 -0
- package/lib/deploy/extensions/prepare.js +103 -0
- package/lib/deploy/extensions/release.js +43 -0
- package/lib/deploy/extensions/secrets.js +150 -0
- package/lib/deploy/extensions/tasks.js +98 -0
- package/lib/deploy/extensions/validate.js +17 -0
- package/lib/deploy/functions/backend.js +93 -115
- package/lib/deploy/functions/checkIam.js +8 -8
- package/lib/deploy/functions/containerCleaner.js +82 -22
- package/lib/deploy/functions/deploy.js +4 -10
- package/lib/deploy/functions/functionsDeployHelper.js +3 -68
- package/lib/deploy/functions/prepare.js +62 -27
- package/lib/deploy/functions/pricing.js +17 -17
- package/lib/deploy/functions/prompts.js +22 -21
- package/lib/deploy/functions/release/executor.js +39 -0
- package/lib/deploy/functions/release/fabricator.js +422 -0
- package/lib/deploy/functions/release/index.js +73 -0
- package/lib/deploy/functions/release/planner.js +162 -0
- package/lib/deploy/functions/release/reporter.js +165 -0
- package/lib/deploy/functions/release/sourceTokenScraper.js +28 -0
- package/lib/deploy/functions/release/timer.js +14 -0
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +129 -126
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +41 -45
- package/lib/deploy/functions/triggerRegionHelper.js +40 -0
- package/lib/deploy/functions/validate.js +1 -24
- package/lib/deploy/index.js +1 -0
- package/lib/downloadUtils.js +37 -0
- package/lib/emulator/auth/apiSpec.js +1788 -403
- package/lib/emulator/auth/handlers.js +6 -5
- package/lib/emulator/auth/operations.js +439 -40
- package/lib/emulator/auth/server.js +32 -11
- package/lib/emulator/auth/state.js +205 -5
- package/lib/emulator/auth/widget_ui.js +2 -2
- package/lib/emulator/download.js +2 -31
- package/lib/emulator/downloadableEmulators.js +7 -7
- package/lib/emulator/emulatorLogger.js +0 -3
- package/lib/emulator/events/types.js +16 -0
- package/lib/emulator/functionsEmulator.js +120 -21
- package/lib/emulator/functionsEmulatorRuntime.js +46 -121
- package/lib/emulator/functionsEmulatorShared.js +51 -7
- package/lib/emulator/functionsEmulatorShell.js +1 -1
- package/lib/emulator/pubsubEmulator.js +61 -40
- package/lib/emulator/storage/cloudFunctions.js +37 -7
- package/lib/extensions/askUserForConsent.js +14 -1
- package/lib/extensions/askUserForParam.js +81 -4
- package/lib/extensions/billingMigrationHelper.js +1 -11
- package/lib/extensions/changelog.js +2 -1
- package/lib/extensions/checkProjectBilling.js +7 -7
- package/lib/extensions/displayExtensionInfo.js +35 -33
- package/lib/extensions/emulator/optionsHelper.js +3 -3
- package/lib/extensions/emulator/triggerHelper.js +2 -32
- package/lib/extensions/export.js +107 -0
- package/lib/extensions/extensionsApi.js +149 -97
- package/lib/extensions/extensionsHelper.js +36 -32
- package/lib/extensions/listExtensions.js +16 -11
- package/lib/extensions/paramHelper.js +73 -40
- package/lib/extensions/provisioningHelper.js +16 -3
- package/lib/extensions/refs.js +67 -0
- package/lib/extensions/secretsUtils.js +59 -0
- package/lib/extensions/updateHelper.js +33 -47
- package/lib/extensions/versionHelper.js +14 -0
- package/lib/extensions/warnings.js +33 -1
- package/lib/functional.js +64 -0
- package/lib/functions/env.js +26 -13
- package/lib/functions/runtimeConfigExport.js +137 -0
- package/lib/gcp/artifactregistry.js +16 -0
- package/lib/gcp/cloudfunctions.js +65 -35
- package/lib/gcp/cloudfunctionsv2.js +56 -43
- package/lib/gcp/cloudscheduler.js +22 -16
- package/lib/gcp/cloudtasks.js +143 -0
- package/lib/gcp/docker.js +7 -1
- package/lib/gcp/proto.js +2 -2
- package/lib/gcp/pubsub.js +1 -9
- package/lib/gcp/secretManager.js +132 -0
- package/lib/gcp/storage.js +16 -0
- package/lib/previews.js +1 -1
- package/lib/requireInteractive.js +12 -0
- package/lib/utils.js +30 -1
- package/package.json +6 -4
- package/schema/firebase-config.json +9 -0
- package/lib/deploy/functions/deploymentPlanner.js +0 -113
- package/lib/deploy/functions/deploymentTimer.js +0 -23
- package/lib/deploy/functions/errorHandler.js +0 -75
- package/lib/deploy/functions/release.js +0 -116
- package/lib/deploy/functions/tasks.js +0 -324
- package/lib/functions/listFunctions.js +0 -10
- package/lib/functionsDelete.js +0 -60
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
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
|
|
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
|
-
|
|
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.
|
|
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(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
displayExtensionInfo_1.
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
113
|
+
async function updateToVersionFromPublisherSource(projectId, instanceId, extVersionRef, existingSpec) {
|
|
116
114
|
let source;
|
|
117
|
-
const
|
|
118
|
-
const version =
|
|
119
|
-
const extensionRef =
|
|
120
|
-
displayExtensionInfo_1.displayExtInfo(instanceId,
|
|
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
|
-
|
|
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
|
|
156
|
-
return updateToVersionFromPublisherSource(projectId, instanceId, `${extRef}@latest`, existingSpec
|
|
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;
|
package/lib/functions/env.js
CHANGED
|
@@ -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
|
-
"[
|
|
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"
|
|
115
|
-
if (
|
|
116
|
-
files.push(
|
|
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;
|