@opennextjs/cloudflare 0.3.10 → 0.4.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 (54) hide show
  1. package/README.md +1 -64
  2. package/dist/api/{get-cloudflare-context.d.ts → cloudflare-context.d.ts} +8 -1
  3. package/dist/api/cloudflare-context.js +96 -0
  4. package/dist/api/index.d.ts +1 -1
  5. package/dist/api/index.js +1 -1
  6. package/dist/api/kvCache.d.ts +0 -5
  7. package/dist/api/kvCache.js +15 -28
  8. package/dist/cli/build/build.d.ts +1 -1
  9. package/dist/cli/build/build.js +2 -12
  10. package/dist/cli/build/bundle-server.d.ts +4 -5
  11. package/dist/cli/build/bundle-server.js +32 -36
  12. package/dist/cli/build/open-next/compile-env-files.d.ts +1 -1
  13. package/dist/cli/build/open-next/compile-env-files.js +2 -2
  14. package/dist/cli/build/patches/ast/optional-deps.d.ts +4 -1
  15. package/dist/cli/build/patches/ast/optional-deps.js +2 -2
  16. package/dist/cli/build/patches/ast/util.d.ts +15 -4
  17. package/dist/cli/build/patches/ast/util.js +16 -5
  18. package/dist/cli/build/patches/ast/vercel-og.d.ts +23 -0
  19. package/dist/cli/build/patches/ast/vercel-og.js +58 -0
  20. package/dist/cli/build/patches/ast/vercel-og.spec.d.ts +1 -0
  21. package/dist/cli/build/patches/ast/vercel-og.spec.js +22 -0
  22. package/dist/cli/build/patches/investigated/copy-package-cli-files.d.ts +4 -3
  23. package/dist/cli/build/patches/investigated/copy-package-cli-files.js +8 -5
  24. package/dist/cli/build/patches/investigated/index.d.ts +1 -0
  25. package/dist/cli/build/patches/investigated/index.js +1 -0
  26. package/dist/cli/build/patches/investigated/patch-cache.d.ts +2 -2
  27. package/dist/cli/build/patches/investigated/patch-cache.js +7 -6
  28. package/dist/cli/build/patches/investigated/patch-require.d.ts +1 -4
  29. package/dist/cli/build/patches/investigated/patch-require.js +1 -4
  30. package/dist/cli/build/patches/investigated/patch-vercel-og-library.d.ts +7 -0
  31. package/dist/cli/build/patches/investigated/patch-vercel-og-library.js +39 -0
  32. package/dist/cli/build/patches/investigated/patch-vercel-og-library.spec.d.ts +1 -0
  33. package/dist/cli/build/patches/investigated/patch-vercel-og-library.spec.js +50 -0
  34. package/dist/cli/build/patches/investigated/update-webpack-chunks-file/index.d.ts +2 -5
  35. package/dist/cli/build/patches/investigated/update-webpack-chunks-file/index.js +6 -6
  36. package/dist/cli/build/patches/to-investigate/inline-eval-manifest.d.ts +2 -2
  37. package/dist/cli/build/patches/to-investigate/inline-eval-manifest.js +21 -17
  38. package/dist/cli/build/patches/to-investigate/inline-middleware-manifest-require.d.ts +2 -2
  39. package/dist/cli/build/patches/to-investigate/inline-middleware-manifest-require.js +4 -2
  40. package/dist/cli/build/patches/to-investigate/inline-next-require.d.ts +2 -2
  41. package/dist/cli/build/patches/to-investigate/inline-next-require.js +16 -12
  42. package/dist/cli/build/patches/to-investigate/patch-find-dir.d.ts +3 -6
  43. package/dist/cli/build/patches/to-investigate/patch-find-dir.js +11 -11
  44. package/dist/cli/build/patches/to-investigate/patch-read-file.d.ts +3 -3
  45. package/dist/cli/build/patches/to-investigate/patch-read-file.js +15 -16
  46. package/dist/cli/build/patches/to-investigate/wrangler-deps.d.ts +2 -2
  47. package/dist/cli/build/patches/to-investigate/wrangler-deps.js +36 -67
  48. package/dist/cli/build/utils/create-config-files.d.ts +1 -1
  49. package/dist/cli/project-options.d.ts +7 -0
  50. package/dist/cli/project-options.js +1 -0
  51. package/package.json +4 -4
  52. package/dist/api/get-cloudflare-context.js +0 -42
  53. package/dist/cli/config.d.ts +0 -42
  54. package/dist/cli/config.js +0 -92
