firebase-tools 10.2.1 → 10.3.1
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-configure.js +67 -7
- package/lib/commands/ext-dev-init.js +49 -49
- package/lib/commands/ext-export.js +7 -2
- package/lib/commands/ext-install.js +173 -109
- package/lib/commands/ext-uninstall.js +17 -8
- package/lib/commands/ext-update.js +67 -12
- 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/config.js +6 -3
- package/lib/deploy/extensions/deploymentSummary.js +3 -3
- package/lib/deploy/extensions/planner.js +7 -6
- package/lib/deploy/extensions/tasks.js +1 -1
- package/lib/deploy/functions/backend.js +21 -5
- package/lib/deploy/functions/checkIam.js +5 -5
- 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 +5 -3
- package/lib/deploy/functions/pricing.js +1 -1
- package/lib/deploy/functions/prompts.js +2 -2
- package/lib/deploy/functions/release/fabricator.js +7 -7
- package/lib/deploy/functions/release/index.js +1 -1
- package/lib/deploy/functions/release/planner.js +43 -26
- 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 +22 -12
- package/lib/deploy/functions/runtimes/golang/index.js +2 -2
- package/lib/deploy/functions/runtimes/node/index.js +53 -0
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +2 -2
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +64 -20
- package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
- package/lib/deploy/functions/services/firebaseAlerts.js +30 -0
- package/lib/deploy/functions/services/index.js +9 -1
- package/lib/deploy/functions/services/storage.js +10 -4
- package/lib/deploy/functions/triggerRegionHelper.js +1 -1
- 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 +4 -0
- package/lib/emulator/controller.js +54 -24
- 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 +70 -0
- package/lib/emulator/extensionsEmulator.js +175 -0
- package/lib/emulator/functionsEmulator.js +95 -43
- package/lib/emulator/functionsEmulatorRuntime.js +44 -36
- package/lib/emulator/functionsEmulatorShared.js +30 -11
- 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 +314 -332
- package/lib/emulator/storage/apis/gcloud.js +241 -121
- package/lib/emulator/storage/crc.js +5 -1
- package/lib/emulator/storage/errors.js +9 -0
- package/lib/emulator/storage/files.js +159 -300
- package/lib/emulator/storage/index.js +27 -73
- package/lib/emulator/storage/metadata.js +65 -51
- package/lib/emulator/storage/multipart.js +62 -0
- package/lib/emulator/storage/persistence.js +78 -0
- package/lib/emulator/storage/rules/config.js +33 -0
- package/lib/emulator/storage/rules/manager.js +81 -0
- package/lib/emulator/storage/rules/runtime.js +8 -7
- package/lib/emulator/storage/rules/utils.js +48 -0
- package/lib/emulator/storage/server.js +2 -2
- package/lib/emulator/storage/upload.js +106 -0
- package/lib/emulator/types.js +3 -0
- package/lib/ensureApiEnabled.js +5 -1
- package/lib/error.js +1 -1
- package/lib/extensions/askUserForParam.js +31 -25
- 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 +56 -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 +32 -19
- package/lib/extensions/manifest.js +144 -0
- package/lib/extensions/metricsUtils.js +4 -4
- package/lib/extensions/paramHelper.js +34 -12
- 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 +6 -7
- package/lib/functions/events/v2.js +11 -0
- package/lib/gcp/cloudfunctions.js +43 -11
- package/lib/gcp/cloudfunctionsv2.js +48 -17
- package/lib/gcp/cloudtasks.js +1 -1
- package/lib/gcp/docker.js +2 -2
- package/lib/gcp/resourceManager.js +4 -4
- 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/serve/functions.js +2 -1
- package/lib/utils.js +15 -2
- 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
- package/lib/deploy/extensions/params.js +0 -39
- package/lib/deploy/functions/eventTypes.js +0 -10
|
@@ -58,7 +58,7 @@ function createApp(defaultProjectId, emulator) {
|
|
|
58
58
|
}
|
|
59
59
|
const name = file.name;
|
|
60
60
|
const content = file.content;
|
|
61
|
-
const issues = await emulator.
|
|
61
|
+
const issues = await emulator.setRules({ name, content });
|
|
62
62
|
if (issues.errors.length > 0) {
|
|
63
63
|
res.status(400).json({
|
|
64
64
|
message: "There was an error updating rules, see logs for more details",
|
|
@@ -70,7 +70,7 @@ function createApp(defaultProjectId, emulator) {
|
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
72
|
app.post("/internal/reset", (req, res) => {
|
|
73
|
-
|
|
73
|
+
emulator.reset();
|
|
74
74
|
res.sendStatus(200);
|
|
75
75
|
});
|
|
76
76
|
app.use("/v0", (0, firebase_1.createFirebaseEndpoints)(emulator));
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UploadService = exports.NotCancellableError = exports.UploadNotActiveError = exports.UploadStatus = exports.UploadType = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
var UploadType;
|
|
7
|
+
(function (UploadType) {
|
|
8
|
+
UploadType[UploadType["MULTIPART"] = 0] = "MULTIPART";
|
|
9
|
+
UploadType[UploadType["RESUMABLE"] = 1] = "RESUMABLE";
|
|
10
|
+
})(UploadType = exports.UploadType || (exports.UploadType = {}));
|
|
11
|
+
var UploadStatus;
|
|
12
|
+
(function (UploadStatus) {
|
|
13
|
+
UploadStatus[UploadStatus["ACTIVE"] = 0] = "ACTIVE";
|
|
14
|
+
UploadStatus[UploadStatus["CANCELLED"] = 1] = "CANCELLED";
|
|
15
|
+
UploadStatus[UploadStatus["FINISHED"] = 2] = "FINISHED";
|
|
16
|
+
})(UploadStatus = exports.UploadStatus || (exports.UploadStatus = {}));
|
|
17
|
+
class UploadNotActiveError extends Error {
|
|
18
|
+
}
|
|
19
|
+
exports.UploadNotActiveError = UploadNotActiveError;
|
|
20
|
+
class NotCancellableError extends Error {
|
|
21
|
+
}
|
|
22
|
+
exports.NotCancellableError = NotCancellableError;
|
|
23
|
+
class UploadService {
|
|
24
|
+
constructor(_persistence) {
|
|
25
|
+
this._persistence = _persistence;
|
|
26
|
+
this.reset();
|
|
27
|
+
}
|
|
28
|
+
reset() {
|
|
29
|
+
this._uploads = new Map();
|
|
30
|
+
}
|
|
31
|
+
multipartUpload(request) {
|
|
32
|
+
const upload = this.startMultipartUpload(request, request.dataRaw.byteLength);
|
|
33
|
+
this._persistence.deleteFile(upload.path, true);
|
|
34
|
+
this._persistence.appendBytes(upload.path, request.dataRaw);
|
|
35
|
+
return upload;
|
|
36
|
+
}
|
|
37
|
+
startMultipartUpload(request, sizeInBytes) {
|
|
38
|
+
const id = (0, uuid_1.v4)();
|
|
39
|
+
const upload = {
|
|
40
|
+
id: (0, uuid_1.v4)(),
|
|
41
|
+
bucketId: request.bucketId,
|
|
42
|
+
objectId: request.objectId,
|
|
43
|
+
type: UploadType.MULTIPART,
|
|
44
|
+
path: this.getStagingFileName(id, request.bucketId, request.objectId),
|
|
45
|
+
status: UploadStatus.FINISHED,
|
|
46
|
+
metadata: JSON.parse(request.metadataRaw),
|
|
47
|
+
size: sizeInBytes,
|
|
48
|
+
authorization: request.authorization,
|
|
49
|
+
};
|
|
50
|
+
this._uploads.set(upload.id, upload);
|
|
51
|
+
return upload;
|
|
52
|
+
}
|
|
53
|
+
startResumableUpload(request) {
|
|
54
|
+
const id = (0, uuid_1.v4)();
|
|
55
|
+
const upload = {
|
|
56
|
+
id: id,
|
|
57
|
+
bucketId: request.bucketId,
|
|
58
|
+
objectId: request.objectId,
|
|
59
|
+
type: UploadType.RESUMABLE,
|
|
60
|
+
path: this.getStagingFileName(id, request.bucketId, request.objectId),
|
|
61
|
+
status: UploadStatus.ACTIVE,
|
|
62
|
+
metadata: JSON.parse(request.metadataRaw),
|
|
63
|
+
size: 0,
|
|
64
|
+
authorization: request.authorization,
|
|
65
|
+
};
|
|
66
|
+
this._uploads.set(upload.id, upload);
|
|
67
|
+
this._persistence.deleteFile(upload.path, true);
|
|
68
|
+
return upload;
|
|
69
|
+
}
|
|
70
|
+
continueResumableUpload(uploadId, dataRaw) {
|
|
71
|
+
const upload = this.getResumableUpload(uploadId);
|
|
72
|
+
if (upload.status !== UploadStatus.ACTIVE) {
|
|
73
|
+
throw new UploadNotActiveError();
|
|
74
|
+
}
|
|
75
|
+
this._persistence.appendBytes(upload.path, dataRaw);
|
|
76
|
+
upload.size += dataRaw.byteLength;
|
|
77
|
+
return upload;
|
|
78
|
+
}
|
|
79
|
+
getResumableUpload(uploadId) {
|
|
80
|
+
const upload = this._uploads.get(uploadId);
|
|
81
|
+
if (!upload || upload.type !== UploadType.RESUMABLE) {
|
|
82
|
+
throw new errors_1.NotFoundError();
|
|
83
|
+
}
|
|
84
|
+
return upload;
|
|
85
|
+
}
|
|
86
|
+
cancelResumableUpload(uploadId) {
|
|
87
|
+
const upload = this.getResumableUpload(uploadId);
|
|
88
|
+
if (upload.status === UploadStatus.FINISHED) {
|
|
89
|
+
throw new NotCancellableError();
|
|
90
|
+
}
|
|
91
|
+
upload.status = UploadStatus.CANCELLED;
|
|
92
|
+
return upload;
|
|
93
|
+
}
|
|
94
|
+
finalizeResumableUpload(uploadId) {
|
|
95
|
+
const upload = this.getResumableUpload(uploadId);
|
|
96
|
+
if (upload.status === UploadStatus.CANCELLED) {
|
|
97
|
+
throw new UploadNotActiveError();
|
|
98
|
+
}
|
|
99
|
+
upload.status = UploadStatus.FINISHED;
|
|
100
|
+
return upload;
|
|
101
|
+
}
|
|
102
|
+
getStagingFileName(uploadId, bucketId, objectId) {
|
|
103
|
+
return encodeURIComponent(`${uploadId}_b_${bucketId}_o_${objectId}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.UploadService = UploadService;
|
package/lib/emulator/types.js
CHANGED
|
@@ -13,6 +13,7 @@ var Emulators;
|
|
|
13
13
|
Emulators["UI"] = "ui";
|
|
14
14
|
Emulators["LOGGING"] = "logging";
|
|
15
15
|
Emulators["STORAGE"] = "storage";
|
|
16
|
+
Emulators["EXTENSIONS"] = "extensions";
|
|
16
17
|
})(Emulators = exports.Emulators || (exports.Emulators = {}));
|
|
17
18
|
exports.DOWNLOADABLE_EMULATORS = [
|
|
18
19
|
Emulators.FIRESTORE,
|
|
@@ -48,6 +49,7 @@ exports.EMULATORS_SUPPORTED_BY_UI = [
|
|
|
48
49
|
Emulators.FIRESTORE,
|
|
49
50
|
Emulators.FUNCTIONS,
|
|
50
51
|
Emulators.STORAGE,
|
|
52
|
+
Emulators.EXTENSIONS,
|
|
51
53
|
];
|
|
52
54
|
exports.EMULATORS_SUPPORTED_BY_USE_EMULATOR = [
|
|
53
55
|
Emulators.AUTH,
|
|
@@ -59,6 +61,7 @@ exports.ALL_EMULATORS = [
|
|
|
59
61
|
Emulators.HUB,
|
|
60
62
|
Emulators.UI,
|
|
61
63
|
Emulators.LOGGING,
|
|
64
|
+
Emulators.EXTENSIONS,
|
|
62
65
|
...exports.ALL_SERVICE_EMULATORS,
|
|
63
66
|
];
|
|
64
67
|
function isDownloadableEmulator(value) {
|
package/lib/ensureApiEnabled.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ensure = exports.check = exports.POLL_SETTINGS = void 0;
|
|
3
|
+
exports.enableApiURI = exports.ensure = exports.check = exports.POLL_SETTINGS = void 0;
|
|
4
4
|
const cli_color_1 = require("cli-color");
|
|
5
5
|
const track = require("./track");
|
|
6
6
|
const api_1 = require("./api");
|
|
@@ -75,3 +75,7 @@ async function ensure(projectId, apiName, prefix, silent = false) {
|
|
|
75
75
|
return enableApiWithRetries(projectId, apiName, prefix, silent);
|
|
76
76
|
}
|
|
77
77
|
exports.ensure = ensure;
|
|
78
|
+
function enableApiURI(projectId, apiName) {
|
|
79
|
+
return `https://console.cloud.google.com/apis/library/${apiName}?project=${projectId}`;
|
|
80
|
+
}
|
|
81
|
+
exports.enableApiURI = enableApiURI;
|
package/lib/error.js
CHANGED
|
@@ -23,7 +23,7 @@ function isBillingError(e) {
|
|
|
23
23
|
return !!((_d = (_c = (_b = (_a = e.context) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.details) === null || _d === void 0 ? void 0 : _d.find((d) => {
|
|
24
24
|
var _a;
|
|
25
25
|
return (((_a = d.violations) === null || _a === void 0 ? void 0 : _a.find((v) => v.type === "serviceusage/billing-enabled")) ||
|
|
26
|
-
d.reason
|
|
26
|
+
d.reason === "UREQ_PROJECT_BILLING_NOT_FOUND");
|
|
27
27
|
}));
|
|
28
28
|
}
|
|
29
29
|
exports.isBillingError = isBillingError;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getInquirerDefault = exports.promptCreateSecret = exports.askForParam = exports.ask = exports.checkResponse = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const clc = require("cli-color");
|
|
6
6
|
const { marked } = require("marked");
|
|
@@ -20,7 +20,7 @@ var SecretUpdateAction;
|
|
|
20
20
|
function checkResponse(response, spec) {
|
|
21
21
|
let valid = true;
|
|
22
22
|
let responses;
|
|
23
|
-
if (spec.required && (response
|
|
23
|
+
if (spec.required && (response === "" || response === undefined)) {
|
|
24
24
|
utils.logWarning(`Param ${spec.param} is required, but no value was provided.`);
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
@@ -55,7 +55,31 @@ function checkResponse(response, spec) {
|
|
|
55
55
|
return valid;
|
|
56
56
|
}
|
|
57
57
|
exports.checkResponse = checkResponse;
|
|
58
|
-
async function
|
|
58
|
+
async function ask(projectId, instanceId, paramSpecs, firebaseProjectParams, reconfiguring) {
|
|
59
|
+
if (_.isEmpty(paramSpecs)) {
|
|
60
|
+
logger_1.logger.debug("No params were specified for this extension.");
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
utils.logLabeledBullet(extensionsHelper_1.logPrefix, "answer the questions below to configure your extension:");
|
|
64
|
+
const substituted = (0, extensionsHelper_1.substituteParams)(paramSpecs, firebaseProjectParams);
|
|
65
|
+
const result = {};
|
|
66
|
+
const promises = _.map(substituted, (paramSpec) => {
|
|
67
|
+
return async () => {
|
|
68
|
+
result[paramSpec.param] = await askForParam({
|
|
69
|
+
projectId,
|
|
70
|
+
instanceId,
|
|
71
|
+
paramSpec,
|
|
72
|
+
reconfiguring,
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
await promises.reduce((prev, cur) => prev.then(cur), Promise.resolve());
|
|
77
|
+
logger_1.logger.info();
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
exports.ask = ask;
|
|
81
|
+
async function askForParam(args) {
|
|
82
|
+
const paramSpec = args.paramSpec;
|
|
59
83
|
let valid = false;
|
|
60
84
|
let response = "";
|
|
61
85
|
const description = paramSpec.description || "";
|
|
@@ -99,9 +123,9 @@ async function askForParam(projectId, instanceId, paramSpec, reconfiguring) {
|
|
|
99
123
|
valid = checkResponse(response, paramSpec);
|
|
100
124
|
break;
|
|
101
125
|
case extensionsApi_1.ParamType.SECRET:
|
|
102
|
-
response = reconfiguring
|
|
103
|
-
? await promptReconfigureSecret(projectId, instanceId, paramSpec)
|
|
104
|
-
: await promptCreateSecret(projectId, instanceId, paramSpec);
|
|
126
|
+
response = args.reconfiguring
|
|
127
|
+
? await promptReconfigureSecret(args.projectId, args.instanceId, paramSpec)
|
|
128
|
+
: await promptCreateSecret(args.projectId, args.instanceId, paramSpec);
|
|
105
129
|
valid = true;
|
|
106
130
|
break;
|
|
107
131
|
default:
|
|
@@ -114,7 +138,7 @@ async function askForParam(projectId, instanceId, paramSpec, reconfiguring) {
|
|
|
114
138
|
valid = checkResponse(response, paramSpec);
|
|
115
139
|
}
|
|
116
140
|
}
|
|
117
|
-
return response;
|
|
141
|
+
return { baseValue: response };
|
|
118
142
|
}
|
|
119
143
|
exports.askForParam = askForParam;
|
|
120
144
|
async function promptReconfigureSecret(projectId, instanceId, paramSpec) {
|
|
@@ -210,21 +234,3 @@ function getInquirerDefault(options, def) {
|
|
|
210
234
|
return defaultOption ? defaultOption.label || defaultOption.value : "";
|
|
211
235
|
}
|
|
212
236
|
exports.getInquirerDefault = getInquirerDefault;
|
|
213
|
-
async function ask(projectId, instanceId, paramSpecs, firebaseProjectParams, reconfiguring) {
|
|
214
|
-
if (_.isEmpty(paramSpecs)) {
|
|
215
|
-
logger_1.logger.debug("No params were specified for this extension.");
|
|
216
|
-
return {};
|
|
217
|
-
}
|
|
218
|
-
utils.logLabeledBullet(extensionsHelper_1.logPrefix, "answer the questions below to configure your extension:");
|
|
219
|
-
const substituted = (0, extensionsHelper_1.substituteParams)(paramSpecs, firebaseProjectParams);
|
|
220
|
-
const result = {};
|
|
221
|
-
const promises = _.map(substituted, (paramSpec) => {
|
|
222
|
-
return async () => {
|
|
223
|
-
result[paramSpec.param] = await askForParam(projectId, instanceId, paramSpec, reconfiguring);
|
|
224
|
-
};
|
|
225
|
-
});
|
|
226
|
-
await promises.reduce((prev, cur) => prev.then(cur), Promise.resolve());
|
|
227
|
-
logger_1.logger.info();
|
|
228
|
-
return result;
|
|
229
|
-
}
|
|
230
|
-
exports.ask = ask;
|
|
@@ -58,7 +58,9 @@ function breakingChangesInUpdate(versionsInUpdate) {
|
|
|
58
58
|
const semvers = versionsInUpdate.map((v) => semver.parse(v)).sort(semver.compare);
|
|
59
59
|
for (let i = 1; i < semvers.length; i++) {
|
|
60
60
|
const hasMajorBump = semvers[i - 1].major < semvers[i].major;
|
|
61
|
-
const hasMinorBumpInPreview = semvers[i - 1].major
|
|
61
|
+
const hasMinorBumpInPreview = semvers[i - 1].major === 0 &&
|
|
62
|
+
semvers[i].major === 0 &&
|
|
63
|
+
semvers[i - 1].minor < semvers[i].minor;
|
|
62
64
|
if (hasMajorBump || hasMinorBumpInPreview) {
|
|
63
65
|
breakingVersions.push(semvers[i].raw);
|
|
64
66
|
}
|
|
@@ -49,7 +49,7 @@ Please select the one that you would like to associate with this project:`,
|
|
|
49
49
|
billingEnabled = await openBillingAccount(projectId, billingURL, true);
|
|
50
50
|
}
|
|
51
51
|
else {
|
|
52
|
-
const billingAccount = accounts.find((a) => a.displayName
|
|
52
|
+
const billingAccount = accounts.find((a) => a.displayName === answer);
|
|
53
53
|
billingEnabled = await cloudbilling.setBillingAccount(projectId, billingAccount.name);
|
|
54
54
|
}
|
|
55
55
|
return logBillingStatus(billingEnabled, projectId);
|
|
@@ -136,7 +136,7 @@ async function displayUpdateChangesRequiringConfirmation(args) {
|
|
|
136
136
|
}
|
|
137
137
|
exports.displayUpdateChangesRequiringConfirmation = displayUpdateChangesRequiringConfirmation;
|
|
138
138
|
function compareResources(resource1, resource2) {
|
|
139
|
-
return resource1.name
|
|
139
|
+
return resource1.name === resource2.name && resource1.type === resource2.type;
|
|
140
140
|
}
|
|
141
141
|
function getResourceReadableName(resource) {
|
|
142
142
|
return resource.type === "firebaseextensions.v1beta.function"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getParams = exports.buildOptions = void 0;
|
|
3
|
+
exports.getParams = exports.getSecretEnvVars = exports.getNonSecretEnv = exports.getExtensionFunctionInfo = exports.buildOptions = void 0;
|
|
4
4
|
const fs = require("fs-extra");
|
|
5
5
|
const _ = require("lodash");
|
|
6
6
|
const path = require("path");
|
|
@@ -8,6 +8,7 @@ const paramHelper = require("../paramHelper");
|
|
|
8
8
|
const specHelper = require("./specHelper");
|
|
9
9
|
const localHelper = require("../localHelper");
|
|
10
10
|
const triggerHelper = require("./triggerHelper");
|
|
11
|
+
const extensionsApi_1 = require("../extensionsApi");
|
|
11
12
|
const extensionsHelper = require("../extensionsHelper");
|
|
12
13
|
const config_1 = require("../../config");
|
|
13
14
|
const error_1 = require("../../error");
|
|
@@ -15,9 +16,9 @@ const emulatorLogger_1 = require("../../emulator/emulatorLogger");
|
|
|
15
16
|
const projectUtils_1 = require("../../projectUtils");
|
|
16
17
|
const types_1 = require("../../emulator/types");
|
|
17
18
|
async function buildOptions(options) {
|
|
18
|
-
const
|
|
19
|
-
options.
|
|
20
|
-
const spec = await specHelper.readExtensionYaml(
|
|
19
|
+
const extDevDir = localHelper.findExtensionYaml(process.cwd());
|
|
20
|
+
options.extDevDir = extDevDir;
|
|
21
|
+
const spec = await specHelper.readExtensionYaml(extDevDir);
|
|
21
22
|
extensionsHelper.validateSpec(spec);
|
|
22
23
|
const params = getParams(options, spec);
|
|
23
24
|
extensionsHelper.validateCommandLineParams(params, spec.params);
|
|
@@ -28,13 +29,60 @@ async function buildOptions(options) {
|
|
|
28
29
|
checkTestConfig(testConfig, functionResources);
|
|
29
30
|
}
|
|
30
31
|
options.config = buildConfig(functionResources, testConfig);
|
|
31
|
-
options.
|
|
32
|
+
options.extDevEnv = params;
|
|
32
33
|
const functionEmuTriggerDefs = functionResources.map((r) => triggerHelper.functionResourceToEmulatedTriggerDefintion(r));
|
|
33
|
-
options.
|
|
34
|
-
options.
|
|
34
|
+
options.extDevTriggers = functionEmuTriggerDefs;
|
|
35
|
+
options.extDevNodeVersion = specHelper.getNodeVersion(functionResources);
|
|
35
36
|
return options;
|
|
36
37
|
}
|
|
37
38
|
exports.buildOptions = buildOptions;
|
|
39
|
+
async function getExtensionFunctionInfo(extensionDir, instanceId, paramValues) {
|
|
40
|
+
const spec = await specHelper.readExtensionYaml(extensionDir);
|
|
41
|
+
const functionResources = specHelper.getFunctionResourcesWithParamSubstitution(spec, paramValues);
|
|
42
|
+
const extensionTriggers = functionResources
|
|
43
|
+
.map((r) => triggerHelper.functionResourceToEmulatedTriggerDefintion(r))
|
|
44
|
+
.map((trigger) => {
|
|
45
|
+
trigger.name = `ext-${instanceId}-${trigger.name}`;
|
|
46
|
+
return trigger;
|
|
47
|
+
});
|
|
48
|
+
const nodeMajorVersion = specHelper.getNodeVersion(functionResources);
|
|
49
|
+
const nonSecretEnv = getNonSecretEnv(spec.params, paramValues);
|
|
50
|
+
const secretEnvVariables = getSecretEnvVars(spec.params, paramValues);
|
|
51
|
+
return {
|
|
52
|
+
extensionTriggers,
|
|
53
|
+
nodeMajorVersion,
|
|
54
|
+
nonSecretEnv,
|
|
55
|
+
secretEnvVariables,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
exports.getExtensionFunctionInfo = getExtensionFunctionInfo;
|
|
59
|
+
const isSecretParam = (p) => p.type === extensionsHelper.SpecParamType.SECRET || p.type === extensionsApi_1.ParamType.SECRET;
|
|
60
|
+
function getNonSecretEnv(params, paramValues) {
|
|
61
|
+
const getNonSecretEnv = Object.assign({}, paramValues);
|
|
62
|
+
const secretParams = params.filter(isSecretParam);
|
|
63
|
+
for (const p of secretParams) {
|
|
64
|
+
delete getNonSecretEnv[p.param];
|
|
65
|
+
}
|
|
66
|
+
return getNonSecretEnv;
|
|
67
|
+
}
|
|
68
|
+
exports.getNonSecretEnv = getNonSecretEnv;
|
|
69
|
+
function getSecretEnvVars(params, paramValues) {
|
|
70
|
+
const secretEnvVar = [];
|
|
71
|
+
const secretParams = params.filter(isSecretParam);
|
|
72
|
+
for (const s of secretParams) {
|
|
73
|
+
if (paramValues[s.param]) {
|
|
74
|
+
const [, projectId, , secret, , version] = paramValues[s.param].split("/");
|
|
75
|
+
secretEnvVar.push({
|
|
76
|
+
key: s.param,
|
|
77
|
+
secret,
|
|
78
|
+
projectId,
|
|
79
|
+
version,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return secretEnvVar;
|
|
84
|
+
}
|
|
85
|
+
exports.getSecretEnvVars = getSecretEnvVars;
|
|
38
86
|
function getParams(options, extensionSpec) {
|
|
39
87
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
40
88
|
const userParams = paramHelper.readEnvFile(options.testParams);
|
|
@@ -120,7 +168,7 @@ function getFunctionSourceDirectory(functionResources) {
|
|
|
120
168
|
if (!sourceDirectory) {
|
|
121
169
|
sourceDirectory = dir;
|
|
122
170
|
}
|
|
123
|
-
else if (sourceDirectory
|
|
171
|
+
else if (sourceDirectory !== dir) {
|
|
124
172
|
throw new error_1.FirebaseError(`Found function resources with different sourceDirectories: '${sourceDirectory}' and '${dir}'. The extensions emulator only supports a single sourceDirectory.`);
|
|
125
173
|
}
|
|
126
174
|
}
|
|
@@ -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,
|