firebase-tools 12.4.3 → 12.4.5

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/apiv2.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Client = exports.setAccessToken = exports.setRefreshToken = void 0;
4
4
  const url_1 = require("url");
5
5
  const stream_1 = require("stream");
6
- const ProxyAgent = require("proxy-agent");
6
+ const proxy_agent_1 = require("proxy-agent");
7
7
  const retry = require("retry");
8
8
  const abort_controller_1 = require("abort-controller");
9
9
  const node_fetch_1 = require("node-fetch");
@@ -179,12 +179,8 @@ class Client {
179
179
  redirect: options.redirect,
180
180
  compress: options.compress,
181
181
  };
182
- if (this.opts.proxy) {
183
- fetchOptions.agent = new ProxyAgent(this.opts.proxy);
184
- }
185
- const envProxy = proxyURIFromEnv();
186
- if (envProxy) {
187
- fetchOptions.agent = new ProxyAgent(envProxy);
182
+ if (proxyURIFromEnv()) {
183
+ fetchOptions.agent = new proxy_agent_1.ProxyAgent();
188
184
  }
189
185
  if (options.signal) {
190
186
  fetchOptions.signal = options.signal;
@@ -233,6 +229,7 @@ class Client {
233
229
  }
234
230
  catch (thrown) {
235
231
  const err = thrown instanceof Error ? thrown : new Error(thrown);
232
+ logger_1.logger.debug(`*** [apiv2] error from fetch(${fetchURL}, ${JSON.stringify(fetchOptions)}): ${err}`);
236
233
  const isAbortError = err.name.includes("AbortError");
237
234
  if (isAbortError) {
238
235
  throw new error_1.FirebaseError(`Timeout reached making request to ${fetchURL}`, {
@@ -1,76 +1,53 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const command_1 = require("../command");
5
4
  const Table = require("cli-table");
5
+ const command_1 = require("../command");
6
6
  const clc = require("colorette");
7
7
  const ora = require("ora");
8
8
  const logger_1 = require("../logger");
9
9
  const requirePermissions_1 = require("../requirePermissions");
10
- const projectUtils_1 = require("../projectUtils");
11
- const firedata = require("../gcp/firedata");
12
10
  const types_1 = require("../emulator/types");
13
11
  const commandUtils_1 = require("../emulator/commandUtils");
14
12
  const experiments = require("../experiments");
15
- const projectUtils_2 = require("../projectUtils");
13
+ const projectUtils_1 = require("../projectUtils");
16
14
  const database_1 = require("../management/database");
17
- function logInstances(instances) {
18
- if (instances.length === 0) {
19
- logger_1.logger.info(clc.bold("No database instances found."));
20
- return;
21
- }
22
- const tableHead = ["Database Instance Name", "Location", "Type", "State"];
23
- const table = new Table({ head: tableHead, style: { head: ["green"] } });
24
- instances.forEach((db) => {
25
- table.push([db.name, db.location, db.type, db.state]);
26
- });
27
- logger_1.logger.info(table.toString());
28
- }
29
- function logInstancesCount(count = 0) {
30
- if (count === 0) {
31
- return;
32
- }
33
- logger_1.logger.info("");
34
- logger_1.logger.info(`${count} database instance(s) total.`);
35
- }
36
15
  exports.command = new command_1.Command("database:instances:list")
37
16
  .description("list realtime database instances, optionally filtered by a specified location")
38
17
  .before(requirePermissions_1.requirePermissions, ["firebasedatabase.instances.list"])
18
+ .option("-l, --location <location>", "(optional) location for the database instance, defaults to all regions")
39
19
  .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.DATABASE)
40
20
  .action(async (options) => {
41
21
  const location = (0, database_1.parseDatabaseLocation)(options.location, database_1.DatabaseLocation.ANY);
42
22
  const spinner = ora("Preparing the list of your Firebase Realtime Database instances" +
43
23
  `${location === database_1.DatabaseLocation.ANY ? "" : ` for location: ${location}`}`).start();
44
- let instances;
45
- if (experiments.isEnabled("rtdbmanagement")) {
46
- const projectId = (0, projectUtils_2.needProjectId)(options);
47
- try {
48
- instances = await (0, database_1.listDatabaseInstances)(projectId, location);
49
- }
50
- catch (err) {
51
- spinner.fail();
52
- throw err;
53
- }
54
- spinner.succeed();
55
- logInstances(instances);
56
- logInstancesCount(instances.length);
57
- return instances;
58
- }
59
- const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
24
+ const projectId = (0, projectUtils_1.needProjectId)(options);
25
+ let instances = [];
60
26
  try {
61
- instances = await firedata.listDatabaseInstances(projectNumber);
27
+ instances = await (0, database_1.listDatabaseInstances)(projectId, location);
62
28
  }
63
29
  catch (err) {
64
30
  spinner.fail();
65
31
  throw err;
66
32
  }
67
33
  spinner.succeed();
68
- for (const instance of instances) {
69
- logger_1.logger.info(instance.instance);
34
+ if (instances.length === 0) {
35
+ logger_1.logger.info(clc.bold("No database instances found."));
36
+ return;
37
+ }
38
+ if (!experiments.isEnabled("rtdbmanagement")) {
39
+ for (const instance of instances) {
40
+ logger_1.logger.info(instance.name);
41
+ }
42
+ logger_1.logger.info(`Project ${options.project} has ${instances.length} database instances`);
43
+ return instances;
70
44
  }
71
- logger_1.logger.info(`Project ${options.project} has ${instances.length} database instances`);
45
+ const tableHead = ["Database Instance Name", "Location", "Type", "State"];
46
+ const table = new Table({ head: tableHead, style: { head: ["green"] } });
47
+ for (const db of instances) {
48
+ table.push([db.name, db.location, db.type, db.state]);
49
+ }
50
+ logger_1.logger.info(table.toString());
51
+ logger_1.logger.info(`${instances.length} database instance(s) total.`);
72
52
  return instances;
73
53
  });
74
- if (experiments.isEnabled("rtdbmanagement")) {
75
- exports.command = exports.command.option("-l, --location <location>", "(optional) location for the database instance, defaults to us-central1");
76
- }
@@ -12,9 +12,9 @@ const prompt_1 = require("../prompt");
12
12
  const utils_1 = require("../utils");
13
13
  const projectUtils_1 = require("../projectUtils");
14
14
  const secretManager_1 = require("../gcp/secretManager");
15
+ const ensureApiEnabled_1 = require("../ensureApiEnabled");
15
16
  const secrets = require("../functions/secrets");
16
17
  const backend = require("../deploy/functions/backend");
17
- const ensureApiEnabled_1 = require("../ensureApiEnabled");
18
18
  exports.command = new command_1.Command("functions:secrets:set <KEY>")
19
19
  .description("Create or update a secret for use in Cloud Functions for Firebase.")
20
20
  .withForce("Automatically updates functions to use the new secret.")
@@ -58,7 +58,7 @@ exports.command = new command_1.Command("functions:secrets:set <KEY>")
58
58
  logger_1.logger.debug("Customer set secrets before enabling functions. Exiting");
59
59
  return;
60
60
  }
61
- const haveBackend = await backend.existingBackend({ projectId });
61
+ let haveBackend = await backend.existingBackend({ projectId });
62
62
  const endpointsToUpdate = backend
63
63
  .allEndpoints(haveBackend)
64
64
  .filter((e) => secrets.inUse({ projectId, projectNumber }, secret, e));
@@ -87,4 +87,20 @@ exports.command = new command_1.Command("functions:secrets:set <KEY>")
87
87
  return updated;
88
88
  });
89
89
  await Promise.all(updateOps);
90
+ haveBackend = await backend.existingBackend({ projectId }, true);
91
+ const staleEndpoints = backend.allEndpoints(backend.matchingBackend(haveBackend, (e) => {
92
+ const pInfo = { projectId, projectNumber };
93
+ return secrets.inUse(pInfo, secret, e) && !secrets.versionInUse(pInfo, secretVersion, e);
94
+ }));
95
+ if (staleEndpoints.length !== 0) {
96
+ (0, utils_1.logWarning)(`${staleEndpoints.length} functions are unexpectedly using old version of secret ${secret.name} still:\n\t` +
97
+ staleEndpoints.map((e) => `${e.id}(${e.region})`).join("\n\t"));
98
+ (0, utils_1.logBullet)("Please deploy your functions manually for the change to take effect by running:\n\t" +
99
+ clc.bold("firebase deploy --only functions"));
100
+ }
101
+ const secretsToPrune = (await secrets.pruneSecrets({ projectId, projectNumber }, backend.allEndpoints(haveBackend))).filter((sv) => sv.key === key);
102
+ (0, utils_1.logBullet)(`Removing secret versions: ${secretsToPrune
103
+ .map((sv) => sv.key + "[" + sv.version + "]")
104
+ .join(", ")}`);
105
+ await Promise.all(secretsToPrune.map((sv) => (0, secretManager_1.destroySecretVersion)(projectId, sv.secret, sv.version)));
90
106
  });
@@ -25,11 +25,11 @@ function prepareIndexes(context, options, databaseId, indexesFileName) {
25
25
  async function default_1(context, options) {
26
26
  if (options.only) {
27
27
  const targets = options.only.split(",");
28
- const onlyIndexes = targets.indexOf("firestore:indexes") >= 0;
29
- const onlyRules = targets.indexOf("firestore:rules") >= 0;
28
+ const excludeRules = targets.indexOf("firestore:indexes") >= 0;
29
+ const excludeIndexes = targets.indexOf("firestore:rules") >= 0;
30
30
  const onlyFirestore = targets.indexOf("firestore") >= 0;
31
- context.firestoreIndexes = onlyIndexes || onlyFirestore;
32
- context.firestoreRules = onlyRules || onlyFirestore;
31
+ context.firestoreIndexes = !excludeIndexes || onlyFirestore;
32
+ context.firestoreRules = !excludeRules || onlyFirestore;
33
33
  }
34
34
  else {
35
35
  context.firestoreIndexes = true;
@@ -295,7 +295,7 @@ async function loadCodebases(config, options, firebaseConfig, runtimeConfig, fil
295
295
  logger_1.logger.debug(`Building ${runtimeDelegate.name} source`);
296
296
  await runtimeDelegate.build();
297
297
  const firebaseEnvs = functionsEnv.loadFirebaseEnvs(firebaseConfig, projectId);
298
- (0, utils_1.logLabeledBullet)("functions", `Loading and anaylzing source code for codebase ${codebase} to determine what to deploy`);
298
+ (0, utils_1.logLabeledBullet)("functions", `Loading and analyzing source code for codebase ${codebase} to determine what to deploy`);
299
299
  wantBuilds[codebase] = await runtimeDelegate.discoverBuild(runtimeConfig, Object.assign(Object.assign({}, firebaseEnvs), { GOOGLE_CLOUD_QUOTA_PROJECT: projectId }));
300
300
  wantBuilds[codebase].runtime = codebaseConfig.runtime;
301
301
  }
@@ -223,12 +223,12 @@ class Fabricator {
223
223
  }
224
224
  async createV2Function(endpoint) {
225
225
  var _a, _b, _c, _d, _e;
226
- const storage = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
227
- if (!storage) {
226
+ const storageSource = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
227
+ if (!storageSource) {
228
228
  logger_1.logger.debug("Precondition failed. Cannot create a GCFv2 function without storage");
229
229
  throw new Error("Precondition failed");
230
230
  }
231
- const apiFunction = gcfV2.functionFromEndpoint(endpoint, storage);
231
+ const apiFunction = gcfV2.functionFromEndpoint(Object.assign(Object.assign({}, endpoint), { source: { storageSource } }));
232
232
  const topic = (_b = apiFunction.eventTrigger) === null || _b === void 0 ? void 0 : _b.pubsubTopic;
233
233
  if (topic) {
234
234
  await this.executor
@@ -368,12 +368,12 @@ class Fabricator {
368
368
  }
369
369
  async updateV2Function(endpoint) {
370
370
  var _a, _b, _c, _d;
371
- const storage = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
372
- if (!storage) {
371
+ const storageSource = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
372
+ if (!storageSource) {
373
373
  logger_1.logger.debug("Precondition failed. Cannot update a GCFv2 function without storage");
374
374
  throw new Error("Precondition failed");
375
375
  }
376
- const apiFunction = gcfV2.functionFromEndpoint(endpoint, storage);
376
+ const apiFunction = gcfV2.functionFromEndpoint(Object.assign(Object.assign({}, endpoint), { source: { storageSource } }));
377
377
  if ((_b = apiFunction.eventTrigger) === null || _b === void 0 ? void 0 : _b.pubsubTopic) {
378
378
  delete apiFunction.eventTrigger.pubsubTopic;
379
379
  }
@@ -146,13 +146,13 @@ async function signUp(state, reqBody, ctx) {
146
146
  (0, errors_1.assert)(state.enableAnonymousUser, "ADMIN_ONLY_OPERATION");
147
147
  }
148
148
  }
149
- if (typeof reqBody.email === "string") {
149
+ if (reqBody.email || (reqBody.email === "" && provider)) {
150
150
  (0, errors_1.assert)((0, utils_1.isValidEmailAddress)(reqBody.email), "INVALID_EMAIL");
151
151
  const email = (0, utils_1.canonicalizeEmailAddress)(reqBody.email);
152
152
  (0, errors_1.assert)(!state.getUserByEmail(email), "EMAIL_EXISTS");
153
153
  updates.email = email;
154
154
  }
155
- if (typeof reqBody.password === "string") {
155
+ if (reqBody.password) {
156
156
  (0, errors_1.assert)(reqBody.password.length >= PASSWORD_MIN_LENGTH, `WEAK_PASSWORD : Password should be at least ${PASSWORD_MIN_LENGTH} characters`);
157
157
  updates.salt = "fakeSalt" + (0, utils_1.randomId)(20);
158
158
  updates.passwordHash = hashPassword(reqBody.password, updates.salt);
@@ -84,7 +84,7 @@ class RuntimeWorker {
84
84
  });
85
85
  });
86
86
  }
87
- request(req, resp, body) {
87
+ request(req, resp, body, debug) {
88
88
  if (this.triggerKey !== FREE_WORKER_KEY) {
89
89
  this.logInfo(`Beginning execution of "${this.triggerKey}"`);
90
90
  }
@@ -124,6 +124,10 @@ class RuntimeWorker {
124
124
  const piped = _resp.pipe(resp);
125
125
  piped.on("finish", () => finishReq("finish"));
126
126
  });
127
+ if (debug) {
128
+ proxy.setSocketKeepAlive(false);
129
+ proxy.setTimeout(0);
130
+ }
127
131
  proxy.on("timeout", () => {
128
132
  this.logger.log("ERROR", `Your function timed out after ~${this.timeoutSeconds}s. To configure this timeout, see
129
133
  https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation.`);
@@ -260,7 +264,7 @@ class RuntimeWorkerPool {
260
264
  if (debug) {
261
265
  await worker.sendDebugMsg(debug);
262
266
  }
263
- return worker.request(req, resp, body);
267
+ return worker.request(req, resp, body, !!debug);
264
268
  }
265
269
  getIdleWorker(triggerId) {
266
270
  this.cleanUpWorkers();
@@ -27,6 +27,10 @@ async function check(projectId, apiName, prefix, silent = false) {
27
27
  return isEnabled;
28
28
  }
29
29
  exports.check = check;
30
+ function isPermissionError(e) {
31
+ var _a, _b, _c;
32
+ return ((_c = (_b = (_a = e.context) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.status) === "PERMISSION_DENIED";
33
+ }
30
34
  async function enable(projectId, apiName) {
31
35
  try {
32
36
  await apiClient.post(`/projects/${projectId}/services/${apiName}:enable`, undefined, {
@@ -40,7 +44,24 @@ async function enable(projectId, apiName) {
40
44
 
41
45
  https://console.firebase.google.com/project/${projectId}/usage/details`);
42
46
  }
43
- throw err;
47
+ else if (isPermissionError(err)) {
48
+ const apiPermissionDeniedRegex = new RegExp(/Permission denied to enable service \[([.a-zA-Z]+)\]/);
49
+ const permissionsError = apiPermissionDeniedRegex.exec(err.message);
50
+ if (permissionsError && permissionsError[1]) {
51
+ const serviceUrl = permissionsError[1];
52
+ err.message = `Permissions denied enabling ${serviceUrl}.
53
+ Please ask a project owner to visit the following URL to enable this service:
54
+
55
+ https://console.cloud.google.com/apis/library/${serviceUrl}?project=${projectId}`;
56
+ throw err;
57
+ }
58
+ else {
59
+ throw err;
60
+ }
61
+ }
62
+ else {
63
+ throw err;
64
+ }
44
65
  }
45
66
  }
46
67
  async function pollCheckEnabled(projectId, apiName, prefix, silent, enablementRetries, pollRetries = 0) {
@@ -49,14 +49,21 @@ function getFirestoreConfig(projectId, options) {
49
49
  }
50
50
  }
51
51
  else if (database) {
52
- if (allDatabases) {
52
+ if (allDatabases || onlyDatabases.has(database)) {
53
53
  results.push(c);
54
+ onlyDatabases.delete(database);
54
55
  }
55
56
  }
56
57
  else {
57
58
  throw new error_1.FirebaseError('Must supply either "target" or "databaseId" in firestore config');
58
59
  }
59
60
  }
61
+ if (onlyDatabases.has("rules")) {
62
+ onlyDatabases.delete("rules");
63
+ }
64
+ if (onlyDatabases.has("indexes")) {
65
+ onlyDatabases.delete("indexes");
66
+ }
60
67
  if (!allDatabases && onlyDatabases.size !== 0) {
61
68
  throw new error_1.FirebaseError(`Could not find configurations in firebase.json for the following database targets: ${[
62
69
  ...onlyDatabases,
@@ -13,6 +13,7 @@ const svelte = require("./svelte");
13
13
  const svelekit = require("./sveltekit");
14
14
  const react = require("./react");
15
15
  const vite = require("./vite");
16
+ const flutter = require("./flutter");
16
17
  exports.WebFrameworks = {
17
18
  angular,
18
19
  astro,
@@ -26,4 +27,5 @@ exports.WebFrameworks = {
26
27
  svelekit,
27
28
  react,
28
29
  vite,
30
+ flutter,
29
31
  };
@@ -30,10 +30,6 @@ exports.support = "preview";
30
30
  exports.type = 2;
31
31
  exports.docsUrl = "https://firebase.google.com/docs/hosting/frameworks/nextjs";
32
32
  const DEFAULT_NUMBER_OF_REASONS_TO_LIST = 5;
33
- function getNextVersion(cwd) {
34
- var _a;
35
- return (_a = (0, utils_1.findDependency)("next", { cwd, depth: 0, omitDev: false })) === null || _a === void 0 ? void 0 : _a.version;
36
- }
37
33
  function getReactVersion(cwd) {
38
34
  var _a;
39
35
  return (_a = (0, utils_1.findDependency)("react-dom", { cwd, omitDev: false })) === null || _a === void 0 ? void 0 : _a.version;
@@ -41,7 +37,7 @@ function getReactVersion(cwd) {
41
37
  async function discover(dir) {
42
38
  if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "package.json"))))
43
39
  return;
44
- if (!(await (0, fs_extra_1.pathExists)("next.config.js")) && !getNextVersion(dir))
40
+ if (!(await (0, fs_extra_1.pathExists)("next.config.js")) && !(0, utils_2.getNextVersion)(dir))
45
41
  return;
46
42
  return { mayWantBackend: true, publicDirectory: (0, path_1.join)(dir, PUBLIC_DIR) };
47
43
  }
@@ -72,7 +68,7 @@ async function build(dir) {
72
68
  if (await (0, utils_2.isUsingMiddleware)((0, path_1.join)(dir, distDir), false)) {
73
69
  reasonsForBackend.add("middleware");
74
70
  }
75
- if (await (0, utils_2.isUsingImageOptimization)((0, path_1.join)(dir, distDir))) {
71
+ if (await (0, utils_2.isUsingImageOptimization)(dir, distDir)) {
76
72
  reasonsForBackend.add(`Image Optimization`);
77
73
  }
78
74
  const prerenderManifest = await (0, utils_1.readJSON)((0, path_1.join)(dir, distDir, constants_2.PRERENDER_MANIFEST));
@@ -349,8 +345,7 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
349
345
  await (0, promises_1.mkdir)((0, path_1.join)(destDir, "public"));
350
346
  await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, "public"), (0, path_1.join)(destDir, "public"));
351
347
  }
352
- if (!(await (0, utils_2.hasUnoptimizedImage)(sourceDir, distDir)) &&
353
- ((0, utils_2.usesAppDirRouter)(sourceDir) || (await (0, utils_2.usesNextImage)(sourceDir, distDir)))) {
348
+ if (await (0, utils_2.isUsingImageOptimization)(sourceDir, distDir)) {
354
349
  packageJson.dependencies["sharp"] = constants_1.SHARP_VERSION;
355
350
  }
356
351
  await (0, fs_extra_1.mkdirp)((0, path_1.join)(destDir, distDir));
@@ -386,7 +381,7 @@ async function getConfig(dir) {
386
381
  var _b;
387
382
  let config = {};
388
383
  if ((0, fs_1.existsSync)((0, path_1.join)(dir, "next.config.js"))) {
389
- const version = getNextVersion(dir);
384
+ const version = (0, utils_2.getNextVersion)(dir);
390
385
  if (!version)
391
386
  throw new Error("Unable to find the next dep, try NPM installing?");
392
387
  if ((0, semver_1.gte)(version, "12.0.0")) {
@@ -1,13 +1,22 @@
1
1
  "use strict";
2
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
3
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
4
+ var m = o[Symbol.asyncIterator], i;
5
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
6
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
7
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
8
+ };
2
9
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getBuildId = exports.getHeadersFromMetaFiles = exports.getNonStaticServerComponents = exports.getNonStaticRoutes = exports.getMiddlewareMatcherRegexes = exports.allDependencyNames = exports.isUsingAppDirectory = exports.isUsingImageOptimization = exports.isUsingMiddleware = exports.hasUnoptimizedImage = exports.usesNextImage = exports.usesAppDirRouter = exports.getNextjsRewritesToUse = exports.isHeaderSupportedByHosting = exports.isRedirectSupportedByHosting = exports.isRewriteSupportedByHosting = exports.cleanI18n = exports.cleanCustomRouteI18n = exports.cleanEscapedChars = exports.I18N_SOURCE = void 0;
10
+ exports.getNextVersion = exports.getBuildId = exports.getHeadersFromMetaFiles = exports.getNonStaticServerComponents = exports.getNonStaticRoutes = exports.getMiddlewareMatcherRegexes = exports.allDependencyNames = exports.isUsingAppDirectory = exports.isUsingNextImageInAppDirectory = exports.isUsingImageOptimization = exports.isUsingMiddleware = exports.hasUnoptimizedImage = exports.usesNextImage = exports.usesAppDirRouter = exports.getNextjsRewritesToUse = exports.isHeaderSupportedByHosting = exports.isRedirectSupportedByHosting = exports.isRewriteSupportedByHosting = exports.cleanI18n = exports.cleanCustomRouteI18n = exports.cleanEscapedChars = exports.I18N_SOURCE = void 0;
4
11
  const fs_1 = require("fs");
5
12
  const fs_extra_1 = require("fs-extra");
6
13
  const path_1 = require("path");
14
+ const promises_1 = require("fs/promises");
15
+ const glob_1 = require("glob");
16
+ const semver_1 = require("semver");
7
17
  const utils_1 = require("../utils");
8
18
  const constants_1 = require("./constants");
9
19
  const fsutils_1 = require("../../fsutils");
10
- const promises_1 = require("fs/promises");
11
20
  exports.I18N_SOURCE = /\/:nextInternalLocale(\([^\)]+\))?/;
12
21
  function cleanEscapedChars(path) {
13
22
  return path.replace(/\\([(){}:+?*])/g, (a, b) => b);
@@ -84,20 +93,49 @@ async function isUsingMiddleware(dir, isDevMode) {
84
93
  }
85
94
  }
86
95
  exports.isUsingMiddleware = isUsingMiddleware;
87
- async function isUsingImageOptimization(dir) {
88
- let { isNextImageImported } = await (0, utils_1.readJSON)((0, path_1.join)(dir, constants_1.EXPORT_MARKER));
89
- if (!isNextImageImported && isUsingAppDirectory(dir)) {
90
- isNextImageImported = (await (0, promises_1.readFile)((0, path_1.join)(dir, "server", "client-reference-manifest.js")))
91
- .toString()
92
- .includes("node_modules/next/dist/client/image.js");
96
+ async function isUsingImageOptimization(projectDir, distDir) {
97
+ let isNextImageImported = await usesNextImage(projectDir, distDir);
98
+ if (!isNextImageImported && isUsingAppDirectory((0, path_1.join)(projectDir, distDir))) {
99
+ if (await isUsingNextImageInAppDirectory(projectDir, distDir)) {
100
+ isNextImageImported = true;
101
+ }
93
102
  }
94
103
  if (isNextImageImported) {
95
- const imagesManifest = await (0, utils_1.readJSON)((0, path_1.join)(dir, constants_1.IMAGES_MANIFEST));
104
+ const imagesManifest = await (0, utils_1.readJSON)((0, path_1.join)(projectDir, distDir, constants_1.IMAGES_MANIFEST));
96
105
  return !imagesManifest.images.unoptimized;
97
106
  }
98
107
  return false;
99
108
  }
100
109
  exports.isUsingImageOptimization = isUsingImageOptimization;
110
+ async function isUsingNextImageInAppDirectory(projectDir, nextDir) {
111
+ var _a, e_1, _b, _c;
112
+ const { found: files } = new glob_1.Glob((0, path_1.join)(projectDir, nextDir, "server", "**", "*client-reference-manifest.js"));
113
+ try {
114
+ for (var _d = true, files_1 = __asyncValues(files), files_1_1; files_1_1 = await files_1.next(), _a = files_1_1.done, !_a;) {
115
+ _c = files_1_1.value;
116
+ _d = false;
117
+ try {
118
+ const filepath = _c;
119
+ const fileContents = await (0, promises_1.readFile)(filepath);
120
+ if (fileContents.includes("node_modules/next/dist/client/image")) {
121
+ return true;
122
+ }
123
+ }
124
+ finally {
125
+ _d = true;
126
+ }
127
+ }
128
+ }
129
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
130
+ finally {
131
+ try {
132
+ if (!_d && !_a && (_b = files_1.return)) await _b.call(files_1);
133
+ }
134
+ finally { if (e_1) throw e_1.error; }
135
+ }
136
+ return false;
137
+ }
138
+ exports.isUsingNextImageInAppDirectory = isUsingNextImageInAppDirectory;
101
139
  function isUsingAppDirectory(dir) {
102
140
  const appPathRoutesManifestPath = (0, path_1.join)(dir, constants_1.APP_PATH_ROUTES_MANIFEST);
103
141
  return (0, fsutils_1.fileExistsSync)(appPathRoutesManifestPath);
@@ -172,3 +210,13 @@ async function getBuildId(distDir) {
172
210
  return buildId.toString();
173
211
  }
174
212
  exports.getBuildId = getBuildId;
213
+ function getNextVersion(cwd) {
214
+ const dependency = (0, utils_1.findDependency)("next", { cwd, depth: 0, omitDev: false });
215
+ if (!dependency)
216
+ return undefined;
217
+ const nextVersionSemver = (0, semver_1.coerce)(dependency.version);
218
+ if (!nextVersionSemver)
219
+ return dependency.version;
220
+ return nextVersionSemver.toString();
221
+ }
222
+ exports.getNextVersion = getNextVersion;
@@ -1,20 +1,33 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateEndpointSecret = exports.pruneAndDestroySecrets = exports.pruneSecrets = exports.inUse = exports.getSecretVersions = exports.of = exports.ensureSecret = exports.ensureValidKey = exports.ensureApi = exports.labels = exports.isFirebaseManaged = void 0;
3
+ exports.updateEndpointSecret = exports.pruneAndDestroySecrets = exports.pruneSecrets = exports.versionInUse = exports.inUse = exports.getSecretVersions = exports.of = exports.ensureSecret = exports.ensureValidKey = exports.ensureApi = exports.labels = exports.isFirebaseManaged = void 0;
4
4
  const utils = require("../utils");
5
5
  const poller = require("../operation-poller");
6
- const gcf = require("../gcp/cloudfunctions");
6
+ const gcfV1 = require("../gcp/cloudfunctions");
7
+ const gcfV2 = require("../gcp/cloudfunctionsv2");
7
8
  const ensureApiEnabled = require("../ensureApiEnabled");
9
+ const api_1 = require("../api");
8
10
  const secretManager_1 = require("../gcp/secretManager");
9
11
  const error_1 = require("../error");
10
12
  const utils_1 = require("../utils");
11
13
  const prompt_1 = require("../prompt");
12
14
  const env_1 = require("./env");
13
15
  const logger_1 = require("../logger");
14
- const api_1 = require("../api");
15
16
  const functional_1 = require("../functional");
16
17
  const projectUtils_1 = require("../projectUtils");
17
18
  const FIREBASE_MANAGED = "firebase-managed";
19
+ const gcfV1PollerOptions = {
20
+ apiOrigin: api_1.functionsOrigin,
21
+ apiVersion: "v1",
22
+ masterTimeout: 25 * 60 * 1000,
23
+ maxBackoff: 10000,
24
+ };
25
+ const gcfV2PollerOptions = {
26
+ apiOrigin: api_1.functionsV2Origin,
27
+ apiVersion: "v2",
28
+ masterTimeout: 25 * 60 * 1000,
29
+ maxBackoff: 10000,
30
+ };
18
31
  function isFirebaseManaged(secret) {
19
32
  return Object.keys(secret.labels || []).includes(FIREBASE_MANAGED);
20
33
  }
@@ -110,6 +123,18 @@ function inUse(projectInfo, secret, endpoint) {
110
123
  return false;
111
124
  }
112
125
  exports.inUse = inUse;
126
+ function versionInUse(projectInfo, sv, endpoint) {
127
+ const { projectId, projectNumber } = projectInfo;
128
+ for (const sev of of([endpoint])) {
129
+ if ((sev.projectId === projectId || sev.projectId === projectNumber) &&
130
+ sev.secret === sv.secret.name &&
131
+ sev.version === sv.versionId) {
132
+ return true;
133
+ }
134
+ }
135
+ return false;
136
+ }
137
+ exports.versionInUse = versionInUse;
113
138
  async function pruneSecrets(projectInfo, endpoints) {
114
139
  const { projectId, projectNumber } = projectInfo;
115
140
  const pruneKey = (name, version) => `${name}@${version}`;
@@ -191,26 +216,21 @@ async function updateEndpointSecret(projectInfo, secretVersion, endpoint) {
191
216
  updatedSevs.push(updatedSev);
192
217
  }
193
218
  if (endpoint.platform === "gcfv1") {
194
- const fn = gcf.functionFromEndpoint(endpoint, "");
195
- const op = await gcf.updateFunction({
219
+ const fn = gcfV1.functionFromEndpoint(endpoint, "");
220
+ const op = await gcfV1.updateFunction({
196
221
  name: fn.name,
197
222
  runtime: fn.runtime,
198
223
  entryPoint: fn.entryPoint,
199
224
  secretEnvironmentVariables: updatedSevs,
200
225
  });
201
- const gcfV1PollerOptions = {
202
- apiOrigin: api_1.functionsOrigin,
203
- apiVersion: gcf.API_VERSION,
204
- masterTimeout: 25 * 60 * 1000,
205
- maxBackoff: 10000,
206
- pollerName: `update-${endpoint.region}-${endpoint.id}`,
207
- operationResourceName: op.name,
208
- };
209
- const cfn = await poller.pollOperation(gcfV1PollerOptions);
210
- return gcf.endpointFromFunction(cfn);
226
+ const cfn = await poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { operationResourceName: op.name }));
227
+ return gcfV1.endpointFromFunction(cfn);
211
228
  }
212
229
  else if (endpoint.platform === "gcfv2") {
213
- throw new error_1.FirebaseError(`Unsupported platform ${endpoint.platform}`);
230
+ const fn = gcfV2.functionFromEndpoint(endpoint);
231
+ const op = await gcfV2.updateFunction(Object.assign(Object.assign({}, fn), { serviceConfig: Object.assign(Object.assign({}, fn.serviceConfig), { secretEnvironmentVariables: updatedSevs }) }));
232
+ const cfn = await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { operationResourceName: op.name }));
233
+ return gcfV2.endpointFromFunction(cfn);
214
234
  }
215
235
  else {
216
236
  (0, functional_1.assertExhaustive)(endpoint.platform);
@@ -6,16 +6,17 @@ const repl = require("repl");
6
6
  const _ = require("lodash");
7
7
  const request = require("request");
8
8
  const util = require("util");
9
+ const shell = require("./emulator/functionsEmulatorShell");
10
+ const commandUtils = require("./emulator/commandUtils");
9
11
  const functions_1 = require("./serve/functions");
10
- const LocalFunction = require("./localFunction");
12
+ const localFunction_1 = require("./localFunction");
11
13
  const utils = require("./utils");
12
14
  const logger_1 = require("./logger");
13
- const shell = require("./emulator/functionsEmulatorShell");
14
- const commandUtils = require("./emulator/commandUtils");
15
15
  const types_1 = require("./emulator/types");
16
16
  const hubClient_1 = require("./emulator/hubClient");
17
17
  const portUtils_1 = require("./emulator/portUtils");
18
18
  const constants_1 = require("./emulator/constants");
19
+ const projectUtils_1 = require("./projectUtils");
19
20
  const serveFunctions = new functions_1.FunctionsServer();
20
21
  const actionFunction = async (options) => {
21
22
  var _a, _b, _c, _d, _e, _f;
@@ -26,7 +27,7 @@ const actionFunction = async (options) => {
26
27
  if (options.inspectFunctions) {
27
28
  debugPort = commandUtils.parseInspectionPort(options);
28
29
  }
29
- utils.assertDefined(options.project);
30
+ (0, projectUtils_1.needProjectId)(options);
30
31
  const hubClient = new hubClient_1.EmulatorHubClient(options.project);
31
32
  let remoteEmulators = {};
32
33
  if (hubClient.foundHub()) {
@@ -73,9 +74,9 @@ const actionFunction = async (options) => {
73
74
  const initializeContext = (context) => {
74
75
  for (const trigger of emulator.triggers) {
75
76
  if (emulator.emulatedFunctions.includes(trigger.id)) {
76
- const localFunction = new LocalFunction(trigger, emulator.urls, emulator);
77
+ const localFunction = new localFunction_1.default(trigger, emulator.urls, emulator);
77
78
  const triggerNameDotNotation = trigger.name.replace(/-/g, ".");
78
- _.set(context, triggerNameDotNotation, localFunction.call);
79
+ _.set(context, triggerNameDotNotation, localFunction.makeFn());
79
80
  }
80
81
  }
81
82
  context.help =
@@ -168,8 +168,8 @@ async function deleteFunction(cloudFunction) {
168
168
  }
169
169
  }
170
170
  exports.deleteFunction = deleteFunction;
171
- function functionFromEndpoint(endpoint, source) {
172
- var _a, _b;
171
+ function functionFromEndpoint(endpoint) {
172
+ var _a, _b, _c;
173
173
  if (endpoint.platform !== "gcfv2") {
174
174
  throw new error_1.FirebaseError("Trying to create a v2 CloudFunction with v1 API. This should never happen");
175
175
  }
@@ -183,7 +183,7 @@ function functionFromEndpoint(endpoint, source) {
183
183
  runtime: endpoint.runtime,
184
184
  entryPoint: endpoint.entryPoint,
185
185
  source: {
186
- storageSource: source,
186
+ storageSource: (_a = endpoint.source) === null || _a === void 0 ? void 0 : _a.storageSource,
187
187
  },
188
188
  environmentVariables: {},
189
189
  },
@@ -213,7 +213,7 @@ function functionFromEndpoint(endpoint, source) {
213
213
  eventType: endpoint.eventTrigger.eventType,
214
214
  };
215
215
  if (gcfFunction.eventTrigger.eventType === v2_1.PUBSUB_PUBLISH_EVENT) {
216
- if (!((_a = endpoint.eventTrigger.eventFilters) === null || _a === void 0 ? void 0 : _a.topic)) {
216
+ if (!((_b = endpoint.eventTrigger.eventFilters) === null || _b === void 0 ? void 0 : _b.topic)) {
217
217
  throw new error_1.FirebaseError("Error: Pub/Sub event trigger is missing topic: " +
218
218
  JSON.stringify(endpoint.eventTrigger, null, 2));
219
219
  }
@@ -262,7 +262,7 @@ function functionFromEndpoint(endpoint, source) {
262
262
  gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.CODEBASE_LABEL]: codebase });
263
263
  }
264
264
  else {
265
- (_b = gcfFunction.labels) === null || _b === void 0 ? true : delete _b[constants_1.CODEBASE_LABEL];
265
+ (_c = gcfFunction.labels) === null || _c === void 0 ? true : delete _c[constants_1.CODEBASE_LABEL];
266
266
  }
267
267
  if (endpoint.hash) {
268
268
  gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.HASH_LABEL]: endpoint.hash });
@@ -335,7 +335,7 @@ function endpointFromFunction(gcfFunction) {
335
335
  }
336
336
  const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
337
337
  project,
338
- region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime });
338
+ region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime, source: gcfFunction.buildConfig.source });
339
339
  if (gcfFunction.serviceConfig) {
340
340
  proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "ingressSettings", "environmentVariables", "secretEnvironmentVariables", "timeoutSeconds", "uri");
341
341
  proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccount", "serviceAccountEmail");
@@ -346,7 +346,7 @@ function endpointFromFunction(gcfFunction) {
346
346
  }
347
347
  const mem = mebibytes(prod);
348
348
  if (!backend.isValidMemoryOption(mem)) {
349
- logger_1.logger.warn("Converting a function to an endpoint with an invalid memory option", mem);
349
+ logger_1.logger.debug("Converting a function to an endpoint with an invalid memory option", mem);
350
350
  }
351
351
  return mem;
352
352
  });
@@ -1,191 +1,204 @@
1
1
  "use strict";
2
- var _ = require("lodash");
3
- var request = require("request");
4
- var { encodeFirestoreValue } = require("./firestore/encodeFirestoreValue");
5
- var utils = require("./utils");
6
- var LocalFunction = function (trigger, urls, controller) {
7
- const isCallable = _.get(trigger, ["labels", "deployment-callable"], "false");
8
- this.id = trigger.id;
9
- this.name = trigger.name;
10
- this.eventTrigger = trigger.eventTrigger;
11
- this.httpsTrigger = trigger.httpsTrigger;
12
- this.controller = controller;
13
- this.url = _.get(urls, this.id);
14
- if (this.httpsTrigger) {
15
- if (isCallable == "true") {
16
- this.call = this._constructCallableFunc.bind(this);
17
- }
18
- else {
19
- this.call = request.defaults({
20
- callback: this._requestCallBack,
21
- baseUrl: this.url,
22
- uri: "",
23
- });
24
- }
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const request = require("request");
4
+ const utils = require("./utils");
5
+ const encodeFirestoreValue_1 = require("./firestore/encodeFirestoreValue");
6
+ class LocalFunction {
7
+ constructor(trigger, urls, controller) {
8
+ this.trigger = trigger;
9
+ this.controller = controller;
10
+ this.paramWildcardRegex = new RegExp("{[^/{}]*}", "g");
11
+ this.url = urls[trigger.id];
25
12
  }
26
- else {
27
- this.call = this._call.bind(this);
28
- }
29
- };
30
- LocalFunction.prototype._isDatabaseFunc = function (eventTrigger) {
31
- return utils.getFunctionsEventProvider(eventTrigger.eventType) === "Database";
32
- };
33
- LocalFunction.prototype._isFirestoreFunc = function (eventTrigger) {
34
- return utils.getFunctionsEventProvider(eventTrigger.eventType) === "Firestore";
35
- };
36
- LocalFunction.prototype._substituteParams = function (resource, params) {
37
- var wildcardRegex = new RegExp("{[^/{}]*}", "g");
38
- return resource.replace(wildcardRegex, function (wildcard) {
39
- var wildcardNoBraces = wildcard.slice(1, -1);
40
- var sub = _.get(params, wildcardNoBraces);
41
- return sub || wildcardNoBraces + utils.randomInt(1, 9);
42
- });
43
- };
44
- LocalFunction.prototype._constructCallableFunc = function (data, opts) {
45
- opts = opts || {};
46
- var headers = {};
47
- if (opts.instanceIdToken) {
48
- headers["Firebase-Instance-ID-Token"] = opts.instanceIdToken;
13
+ substituteParams(resource, params) {
14
+ if (!params) {
15
+ return resource;
16
+ }
17
+ return resource.replace(this.paramWildcardRegex, (wildcard) => {
18
+ const wildcardNoBraces = wildcard.slice(1, -1);
19
+ const sub = params === null || params === void 0 ? void 0 : params[wildcardNoBraces];
20
+ return sub || `${wildcardNoBraces}${utils.randomInt(1, 9)}`;
21
+ });
49
22
  }
50
- return request.post({
51
- callback: this._requestCallBack,
52
- baseUrl: this.url,
53
- uri: "",
54
- body: { data: data },
55
- json: true,
56
- headers: headers,
57
- });
58
- };
59
- LocalFunction.prototype._constructAuth = function (auth, authType) {
60
- if (_.get(auth, "admin") || _.get(auth, "variable")) {
61
- return auth;
23
+ constructCallableFunc(data, opts) {
24
+ opts = opts || {};
25
+ const headers = {};
26
+ if (opts.instanceIdToken) {
27
+ headers["Firebase-Instance-ID-Token"] = opts.instanceIdToken;
28
+ }
29
+ return request.post({
30
+ callback: (...args) => this.requestCallBack(...args),
31
+ baseUrl: this.url,
32
+ uri: "",
33
+ body: { data },
34
+ json: true,
35
+ headers: headers,
36
+ });
62
37
  }
63
- if (typeof authType !== "undefined") {
64
- switch (authType) {
65
- case "USER":
66
- return {
67
- variable: {
68
- uid: _.get(auth, "uid", ""),
69
- token: _.get(auth, "token", {}),
70
- },
71
- };
72
- case "ADMIN":
73
- if (_.get(auth, "uid") || _.get(auth, "token")) {
74
- throw new Error("authType and auth are incompatible.");
75
- }
76
- return { admin: true };
77
- case "UNAUTHENTICATED":
78
- if (_.get(auth, "uid") || _.get(auth, "token")) {
79
- throw new Error("authType and auth are incompatible.");
80
- }
81
- return { admin: false };
82
- default:
83
- throw new Error("Unrecognized authType, valid values are: " + "ADMIN, USER, and UNAUTHENTICATED");
38
+ constructAuth(auth, authType) {
39
+ var _a, _b, _c;
40
+ if ((auth === null || auth === void 0 ? void 0 : auth.admin) || (auth === null || auth === void 0 ? void 0 : auth.variable)) {
41
+ return {
42
+ admin: auth.admin || false,
43
+ variable: auth.variable,
44
+ };
84
45
  }
46
+ if (authType) {
47
+ switch (authType) {
48
+ case "USER":
49
+ return {
50
+ admin: false,
51
+ variable: {
52
+ uid: (_a = auth === null || auth === void 0 ? void 0 : auth.uid) !== null && _a !== void 0 ? _a : "",
53
+ token: (_b = auth === null || auth === void 0 ? void 0 : auth.token) !== null && _b !== void 0 ? _b : {},
54
+ },
55
+ };
56
+ case "ADMIN":
57
+ if ((auth === null || auth === void 0 ? void 0 : auth.uid) || (auth === null || auth === void 0 ? void 0 : auth.token)) {
58
+ throw new Error("authType and auth are incompatible.");
59
+ }
60
+ return { admin: true };
61
+ case "UNAUTHENTICATED":
62
+ if ((auth === null || auth === void 0 ? void 0 : auth.uid) || (auth === null || auth === void 0 ? void 0 : auth.token)) {
63
+ throw new Error("authType and auth are incompatible.");
64
+ }
65
+ return { admin: false };
66
+ default:
67
+ throw new Error("Unrecognized authType, valid values are: " + "ADMIN, USER, and UNAUTHENTICATED");
68
+ }
69
+ }
70
+ if (auth) {
71
+ return {
72
+ admin: false,
73
+ variable: {
74
+ uid: (_c = auth.uid) !== null && _c !== void 0 ? _c : "",
75
+ token: auth.token || {},
76
+ },
77
+ };
78
+ }
79
+ return { admin: true };
85
80
  }
86
- if (auth) {
81
+ makeFirestoreValue(input) {
82
+ if (typeof input === "undefined" ||
83
+ input === null ||
84
+ (typeof input === "object" && Object.keys(input).length === 0)) {
85
+ return {};
86
+ }
87
+ if (typeof input !== "object") {
88
+ throw new Error("Firestore data must be key-value pairs.");
89
+ }
90
+ const currentTime = new Date().toISOString();
87
91
  return {
88
- variable: {
89
- uid: auth.uid,
90
- token: auth.token || {},
91
- },
92
+ fields: (0, encodeFirestoreValue_1.encodeFirestoreValue)(input),
93
+ createTime: currentTime,
94
+ updateTime: currentTime,
92
95
  };
93
96
  }
94
- return { admin: true };
95
- };
96
- LocalFunction.prototype._makeFirestoreValue = function (input) {
97
- if (typeof input === "undefined" || _.isEmpty(input)) {
98
- return {};
99
- }
100
- if (typeof input !== "object") {
101
- throw new Error("Firestore data must be key-value pairs.");
102
- }
103
- var currentTime = new Date().toISOString();
104
- return {
105
- fields: encodeFirestoreValue(input),
106
- createTime: currentTime,
107
- updateTime: currentTime,
108
- };
109
- };
110
- LocalFunction.prototype._requestCallBack = function (err, response, body) {
111
- if (err) {
112
- return console.warn("\nERROR SENDING REQUEST: " + err);
113
- }
114
- var status = response ? response.statusCode + ", " : "";
115
- var bodyString = body;
116
- if (typeof body === "string") {
117
- try {
118
- bodyString = JSON.stringify(JSON.parse(bodyString), null, 2);
97
+ requestCallBack(err, response, body) {
98
+ if (err) {
99
+ return console.warn("\nERROR SENDING REQUEST: " + err);
119
100
  }
120
- catch (e) {
101
+ const status = response ? response.statusCode + ", " : "";
102
+ let bodyString = body;
103
+ if (typeof bodyString === "string") {
104
+ try {
105
+ bodyString = JSON.stringify(JSON.parse(bodyString), null, 2);
106
+ }
107
+ catch (e) {
108
+ }
109
+ }
110
+ else {
111
+ bodyString = JSON.stringify(body, null, 2);
121
112
  }
113
+ return console.log("\nRESPONSE RECEIVED FROM FUNCTION: " + status + bodyString);
122
114
  }
123
- else {
124
- bodyString = JSON.stringify(body, null, 2);
115
+ isDatabaseFn(eventTrigger) {
116
+ return utils.getFunctionsEventProvider(eventTrigger.eventType) === "Database";
125
117
  }
126
- return console.log("\nRESPONSE RECEIVED FROM FUNCTION: " + status + bodyString);
127
- };
128
- LocalFunction.prototype._call = function (data, opts) {
129
- opts = opts || {};
130
- var operationType;
131
- var dataPayload;
132
- if (this.httpsTrigger) {
133
- this.controller.call(this.name, data || {});
118
+ isFirestoreFunc(eventTrigger) {
119
+ return utils.getFunctionsEventProvider(eventTrigger.eventType) === "Firestore";
134
120
  }
135
- else if (this.eventTrigger) {
136
- if (this._isDatabaseFunc(this.eventTrigger)) {
137
- operationType = utils.last(this.eventTrigger.eventType.split("."));
138
- switch (operationType) {
139
- case "create":
140
- dataPayload = {
141
- data: null,
142
- delta: data,
143
- };
144
- break;
145
- case "delete":
146
- dataPayload = {
147
- data: data,
148
- delta: null,
149
- };
150
- break;
151
- default:
152
- dataPayload = {
153
- data: data.before,
154
- delta: data.after,
155
- };
121
+ triggerEvent(data, opts) {
122
+ opts = opts || {};
123
+ let operationType;
124
+ let dataPayload;
125
+ if (this.trigger.httpsTrigger) {
126
+ this.controller.call(this.trigger.name, data || {}, opts);
127
+ }
128
+ else if (this.trigger.eventTrigger) {
129
+ if (this.isDatabaseFn(this.trigger.eventTrigger)) {
130
+ operationType = utils.last(this.trigger.eventTrigger.eventType.split("."));
131
+ switch (operationType) {
132
+ case "create":
133
+ dataPayload = {
134
+ data: null,
135
+ delta: data,
136
+ };
137
+ break;
138
+ case "delete":
139
+ dataPayload = {
140
+ data: data,
141
+ delta: null,
142
+ };
143
+ break;
144
+ default:
145
+ dataPayload = {
146
+ data: data.before,
147
+ delta: data.after,
148
+ };
149
+ }
150
+ opts.resource = this.substituteParams(this.trigger.eventTrigger.resource, opts.params);
151
+ opts.auth = this.constructAuth(opts.auth, opts.authType);
152
+ this.controller.call(this.trigger.name, dataPayload, opts);
153
+ }
154
+ else if (this.isFirestoreFunc(this.trigger.eventTrigger)) {
155
+ operationType = utils.last(this.trigger.eventTrigger.eventType.split("."));
156
+ switch (operationType) {
157
+ case "create":
158
+ dataPayload = {
159
+ value: this.makeFirestoreValue(data),
160
+ oldValue: {},
161
+ };
162
+ break;
163
+ case "delete":
164
+ dataPayload = {
165
+ value: {},
166
+ oldValue: this.makeFirestoreValue(data),
167
+ };
168
+ break;
169
+ default:
170
+ dataPayload = {
171
+ value: this.makeFirestoreValue(data.after),
172
+ oldValue: this.makeFirestoreValue(data.before),
173
+ };
174
+ }
175
+ opts.resource = this.substituteParams(this.trigger.eventTrigger.resource, opts.params);
176
+ this.controller.call(this.trigger.name, dataPayload, opts);
177
+ }
178
+ else {
179
+ this.controller.call(this.trigger.name, data || {}, opts);
156
180
  }
157
- opts.resource = this._substituteParams(this.eventTrigger.resource, opts.params);
158
- opts.auth = this._constructAuth(opts.auth, opts.authType);
159
- this.controller.call(this.name, dataPayload, opts);
160
181
  }
161
- else if (this._isFirestoreFunc(this.eventTrigger)) {
162
- operationType = utils.last(this.eventTrigger.eventType.split("."));
163
- switch (operationType) {
164
- case "create":
165
- dataPayload = {
166
- value: this._makeFirestoreValue(data),
167
- oldValue: {},
168
- };
169
- break;
170
- case "delete":
171
- dataPayload = {
172
- value: {},
173
- oldValue: this._makeFirestoreValue(data),
174
- };
175
- break;
176
- default:
177
- dataPayload = {
178
- value: this._makeFirestoreValue(data.after),
179
- oldValue: this._makeFirestoreValue(data.before),
180
- };
182
+ return console.log("Successfully invoked function.");
183
+ }
184
+ makeFn() {
185
+ var _a;
186
+ if (this.trigger.httpsTrigger) {
187
+ const isCallable = !!((_a = this.trigger.labels) === null || _a === void 0 ? void 0 : _a["deployment-callable"]);
188
+ if (isCallable) {
189
+ return (data, opt) => this.constructCallableFunc(data, opt);
190
+ }
191
+ else {
192
+ return request.defaults({
193
+ callback: (...args) => this.requestCallBack(...args),
194
+ baseUrl: this.url,
195
+ uri: "",
196
+ });
181
197
  }
182
- opts.resource = this._substituteParams(this.eventTrigger.resource, opts.params);
183
- this.controller.call(this.name, dataPayload, opts);
184
198
  }
185
199
  else {
186
- this.controller.call(this.name, data || {}, opts);
200
+ return (data, opt) => this.triggerEvent(data, opt);
187
201
  }
188
202
  }
189
- return "Successfully invoked function.";
190
- };
191
- module.exports = LocalFunction;
203
+ }
204
+ exports.default = LocalFunction;
@@ -24,6 +24,14 @@ async function autoAuth(options, authScopes) {
24
24
  const client = getAuthClient({ scopes: authScopes, projectId: options.project });
25
25
  const token = await client.getAccessToken();
26
26
  token !== null ? apiv2.setAccessToken(token) : false;
27
+ let clientEmail;
28
+ try {
29
+ const credentials = await client.getCredentials();
30
+ clientEmail = credentials.client_email;
31
+ }
32
+ catch (e) {
33
+ logger_1.logger.debug(`Error getting account credentials.`);
34
+ }
27
35
  if (!options.isVSCE && (0, monospace_1.isMonospaceEnv)()) {
28
36
  await (0, monospace_1.selectProjectInMonospace)({
29
37
  projectRoot: options.config.projectDir,
@@ -31,6 +39,7 @@ async function autoAuth(options, authScopes) {
31
39
  isVSCE: options.isVSCE,
32
40
  });
33
41
  }
42
+ return clientEmail;
34
43
  }
35
44
  async function requireAuth(options) {
36
45
  api.setScopes([scopes.CLOUD_PLATFORM, scopes.FIREBASE_PLATFORM]);
package/lib/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.openInBrowser = exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
3
+ exports.openInBrowser = exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
4
4
  const _ = require("lodash");
5
5
  const url = require("url");
6
6
  const clc = require("colorette");
@@ -375,14 +375,6 @@ function thirtyDaysFromNow() {
375
375
  return new Date(Date.now() + THIRTY_DAYS_IN_MILLISECONDS);
376
376
  }
377
377
  exports.thirtyDaysFromNow = thirtyDaysFromNow;
378
- function assertDefined(val, message) {
379
- if (val === undefined || val === null) {
380
- throw new assert_1.AssertionError({
381
- message: message || `expected value to be defined but got "${val}"`,
382
- });
383
- }
384
- }
385
- exports.assertDefined = assertDefined;
386
378
  function assertIsString(val, message) {
387
379
  if (typeof val !== "string") {
388
380
  throw new assert_1.AssertionError({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "12.4.3",
3
+ "version": "12.4.5",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -99,11 +99,11 @@
99
99
  "p-limit": "^3.0.1",
100
100
  "portfinder": "^1.0.32",
101
101
  "progress": "^2.0.3",
102
- "proxy-agent": "^5.0.0",
102
+ "proxy-agent": "^6.3.0",
103
103
  "request": "^2.87.0",
104
104
  "retry": "^0.13.1",
105
105
  "rimraf": "^3.0.0",
106
- "semver": "^5.7.1",
106
+ "semver": "^7.5.2",
107
107
  "stream-chain": "^2.2.4",
108
108
  "stream-json": "^1.7.3",
109
109
  "strip-ansi": "^6.0.1",
@@ -12,7 +12,7 @@
12
12
  "license": "MIT",
13
13
  "dependencies": {
14
14
  "chalk": "^2.4.2",
15
- "npm": "^6.10.2",
15
+ "npm": "^9.8.0",
16
16
  "shelljs": "^0.8.3",
17
17
  "shx": "^0.3.2",
18
18
  "user-home": "^2.0.0"
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.listDatabaseInstances = void 0;
4
- const api_1 = require("../api");
5
- const apiv2_1 = require("../apiv2");
6
- const logger_1 = require("../logger");
7
- const utils = require("../utils");
8
- function _handleErrorResponse(response) {
9
- if (response.body && response.body.error) {
10
- return utils.reject(response.body.error, { code: 2 });
11
- }
12
- logger_1.logger.debug("[firedata] error:", response.status, response.body);
13
- return utils.reject("Unexpected error encountered with FireData.", {
14
- code: 2,
15
- });
16
- }
17
- async function listDatabaseInstances(projectNumber) {
18
- const client = new apiv2_1.Client({ urlPrefix: api_1.firedataOrigin, apiVersion: "v1" });
19
- const response = await client.get(`/projects/${projectNumber}/databases`, {
20
- resolveOnHTTPError: true,
21
- });
22
- if (response.status === 200) {
23
- return response.body.instance;
24
- }
25
- return _handleErrorResponse(response);
26
- }
27
- exports.listDatabaseInstances = listDatabaseInstances;