firebase-tools 13.22.1 → 13.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/lib/apiv2.js +2 -2
  2. package/lib/apphosting/backend.js +294 -0
  3. package/lib/apphosting/githubConnections.js +54 -23
  4. package/lib/apphosting/index.js +3 -260
  5. package/lib/apphosting/rollout.js +12 -9
  6. package/lib/bin/firebase.js +2 -2
  7. package/lib/commands/apphosting-backends-create.js +4 -4
  8. package/lib/commands/apphosting-backends-delete.js +4 -14
  9. package/lib/commands/apphosting-repos-create.js +23 -0
  10. package/lib/commands/apphosting-rollouts-create.js +3 -4
  11. package/lib/commands/apphosting-secrets-grantaccess.js +2 -2
  12. package/lib/commands/dataconnect-sql-shell.js +111 -0
  13. package/lib/commands/index.js +3 -0
  14. package/lib/commands/init.js +6 -6
  15. package/lib/dataconnect/schemaMigration.js +2 -1
  16. package/lib/deploy/functions/services/auth.js +40 -15
  17. package/lib/deploy/functions/services/index.js +2 -0
  18. package/lib/emulator/commandUtils.js +2 -2
  19. package/lib/emulator/downloadableEmulators.js +9 -9
  20. package/lib/emulator/functionsEmulator.js +0 -2
  21. package/lib/emulator/loggingEmulator.js +2 -2
  22. package/lib/firestore/delete.js +11 -0
  23. package/lib/frameworks/next/index.js +9 -1
  24. package/lib/frameworks/next/utils.js +7 -4
  25. package/lib/frameworks/vite/index.js +2 -2
  26. package/lib/functions/constants.js +4 -0
  27. package/lib/functions/events/v1.js +9 -2
  28. package/lib/gcp/apphosting.js +1 -1
  29. package/lib/gcp/cloudsql/interactive.js +49 -0
  30. package/lib/gcp/firestore.js +5 -1
  31. package/lib/init/features/apphosting.js +3 -0
  32. package/lib/responseToError.js +5 -2
  33. package/lib/utils.js +2 -2
  34. package/package.json +1 -2
@@ -27,18 +27,22 @@ class AuthBlockingService {
27
27
  }
28
28
  }
