firebase-tools 11.29.1 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/lib/api.js +4 -2
  2. package/lib/commands/database-import.js +2 -2
  3. package/lib/commands/ext-configure.js +2 -1
  4. package/lib/commands/ext-dev-deprecate.js +24 -20
  5. package/lib/commands/ext-dev-list.js +12 -11
  6. package/lib/commands/ext-dev-publish.js +13 -47
  7. package/lib/commands/ext-dev-register.js +8 -5
  8. package/lib/commands/ext-dev-undeprecate.js +4 -4
  9. package/lib/commands/ext-dev-upload.js +88 -0
  10. package/lib/commands/ext-dev-usage.js +3 -3
  11. package/lib/commands/ext-install.js +5 -10
  12. package/lib/commands/ext-uninstall.js +0 -1
  13. package/lib/commands/ext-update.js +4 -10
  14. package/lib/commands/hosting-channel-deploy.js +3 -0
  15. package/lib/commands/index.js +9 -19
  16. package/lib/database/import.js +113 -18
  17. package/lib/deploy/extensions/planner.js +13 -7
  18. package/lib/deploy/extensions/prepare.js +16 -32
  19. package/lib/deploy/functions/ensure.js +7 -1
  20. package/lib/deploy/functions/release/fabricator.js +2 -0
  21. package/lib/deploy/functions/runtimes/discovery/index.js +1 -1
  22. package/lib/deploy/functions/runtimes/index.js +11 -3
  23. package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +3 -3
  24. package/lib/deploy/functions/runtimes/python/index.js +41 -13
  25. package/lib/deploy/hosting/convertConfig.js +8 -4
  26. package/lib/deploy/hosting/prepare.js +64 -6
  27. package/lib/deploy/index.js +24 -8
  28. package/lib/emulator/adminSdkConfig.js +8 -0
  29. package/lib/emulator/controller.js +7 -9
  30. package/lib/emulator/download.js +3 -12
  31. package/lib/emulator/downloadableEmulators.js +5 -5
  32. package/lib/emulator/functionsEmulator.js +57 -7
  33. package/lib/emulator/functionsEmulatorRuntime.js +4 -1
  34. package/lib/emulator/functionsEmulatorShared.js +1 -0
  35. package/lib/emulator/functionsRuntimeWorker.js +12 -4
  36. package/lib/emulator/storage/rules/config.js +17 -7
  37. package/lib/experiments.js +22 -8
  38. package/lib/extensions/extensionsApi.js +24 -151
  39. package/lib/extensions/extensionsHelper.js +283 -146
  40. package/lib/extensions/manifest.js +1 -8
  41. package/lib/extensions/publisherApi.js +215 -0
  42. package/lib/extensions/refs.js +1 -1
  43. package/lib/extensions/resolveSource.js +1 -18
  44. package/lib/extensions/tos.js +78 -0
  45. package/lib/extensions/warnings.js +21 -41
  46. package/lib/frameworks/angular/index.js +74 -192
  47. package/lib/frameworks/angular/interfaces.js +2 -0
  48. package/lib/frameworks/angular/utils.js +274 -0
  49. package/lib/frameworks/astro/index.js +3 -4
  50. package/lib/frameworks/constants.js +45 -0
  51. package/lib/frameworks/express/index.js +3 -2
  52. package/lib/frameworks/flutter/index.js +39 -0
  53. package/lib/frameworks/flutter/utils.js +11 -0
  54. package/lib/frameworks/index.js +104 -145
  55. package/lib/frameworks/interfaces.js +2 -0
  56. package/lib/frameworks/next/constants.js +2 -1
  57. package/lib/frameworks/next/index.js +197 -114
  58. package/lib/frameworks/next/utils.js +97 -15
  59. package/lib/frameworks/nuxt/index.js +4 -5
  60. package/lib/frameworks/nuxt/utils.js +2 -2
  61. package/lib/frameworks/nuxt2/index.js +5 -5
  62. package/lib/frameworks/utils.js +108 -1
  63. package/lib/frameworks/vite/index.js +5 -6
  64. package/lib/functions/ensureTargeted.js +4 -4
  65. package/lib/functions/python.js +12 -5
  66. package/lib/gcp/resourceManager.js +1 -0
  67. package/lib/hosting/api.js +32 -1
  68. package/lib/hosting/config.js +4 -8
  69. package/lib/init/features/functions/index.js +4 -7
  70. package/lib/init/features/hosting/github.js +7 -2
  71. package/lib/init/features/hosting/index.js +3 -2
  72. package/lib/serve/index.js +2 -1
  73. package/lib/unzip.js +126 -0
  74. package/package.json +2 -3
  75. package/schema/firebase-config.json +1 -1
  76. package/templates/extensions/POSTINSTALL.md +2 -2
  77. package/templates/extensions/PREINSTALL.md +1 -1
  78. package/templates/extensions/extension.yaml +10 -6
  79. package/templates/extensions/javascript/WELCOME.md +1 -1
  80. package/templates/extensions/typescript/WELCOME.md +1 -1
  81. package/templates/extensions/typescript/index.ts +1 -1
  82. package/templates/init/functions/javascript/index.js +16 -6
  83. package/templates/init/functions/javascript/package.lint.json +4 -4
  84. package/templates/init/functions/javascript/package.nolint.json +4 -4
  85. package/templates/init/functions/python/requirements.txt +1 -1
  86. package/templates/init/functions/typescript/index.ts +16 -6
  87. package/templates/init/functions/typescript/package.lint.json +4 -4
  88. package/templates/init/functions/typescript/package.nolint.json +4 -4
  89. package/lib/commands/ext-dev-emulators-exec.js +0 -27
  90. package/lib/commands/ext-dev-emulators-start.js +0 -24
  91. package/lib/commands/ext-dev-extension-delete.js +0 -45
  92. package/lib/commands/ext-dev-unpublish.js +0 -49
  93. package/lib/commands/ext-sources-create.js +0 -24
  94. package/lib/extensions/askUserForConsent.js +0 -33
  95. package/npm-shrinkwrap.json +0 -12649
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebFrameworks = exports.I18N_ROOT = exports.ALLOWED_SSR_REGIONS = exports.DEFAULT_REGION = exports.VALID_LOCALE_FORMATS = exports.VALID_ENGINES = exports.NODE_VERSION = exports.SHARP_VERSION = exports.FIREBASE_ADMIN_VERSION = exports.FIREBASE_FUNCTIONS_VERSION = exports.FIREBASE_FRAMEWORKS_VERSION = exports.MAILING_LIST_URL = exports.FEATURE_REQUEST_URL = exports.FILE_BUG_URL = exports.DEFAULT_DOCS_URL = exports.SupportLevelWarnings = exports.NPM_COMMAND_TIMEOUT_MILLIES = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const clc = require("colorette");
7
+ exports.NPM_COMMAND_TIMEOUT_MILLIES = 10000;
8
+ exports.SupportLevelWarnings = {
9
+ ["experimental"]: (framework) => `Thank you for trying our ${clc.italic("experimental")} support for ${framework} on Firebase Hosting.
10
+ ${clc.yellow(`While this integration is maintained by Googlers it is not a supported Firebase product.
11
+ Issues filed on GitHub will be addressed on a best-effort basis by maintainers and other community members.`)}`,
12
+ ["preview"]: (framework) => `Thank you for trying our ${clc.italic("early preview")} of ${framework} support on Firebase Hosting.
13
+ ${clc.yellow("During the preview, support is best-effort and breaking changes can be expected. Proceed with caution.")}`,
14
+ };
15
+ exports.DEFAULT_DOCS_URL = "https://firebase.google.com/docs/hosting/frameworks/frameworks-overview";
16
+ exports.FILE_BUG_URL = "https://github.com/firebase/firebase-tools/issues/new?template=bug_report.md";
17
+ exports.FEATURE_REQUEST_URL = "https://github.com/firebase/firebase-tools/issues/new?template=feature_request.md";
18
+ exports.MAILING_LIST_URL = "https://goo.gle/41enW5X";
19
+ exports.FIREBASE_FRAMEWORKS_VERSION = "^0.10.1";
20
+ exports.FIREBASE_FUNCTIONS_VERSION = "^4.3.0";
21
+ exports.FIREBASE_ADMIN_VERSION = "^11.0.1";
22
+ exports.SHARP_VERSION = "^0.32.1";
23
+ exports.NODE_VERSION = parseInt(process.versions.node, 10);
24
+ exports.VALID_ENGINES = { node: [16, 18] };
25
+ exports.VALID_LOCALE_FORMATS = [/^ALL_[a-z]+$/, /^[a-z]+_ALL$/, /^[a-z]+(_[a-z]+)?$/];
26
+ exports.DEFAULT_REGION = "us-central1";
27
+ exports.ALLOWED_SSR_REGIONS = [
28
+ { name: "us-central1 (Iowa)", value: "us-central1" },
29
+ { name: "us-west1 (Oregon)", value: "us-west1" },
30
+ { name: "us-east1 (South Carolina)", value: "us-east1" },
31
+ { name: "europe-west1 (Belgium)", value: "europe-west1" },
32
+ { name: "asia-east1 (Taiwan)", value: "asia-east1" },
33
+ ];
34
+ exports.I18N_ROOT = "/";
35
+ exports.WebFrameworks = Object.fromEntries((0, fs_1.readdirSync)(__dirname)
36
+ .filter((path) => (0, fs_1.statSync)((0, path_1.join)(__dirname, path)).isDirectory())
37
+ .map((path) => {
38
+ try {
39
+ return [path, require((0, path_1.join)(__dirname, path))];
40
+ }
41
+ catch (e) {
42
+ return [];
43
+ }
44
+ })
45
+ .filter(([, obj]) => obj && obj.name && obj.discover && obj.build && obj.type !== undefined && obj.support));
@@ -1,14 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.build = exports.discover = exports.type = exports.support = exports.name = void 0;
3
+ exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.build = exports.discover = exports.docsUrl = exports.type = exports.support = exports.name = void 0;
4
4
  const child_process_1 = require("child_process");
