firebase-tools 11.23.1 → 11.24.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.
@@ -24,7 +24,7 @@ function readCommonTemplates() {
24
24
  extSpecTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "extension.yaml"), "utf8"),
25
25
  preinstallTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "PREINSTALL.md"), "utf8"),
26
26
  postinstallTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "POSTINSTALL.md"), "utf8"),
27
- changelogTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "CHANGELOG.md"), "utf8"),
27
+ changelogTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "CL-template.md"), "utf8"),
28
28
  };
29
29
  }
30
30
  exports.command = new command_1.Command("ext:dev:init")
@@ -93,7 +93,7 @@ class Delegate {
93
93
  }
94
94
  serveAdmin(port, config, envs) {
95
95
  var _a;
96
- const env = Object.assign(Object.assign({}, envs), { PORT: port, FUNCTIONS_CONTROL_API: "true", HOME: process.env.HOME, PATH: process.env.PATH, NODE_ENV: process.env.NODE_ENV });
96
+ const env = Object.assign(Object.assign({}, envs), { PORT: port, FUNCTIONS_CONTROL_API: "true", HOME: process.env.HOME, PATH: process.env.PATH, NODE_ENV: process.env.NODE_ENV, __FIREBASE_FRAMEWORKS_ENTRY__: process.env.__FIREBASE_FRAMEWORKS_ENTRY__ });
97
97
  if (Object.keys(config || {}).length) {
98
98
  env.CLOUD_RUNTIME_CONFIG = JSON.stringify(config);
99
99
  }
@@ -143,7 +143,13 @@ async function convertConfig(context, functionsPayload, deploy) {
143
143
  }
144
144
  return apiRewrite;
145
145
  }
146
- (0, functional_1.assertExhaustive)(rewrite);
146
+ try {
147
+ (0, functional_1.assertExhaustive)(rewrite);
148
+ }
149
+ catch (e) {
150
+ throw new error_1.FirebaseError("Invalid hosting rewrite config in firebase.json. " +
151
+ "A rewrite config must specify 'destination', 'function', 'dynamicLinks', or 'run'");
152
+ }
147
153
  });