29
29
  configChanged(newConfig, config) {
30
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
30
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
31
31
  if (((_b = (_a = newConfig.triggers) === null || _a === void 0 ? void 0 : _a.beforeCreate) === null || _b === void 0 ? void 0 : _b.functionUri) !==
32
32
  ((_d = (_c = config.triggers) === null || _c === void 0 ? void 0 : _c.beforeCreate) === null || _d === void 0 ? void 0 : _d.functionUri) ||
33
- ((_f = (_e = newConfig.triggers) === null || _e === void 0 ? void 0 : _e.beforeSignIn) === null || _f === void 0 ? void 0 : _f.functionUri) !== ((_h = (_g = config.triggers) === null || _g === void 0 ? void 0 : _g.beforeSignIn) === null || _h === void 0 ? void 0 : _h.functionUri)) {
33
+ ((_f = (_e = newConfig.triggers) === null || _e === void 0 ? void 0 : _e.beforeSignIn) === null || _f === void 0 ? void 0 : _f.functionUri) !==
34
+ ((_h = (_g = config.triggers) === null || _g === void 0 ? void 0 : _g.beforeSignIn) === null || _h === void 0 ? void 0 : _h.functionUri) ||
35
+ ((_k = (_j = newConfig.triggers) === null || _j === void 0 ? void 0 : _j.beforeSendEmail) === null || _k === void 0 ? void 0 : _k.functionUri) !==
36
+ ((_m = (_l = config.triggers) === null || _l === void 0 ? void 0 : _l.beforeSendEmail) === null || _m === void 0 ? void 0 : _m.functionUri) ||
37
+ ((_p = (_o = newConfig.triggers) === null || _o === void 0 ? void 0 : _o.beforeSendSms) === null || _p === void 0 ? void 0 : _p.functionUri) !== ((_r = (_q = config.triggers) === null || _q === void 0 ? void 0 : _q.beforeSendSms) === null || _r === void 0 ? void 0 : _r.functionUri)) {
34
38
  return true;
35
39
  }
36
- if (!!((_j = newConfig.forwardInboundCredentials) === null || _j === void 0 ? void 0 : _j.accessToken) !==
37
- !!((_k = config.forwardInboundCredentials) === null || _k === void 0 ? void 0 : _k.accessToken) ||
38
- !!((_l = newConfig.forwardInboundCredentials) === null || _l === void 0 ? void 0 : _l.idToken) !==
39
- !!((_m = config.forwardInboundCredentials) === null || _m === void 0 ? void 0 : _m.idToken) ||
40
- !!((_o = newConfig.forwardInboundCredentials) === null || _o === void 0 ? void 0 : _o.refreshToken) !==
41
- !!((_p = config.forwardInboundCredentials) === null || _p === void 0 ? void 0 : _p.refreshToken)) {
40
+ if (!!((_s = newConfig.forwardInboundCredentials) === null || _s === void 0 ? void 0 : _s.accessToken) !==
41
+ !!((_t = config.forwardInboundCredentials) === null || _t === void 0 ? void 0 : _t.accessToken) ||
42
+ !!((_u = newConfig.forwardInboundCredentials) === null || _u === void 0 ? void 0 : _u.idToken) !==
43
+ !!((_v = config.forwardInboundCredentials) === null || _v === void 0 ? void 0 : _v.idToken) ||
44
+ !!((_w = newConfig.forwardInboundCredentials) === null || _w === void 0 ? void 0 : _w.refreshToken) !==
45
+ !!((_x = config.forwardInboundCredentials) === null || _x === void 0 ? void 0 : _x.refreshToken)) {
42
46
  return true;
43
47
  }
44
48
  return false;
@@ -51,11 +55,24 @@ class AuthBlockingService {
51
55
  functionUri: endpoint.uri,
52
56
  } });
53
57
  }