5
5
  const fs_extra_1 = require("fs-extra");
6
6
  const promises_1 = require("fs/promises");
7
7
  const path_1 = require("path");
8
8
  const { dynamicImport } = require(true && "../../dynamicImport");
9
9
  exports.name = "Express.js";
10
- exports.support = "experimental";
10
+ exports.support = "preview";
11
11
  exports.type = 0;
12
+ exports.docsUrl = "https://firebase.google.com/docs/hosting/frameworks/express";
12
13
  async function getConfig(root) {
13
14
  var _a, _b;
14
15
  const packageJsonBuffer = await (0, promises_1.readFile)((0, path_1.join)(root, "package.json"));
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ɵcodegenPublicDirectory = exports.build = exports.discover = exports.support = exports.type = exports.name = void 0;
4
+ const cross_spawn_1 = require("cross-spawn");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const path_1 = require("path");
7
+ const js_yaml_1 = require("js-yaml");
8
+ const promises_1 = require("fs/promises");
9
+ const error_1 = require("../../error");
10
+ const utils_1 = require("./utils");
11
+ exports.name = "Flutter";
12
+ exports.type = 3;
13
+ exports.support = "experimental";
14
+ async function discover(dir) {
15
+ var _a;
16
+ if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "pubspec.yaml"))))
17
+ return;
18
+ if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "web"))))
19
+ return;
20
+ const pubSpecBuffer = await (0, promises_1.readFile)((0, path_1.join)(dir, "pubspec.yaml"));
21
+ const pubSpec = (0, js_yaml_1.load)(pubSpecBuffer.toString());
22
+ const usingFlutter = (_a = pubSpec.dependencies) === null || _a === void 0 ? void 0 : _a.flutter;
23
+ if (!usingFlutter)
24
+ return;
25
+ return { mayWantBackend: false, publicDirectory: (0, path_1.join)(dir, "web") };
26
+ }
27
+ exports.discover = discover;
28
+ function build(cwd) {
29
+ (0, utils_1.assertFlutterCliExists)();
30
+ const build = (0, cross_spawn_1.sync)("flutter", ["build", "web"], { cwd, stdio: "inherit" });
31
+ if (build.status)
32
+ throw new error_1.FirebaseError("Unable to build your Flutter app");
33
+ return Promise.resolve({ wantsBackend: false });
34
+ }
35
+ exports.build = build;
36
+ async function ɵcodegenPublicDirectory(sourceDir, destDir) {
37
+ await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, "build", "web"), destDir);
38
+ }
39
+ exports.ɵcodegenPublicDirectory = ɵcodegenPublicDirectory;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertFlutterCliExists = void 0;
4
+ const cross_spawn_1 = require("cross-spawn");
5
+ const error_1 = require("../../error");
6
+ function assertFlutterCliExists() {
7
+ const process = (0, cross_spawn_1.sync)("flutter", ["--version"], { stdio: "ignore" });
8
+ if (process.status)
9
+ throw new error_1.FirebaseError("Flutter CLI not found.");
10
+ }
11
+ exports.assertFlutterCliExists = assertFlutterCliExists;
@@ -1,15 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prepareFrameworks = exports.findDependency = exports.getNodeModuleBin = 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;
3
+ exports.prepareFrameworks = exports.discover = exports.WebFrameworks = 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");
7
7
  const cross_spawn_1 = require("cross-spawn");
