firebase-tools 10.6.0 → 10.7.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/command.js +4 -4
- package/lib/commands/deploy.js +1 -1
- package/lib/commands/emulators-start.js +7 -2
- package/lib/commands/ext-configure.js +15 -5
- package/lib/commands/ext-export.js +6 -5
- package/lib/commands/ext-install.js +28 -44
- package/lib/commands/ext-update.js +9 -1
- package/lib/commands/functions-delete.js +7 -3
- package/lib/commands/hosting-channel-deploy.js +2 -2
- package/lib/deploy/database/deploy.js +4 -0
- package/lib/deploy/database/index.js +1 -0
- package/lib/deploy/extensions/deploy.js +4 -4
- package/lib/deploy/extensions/deploymentSummary.js +8 -5
- package/lib/deploy/extensions/planner.js +36 -9
- package/lib/deploy/extensions/prepare.js +1 -1
- package/lib/deploy/extensions/secrets.js +2 -2
- package/lib/deploy/extensions/tasks.js +60 -21
- package/lib/deploy/functions/backend.js +37 -2
- package/lib/deploy/functions/build.js +173 -0
- package/lib/deploy/functions/checkIam.js +11 -14
- package/lib/deploy/functions/containerCleaner.js +8 -7
- package/lib/deploy/functions/deploy.js +49 -28
- package/lib/deploy/functions/ensure.js +4 -4
- package/lib/deploy/functions/functionsDeployHelper.js +99 -24
- package/lib/deploy/functions/prepare.js +129 -71
- package/lib/deploy/functions/prepareFunctionsUpload.js +16 -21
- package/lib/deploy/functions/pricing.js +6 -3
- package/lib/deploy/functions/prompts.js +1 -7
- package/lib/deploy/functions/release/executor.js +1 -1
- package/lib/deploy/functions/release/fabricator.js +69 -25
- package/lib/deploy/functions/release/index.js +20 -6
- package/lib/deploy/functions/release/planner.js +18 -10
- package/lib/deploy/functions/release/reporter.js +14 -11
- package/lib/deploy/functions/runtimes/discovery/parsing.js +12 -6
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +50 -3
- package/lib/deploy/functions/runtimes/golang/index.js +3 -0
- package/lib/deploy/functions/runtimes/node/index.js +7 -0
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +3 -3
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +132 -6
- package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
- package/lib/deploy/functions/services/auth.js +95 -0
- package/lib/deploy/functions/services/index.js +41 -21
- package/lib/deploy/functions/validate.js +33 -7
- package/lib/deploy/hosting/args.js +2 -0
- package/lib/deploy/hosting/convertConfig.js +39 -8
- package/lib/deploy/hosting/deploy.js +3 -3
- package/lib/deploy/hosting/prepare.js +2 -2
- package/lib/deploy/hosting/release.js +6 -2
- package/lib/deploy/index.js +82 -93
- package/lib/deploy/remoteconfig/deploy.js +4 -0
- package/lib/deploy/remoteconfig/index.js +3 -1
- package/lib/emulator/auth/cloudFunctions.js +6 -2
- package/lib/emulator/auth/operations.js +5 -1
- package/lib/emulator/auth/server.js +8 -1
- package/lib/emulator/auth/state.js +27 -24
- package/lib/emulator/auth/utils.js +3 -25
- package/lib/emulator/controller.js +17 -14
- package/lib/emulator/databaseEmulator.js +36 -3
- package/lib/emulator/downloadableEmulators.js +39 -23
- package/lib/emulator/extensions/validation.js +2 -2
- package/lib/emulator/extensionsEmulator.js +85 -21
- package/lib/emulator/functionsEmulator.js +89 -15
- package/lib/emulator/functionsEmulatorRuntime.js +1 -1
- package/lib/emulator/functionsEmulatorShared.js +25 -2
- package/lib/emulator/functionsEmulatorShell.js +2 -3
- package/lib/emulator/functionsEmulatorUtils.js +5 -1
- package/lib/emulator/pubsubEmulator.js +13 -9
- package/lib/emulator/registry.js +34 -12
- package/lib/emulator/storage/apis/firebase.js +33 -6
- package/lib/emulator/storage/apis/gcloud.js +6 -3
- package/lib/emulator/storage/files.js +9 -1
- package/lib/ensureApiEnabled.js +8 -4
- package/lib/extensions/changelog.js +1 -1
- package/lib/extensions/emulator/optionsHelper.js +4 -3
- package/lib/extensions/emulator/specHelper.js +7 -1
- package/lib/extensions/extensionsHelper.js +30 -24
- package/lib/extensions/manifest.js +27 -7
- package/lib/extensions/paramHelper.js +7 -5
- package/lib/extensions/provisioningHelper.js +2 -2
- package/lib/extensions/warnings.js +11 -4
- package/lib/functions/events/index.js +7 -0
- package/lib/functions/events/v1.js +6 -0
- package/lib/functions/projectConfig.js +32 -6
- package/lib/functionsShellCommandAction.js +1 -1
- package/lib/gcp/cloudfunctions.js +38 -5
- package/lib/gcp/cloudfunctionsv2.js +46 -7
- package/lib/gcp/identityPlatform.js +44 -0
- package/lib/gcp/secretManager.js +1 -1
- package/lib/metaprogramming.js +2 -0
- package/lib/previews.js +1 -1
- package/lib/serve/functions.js +16 -19
- package/lib/serve/hosting.js +25 -12
- package/lib/serve/index.js +6 -0
- package/lib/track.js +15 -21
- package/npm-shrinkwrap.json +256 -527
- package/package.json +6 -3
- package/schema/firebase-config.json +6 -0
package/lib/command.js
CHANGED
|
@@ -9,7 +9,7 @@ const rc_1 = require("./rc");
|
|
|
9
9
|
const config_1 = require("./config");
|
|
10
10
|
const configstore_1 = require("./configstore");
|
|
11
11
|
const detectProjectRoot_1 = require("./detectProjectRoot");
|
|
12
|
-
const
|
|
12
|
+
const track_1 = require("./track");
|
|
13
13
|
const clc = require("cli-color");
|
|
14
14
|
const auth_1 = require("./auth");
|
|
15
15
|
const projects_1 = require("./management/projects");
|
|
@@ -85,7 +85,7 @@ class Command {
|
|
|
85
85
|
}, null, 2));
|
|
86
86
|
}
|
|
87
87
|
const duration = new Date().getTime() - start;
|
|
88
|
-
void track(this.name, "success", duration).then(() => process.exit());
|
|
88
|
+
void (0, track_1.track)(this.name, "success", duration).then(() => process.exit());
|
|
89
89
|
})
|
|
90
90
|
.catch(async (err) => {
|
|
91
91
|
if ((0, utils_1.getInheritedOption)(options, "json")) {
|
|
@@ -96,7 +96,7 @@ class Command {
|
|
|
96
96
|
}
|
|
97
97
|
const duration = Date.now() - start;
|
|
98
98
|
const errorEvent = err.exit === 1 ? "Error (User)" : "Error (Unexpected)";
|
|
99
|
-
await Promise.all([track(this.name, "error", duration), track(errorEvent, "", duration)]);
|
|
99
|
+
await Promise.all([(0, track_1.track)(this.name, "error", duration), (0, track_1.track)(errorEvent, "", duration)]);
|
|
100
100
|
client.errorOut(err);
|
|
101
101
|
});
|
|
102
102
|
});
|
|
@@ -197,7 +197,7 @@ function validateProjectId(project) {
|
|
|
197
197
|
if (PROJECT_ID_REGEX.test(project)) {
|
|
198
198
|
return;
|
|
199
199
|
}
|
|
200
|
-
track("Project ID Check", "invalid");
|
|
200
|
+
(0, track_1.track)("Project ID Check", "invalid");
|
|
201
201
|
const invalidMessage = "Invalid project id: " + clc.bold(project) + ".";
|
|
202
202
|
if (project.toLowerCase() !== project) {
|
|
203
203
|
throw new error_1.FirebaseError(invalidMessage + "\nNote: Project id must be all lowercase.");
|
package/lib/commands/deploy.js
CHANGED
|
@@ -5,7 +5,7 @@ const { requirePermissions } = require("../requirePermissions");
|
|
|
5
5
|
const { checkServiceAccountIam } = require("../deploy/functions/checkIam");
|
|
6
6
|
const checkValidTargetFilters = require("../checkValidTargetFilters");
|
|
7
7
|
const { Command } = require("../command");
|
|
8
|
-
const deploy = require("../deploy");
|
|
8
|
+
const { deploy } = require("../deploy");
|
|
9
9
|
const { requireConfig } = require("../requireConfig");
|
|
10
10
|
const { filterTargets } = require("../filterTargets");
|
|
11
11
|
const { requireHostingSite } = require("../requireHostingSite");
|
|
@@ -63,7 +63,7 @@ module.exports = new command_1.Command("emulators:start")
|
|
|
63
63
|
.map((emulator) => {
|
|
64
64
|
const emulatorName = constants_1.Constants.description(emulator).replace(/ emulator/i, "");
|
|
65
65
|
const isSupportedByUi = types_1.EMULATORS_SUPPORTED_BY_UI.includes(emulator);
|
|
66
|
-
const info = registry_1.EmulatorRegistry.getInfo(emulator
|
|
66
|
+
const info = registry_1.EmulatorRegistry.getInfo(emulator);
|
|
67
67
|
if (!info) {
|
|
68
68
|
return [emulatorName, "Failed to initialize (see above)", "", ""];
|
|
69
69
|
}
|
|
@@ -77,6 +77,11 @@ module.exports = new command_1.Command("emulators:start")
|
|
|
77
77
|
})
|
|
78
78
|
.map((col) => col.slice(0, head.length))
|
|
79
79
|
.filter((v) => v));
|
|
80
|
+
let extensionsTable = "";
|
|
81
|
+
if (registry_1.EmulatorRegistry.isRunning(types_1.Emulators.EXTENSIONS)) {
|
|
82
|
+
const extensionsEmulatorInstance = registry_1.EmulatorRegistry.get(types_1.Emulators.EXTENSIONS);
|
|
83
|
+
extensionsTable = extensionsEmulatorInstance.extensionsInfoTable(options);
|
|
84
|
+
}
|
|
80
85
|
logger_1.logger.info(`\n${successMessageTable}
|
|
81
86
|
|
|
82
87
|
${emulatorsTable}
|
|
@@ -84,7 +89,7 @@ ${hubInfo
|
|
|
84
89
|
? clc.blackBright(" Emulator Hub running at ") + registry_1.EmulatorRegistry.getInfoHostString(hubInfo)
|
|
85
90
|
: clc.blackBright(" Emulator Hub not running.")}
|
|
86
91
|
${clc.blackBright(" Other reserved ports:")} ${reservedPortsString}
|
|
87
|
-
|
|
92
|
+
${extensionsTable}
|
|
88
93
|
Issues? Report them at ${stylizeLink("https://github.com/firebase/firebase-tools/issues")} and attach the *-debug.log files.
|
|
89
94
|
`);
|
|
90
95
|
for (const notice of deprecationNotices) {
|
|
@@ -41,13 +41,22 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
|
|
|
41
41
|
throw new error_1.FirebaseError(`Command not supported in non-interactive mode, edit ./extensions/${instanceId}.env directly instead`);
|
|
42
42
|
}
|
|
43
43
|
const config = manifest.loadConfig(options);
|
|
44
|
-
const
|
|
45
|
-
const
|
|
44
|
+
const refOrPath = manifest.getInstanceTarget(instanceId, config);
|
|
45
|
+
const isLocalSource = (0, extensionsHelper_1.isLocalPath)(refOrPath);
|
|
46
|
+
let spec;
|
|
47
|
+
if (isLocalSource) {
|
|
48
|
+
const source = await (0, extensionsHelper_1.createSourceFromLocation)((0, projectUtils_1.needProjectId)({ projectId }), refOrPath);
|
|
49
|
+
spec = source.spec;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const extensionVersion = await extensionsApi.getExtensionVersion(refOrPath);
|
|
53
|
+
spec = extensionVersion.spec;
|
|
54
|
+
}
|
|
46
55
|
const oldParamValues = manifest.readInstanceParam({
|
|
47
56
|
instanceId,
|
|
48
57
|
projectDir: config.projectDir,
|
|
49
58
|
});
|
|
50
|
-
const [immutableParams, tbdParams] = (0, functional_1.partition)(
|
|
59
|
+
const [immutableParams, tbdParams] = (0, functional_1.partition)(spec.params, (param) => { var _a; return (_a = param.immutable) !== null && _a !== void 0 ? _a : false; });
|
|
51
60
|
infoImmutableParams(immutableParams, oldParamValues);
|
|
52
61
|
paramHelper.setNewDefaults(tbdParams, oldParamValues);
|
|
53
62
|
const mutableParamsBindingOptions = await paramHelper.getParams({
|
|
@@ -62,9 +71,10 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
|
|
|
62
71
|
await manifest.writeToManifest([
|
|
63
72
|
{
|
|
64
73
|
instanceId,
|
|
65
|
-
ref:
|
|
74
|
+
ref: !isLocalSource ? refs.parse(refOrPath) : undefined,
|
|
75
|
+
localPath: isLocalSource ? refOrPath : undefined,
|
|
66
76
|
params: newParamOptions,
|
|
67
|
-
|
|
77
|
+
extensionSpec: spec,
|
|
68
78
|
},
|
|
69
79
|
], config, {
|
|
70
80
|
nonInteractive: false,
|
|
@@ -22,16 +22,17 @@ module.exports = new command_1.Command("ext:export")
|
|
|
22
22
|
.action(async (options) => {
|
|
23
23
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
24
24
|
const projectNumber = await (0, getProjectNumber_1.getProjectNumber)(options);
|
|
25
|
-
const have = await Promise.all(
|
|
26
|
-
const subbed = await (0, export_1.setSecretParamsToLatest)(i);
|
|
27
|
-
return (0, export_1.parameterizeProject)(projectId, projectNumber, subbed);
|
|
28
|
-
}));
|
|
25
|
+
const have = await Promise.all(await planner.have(projectId));
|
|
29
26
|
if (have.length === 0) {
|
|
30
27
|
logger_1.logger.info(`No extension instances installed on ${projectId}, so there is nothing to export.`);
|
|
31
28
|
return;
|
|
32
29
|
}
|
|
33
30
|
const [withRef, withoutRef] = (0, functional_1.partition)(have, (s) => !!s.ref);
|
|
34
|
-
|
|
31
|
+
const withRefSubbed = await Promise.all(withRef.map(async (i) => {
|
|
32
|
+
const subbed = await (0, export_1.setSecretParamsToLatest)(i);
|
|
33
|
+
return (0, export_1.parameterizeProject)(projectId, projectNumber, subbed);
|
|
34
|
+
}));
|
|
35
|
+
(0, export_1.displayExportInfo)(withRefSubbed, withoutRef);
|
|
35
36
|
if (!options.nonInteractive &&
|
|
36
37
|
!options.force &&
|
|
37
38
|
!(await (0, prompt_1.promptOnce)({
|
|
@@ -46,7 +46,7 @@ exports.default = new command_1.Command("ext:install [extensionName]")
|
|
|
46
46
|
.before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
|
|
47
47
|
.before(extensionsHelper_1.diagnoseAndFixProject)
|
|
48
48
|
.action(async (extensionName, options) => {
|
|
49
|
-
var _a;
|
|
49
|
+
var _a, _b;
|
|
50
50
|
const projectId = (0, projectUtils_1.getProjectId)(options);
|
|
51
51
|
const paramsEnvPath = ((_a = options.params) !== null && _a !== void 0 ? _a : "");
|
|
52
52
|
let learnMore = false;
|
|
@@ -62,20 +62,23 @@ exports.default = new command_1.Command("ext:install [extensionName]")
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
let source;
|
|
65
|
-
let
|
|
65
|
+
let extensionVersion;
|
|
66
66
|
if ((0, extensionsHelper_1.isUrlPath)(extensionName)) {
|
|
67
|
-
|
|
67
|
+
throw new error_1.FirebaseError(`Installing with a source url is no longer supported in the CLI. Please use Firebase Console instead.`);
|
|
68
68
|
}
|
|
69
|
-
if ((0, extensionsHelper_1.
|
|
69
|
+
if ((0, extensionsHelper_1.isLocalPath)(extensionName)) {
|
|
70
|
+
source = await (0, extensionsHelper_1.createSourceFromLocation)((0, projectUtils_1.needProjectId)({ projectId }), extensionName);
|
|
71
|
+
(0, displayExtensionInfo_1.displayExtInfo)(extensionName, "", source.spec);
|
|
70
72
|
void (0, track_1.track)("Extension Install", "Install by Source", options.interactive ? 1 : 0);
|
|
71
|
-
if (options.local) {
|
|
72
|
-
throw new error_1.FirebaseError("Installing a local source locally is not supported yet, please use ext:dev:emulator commands");
|
|
73
|
-
}
|
|
74
|
-
source = await infoInstallBySource((0, projectUtils_1.needProjectId)({ projectId }), extensionName);
|
|
75
73
|
}
|
|
76
74
|
else {
|
|
77
75
|
void (0, track_1.track)("Extension Install", "Install by Extension Ref", options.interactive ? 1 : 0);
|
|
78
|
-
|
|
76
|
+
extensionName = (0, extensionsHelper_1.canonicalizeRefInput)(extensionName);
|
|
77
|
+
extensionVersion = await extensionsApi.getExtensionVersion(extensionName);
|
|
78
|
+
await infoExtensionVersion({
|
|
79
|
+
extensionName,
|
|
80
|
+
extensionVersion,
|
|
81
|
+
});
|
|
79
82
|
}
|
|
80
83
|
if (!(await (0, extensionsHelper_1.confirm)({
|
|
81
84
|
nonInteractive: options.nonInteractive,
|
|
@@ -84,10 +87,10 @@ exports.default = new command_1.Command("ext:install [extensionName]")
|
|
|
84
87
|
}))) {
|
|
85
88
|
return;
|
|
86
89
|
}
|
|
87
|
-
if (!source && !
|
|
90
|
+
if (!source && !extensionVersion) {
|
|
88
91
|
throw new error_1.FirebaseError("Could not find a source. Please specify a valid source to continue.");
|
|
89
92
|
}
|
|
90
|
-
const spec = (source === null || source === void 0 ? void 0 : source.spec)
|
|
93
|
+
const spec = (_b = source === null || source === void 0 ? void 0 : source.spec) !== null && _b !== void 0 ? _b : extensionVersion === null || extensionVersion === void 0 ? void 0 : extensionVersion.spec;
|
|
91
94
|
if (!spec) {
|
|
92
95
|
throw new error_1.FirebaseError(`Could not find the extension.yaml for extension '${clc.bold(extensionName)}'. Please make sure this is a valid extension and try again.`);
|
|
93
96
|
}
|
|
@@ -103,7 +106,7 @@ exports.default = new command_1.Command("ext:install [extensionName]")
|
|
|
103
106
|
projectId,
|
|
104
107
|
extensionName,
|
|
105
108
|
source,
|
|
106
|
-
extVersion,
|
|
109
|
+
extVersion: extensionVersion,
|
|
107
110
|
nonInteractive: options.nonInteractive,
|
|
108
111
|
force: options.force,
|
|
109
112
|
});
|
|
@@ -123,7 +126,7 @@ exports.default = new command_1.Command("ext:install [extensionName]")
|
|
|
123
126
|
projectId: projectId,
|
|
124
127
|
extensionName,
|
|
125
128
|
source,
|
|
126
|
-
extVersion,
|
|
129
|
+
extVersion: extensionVersion,
|
|
127
130
|
nonInteractive: options.nonInteractive,
|
|
128
131
|
force: options.force,
|
|
129
132
|
});
|
|
@@ -137,37 +140,17 @@ exports.default = new command_1.Command("ext:install [extensionName]")
|
|
|
137
140
|
throw err;
|
|
138
141
|
}
|
|
139
142
|
});
|
|
140
|
-
async function
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
source = await (0, extensionsHelper_1.createSourceFromLocation)(projectId, extensionName);
|
|
144
|
-
}
|
|
145
|
-
catch (err) {
|
|
146
|
-
throw new error_1.FirebaseError(`Unable to find published extension '${clc.bold(extensionName)}', ` +
|
|
147
|
-
`and encountered the following error when trying to create an instance of extension '${clc.bold(extensionName)}':\n ${err.message}`);
|
|
148
|
-
}
|
|
149
|
-
(0, displayExtensionInfo_1.displayExtInfo)(extensionName, "", source.spec);
|
|
150
|
-
return source;
|
|
151
|
-
}
|
|
152
|
-
async function infoInstallByReference(extensionName, interactive) {
|
|
153
|
-
if (extensionName.split("/").length < 2) {
|
|
154
|
-
const [extensionID, version] = extensionName.split("@");
|
|
155
|
-
extensionName = `firebase/${extensionID}@${version || "latest"}`;
|
|
156
|
-
}
|
|
157
|
-
const ref = refs.parse(extensionName);
|
|
143
|
+
async function infoExtensionVersion(args) {
|
|
144
|
+
const ref = refs.parse(args.extensionName);
|
|
158
145
|
const extension = await extensionsApi.getExtension(refs.toExtensionRef(ref));
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
extensionName = `${extensionName}@latest`;
|
|
162
|
-
}
|
|
163
|
-
const extVersion = await extensionsApi.getExtensionVersion(extensionName);
|
|
164
|
-
(0, displayExtensionInfo_1.displayExtInfo)(extensionName, ref.publisherId, extVersion.spec, true);
|
|
165
|
-
await (0, warnings_1.displayWarningPrompts)(ref.publisherId, extension.registryLaunchStage, extVersion);
|
|
166
|
-
return extVersion;
|
|
146
|
+
(0, displayExtensionInfo_1.displayExtInfo)(args.extensionName, ref.publisherId, args.extensionVersion.spec, true);
|
|
147
|
+
await (0, warnings_1.displayWarningPrompts)(ref.publisherId, extension.registryLaunchStage, args.extensionVersion);
|
|
167
148
|
}
|
|
168
149
|
async function installToManifest(options) {
|
|
169
|
-
|
|
170
|
-
const
|
|
150
|
+
var _a;
|
|
151
|
+
const { projectId, extensionName, extVersion, source, paramsEnvPath, nonInteractive, force } = options;
|
|
152
|
+
const isLocalSource = (0, extensionsHelper_1.isLocalPath)(extensionName);
|
|
153
|
+
const spec = (_a = extVersion === null || extVersion === void 0 ? void 0 : extVersion.spec) !== null && _a !== void 0 ? _a : source === null || source === void 0 ? void 0 : source.spec;
|
|
171
154
|
if (!spec) {
|
|
172
155
|
throw new error_1.FirebaseError(`Could not find the extension.yaml for ${extensionName}. Please make sure this is a valid extension and try again.`);
|
|
173
156
|
}
|
|
@@ -183,13 +166,14 @@ async function installToManifest(options) {
|
|
|
183
166
|
paramsEnvPath,
|
|
184
167
|
instanceId,
|
|
185
168
|
});
|
|
186
|
-
const ref = refs.parse(extVersion.ref);
|
|
169
|
+
const ref = extVersion ? refs.parse(extVersion.ref) : undefined;
|
|
187
170
|
await manifest.writeToManifest([
|
|
188
171
|
{
|
|
189
172
|
instanceId,
|
|
190
|
-
ref,
|
|
173
|
+
ref: !isLocalSource ? ref : undefined,
|
|
174
|
+
localPath: isLocalSource ? extensionName : undefined,
|
|
191
175
|
params: paramBindingOptions,
|
|
192
|
-
|
|
176
|
+
extensionSpec: spec,
|
|
193
177
|
},
|
|
194
178
|
], config, { nonInteractive, force: force !== null && force !== void 0 ? force : false });
|
|
195
179
|
manifest.showPreviewWarning();
|
|
@@ -45,6 +45,13 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
45
45
|
if (options.local) {
|
|
46
46
|
const projectId = (0, projectUtils_1.getProjectId)(options);
|
|
47
47
|
const config = manifest.loadConfig(options);
|
|
48
|
+
const oldRefOrPath = manifest.getInstanceTarget(instanceId, config);
|
|
49
|
+
if ((0, extensionsHelper_1.isLocalPath)(oldRefOrPath)) {
|
|
50
|
+
throw new error_1.FirebaseError(`Updating an extension with local source is not neccessary. ` +
|
|
51
|
+
`Rerun "firebase deploy" or restart the emulator after making changes to your local extension source. ` +
|
|
52
|
+
`If you've edited the extension param spec, you can edit an extension instance's params ` +
|
|
53
|
+
`interactively by running "firebase ext:configure --local {instance-id}"`);
|
|
54
|
+
}
|
|
48
55
|
const oldRef = manifest.getInstanceRef(instanceId, config);
|
|
49
56
|
const oldExtensionVersion = await extensionsApi.getExtensionVersion(refs.toExtensionVersionRef(oldRef));
|
|
50
57
|
updateSource = (0, updateHelper_1.inferUpdateSource)(updateSource, refs.toExtensionRef(oldRef));
|
|
@@ -84,7 +91,8 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
84
91
|
instanceId,
|
|
85
92
|
ref: refs.parse(newExtensionVersion.ref),
|
|
86
93
|
params: newParamBindingOptions,
|
|
87
|
-
|
|
94
|
+
extensionSpec: newExtensionVersion.spec,
|
|
95
|
+
extensionVersion: newExtensionVersion,
|
|
88
96
|
},
|
|
89
97
|
], config, {
|
|
90
98
|
nonInteractive: options.nonInteractive,
|
|
@@ -29,7 +29,7 @@ exports.default = new command_1.Command("functions:delete [filters...]")
|
|
|
29
29
|
}
|
|
30
30
|
const context = {
|
|
31
31
|
projectId: (0, projectUtils_1.needProjectId)(options),
|
|
32
|
-
filters: filters.map((f) => f.split(".")),
|
|
32
|
+
filters: filters.map((f) => ({ idChunks: f.split(".") })),
|
|
33
33
|
};
|
|
34
34
|
const [config, existingBackend] = await Promise.all([
|
|
35
35
|
functionsConfig.getFirebaseConfig(options),
|
|
@@ -40,7 +40,10 @@ exports.default = new command_1.Command("functions:delete [filters...]")
|
|
|
40
40
|
if (options.region) {
|
|
41
41
|
existingBackend.endpoints = { [options.region]: existingBackend.endpoints[options.region] };
|
|
42
42
|
}
|
|
43
|
-
const plan = planner.createDeploymentPlan(
|
|
43
|
+
const plan = planner.createDeploymentPlan({
|
|
44
|
+
wantBackend: backend.empty(),
|
|
45
|
+
haveBackend: existingBackend,
|
|
46
|
+
codebase: "",
|
|
44
47
|
filters: context.filters,
|
|
45
48
|
deleteAll: true,
|
|
46
49
|
});
|
|
@@ -72,8 +75,9 @@ exports.default = new command_1.Command("functions:delete [filters...]")
|
|
|
72
75
|
try {
|
|
73
76
|
const fab = new fabricator.Fabricator({
|
|
74
77
|
functionExecutor,
|
|
75
|
-
executor: new executor.QueueExecutor({}),
|
|
76
78
|
appEngineLocation,
|
|
79
|
+
executor: new executor.QueueExecutor({}),
|
|
80
|
+
sources: {},
|
|
77
81
|
});
|
|
78
82
|
const summary = await fab.applyPlan(plan);
|
|
79
83
|
await reporter.logAndTrackDeployStats(summary);
|
|
@@ -6,7 +6,7 @@ const error_1 = require("../error");
|
|
|
6
6
|
const api_1 = require("../hosting/api");
|
|
7
7
|
const normalizedHostingConfigs_1 = require("../hosting/normalizedHostingConfigs");
|
|
8
8
|
const requirePermissions_1 = require("../requirePermissions");
|
|
9
|
-
const
|
|
9
|
+
const deploy_1 = require("../deploy");
|
|
10
10
|
const projectUtils_1 = require("../projectUtils");
|
|
11
11
|
const logger_1 = require("../logger");
|
|
12
12
|
const requireConfig_1 = require("../requireConfig");
|
|
@@ -82,7 +82,7 @@ exports.default = new command_1.Command("hosting:channel:deploy [channelId]")
|
|
|
82
82
|
siteInfo.expireTime = chan.expireTime;
|
|
83
83
|
return;
|
|
84
84
|
}));
|
|
85
|
-
const { hosting } = await deploy(["hosting"], options, { hostingChannel: channelId });
|
|
85
|
+
const { hosting } = await (0, deploy_1.deploy)(["hosting"], options, { hostingChannel: channelId });
|
|
86
86
|
const versionNames = [];
|
|
87
87
|
if (typeof hosting === "string") {
|
|
88
88
|
versionNames.push(hosting);
|
|
@@ -10,7 +10,7 @@ const provisioningHelper_1 = require("../../extensions/provisioningHelper");
|
|
|
10
10
|
const secrets_1 = require("./secrets");
|
|
11
11
|
const validate_1 = require("./validate");
|
|
12
12
|
async function deploy(context, options, payload) {
|
|
13
|
-
var _a, _b, _c, _d, _e, _f;
|
|
13
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
14
14
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
15
15
|
await (0, validate_1.checkBilling)(projectId, options.nonInteractive);
|
|
16
16
|
await (0, provisioningHelper_1.bulkCheckProductsProvisioned)(projectId, [
|
|
@@ -25,15 +25,15 @@ async function deploy(context, options, payload) {
|
|
|
25
25
|
concurrency: 5,
|
|
26
26
|
handler: tasks.extensionsDeploymentHandler(errorHandler),
|
|
27
27
|
});
|
|
28
|
-
for (const create of (_d = payload.instancesToCreate) !== null &&
|
|
28
|
+
for (const create of (_e = (_d = payload.instancesToCreate) === null || _d === void 0 ? void 0 : _d.filter((i) => !!i.ref)) !== null && _e !== void 0 ? _e : []) {
|
|
29
29
|
const task = tasks.createExtensionInstanceTask(projectId, create, true);
|
|
30
30
|
void validationQueue.run(task);
|
|
31
31
|
}
|
|
32
|
-
for (const update of (
|
|
32
|
+
for (const update of (_g = (_f = payload.instancesToUpdate) === null || _f === void 0 ? void 0 : _f.filter((i) => !!i.ref)) !== null && _g !== void 0 ? _g : []) {
|
|
33
33
|
const task = tasks.updateExtensionInstanceTask(projectId, update, true);
|
|
34
34
|
void validationQueue.run(task);
|
|
35
35
|
}
|
|
36
|
-
for (const configure of (
|
|
36
|
+
for (const configure of (_j = (_h = payload.instancesToConfigure) === null || _h === void 0 ? void 0 : _h.filter((i) => !!i.ref)) !== null && _j !== void 0 ? _j : []) {
|
|
37
37
|
const task = tasks.configureExtensionInstanceTask(projectId, configure, true);
|
|
38
38
|
void validationQueue.run(task);
|
|
39
39
|
}
|
|
@@ -6,16 +6,19 @@ const refs = require("../../extensions/refs");
|
|
|
6
6
|
const humanReadable = (dep) => `${clc.bold(dep.instanceId)} (${dep.ref ? `${refs.toExtensionVersionRef(dep.ref)}` : `Installed from local source`})`;
|
|
7
7
|
exports.humanReadable = humanReadable;
|
|
8
8
|
const humanReadableUpdate = (from, to) => {
|
|
9
|
-
var _a
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
var _a;
|
|
10
|
+
if (from.ref &&
|
|
11
|
+
to.ref &&
|
|
12
|
+
from.ref.publisherId === to.ref.publisherId &&
|
|
13
|
+
from.ref.extensionId === to.ref.extensionId) {
|
|
14
|
+
return `\t${clc.bold(from.instanceId)} (${refs.toExtensionVersionRef(from.ref)} => ${(_a = to.ref) === null || _a === void 0 ? void 0 : _a.version})`;
|
|
13
15
|
}
|
|
14
16
|
else {
|
|
15
17
|
const fromRef = from.ref
|
|
16
18
|
? `${refs.toExtensionVersionRef(from.ref)}`
|
|
17
19
|
: `Installed from local source`;
|
|
18
|
-
|
|
20
|
+
const toRef = to.ref ? `${refs.toExtensionVersionRef(to.ref)}` : `Installed from local source`;
|
|
21
|
+
return `\t${clc.bold(from.instanceId)} (${fromRef} => ${toRef})`;
|
|
19
22
|
}
|
|
20
23
|
};
|
|
21
24
|
function createsSummary(toCreate) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveVersion = exports.want = exports.have = exports.getExtension = exports.getExtensionVersion = void 0;
|
|
3
|
+
exports.resolveVersion = exports.want = exports.have = exports.getExtensionSpec = exports.getExtension = exports.getExtensionVersion = void 0;
|
|
4
4
|
const semver = require("semver");
|
|
5
5
|
const extensionsApi = require("../../extensions/extensionsApi");
|
|
6
6
|
const refs = require("../../extensions/refs");
|
|
@@ -8,6 +8,7 @@ const error_1 = require("../../error");
|
|
|
8
8
|
const extensionsHelper_1 = require("../../extensions/extensionsHelper");
|
|
9
9
|
const logger_1 = require("../../logger");
|
|
10
10
|
const manifest_1 = require("../../extensions/manifest");
|
|
11
|
+
const specHelper_1 = require("../../extensions/emulator/specHelper");
|
|
11
12
|
async function getExtensionVersion(i) {
|
|
12
13
|
if (!i.extensionVersion) {
|
|
13
14
|
if (!i.ref) {
|
|
@@ -20,7 +21,7 @@ async function getExtensionVersion(i) {
|
|
|
20
21
|
exports.getExtensionVersion = getExtensionVersion;
|
|
21
22
|
async function getExtension(i) {
|
|
22
23
|
if (!i.ref) {
|
|
23
|
-
throw new error_1.FirebaseError(`Can't get
|
|
24
|
+
throw new error_1.FirebaseError(`Can't get Extension for ${i.instanceId} because it has no ref`);
|
|
24
25
|
}
|
|
25
26
|
if (!i.extension) {
|
|
26
27
|
i.extension = await extensionsApi.getExtension(refs.toExtensionRef(i.ref));
|
|
@@ -28,6 +29,23 @@ async function getExtension(i) {
|
|
|
28
29
|
return i.extension;
|
|
29
30
|
}
|
|
30
31
|
exports.getExtension = getExtension;
|
|
32
|
+
async function getExtensionSpec(i) {
|
|
33
|
+
if (!i.extensionSpec) {
|
|
34
|
+
if (i.ref) {
|
|
35
|
+
const extensionVersion = await getExtensionVersion(i);
|
|
36
|
+
i.extensionSpec = extensionVersion.spec;
|
|
37
|
+
}
|
|
38
|
+
else if (i.localPath) {
|
|
39
|
+
i.extensionSpec = await (0, specHelper_1.readExtensionYaml)(i.localPath);
|
|
40
|
+
i.extensionSpec.postinstallContent = await (0, specHelper_1.readPostinstall)(i.localPath);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
throw new error_1.FirebaseError("InstanceSpec had no ref or localPath, unable to get extensionSpec");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return i.extensionSpec;
|
|
47
|
+
}
|
|
48
|
+
exports.getExtensionSpec = getExtensionSpec;
|
|
31
49
|
async function have(projectId) {
|
|
32
50
|
const instances = await extensionsApi.listInstances(projectId);
|
|
33
51
|
return instances.map((i) => {
|
|
@@ -50,8 +68,6 @@ async function want(args) {
|
|
|
50
68
|
for (const e of Object.entries(args.extensions)) {
|
|
51
69
|
try {
|
|
52
70
|
const instanceId = e[0];
|
|
53
|
-
const ref = refs.parse(e[1]);
|
|
54
|
-
ref.version = await resolveVersion(ref);
|
|
55
71
|
const params = (0, manifest_1.readInstanceParam)({
|
|
56
72
|
projectDir: args.projectDir,
|
|
57
73
|
instanceId,
|
|
@@ -62,11 +78,22 @@ async function want(args) {
|
|
|
62
78
|
});
|
|
63
79
|
const autoPopulatedParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId, args.emulatorMode);
|
|
64
80
|
const subbedParams = (0, extensionsHelper_1.substituteParams)(params, autoPopulatedParams);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
if ((0, extensionsHelper_1.isLocalPath)(e[1])) {
|
|
82
|
+
instanceSpecs.push({
|
|
83
|
+
instanceId,
|
|
84
|
+
localPath: e[1],
|
|
85
|
+
params: subbedParams,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const ref = refs.parse(e[1]);
|
|
90
|
+
ref.version = await resolveVersion(ref);
|
|
91
|
+
instanceSpecs.push({
|
|
92
|
+
instanceId,
|
|
93
|
+
ref,
|
|
94
|
+
params: subbedParams,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
70
97
|
}
|
|
71
98
|
catch (err) {
|
|
72
99
|
logger_1.logger.debug(`Got error reading extensions entry ${e}: ${err}`);
|
|
@@ -28,7 +28,7 @@ async function prepare(context, options, payload) {
|
|
|
28
28
|
projectDir: options.config.projectDir,
|
|
29
29
|
extensions: options.config.get("extensions"),
|
|
30
30
|
});
|
|
31
|
-
const usingSecrets = await Promise.all((_a = context.
|
|
31
|
+
const usingSecrets = await Promise.all((_a = context.want) === null || _a === void 0 ? void 0 : _a.map(secrets_1.checkSpecForSecrets));
|
|
32
32
|
if (usingSecrets.some((i) => i)) {
|
|
33
33
|
await (0, secretsUtils_1.ensureSecretManagerApiEnabled)(options);
|
|
34
34
|
}
|
|
@@ -29,8 +29,8 @@ async function handleSecretParams(payload, have, nonInteractive) {
|
|
|
29
29
|
}
|
|
30
30
|
exports.handleSecretParams = handleSecretParams;
|
|
31
31
|
async function checkSpecForSecrets(i) {
|
|
32
|
-
const
|
|
33
|
-
return secretUtils.usesSecrets(
|
|
32
|
+
const extensionSpec = await (0, planner_1.getExtensionSpec)(i);
|
|
33
|
+
return secretUtils.usesSecrets(extensionSpec);
|
|
34
34
|
}
|
|
35
35
|
exports.checkSpecForSecrets = checkSpecForSecrets;
|
|
36
36
|
const secretsInSpec = (spec) => {
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.deleteExtensionInstanceTask = exports.configureExtensionInstanceTask = exports.updateExtensionInstanceTask = exports.createExtensionInstanceTask = exports.extensionsDeploymentHandler = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
|
+
const error_1 = require("../../error");
|
|
5
6
|
const extensionsApi = require("../../extensions/extensionsApi");
|
|
7
|
+
const extensionsHelper_1 = require("../../extensions/extensionsHelper");
|
|
6
8
|
const refs = require("../../extensions/refs");
|
|
7
9
|
const utils = require("../../utils");
|
|
8
10
|
const isRetryable = (err) => err.status === 429 || err.status === 409;
|
|
@@ -25,13 +27,28 @@ function extensionsDeploymentHandler(errorHandler) {
|
|
|
25
27
|
exports.extensionsDeploymentHandler = extensionsDeploymentHandler;
|
|
26
28
|
function createExtensionInstanceTask(projectId, instanceSpec, validateOnly = false) {
|
|
27
29
|
const run = async () => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
if (instanceSpec.ref) {
|
|
31
|
+
await extensionsApi.createInstance({
|
|
32
|
+
projectId,
|
|
33
|
+
instanceId: instanceSpec.instanceId,
|
|
34
|
+
params: instanceSpec.params,
|
|
35
|
+
extensionVersionRef: refs.toExtensionVersionRef(instanceSpec.ref),
|
|
36
|
+
validateOnly,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else if (instanceSpec.localPath) {
|
|
40
|
+
const extensionSource = await (0, extensionsHelper_1.createSourceFromLocation)(projectId, instanceSpec.localPath);
|
|
41
|
+
await extensionsApi.createInstance({
|
|
42
|
+
projectId,
|
|
43
|
+
instanceId: instanceSpec.instanceId,
|
|
44
|
+
params: instanceSpec.params,
|
|
45
|
+
extensionSource,
|
|
46
|
+
validateOnly,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
throw new error_1.FirebaseError(`Tried to create extension instance ${instanceSpec.instanceId} without a ref or a local path. This should never happen.`);
|
|
51
|
+
}
|
|
35
52
|
printSuccess(instanceSpec.instanceId, "create", validateOnly);
|
|
36
53
|
return;
|
|
37
54
|
};
|
|
@@ -44,13 +61,27 @@ function createExtensionInstanceTask(projectId, instanceSpec, validateOnly = fal
|
|
|
44
61
|
exports.createExtensionInstanceTask = createExtensionInstanceTask;
|
|
45
62
|
function updateExtensionInstanceTask(projectId, instanceSpec, validateOnly = false) {
|
|
46
63
|
const run = async () => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
if (instanceSpec.ref) {
|
|
65
|
+
await extensionsApi.updateInstanceFromRegistry({
|
|
66
|
+
projectId,
|
|
67
|
+
instanceId: instanceSpec.instanceId,
|
|
68
|
+
extRef: refs.toExtensionVersionRef(instanceSpec.ref),
|
|
69
|
+
params: instanceSpec.params,
|
|
70
|
+
validateOnly,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
else if (instanceSpec.localPath) {
|
|
74
|
+
const extensionSource = await (0, extensionsHelper_1.createSourceFromLocation)(projectId, instanceSpec.localPath);
|
|
75
|
+
await extensionsApi.updateInstance({
|
|
76
|
+
projectId,
|
|
77
|
+
instanceId: instanceSpec.instanceId,
|
|
78
|
+
extensionSource,
|
|
79
|
+
validateOnly,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
throw new error_1.FirebaseError(`Tried to update extension instance ${instanceSpec.instanceId} without a ref or a local path. This should never happen.`);
|
|
84
|
+
}
|
|
54
85
|
printSuccess(instanceSpec.instanceId, "update", validateOnly);
|
|
55
86
|
return;
|
|
56
87
|
};
|
|
@@ -63,12 +94,20 @@ function updateExtensionInstanceTask(projectId, instanceSpec, validateOnly = fal
|
|
|
63
94
|
exports.updateExtensionInstanceTask = updateExtensionInstanceTask;
|
|
64
95
|
function configureExtensionInstanceTask(projectId, instanceSpec, validateOnly = false) {
|
|
65
96
|
const run = async () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
97
|
+
if (instanceSpec.ref) {
|
|
98
|
+
await extensionsApi.configureInstance({
|
|
99
|
+
projectId,
|
|
100
|
+
instanceId: instanceSpec.instanceId,
|
|
101
|
+
params: instanceSpec.params,
|
|
102
|
+
validateOnly,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
else if (instanceSpec.localPath) {
|
|
106
|
+
throw new error_1.FirebaseError(`Tried to configure extension instance ${instanceSpec.instanceId} from a local path. This should never happen.`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
throw new error_1.FirebaseError(`Tried to configure extension instance ${instanceSpec.instanceId} without a ref or a local path. This should never happen.`);
|
|
110
|
+
}
|
|
72
111
|
printSuccess(instanceSpec.instanceId, "configure", validateOnly);
|
|
73
112
|
return;
|
|
74
113
|
};
|
|
@@ -81,7 +120,7 @@ function configureExtensionInstanceTask(projectId, instanceSpec, validateOnly =
|
|
|
81
120
|
exports.configureExtensionInstanceTask = configureExtensionInstanceTask;
|
|
82
121
|
function deleteExtensionInstanceTask(projectId, instanceSpec) {
|
|
83
122
|
const run = async () => {
|
|
84
|
-
|
|
123
|
+
await extensionsApi.deleteInstance(projectId, instanceSpec.instanceId);
|
|
85
124
|
printSuccess(instanceSpec.instanceId, "delete", false);
|
|
86
125
|
return;
|
|
87
126
|
};
|