@@ -0,0 +1,23 @@
1
+ import { SgNode } from "@ast-grep/napi";
2
+ export declare const vercelOgImportRule = "\nrule:\n pattern: $NODE\n kind: string\n regex: \"next/dist/compiled/@vercel/og/index\\\\.node\\\\.js\"\ninside:\n kind: arguments\n inside:\n kind: call_expression\n stopBy: end\n has:\n field: function\n regex: \"import\"\n\nfix: |-\n \"next/dist/compiled/@vercel/og/index.edge.js\"\n";
3
+ /**
4
+ * Patches Node.js imports for the library to be Edge imports.
5
+ *
6
+ * @param root Root node.
7
+ * @returns Results of applying the rule.
8
+ */
9
+ export declare function patchVercelOgImport(root: SgNode): {
10
+ edits: import("@ast-grep/napi").Edit[];
11
+ matches: SgNode<import("@ast-grep/napi/types/staticTypes.js").TypesMap, import("@ast-grep/napi/types/staticTypes.js").Kinds<import("@ast-grep/napi/types/staticTypes.js").TypesMap>>[];
12
+ };
13
+ export declare const vercelOgFallbackFontRule = "\nrule:\n kind: variable_declaration\n all:\n - has:\n kind: variable_declarator\n has:\n kind: identifier\n regex: ^fallbackFont$\n - has:\n kind: call_expression\n pattern: fetch(new URL(\"$PATH\", $$$REST))\n stopBy: end\n\nfix: |-\n async function getFallbackFont() {\n // .bin is used so that a loader does not need to be configured for .ttf files\n return (await import(\"$PATH.bin\")).default;\n }\n\n var fallbackFont = getFallbackFont();\n";
14
+ /**
15
+ * Patches the default font fetching to use a .bin import.
16
+ *
17
+ * @param root Root node.
18
+ * @returns Results of applying the rule.
19
+ */
20
+ export declare function patchVercelOgFallbackFont(root: SgNode): {
21
+ edits: import("@ast-grep/napi").Edit[];
22
+ matches: SgNode<import("@ast-grep/napi/types/staticTypes.js").TypesMap, import("@ast-grep/napi/types/staticTypes.js").Kinds<import("@ast-grep/napi/types/staticTypes.js").TypesMap>>[];
23
+ };
@@ -0,0 +1,58 @@
1
+ import { applyRule } from "./util.js";
2
+ export const vercelOgImportRule = `
3
+ rule:
4
+ pattern: $NODE
5
+ kind: string
6
+ regex: "next/dist/compiled/@vercel/og/index\\\\.node\\\\.js"
7
+ inside:
8
+ kind: arguments
9
+ inside:
10
+ kind: call_expression
11
+ stopBy: end
12
+ has:
13
+ field: function
14
+ regex: "import"
15
+
16
+ fix: |-
17
+ "next/dist/compiled/@vercel/og/index.edge.js"
18
+ `;
19
+ /**
20
+ * Patches Node.js imports for the library to be Edge imports.
21
+ *
22
+ * @param root Root node.
23
+ * @returns Results of applying the rule.
24
+ */
25
+ export function patchVercelOgImport(root) {
26
+ return applyRule(vercelOgImportRule, root);
27
+ }
28
+ export const vercelOgFallbackFontRule = `
29
+ rule:
30
+ kind: variable_declaration
31
+ all:
32
+ - has:
33
+ kind: variable_declarator
34
+ has:
35
+ kind: identifier
36
+ regex: ^fallbackFont$
37
+ - has:
38
+ kind: call_expression
39
+ pattern: fetch(new URL("$PATH", $$$REST))
40
+ stopBy: end
41
+
42
+ fix: |-
43
+ async function getFallbackFont() {
44
+ // .bin is used so that a loader does not need to be configured for .ttf files
45
+ return (await import("$PATH.bin")).default;
46
+ }
47
+
48
+ var fallbackFont = getFallbackFont();
49
+ `;
50
+ /**
51
+ * Patches the default font fetching to use a .bin import.
52
+ *
53
+ * @param root Root node.
54
+ * @returns Results of applying the rule.
55
+ */
56
+ export function patchVercelOgFallbackFont(root) {
57
+ return applyRule(vercelOgFallbackFontRule, root);
58
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { patchCode } from "./util";
3
+ import { vercelOgFallbackFontRule, vercelOgImportRule } from "./vercel-og";
4
+ describe("vercelOgImportRule", () => {
5
+ it("should rewrite a node import to an edge import", () => {
6
+ const code = `e.exports=import("next/dist/compiled/@vercel/og/index.node.js")`;
7
+ expect(patchCode(code, vercelOgImportRule)).toMatchInlineSnapshot(`"e.exports=import("next/dist/compiled/@vercel/og/index.edge.js")"`);
8
+ });
9
+ });
10
+ describe("vercelOgFallbackFontRule", () => {
11
+ it("should replace a fetch call for a font with an import", () => {
12
+ const code = `var fallbackFont = fetch(new URL("./noto-sans-v27-latin-regular.ttf", import.meta.url)).then((res) => res.arrayBuffer());`;
13
+ expect(patchCode(code, vercelOgFallbackFontRule)).toMatchInlineSnapshot(`
14
+ "async function getFallbackFont() {
15
+ // .bin is used so that a loader does not need to be configured for .ttf files
16
+ return (await import("./noto-sans-v27-latin-regular.ttf.bin")).default;
17
+ }
18
+
19
+ var fallbackFont = getFallbackFont();"
20
+ `);
21
+ });
22
+ });
@@ -1,6 +1,7 @@
1
1
  import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
2
- import { Config } from "../../../config.js";
3
2
  /**
4
- * Copies the template files present in the cloudflare adapter package into the standalone node_modules folder
3
+ * Copies
4
+ * - the template files present in the cloudflare adapter package to `.open-next/cloudflare-templates`
5
+ * - `worker.js` to `.open-next/`
5
6
  */
6
- export declare function copyPackageCliFiles(packageDistDir: string, config: Config, openNextOptions: BuildOptions): void;
7
+ export declare function copyPackageCliFiles(packageDistDir: string, buildOpts: BuildOptions): void;
@@ -2,12 +2,15 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { getOutputWorkerPath } from "../../bundle-server.js";
4
4
  /**
5
- * Copies the template files present in the cloudflare adapter package into the standalone node_modules folder
5
+ * Copies
6
+ * - the template files present in the cloudflare adapter package to `.open-next/cloudflare-templates`
7
+ * - `worker.js` to `.open-next/`
6
8
  */
7
- export function copyPackageCliFiles(packageDistDir, config, openNextOptions) {
9
+ export function copyPackageCliFiles(packageDistDir, buildOpts) {
8
10
  console.log("# copyPackageTemplateFiles");
9
- const sourceDir = path.join(packageDistDir, "cli");
10
- const destinationDir = path.join(config.paths.internal.package, "cli");
11
+ const sourceDir = path.join(packageDistDir, "cli/templates");
12
+ const destinationDir = path.join(buildOpts.outputDir, "cloudflare-templates");
13
+ fs.mkdirSync(destinationDir, { recursive: true });
11
14
  fs.cpSync(sourceDir, destinationDir, { recursive: true });
12
- fs.copyFileSync(path.join(packageDistDir, "cli", "templates", "worker.js"), getOutputWorkerPath(openNextOptions));
15
+ fs.copyFileSync(path.join(packageDistDir, "cli/templates/worker.js"), getOutputWorkerPath(buildOpts));
13
16
  }
@@ -1,4 +1,5 @@
1
1
  export * from "./copy-package-cli-files.js";
2
2
  export * from "./patch-cache.js";
3
3
  export * from "./patch-require.js";
4
+ export * from "./patch-vercel-og-library.js";
4
5
  export * from "./update-webpack-chunks-file/index.js";
@@ -1,4 +1,5 @@
1
1
  export * from "./copy-package-cli-files.js";
2
2
  export * from "./patch-cache.js";
3
3
  export * from "./patch-require.js";
4
+ export * from "./patch-vercel-og-library.js";
4
5
  export * from "./update-webpack-chunks-file/index.js";
@@ -1,4 +1,4 @@
1
- import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
2
  /**
3
3
  * Sets up the OpenNext cache handler in a Next.js build.
4
4
  *
@@ -10,4 +10,4 @@ import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
10
10
  * build-time. Therefore, we have to manually override the default way that the cache handler is
11
11
  * instantiated with a dynamic require that uses a string literal for the path.
12
12
  */
13
- export declare function patchCache(code: string, openNextOptions: BuildOptions): Promise<string>;
13
+ export declare function patchCache(code: string, buildOpts: BuildOptions): Promise<string>;
@@ -1,4 +1,5 @@
1
1
  import path from "node:path";
2
+ import { getPackagePath } from "@opennextjs/aws/build/helper.js";
2
3
  import { normalizePath } from "../../utils/index.js";
3
4
  /**
4
5
  * Sets up the OpenNext cache handler in a Next.js build.
@@ -11,13 +12,13 @@ import { normalizePath } from "../../utils/index.js";
11
12
  * build-time. Therefore, we have to manually override the default way that the cache handler is
12
13
  * instantiated with a dynamic require that uses a string literal for the path.
13
14
  */
14
- export async function patchCache(code, openNextOptions) {
15
- const { appBuildOutputPath, outputDir, monorepoRoot } = openNextOptions;
15
+ export async function patchCache(code, buildOpts) {
16
+ const { outputDir } = buildOpts;
16
17
  // TODO: switch to cache.mjs
17
- const outputPath = path.join(outputDir, "server-functions", "default");
18
- const packagePath = path.relative(monorepoRoot, appBuildOutputPath);
19
- const cacheFile = path.join(outputPath, packagePath, "cache.cjs");
20
- return code.replace("const { cacheHandler } = this.nextConfig;", `const cacheHandler = null;
18
+ const outputPath = path.join(outputDir, "server-functions/default");
19
+ const cacheFile = path.join(outputPath, getPackagePath(buildOpts), "cache.cjs");
20
+ return code.replace("const { cacheHandler } = this.nextConfig;", `
21
+ const cacheHandler = null;
21
22
  CacheHandler = require('${normalizePath(cacheFile)}').default;
22
23
  `);
23
24
  }
@@ -1,7 +1,4 @@
1
1
  /**
2
- * ESBuild does not support CJS format
3
- * See https://github.com/evanw/esbuild/issues/1921 and linked issues
4
- * Some of the solutions are based on `module.createRequire()` not implemented in workerd.
5
- * James on Aug 29: `module.createRequire()` is planned.
2
+ * Replaces webpack `__require` with actual `require`
6
3
  */
7
4
  export declare function patchRequire(code: string): string;
@@ -1,8 +1,5 @@
1
1
  /**
2
- * ESBuild does not support CJS format
3
- * See https://github.com/evanw/esbuild/issues/1921 and linked issues
4
- * Some of the solutions are based on `module.createRequire()` not implemented in workerd.
5
- * James on Aug 29: `module.createRequire()` is planned.
2
+ * Replaces webpack `__require` with actual `require`
6
3
  */
7
4
  export function patchRequire(code) {
8
5
  return code.replace(/__require\d?\(/g, "require(").replace(/__require\d?\./g, "require.");
@@ -0,0 +1,7 @@
1
+ import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
2
+ /**
3
+ * Patches the usage of @vercel/og to be compatible with Cloudflare Workers.
4
+ *
5
+ * @param buildOpts Build options.
6
+ */
7
+ export declare function patchVercelOgLibrary(buildOpts: BuildOptions): void;
@@ -0,0 +1,39 @@
1
+ import { copyFileSync, existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { getPackagePath } from "@opennextjs/aws/build/helper.js";
4
+ import { globSync } from "glob";
5
+ import { parseFile } from "../ast/util.js";
6
+ import { patchVercelOgFallbackFont, patchVercelOgImport } from "../ast/vercel-og.js";
7
+ /**
8
+ * Patches the usage of @vercel/og to be compatible with Cloudflare Workers.
9
+ *
10
+ * @param buildOpts Build options.
11
+ */
12
+ export function patchVercelOgLibrary(buildOpts) {
13
+ const { appBuildOutputPath, outputDir } = buildOpts;
14
+ const packagePath = path.join(outputDir, "server-functions/default", getPackagePath(buildOpts));
15
+ for (const traceInfoPath of globSync(path.join(appBuildOutputPath, ".next/server/**/*.nft.json"))) {
16
+ const traceInfo = JSON.parse(readFileSync(traceInfoPath, { encoding: "utf8" }));
17
+ const tracedNodePath = traceInfo.files.find((p) => p.endsWith("@vercel/og/index.node.js"));
18
+ if (!tracedNodePath)
19
+ continue;
20
+ const outputDir = path.join(packagePath, "node_modules/next/dist/compiled/@vercel/og");
21
+ const outputEdgePath = path.join(outputDir, "index.edge.js");
22
+ // Ensure the edge version is available in the OpenNext node_modules.
23
+ if (!existsSync(outputEdgePath)) {
24
+ const tracedEdgePath = path.join(path.dirname(traceInfoPath), tracedNodePath.replace("index.node.js", "index.edge.js"));
25
+ copyFileSync(tracedEdgePath, outputEdgePath);
26
+ // Change font fetches in the library to use imports.
27
+ const node = parseFile(outputEdgePath);
28
+ const { edits, matches } = patchVercelOgFallbackFont(node);
29
+ writeFileSync(outputEdgePath, node.commitEdits(edits));
30
+ const fontFileName = matches[0].getMatch("PATH").text();
31
+ renameSync(path.join(outputDir, fontFileName), path.join(outputDir, `${fontFileName}.bin`));
32
+ }
33
+ // Change node imports for the library to edge imports.
34
+ const routeFilePath = traceInfoPath.replace(appBuildOutputPath, packagePath).replace(".nft.json", "");
35
+ const node = parseFile(routeFilePath);
36
+ const { edits } = patchVercelOgImport(node);
37
+ writeFileSync(routeFilePath, node.commitEdits(edits));
38
+ }
39
+ }
@@ -0,0 +1,50 @@
1
+ import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import mockFs from "mock-fs";
4
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
5
+ import { patchVercelOgLibrary } from "./patch-vercel-og-library";
6
+ const nodeModulesVercelOgDir = "node_modules/.pnpm/next@14.2.11/node_modules/next/dist/compiled/@vercel/og";
7
+ const nextServerOgNftPath = "examples/api/.next/server/app/og/route.js.nft.json";
8
+ const openNextFunctionDir = "examples/api/.open-next/server-functions/default/examples/api";
9
+ const openNextOgRoutePath = path.join(openNextFunctionDir, ".next/server/app/og/route.js");
10
+ const openNextVercelOgDir = path.join(openNextFunctionDir, "node_modules/next/dist/compiled/@vercel/og");
11
+ const buildOpts = {
12
+ appBuildOutputPath: "examples/api",
13
+ monorepoRoot: "",
14
+ outputDir: "examples/api/.open-next",
15
+ };
16
+ describe("patchVercelOgLibrary", () => {
17
+ beforeAll(() => {
18
+ mockFs();
19
+ mkdirSync(nodeModulesVercelOgDir, { recursive: true });
20
+ mkdirSync(path.dirname(nextServerOgNftPath), { recursive: true });
21
+ mkdirSync(path.dirname(openNextOgRoutePath), { recursive: true });
22
+ mkdirSync(openNextVercelOgDir, { recursive: true });
23
+ writeFileSync(nextServerOgNftPath, JSON.stringify({ version: 1, files: [`../../../../../../${nodeModulesVercelOgDir}/index.node.js`] }));
24
+ writeFileSync(path.join(nodeModulesVercelOgDir, "index.edge.js"), `var fallbackFont = fetch(new URL("./noto-sans-v27-latin-regular.ttf", import.meta.url)).then((res) => res.arrayBuffer());`);
25
+ writeFileSync(openNextOgRoutePath, `e.exports=import("next/dist/compiled/@vercel/og/index.node.js")`);
26
+ writeFileSync(path.join(openNextVercelOgDir, "index.node.js"), "");
27
+ writeFileSync(path.join(openNextVercelOgDir, "noto-sans-v27-latin-regular.ttf"), "");
28
+ });
29
+ afterAll(() => mockFs.restore());
30
+ it("should patch the open-next files correctly", () => {
31
+ patchVercelOgLibrary(buildOpts);
32
+ expect(readdirSync(openNextVercelOgDir)).toMatchInlineSnapshot(`
33
+ [
34
+ "index.edge.js",
35
+ "index.node.js",
36
+ "noto-sans-v27-latin-regular.ttf.bin",
37
+ ]
38
+ `);
39
+ expect(readFileSync(path.join(openNextVercelOgDir, "index.edge.js"), { encoding: "utf-8" }))
40
+ .toMatchInlineSnapshot(`
41
+ "async function getFallbackFont() {
42
+ // .bin is used so that a loader does not need to be configured for .ttf files
43
+ return (await import("./noto-sans-v27-latin-regular.ttf.bin")).default;
44
+ }
45
+
46
+ var fallbackFont = getFallbackFont();"
47
+ `);
48
+ expect(readFileSync(openNextOgRoutePath, { encoding: "utf-8" })).toMatchInlineSnapshot(`"e.exports=import("next/dist/compiled/@vercel/og/index.edge.js")"`);
49
+ });
50
+ });
@@ -1,8 +1,5 @@
1
- import { Config } from "../../../../config.js";
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
2
  /**
3
3
  * Fixes the webpack-runtime.js file by removing its webpack dynamic requires.
4
- *
5
- * This hack is particularly bad as it indicates that files inside the output directory still get a hold of files from the outside: `${nextjsAppPaths.standaloneAppServerDir}/webpack-runtime.js`
6
- * so this shows that not everything that's needed to deploy the application is in the output directory...
7
4
  */
8
- export declare function updateWebpackChunksFile(config: Config): Promise<void>;
5
+ export declare function updateWebpackChunksFile(buildOpts: BuildOptions): Promise<void>;
@@ -1,17 +1,17 @@
1
1
  import { readdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { getPackagePath } from "@opennextjs/aws/build/helper.js";
3
4
  import { getUpdatedWebpackChunksFileContent } from "./get-updated-webpack-chunks-file-content.js";
4
5
  /**
5
6
  * Fixes the webpack-runtime.js file by removing its webpack dynamic requires.
6
- *
7
- * This hack is particularly bad as it indicates that files inside the output directory still get a hold of files from the outside: `${nextjsAppPaths.standaloneAppServerDir}/webpack-runtime.js`
8
- * so this shows that not everything that's needed to deploy the application is in the output directory...
9
7
  */
10
- export async function updateWebpackChunksFile(config) {
8
+ export async function updateWebpackChunksFile(buildOpts) {
11
9
  console.log("# updateWebpackChunksFile");
12
- const webpackRuntimeFile = join(config.paths.output.standaloneAppServer, "webpack-runtime.js");
10
+ const { outputDir } = buildOpts;
11
+ const dotNextServerDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next/server");
12
+ const webpackRuntimeFile = join(dotNextServerDir, "webpack-runtime.js");
13
13
  const fileContent = readFileSync(webpackRuntimeFile, "utf-8");
14
- const chunks = readdirSync(join(config.paths.output.standaloneAppServer, "chunks"))
14
+ const chunks = readdirSync(join(dotNextServerDir, "chunks"))
15
15
  .filter((chunk) => /^\d+\.js$/.test(chunk))
16
16
  .map((chunk) => {
17
17
  console.log(` - chunk ${chunk}`);
@@ -1,4 +1,4 @@
1
- import { Config } from "../../../config.js";
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
2
  /**
3
3
  * `evalManifest` relies on readFileSync so we need to patch the function so that it instead returns the content of the manifest files
4
4
  * which are known at build time
@@ -6,4 +6,4 @@ import { Config } from "../../../config.js";
6
6
  * Note: we could/should probably just patch readFileSync here or something, but here the issue is that after the readFileSync call
7
7
  * there is a vm `runInNewContext` call which we also don't support (source: https://github.com/vercel/next.js/blob/b1e32c5d1f/packages/next/src/server/load-manifest.ts#L88)
8
8
  */
9
- export declare function inlineEvalManifest(code: string, config: Config): string;
9
+ export declare function inlineEvalManifest(code: string, buildOpts: BuildOptions): string;
@@ -1,4 +1,5 @@
1
- import { join, posix } from "node:path";
1
+ import { join, relative } from "node:path";
2
+ import { getPackagePath } from "@opennextjs/aws/build/helper.js";
2
3
  import { globSync } from "glob";
3
4
  import { normalizePath } from "../../utils/index.js";
4
5
  /**
@@ -8,24 +9,27 @@ import { normalizePath } from "../../utils/index.js";
8
9
  * Note: we could/should probably just patch readFileSync here or something, but here the issue is that after the readFileSync call
9
10
  * there is a vm `runInNewContext` call which we also don't support (source: https://github.com/vercel/next.js/blob/b1e32c5d1f/packages/next/src/server/load-manifest.ts#L88)
10
11
  */
11
- export function inlineEvalManifest(code, config) {
12
- const manifestJss = globSync(normalizePath(join(config.paths.output.standaloneAppDotNext, "**/*_client-reference-manifest.js"))).map((file) => normalizePath(file).replace(normalizePath(config.paths.output.standaloneApp) + posix.sep, ""));
12
+ export function inlineEvalManifest(code, buildOpts) {
13
+ const { outputDir } = buildOpts;
14
+ const baseDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next");
15
+ const appDir = join(baseDir, "server/app");
16
+ const manifests = globSync(join(baseDir, "**/*_client-reference-manifest.js"));
13
17
  return code.replace(/function evalManifest\((.+?), .+?\) {/, `$&
14
- ${manifestJss
15
- .map((manifestJs) => `
16
- if ($1.endsWith("${manifestJs}")) {
17
- require(${JSON.stringify(join(config.paths.output.standaloneApp, manifestJs))});
18
- return {
19
- __RSC_MANIFEST: {
20
- "${manifestJs
21
- .replace(".next/server/app", "")
22
- .replace("_client-reference-manifest.js", "")}": globalThis.__RSC_MANIFEST["${manifestJs
23
- .replace(".next/server/app", "")
24
- .replace("_client-reference-manifest.js", "")}"],
25
- },
26
- };
18
+ ${manifests
19
+ .map((manifest) => {
20
+ const endsWith = normalizePath(relative(baseDir, manifest));
21
+ const key = normalizePath("/" + relative(appDir, manifest)).replace("_client-reference-manifest.js", "");
22
+ return `
23
+ if ($1.endsWith("${endsWith}")) {
24
+ require(${JSON.stringify(manifest)});
25
+ return {
26
+ __RSC_MANIFEST: {
27
+ "${key}": globalThis.__RSC_MANIFEST["${key}"],
28
+ },
29
+ };
27
30
  }
28
- `)
31
+ `;
32
+ })
29
33
  .join("\n")}
30
34
  throw new Error("Unknown evalManifest: " + $1);
31
35
  `);
@@ -1,6 +1,6 @@
1
- import { Config } from "../../../config.js";
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
2
  /**
3
3
  * Inlines the middleware manifest from the build output to prevent a dynamic require statement
4
4
  * as they result in runtime failures.
5
5
  */
6
- export declare function inlineMiddlewareManifestRequire(code: string, config: Config): string;
6
+ export declare function inlineMiddlewareManifestRequire(code: string, buildOpts: BuildOptions): string;
@@ -1,11 +1,13 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { getPackagePath } from "@opennextjs/aws/build/helper.js";
3
4
  /**
4
5
  * Inlines the middleware manifest from the build output to prevent a dynamic require statement
5
6
  * as they result in runtime failures.
6
7
  */
7
- export function inlineMiddlewareManifestRequire(code, config) {
8
- const middlewareManifestPath = join(config.paths.output.standaloneAppServer, "middleware-manifest.json");
8
+ export function inlineMiddlewareManifestRequire(code, buildOpts) {
9
+ const { outputDir } = buildOpts;
10
+ const middlewareManifestPath = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next/server/middleware-manifest.json");
9
11
  const middlewareManifest = existsSync(middlewareManifestPath)
10
12
  ? JSON.parse(readFileSync(middlewareManifestPath, "utf-8"))
11
13
  : {};
@@ -1,6 +1,6 @@
1
- import { Config } from "../../../config.js";
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
2
  /**
3
3
  * The following avoid various Next.js specific files `require`d at runtime since we can just read
4
4
  * and inline their content during build time
5
5
  */
6
- export declare function inlineNextRequire(code: string, config: Config): string;
6
+ export declare function inlineNextRequire(code: string, buildOpts: BuildOptions): string;
@@ -1,33 +1,37 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { getPackagePath } from "@opennextjs/aws/build/helper.js";
3
4
  /**
4
5
  * The following avoid various Next.js specific files `require`d at runtime since we can just read
5
6
  * and inline their content during build time
6
7
  */
7
- export function inlineNextRequire(code, config) {
8
- const pagesManifestFile = join(config.paths.output.standaloneAppServer, "pages-manifest.json");
9
- const appPathsManifestFile = join(config.paths.output.standaloneAppServer, "app-paths-manifest.json");
10
- const pagesManifestFiles = existsSync(pagesManifestFile)
11
- ? Object.values(JSON.parse(readFileSync(pagesManifestFile, "utf-8"))).map((file) => ".next/server/" + file)
8
+ // TODO(vicb): __NEXT_PRIVATE_RUNTIME_TYPE is not handled by this patch
9
+ export function inlineNextRequire(code, buildOpts) {
10
+ const { outputDir } = buildOpts;
11
+ const serverDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next/server");
12
+ const pagesManifestFile = join(serverDir, "pages-manifest.json");
13
+ const appPathsManifestFile = join(serverDir, "app-paths-manifest.json");
14
+ const pagesManifests = existsSync(pagesManifestFile)
15
+ ? Object.values(JSON.parse(readFileSync(pagesManifestFile, "utf-8")))
12
16
  : [];
13
- const appPathsManifestFiles = existsSync(appPathsManifestFile)
14
- ? Object.values(JSON.parse(readFileSync(appPathsManifestFile, "utf-8"))).map((file) => ".next/server/" + file)
17
+ const appPathsManifests = existsSync(appPathsManifestFile)
18
+ ? Object.values(JSON.parse(readFileSync(appPathsManifestFile, "utf-8")))
15
19
  : [];
16
- const allManifestFiles = pagesManifestFiles.concat(appPathsManifestFiles);
17
- const htmlPages = allManifestFiles.filter((file) => file.endsWith(".html"));
18
- const pageModules = allManifestFiles.filter((file) => file.endsWith(".js"));
20
+ const manifests = pagesManifests.concat(appPathsManifests);
21
+ const htmlPages = manifests.filter((file) => file.endsWith(".html"));
22
+ const pageModules = manifests.filter((file) => file.endsWith(".js"));
19
23
  return code.replace(/const pagePath = getPagePath\(.+?\);/, `$&
20
24
  ${htmlPages
21
25
  .map((htmlPage) => `
22
26
  if (pagePath.endsWith("${htmlPage}")) {
23
- return ${JSON.stringify(readFileSync(join(config.paths.output.standaloneApp, htmlPage), "utf-8"))};
27
+ return ${JSON.stringify(readFileSync(join(serverDir, htmlPage), "utf-8"))};
24
28
  }
25
29
  `)
26
30
  .join("\n")}
27
31
  ${pageModules
28
32
  .map((module) => `
29
33
  if (pagePath.endsWith("${module}")) {
30
- return require(${JSON.stringify(join(config.paths.output.standaloneApp, module))});
34
+ return require(${JSON.stringify(join(serverDir, module))});
31
35
  }
32
36
  `)
33
37
  .join("\n")}
@@ -1,8 +1,5 @@
1
- import { Config } from "../../../config.js";
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
2
  /**
3
- * Here we patch `findDir` so that the next server can detect whether the `app` or `pages` directory exists
4
- * (source: https://github.com/vercel/next.js/blob/ba995993/packages/next/src/lib/find-pages-dir.ts#L4-L13)
5
- * (usage source: https://github.com/vercel/next.js/blob/ba995993/packages/next/src/server/next-server.ts#L450-L451)
6
- * Note: `findDir` uses `fs.existsSync` under the hood, so patching that should be enough to make this work
3
+ * Patches `findDir` so that the next server can detect whether the `app` or `pages` directory exists
7
4
  */
8
- export declare function patchFindDir(code: string, config: Config): string;
5
+ export declare function patchFindDir(code: string, buildOpts: BuildOptions): string;
@@ -1,20 +1,20 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { getPackagePath } from "@opennextjs/aws/build/helper.js";
3
4
  /**
4
- * Here we patch `findDir` so that the next server can detect whether the `app` or `pages` directory exists
5
- * (source: https://github.com/vercel/next.js/blob/ba995993/packages/next/src/lib/find-pages-dir.ts#L4-L13)
6
- * (usage source: https://github.com/vercel/next.js/blob/ba995993/packages/next/src/server/next-server.ts#L450-L451)
7
- * Note: `findDir` uses `fs.existsSync` under the hood, so patching that should be enough to make this work
5
+ * Patches `findDir` so that the next server can detect whether the `app` or `pages` directory exists
8
6
  */
9
- export function patchFindDir(code, config) {
7
+ export function patchFindDir(code, buildOpts) {
8
+ const { outputDir } = buildOpts;
9
+ const baseDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next/server");
10
10
  return code.replace(/function findDir\((?<dir>dir\d*), (?<name>name\d*)\) {/, `function findDir($dir, $name) {
11
11
  if ($dir.endsWith(".next/server")) {
12
- if ($name === "app") {
13
- return ${existsSync(`${join(config.paths.output.standaloneAppServer, "app")}`)};
14
- }
15
- if ($name === "pages") {
16
- return ${existsSync(`${join(config.paths.output.standaloneAppServer, "pages")}`)};
17
- }
12
+ if ($name === "app") {
13
+ return ${existsSync(`${join(baseDir, "app")}`)};
14
+ }
15
+ if ($name === "pages") {
16
+ return ${existsSync(`${join(baseDir, "pages")}`)};
17
+ }
18
18
  }
19
19
  throw new Error("Unknown findDir call: " + $dir + " " + $name);
20
20
  `);
@@ -1,3 +1,3 @@
1
- import { Config } from "../../../config.js";
2
- export declare function patchBuildId(code: string, config: Config): string;
3
- export declare function patchLoadManifest(code: string, config: Config): string;
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
+ export declare function patchBuildId(code: string, buildOpts: BuildOptions): string;
3
+ export declare function patchLoadManifest(code: string, buildOpts: BuildOptions): string;
@@ -1,26 +1,25 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { join, posix } from "node:path";
2
+ import { join, relative } from "node:path";
3
+ import { getBuildId, getPackagePath } from "@opennextjs/aws/build/helper.js";
3
4
  import { globSync } from "glob";
4
5
  import { normalizePath } from "../../utils/index.js";
5
- export function patchBuildId(code, config) {
6
- // The next-server code gets the buildId from the filesystem, resulting in a `[unenv] fs.readFileSync is not implemented yet!` error
7
- // so we add an early return to the `getBuildId` function so that the `readyFileSync` is never encountered
8
- // (source: https://github.com/vercel/next.js/blob/15aeb92efb34c09a36/packages/next/src/server/next-server.ts#L438-L451)
9
- // Note: we could/should probably just patch readFileSync here or something!
6
+ export function patchBuildId(code, buildOpts) {
7
+ // The Next code gets the buildId from the filesystem so we hardcode the value at build time.
10
8
  return code.replace("getBuildId() {", `getBuildId() {
11
- return ${JSON.stringify(readFileSync(join(config.paths.output.standaloneAppDotNext, "BUILD_ID"), "utf-8"))};
9
+ return ${JSON.stringify(getBuildId(buildOpts))};
12
10
  `);
13
11
  }
14
- export function patchLoadManifest(code, config) {
15
- // Same as patchBuildId, the next-server code loads the manifests with `readFileSync` and we want to avoid that
16
- // (source: https://github.com/vercel/next.js/blob/15aeb92e/packages/next/src/server/load-manifest.ts#L34-L56)
17
- // Note: we could/should probably just patch readFileSync here or something!
18
- const manifestJsons = globSync(normalizePath(join(config.paths.output.standaloneAppDotNext, "**/*-manifest.json"))).map((file) => normalizePath(file).replace(normalizePath(config.paths.output.standaloneApp) + posix.sep, ""));
12
+ export function patchLoadManifest(code, buildOpts) {
13
+ // Inline manifest that Next would otherwise retrieve from the file system.
14
+ const { outputDir } = buildOpts;
15
+ const baseDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts));
16
+ const dotNextDir = join(baseDir, ".next");
17
+ const manifests = globSync(join(dotNextDir, "**/*-manifest.json"));
19
18
  return code.replace(/function loadManifest\((.+?), .+?\) {/, `$&
20
- ${manifestJsons
21
- .map((manifestJson) => `
22
- if ($1.endsWith("${manifestJson}")) {
23
- return ${readFileSync(join(config.paths.output.standaloneApp, manifestJson), "utf-8")};
19
+ ${manifests
20
+ .map((manifest) => `
21
+ if ($1.endsWith("${normalizePath("/" + relative(dotNextDir, manifest))}")) {
22
+ return ${readFileSync(manifest, "utf-8")};
24
23
  }
25
24
  `)
26
25
  .join("\n")}
@@ -1,2 +1,2 @@
1
- import { Config } from "../../../config.js";
2
- export declare function patchWranglerDeps(config: Config): void;
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
+ export declare function patchWranglerDeps(buildOpts: BuildOptions): void;