148
154
  if (config.rewrites) {
149
155
  const versionId = (0, utils_1.last)(deploy.version.split("/"));
@@ -219,6 +219,13 @@ exports.shutdownWhenKilled = shutdownWhenKilled;
219
219
  async function runScript(script, extraEnv) {
220
220
  utils.logBullet(`Running script: ${clc.bold(script)}`);
221
221
  const env = Object.assign(Object.assign({}, process.env), extraEnv);
222
+ if (env.GCLOUD_PROJECT && !env.FIREBASE_CONFIG) {
223
+ env.FIREBASE_CONFIG = JSON.stringify({
224
+ projectId: env.GCLOUD_PROJECT,
225
+ storageBucket: `${env.GCLOUD_PROJECT}.appspot.com`,
226
+ databaseURL: `https://${env.GCLOUD_PROJECT}.firebaseio.com`,
227
+ });
228
+ }
222
229
  const emulatorInfos = registry_1.EmulatorRegistry.listRunningWithInfo();
223
230
  (0, env_1.setEnvVarsForEmulators)(env, emulatorInfos);
224
231
  const proc = childProcess.spawn(script, {
@@ -342,7 +349,7 @@ async function checkJavaMajorVersion() {
342
349
  });
343
350
  }).then((output) => {
344
351
  let versionInt = -1;
345
- const match = output.match(JAVA_VERSION_REGEX);
352
+ const match = JAVA_VERSION_REGEX.exec(output);
346
353
  if (match) {
347
354
  const version = match[1];
348
355
  versionInt = parseInt(version, 10);
@@ -136,7 +136,7 @@ function writeExtensionsToFirebaseJson(specs, config) {
136
136
  async function writeEnvFiles(specs, config, force) {
137
137
  for (const spec of specs) {
138
138
  const content = Object.entries(spec.params)
139
- .filter((r) => r[1].baseValue !== "")
139
+ .filter((r) => r[1].baseValue !== "" && r[1].baseValue !== undefined)
140
140
  .sort((a, b) => {
141
141
  return a[0].localeCompare(b[0]);
142
142
  })
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createServerResponseProxy = exports.prepareFrameworks = exports.findDependency = exports.discover = exports.relativeRequire = exports.WebFrameworks = exports.NODE_VERSION = exports.DEFAULT_REGION = exports.FIREBASE_ADMIN_VERSION = exports.FIREBASE_FUNCTIONS_VERSION = exports.FIREBASE_FRAMEWORKS_VERSION = void 0;
3
+ exports.createServerResponseProxy = exports.prepareFrameworks = exports.findDependency = exports.discover = exports.relativeRequire = exports.WebFrameworks = exports.ALLOWED_SSR_REGIONS = exports.DEFAULT_REGION = exports.NODE_VERSION = exports.FIREBASE_ADMIN_VERSION = exports.FIREBASE_FUNCTIONS_VERSION = exports.FIREBASE_FRAMEWORKS_VERSION = void 0;
4
4
  const path_1 = require("path");
5
5
  const process_1 = require("process");
6
6
  const child_process_1 = require("child_process");
@@ -37,8 +37,15 @@ const SupportLevelWarnings = {
37
37
  exports.FIREBASE_FRAMEWORKS_VERSION = "^0.6.0";
38
38
  exports.FIREBASE_FUNCTIONS_VERSION = "^3.23.0";
39
39
  exports.FIREBASE_ADMIN_VERSION = "^11.0.1";
40
- exports.DEFAULT_REGION = "us-central1";
41
40
  exports.NODE_VERSION = parseInt(process.versions.node, 10).toString();
41
+ exports.DEFAULT_REGION = "us-central1";
42
+ exports.ALLOWED_SSR_REGIONS = [
43
+ { name: "us-central1 (Iowa)", value: "us-central1" },
44
+ { name: "us-west1 (Oregon)", value: "us-west1" },
45
+ { name: "us-east1 (South Carolina)", value: "us-east1" },
46
+ { name: "europe-west1 (Belgium)", value: "europe-west1" },
47
+ { name: "asia-east1 (Taiwan)", value: "asia-east1" },
48
+ ];
42
49
  const DEFAULT_FIND_DEP_OPTIONS = {
43
50
  cwd: process.cwd(),
44
51
  omitDev: true,
@@ -122,8 +129,8 @@ function findDependency(name, options = {}) {
122
129
  }
123
130
  exports.findDependency = findDependency;
124
131
  async function prepareFrameworks(targetNames, context, options, emulators = []) {
125
- var _a, _b;
126
- var _c, _d, _e, _f;
132
+ var _a, _b, _c;
133
+ var _d, _e, _f, _g;
127
134
  const nodeVersion = process.version;
128
135
  if (!semver.satisfies(nodeVersion, ">=16.0.0")) {
129
136
  throw new error_1.FirebaseError(`The frameworks awareness feature requires Node.JS >= 16 and npm >= 8 in order to work correctly, due to some of the downstream dependencies. Please upgrade your version of Node.JS, reinstall firebase-tools, and give it another go.`);
@@ -135,7 +142,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
135
142
  try {
136
143
  await (0, requireHostingSite_1.requireHostingSite)(options);
137
144
  }
138
- catch (_g) {
145
+ catch (_h) {
139
146
  options.site = project;
140
147
  }
141
148
  }
@@ -144,8 +151,9 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
144
151
  if (configs.length === 0) {
145
152
  return;
146
153
  }
154
+ const allowedRegionsValues = exports.ALLOWED_SSR_REGIONS.map((r) => r.value);
147
155
  for (const config of configs) {
148
- const { source, site, public: publicDir } = config;
156
+ const { source, site, public: publicDir, frameworksBackend } = config;
149
157
  if (!source) {
150
158
  continue;
151
159
  }
@@ -159,8 +167,13 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
159
167
  if (publicDir) {
160
168
  throw new Error(`hosting.public and hosting.source cannot both be set in firebase.json`);
161
169
  }
170
+ const ssrRegion = (_b = frameworksBackend === null || frameworksBackend === void 0 ? void 0 : frameworksBackend.region) !== null && _b !== void 0 ? _b : exports.DEFAULT_REGION;
171
+ if (!allowedRegionsValues.includes(ssrRegion)) {
172
+ const validRegions = allowedRegionsValues.join(", ");
173
+ throw new error_1.FirebaseError(`Hosting config for site ${site} places server-side content in region ${ssrRegion} which is not known. Valid regions are ${validRegions}`);
174
+ }
162
175
  const getProjectPath = (...args) => (0, path_1.join)(projectRoot, source, ...args);
163
- const functionName = `ssr${site.toLowerCase().replace(/-/g, "")}`;
176
+ const functionId = `ssr${site.toLowerCase().replace(/-/g, "")}`;
164
177
  const usesFirebaseAdminSdk = !!findDependency("firebase-admin", { cwd: getProjectPath() });
165
178
  const usesFirebaseJsSdk = !!findDependency("@firebase/app", { cwd: getProjectPath() });
166
179
  if (usesFirebaseAdminSdk) {
@@ -249,7 +262,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
249
262
  config.rewrites.push(...rewrites);
250
263
  config.redirects.push(...redirects);
251
264
  config.headers.push(...headers);
252
- (_b = config.trailingSlash) !== null && _b !== void 0 ? _b : (config.trailingSlash = trailingSlash);
265
+ (_c = config.trailingSlash) !== null && _c !== void 0 ? _c : (config.trailingSlash = trailingSlash);
253
266
  if (await (0, fs_extra_1.pathExists)(hostingDist))
254
267
  await (0, promises_1.rm)(hostingDist, { recursive: true });
255
268
  await (0, fs_extra_1.mkdirp)(hostingDist);
@@ -265,7 +278,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
265
278
  const rewrite = {
266
279
  source: "**",
267
280
  function: {
268
- functionId: functionName,
281
+ functionId,
269
282
  },
270
283
  };
271
284
  if (experiments.isEnabled("pintags")) {
@@ -306,27 +319,15 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
306
319
  await (0, fs_extra_1.mkdirp)(functionsDist);
307
320
  }
308
321
  const { packageJson, bootstrapScript, frameworksEntry = framework, } = await codegenFunctionsDirectory(getProjectPath(), functionsDist);
309
- await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, "functions.yaml"), JSON.stringify({
310
- endpoints: {
311
- [functionName]: {
312
- platform: "gcfv2",
313
- region: [exports.DEFAULT_REGION],
314
- labels: {},
315
- httpsTrigger: {},
316
- entryPoint: "ssr",
317
- },
318
- },
319
- specVersion: "v1alpha1",
320
- requiredAPIs: [],
321
- }, null, 2));
322
+ process.env.__FIREBASE_FRAMEWORKS_ENTRY__ = frameworksEntry;
322
323
  packageJson.main = "server.js";
323
324
  delete packageJson.devDependencies;
324
325
  packageJson.dependencies || (packageJson.dependencies = {});
325
- (_c = packageJson.dependencies)["firebase-frameworks"] || (_c["firebase-frameworks"] = exports.FIREBASE_FRAMEWORKS_VERSION);
326
- (_d = packageJson.dependencies)["firebase-functions"] || (_d["firebase-functions"] = exports.FIREBASE_FUNCTIONS_VERSION);
327
- (_e = packageJson.dependencies)["firebase-admin"] || (_e["firebase-admin"] = exports.FIREBASE_ADMIN_VERSION);
326
+ (_d = packageJson.dependencies)["firebase-frameworks"] || (_d["firebase-frameworks"] = exports.FIREBASE_FRAMEWORKS_VERSION);
327
+ (_e = packageJson.dependencies)["firebase-functions"] || (_e["firebase-functions"] = exports.FIREBASE_FUNCTIONS_VERSION);
328
+ (_f = packageJson.dependencies)["firebase-admin"] || (_f["firebase-admin"] = exports.FIREBASE_ADMIN_VERSION);
328
329
  packageJson.engines || (packageJson.engines = {});
329
- (_f = packageJson.engines).node || (_f.node = exports.NODE_VERSION);
330
+ (_g = packageJson.engines).node || (_g.node = exports.NODE_VERSION);
330
331
  for (const [name, version] of Object.entries(packageJson.dependencies)) {
331
332
  if (version.startsWith("file:")) {
332
333
  const path = version.replace(/^file:/, "");
@@ -374,10 +375,18 @@ ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\
374
375
  });
375
376
  if (bootstrapScript)
376
377
  await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, "bootstrap.js"), bootstrapScript);
377
- await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, "server.js"), `const { onRequest } = require('firebase-functions/v2/https');
378
- const server = import('firebase-frameworks');
379
- exports.ssr = onRequest((req, res) => server.then(it => it.handle(req, res)));
380
- `);
378
+ if (packageJson.type === "module") {
379
+ await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, "server.js"), `import { onRequest } from 'firebase-functions/v2/https';
380
+ const server = import('firebase-frameworks');
381
+ export const ${functionId} = onRequest(${JSON.stringify(frameworksBackend || {})}, (req, res) => server.then(it => it.handle(req, res)));
382
+ `);
383
+ }
384
+ else {
385
+ await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, "server.js"), `const { onRequest } = require('firebase-functions/v2/https');
386
+ const server = import('firebase-frameworks');
387
+ exports.${functionId} = onRequest(${JSON.stringify(frameworksBackend || {})}, (req, res) => server.then(it => it.handle(req, res)));
388
+ `);
389
+ }
381
390
  }
382
391
  else {
383
392
  config.rewrites.push({
package/lib/functional.js CHANGED
@@ -53,7 +53,7 @@ const zipIn = (other) => (elem, ndx) => {
53
53
  };
54
54
  exports.zipIn = zipIn;
55
55
  function assertExhaustive(val) {
56
- throw new Error(`Never has a value (${val}). This should be impossible`);
56
+ throw new Error(`Never has a value (${val}).`);
57
57
  }
58
58
  exports.assertExhaustive = assertExhaustive;
59
59
  function partition(arr, predicate) {
@@ -37,6 +37,9 @@ const actionFunction = async (options) => {
37
37
  const otherEmulators = types_1.EMULATORS_SUPPORTED_BY_FUNCTIONS.filter((e) => remoteEmulators[e] === undefined);
38
38
  let host = constants_1.Constants.getDefaultHost();
39
39
  let port = 5000;
40
+ if (typeof options.port === "number") {
41
+ port = options.port;
42
+ }
40
43
  const functionsInfo = remoteEmulators[types_1.Emulators.FUNCTIONS];
41
44
  if (functionsInfo) {
42
45
  utils.logLabeledWarning("functions", `You are already running the Cloud Functions emulator on port ${functionsInfo.port}. Running the emulator and the Functions shell simultaenously can result in unexpected behavior.`);
@@ -86,9 +86,19 @@ async function doSetup(setup, config) {
86
86
  (0, rimraf_1.sync)(setup.hosting.source);
87
87
  await frameworks_1.WebFrameworks[setup.hosting.whichFramework].init(setup, config);
88
88
  }
89
+ await (0, prompt_1.promptOnce)({
90
+ name: "region",
91
+ type: "list",
92
+ message: "In which region would you like to host server-side content, if applicable?",
93
+ default: frameworks_1.DEFAULT_REGION,
94
+ choices: frameworks_1.ALLOWED_SSR_REGIONS,
95
+ }, setup.hosting);
89
96
  setup.config.hosting = {
90
97
  source: setup.hosting.source,
91
98
  ignore: DEFAULT_IGNORES,
99
+ frameworksBackend: {
100
+ region: setup.hosting.region,
101
+ },
92
102
  };
93
103
  }
94
104
  else {
package/lib/prompt.js CHANGED
@@ -24,7 +24,8 @@ async function prompt(options, questions) {
24
24
  }
25
25
  exports.prompt = prompt;
26
26
  async function promptOnce(question, options = {}) {
27
- question.name = question.name || "question";
27
+ var _a;
28
+ question.name = ((_a = question.name) === null || _a === void 0 ? void 0 : _a.replace(/\./g, "/")) || "question";
28
29
  await prompt(options, [question]);
29
30
  return options[question.name];
30
31
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "11.23.1",
3
+ "version": "11.24.1",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "firebase-tools",
9
- "version": "11.23.1",
9
+ "version": "11.24.1",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@google-cloud/pubsub": "^3.0.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "11.23.1",
3
+ "version": "11.24.1",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -5,6 +5,126 @@
5
5
  "ExtensionsConfig": {
6
6
  "additionalProperties": false,
7
7
  "type": "object"
8
+ },
9
+ "FrameworksBackendOptions": {
10
+ "additionalProperties": false,
11
+ "properties": {
12
+ "concurrency": {
13
+ "description": "Number of requests a function can serve at once.",
14
+ "type": "number"
15
+ },
16
+ "cors": {
17
+ "description": "If true, allows CORS on requests to this function.\nIf this is a `string` or `RegExp`, allows requests from domains that match the provided value.\nIf this is an `Array`, allows requests from domains matching at least one entry of the array.\nDefaults to true for {@link https.CallableFunction} and false otherwise.",
18
+ "type": [
19
+ "string",
20
+ "boolean"
21
+ ]
22
+ },
23
+ "cpu": {
24
+ "anyOf": [
25
+ {
26
+ "enum": [
27
+ "gcf_gen1"
28
+ ],
29
+ "type": "string"
30
+ },
31
+ {
32
+ "type": "number"
33
+ }
34
+ ],
35
+ "description": "Fractional number of CPUs to allocate to a function."
36
+ },
37
+ "enforceAppCheck": {
38
+ "description": "Determines whether Firebase AppCheck is enforced. Defaults to false.",
39
+ "type": "boolean"
40
+ },
41
+ "ingressSettings": {
42
+ "description": "Ingress settings which control where this function can be called from.",
43
+ "enum": [
44
+ "ALLOW_ALL",
45
+ "ALLOW_INTERNAL_AND_GCLB",
46
+ "ALLOW_INTERNAL_ONLY"
47
+ ],
48
+ "type": "string"
49
+ },
50
+ "invoker": {
51
+ "description": "Invoker to set access control on https functions.",
52
+ "enum": [
53
+ "public"
54
+ ],
55
+ "type": "string"
56
+ },
57
+ "labels": {
58
+ "$ref": "#/definitions/Record<string,string>",
59
+ "description": "User labels to set on the function."
60
+ },
61
+ "maxInstances": {
62
+ "description": "Max number of instances to be running in parallel.",
63
+ "type": "number"
64
+ },
65
+ "memory": {
66
+ "description": "Amount of memory to allocate to a function.",
67
+ "enum": [
68
+ "128MiB",
69
+ "16GiB",
70
+ "1GiB",
71
+ "256MiB",
72
+ "2GiB",
73
+ "32GiB",
74
+ "4GiB",
75
+ "512MiB",
76
+ "8GiB"
77
+ ],
78
+ "type": "string"
79
+ },
80
+ "minInstances": {
81
+ "description": "Min number of actual instances to be running at a given time.",
82
+ "type": "number"
83
+ },
84
+ "omit": {
85
+ "description": "If true, do not deploy or emulate this function.",
86
+ "type": "boolean"
87
+ },
88
+ "preserveExternalChanges": {
89
+ "description": "Controls whether function configuration modified outside of function source is preserved. Defaults to false.",
90
+ "type": "boolean"
91
+ },
92
+ "region": {
93
+ "description": "HTTP functions can override global options and can specify multiple regions to deploy to.",
94
+ "type": "string"
95
+ },
96
+ "secrets": {
97
+ "items": {
98
+ "type": "string"
99
+ },
100
+ "type": "array"
101
+ },
102
+ "serviceAccount": {
103
+ "description": "Specific service account for the function to run as.",
104
+ "type": "string"
105
+ },
106
+ "timeoutSeconds": {
107
+ "description": "Timeout for the function in sections, possible values are 0 to 540.\nHTTPS functions can specify a higher timeout.",
108
+ "type": "number"
109
+ },
110
+ "vpcConnector": {
111
+ "description": "Connect cloud function to specified VPC connector.",
112
+ "type": "string"
113
+ },
114
+ "vpcConnectorEgressSettings": {
115
+ "description": "Egress settings for VPC connector.",
116
+ "enum": [
117
+ "ALL_TRAFFIC",
118
+ "PRIVATE_RANGES_ONLY"
119
+ ],
120
+ "type": "string"
121
+ }
122
+ },
123
+ "type": "object"
124
+ },
125
+ "Record<string,string>": {
126
+ "additionalProperties": false,
127
+ "type": "object"
8
128
  }
9
129
  },
10
130
  "properties": {
@@ -473,6 +593,9 @@
473
593
  "cleanUrls": {
474
594
  "type": "boolean"
475
595
  },
596
+ "frameworksBackend": {
597
+ "$ref": "#/definitions/FrameworksBackendOptions"
598
+ },
476
599
  "headers": {
477
600
  "items": {
478
601
  "anyOf": [
@@ -1064,6 +1187,9 @@
1064
1187
  "cleanUrls": {
1065
1188
  "type": "boolean"
1066
1189
  },
1190
+ "frameworksBackend": {
1191
+ "$ref": "#/definitions/FrameworksBackendOptions"
1192
+ },
1067
1193
  "headers": {
1068
1194
  "items": {
1069
1195
  "anyOf": [
@@ -1655,6 +1781,9 @@
1655
1781
  "cleanUrls": {
1656
1782
  "type": "boolean"
1657
1783
  },
1784
+ "frameworksBackend": {
1785
+ "$ref": "#/definitions/FrameworksBackendOptions"
1786
+ },
1658
1787
  "headers": {
1659
1788
  "items": {
1660
1789
  "anyOf": [
@@ -0,0 +1,2 @@
1
+ ## Version 0.0.1
2
+ - Initial Version
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "main": "index.js",
16
16
  "dependencies": {
17
- "firebase-admin": "^111.5.0",
17
+ "firebase-admin": "^11.5.0",
18
18
  "firebase-functions": "^4.2.0"
19
19
  },
20
20
  "devDependencies": {
@@ -2,12 +2,12 @@
2
2
  # To get started, simply uncomment the below code or create your own.
3
3
  # Deploy with `firebase deploy`
4
4
 
5
- from firebase_functions import https
5
+ from firebase_functions import https_fn
6
6
  from firebase_admin import initialize_app
7
7
 
8
8
  # initialize_app()
9
9
  #
10
10
  #
11
- # @https.on_request()
12
- # def on_request_example(req: https.Request) -> https.Response:
13
- # return https.Response("Hello world!")
11
+ # @https_fn.on_request()
12
+ # def on_request_example(req: https_fn.Request) -> https_fn.Response:
13
+ # return https_fn.Response("Hello world!")