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