firebase-tools 12.2.1 → 12.3.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 (35) hide show
  1. package/lib/commands/functions-secrets-access.js +2 -0
  2. package/lib/commands/functions-secrets-destroy.js +1 -0
  3. package/lib/commands/functions-secrets-get.js +2 -0
  4. package/lib/commands/functions-secrets-prune.js +3 -2
  5. package/lib/commands/functions-secrets-set.js +8 -0
  6. package/lib/commands/hosting-channel-deploy.js +5 -3
  7. package/lib/commands/index.js +2 -0
  8. package/lib/commands/internaltesting-frameworks-compose.js +20 -0
  9. package/lib/deploy/functions/release/executor.js +19 -10
  10. package/lib/deploy/functions/release/fabricator.js +22 -8
  11. package/lib/deploy/index.js +1 -1
  12. package/lib/emulator/auth/operations.js +2 -2
  13. package/lib/emulator/commandUtils.js +1 -1
  14. package/lib/emulator/controller.js +6 -2
  15. package/lib/emulator/functionsEmulatorShared.js +3 -0
  16. package/lib/frameworks/angular/index.js +10 -9
  17. package/lib/frameworks/astro/index.js +8 -6
  18. package/lib/frameworks/compose/discover/index.js +23 -0
  19. package/lib/frameworks/compose/driver/docker.js +177 -0
  20. package/lib/frameworks/compose/driver/hooks.js +22 -0
  21. package/lib/frameworks/compose/driver/index.js +16 -0
  22. package/lib/frameworks/compose/driver/local.js +42 -0
  23. package/lib/frameworks/compose/index.js +30 -0
  24. package/lib/frameworks/compose/interfaces.js +21 -0
  25. package/lib/frameworks/index.js +57 -48
  26. package/lib/frameworks/next/index.js +18 -17
  27. package/lib/frameworks/nuxt/index.js +7 -7
  28. package/lib/frameworks/nuxt2/index.js +2 -1
  29. package/lib/frameworks/utils.js +37 -22
  30. package/lib/frameworks/vite/index.js +2 -1
  31. package/lib/functions/secrets.js +8 -1
  32. package/lib/serve/index.js +1 -1
  33. package/package.json +1 -1
  34. package/templates/extensions/extension.yaml +7 -57
  35. package/templates/extensions/javascript/index.js +1 -1
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DockerDriver = exports.DockerfileBuilder = void 0;
4
+ const fs = require("node:fs");
5
+ const path = require("node:path");
6
+ const spawn = require("cross-spawn");
7
+ const hooks_1 = require("./hooks");
8
+ const ADAPTER_SCRIPTS_PATH = "./.firebase/adapters";
9
+ const DOCKER_STAGE_INSTALL = "installer";
10
+ const DOCKER_STAGE_BUILD = "builder";
11
+ class DockerfileBuilder {
12
+ constructor() {
13
+ this.dockerfile = "";
14
+ this.lastStage = "";
15
+ }
16
+ from(image, name) {
17
+ this.dockerfile += `FROM ${image}`;
18
+ if (name) {
19
+ this.dockerfile += ` AS ${name}`;
20
+ this.lastStage = name;
21
+ }
22
+ this.dockerfile += "\n";
23
+ return this;
24
+ }
25
+ fromLastStage(name) {
26
+ return this.from(this.lastStage, name);
27
+ }
28
+ tempFrom(image, name) {
29
+ this.dockerfile += `FROM ${image}`;
30
+ if (name) {
31
+ this.dockerfile += ` AS ${name}`;
32
+ }
33
+ this.dockerfile += "\n";
34
+ return this;
35
+ }
36
+ workdir(dir) {
37
+ this.dockerfile += `WORKDIR ${dir}\n`;
38
+ return this;
39
+ }
40
+ copyForFirebase(src, dest, from) {
41
+ if (from) {
42
+ this.dockerfile += `COPY --chown=firebase:firebase --from=${from} ${src} ${dest}\n`;
43
+ }
44
+ else {
45
+ this.dockerfile += `COPY --chown=firebase:firebase ${src} ${dest}\n`;
46
+ }
47
+ return this;
48
+ }
49
+ copyFrom(src, dest, from) {
50
+ this.dockerfile += `COPY --from=${from} ${src} ${dest}\n`;
51
+ return this;
52
+ }
53
+ run(cmd, mount) {
54
+ if (mount) {
55
+ this.dockerfile += `RUN --mount=${mount} ${cmd}\n`;
56
+ }
57
+ else {
58
+ this.dockerfile += `RUN ${cmd}\n`;
59
+ }
60
+ return this;
61
+ }
62
+ env(key, value) {
63
+ this.dockerfile += `ENV ${key}="${value}"\n`;
64
+ return this;
65
+ }
66
+ envs(envs) {
67
+ for (const [key, value] of Object.entries(envs)) {
68
+ this.env(key, value);
69
+ }
70
+ return this;
71
+ }
72
+ cmd(cmds) {
73
+ this.dockerfile += `CMD [${cmds.map((c) => `"${c}"`).join(", ")}]\n`;
74
+ return this;
75
+ }
76
+ user(user) {
77
+ this.dockerfile += `USER ${user}\n`;
78
+ return this;
79
+ }
80
+ toString() {
81
+ return this.dockerfile;
82
+ }
83
+ }
84
+ exports.DockerfileBuilder = DockerfileBuilder;
85
+ class DockerDriver {
86
+ constructor(spec) {
87
+ this.spec = spec;
88
+ this.dockerfileBuilder = new DockerfileBuilder();
89
+ this.dockerfileBuilder.from(spec.baseImage, "base").user("firebase");
90
+ }
91
+ execDockerPush(args) {
92
+ console.log(`executing docker build: ${args.join(" ")}`);
93
+ return spawn.sync("docker", ["push", ...args], {
94
+ stdio: ["pipe", "inherit", "inherit"],
95
+ });
96
+ }
97
+ execDockerBuild(args, contextDir) {
98
+ console.log(`executing docker build: ${args.join(" ")} ${contextDir}`);
99
+ console.log(this.dockerfileBuilder.toString());
100
+ return spawn.sync("docker", ["buildx", "build", ...args, "-f", "-", contextDir], {
101
+ env: Object.assign(Object.assign({}, process.env), this.spec.environmentVariables),
102
+ input: this.dockerfileBuilder.toString(),
103
+ stdio: ["pipe", "inherit", "inherit"],
104
+ });
105
+ }
106
+ buildStage(stage, contextDir, tag) {
107
+ console.log(`Building stage: ${stage}`);
108
+ const args = ["--target", stage];
109
+ if (tag) {
110
+ args.push("--tag", tag);
111
+ }
112
+ const ret = this.execDockerBuild(args, contextDir);
113
+ if (ret.error || ret.status !== 0) {
114
+ throw new Error(`Failed to execute stage ${stage}: error=${ret.error} status=${ret.status}`);
115
+ }
116
+ }
117
+ exportBundle(stage, contextDir) {
118
+ const exportStage = `${stage}-export`;
119
+ this.dockerfileBuilder
120
+ .tempFrom("scratch", exportStage)
121
+ .copyFrom(hooks_1.BUNDLE_PATH, "/bundle.json", stage);
122
+ const ret = this.execDockerBuild(["--target", exportStage, "--output", ".firebase/.output"], contextDir);
123
+ if (ret.error || ret.status !== 0) {
124
+ throw new Error(`Failed to export bundle ${stage}: error=${ret.error} status=${ret.status}`);
125
+ }
126
+ return JSON.parse(fs.readFileSync("./.firebase/.output/bundle.json", "utf8"));
127
+ }
128
+ install() {
129
+ this.dockerfileBuilder
130
+ .fromLastStage(DOCKER_STAGE_INSTALL)
131
+ .workdir("/home/firebase/app")
132
+ .envs(this.spec.environmentVariables || {})
133
+ .copyForFirebase("package.json", ".")
134
+ .run(this.spec.installCommand);
135
+ this.buildStage(DOCKER_STAGE_INSTALL, ".");
136
+ }
137
+ build() {
138
+ this.dockerfileBuilder
139
+ .fromLastStage(DOCKER_STAGE_BUILD)
140
+ .copyForFirebase(".", ".")
141
+ .run(this.spec.buildCommand);
142
+ this.buildStage(DOCKER_STAGE_BUILD, ".");
143
+ }
144
+ export(bundle) {
145
+ var _a;
146
+ const startCmd = (_a = bundle.server) === null || _a === void 0 ? void 0 : _a.start.cmd;
147
+ if (startCmd) {
148
+ const exportStage = "exporter";
149
+ this.dockerfileBuilder
150
+ .from(this.spec.baseImage, exportStage)
151
+ .workdir("/home/firebase/app")
152
+ .copyForFirebase("/home/firebase/app", ".", DOCKER_STAGE_BUILD)
153
+ .cmd(startCmd);
154
+ const imageName = `us-docker.pkg.dev/${process.env.PROJECT_ID}/test/demo-nodappe`;
155
+ this.buildStage(exportStage, ".", imageName);
156
+ const ret = this.execDockerPush([imageName]);
157
+ if (ret.error || ret.status !== 0) {
158
+ throw new Error(`Failed to push image ${imageName}: error=${ret.error} status=${ret.status}`);
159
+ }
160
+ }
161
+ }
162
+ execHook(bundle, hook) {
163
+ const hookScript = `hook-${Date.now()}.js`;
164
+ const hookScriptSrc = (0, hooks_1.genHookScript)(bundle, hook);
165
+ if (!fs.existsSync(ADAPTER_SCRIPTS_PATH)) {
166
+ fs.mkdirSync(ADAPTER_SCRIPTS_PATH, { recursive: true });
167
+ }
168
+ fs.writeFileSync(path.join(ADAPTER_SCRIPTS_PATH, hookScript), hookScriptSrc);
169
+ const hookStage = path.basename(hookScript, ".js");
170
+ this.dockerfileBuilder
171
+ .fromLastStage(hookStage)
172
+ .run(`NODE_PATH=./node_modules node /framework/adapters/${hookScript}`, `source=${ADAPTER_SCRIPTS_PATH},target=/framework/adapters`);
173
+ this.buildStage(hookStage, ".");
174
+ return this.exportBundle(hookStage, ".");
175
+ }
176
+ }
177
+ exports.DockerDriver = DockerDriver;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.genHookScript = exports.BUNDLE_PATH = void 0;
4
+ exports.BUNDLE_PATH = "/home/firebase/app/.firebase/.output/bundle.json";
5
+ function genHookScript(bundle, hook) {
6
+ let hookSrc = hook.toString().trimLeft();
7
+ if (!hookSrc.startsWith("(") && !hookSrc.startsWith("function ")) {
8
+ hookSrc = `function ${hookSrc}`;
9
+ }
10
+ return `
11
+ const fs = require("node:fs");
12
+ const path = require("node:path");
13
+
14
+ const bundleDir = path.dirname("${exports.BUNDLE_PATH}");
15
+ if (!fs.existsSync(bundleDir)) {
16
+ fs.mkdirSync(bundleDir, { recursive: true });
17
+ }
18
+ const bundle = (${hookSrc})(${JSON.stringify(bundle)});
19
+ fs.writeFileSync("${exports.BUNDLE_PATH}", JSON.stringify(bundle));
20
+ `;
21
+ }
22
+ exports.genHookScript = genHookScript;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDriver = exports.SUPPORTED_MODES = void 0;
4
+ const local_1 = require("./local");
5
+ const docker_1 = require("./docker");
6
+ exports.SUPPORTED_MODES = ["local", "docker"];
7
+ function getDriver(mode, app) {
8
+ if (mode === "local") {
9
+ return new local_1.LocalDriver(app);
10
+ }
11
+ else if (mode === "docker") {
12
+ return new docker_1.DockerDriver(app);
13
+ }
14
+ throw new Error(`Unsupported mode ${mode}`);
15
+ }
16
+ exports.getDriver = getDriver;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalDriver = void 0;
4
+ const fs = require("node:fs");
5
+ const spawn = require("cross-spawn");
6
+ const hooks_1 = require("./hooks");
7
+ class LocalDriver {
8
+ constructor(spec) {
9
+ this.spec = spec;
10
+ }
11
+ execCmd(cmd, args) {
12
+ const ret = spawn.sync(cmd, args, {
13
+ env: Object.assign(Object.assign({}, process.env), this.spec.environmentVariables),
14
+ stdio: ["pipe", "inherit", "inherit"],
15
+ });
16
+ if (ret.error) {
17
+ throw ret.error;
18
+ }
19
+ }
20
+ install() {
21
+ const [cmd, ...args] = this.spec.installCommand.split(" ");
22
+ this.execCmd(cmd, args);
23
+ }
24
+ build() {
25
+ const [cmd, ...args] = this.spec.buildCommand.split(" ");
26
+ this.execCmd(cmd, args);
27
+ }
28
+ export(bundle) {
29
+ }
30
+ execHook(bundle, hook) {
31
+ const script = (0, hooks_1.genHookScript)(bundle, hook);
32
+ this.execCmd("node", ["-e", script]);
33
+ if (!fs.existsSync(hooks_1.BUNDLE_PATH)) {
34
+ console.warn(`Expected hook to generate app bundle at ${hooks_1.BUNDLE_PATH} but got nothing.`);
35
+ console.warn("Returning original bundle.");
36
+ return bundle;
37
+ }
38
+ const newBundle = JSON.parse(fs.readFileSync(hooks_1.BUNDLE_PATH, "utf8"));
39
+ return newBundle;
40
+ }
41
+ }
42
+ exports.LocalDriver = LocalDriver;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compose = void 0;
4
+ const driver_1 = require("./driver");
5
+ const discover_1 = require("./discover");
6
+ function compose(mode) {
7
+ let bundle = { version: "v1alpha" };
8
+ const spec = (0, discover_1.discover)();
9
+ const driver = (0, driver_1.getDriver)(mode, spec);
10
+ if (spec.startCommand) {
11
+ bundle.server = {
12
+ start: {
13
+ cmd: spec.startCommand.split(" "),
14
+ },
15
+ };
16
+ }
17
+ driver.install();
18
+ if (spec.afterInstall) {
19
+ bundle = driver.execHook(bundle, spec.afterInstall);
20
+ }
21
+ driver.build();
22
+ if (spec.afterBuild) {
23
+ bundle = driver.execHook(bundle, spec.afterBuild);
24
+ }
25
+ if (bundle.server) {
26
+ driver.export(bundle);
27
+ }
28
+ return bundle;
29
+ }
30
+ exports.compose = compose;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Driver = void 0;
4
+ class Driver {
5
+ constructor(spec) {
6
+ this.spec = spec;
7
+ }
8
+ install() {
9
+ throw new Error("install() not implemented");
10
+ }
11
+ build() {
12
+ throw new Error("build() not implemented");
13
+ }
14
+ export(bundle) {
15
+ throw new Error("export() not implemented");
16
+ }
17
+ execHook(bundle, hook) {
18
+ throw new Error("execHook() not implemented");
19
+ }
20
+ }
21
+ exports.Driver = Driver;
@@ -8,7 +8,6 @@ const cross_spawn_1 = require("cross-spawn");
8
8
  const promises_1 = require("fs/promises");
