firebase-tools 10.2.1 → 10.2.2
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/lib/appdistribution/options-parser-util.js +1 -1
- package/lib/auth.js +3 -3
- package/lib/command.js +1 -1
- package/lib/commands/apps-android-sha-create.js +2 -2
- package/lib/commands/apps-sdkconfig.js +1 -1
- package/lib/commands/database-rules-list.js +2 -2
- package/lib/commands/emulators-start.js +1 -1
- package/lib/commands/ext-dev-init.js +49 -49
- package/lib/commands/ext-export.js +12 -2
- package/lib/commands/ext-install.js +104 -104
- package/lib/commands/ext-uninstall.js +8 -8
- package/lib/commands/ext-update.js +9 -9
- package/lib/commands/functions-config-export.js +1 -1
- package/lib/commands/hosting-clone.js +3 -3
- package/lib/commands/remoteconfig-get.js +1 -1
- package/lib/deploy/extensions/deploymentSummary.js +3 -3
- package/lib/deploy/extensions/params.js +3 -0
- package/lib/deploy/extensions/planner.js +2 -1
- package/lib/deploy/extensions/tasks.js +1 -1
- package/lib/deploy/functions/backend.js +12 -5
- package/lib/deploy/functions/checkIam.js +1 -1
- package/lib/deploy/functions/containerCleaner.js +3 -3
- package/lib/deploy/functions/ensure.js +3 -3
- package/lib/deploy/functions/functionsDeployHelper.js +2 -2
- package/lib/deploy/functions/prepare.js +3 -2
- package/lib/deploy/functions/pricing.js +1 -1
- package/lib/deploy/functions/prompts.js +2 -2
- package/lib/deploy/functions/release/fabricator.js +3 -3
- package/lib/deploy/functions/release/index.js +1 -1
- package/lib/deploy/functions/release/planner.js +11 -8
- package/lib/deploy/functions/release/reporter.js +3 -0
- package/lib/deploy/functions/runtimes/discovery/index.js +6 -6
- package/lib/deploy/functions/runtimes/discovery/parsing.js +1 -1
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +16 -11
- package/lib/deploy/functions/runtimes/golang/index.js +2 -2
- package/lib/deploy/functions/runtimes/node/index.js +26 -0
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +2 -2
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +28 -7
- package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
- package/lib/deploy/functions/validate.js +3 -3
- package/lib/deploy/hosting/deploy.js +2 -2
- package/lib/deploy/hosting/hashcache.js +21 -19
- package/lib/deploy/hosting/uploader.js +5 -5
- package/lib/deploy/remoteconfig/functions.js +2 -2
- package/lib/emulator/auth/cloudFunctions.js +1 -1
- package/lib/emulator/auth/operations.js +1 -1
- package/lib/emulator/constants.js +3 -0
- package/lib/emulator/controller.js +47 -19
- package/lib/emulator/download.js +18 -1
- package/lib/emulator/downloadableEmulators.js +1 -1
- package/lib/emulator/emulatorLogger.js +12 -1
- package/lib/emulator/extensions/validation.js +35 -0
- package/lib/emulator/extensionsEmulator.js +140 -0
- package/lib/emulator/functionsEmulator.js +86 -39
- package/lib/emulator/functionsEmulatorRuntime.js +44 -36
- package/lib/emulator/functionsEmulatorShell.js +1 -1
- package/lib/emulator/functionsEmulatorUtils.js +4 -4
- package/lib/emulator/functionsRuntimeWorker.js +2 -2
- package/lib/emulator/hub.js +4 -3
- package/lib/emulator/loggingEmulator.js +1 -1
- package/lib/emulator/pubsubEmulator.js +1 -1
- package/lib/emulator/registry.js +10 -2
- package/lib/emulator/storage/apis/firebase.js +31 -26
- package/lib/emulator/storage/apis/gcloud.js +7 -12
- package/lib/emulator/storage/files.js +36 -34
- package/lib/emulator/storage/index.js +2 -2
- package/lib/emulator/storage/metadata.js +2 -2
- package/lib/emulator/storage/rules/runtime.js +8 -7
- package/lib/emulator/types.js +3 -0
- package/lib/ensureApiEnabled.js +5 -1
- package/lib/error.js +1 -1
- package/lib/extensions/askUserForParam.js +1 -1
- package/lib/extensions/changelog.js +3 -1
- package/lib/extensions/checkProjectBilling.js +1 -1
- package/lib/extensions/displayExtensionInfo.js +1 -1
- package/lib/extensions/emulator/optionsHelper.js +24 -8
- package/lib/extensions/emulator/specHelper.js +10 -23
- package/lib/extensions/export.js +1 -51
- package/lib/extensions/extensionsApi.js +1 -1
- package/lib/extensions/extensionsHelper.js +13 -9
- package/lib/extensions/manifest.js +48 -0
- package/lib/extensions/metricsUtils.js +4 -4
- package/lib/extensions/paramHelper.js +4 -4
- package/lib/extensions/refs.js +1 -1
- package/lib/extensions/secretsUtils.js +3 -3
- package/lib/functional.js +1 -1
- package/lib/functions/env.js +2 -1
- package/lib/gcp/cloudfunctions.js +24 -5
- package/lib/gcp/cloudfunctionsv2.js +18 -5
- package/lib/gcp/cloudtasks.js +1 -1
- package/lib/gcp/docker.js +2 -2
- package/lib/gcp/run.js +2 -2
- package/lib/hosting/api.js +1 -1
- package/lib/hosting/proxy.js +2 -2
- package/lib/init/features/account.js +1 -1
- package/lib/management/database.js +1 -1
- package/lib/previews.js +1 -1
- package/lib/utils.js +1 -1
- package/npm-shrinkwrap.json +786 -393
- package/package.json +1 -1
- package/schema/firebase-config.json +5 -0
- package/templates/init/functions/javascript/package.lint.json +3 -3
- package/templates/init/functions/javascript/package.nolint.json +2 -2
- package/templates/init/functions/typescript/package.lint.json +7 -7
- package/templates/init/functions/typescript/package.nolint.json +3 -3
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getNodeVersion = exports.getFunctionProperties = exports.getFunctionResourcesWithParamSubstitution = exports.readFileFromDirectory = exports.readExtensionYaml = void 0;
|
|
4
4
|
const yaml = require("js-yaml");
|
|
5
|
-
const _ = require("lodash");
|
|
6
5
|
const path = require("path");
|
|
7
6
|
const fs = require("fs-extra");
|
|
8
7
|
const error_1 = require("../../error");
|
|
9
8
|
const extensionsHelper_1 = require("../extensionsHelper");
|
|
10
|
-
const
|
|
11
|
-
const types_1 = require("../../emulator/types");
|
|
9
|
+
const functionsEmulatorUtils_1 = require("../../emulator/functionsEmulatorUtils");
|
|
12
10
|
const SPEC_FILE = "extension.yaml";
|
|
13
11
|
const validFunctionTypes = [
|
|
14
12
|
"firebaseextensions.v1beta.function",
|
|
@@ -62,35 +60,24 @@ function getFunctionProperties(resources) {
|
|
|
62
60
|
}
|
|
63
61
|
exports.getFunctionProperties = getFunctionProperties;
|
|
64
62
|
function getNodeVersion(resources) {
|
|
65
|
-
const
|
|
63
|
+
const invalidRuntimes = [];
|
|
66
64
|
const versions = resources.map((r) => {
|
|
67
65
|
var _a, _b;
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
if ((_a = r.properties) === null || _a === void 0 ? void 0 : _a.runtime) {
|
|
67
|
+
const runtimeName = (_b = r.properties) === null || _b === void 0 ? void 0 : _b.runtime;
|
|
68
|
+
const runtime = (0, functionsEmulatorUtils_1.parseRuntimeVersion)(runtimeName);
|
|
69
|
+
if (!runtime) {
|
|
70
|
+
invalidRuntimes.push(runtimeName);
|
|
71
71
|
}
|
|
72
72
|
else {
|
|
73
|
-
|
|
73
|
+
return runtime;
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
return
|
|
77
|
-
});
|
|
78
|
-
if (functionNamesWithoutRuntime.length) {
|
|
79
|
-
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS).logLabeled("WARN", "extensions", `No 'runtime' property found for the following functions, defaulting to nodejs8: ${functionNamesWithoutRuntime.join(", ")}`);
|
|
80
|
-
}
|
|
81
|
-
const invalidRuntimes = _.filter(versions, (v) => {
|
|
82
|
-
return !_.includes(v, "nodejs");
|
|
76
|
+
return 14;
|
|
83
77
|
});
|
|
84
78
|
if (invalidRuntimes.length) {
|
|
85
79
|
throw new error_1.FirebaseError(`The following runtimes are not supported by the Emulator Suite: ${invalidRuntimes.join(", ")}. \n Only Node runtimes are supported.`);
|
|
86
80
|
}
|
|
87
|
-
|
|
88
|
-
return "10";
|
|
89
|
-
}
|
|
90
|
-
if (_.includes(versions, "nodejs6")) {
|
|
91
|
-
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS).logLabeled("WARN", "extensions", "Node 6 is deprecated. We recommend upgrading to a newer version.");
|
|
92
|
-
return "6";
|
|
93
|
-
}
|
|
94
|
-
return "8";
|
|
81
|
+
return Math.max(...versions);
|
|
95
82
|
}
|
|
96
83
|
exports.getNodeVersion = getNodeVersion;
|
package/lib/extensions/export.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const clc = require("cli-color");
|
|
5
|
-
const refs = require("./refs");
|
|
6
|
-
const config_1 = require("../config");
|
|
3
|
+
exports.displayExportInfo = exports.setSecretParamsToLatest = exports.parameterizeProject = void 0;
|
|
7
4
|
const planner_1 = require("../deploy/extensions/planner");
|
|
8
5
|
const deploymentSummary_1 = require("../deploy/extensions/deploymentSummary");
|
|
9
6
|
const logger_1 = require("../logger");
|
|
10
|
-
const error_1 = require("../error");
|
|
11
|
-
const prompt_1 = require("../prompt");
|
|
12
7
|
const secretManager_1 = require("../gcp/secretManager");
|
|
13
8
|
const secretsUtils_1 = require("./secretsUtils");
|
|
14
9
|
function parameterizeProject(projectId, projectNumber, spec) {
|
|
@@ -60,48 +55,3 @@ function displaySpecs(specs) {
|
|
|
60
55
|
logger_1.logger.info("");
|
|
61
56
|
}
|
|
62
57
|
}
|
|
63
|
-
function writeExtensionsToFirebaseJson(have, existingConfig) {
|
|
64
|
-
const extensions = existingConfig.get("extensions", {});
|
|
65
|
-
for (const s of have) {
|
|
66
|
-
extensions[s.instanceId] = refs.toExtensionVersionRef(s.ref);
|
|
67
|
-
}
|
|
68
|
-
existingConfig.set("extensions", extensions);
|
|
69
|
-
logger_1.logger.info("Adding Extensions to " + clc.bold("firebase.json") + "...");
|
|
70
|
-
existingConfig.writeProjectFile("firebase.json", existingConfig.src);
|
|
71
|
-
}
|
|
72
|
-
async function writeEnvFile(spec, existingConfig, force) {
|
|
73
|
-
const content = Object.entries(spec.params)
|
|
74
|
-
.map((r) => `${r[0]}=${r[1]}`)
|
|
75
|
-
.join("\n");
|
|
76
|
-
await existingConfig.askWriteProjectFile(`extensions/${spec.instanceId}.env`, content, force);
|
|
77
|
-
}
|
|
78
|
-
async function writeFiles(have, options) {
|
|
79
|
-
const existingConfig = config_1.Config.load(options, true);
|
|
80
|
-
if (!existingConfig) {
|
|
81
|
-
throw new error_1.FirebaseError("Not currently in a Firebase directory. Please run `firebase init` to create a Firebase directory.");
|
|
82
|
-
}
|
|
83
|
-
if (existingConfig.has("extensions") &&
|
|
84
|
-
Object.keys(existingConfig.get("extensions")).length &&
|
|
85
|
-
!options.nonInteractive &&
|
|
86
|
-
!options.force) {
|
|
87
|
-
const currentExtensions = Object.entries(existingConfig.get("extensions"))
|
|
88
|
-
.map((i) => `${i[0]}: ${i[1]}`)
|
|
89
|
-
.join("\n\t");
|
|
90
|
-
const overwrite = await (0, prompt_1.promptOnce)({
|
|
91
|
-
type: "list",
|
|
92
|
-
message: `firebase.json already contains extensions:\n${currentExtensions}\nWould you like to overwrite or merge?`,
|
|
93
|
-
choices: [
|
|
94
|
-
{ name: "Overwrite", value: true },
|
|
95
|
-
{ name: "Merge", value: false },
|
|
96
|
-
],
|
|
97
|
-
});
|
|
98
|
-
if (overwrite) {
|
|
99
|
-
existingConfig.set("extensions", {});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
writeExtensionsToFirebaseJson(have, existingConfig);
|
|
103
|
-
for (const spec of have) {
|
|
104
|
-
await writeEnvFile(spec, existingConfig, options.force);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
exports.writeFiles = writeFiles;
|
|
@@ -295,7 +295,7 @@ async function listExtensionVersions(ref, filter = "") {
|
|
|
295
295
|
exports.listExtensionVersions = listExtensionVersions;
|
|
296
296
|
async function getPublisherProfile(projectId, publisherId) {
|
|
297
297
|
const res = await apiClient.get(`/projects/${projectId}/publisherProfile`, {
|
|
298
|
-
queryParams: publisherId
|
|
298
|
+
queryParams: publisherId === undefined
|
|
299
299
|
? undefined
|
|
300
300
|
: {
|
|
301
301
|
publisherId,
|
|
@@ -112,7 +112,7 @@ function populateDefaultParams(paramVars, paramSpecs) {
|
|
|
112
112
|
const newParams = paramVars;
|
|
113
113
|
for (const param of paramSpecs) {
|
|
114
114
|
if (!paramVars[param.param]) {
|
|
115
|
-
if (param.default
|
|
115
|
+
if (param.default !== undefined && param.required) {
|
|
116
116
|
newParams[param.param] = param.default;
|
|
117
117
|
}
|
|
118
118
|
else if (param.required) {
|
|
@@ -197,13 +197,13 @@ function validateSpec(spec) {
|
|
|
197
197
|
if (param.type && !_.includes(SpecParamType, param.type)) {
|
|
198
198
|
errors.push(`Invalid type ${param.type} for param${param.param ? ` ${param.param}` : ""}. Valid types are ${_.values(SpecParamType).join(", ")}`);
|
|
199
199
|
}
|
|
200
|
-
if (!param.type || param.type
|
|
200
|
+
if (!param.type || param.type === SpecParamType.STRING) {
|
|
201
201
|
if (param.options) {
|
|
202
202
|
errors.push(`Param${param.param ? ` ${param.param}` : ""} cannot have options because it is type STRING`);
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
if (param.type &&
|
|
206
|
-
(param.type
|
|
206
|
+
(param.type === SpecParamType.SELECT || param.type === SpecParamType.MULTISELECT)) {
|
|
207
207
|
if (param.validationRegex) {
|
|
208
208
|
errors.push(`Param${param.param ? ` ${param.param}` : ""} cannot have validationRegex because it is type ${param.type}`);
|
|
209
209
|
}
|
|
@@ -211,12 +211,12 @@ function validateSpec(spec) {
|
|
|
211
211
|
errors.push(`Param${param.param ? ` ${param.param}` : ""} requires options because it is type ${param.type}`);
|
|
212
212
|
}
|
|
213
213
|
for (const opt of param.options || []) {
|
|
214
|
-
if (opt.value
|
|
214
|
+
if (opt.value === undefined) {
|
|
215
215
|
errors.push(`Option for param${param.param ? ` ${param.param}` : ""} is missing required field: value`);
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
|
-
if (param.type && param.type
|
|
219
|
+
if (param.type && param.type === SpecParamType.SELECTRESOURCE) {
|
|
220
220
|
if (!param.resourceType) {
|
|
221
221
|
errors.push(`Param${param.param ? ` ${param.param}` : ""} must have resourceType because it is type ${param.type}`);
|
|
222
222
|
}
|
|
@@ -268,7 +268,7 @@ async function archiveAndUploadSource(extPath, bucketName) {
|
|
|
268
268
|
}
|
|
269
269
|
async function publishExtensionVersionFromLocalSource(args) {
|
|
270
270
|
const extensionSpec = await (0, localHelper_1.getLocalExtensionSpec)(args.rootDirectory);
|
|
271
|
-
if (extensionSpec.name
|
|
271
|
+
if (extensionSpec.name !== args.extensionId) {
|
|
272
272
|
throw new error_1.FirebaseError(`Extension ID '${clc.bold(args.extensionId)}' does not match the name in extension.yaml '${clc.bold(extensionSpec.name)}'.`);
|
|
273
273
|
}
|
|
274
274
|
const subbedSpec = JSON.parse(JSON.stringify(extensionSpec));
|
|
@@ -325,7 +325,9 @@ async function publishExtensionVersionFromLocalSource(args) {
|
|
|
325
325
|
}
|
|
326
326
|
catch (err) {
|
|
327
327
|
uploadSpinner.fail();
|
|
328
|
-
throw err
|
|
328
|
+
throw new error_1.FirebaseError(`Failed to archive and upload extension source, ${err}`, {
|
|
329
|
+
original: err,
|
|
330
|
+
});
|
|
329
331
|
}
|
|
330
332
|
const publishSpinner = ora(`Publishing ${clc.bold(ref)}`);
|
|
331
333
|
let res;
|
|
@@ -336,7 +338,7 @@ async function publishExtensionVersionFromLocalSource(args) {
|
|
|
336
338
|
}
|
|
337
339
|
catch (err) {
|
|
338
340
|
publishSpinner.fail();
|
|
339
|
-
if (err.status
|
|
341
|
+
if (err.status === 404) {
|
|
340
342
|
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.`));
|
|
341
343
|
}
|
|
342
344
|
throw err;
|
|
@@ -360,7 +362,9 @@ async function createSourceFromLocation(projectId, sourceUri) {
|
|
|
360
362
|
}
|
|
361
363
|
catch (err) {
|
|
362
364
|
uploadSpinner.fail();
|
|
363
|
-
throw err
|
|
365
|
+
throw new error_1.FirebaseError(`Failed to archive and upload extension source, ${err}`, {
|
|
366
|
+
original: err,
|
|
367
|
+
});
|
|
364
368
|
}
|
|
365
369
|
}
|
|
366
370
|
else {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.writeToManifest = void 0;
|
|
4
|
+
const clc = require("cli-color");
|
|
5
|
+
const refs = require("./refs");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
const prompt_1 = require("../prompt");
|
|
8
|
+
async function writeToManifest(specs, config, options) {
|
|
9
|
+
if (config.has("extensions") &&
|
|
10
|
+
Object.keys(config.get("extensions")).length &&
|
|
11
|
+
!options.nonInteractive &&
|
|
12
|
+
!options.force) {
|
|
13
|
+
const currentExtensions = Object.entries(config.get("extensions"))
|
|
14
|
+
.map((i) => `${i[0]}: ${i[1]}`)
|
|
15
|
+
.join("\n\t");
|
|
16
|
+
const overwrite = await (0, prompt_1.promptOnce)({
|
|
17
|
+
type: "list",
|
|
18
|
+
message: `firebase.json already contains extensions:\n${currentExtensions}\nWould you like to overwrite or merge?`,
|
|
19
|
+
choices: [
|
|
20
|
+
{ name: "Overwrite", value: true },
|
|
21
|
+
{ name: "Merge", value: false },
|
|
22
|
+
],
|
|
23
|
+
});
|
|
24
|
+
if (overwrite) {
|
|
25
|
+
config.set("extensions", {});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
writeExtensionsToFirebaseJson(specs, config);
|
|
29
|
+
await writeEnvFiles(specs, config, options.force);
|
|
30
|
+
}
|
|
31
|
+
exports.writeToManifest = writeToManifest;
|
|
32
|
+
function writeExtensionsToFirebaseJson(specs, config) {
|
|
33
|
+
const extensions = config.get("extensions", {});
|
|
34
|
+
for (const s of specs) {
|
|
35
|
+
extensions[s.instanceId] = refs.toExtensionVersionRef(s.ref);
|
|
36
|
+
}
|
|
37
|
+
config.set("extensions", extensions);
|
|
38
|
+
logger_1.logger.info("Adding Extensions to " + clc.bold("firebase.json") + "...");
|
|
39
|
+
config.writeProjectFile("firebase.json", config.src);
|
|
40
|
+
}
|
|
41
|
+
async function writeEnvFiles(specs, config, force) {
|
|
42
|
+
for (const spec of specs) {
|
|
43
|
+
const content = Object.entries(spec.params)
|
|
44
|
+
.map((r) => `${r[0]}=${r[1]}`)
|
|
45
|
+
.join("\n");
|
|
46
|
+
await config.askWriteProjectFile(`extensions/${spec.instanceId}.env`, content, force);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -7,19 +7,19 @@ function parseTimeseriesResponse(series) {
|
|
|
7
7
|
const ret = [];
|
|
8
8
|
for (const s of series) {
|
|
9
9
|
const ref = buildRef(s);
|
|
10
|
-
if (ref
|
|
10
|
+
if (ref === undefined) {
|
|
11
11
|
continue;
|
|
12
12
|
}
|
|
13
13
|
let valueToday;
|
|
14
14
|
let value7dAgo;
|
|
15
15
|
let value28dAgo;
|
|
16
|
-
if (s.points.length >= 28 && s.points[27].value.int64Value
|
|
16
|
+
if (s.points.length >= 28 && s.points[27].value.int64Value !== undefined) {
|
|
17
17
|
value28dAgo = parseBucket(s.points[27].value.int64Value);
|
|
18
18
|
}
|
|
19
|
-
if (s.points.length >= 7 && s.points[6].value.int64Value
|
|
19
|
+
if (s.points.length >= 7 && s.points[6].value.int64Value !== undefined) {
|
|
20
20
|
value7dAgo = parseBucket(s.points[6].value.int64Value);
|
|
21
21
|
}
|
|
22
|
-
if (s.points.length >= 1 && s.points[0].value.int64Value
|
|
22
|
+
if (s.points.length >= 1 && s.points[0].value.int64Value !== undefined) {
|
|
23
23
|
valueToday = parseBucket(s.points[0].value.int64Value);
|
|
24
24
|
}
|
|
25
25
|
ret.push({
|
|
@@ -49,7 +49,7 @@ async function getParams(args) {
|
|
|
49
49
|
const firebaseProjectParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId);
|
|
50
50
|
params = await askUserForParam.ask(args.projectId, args.instanceId, args.paramSpecs, firebaseProjectParams, !!args.reconfiguring);
|
|
51
51
|
}
|
|
52
|
-
track("Extension Params", _.isEmpty(params) ? "Not Present" : "Present", _.size(params));
|
|
52
|
+
void track("Extension Params", _.isEmpty(params) ? "Not Present" : "Present", _.size(params));
|
|
53
53
|
return params;
|
|
54
54
|
}
|
|
55
55
|
exports.getParams = getParams;
|
|
@@ -82,7 +82,7 @@ async function getParamsForUpdate(args) {
|
|
|
82
82
|
instanceId: args.instanceId,
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
-
track("Extension Params", _.isEmpty(params) ? "Not Present" : "Present", _.size(params));
|
|
85
|
+
void track("Extension Params", _.isEmpty(params) ? "Not Present" : "Present", _.size(params));
|
|
86
86
|
return params;
|
|
87
87
|
}
|
|
88
88
|
exports.getParamsForUpdate = getParamsForUpdate;
|
|
@@ -116,10 +116,10 @@ function getParamsFromFile(args) {
|
|
|
116
116
|
let envParams;
|
|
117
117
|
try {
|
|
118
118
|
envParams = readEnvFile(args.paramsEnvPath);
|
|
119
|
-
track("Extension Env File", "Present");
|
|
119
|
+
void track("Extension Env File", "Present");
|
|
120
120
|
}
|
|
121
121
|
catch (err) {
|
|
122
|
-
track("Extension Env File", "Invalid");
|
|
122
|
+
void track("Extension Env File", "Invalid");
|
|
123
123
|
throw new error_1.FirebaseError(`Error reading env file: ${err.message}\n`, { original: err });
|
|
124
124
|
}
|
|
125
125
|
const params = (0, extensionsHelper_1.populateDefaultParams)(envParams, args.paramSpecs);
|
package/lib/extensions/refs.js
CHANGED
|
@@ -20,7 +20,7 @@ function parse(refOrName) {
|
|
|
20
20
|
exports.parse = parse;
|
|
21
21
|
function parseRef(ref) {
|
|
22
22
|
const parts = refRegex.exec(ref);
|
|
23
|
-
if (parts && (parts.length
|
|
23
|
+
if (parts && (parts.length === 5 || parts.length === 7)) {
|
|
24
24
|
const publisherId = parts[1];
|
|
25
25
|
const extensionId = parts[2];
|
|
26
26
|
const version = parts[4];
|
|
@@ -15,7 +15,7 @@ async function ensureSecretManagerApiEnabled(options) {
|
|
|
15
15
|
}
|
|
16
16
|
exports.ensureSecretManagerApiEnabled = ensureSecretManagerApiEnabled;
|
|
17
17
|
function usesSecrets(spec) {
|
|
18
|
-
return spec.params && !!spec.params.find((p) => p.type
|
|
18
|
+
return spec.params && !!spec.params.find((p) => p.type === extensionsApi.ParamType.SECRET);
|
|
19
19
|
}
|
|
20
20
|
exports.usesSecrets = usesSecrets;
|
|
21
21
|
async function grantFirexServiceAgentSecretAdminRole(secret) {
|
|
@@ -38,7 +38,7 @@ async function getManagedSecrets(instance) {
|
|
|
38
38
|
exports.getManagedSecrets = getManagedSecrets;
|
|
39
39
|
function getActiveSecrets(spec, params) {
|
|
40
40
|
return spec.params
|
|
41
|
-
.map((p) => (p.type
|
|
41
|
+
.map((p) => (p.type === extensionsApi.ParamType.SECRET ? params[p.param] : ""))
|
|
42
42
|
.filter((pv) => !!pv);
|
|
43
43
|
}
|
|
44
44
|
exports.getActiveSecrets = getActiveSecrets;
|
|
@@ -50,7 +50,7 @@ function getSecretLabels(instanceId) {
|
|
|
50
50
|
exports.getSecretLabels = getSecretLabels;
|
|
51
51
|
function prettySecretName(secretResourceName) {
|
|
52
52
|
const nameTokens = secretResourceName.split("/");
|
|
53
|
-
if (nameTokens.length
|
|
53
|
+
if (nameTokens.length !== 4 && nameTokens.length !== 6) {
|
|
54
54
|
logger_1.logger.debug(`unable to parse secret secretResourceName: ${secretResourceName}`);
|
|
55
55
|
return secretResourceName;
|
|
56
56
|
}
|
package/lib/functional.js
CHANGED
|
@@ -40,7 +40,7 @@ function reduceFlat(accum, next) {
|
|
|
40
40
|
}
|
|
41
41
|
exports.reduceFlat = reduceFlat;
|
|
42
42
|
function* zip(left, right) {
|
|
43
|
-
if (left.length
|
|
43
|
+
if (left.length !== right.length) {
|
|
44
44
|
throw new Error("Cannot zip between two lists of differen lengths");
|
|
45
45
|
}
|
|
46
46
|
for (let i = 0; i < left.length; i++) {
|
package/lib/functions/env.js
CHANGED
|
@@ -12,6 +12,7 @@ const RESERVED_PREFIXES = ["X_GOOGLE_", "FIREBASE_", "EXT_"];
|
|
|
12
12
|
const RESERVED_KEYS = [
|
|
13
13
|
"FIREBASE_CONFIG",
|
|
14
14
|
"CLOUD_RUNTIME_CONFIG",
|
|
15
|
+
"EVENTARC_CLOUD_EVENT_SOURCE",
|
|
15
16
|
"ENTRY_POINT",
|
|
16
17
|
"GCP_PROJECT",
|
|
17
18
|
"GCLOUD_PROJECT",
|
|
@@ -141,7 +142,7 @@ exports.hasUserEnvs = hasUserEnvs;
|
|
|
141
142
|
function loadUserEnvs({ functionsSource, projectId, projectAlias, isEmulator, }) {
|
|
142
143
|
var _a;
|
|
143
144
|
const envFiles = findEnvfiles(functionsSource, projectId, projectAlias, isEmulator);
|
|
144
|
-
if (envFiles.length
|
|
145
|
+
if (envFiles.length === 0) {
|
|
145
146
|
return {};
|
|
146
147
|
}
|
|
147
148
|
if (projectAlias) {
|
|
@@ -92,7 +92,7 @@ async function getIamPolicy(fnName) {
|
|
|
92
92
|
}
|
|
93
93
|
exports.getIamPolicy = getIamPolicy;
|
|
94
94
|
async function setInvokerCreate(projectId, fnName, invoker) {
|
|
95
|
-
if (invoker.length
|
|
95
|
+
if (invoker.length === 0) {
|
|
96
96
|
throw new error_1.FirebaseError("Invoker cannot be an empty array");
|
|
97
97
|
}
|
|
98
98
|
const invokerMembers = proto.getInvokerMembers(invoker, projectId);
|
|
@@ -108,7 +108,7 @@ async function setInvokerCreate(projectId, fnName, invoker) {
|
|
|
108
108
|
exports.setInvokerCreate = setInvokerCreate;
|
|
109
109
|
async function setInvokerUpdate(projectId, fnName, invoker) {
|
|
110
110
|
var _a;
|
|
111
|
-
if (invoker.length
|
|
111
|
+
if (invoker.length === 0) {
|
|
112
112
|
throw new error_1.FirebaseError("Invoker cannot be an empty array");
|
|
113
113
|
}
|
|
114
114
|
const invokerMembers = proto.getInvokerMembers(invoker, projectId);
|
|
@@ -206,6 +206,7 @@ function endpointFromFunction(gcfFunction) {
|
|
|
206
206
|
const [, project, , region, , id] = gcfFunction.name.split("/");
|
|
207
207
|
let trigger;
|
|
208
208
|
let uri;
|
|
209
|
+
let securityLevel;
|
|
209
210
|
if ((_a = gcfFunction.labels) === null || _a === void 0 ? void 0 : _a["deployment-scheduled"]) {
|
|
210
211
|
trigger = {
|
|
211
212
|
scheduleTrigger: {},
|
|
@@ -219,6 +220,7 @@ function endpointFromFunction(gcfFunction) {
|
|
|
219
220
|
else if (gcfFunction.httpsTrigger) {
|
|
220
221
|
trigger = { httpsTrigger: {} };
|
|
221
222
|
uri = gcfFunction.httpsTrigger.url;
|
|
223
|
+
securityLevel = gcfFunction.httpsTrigger.securityLevel;
|
|
222
224
|
}
|
|
223
225
|
else {
|
|
224
226
|
trigger = {
|
|
@@ -240,12 +242,19 @@ function endpointFromFunction(gcfFunction) {
|
|
|
240
242
|
if (uri) {
|
|
241
243
|
endpoint.uri = uri;
|
|
242
244
|
}
|
|
243
|
-
|
|
245
|
+
if (securityLevel) {
|
|
246
|
+
endpoint.securityLevel = securityLevel;
|
|
247
|
+
}
|
|
248
|
+
proto.copyIfPresent(endpoint, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "timeout", "minInstances", "maxInstances", "ingressSettings", "labels", "environmentVariables", "secretEnvironmentVariables", "sourceUploadUrl");
|
|
249
|
+
if (gcfFunction.vpcConnector) {
|
|
250
|
+
endpoint.vpc = { connector: gcfFunction.vpcConnector };
|
|
251
|
+
proto.renameIfPresent(endpoint.vpc, gcfFunction, "egressSettings", "vpcConnectorEgressSettings");
|
|
252
|
+
}
|
|
244
253
|
return endpoint;
|
|
245
254
|
}
|
|
246
255
|
exports.endpointFromFunction = endpointFromFunction;
|
|
247
256
|
function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
248
|
-
if (endpoint.platform
|
|
257
|
+
if (endpoint.platform !== "gcfv1") {
|
|
249
258
|
throw new error_1.FirebaseError("Trying to create a v1 CloudFunction with v2 API. This should never happen");
|
|
250
259
|
}
|
|
251
260
|
if (!runtimes.isValidRuntime(endpoint.runtime)) {
|
|
@@ -282,8 +291,18 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
282
291
|
}
|
|
283
292
|
else {
|
|
284
293
|
gcfFunction.httpsTrigger = {};
|
|
294
|
+
if (backend.isCallableTriggered(endpoint)) {
|
|
295
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-callabled": "true" });
|
|
296
|
+
}
|
|
297
|
+
if (endpoint.securityLevel) {
|
|
298
|
+
gcfFunction.httpsTrigger.securityLevel = endpoint.securityLevel;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "timeout", "availableMemoryMb", "minInstances", "maxInstances", "ingressSettings", "environmentVariables", "secretEnvironmentVariables");
|
|
302
|
+
if (endpoint.vpc) {
|
|
303
|
+
proto.renameIfPresent(gcfFunction, endpoint.vpc, "vpcConnector", "connector");
|
|
304
|
+
proto.renameIfPresent(gcfFunction, endpoint.vpc, "vpcConnectorEgressSettings", "egressSettings");
|
|
285
305
|
}
|
|
286
|
-
proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "timeout", "availableMemoryMb", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables", "secretEnvironmentVariables");
|
|
287
306
|
return gcfFunction;
|
|
288
307
|
}
|
|
289
308
|
exports.functionFromEndpoint = functionFromEndpoint;
|
|
@@ -106,7 +106,7 @@ async function listFunctionsInternal(projectId, region) {
|
|
|
106
106
|
let pageToken = "";
|
|
107
107
|
while (true) {
|
|
108
108
|
const url = `projects/${projectId}/locations/${region}/functions`;
|
|
109
|
-
const opts = pageToken
|
|
109
|
+
const opts = pageToken === "" ? {} : { queryParams: { pageToken } };
|
|
110
110
|
const res = await client.get(url, opts);
|
|
111
111
|
functions.push(...(res.body.functions || []));
|
|
112
112
|
for (const region of res.body.unreachable || []) {
|
|
@@ -122,9 +122,10 @@ async function listFunctionsInternal(projectId, region) {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
async function updateFunction(cloudFunction) {
|
|
125
|
+
const fieldMasks = proto.fieldMasks(cloudFunction, "labels", "serviceConfig.environmentVariables");
|
|
125
126
|
try {
|
|
126
127
|
const queryParams = {
|
|
127
|
-
updateMask:
|
|
128
|
+
updateMask: fieldMasks.join(","),
|
|
128
129
|
};
|
|
129
130
|
const res = await client.patch(cloudFunction.name, cloudFunction, { queryParams });
|
|
130
131
|
return res.body;
|
|
@@ -145,7 +146,7 @@ async function deleteFunction(cloudFunction) {
|
|
|
145
146
|
}
|
|
146
147
|
exports.deleteFunction = deleteFunction;
|
|
147
148
|
function functionFromEndpoint(endpoint, source) {
|
|
148
|
-
if (endpoint.platform
|
|
149
|
+
if (endpoint.platform !== "gcfv2") {
|
|
149
150
|
throw new error_1.FirebaseError("Trying to create a v2 CloudFunction with v1 API. This should never happen");
|
|
150
151
|
}
|
|
151
152
|
if (!runtimes.isValidRuntime(endpoint.runtime)) {
|
|
@@ -165,11 +166,15 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
165
166
|
serviceConfig: {},
|
|
166
167
|
};
|
|
167
168
|
proto.copyIfPresent(gcfFunction, endpoint, "labels");
|
|
168
|
-
proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "environmentVariables", "
|
|
169
|
+
proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "environmentVariables", "serviceAccountEmail", "ingressSettings");
|
|
169
170
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "availableMemory", "availableMemoryMb", (mb) => `${mb}M`);
|
|
170
171
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "timeoutSeconds", "timeout", proto.secondsFromDuration);
|
|
171
172
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "minInstanceCount", "minInstances");
|
|
172
173
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "maxInstanceCount", "maxInstances");
|
|
174
|
+
if (endpoint.vpc) {
|
|
175
|
+
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint.vpc, "vpcConnector", "connector");
|
|
176
|
+
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint.vpc, "vpcConnectorEgressSettings", "egressSettings");
|
|
177
|
+
}
|
|
173
178
|
if (backend.isEventTriggered(endpoint)) {
|
|
174
179
|
gcfFunction.eventTrigger = {
|
|
175
180
|
eventType: endpoint.eventTrigger.eventType,
|
|
@@ -187,6 +192,7 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
187
192
|
if (endpoint.eventTrigger.retry) {
|
|
188
193
|
logger_1.logger.warn("Cannot set a retry policy on Cloud Function", endpoint.id);
|
|
189
194
|
}
|
|
195
|
+
gcfFunction.serviceConfig.environmentVariables = Object.assign(Object.assign({}, gcfFunction.serviceConfig.environmentVariables), { FUNCTION_SIGNATURE_TYPE: "cloudevent" });
|
|
190
196
|
}
|
|
191
197
|
else if (backend.isScheduleTriggered(endpoint)) {
|
|
192
198
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-scheduled": "true" });
|
|
@@ -194,6 +200,9 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
194
200
|
else if (backend.isTaskQueueTriggered(endpoint)) {
|
|
195
201
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-taskqueue": "true" });
|
|
196
202
|
}
|
|
203
|
+
else if (backend.isCallableTriggered(endpoint)) {
|
|
204
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-callable": "true" });
|
|
205
|
+
}
|
|
197
206
|
return gcfFunction;
|
|
198
207
|
}
|
|
199
208
|
exports.functionFromEndpoint = functionFromEndpoint;
|
|
@@ -238,12 +247,16 @@ function endpointFromFunction(gcfFunction) {
|
|
|
238
247
|
const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
|
|
239
248
|
project,
|
|
240
249
|
region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime, uri: gcfFunction.serviceConfig.uri });
|
|
241
|
-
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "
|
|
250
|
+
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "ingressSettings", "environmentVariables");
|
|
242
251
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "availableMemoryMb", "availableMemory", megabytes);
|
|
243
252
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "timeout", "timeoutSeconds", proto.durationFromSeconds);
|
|
244
253
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "minInstances", "minInstanceCount");
|
|
245
254
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "maxInstances", "maxInstanceCount");
|
|
246
255
|
proto.copyIfPresent(endpoint, gcfFunction, "labels");
|
|
256
|
+
if (gcfFunction.serviceConfig.vpcConnector) {
|
|
257
|
+
endpoint.vpc = { connector: gcfFunction.serviceConfig.vpcConnector };
|
|
258
|
+
proto.renameIfPresent(endpoint.vpc, gcfFunction.serviceConfig, "egressSettings", "vpcConnectorEgressSettings");
|
|
259
|
+
}
|
|
247
260
|
return endpoint;
|
|
248
261
|
}
|
|
249
262
|
exports.endpointFromFunction = endpointFromFunction;
|
package/lib/gcp/cloudtasks.js
CHANGED
|
@@ -102,7 +102,7 @@ async function setEnqueuer(name, invoker, assumeEmpty = false) {
|
|
|
102
102
|
const invokerMembers = proto.getInvokerMembers(invoker, project);
|
|
103
103
|
while (true) {
|
|
104
104
|
const policy = {
|
|
105
|
-
bindings: existing.bindings.filter((binding) => binding.role
|
|
105
|
+
bindings: existing.bindings.filter((binding) => binding.role !== ENQUEUER_ROLE),
|
|
106
106
|
etag: existing.etag,
|
|
107
107
|
version: existing.version,
|
|
108
108
|
};
|
package/lib/gcp/docker.js
CHANGED
|
@@ -58,7 +58,7 @@ class Client {
|
|
|
58
58
|
if (!response.body) {
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
|
-
if (((_a = response.body.errors) === null || _a === void 0 ? void 0 : _a.length)
|
|
61
|
+
if (((_a = response.body.errors) === null || _a === void 0 ? void 0 : _a.length) !== 0) {
|
|
62
62
|
throw new error_1.FirebaseError(`Failed to delete tag ${tag} at path ${path}`, {
|
|
63
63
|
children: response.body.errors,
|
|
64
64
|
});
|
|
@@ -70,7 +70,7 @@ class Client {
|
|
|
70
70
|
if (!response.body) {
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
|
-
if (((_a = response.body.errors) === null || _a === void 0 ? void 0 : _a.length)
|
|
73
|
+
if (((_a = response.body.errors) === null || _a === void 0 ? void 0 : _a.length) !== 0) {
|
|
74
74
|
throw new error_1.FirebaseError(`Failed to delete image ${digest} at path ${path}`, {
|
|
75
75
|
children: response.body.errors,
|
|
76
76
|
});
|
package/lib/gcp/run.js
CHANGED
|
@@ -63,7 +63,7 @@ async function getIamPolicy(serviceName, httpClient = client) {
|
|
|
63
63
|
}
|
|
64
64
|
exports.getIamPolicy = getIamPolicy;
|
|
65
65
|
async function setInvokerCreate(projectId, serviceName, invoker, httpClient = client) {
|
|
66
|
-
if (invoker.length
|
|
66
|
+
if (invoker.length === 0) {
|
|
67
67
|
throw new error_1.FirebaseError("Invoker cannot be an empty array");
|
|
68
68
|
}
|
|
69
69
|
const invokerMembers = proto.getInvokerMembers(invoker, projectId);
|
|
@@ -79,7 +79,7 @@ async function setInvokerCreate(projectId, serviceName, invoker, httpClient = cl
|
|
|
79
79
|
exports.setInvokerCreate = setInvokerCreate;
|
|
80
80
|
async function setInvokerUpdate(projectId, serviceName, invoker, httpClient = client) {
|
|
81
81
|
var _a;
|
|
82
|
-
if (invoker.length
|
|
82
|
+
if (invoker.length === 0) {
|
|
83
83
|
throw new error_1.FirebaseError("Invoker cannot be an empty array");
|
|
84
84
|
}
|
|
85
85
|
const invokerMembers = proto.getInvokerMembers(invoker, projectId);
|
package/lib/hosting/api.js
CHANGED
|
@@ -192,7 +192,7 @@ async function removeAuthDomain(project, url) {
|
|
|
192
192
|
return domains;
|
|
193
193
|
}
|
|
194
194
|
const targetDomain = url.replace("https://", "");
|
|
195
|
-
const authDomains = domains.filter((domain) => domain
|
|
195
|
+
const authDomains = domains.filter((domain) => domain !== targetDomain);
|
|
196
196
|
return (0, auth_1.updateAuthDomains)(project, authDomains);
|
|
197
197
|
}
|
|
198
198
|
exports.removeAuthDomain = removeAuthDomain;
|
package/lib/hosting/proxy.js
CHANGED
|
@@ -54,7 +54,7 @@ function proxyRequestHandler(url, rewriteIdentifier) {
|
|
|
54
54
|
continue;
|
|
55
55
|
}
|
|
56
56
|
const value = req.headers[key];
|
|
57
|
-
if (value
|
|
57
|
+
if (value === undefined) {
|
|
58
58
|
headers.delete(key);
|
|
59
59
|
}
|
|
60
60
|
else if (Array.isArray(value)) {
|
|
@@ -115,7 +115,7 @@ function proxyRequestHandler(url, rewriteIdentifier) {
|
|
|
115
115
|
if (location) {
|
|
116
116
|
try {
|
|
117
117
|
const locationURL = new url_1.URL(location);
|
|
118
|
-
if (locationURL.origin
|
|
118
|
+
if (locationURL.origin === u.origin) {
|
|
119
119
|
const unborkedLocation = location.replace(locationURL.origin, "");
|
|
120
120
|
proxyRes.response.headers.set("location", unborkedLocation);
|
|
121
121
|
}
|
|
@@ -27,7 +27,7 @@ async function promptForAccount() {
|
|
|
27
27
|
message: "Please select an option:",
|
|
28
28
|
choices,
|
|
29
29
|
});
|
|
30
|
-
if (emailChoice
|
|
30
|
+
if (emailChoice === "__add__") {
|
|
31
31
|
const newAccount = await (0, auth_1.loginAdditionalAccount)(true);
|
|
32
32
|
if (!newAccount) {
|
|
33
33
|
throw new error_1.FirebaseError("Failed to add new account", { exit: 1 });
|
|
@@ -168,7 +168,7 @@ function convertDatabaseInstance(serverInstance) {
|
|
|
168
168
|
throw new error_1.FirebaseError(`DatabaseInstance response is missing field "name"`);
|
|
169
169
|
}
|
|
170
170
|
const m = serverInstance.name.match(INSTANCE_RESOURCE_NAME_REGEX);
|
|
171
|
-
if (!m || m.length
|
|
171
|
+
if (!m || m.length !== 4) {
|
|
172
172
|
throw new error_1.FirebaseError(`Error parsing instance resource name: ${serverInstance.name}, matches: ${m}`);
|
|
173
173
|
}
|
|
174
174
|
return {
|