8
- const fs_1 = require("fs");
9
- const url_1 = require("url");
10
8
  const promises_1 = require("fs/promises");
11
9
  const fs_extra_1 = require("fs-extra");
12
- const clc = require("colorette");
13
10
  const process = require("node:process");
14
11
  const semver = require("semver");
15
12
  const glob = require("glob");
@@ -26,67 +23,22 @@ const constants_1 = require("../emulator/constants");
26
23
  const error_1 = require("../error");
27
24
  const requireHostingSite_1 = require("../requireHostingSite");
28
25
  const experiments = require("../experiments");
29
- const ensureTargeted_1 = require("../functions/ensureTargeted");
30
26
  const implicitInit_1 = require("../hosting/implicitInit");
31
- const fsutils_1 = require("../fsutils");
32
- const { dynamicImport } = require(true && "../dynamicImport");
33
- const SupportLevelWarnings = {
34
- ["experimental"]: clc.yellow(`This is an experimental integration, proceed with caution.`),
35
- ["community-supported"]: clc.yellow(`This is a community-supported integration, support is best effort.`),
36
- };
37
- exports.FIREBASE_FRAMEWORKS_VERSION = "^0.7.0";
38
- exports.FIREBASE_FUNCTIONS_VERSION = "^3.23.0";
39
- exports.FIREBASE_ADMIN_VERSION = "^11.0.1";
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
- ];
49
- const DEFAULT_FIND_DEP_OPTIONS = {
50
- cwd: process.cwd(),
51
- omitDev: true,
52
- };
53
- exports.WebFrameworks = Object.fromEntries((0, fs_1.readdirSync)(__dirname)
54
- .filter((path) => (0, fs_1.statSync)((0, path_1.join)(__dirname, path)).isDirectory())
55
- .map((path) => {
56
- try {
57
- return [path, require((0, path_1.join)(__dirname, path))];
58
- }
59
- catch (e) {
60
- return [];
61
- }
62
- })
63
- .filter(([, obj]) => obj && obj.name && obj.discover && obj.build && obj.type !== undefined && obj.support));
64
- function relativeRequire(dir, mod) {
65
- try {
66
- const path = require.resolve(mod, { paths: [dir] });
67
- if ((0, path_1.extname)(path) === ".mjs") {
68
- return dynamicImport((0, url_1.pathToFileURL)(path).toString());
69
- }
70
- else {
71
- return require(path);
72
- }
73
- }
74
- catch (e) {
75
- const path = (0, path_1.relative)(process.cwd(), dir);
76
- console.error(`Could not load dependency ${mod} in ${path.startsWith("..") ? path : `./${path}`}, have you run \`npm install\`?`);
77
- throw e;
78
- }
79
- }
80
- exports.relativeRequire = relativeRequire;
27
+ const utils_1 = require("./utils");
28
+ const constants_2 = require("./constants");
29
+ Object.defineProperty(exports, "WebFrameworks", { enumerable: true, get: function () { return constants_2.WebFrameworks; } });
30
+ const utils_2 = require("../utils");
31
+ const ensureTargeted_1 = require("../functions/ensureTargeted");
32
+ const util_1 = require("util");
81
33
  async function discover(dir, warn = true) {
82
34
  const allFrameworkTypes = [
83
- ...new Set(Object.values(exports.WebFrameworks).map(({ type }) => type)),
35
+ ...new Set(Object.values(constants_2.WebFrameworks).map(({ type }) => type)),
84
36
  ].sort();
85
37
  for (const discoveryType of allFrameworkTypes) {
86
38
  const frameworksDiscovered = [];
87
- for (const framework in exports.WebFrameworks) {
88
- if (exports.WebFrameworks[framework]) {
89
- const { discover, type } = exports.WebFrameworks[framework];
39
+ for (const framework in constants_2.WebFrameworks) {
40
+ if (constants_2.WebFrameworks[framework]) {
41
+ const { discover, type } = constants_2.WebFrameworks[framework];
90
42
  if (type !== discoveryType)
91
43
  continue;
92
44
  const result = await discover(dir);
@@ -107,54 +59,21 @@ async function discover(dir, warn = true) {
107
59
  return;
108
60
  }
109
61
  exports.discover = discover;
110
- function scanDependencyTree(searchingFor, dependencies = {}) {
111
- for (const [name, dependency] of Object.entries(dependencies)) {
112
- if (name === searchingFor)
113
- return dependency;
114
- const result = scanDependencyTree(searchingFor, dependency.dependencies);
115
- if (result)
116
- return result;
117
- }
118
- return;
119
- }
120
- function getNodeModuleBin(name, cwd) {
121
- var _a;
122
- const cantFindExecutable = new error_1.FirebaseError(`Could not find the ${name} executable.`);
123
- const npmRoot = (_a = (0, cross_spawn_1.sync)("npm", ["root"], { cwd }).stdout) === null || _a === void 0 ? void 0 : _a.toString().trim();
124
- if (!npmRoot) {
125
- throw cantFindExecutable;
126
- }
127
- const path = (0, path_1.join)(npmRoot, ".bin", name);
128
- if (!(0, fsutils_1.fileExistsSync)(path)) {
129
- throw cantFindExecutable;
62
+ const BUILD_MEMO = new Map();
63
+ function memoizeBuild(dir, build, deps) {
64
+ const key = [dir, ...deps];
65
+ for (const existingKey of BUILD_MEMO.keys()) {
66
+ if ((0, util_1.isDeepStrictEqual)(existingKey, key)) {
67
+ return BUILD_MEMO.get(existingKey);
68
+ }
130
69
  }
131
- return path;
132
- }
133
- exports.getNodeModuleBin = getNodeModuleBin;
134
- function findDependency(name, options = {}) {
135
- var _a;
136
- const { cwd: dir, depth, omitDev } = Object.assign(Object.assign({}, DEFAULT_FIND_DEP_OPTIONS), options);
137
- const cwd = (_a = (0, cross_spawn_1.sync)("npm", ["root"], { cwd: dir }).stdout) === null || _a === void 0 ? void 0 : _a.toString().trim();
138
- if (!cwd)
139
- return;
140
- const env = Object.assign({}, process.env);
141
- delete env.NODE_ENV;
142
- const result = (0, cross_spawn_1.sync)("npm", [
143
- "list",
144
- name,
145
- "--json",
146
- ...(omitDev ? ["--omit", "dev"] : []),
147
- ...(depth === undefined ? [] : ["--depth", depth.toString(10)]),
148
- ], { cwd, env });
149
- if (!result.stdout)
150
- return;
151
- const json = JSON.parse(result.stdout.toString());
152
- return scanDependencyTree(name, json.dependencies);
70
+ const value = build(dir);
71
+ BUILD_MEMO.set(key, value);
72
+ return value;
153
73
  }
154
- exports.findDependency = findDependency;
155
74
  async function prepareFrameworks(targetNames, context, options, emulators = []) {
156
- var _a, _b, _c;
157
- var _d, _e, _f, _g;
75
+ var _a, _b, _c, _d, _e;
76
+ var _f, _g, _h, _j, _k;
158
77
  const nodeVersion = process.version;
159
78
  if (!semver.satisfies(nodeVersion, ">=16.0.0")) {
160
79
  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.`);
@@ -166,7 +85,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
166
85
  try {
167
86
  await (0, requireHostingSite_1.requireHostingSite)(options);
168
87
  }
169
- catch (_h) {
88
+ catch (_l) {
170
89
  options.site = project;
171
90
  }
172
91
  }
@@ -175,7 +94,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
175
94
  if (configs.length === 0) {
176
95
  return;
177
96
  }
178
- const allowedRegionsValues = exports.ALLOWED_SSR_REGIONS.map((r) => r.value);
97
+ const allowedRegionsValues = constants_2.ALLOWED_SSR_REGIONS.map((r) => r.value);
179
98
  for (const config of configs) {
180
99
  const { source, site, public: publicDir, frameworksBackend } = config;
181
100
  if (!source) {
@@ -191,15 +110,16 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
191
110
  if (publicDir) {
192
111
  throw new Error(`hosting.public and hosting.source cannot both be set in firebase.json`);
193
112
  }
194
- const ssrRegion = (_b = frameworksBackend === null || frameworksBackend === void 0 ? void 0 : frameworksBackend.region) !== null && _b !== void 0 ? _b : exports.DEFAULT_REGION;
113
+ const ssrRegion = (_b = frameworksBackend === null || frameworksBackend === void 0 ? void 0 : frameworksBackend.region) !== null && _b !== void 0 ? _b : constants_2.DEFAULT_REGION;
114
+ const omitCloudFunction = (_c = frameworksBackend === null || frameworksBackend === void 0 ? void 0 : frameworksBackend.omit) !== null && _c !== void 0 ? _c : false;
195
115
  if (!allowedRegionsValues.includes(ssrRegion)) {
196
- const validRegions = allowedRegionsValues.join(", ");
116
+ const validRegions = (0, utils_1.conjoinOptions)(allowedRegionsValues);
197
117
  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}`);
198
118
  }
199
119
  const getProjectPath = (...args) => (0, path_1.join)(projectRoot, source, ...args);
200
120
  const functionId = `ssr${site.toLowerCase().replace(/-/g, "")}`;
201
- const usesFirebaseAdminSdk = !!findDependency("firebase-admin", { cwd: getProjectPath() });
202
- const usesFirebaseJsSdk = !!findDependency("@firebase/app", { cwd: getProjectPath() });
121
+ const usesFirebaseAdminSdk = !!(0, utils_1.findDependency)("firebase-admin", { cwd: getProjectPath() });
122
+ const usesFirebaseJsSdk = !!(0, utils_1.findDependency)("@firebase/app", { cwd: getProjectPath() });
203
123
  if (usesFirebaseAdminSdk) {
204
124
  process.env.GOOGLE_CLOUD_PROJECT = project;
205
125
  if (account && !process.env.GOOGLE_APPLICATION_CREDENTIALS) {
@@ -264,11 +184,12 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
264
184
  process.env.__FIREBASE_DEFAULTS__ = JSON.stringify(firebaseDefaults);
265
185
  }
266
186
  const results = await discover(getProjectPath());
267
- if (!results)
268
- throw new error_1.FirebaseError("Unable to detect the web framework in use, check firebase-debug.log for more info.");
187
+ if (!results) {
188
+ throw new error_1.FirebaseError((0, utils_1.frameworksCallToAction)("Unable to detect the web framework in use, check firebase-debug.log for more info."));
189
+ }
269
190
  const { framework, mayWantBackend, publicDirectory } = results;
270
- const { build, ɵcodegenPublicDirectory, ɵcodegenFunctionsDirectory: codegenProdModeFunctionsDirectory, getDevModeHandle, name, support, } = exports.WebFrameworks[framework];
271
- console.log(`Detected a ${name} codebase. ${SupportLevelWarnings[support] || ""}\n`);
191
+ const { build, ɵcodegenPublicDirectory, ɵcodegenFunctionsDirectory: codegenProdModeFunctionsDirectory, getDevModeHandle, name, support, docsUrl, } = constants_2.WebFrameworks[framework];
192
+ console.log(`\n${(0, utils_1.frameworksCallToAction)(constants_2.SupportLevelWarnings[support](name), docsUrl, " ")}\n`);
272
193
  const isDevMode = context._name === "serve" || context._name === "emulators:start";
273
194
  const hostingEmulatorInfo = emulators.find((e) => e.name === types_1.Emulators.HOSTING);
274
195
  const devModeHandle = isDevMode &&
@@ -283,17 +204,22 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
283
204
  }
284
205
  }
285
206
  else {
286
- const { wantsBackend = false, rewrites = [], redirects = [], headers = [], trailingSlash, } = (await build(getProjectPath())) || {};
207
+ const { wantsBackend = false, rewrites = [], redirects = [], headers = [], trailingSlash, i18n = false, } = (await memoizeBuild(getProjectPath(), build, [firebaseDefaults])) || {};
287
208
  config.rewrites.push(...rewrites);
288
209
  config.redirects.push(...redirects);
289
210
  config.headers.push(...headers);
290
- (_c = config.trailingSlash) !== null && _c !== void 0 ? _c : (config.trailingSlash = trailingSlash);
211
+ (_d = config.trailingSlash) !== null && _d !== void 0 ? _d : (config.trailingSlash = trailingSlash);
212
+ if (i18n)
213
+ (_e = config.i18n) !== null && _e !== void 0 ? _e : (config.i18n = { root: constants_2.I18N_ROOT });
291
214
  if (await (0, fs_extra_1.pathExists)(hostingDist))
292
215
  await (0, promises_1.rm)(hostingDist, { recursive: true });
293
216
  await (0, fs_extra_1.mkdirp)(hostingDist);
294
- await ɵcodegenPublicDirectory(getProjectPath(), hostingDist);
217
+ await ɵcodegenPublicDirectory(getProjectPath(), hostingDist, {
218
+ project,
219
+ site,
220
+ });
295
221
  config.public = (0, path_1.relative)(projectRoot, hostingDist);
296
- if (wantsBackend)
222
+ if (wantsBackend && !omitCloudFunction)
297
223
  codegenFunctionsDirectory = codegenProdModeFunctionsDirectory;
298
224
  }
299
225
  config.webFramework = `${framework}${codegenFunctionsDirectory ? "_ssr" : ""}`;
@@ -302,16 +228,9 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
302
228
  firebaseDefaults._authTokenSyncURL = "/__session";
303
229
  process.env.__FIREBASE_DEFAULTS__ = JSON.stringify(firebaseDefaults);
304
230
  }
305
- const rewrite = {
306
- source: "**",
307
- function: {
308
- functionId,
309
- },
310
- };
311
- if (experiments.isEnabled("pintags")) {
312
- rewrite.function.pinTag = true;
231
+ if (context.hostingChannel) {
232
+ experiments.assertEnabled("pintags", "deploy an app that requires a backend to a preview channel");
313
233
  }
314
- config.rewrites.push(rewrite);
315
234
  const codebase = `firebase-frameworks-${site}`;
316
235
  const existingFunctionsConfig = options.config.get("functions")
317
236
  ? [].concat(options.config.get("functions"))
@@ -323,11 +242,16 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
323
242
  codebase,
324
243
  },
325
244
  ]);
326
- if (!targetNames.includes("functions")) {
327
- targetNames.unshift("functions");
328
- }
329
- if (options.only) {
330
- options.only = (0, ensureTargeted_1.ensureTargeted)(options.only, codebase);
245
+ if (!experiments.isEnabled("pintags") ||
246
+ context._name === "serve" ||
247
+ context._name === "emulators:start" ||
248
+ context._name === "emulators:exec") {
249
+ if (!targetNames.includes("functions")) {
250
+ targetNames.unshift("functions");
251
+ }
252
+ if (options.only) {
253
+ options.only = (0, ensureTargeted_1.ensureTargeted)(options.only, codebase);
254
+ }
331
255
  }
332
256
  if (await (0, fs_extra_1.pathExists)(functionsDist)) {
333
257
  const functionsDistStat = await (0, fs_extra_1.stat)(functionsDist);
@@ -345,16 +269,38 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
345
269
  else {
346
270
  await (0, fs_extra_1.mkdirp)(functionsDist);
347
271
  }
348
- const { packageJson, bootstrapScript, frameworksEntry = framework, } = await codegenFunctionsDirectory(getProjectPath(), functionsDist);
272
+ const { packageJson, bootstrapScript, frameworksEntry = framework, baseUrl = "", dotEnv = {}, } = await codegenFunctionsDirectory(getProjectPath(), functionsDist);
273
+ config.rewrites.push({
274
+ source: path_1.posix.normalize(path_1.posix.join(baseUrl, "**")),
275
+ function: {
276
+ functionId,
277
+ region: ssrRegion,
278
+ pinTag: experiments.isEnabled("pintags"),
279
+ },
280
+ });
349
281
  process.env.__FIREBASE_FRAMEWORKS_ENTRY__ = frameworksEntry;
350
282
  packageJson.main = "server.js";
351
- delete packageJson.devDependencies;
352
283
  packageJson.dependencies || (packageJson.dependencies = {});
353
- (_d = packageJson.dependencies)["firebase-frameworks"] || (_d["firebase-frameworks"] = exports.FIREBASE_FRAMEWORKS_VERSION);
354
- (_e = packageJson.dependencies)["firebase-functions"] || (_e["firebase-functions"] = exports.FIREBASE_FUNCTIONS_VERSION);
355
- (_f = packageJson.dependencies)["firebase-admin"] || (_f["firebase-admin"] = exports.FIREBASE_ADMIN_VERSION);
284
+ (_f = packageJson.dependencies)["firebase-frameworks"] || (_f["firebase-frameworks"] = constants_2.FIREBASE_FRAMEWORKS_VERSION);
285
+ (_g = packageJson.dependencies)["firebase-functions"] || (_g["firebase-functions"] = constants_2.FIREBASE_FUNCTIONS_VERSION);
286
+ (_h = packageJson.dependencies)["firebase-admin"] || (_h["firebase-admin"] = constants_2.FIREBASE_ADMIN_VERSION);
356
287
  packageJson.engines || (packageJson.engines = {});
357
- (_g = packageJson.engines).node || (_g.node = exports.NODE_VERSION);
288
+ const validEngines = constants_2.VALID_ENGINES.node.filter((it) => it <= constants_2.NODE_VERSION);
289
+ const engine = validEngines[validEngines.length - 1] || constants_2.VALID_ENGINES.node[0];
290
+ if (engine !== constants_2.NODE_VERSION) {
291
+ (0, utils_2.logWarning)(`This integration expects Node version ${(0, utils_1.conjoinOptions)(constants_2.VALID_ENGINES.node, "or")}. You're running version ${constants_2.NODE_VERSION}, problems may be encountered.`);
292
+ }
293
+ (_j = packageJson.engines).node || (_j.node = engine.toString());
294
+ delete packageJson.scripts;
295
+ delete packageJson.devDependencies;
296
+ const bundledDependencies = packageJson.bundledDependencies || {};
297
+ if (Object.keys(bundledDependencies).length) {
298
+ (0, utils_2.logWarning)("Bundled dependencies aren't supported in Cloud Functions, converting to dependencies.");
299
+ for (const [dep, version] of Object.entries(bundledDependencies)) {
300
+ (_k = packageJson.dependencies)[dep] || (_k[dep] = version);
301
+ }
302
+ delete packageJson.bundledDependencies;
303
+ }
358
304
  for (const [name, version] of Object.entries(packageJson.dependencies)) {
359
305
  if (version.startsWith("file:")) {
360
306
  const path = version.replace(/^file:/, "");
@@ -362,12 +308,12 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
362
308
  continue;
363
309
  const stats = await (0, fs_extra_1.stat)(path);
364
310
  if (stats.isDirectory()) {
365
- const result = (0, cross_spawn_1.sync)("npm", ["pack", (0, path_1.relative)(functionsDist, path)], {
311
+ const result = (0, cross_spawn_1.sync)("npm", ["pack", (0, path_1.relative)(functionsDist, path), "--json=true"], {
366
312
  cwd: functionsDist,
367
313
  });
368
- if (!result.stdout)
314
+ if (result.status)
369
315
  throw new Error(`Error running \`npm pack\` at ${path}`);
370
- const filename = result.stdout.toString().trim();
316
+ const { filename } = JSON.parse(result.stdout.toString())[0];
371
317
  packageJson.dependencies[name] = `file:${filename}`;
372
318
  }
373
319
  else {
@@ -383,13 +329,16 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
383
329
  if (await (0, fs_extra_1.pathExists)(getProjectPath(".npmrc"))) {
384
330
  await (0, promises_1.copyFile)(getProjectPath(".npmrc"), (0, path_1.join)(functionsDist, ".npmrc"));
385
331
  }
386
- let existingDotEnvContents = "";
332
+ let dotEnvContents = "";
387
333
  if (await (0, fs_extra_1.pathExists)(getProjectPath(".env"))) {
388
- existingDotEnvContents = (await (0, promises_1.readFile)(getProjectPath(".env"))).toString();
334
+ dotEnvContents = (await (0, promises_1.readFile)(getProjectPath(".env"))).toString();
335
+ }
336
+ for (const [key, value] of Object.entries(dotEnv)) {
337
+ dotEnvContents += `\n${key}=${value}`;
389
338
  }
390
- await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, ".env"), `${existingDotEnvContents}
339
+ await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, ".env"), `${dotEnvContents}
391
340
  __FIREBASE_FRAMEWORKS_ENTRY__=${frameworksEntry}
392
- ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\n` : ""}`);
341
+ ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\n` : ""}`.trimStart());
393
342
  const envs = await new Promise((resolve, reject) => glob(getProjectPath(".env.*"), (err, matches) => {
394
343
  if (err)
395
344
  reject(err);
@@ -416,6 +365,9 @@ ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\
416
365
  }
417
366
  }
418
367
  else {
368
+ if (await (0, fs_extra_1.pathExists)(functionsDist)) {
369
+ await (0, promises_1.rm)(functionsDist, { recursive: true });
370
+ }
419
371
  config.rewrites.push({
420
372
  source: "**",
421
373
  destination: "/index.html",
@@ -437,6 +389,13 @@ ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\
437
389
  });
438
390
  }
439
391
  }
392
+ if (process.env.DEBUG) {
393
+ console.log("Effective firebase.json:");
394
+ console.log(JSON.stringify(configs, undefined, 2));
395
+ }
396
+ BUILD_MEMO.clear();
397
+ delete process.env.__FIREBASE_DEFAULTS__;
398
+ delete process.env.__FIREBASE_FRAMEWORKS_ENTRY__;
440
399
  }
441
400
  exports.prepareFrameworks = prepareFrameworks;
442
401
  function codegenDevModeFunctionsDirectory() {
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ROUTES_MANIFEST = exports.PRERENDER_MANIFEST = exports.PAGES_MANIFEST = exports.MIDDLEWARE_MANIFEST = exports.IMAGES_MANIFEST = exports.EXPORT_MARKER = exports.APP_PATH_ROUTES_MANIFEST = void 0;
3
+ exports.APP_PATHS_MANIFEST = exports.ROUTES_MANIFEST = exports.PRERENDER_MANIFEST = exports.PAGES_MANIFEST = exports.MIDDLEWARE_MANIFEST = exports.IMAGES_MANIFEST = exports.EXPORT_MARKER = exports.APP_PATH_ROUTES_MANIFEST = void 0;
4
4
  exports.APP_PATH_ROUTES_MANIFEST = "app-path-routes-manifest.json";
5
5
  exports.EXPORT_MARKER = "export-marker.json";
6
6
  exports.IMAGES_MANIFEST = "images-manifest.json";
@@ -8,3 +8,4 @@ exports.MIDDLEWARE_MANIFEST = "middleware-manifest.json";
8
8
  exports.PAGES_MANIFEST = "pages-manifest.json";
9
9
  exports.PRERENDER_MANIFEST = "prerender-manifest.json";
10
10
  exports.ROUTES_MANIFEST = "routes-manifest.json";
11
+ exports.APP_PATHS_MANIFEST = "app-paths-manifest.json";