firebase-tools 14.27.0 → 15.1.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.
Files changed (61) hide show
  1. package/lib/appUtils.js +14 -15
  2. package/lib/archiveDirectory.js +7 -45
  3. package/lib/bin/cli.js +35 -8
  4. package/lib/bin/mcp.js +46 -8
  5. package/lib/command.js +5 -1
  6. package/lib/commands/dataconnect-execute.js +1 -1
  7. package/lib/commands/dataconnect-sdk-generate.js +7 -5
  8. package/lib/commands/dataconnect-sql-diff.js +7 -5
  9. package/lib/commands/dataconnect-sql-grant.js +12 -12
  10. package/lib/commands/dataconnect-sql-migrate.js +6 -4
  11. package/lib/commands/dataconnect-sql-setup.js +6 -4
  12. package/lib/commands/dataconnect-sql-shell.js +6 -4
  13. package/lib/commands/firestore-backups-list.js +1 -1
  14. package/lib/commands/functions-config-clone.js +2 -2
  15. package/lib/commands/functions-config-export.js +137 -92
  16. package/lib/commands/functions-config-get.js +1 -2
  17. package/lib/commands/functions-config-set.js +2 -2
  18. package/lib/commands/functions-config-unset.js +2 -2
  19. package/lib/commands/help.js +1 -1
  20. package/lib/commands/index.js +15 -10
  21. package/lib/commands/init.js +8 -0
  22. package/lib/config.js +1 -5
  23. package/lib/dataconnect/load.js +18 -21
  24. package/lib/deploy/database/prepare.js +1 -3
  25. package/lib/deploy/functions/prepare.js +5 -1
  26. package/lib/deploy/functions/prepareFunctionsUpload.js +1 -2
  27. package/lib/deploy/functions/runtimes/node/index.js +11 -12
  28. package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
  29. package/lib/deploy/functions/validate.js +49 -2
  30. package/lib/emulator/commandUtils.js +1 -1
  31. package/lib/emulator/controller.js +1 -2
  32. package/lib/emulator/databaseEmulator.js +1 -5
  33. package/lib/emulator/downloadableEmulatorInfo.json +30 -30
  34. package/lib/emulator/functionsEmulator.js +0 -40
  35. package/lib/emulator/functionsEmulatorRuntime.js +1 -118
  36. package/lib/emulator/functionsEmulatorShared.js +1 -6
  37. package/lib/experiments.js +8 -1
  38. package/lib/extensions/extensionsHelper.js +0 -1
  39. package/lib/frameworks/constants.js +1 -1
  40. package/lib/fsAsync.js +11 -3
  41. package/lib/functionsConfig.js +39 -1
  42. package/lib/gcp/cloudsql/cloudsqladmin.js +1 -1
  43. package/lib/index.js +44 -1
  44. package/lib/init/features/dataconnect/resolver.js +111 -0
  45. package/lib/init/features/index.js +4 -1
  46. package/lib/init/features/project.js +1 -0
  47. package/lib/init/index.js +5 -0
  48. package/lib/mcp/index.js +31 -22
  49. package/lib/mcp/tools/core/get_environment.js +4 -1
  50. package/lib/mcp/tools/dataconnect/compile.js +13 -7
  51. package/lib/mcp/tools/dataconnect/execute.js +10 -7
  52. package/lib/mcp/tools/dataconnect/generate_operation.js +7 -3
  53. package/lib/mcp/tools/index.js +53 -44
  54. package/package.json +1 -2
  55. package/lib/deploy/functions/runtimes/node/extractTriggers.js +0 -23
  56. package/lib/deploy/functions/runtimes/node/parseTriggers.js +0 -332
  57. package/lib/deploy/functions/runtimes/node/triggerParser.js +0 -72
  58. package/lib/functions/deprecationWarnings.js +0 -21
  59. package/lib/functions/runtimeConfigExport.js +0 -141
  60. package/lib/handlePreviewToggles.js +0 -38
  61. package/lib/parseBoltRules.js +0 -29