9
9
  const fs_extra_1 = require("fs-extra");
10
10
  const process = require("node:process");
11
- const semver = require("semver");
12
11
  const glob = require("glob");
13
12
  const projectUtils_1 = require("../projectUtils");
14
13
  const config_1 = require("../hosting/config");
@@ -30,6 +29,8 @@ Object.defineProperty(exports, "WebFrameworks", { enumerable: true, get: functio
30
29
  const utils_2 = require("../utils");
31
30
  const ensureTargeted_1 = require("../functions/ensureTargeted");
32
31
  const util_1 = require("util");
32
+ const projectPath_1 = require("../projectPath");
33
+ const logger_1 = require("../logger");
33
34
  async function discover(dir, warn = true) {
34
35
  const allFrameworkTypes = [
35
36
  ...new Set(Object.values(constants_2.WebFrameworks).map(({ type }) => type)),
@@ -71,21 +72,17 @@ function memoizeBuild(dir, build, deps, target) {
71
72
  BUILD_MEMO.set(key, value);
72
73
  return value;
73
74
  }
74
- async function prepareFrameworks(targetNames, context, options, emulators = []) {
75
- var _a, _b, _c, _d, _e;
76
- var _f, _g, _h, _j, _k;
77
- const nodeVersion = process.version;
78
- if (!semver.satisfies(nodeVersion, ">=16.0.0")) {
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.`);
80
- }
81
- const project = (0, projectUtils_1.needProjectId)(context);
82
- const { projectRoot } = options;
75
+ async function prepareFrameworks(purpose, targetNames, context, options, emulators = []) {
76
+ var _a, _b, _c, _d, _e, _f;
77
+ var _g, _h, _j, _k, _l;
78
+ const project = (0, projectUtils_1.needProjectId)(context || options);
79
+ const projectRoot = (0, projectPath_1.resolveProjectPath)(options, ".");
83
80
  const account = (0, auth_1.getProjectDefaultAccount)(projectRoot);
84
81
  if (!options.site) {
85
82
  try {
86
83
  await (0, requireHostingSite_1.requireHostingSite)(options);
87
84
  }
88
- catch (_l) {
85
+ catch (_m) {
89
86
  options.site = project;
90
87
  }
91
88
  }
@@ -189,13 +186,17 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
189
186
  }
190
187
  const { framework, mayWantBackend, publicDirectory } = results;
191
188
  const { build, ɵcodegenPublicDirectory, ɵcodegenFunctionsDirectory: codegenProdModeFunctionsDirectory, getDevModeHandle, name, support, docsUrl, getValidBuildTargets = constants_2.GET_DEFAULT_BUILD_TARGETS, shouldUseDevModeHandle = constants_2.DEFAULT_SHOULD_USE_DEV_MODE_HANDLE, } = constants_2.WebFrameworks[framework];
192
- console.log(`\n${(0, utils_1.frameworksCallToAction)(constants_2.SupportLevelWarnings[support](name), docsUrl, " ")}\n`);
189
+ logger_1.logger.info(`\n${(0, utils_1.frameworksCallToAction)(constants_2.SupportLevelWarnings[support](name), docsUrl, " ")}\n`);
193
190
  const hostingEmulatorInfo = emulators.find((e) => e.name === types_1.Emulators.HOSTING);
194
- const buildTargetPurpose = context._name === "deploy" ? "deploy" : context._name === "emulators:exec" ? "test" : "serve";
195
- const validBuildTargets = await getValidBuildTargets(buildTargetPurpose, getProjectPath());
196
- const frameworksBuildTarget = (0, utils_1.getFrameworksBuildTarget)(buildTargetPurpose, validBuildTargets);
197
- const useDevModeHandle = await shouldUseDevModeHandle(frameworksBuildTarget, getProjectPath());
191
+ const validBuildTargets = await getValidBuildTargets(purpose, getProjectPath());
192
+ const frameworksBuildTarget = (0, utils_1.getFrameworksBuildTarget)(purpose, validBuildTargets);
193
+ const useDevModeHandle = purpose !== "deploy" &&
194
+ (await shouldUseDevModeHandle(frameworksBuildTarget, getProjectPath()));
198
195
  let codegenFunctionsDirectory;
196
+ let baseUrl = "";
197
+ const rewrites = [];
198
+ const redirects = [];
199
+ const headers = [];
199
200
  const devModeHandle = useDevModeHandle &&
200
201
  getDevModeHandle &&
201
202
  (await getDevModeHandle(getProjectPath(), frameworksBuildTarget, hostingEmulatorInfo));
@@ -208,13 +209,19 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
208
209
  }
209
210
  else {
210
211
  const buildResult = await memoizeBuild(getProjectPath(), build, [firebaseDefaults, frameworksBuildTarget], frameworksBuildTarget);
211
- const { wantsBackend = false, rewrites = [], redirects = [], headers = [], trailingSlash, i18n = false, } = buildResult || {};
212
- config.rewrites.push(...rewrites);
213
- config.redirects.push(...redirects);
214
- config.headers.push(...headers);
215
- (_d = config.trailingSlash) !== null && _d !== void 0 ? _d : (config.trailingSlash = trailingSlash);
212
+ const { wantsBackend = false, trailingSlash, i18n = false } = buildResult || {};
213
+ if (buildResult) {
214
+ baseUrl = (_d = buildResult.baseUrl) !== null && _d !== void 0 ? _d : baseUrl;
215
+ if (buildResult.headers)
216
+ headers.push(...buildResult.headers);
217
+ if (buildResult.rewrites)
218
+ rewrites.push(...buildResult.rewrites);
219
+ if (buildResult.redirects)
220
+ redirects.push(...buildResult.redirects);
221
+ }
222
+ (_e = config.trailingSlash) !== null && _e !== void 0 ? _e : (config.trailingSlash = trailingSlash);
216
223
  if (i18n)
217
- (_e = config.i18n) !== null && _e !== void 0 ? _e : (config.i18n = { root: constants_2.I18N_ROOT });
224
+ (_f = config.i18n) !== null && _f !== void 0 ? _f : (config.i18n = { root: constants_2.I18N_ROOT });
218
225
  if (await (0, fs_extra_1.pathExists)(hostingDist))
219
226
  await (0, promises_1.rm)(hostingDist, { recursive: true });
220
227
  await (0, fs_extra_1.mkdirp)(hostingDist);
@@ -232,7 +239,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
232
239
  firebaseDefaults._authTokenSyncURL = "/__session";
233
240
  process.env.__FIREBASE_DEFAULTS__ = JSON.stringify(firebaseDefaults);
234
241
  }
235
- if (context.hostingChannel) {
242
+ if (context === null || context === void 0 ? void 0 : context.hostingChannel) {
236
243
  experiments.assertEnabled("pintags", "deploy an app that requires a backend to a preview channel");
237
244
  }
238
245
  const codebase = `firebase-frameworks-${site}`;
@@ -246,10 +253,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
246
253
  codebase,
247
254
  },
248
255
  ]);
249
- if (!experiments.isEnabled("pintags") ||
250
- context._name === "serve" ||
251
- context._name === "emulators:start" ||
252
- context._name === "emulators:exec") {
256
+ if (!experiments.isEnabled("pintags") || purpose !== "deploy") {
253
257
  if (!targetNames.includes("functions")) {
254
258
  targetNames.unshift("functions");
255
259
  }
@@ -273,38 +277,41 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
273
277
  else {
274
278
  await (0, fs_extra_1.mkdirp)(functionsDist);
275
279
  }
276
- const { packageJson, bootstrapScript, frameworksEntry = framework, baseUrl = "", dotEnv = {}, rewriteSource = path_1.posix.join(baseUrl, "**"), } = await codegenFunctionsDirectory(getProjectPath(), functionsDist, frameworksBuildTarget);
277
- config.rewrites = [
278
- {
279
- source: rewriteSource,
280
- function: {
281
- functionId,
282
- region: ssrRegion,
283
- pinTag: experiments.isEnabled("pintags"),
284
- },
280
+ const { packageJson, bootstrapScript, frameworksEntry = framework, dotEnv = {}, rewriteSource, } = await codegenFunctionsDirectory(getProjectPath(), functionsDist, frameworksBuildTarget);
281
+ const rewrite = {
282
+ source: rewriteSource || path_1.posix.join(baseUrl, "**"),
283
+ function: {
284
+ functionId,
285
+ region: ssrRegion,
286
+ pinTag: experiments.isEnabled("pintags"),
285
287
  },
286
- ...config.rewrites,
287
- ];
288
+ };
289
+ if (rewriteSource) {
290
+ config.rewrites.unshift(rewrite);
291
+ }
292
+ else {
293
+ rewrites.push(rewrite);
294
+ }
288
295
  process.env.__FIREBASE_FRAMEWORKS_ENTRY__ = frameworksEntry;
289
296
  packageJson.main = "server.js";
290
297
  packageJson.dependencies || (packageJson.dependencies = {});
291
- (_f = packageJson.dependencies)["firebase-frameworks"] || (_f["firebase-frameworks"] = constants_2.FIREBASE_FRAMEWORKS_VERSION);
292
- (_g = packageJson.dependencies)["firebase-functions"] || (_g["firebase-functions"] = constants_2.FIREBASE_FUNCTIONS_VERSION);
293
- (_h = packageJson.dependencies)["firebase-admin"] || (_h["firebase-admin"] = constants_2.FIREBASE_ADMIN_VERSION);
298
+ (_g = packageJson.dependencies)["firebase-frameworks"] || (_g["firebase-frameworks"] = constants_2.FIREBASE_FRAMEWORKS_VERSION);
299
+ (_h = packageJson.dependencies)["firebase-functions"] || (_h["firebase-functions"] = constants_2.FIREBASE_FUNCTIONS_VERSION);
300
+ (_j = packageJson.dependencies)["firebase-admin"] || (_j["firebase-admin"] = constants_2.FIREBASE_ADMIN_VERSION);
294
301
  packageJson.engines || (packageJson.engines = {});
295
302
  const validEngines = constants_2.VALID_ENGINES.node.filter((it) => it <= constants_2.NODE_VERSION);
296
303
  const engine = validEngines[validEngines.length - 1] || constants_2.VALID_ENGINES.node[0];
297
304
  if (engine !== constants_2.NODE_VERSION) {
298
305
  (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.`);
299
306
  }
300
- (_j = packageJson.engines).node || (_j.node = engine.toString());
307
+ (_k = packageJson.engines).node || (_k.node = engine.toString());
301
308
  delete packageJson.scripts;
302
309
  delete packageJson.devDependencies;
303
310
  const bundledDependencies = packageJson.bundledDependencies || {};
304
311
  if (Object.keys(bundledDependencies).length) {
305
312
  (0, utils_2.logWarning)("Bundled dependencies aren't supported in Cloud Functions, converting to dependencies.");
306
313
  for (const [dep, version] of Object.entries(bundledDependencies)) {
307
- (_k = packageJson.dependencies)[dep] || (_k[dep] = version);
314
+ (_l = packageJson.dependencies)[dep] || (_l[dep] = version);
308
315
  }
309
316
  delete packageJson.bundledDependencies;
310
317
  }
@@ -376,13 +383,18 @@ ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\
376
383
  await (0, promises_1.rm)(functionsDist, { recursive: true });
377
384
  }
378
385
  }
386
+ const ourConfigShouldComeFirst = !["", "/"].includes(baseUrl);
387
+ const operation = ourConfigShouldComeFirst ? "unshift" : "push";
388
+ config.rewrites[operation](...rewrites);
389
+ config.redirects[operation](...redirects);
390
+ config.headers[operation](...headers);
379
391
  if (firebaseDefaults) {
380
392
  const encodedDefaults = Buffer.from(JSON.stringify(firebaseDefaults)).toString("base64url");
381
393
  const expires = new Date(new Date().getTime() + 60000000000);
382
394
  const sameSite = "Strict";
383
395
  const path = `/`;
384
396
  config.headers.push({
385
- source: "**/*.[jt]s",
397
+ source: path_1.posix.join(baseUrl, "**", "*.[jt]s"),
386
398
  headers: [
387
399
  {
388
400
  key: "Set-Cookie",
@@ -392,10 +404,7 @@ ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\
392
404
  });
393
405
  }
394
406
  }
395
- if (process.env.DEBUG) {
396
- console.log("Effective firebase.json:");
397
- console.log(JSON.stringify(configs, undefined, 2));
398
- }
407
+ logger_1.logger.debug("[web frameworks] effective firebase.json: ", JSON.stringify({ hosting: configs, functions: options.config.get("functions") }, undefined, 2));
399
408
  BUILD_MEMO.clear();
400
409
  delete process.env.__FIREBASE_DEFAULTS__;
401
410
  delete process.env.__FIREBASE_FRAMEWORKS_ENTRY__;
@@ -22,6 +22,7 @@ const utils_2 = require("./utils");
22
22
  const constants_1 = require("../constants");
23
23
  const constants_2 = require("./constants");
24
24
  const api_1 = require("../../hosting/api");
25
+ const logger_1 = require("../../logger");
25
26
  const DEFAULT_BUILD_SCRIPT = ["next build"];
26
27
  const PUBLIC_DIR = "public";
27
28
  exports.name = "Next.js";
@@ -58,7 +59,7 @@ async function build(dir) {
58
59
  throw e;
59
60
  });
60
61
  const reasonsForBackend = new Set();
61
- const { distDir, trailingSlash, basePath } = await getConfig(dir);
62
+ const { distDir, trailingSlash, basePath: baseUrl } = await getConfig(dir);
62
63
  if (await (0, utils_2.isUsingMiddleware)((0, path_1.join)(dir, distDir), false)) {
63
64
  reasonsForBackend.add("middleware");
64
65
  }
@@ -103,7 +104,7 @@ async function build(dir) {
103
104
  (0, utils_1.readJSON)((0, path_1.join)(dir, distDir, constants_2.APP_PATH_ROUTES_MANIFEST)).catch(() => undefined),
104
105
  ]);
105
106
  if (appPathRoutesManifest) {
106
- const headersFromMetaFiles = await (0, utils_2.getHeadersFromMetaFiles)(dir, distDir, basePath, appPathRoutesManifest);
107
+ const headersFromMetaFiles = await (0, utils_2.getHeadersFromMetaFiles)(dir, distDir, baseUrl, appPathRoutesManifest);
107
108
  headers.push(...headersFromMetaFiles);
108
109
  if (appPathsManifest) {
109
110
  const unrenderedServerComponents = (0, utils_2.getNonStaticServerComponents)(appPathsManifest, appPathRoutesManifest, prerenderedRoutes, dynamicRoutes);
@@ -144,15 +145,17 @@ async function build(dir) {
144
145
  }));
145
146
  const wantsBackend = reasonsForBackend.size > 0;
146
147
  if (wantsBackend) {
147
- const numberOfReasonsToList = process.env.DEBUG ? Infinity : DEFAULT_NUMBER_OF_REASONS_TO_LIST;
148
- console.log("Building a Cloud Function to run this application. This is needed due to:");
149
- for (const reason of Array.from(reasonsForBackend).slice(0, numberOfReasonsToList)) {
150
- console.log(` • ${reason}`);
148
+ logger_1.logger.info("Building a Cloud Function to run this application. This is needed due to:");
149
+ for (const reason of Array.from(reasonsForBackend).slice(0, DEFAULT_NUMBER_OF_REASONS_TO_LIST)) {
150
+ logger_1.logger.info(` ${reason}`);
151
151
  }
152
- if (reasonsForBackend.size > numberOfReasonsToList) {
153
- console.log(` • and ${reasonsForBackend.size - numberOfReasonsToList} other reasons, use --debug to see more`);
152
+ for (const reason of Array.from(reasonsForBackend).slice(DEFAULT_NUMBER_OF_REASONS_TO_LIST)) {
153
+ logger_1.logger.debug(` • ${reason}`);
154
154
  }
155
- console.log("");
155
+ if (reasonsForBackend.size > DEFAULT_NUMBER_OF_REASONS_TO_LIST && !process.env.DEBUG) {
156
+ logger_1.logger.info(` • and ${reasonsForBackend.size - DEFAULT_NUMBER_OF_REASONS_TO_LIST} other reasons, use --debug to see more`);
157
+ }
158
+ logger_1.logger.info("");
156
159
  }
157
160
  const i18n = !!nextjsI18n;
158
161
  return {
@@ -162,6 +165,7 @@ async function build(dir) {
162
165
  rewrites,
163
166
  trailingSlash,
164
167
  i18n,
168
+ baseUrl,
165
169
  };
166
170
  }
167
171
  exports.build = build;
@@ -226,13 +230,11 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
226
230
  await Promise.all(Object.entries(routesToCopy).map(async ([path, route]) => {
227
231
  var _a, _b;
228
232
  if (route.initialRevalidateSeconds) {
229
- if (process.env.DEBUG)
230
- console.log(`skipping ${path} due to revalidate`);
233
+ logger_1.logger.debug(`skipping ${path} due to revalidate`);
231
234
  return;
232
235
  }
233
236
  if (pathsUsingsFeaturesNotSupportedByHosting.some((it) => path.match(it))) {
234
- if (process.env.DEBUG)
235
- console.log(`skipping ${path} due to it matching an unsupported rewrite/redirect/header or middlware`);
237
+ logger_1.logger.debug(`skipping ${path} due to it matching an unsupported rewrite/redirect/header or middlware`);
236
238
  return;
237
239
  }
238
240
  const appPathRoute = route.srcRoute && ((_a = appPathRoutesEntries.find(([, it]) => it === route.srcRoute)) === null || _a === void 0 ? void 0 : _a[0]);
@@ -245,8 +247,7 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
245
247
  !matchingI18nDomain.locales ||
246
248
  matchingI18nDomain.locales.includes(locale);
247
249
  if (!includeOnThisDomain) {
248
- if (process.env.DEBUG)
249
- console.log(`skipping ${path} since it is for a locale not deployed on this domain`);
250
+ logger_1.logger.debug(`skipping ${path} since it is for a locale not deployed on this domain`);
250
251
  return;
251
252
  }
252
253
  const sourcePartsOrIndex = sourceParts.length > 0 ? sourceParts : ["index"];
@@ -293,7 +294,7 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
293
294
  exports.ɵcodegenPublicDirectory = ɵcodegenPublicDirectory;
294
295
  const BUNDLE_NEXT_CONFIG_TIMEOUT = 10000;
295
296
  async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
296
- const { distDir, basePath } = await getConfig(sourceDir);
297
+ const { distDir } = await getConfig(sourceDir);
297
298
  const packageJson = await (0, utils_1.readJSON)((0, path_1.join)(sourceDir, "package.json"));
298
299
  if ((0, fs_1.existsSync)((0, path_1.join)(sourceDir, "next.config.js"))) {
299
300
  try {
@@ -345,7 +346,7 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
345
346
  }
346
347
  await (0, fs_extra_1.mkdirp)((0, path_1.join)(destDir, distDir));
347
348
  await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, distDir), (0, path_1.join)(destDir, distDir));
348
- return { packageJson, frameworksEntry: "next.js", basePath };
349
+ return { packageJson, frameworksEntry: "next.js" };
349
350
  }
350
351
  exports.ɵcodegenFunctionsDirectory = ɵcodegenFunctionsDirectory;
351
352
  async function getDevModeHandle(dir, _, hostingEmulatorInfo) {