54
- else {
58
+ else if (endpoint.blockingTrigger.eventType === events.v1.BEFORE_SIGN_IN_EVENT) {
55
59
  newBlockingConfig.triggers = Object.assign(Object.assign({}, newBlockingConfig.triggers), { beforeSignIn: {
56
60
  functionUri: endpoint.uri,
57
61
  } });
58
62
  }
63
+ else if (endpoint.blockingTrigger.eventType === events.v1.BEFORE_SEND_EMAIL_EVENT) {
64
+ newBlockingConfig.triggers = Object.assign(Object.assign({}, newBlockingConfig.triggers), { beforeSendEmail: {
65
+ functionUri: endpoint.uri,
66
+ } });
67
+ }
68
+ else if (endpoint.blockingTrigger.eventType === events.v1.BEFORE_SEND_SMS_EVENT) {
69
+ newBlockingConfig.triggers = Object.assign(Object.assign({}, newBlockingConfig.triggers), { beforeSendSms: {
70
+ functionUri: endpoint.uri,
71
+ } });
72
+ }
73
+ else {
74
+ throw new error_1.FirebaseError(`Received invalid blocking trigger event type ${endpoint.blockingTrigger.eventType}`);
75
+ }
59
76
  newBlockingConfig.forwardInboundCredentials = Object.assign(Object.assign({}, oldBlockingConfig.forwardInboundCredentials), endpoint.blockingTrigger.options);
60
77
  if (!this.configChanged(newBlockingConfig, oldBlockingConfig)) {
61
78
  return;
@@ -70,17 +87,25 @@ class AuthBlockingService {
70
87
  return this.triggerQueue;
71
88
  }
72
89
  async unregisterTriggerLocked(endpoint) {
73
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
90
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
74
91
  const blockingConfig = await identityPlatform.getBlockingFunctionsConfig(endpoint.project);
75
92
  if (endpoint.uri !== ((_b = (_a = blockingConfig.triggers) === null || _a === void 0 ? void 0 : _a.beforeCreate) === null || _b === void 0 ? void 0 : _b.functionUri) &&
76
- endpoint.uri !== ((_d = (_c = blockingConfig.triggers) === null || _c === void 0 ? void 0 : _c.beforeSignIn) === null || _d === void 0 ? void 0 : _d.functionUri)) {
93
+ endpoint.uri !== ((_d = (_c = blockingConfig.triggers) === null || _c === void 0 ? void 0 : _c.beforeSignIn) === null || _d === void 0 ? void 0 : _d.functionUri) &&
94
+ endpoint.uri !== ((_f = (_e = blockingConfig.triggers) === null || _e === void 0 ? void 0 : _e.beforeSendEmail) === null || _f === void 0 ? void 0 : _f.functionUri) &&
95
+ endpoint.uri !== ((_h = (_g = blockingConfig.triggers) === null || _g === void 0 ? void 0 : _g.beforeSendSms) === null || _h === void 0 ? void 0 : _h.functionUri)) {
77
96
  return;
78
97
  }
79
- if (endpoint.uri === ((_f = (_e = blockingConfig.triggers) === null || _e === void 0 ? void 0 : _e.beforeCreate) === null || _f === void 0 ? void 0 : _f.functionUri)) {
80
- (_g = blockingConfig.triggers) === null || _g === void 0 ? true : delete _g.beforeCreate;
98
+ if (endpoint.uri === ((_k = (_j = blockingConfig.triggers) === null || _j === void 0 ? void 0 : _j.beforeCreate) === null || _k === void 0 ? void 0 : _k.functionUri)) {
99
+ (_l = blockingConfig.triggers) === null || _l === void 0 ? true : delete _l.beforeCreate;
100
+ }
101
+ if (endpoint.uri === ((_o = (_m = blockingConfig.triggers) === null || _m === void 0 ? void 0 : _m.beforeSignIn) === null || _o === void 0 ? void 0 : _o.functionUri)) {
102
+ (_p = blockingConfig.triggers) === null || _p === void 0 ? true : delete _p.beforeSignIn;
103
+ }
104
+ if (endpoint.uri === ((_r = (_q = blockingConfig.triggers) === null || _q === void 0 ? void 0 : _q.beforeSendEmail) === null || _r === void 0 ? void 0 : _r.functionUri)) {
105
+ (_s = blockingConfig.triggers) === null || _s === void 0 ? true : delete _s.beforeSendEmail;
81
106
  }
82
- if (endpoint.uri === ((_j = (_h = blockingConfig.triggers) === null || _h === void 0 ? void 0 : _h.beforeSignIn) === null || _j === void 0 ? void 0 : _j.functionUri)) {
83
- (_k = blockingConfig.triggers) === null || _k === void 0 ? true : delete _k.beforeSignIn;
107
+ if (endpoint.uri === ((_u = (_t = blockingConfig.triggers) === null || _t === void 0 ? void 0 : _t.beforeSendSms) === null || _u === void 0 ? void 0 : _u.functionUri)) {
108
+ (_v = blockingConfig.triggers) === null || _v === void 0 ? true : delete _v.beforeSendSms;
84
109
  }
85
110
  await identityPlatform.setBlockingFunctionsConfig(endpoint.project, blockingConfig);
86
111
  }
@@ -94,6 +94,8 @@ const EVENT_SERVICE_MAPPING = {
94
94
  "google.firebase.firebasealerts.alerts.v1.published": firebaseAlertsService,
95
95
  "providers/cloud.auth/eventTypes/user.beforeCreate": authBlockingService,
96
96
  "providers/cloud.auth/eventTypes/user.beforeSignIn": authBlockingService,
97
+ "providers/cloud.auth/eventTypes/user.beforeSendEmail": authBlockingService,
98
+ "providers/cloud.auth/eventTypes/user.beforeSendSms": authBlockingService,
97
99
  "google.firebase.database.ref.v1.written": databaseService,
98
100
  "google.firebase.database.ref.v1.created": databaseService,
99
101
  "google.firebase.database.ref.v1.updated": databaseService,
@@ -384,5 +384,5 @@ async function checkJavaMajorVersion() {
384
384
  }
385
385
  exports.checkJavaMajorVersion = checkJavaMajorVersion;
386
386
  exports.MIN_SUPPORTED_JAVA_MAJOR_VERSION = 11;
387
- exports.JAVA_DEPRECATION_WARNING = "firebase-tools no longer supports Java version before 11. " +
388
- "Please upgrade to Java version 11 or above to continue using the emulators.";
387
+ exports.JAVA_DEPRECATION_WARNING = "firebase-tools no longer supports Java versions before 11. " +
388
+ "Please install a JDK at version 11 or above to get a compatible runtime.";
@@ -48,20 +48,20 @@ const EMULATOR_UPDATE_DETAILS = {
48
48
  },
49
49
  dataconnect: process.platform === "darwin"
50
50
  ? {
51
- version: "1.5.1",
52
- expectedSize: 25289472,
53
- expectedChecksum: "92c425072db66c7e2cfa40b703ed807b",
51
+ version: "1.6.0",
52
+ expectedSize: 25301760,
53
+ expectedChecksum: "4fad7ada11b35ecea6c8aadf132a5a8a",
54
54
  }
55
55
  : process.platform === "win32"
56
56
  ? {
57
- version: "1.5.1",
58
- expectedSize: 25720320,
59
- expectedChecksum: "2a5c654770233b740980d5f98f24be73",
57
+ version: "1.6.0",
58
+ expectedSize: 25731072,
59
+ expectedChecksum: "8d3a59cc79cd74199ee1d8c28012297f",
60
60
  }
61
61
  : {
62
- version: "1.5.1",
63
- expectedSize: 25202840,
64
- expectedChecksum: "f95156cbcac237268791638ea0eb10e7",
62
+ version: "1.6.0",
63
+ expectedSize: 25219224,
64
+ expectedChecksum: "ceb10cfca7ded004c48f7724dbc0cccf",
65
65
  },
66
66
  };
67
67
  exports.DownloadDetails = {
@@ -256,13 +256,11 @@ class FunctionsEmulator {
256
256
  }
257
257
  async start() {
258
258
  const credentialEnv = await this.getCredentialsEnvironment();
259
- console.log("got creds env");
260
259
  for (const e of this.staticBackends) {
261
260
  e.env = Object.assign(Object.assign({}, credentialEnv), e.env);
262
261
  }
263
262
  if (Object.keys(this.adminSdkConfig || {}).length <= 1) {
264
263
  const adminSdkConfig = await (0, adminSdkConfig_1.getProjectAdminSdkConfigOrCached)(this.args.projectId);
265
- console.log("got admin sdk");
266
264
  if (adminSdkConfig) {
267
265
  this.adminSdkConfig = adminSdkConfig;
268
266
  }
@@ -7,7 +7,7 @@ const triple_beam_1 = require("triple-beam");
7
7
  const WebSocket = require("ws");
8
8
  const TransportStream = require("winston-transport");
9
9
  const logger_1 = require("../logger");
10
- const stripAnsi = require("strip-ansi");
10
+ const node_util_1 = require("node:util");
11
11
  class LoggingEmulator {
12
12
  constructor(args) {
13
13
  this.args = args;
@@ -106,7 +106,7 @@ class WebSocketTransport extends TransportStream {
106
106
  if (bundle.data && bundle.data.metadata && bundle.data.metadata.message) {
107
107
  bundle.message = bundle.data.metadata.message;
108
108
  }
109
- bundle.message = stripAnsi(bundle.message);
109
+ bundle.message = (0, node_util_1.stripVTControlCharacters)(bundle.message);
110
110
  this.history.push(bundle);
111
111
  this.connections.forEach((ws) => {
112
112
  ws.send(JSON.stringify(bundle));
@@ -237,6 +237,17 @@ class FirestoreDelete {
237
237
  }
238
238
  queue.unshift(...toDelete);
239
239
  }
240
+ else if (e.status === 429 &&
241
+ this.deleteBatchSize >= 10 &&
242
+ e.message.includes("database has exceeded their maximum bandwidth")) {
243
+ logger_1.logger.debug("Database has exceeded maximum write bandwidth", e);
244
+ const newBatchSize = Math.floor(toDelete.length / 2);
245
+ if (newBatchSize < this.deleteBatchSize) {
246
+ utils.logLabeledWarning("firestore", `delete rate exceeding maximum bandwidth, reducing batch size from ${this.deleteBatchSize} to ${newBatchSize}`);
247
+ this.setDeleteBatchSize(newBatchSize);
248
+ }
249
+ queue.unshift(...toDelete);
250
+ }
240
251
  else if (e.status >= 500 && e.status < 600) {
241
252
  logger_1.logger.debug("Server error deleting doc batch", e);
242
253
  toDelete.forEach((doc) => {
@@ -126,8 +126,11 @@ async function build(dir, target, context) {
126
126
  (0, utils_1.readJSON)((0, path_1.join)(dir, distDir, "server", constants_2.SERVER_REFERENCE_MANIFEST)).catch(() => undefined),
127
127
  ]);
128
128
  if (appPathRoutesManifest) {
129
- const headersFromMetaFiles = await (0, utils_2.getHeadersFromMetaFiles)(dir, distDir, baseUrl, appPathRoutesManifest);
129
+ const { headers: headersFromMetaFiles, pprRoutes } = await (0, utils_2.getAppMetadataFromMetaFiles)(dir, distDir, baseUrl, appPathRoutesManifest);
130
130
  headers.push(...headersFromMetaFiles);
131
+ for (const route of pprRoutes) {
132
+ reasonsForBackend.add(`route with ppr ${route}`);
133
+ }
131
134
  if (appPathsManifest) {
132
135
  const unrenderedServerComponents = (0, utils_2.getNonStaticServerComponents)(appPathsManifest, appPathRoutesManifest, prerenderedRoutes, dynamicRoutes);
133
136
  const notFoundPageKey = ["/_not-found", "/_not-found/page"].find((key) => unrenderedServerComponents.has(key));
@@ -270,6 +273,7 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
270
273
  ];
271
274
  }));
272
275
  const routesToCopy = Object.assign(Object.assign({}, prerenderManifest.routes), pagesManifestLikePrerender);
276
+ const { pprRoutes } = await (0, utils_2.getAppMetadataFromMetaFiles)(sourceDir, distDir, basePath, appPathRoutesManifest);
273
277
  await Promise.all(Object.entries(routesToCopy).map(async ([path, route]) => {
274
278
  var _a, _b;
275
279
  if (route.initialRevalidateSeconds) {
@@ -308,6 +312,10 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
308
312
  let defaultDestPath = isDefaultLocale && (0, path_1.join)(destDir, basePath, ...destPartsOrIndex);
309
313
  if (!(0, fsutils_1.fileExistsSync)(sourcePath) && (0, fsutils_1.fileExistsSync)(`${sourcePath}.html`)) {
310
314
  sourcePath += ".html";
315
+ if (pprRoutes.includes(path)) {
316
+ logger_1.logger.debug(`skipping ${path} due to ppr`);
317
+ return;
318
+ }
311
319
  if (localizedDestPath)
312
320
  localizedDestPath += ".html";
313
321
  if (defaultDestPath)
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.installEsbuild = exports.getGlobalEsbuildVersion = exports.findEsbuildPath = exports.whichNextConfigFile = exports.getProductionDistDirFiles = exports.getRoutesWithServerAction = exports.hasStaticAppNotFoundComponent = 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;
3
+ exports.installEsbuild = exports.getGlobalEsbuildVersion = exports.findEsbuildPath = exports.whichNextConfigFile = exports.getProductionDistDirFiles = exports.getRoutesWithServerAction = exports.hasStaticAppNotFoundComponent = exports.getNextVersion = exports.getBuildId = exports.getAppMetadataFromMetaFiles = 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
4
  const fs_1 = require("fs");
5
5
  const fs_extra_1 = require("fs-extra");
6
6
  const path_1 = require("path");
@@ -167,8 +167,9 @@ function getNonStaticServerComponents(appPathsManifest, appPathRoutesManifest, p
167
167
  return new Set(nonStaticServerComponents);
168
168
  }
169
169
  exports.getNonStaticServerComponents = getNonStaticServerComponents;
170
- async function getHeadersFromMetaFiles(sourceDir, distDir, basePath, appPathRoutesManifest) {
170
+ async function getAppMetadataFromMetaFiles(sourceDir, distDir, basePath, appPathRoutesManifest) {
171
171
  const headers = [];
172
+ const pprRoutes = [];
172
173
  await Promise.all(Object.entries(appPathRoutesManifest).map(async ([key, source]) => {
173
174
  if (!["route", "page"].includes((0, path_1.basename)(key)))
174
175
  return;
@@ -183,11 +184,13 @@ async function getHeadersFromMetaFiles(sourceDir, distDir, basePath, appPathRout
183
184
  source: path_1.posix.join(basePath, source),
184
185
  headers: Object.entries(meta.headers).map(([key, value]) => ({ key, value })),
185
186
  });
187
+ if (meta.postponed)
188
+ pprRoutes.push(source);
186
189
  }
187
190
  }));
188
- return headers;
191
+ return { headers, pprRoutes };
189
192
  }
190
- exports.getHeadersFromMetaFiles = getHeadersFromMetaFiles;
193
+ exports.getAppMetadataFromMetaFiles = getAppMetadataFromMetaFiles;
191
194
  async function getBuildId(distDir) {
192
195
  const buildId = await (0, promises_1.readFile)((0, path_1.join)(distDir, "BUILD_ID"));
193
196
  return buildId.toString();
@@ -6,7 +6,7 @@ const cross_spawn_1 = require("cross-spawn");
6
6
  const fs_1 = require("fs");
7
7
  const fs_extra_1 = require("fs-extra");
8
8
  const path_1 = require("path");
9
- const stripAnsi = require("strip-ansi");
9
+ const node_util_1 = require("node:util");
10
10
  const prompt_1 = require("../../prompt");
11
11
  const utils_1 = require("../utils");
12
12
  exports.name = "Vite";
@@ -94,7 +94,7 @@ async function getDevModeHandle(dir) {
94
94
  const serve = (0, cross_spawn_1.spawn)(cli, [], { cwd: dir });
95
95
  serve.stdout.on("data", (data) => {
96
96
  process.stdout.write(data);
97
- const dataWithoutAnsiCodes = stripAnsi(data.toString());
97
+ const dataWithoutAnsiCodes = (0, node_util_1.stripVTControlCharacters)(data.toString());
98
98
  const match = dataWithoutAnsiCodes.match(/(http:\/\/.+:\d+)/);
99
99
  if (match)
100
100
  resolve(match[1]);
@@ -7,8 +7,12 @@ exports.BLOCKING_LABEL = "deployment-blocking";
7
7
  exports.BLOCKING_LABEL_KEY_TO_EVENT = {
8
8
  "before-create": "providers/cloud.auth/eventTypes/user.beforeCreate",
9
9
  "before-sign-in": "providers/cloud.auth/eventTypes/user.beforeSignIn",
10
+ "before-send-email": "providers/cloud.auth/eventTypes/user.beforeSendEmail",
11
+ "before-send-sms": "providers/cloud.auth/eventTypes/user.beforeSendSms",
10
12
  };
11
13
  exports.BLOCKING_EVENT_TO_LABEL_KEY = {
12
14
  "providers/cloud.auth/eventTypes/user.beforeCreate": "before-create",
13
15
  "providers/cloud.auth/eventTypes/user.beforeSignIn": "before-sign-in",
16
+ "providers/cloud.auth/eventTypes/user.beforeSendEmail": "before-send-email",
17
+ "providers/cloud.auth/eventTypes/user.beforeSendSms": "before-send-sms",
14
18
  };
@@ -1,6 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AUTH_BLOCKING_EVENTS = exports.BEFORE_SIGN_IN_EVENT = exports.BEFORE_CREATE_EVENT = void 0;
3
+ exports.AUTH_BLOCKING_EVENTS = exports.BEFORE_SEND_SMS_EVENT = exports.BEFORE_SEND_EMAIL_EVENT = exports.BEFORE_SIGN_IN_EVENT = exports.BEFORE_CREATE_EVENT = void 0;
4
4
  exports.BEFORE_CREATE_EVENT = "providers/cloud.auth/eventTypes/user.beforeCreate";
5
5
  exports.BEFORE_SIGN_IN_EVENT = "providers/cloud.auth/eventTypes/user.beforeSignIn";
6
- exports.AUTH_BLOCKING_EVENTS = [exports.BEFORE_CREATE_EVENT, exports.BEFORE_SIGN_IN_EVENT];
6
+ exports.BEFORE_SEND_EMAIL_EVENT = "providers/cloud.auth/eventTypes/user.beforeSendEmail";
7
+ exports.BEFORE_SEND_SMS_EVENT = "providers/cloud.auth/eventTypes/user.beforeSendSms";
8
+ exports.AUTH_BLOCKING_EVENTS = [
9
+ exports.BEFORE_CREATE_EVENT,
10
+ exports.BEFORE_SIGN_IN_EVENT,
11
+ exports.BEFORE_SEND_EMAIL_EVENT,
12
+ exports.BEFORE_SEND_SMS_EVENT,
13
+ ];
@@ -9,7 +9,7 @@ const ensureApiEnabled_1 = require("../ensureApiEnabled");
9
9
  const deploymentTool = require("../deploymentTool");
10
10
  const error_1 = require("../error");
11
11
  const metaprogramming_1 = require("../metaprogramming");
12
- exports.API_VERSION = "v1alpha";
12
+ exports.API_VERSION = "v1beta";
13
13
  exports.client = new apiv2_1.Client({
14
14
  urlPrefix: (0, api_1.apphostingOrigin)(),
15
15
  auth: true,
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.interactiveExecuteQuery = exports.confirmDangerousQuery = void 0;
4
+ const ora = require("ora");
5
+ const clc = require("colorette");
6
+ const logger_1 = require("../../logger");
7
+ const prompt_1 = require("../../prompt");
8
+ const Table = require("cli-table");
9
+ const destructiveSqlKeywords = ["DROP", "DELETE"];
10
+ function checkIsDestructiveSql(query) {
11
+ const upperCaseQuery = query.toUpperCase();
12
+ return destructiveSqlKeywords.some((keyword) => upperCaseQuery.includes(keyword.toUpperCase()));
13
+ }
14
+ async function confirmDangerousQuery(query) {
15
+ if (checkIsDestructiveSql(query)) {
16
+ return await (0, prompt_1.confirm)({
17
+ message: clc.yellow("This query may be destructive. Are you sure you want to proceed?"),
18
+ default: false,
19
+ });
20
+ }
21
+ return true;
22
+ }
23
+ exports.confirmDangerousQuery = confirmDangerousQuery;
24
+ async function interactiveExecuteQuery(query, conn) {
25
+ const spinner = ora("Executing query...").start();
26
+ try {
27
+ const results = await conn.query(query);
28
+ spinner.succeed(clc.green("Query executed successfully"));
29
+ if (Array.isArray(results.rows) && results.rows.length > 0) {
30
+ const table = new Table({
31
+ head: Object.keys(results.rows[0]).map((key) => clc.cyan(key)),
32
+ style: { head: [], border: [] },
33
+ });
34
+ for (const row of results.rows) {
35
+ table.push(Object.values(row));
36
+ }
37
+ logger_1.logger.info(table.toString());
38
+ }
39
+ else {
40
+ if (query.toUpperCase().includes("SELECT")) {
41
+ logger_1.logger.info(clc.yellow("No results returned"));
42
+ }
43
+ }
44
+ }
45
+ catch (err) {
46
+ spinner.fail(clc.red(`Failed executing query: ${err}`));
47
+ }
48
+ }
49
+ exports.interactiveExecuteQuery = interactiveExecuteQuery;
@@ -62,7 +62,11 @@ async function deleteDocuments(project, docs, allowEmulator = false) {
62
62
  return { delete: doc.name };
63
63
  });
64
64
  const data = { writes };
65
- const res = await apiClient.post(url, data);
65
+ const res = await apiClient.post(url, data, {
66
+ retries: 10,
67
+ retryCodes: [429, 409, 503],
68
+ retryMaxTimeout: 20 * 1000,
69
+ });
66
70
  return res.body.writeResults.length;
67
71
  }
68
72
  exports.deleteDocuments = deleteDocuments;
@@ -4,9 +4,12 @@ exports.doSetup = void 0;
4
4
  const clc = require("colorette");
5
5
  const utils = require("../../utils");
6
6
  const templates_1 = require("../../templates");
7
+ const cloudbilling_1 = require("../../gcp/cloudbilling");
7
8
  const APPHOSTING_YAML_TEMPLATE = (0, templates_1.readTemplateSync)("init/apphosting/apphosting.yaml");
8
9
  async function doSetup(setup, config) {
10
+ await (0, cloudbilling_1.checkBillingEnabled)(setup.projectId);
9
11
  utils.logBullet("Writing default settings to " + clc.bold("apphosting.yaml") + "...");
10
12
  await config.askWriteProjectFile("apphosting.yaml", APPHOSTING_YAML_TEMPLATE);
13
+ utils.logSuccess("Create a new App Hosting backend with `firebase apphosting:backends:create`");
11
14
  }
12
15
  exports.doSetup = doSetup;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.responseToError = void 0;
4
4
  const _ = require("lodash");
5
5
  const error_1 = require("./error");
6
- function responseToError(response, body) {
6
+ function responseToError(response, body, url) {
7
7
  if (response.statusCode < 400) {
8
8
  return;
9
9
  }
@@ -37,7 +37,10 @@ function responseToError(response, body) {
37
37
  message: errMessage,
38
38
  };
39
39
  }
40
- const message = "HTTP Error: " + response.statusCode + ", " + (body.error.message || body.error);
40
+ let message = "HTTP Error: " + response.statusCode + ", " + (body.error.message || body.error);
41
+ if (url) {
42
+ message = "Request to " + url + " had " + message;
43
+ }
41
44
  let exitCode;
42
45
  if (response.statusCode >= 500) {
43
46
  exitCode = 2;
package/lib/utils.js CHANGED
@@ -17,7 +17,7 @@ const stream_1 = require("stream");
17
17
  const winston = require("winston");
18
18
  const triple_beam_1 = require("triple-beam");
19
19
  const assert_1 = require("assert");
20
- const stripAnsi = require("strip-ansi");
20
+ const node_util_1 = require("node:util");
21
21
  const portfinder_1 = require("portfinder");
22
22
  const configstore_1 = require("./configstore");
23
23
  const error_1 = require("./error");
@@ -315,7 +315,7 @@ function setupLoggers() {
315
315
  level: "debug",
316
316
  format: winston.format.printf((info) => {
317
317
  const segments = [info.message, ...(info[triple_beam_1.SPLAT] || [])].map(tryStringify);
318
- return `${stripAnsi(segments.join(" "))}`;
318
+ return `${(0, node_util_1.stripVTControlCharacters)(segments.join(" "))}`;
319
319
  }),
320
320
  }));
321
321
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "13.22.1",
3
+ "version": "13.23.1",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -114,7 +114,6 @@
114
114
  "sql-formatter": "^15.3.0",
115
115
  "stream-chain": "^2.2.4",
116
116
  "stream-json": "^1.7.3",
117
- "strip-ansi": "^6.0.1",
118
117
  "superstatic": "^9.0.3",
119
118
  "tar": "^6.1.11",
120
119
  "tcp-port-used": "^1.0.2",