@@ -1,332 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addResourcesToBackend = exports.addResourcesToBuild = exports.mergeRequiredAPIs = exports.discoverBackend = exports.discoverBuild = exports.useStrategy = void 0;
4
- const path = require("path");
5
- const _ = require("lodash");
6
- const child_process_1 = require("child_process");
7
- const error_1 = require("../../../../error");
8
- const logger_1 = require("../../../../logger");
9
- const backend = require("../../backend");
10
- const api = require("../../../../api");
11
- const proto = require("../../../../gcp/proto");
12
- const events = require("../../../../functions/events");
13
- const functional_1 = require("../../../../functional");
14
- const TRIGGER_PARSER = path.resolve(__dirname, "./triggerParser.js");
15
- function removeInspectOptions(options) {
16
- return options.filter((opt) => !opt.startsWith("--inspect"));
17
- }
18
- function parseTriggers(projectId, sourceDir, configValues, envs) {
19
- return new Promise((resolve, reject) => {
20
- const env = Object.assign({}, envs);
21
- env.GCLOUD_PROJECT = projectId;
22
- if (!_.isEmpty(configValues)) {
23
- env.CLOUD_RUNTIME_CONFIG = JSON.stringify(configValues);
24
- }
25
- const execArgv = removeInspectOptions(process.execArgv);
26
- if (env.NODE_OPTIONS) {
27
- env.NODE_OPTIONS = removeInspectOptions(env.NODE_OPTIONS.split(" ")).join(" ");
28
- }
29
- const parser = (0, child_process_1.fork)(TRIGGER_PARSER, [sourceDir], {
30
- silent: true,
31
- env: env,
32
- execArgv: execArgv,
33
- });
34
- parser.on("message", (message) => {
35
- if (message.triggers) {
36
- resolve(message.triggers);
37
- }
38
- else if (message.error) {
39
- reject(new error_1.FirebaseError(message.error, { exit: 1 }));
40
- }
41
- });
42
- parser.on("exit", (code) => {
43
- if (code !== 0) {
44
- reject(new error_1.FirebaseError("There was an unknown problem while trying to parse function triggers.", { exit: 2 }));
45
- }
46
- });
47
- });
48
- }
49
- function useStrategy() {
50
- return Promise.resolve(true);
51
- }
52
- exports.useStrategy = useStrategy;
53
- async function discoverBuild(projectId, sourceDir, runtime, configValues, envs) {
54
- const triggerAnnotations = await parseTriggers(projectId, sourceDir, configValues, envs);
55
- const want = {
56
- requiredAPIs: [],
57
- endpoints: {},
58
- params: [],
59
- };
60
- for (const annotation of triggerAnnotations) {
61
- addResourcesToBuild(projectId, runtime, annotation, want);
62
- }
63
- return want;
64
- }
65
- exports.discoverBuild = discoverBuild;
66
- async function discoverBackend(projectId, sourceDir, runtime, configValues, envs) {
67
- const triggerAnnotations = await parseTriggers(projectId, sourceDir, configValues, envs);
68
- const want = Object.assign(Object.assign({}, backend.empty()), { environmentVariables: envs });
69
- for (const annotation of triggerAnnotations) {
70
- addResourcesToBackend(projectId, runtime, annotation, want);
71
- }
72
- return want;
73
- }
74
- exports.discoverBackend = discoverBackend;
75
- function mergeRequiredAPIs(backend) {
76
- const apiToReasons = {};
77
- for (const { api, reason } of backend.requiredAPIs) {
78
- const reasons = apiToReasons[api] || new Set();
79
- if (reason) {
80
- reasons.add(reason);
81
- }
82
- apiToReasons[api] = reasons;
83
- }
84
- const merged = [];
85
- for (const [api, reasons] of Object.entries(apiToReasons)) {
86
- merged.push({ api, reason: Array.from(reasons).join(" ") });
87
- }
88
- backend.requiredAPIs = merged;
89
- }
90
- exports.mergeRequiredAPIs = mergeRequiredAPIs;
91
- function addResourcesToBuild(projectId, runtime, annotation, want) {
92
- var _a, _b;
93
- Object.freeze(annotation);
94
- const toSeconds = (0, functional_1.nullsafeVisitor)(proto.secondsFromDuration);
95
- const regions = annotation.regions || [api.functionsDefaultRegion()];
96
- let triggered;
97
- const triggerCount = +!!annotation.httpsTrigger +
98
- +!!annotation.eventTrigger +
99
- +!!annotation.taskQueueTrigger +
100
- +!!annotation.blockingTrigger;
101
- if (triggerCount !== 1) {
102
- throw new error_1.FirebaseError("Unexpected annotation generated by the Firebase Functions SDK. This should never happen.");
103
- }
104
- if (annotation.taskQueueTrigger) {
105
- want.requiredAPIs.push({
106
- api: "cloudtasks.googleapis.com",
107
- reason: "Needed for task queue functions.",
108
- });
109
- triggered = {
110
- taskQueueTrigger: {},
111
- };
112
- proto.copyIfPresent(triggered.taskQueueTrigger, annotation.taskQueueTrigger, "invoker");
113
- proto.copyIfPresent(triggered.taskQueueTrigger, annotation.taskQueueTrigger, "rateLimits");
114
- if (annotation.taskQueueTrigger.retryConfig) {
115
- triggered.taskQueueTrigger.retryConfig = {};
116
- proto.copyIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxAttempts", "maxDoublings");
117
- proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "minBackoffSeconds", "minBackoff", toSeconds);
118
- proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxBackoffSeconds", "maxBackoff", toSeconds);
119
- proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxRetrySeconds", "maxRetryDuration", toSeconds);
120
- }
121
- }
122
- else if (annotation.httpsTrigger) {
123
- if ((_a = annotation.labels) === null || _a === void 0 ? void 0 : _a["deployment-callable"]) {
124
- delete annotation.labels["deployment-callable"];
125
- triggered = { callableTrigger: {} };
126
- }
127
- else {
128
- const trigger = {};
129
- if (annotation.failurePolicy) {
130
- logger_1.logger.warn(`Ignoring retry policy for HTTPS function ${annotation.name}`);
131
- }
132
- if (annotation.httpsTrigger.invoker) {
133
- trigger.invoker = annotation.httpsTrigger.invoker;
134
- }
135
- triggered = { httpsTrigger: trigger };
136
- }
137
- }
138
- else if (annotation.schedule) {
139
- want.requiredAPIs.push({
140
- api: "cloudscheduler.googleapis.com",
141
- reason: "Needed for scheduled functions.",
142
- });
143
- triggered = {
144
- scheduleTrigger: {
145
- schedule: annotation.schedule.schedule,
146
- timeZone: (_b = annotation.schedule.timeZone) !== null && _b !== void 0 ? _b : null,
147
- retryConfig: {},
148
- },
149
- };
150
- if (annotation.schedule.retryConfig) {
151
- triggered.scheduleTrigger.retryConfig = {};
152
- proto.copyIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "retryCount", "maxDoublings");
153
- proto.convertIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "maxRetrySeconds", "maxRetryDuration", toSeconds);
154
- proto.convertIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "minBackoffSeconds", "minBackoffDuration", toSeconds);
155
- proto.convertIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "maxBackoffSeconds", "maxBackoffDuration", toSeconds);
156
- }
157
- }
158
- else if (annotation.blockingTrigger) {
159
- if (events.v1.AUTH_BLOCKING_EVENTS.includes(annotation.blockingTrigger.eventType)) {
160
- want.requiredAPIs.push({
161
- api: "identitytoolkit.googleapis.com",
162
- reason: "Needed for auth blocking functions.",
163
- });
164
- }
165
- triggered = {
166
- blockingTrigger: {
167
- eventType: annotation.blockingTrigger.eventType,
168
- },
169
- };
170
- }
171
- else if (annotation.eventTrigger) {
172
- triggered = {
173
- eventTrigger: {
174
- eventType: annotation.eventTrigger.eventType,
175
- eventFilters: { resource: annotation.eventTrigger.resource },
176
- retry: !!annotation.failurePolicy,
177
- },
178
- };
179
- }
180
- else {
181
- throw new error_1.FirebaseError("Do not understand Cloud Function annotation without a trigger" +
182
- JSON.stringify(annotation, null, 2));
183
- }
184
- const endpointId = annotation.name;
185
- const endpoint = Object.assign({ platform: annotation.platform || "gcfv1", region: regions, project: projectId, entryPoint: annotation.entryPoint, runtime: runtime }, triggered);
186
- proto.renameIfPresent(endpoint, annotation, "serviceAccount", "serviceAccountEmail");
187
- if (annotation.vpcConnector != null) {
188
- endpoint.vpc = { connector: annotation.vpcConnector };
189
- proto.renameIfPresent(endpoint.vpc, annotation, "egressSettings", "vpcConnectorEgressSettings");
190
- }
191
- proto.copyIfPresent(endpoint, annotation, "concurrency", "labels", "maxInstances", "minInstances", "availableMemoryMb");
192
- proto.convertIfPresent(endpoint, annotation, "ingressSettings", (str) => {
193
- if (str === null) {
194
- return null;
195
- }
196
- if (!backend.AllIngressSettings.includes(str)) {
197
- throw new Error(`Invalid ingress setting ${str}`);
198
- }
199
- return str;
200
- });
201
- proto.convertIfPresent(endpoint, annotation, "timeoutSeconds", "timeout", proto.secondsFromDuration);
202
- if (annotation.secrets) {
203
- endpoint.secretEnvironmentVariables = annotation.secrets.map((secret) => {
204
- return {
205
- secret,
206
- projectId,
207
- key: secret,
208
- };
209
- });
210
- }
211
- want.endpoints[endpointId] = endpoint;
212
- }
213
- exports.addResourcesToBuild = addResourcesToBuild;
214
- function addResourcesToBackend(projectId, runtime, annotation, want) {
215
- var _a;
216
- Object.freeze(annotation);
217
- for (const region of annotation.regions || [api.functionsDefaultRegion()]) {
218
- let triggered;
219
- const triggerCount = +!!annotation.httpsTrigger +
220
- +!!annotation.eventTrigger +
221
- +!!annotation.taskQueueTrigger +
222
- +!!annotation.blockingTrigger;
223
- if (triggerCount !== 1) {
224
- throw new error_1.FirebaseError("Unexpected annotation generated by the Firebase Functions SDK. This should never happen.");
225
- }
226
- if (annotation.taskQueueTrigger) {
227
- triggered = { taskQueueTrigger: annotation.taskQueueTrigger };
228
- want.requiredAPIs.push({
229
- api: "cloudtasks.googleapis.com",
230
- reason: "Needed for task queue functions.",
231
- });
232
- }
233
- else if (annotation.httpsTrigger) {
234
- if ((_a = annotation.labels) === null || _a === void 0 ? void 0 : _a["deployment-callable"]) {
235
- delete annotation.labels["deployment-callable"];
236
- triggered = { callableTrigger: {} };
237
- }
238
- else {
239
- const trigger = {};
240
- if (annotation.failurePolicy) {
241
- logger_1.logger.warn(`Ignoring retry policy for HTTPS function ${annotation.name}`);
242
- }
243
- proto.copyIfPresent(trigger, annotation.httpsTrigger, "invoker");
244
- triggered = { httpsTrigger: trigger };
245
- }
246
- }
247
- else if (annotation.schedule) {
248
- want.requiredAPIs.push({
249
- api: "cloudscheduler.googleapis.com",
250
- reason: "Needed for scheduled functions.",
251
- });
252
- triggered = { scheduleTrigger: annotation.schedule };
253
- }
254
- else if (annotation.blockingTrigger) {
255
- if (events.v1.AUTH_BLOCKING_EVENTS.includes(annotation.blockingTrigger.eventType)) {
256
- want.requiredAPIs.push({
257
- api: "identitytoolkit.googleapis.com",
258
- reason: "Needed for auth blocking functions.",
259
- });
260
- }
261
- triggered = {
262
- blockingTrigger: {
263
- eventType: annotation.blockingTrigger.eventType,
264
- options: annotation.blockingTrigger.options,
265
- },
266
- };
267
- }
268
- else {
269
- triggered = {
270
- eventTrigger: {
271
- eventType: annotation.eventTrigger.eventType,
272
- eventFilters: { resource: annotation.eventTrigger.resource },
273
- retry: !!annotation.failurePolicy,
274
- },
275
- };
276
- if (annotation.platform === "gcfv2") {
277
- if (annotation.eventTrigger.eventType === events.v2.PUBSUB_PUBLISH_EVENT) {
278
- triggered.eventTrigger.eventFilters = { topic: annotation.eventTrigger.resource };
279
- }
280
- if (events.v2.STORAGE_EVENTS.find((event) => { var _a; return event === (((_a = annotation.eventTrigger) === null || _a === void 0 ? void 0 : _a.eventType) || ""); })) {
281
- triggered.eventTrigger.eventFilters = { bucket: annotation.eventTrigger.resource };
282
- }
283
- }
284
- }
285
- const endpoint = Object.assign({ platform: annotation.platform || "gcfv1", id: annotation.name, region: region, project: projectId, entryPoint: annotation.entryPoint, runtime: runtime }, triggered);
286
- if (annotation.vpcConnector != null) {
287
- let maybeId = annotation.vpcConnector;
288
- if (maybeId && !maybeId.includes("/")) {
289
- maybeId = `projects/${projectId}/locations/${region}/connectors/${maybeId}`;
290
- }
291
- endpoint.vpc = { connector: maybeId };
292
- proto.renameIfPresent(endpoint.vpc, annotation, "egressSettings", "vpcConnectorEgressSettings");
293
- }
294
- if (annotation.secrets) {
295
- const secretEnvs = [];
296
- for (const secret of annotation.secrets) {
297
- const secretEnv = {
298
- secret,
299
- projectId,
300
- key: secret,
301
- };
302
- secretEnvs.push(secretEnv);
303
- }
304
- endpoint.secretEnvironmentVariables = secretEnvs;
305
- }
306
- proto.copyIfPresent(endpoint, annotation, "concurrency", "labels", "maxInstances", "minInstances");
307
- proto.renameIfPresent(endpoint, annotation, "serviceAccount", "serviceAccountEmail");
308
- proto.convertIfPresent(endpoint, annotation, "ingressSettings", (ingress) => {
309
- if (ingress == null) {
310
- return null;
311
- }
312
- if (!backend.AllIngressSettings.includes(ingress)) {
313
- throw new error_1.FirebaseError(`Invalid ingress setting ${ingress}`);
314
- }
315
- return ingress;
316
- });
317
- proto.convertIfPresent(endpoint, annotation, "availableMemoryMb", (mem) => {
318
- if (mem === null) {
319
- return null;
320
- }
321
- if (!backend.isValidMemoryOption(mem)) {
322
- throw new error_1.FirebaseError(`This version of firebase-tools does not know about the memory option ${mem}. Is an upgrade necessary?`);
323
- }
324
- return mem;
325
- });
326
- proto.convertIfPresent(endpoint, annotation, "timeoutSeconds", "timeout", proto.secondsFromDuration);
327
- want.endpoints[region] = want.endpoints[region] || {};
328
- want.endpoints[region][endpoint.id] = endpoint;
329
- mergeRequiredAPIs(want);
330
- }
331
- }
332
- exports.addResourcesToBackend = addResourcesToBackend;
@@ -1,72 +0,0 @@
1
- "use strict";
2
- var url = require("url");
3
- var extractTriggers = require("./extractTriggers");
4
- var EXIT = function () {
5
- process.exit(0);
6
- };
7
- const dynamicImport = new Function("modulePath", "return import(modulePath)");
8
- async function loadModule(packageDir) {
9
- try {
10
- return require(packageDir);
11
- }
12
- catch (e) {
13
- if (e.code === "ERR_REQUIRE_ESM") {
14
- const modulePath = require.resolve(packageDir);
15
- const moduleURL = url.pathToFileURL(modulePath).href;
16
- return await dynamicImport(moduleURL);
17
- }
18
- throw e;
19
- }
20
- }
21
- (async function () {
22
- if (!process.send) {
23
- console.warn("Could not parse function triggers (process.send === undefined).");
24
- process.exit(1);
25
- }
26
- var packageDir = process.argv[2];
27
- if (!packageDir) {
28
- process.send({ error: "Must supply package directory for functions trigger parsing." }, EXIT);
29
- return;
30
- }
31
- var mod;
32
- var triggers = [];
33
- try {
34
- mod = await loadModule(packageDir);
35
- }
36
- catch (e) {
37
- if (e.code === "MODULE_NOT_FOUND") {
38
- process.send({
39
- error: "Error parsing triggers: " +
40
- e.message +
41
- '\n\nTry running "npm install" in your functions directory before deploying.',
42
- }, EXIT);
43
- return;
44
- }
45
- if (/Firebase config variables are not available/.test(e.message)) {
46
- process.send({
47
- error: "Error occurred while parsing your function triggers. " +
48
- 'Please ensure you have the latest firebase-functions SDK by running "npm i --save firebase-functions@latest" inside your functions folder.\n\n' +
49
- e.stack,
50
- }, EXIT);
51
- return;
52
- }
53
- process.send({
54
- error: "Error occurred while parsing your function triggers.\n\n" + e.stack,
55
- }, EXIT);
56
- return;
57
- }
58
- try {
59
- extractTriggers(mod, triggers);
60
- }
61
- catch (err) {
62
- if (/Maximum call stack size exceeded/.test(err.message)) {
63
- process.send({
64
- error: "Error occurred while parsing your function triggers. Please ensure that index.js only " +
65
- "exports cloud functions.\n\n",
66
- }, EXIT);
67
- return;
68
- }
69
- process.send({ error: err.message }, EXIT);
70
- }
71
- process.send({ triggers: triggers }, EXIT);
72
- })();
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.logFunctionsConfigDeprecationWarning = void 0;
4
- const utils_1 = require("../utils");
5
- const FUNCTIONS_CONFIG_DEPRECATION_MESSAGE = `DEPRECATION NOTICE: Action required to deploy after March 2026
6
-
7
- functions.config() API is deprecated.
8
- Cloud Runtime Configuration API, the Google Cloud service used to store function configuration data, will be shut down in March 2026. As a result, you must migrate away from using functions.config() to continue deploying your functions after March 2026.
9
-
10
- What this means for you:
11
-
12
- - The Firebase CLI commands for managing this configuration (functions:config:set, get, unset, clone, and export) are deprecated. These commands will no longer work after March 2026.
13
- - firebase deploy command will fail for functions that use the legacy functions.config() API after March 2026.
14
-
15
- Existing deployments will continue to work with their current configuration.
16
-
17
- See your migration options at: https://firebase.google.com/docs/functions/config-env#migrate-to-dotenv`;
18
- function logFunctionsConfigDeprecationWarning() {
19
- (0, utils_1.logWarningToStderr)(FUNCTIONS_CONFIG_DEPRECATION_MESSAGE);
20
- }
21
- exports.logFunctionsConfigDeprecationWarning = logFunctionsConfigDeprecationWarning;
@@ -1,141 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateDotenvFilename = exports.toDotenvFormat = exports.hydrateEnvs = exports.configToEnv = exports.convertKey = exports.hydrateConfigs = exports.getProjectInfos = void 0;
4
- const clc = require("colorette");
5
- const env = require("./env");
6
- const functionsConfig = require("../functionsConfig");
7
- const error_1 = require("../error");
8
- const logger_1 = require("../logger");
9
- const projectUtils_1 = require("../projectUtils");
10
- const rc_1 = require("../rc");
11
- const utils_1 = require("../utils");
12
- const functional_1 = require("../functional");
13
- function getProjectInfos(options) {
14
- const result = {};
15
- const rc = (0, rc_1.loadRC)(options);
16
- if (rc.projects) {
17
- for (const [alias, projectId] of Object.entries(rc.projects)) {
18
- if (Object.keys(result).includes(projectId)) {
19
- (0, utils_1.logWarning)(`Multiple aliases found for ${clc.bold(projectId)}. ` +
20
- `Preferring alias (${clc.bold(result[projectId])}) over (${clc.bold(alias)}).`);
21
- continue;
22
- }
23
- result[projectId] = alias;
24
- }
25
- }
26
- const projectId = (0, projectUtils_1.getProjectId)(options);
27
- if (projectId && !Object.keys(result).includes(projectId)) {
28
- result[projectId] = projectId;
29
- }
30
- return Object.entries(result).map(([k, v]) => {
31
- const result = { projectId: k };
32
- if (k !== v) {
33
- result.alias = v;
34
- }
35
- return result;
36
- });
37
- }
38
- exports.getProjectInfos = getProjectInfos;
39
- async function hydrateConfigs(pInfos) {
40
- const hydrate = pInfos.map((info) => {
41
- return functionsConfig
42
- .materializeAll(info.projectId)
43
- .then((config) => {
44
- info.config = config;
45
- return;
46
- })
47
- .catch((err) => {
48
- logger_1.logger.debug(`Failed to fetch runtime config for project ${info.projectId}: ${err.message}`);
49
- });
50
- });
51
- await Promise.all(hydrate);
52
- }
53
- exports.hydrateConfigs = hydrateConfigs;
54
- function convertKey(configKey, prefix) {
55
- const baseKey = configKey
56
- .toUpperCase()
57
- .replace(/\./g, "_")
58
- .replace(/-/g, "_");
59
- let envKey = baseKey;
60
- try {
61
- env.validateKey(envKey);
62
- }
63
- catch (err) {
64
- if (err instanceof env.KeyValidationError) {
65
- envKey = prefix + envKey;
66
- env.validateKey(envKey);
67
- }
68
- }
69
- return envKey;
70
- }
71
- exports.convertKey = convertKey;
72
- function configToEnv(configs, prefix) {
73
- const success = [];
74
- const errors = [];
75
- for (const [configKey, value] of (0, functional_1.flatten)(configs)) {
76
- try {
77
- const envKey = convertKey(configKey, prefix);
78
- success.push({ origKey: configKey, newKey: envKey, value: value });
79
- }
80
- catch (err) {
81
- if (err instanceof env.KeyValidationError) {
82
- errors.push({
83
- origKey: configKey,
84
- newKey: err.key,
85
- err: err.message,
86
- value: value,
87
- });
88
- }
89
- else {
90
- throw new error_1.FirebaseError("Unexpected error while converting config", {
91
- exit: 2,
92
- original: err,
93
- });
94
- }
95
- }
96
- }
97
- return { success, errors };
98
- }
99
- exports.configToEnv = configToEnv;
100
- function hydrateEnvs(pInfos, prefix) {
101
- let errMsg = "";
102
- for (const pInfo of pInfos) {
103
- const { success, errors } = configToEnv(pInfo.config, prefix);
104
- if (errors.length > 0) {
105
- const msg = `${pInfo.projectId} ` +
106
- `${pInfo.alias ? "(" + pInfo.alias + ")" : ""}:\n` +
107
- errors.map((err) => `\t${err.origKey} => ${clc.bold(err.newKey)} (${err.err})`).join("\n") +
108
- "\n";
109
- errMsg += msg;
110
- }
111
- else {
112
- pInfo.envs = success;
113
- }
114
- }
115
- return errMsg;
116
- }
117
- exports.hydrateEnvs = hydrateEnvs;
118
- const CHARACTERS_TO_ESCAPE_SEQUENCES = {
119
- "\n": "\\n",
120
- "\r": "\\r",
121
- "\t": "\\t",
122
- "\v": "\\v",
123
- "\\": "\\\\",
124
- '"': '\\"',
125
- "'": "\\'",
126
- };
127
- function escape(s) {
128
- return s.replace(/[\n\r\t\v\\"']/g, (ch) => CHARACTERS_TO_ESCAPE_SEQUENCES[ch]);
129
- }
130
- function toDotenvFormat(envs, header = "") {
131
- const lines = envs.map(({ newKey, value }) => `${newKey}="${escape(value)}"`);
132
- const maxLineLen = Math.max(...lines.map((l) => l.length));
133
- return (`${header}\n` +
134
- lines.map((line, idx) => `${line.padEnd(maxLineLen)} # from ${envs[idx].origKey}`).join("\n"));
135
- }
136
- exports.toDotenvFormat = toDotenvFormat;
137
- function generateDotenvFilename(pInfo) {
138
- var _a;
139
- return `.env.${(_a = pInfo.alias) !== null && _a !== void 0 ? _a : pInfo.projectId}`;
140
- }
141
- exports.generateDotenvFilename = generateDotenvFilename;
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handlePreviewToggles = void 0;
4
- const colorette_1 = require("colorette");
5
- const experiments = require("./experiments");
6
- function errorOut(name) {
7
- console.log(`${(0, colorette_1.bold)((0, colorette_1.red)("Error:"))} Did not recognize preview feature ${(0, colorette_1.bold)(name || "")}`);
8
- process.exit(1);
9
- }
10
- function handlePreviewToggles(args) {
11
- const name = args[1];
12
- const isValid = experiments.isValidExperiment(name);
13
- if (args[0] === "--open-sesame") {
14
- console.log(`${(0, colorette_1.bold)("firebase --open-sesame")} is deprecated and wil be removed in a future ` +
15
- `version. Use the new "experiments" family of commands, including ${(0, colorette_1.bold)("firebase experiments:enable")}`);
16
- if (isValid) {
17
- console.log(`Enabling experiment ${(0, colorette_1.bold)(name)} ...`);
18
- experiments.setEnabled(name, true);
19
- experiments.flushToDisk();
20
- console.log("Experiment enabled!");
21
- return process.exit(0);
22
- }
23
- errorOut(name);
24
- }
25
- else if (args[0] === "--close-sesame") {
26
- console.log(`${(0, colorette_1.bold)("firebase --open-sesame")} is deprecated and wil be removed in a future ` +
27
- `version. Use the new "experiments" family of commands, including ${(0, colorette_1.bold)("firebase experiments:disable")}`);
28
- if (isValid) {
29
- console.log(`Disabling experiment ${(0, colorette_1.bold)(name)}...`);
30
- experiments.setEnabled(name, false);
31
- experiments.flushToDisk();
32
- return process.exit(0);
33
- }
34
- errorOut(name);
35
- }
36
- return false;
37
- }
38
- exports.handlePreviewToggles = handlePreviewToggles;
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseBoltRules = void 0;
4
- const fs = require("fs");
5
- const spawn = require("cross-spawn");
6
- const clc = require("colorette");
7
- const _ = require("lodash");
8
- const error_1 = require("./error");
9
- function parseBoltRules(filename) {
10
- const ruleSrc = fs.readFileSync(filename, "utf8");
11
- const result = spawn.sync("npx", ["--no-install", "firebase-bolt"], {
12
- input: ruleSrc,
13
- timeout: 10000,
14
- encoding: "utf-8",
15
- });
16
- if (result.error && _.get(result.error, "code") === "ENOENT") {
17
- throw new error_1.FirebaseError("Bolt not installed, run " + clc.bold("npm install -g firebase-bolt"));
18
- }
19
- else if (result.error) {
20
- throw new error_1.FirebaseError("Unexpected error parsing Bolt rules file", {
21
- exit: 2,
22
- });
23
- }
24
- else if (result.status != null && result.status > 0) {
25
- throw new error_1.FirebaseError(result.stderr.toString(), { exit: 1 });
26
- }
27
- return result.stdout;
28
- }
29
- exports.parseBoltRules = parseBoltRules;