@opennextjs/cloudflare 0.5.12 → 0.6.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 (110) hide show
  1. package/README.md +8 -8
  2. package/dist/api/cloudflare-context.d.ts +16 -5
  3. package/dist/api/config.d.ts +16 -43
  4. package/dist/api/config.js +21 -19
  5. package/dist/api/durable-objects/queue.d.ts +32 -0
  6. package/dist/api/durable-objects/queue.js +234 -0
  7. package/dist/api/durable-objects/queue.spec.js +290 -0
  8. package/dist/api/durable-objects/sharded-tag-cache.d.ts +7 -0
  9. package/dist/api/durable-objects/sharded-tag-cache.js +22 -0
  10. package/dist/api/durable-objects/sharded-tag-cache.spec.js +37 -0
  11. package/dist/api/overrides/incremental-cache/internal.d.ts +5 -0
  12. package/dist/api/{kv-cache.d.ts → overrides/incremental-cache/kv-incremental-cache.d.ts} +1 -1
  13. package/dist/api/{kv-cache.js → overrides/incremental-cache/kv-incremental-cache.js} +5 -5
  14. package/dist/api/overrides/incremental-cache/r2-incremental-cache.d.ts +17 -0
  15. package/dist/api/overrides/incremental-cache/r2-incremental-cache.js +61 -0
  16. package/dist/api/overrides/incremental-cache/regional-cache.d.ts +51 -0
  17. package/dist/api/overrides/incremental-cache/regional-cache.js +111 -0
  18. package/dist/api/overrides/queue/do-queue.d.ts +6 -0
  19. package/dist/api/overrides/queue/do-queue.js +15 -0
  20. package/dist/api/{memory-queue.d.ts → overrides/queue/memory-queue.d.ts} +3 -3
  21. package/dist/api/{memory-queue.js → overrides/queue/memory-queue.js} +18 -14
  22. package/dist/api/overrides/queue/memory-queue.spec.d.ts +1 -0
  23. package/dist/api/{memory-queue.spec.js → overrides/queue/memory-queue.spec.js} +20 -14
  24. package/dist/api/overrides/tag-cache/d1-next-tag-cache.d.ts +13 -0
  25. package/dist/api/overrides/tag-cache/d1-next-tag-cache.js +61 -0
  26. package/dist/api/{d1-tag-cache.d.ts → overrides/tag-cache/d1-tag-cache.d.ts} +3 -5
  27. package/dist/api/{d1-tag-cache.js → overrides/tag-cache/d1-tag-cache.js} +22 -29
  28. package/dist/api/overrides/tag-cache/do-sharded-tag-cache.d.ts +122 -0
  29. package/dist/api/overrides/tag-cache/do-sharded-tag-cache.js +247 -0
  30. package/dist/api/overrides/tag-cache/do-sharded-tag-cache.spec.d.ts +1 -0
  31. package/dist/api/overrides/tag-cache/do-sharded-tag-cache.spec.js +322 -0
  32. package/dist/cli/args.d.ts +13 -2
  33. package/dist/cli/args.js +44 -29
  34. package/dist/cli/build/build.d.ts +5 -1
  35. package/dist/cli/build/build.js +9 -19
  36. package/dist/cli/build/bundle-server.js +5 -13
  37. package/dist/cli/build/open-next/compile-cache-assets-manifest.d.ts +1 -1
  38. package/dist/cli/build/open-next/compile-cache-assets-manifest.js +4 -6
  39. package/dist/cli/build/open-next/compileDurableObjects.d.ts +2 -0
  40. package/dist/cli/build/open-next/compileDurableObjects.js +30 -0
  41. package/dist/cli/build/open-next/copyCacheAssets.js +1 -1
  42. package/dist/cli/build/open-next/createServerBundle.d.ts +9 -1
  43. package/dist/cli/build/open-next/createServerBundle.js +28 -9
  44. package/dist/cli/build/patches/ast/patch-vercel-og-library.js +1 -1
  45. package/dist/cli/build/patches/ast/vercel-og.d.ts +5 -5
  46. package/dist/cli/build/patches/ast/vercel-og.js +1 -1
  47. package/dist/cli/build/patches/ast/vercel-og.spec.js +1 -1
  48. package/dist/cli/build/patches/ast/webpack-runtime.js +1 -1
  49. package/dist/cli/build/patches/ast/webpack-runtime.spec.js +1 -1
  50. package/dist/cli/build/patches/plugins/build-id.d.ts +2 -2
  51. package/dist/cli/build/patches/plugins/build-id.js +12 -5
  52. package/dist/cli/build/patches/plugins/build-id.spec.js +1 -1
  53. package/dist/cli/build/patches/plugins/dynamic-requires.d.ts +1 -2
  54. package/dist/cli/build/patches/plugins/dynamic-requires.js +21 -11
  55. package/dist/cli/build/patches/plugins/eval-manifest.d.ts +2 -2
  56. package/dist/cli/build/patches/plugins/eval-manifest.js +12 -5
  57. package/dist/cli/build/patches/plugins/find-dir.d.ts +2 -2
  58. package/dist/cli/build/patches/plugins/find-dir.js +10 -5
  59. package/dist/cli/build/patches/plugins/instrumentation.d.ts +2 -5
  60. package/dist/cli/build/patches/plugins/instrumentation.js +19 -3
  61. package/dist/cli/build/patches/plugins/instrumentation.spec.js +1 -1
  62. package/dist/cli/build/patches/plugins/load-manifest.d.ts +2 -2
  63. package/dist/cli/build/patches/plugins/load-manifest.js +12 -5
  64. package/dist/cli/build/patches/plugins/next-minimal.d.ts +4 -7
  65. package/dist/cli/build/patches/plugins/next-minimal.js +31 -15
  66. package/dist/cli/build/patches/plugins/next-minimal.spec.js +1 -1
  67. package/dist/cli/build/patches/plugins/patch-depd-deprecations.d.ts +2 -2
  68. package/dist/cli/build/patches/plugins/patch-depd-deprecations.js +10 -2
  69. package/dist/cli/build/patches/plugins/patch-depd-deprecations.spec.js +1 -1
  70. package/dist/cli/build/patches/plugins/require.d.ts +2 -2
  71. package/dist/cli/build/patches/plugins/require.js +43 -35
  72. package/dist/cli/build/patches/plugins/res-revalidate.d.ts +3 -0
  73. package/dist/cli/build/patches/plugins/res-revalidate.js +77 -0
  74. package/dist/cli/build/patches/plugins/res-revalidate.spec.d.ts +1 -0
  75. package/dist/cli/build/patches/plugins/res-revalidate.spec.js +141 -0
  76. package/dist/cli/build/utils/create-config-files.d.ts +2 -2
  77. package/dist/cli/build/utils/create-config-files.js +3 -3
  78. package/dist/cli/build/utils/ensure-cf-config.js +3 -13
  79. package/dist/cli/commands/deploy.d.ts +5 -0
  80. package/dist/cli/commands/deploy.js +9 -0
  81. package/dist/cli/commands/populate-cache.d.ts +7 -0
  82. package/dist/cli/commands/populate-cache.js +78 -0
  83. package/dist/cli/commands/preview.d.ts +5 -0
  84. package/dist/cli/commands/preview.js +9 -0
  85. package/dist/cli/index.js +36 -9
  86. package/dist/cli/project-options.d.ts +5 -1
  87. package/dist/cli/templates/worker.d.ts +3 -4
  88. package/dist/cli/templates/worker.js +30 -18
  89. package/dist/cli/utils/run-wrangler.d.ts +18 -0
  90. package/dist/cli/utils/run-wrangler.js +41 -0
  91. package/package.json +7 -9
  92. package/templates/open-next.config.ts +1 -1
  93. package/templates/wrangler.jsonc +2 -2
  94. package/dist/api/kvCache.d.ts +0 -5
  95. package/dist/api/kvCache.js +0 -5
  96. package/dist/cli/build/patches/ast/util.d.ts +0 -50
  97. package/dist/cli/build/patches/ast/util.js +0 -65
  98. package/dist/cli/build/patches/ast/util.spec.js +0 -43
  99. package/dist/cli/build/patches/plugins/content-updater.d.ts +0 -44
  100. package/dist/cli/build/patches/plugins/content-updater.js +0 -55
  101. package/dist/cli/build/patches/plugins/fetch-cache-wait-until.d.ts +0 -14
  102. package/dist/cli/build/patches/plugins/fetch-cache-wait-until.js +0 -40
  103. package/dist/cli/build/patches/plugins/fetch-cache-wait-until.spec.js +0 -453
  104. package/dist/cli/templates/shims/node-fs.d.ts +0 -17
  105. package/dist/cli/templates/shims/node-fs.js +0 -51
  106. package/dist/cli/templates/shims/throw.d.ts +0 -0
  107. package/dist/cli/templates/shims/throw.js +0 -2
  108. /package/dist/api/{memory-queue.spec.d.ts → durable-objects/queue.spec.d.ts} +0 -0
  109. /package/dist/{cli/build/patches/ast/util.spec.d.ts → api/durable-objects/sharded-tag-cache.spec.d.ts} +0 -0
  110. /package/dist/{cli/build/patches/plugins/fetch-cache-wait-until.spec.d.ts → api/overrides/incremental-cache/internal.js} +0 -0
@@ -1,9 +1,13 @@
1
+ import { BuildOptions } from "@opennextjs/aws/build/helper.js";
2
+ import { OpenNextConfig } from "@opennextjs/aws/types/open-next.js";
1
3
  import type { ProjectOptions } from "../project-options.js";
2
4
  /**
3
5
  * Builds the application in a format that can be passed to workerd
4
6
  *
5
7
  * It saves the output in a `.worker-next` directory
6
8
  *
9
+ * @param options The OpenNext options
10
+ * @param config The OpenNext config
7
11
  * @param projectOpts The options for the project
8
12
  */
9
- export declare function build(projectOpts: ProjectOptions): Promise<void>;
13
+ export declare function build(options: BuildOptions, config: OpenNextConfig, projectOpts: ProjectOptions): Promise<void>;
@@ -1,39 +1,28 @@
1
- import { createRequire } from "node:module";
2
- import { dirname } from "node:path";
3
1
  import { buildNextjsApp, setStandaloneBuildMode } from "@opennextjs/aws/build/buildNextApp.js";
4
2
  import { compileCache } from "@opennextjs/aws/build/compileCache.js";
5
- import { compileOpenNextConfig } from "@opennextjs/aws/build/compileConfig.js";
6
3
  import { createCacheAssets, createStaticAssets } from "@opennextjs/aws/build/createAssets.js";
7
4
  import { createMiddleware } from "@opennextjs/aws/build/createMiddleware.js";
8
5
  import * as buildHelper from "@opennextjs/aws/build/helper.js";
9
- import { printHeader, showWarningOnWindows } from "@opennextjs/aws/build/utils.js";
6
+ import { printHeader } from "@opennextjs/aws/build/utils.js";
10
7
  import logger from "@opennextjs/aws/logger.js";
11
8
  import { bundleServer } from "./bundle-server.js";
12
9
  import { compileCacheAssetsManifestSqlFile } from "./open-next/compile-cache-assets-manifest.js";
13
10
  import { compileEnvFiles } from "./open-next/compile-env-files.js";
11
+ import { compileDurableObjects } from "./open-next/compileDurableObjects.js";
14
12
  import { copyCacheAssets } from "./open-next/copyCacheAssets.js";
15
13
  import { createServerBundle } from "./open-next/createServerBundle.js";
16
- import { createOpenNextConfigIfNotExistent, createWranglerConfigIfNotExistent, ensureCloudflareConfig, } from "./utils/index.js";
14
+ import { createWranglerConfigIfNotExistent } from "./utils/index.js";
17
15
  import { getVersion } from "./utils/version.js";
18
16
  /**
19
17
  * Builds the application in a format that can be passed to workerd
20
18
  *
21
19
  * It saves the output in a `.worker-next` directory
22
20
  *
21
+ * @param options The OpenNext options
22
+ * @param config The OpenNext config
23
23
  * @param projectOpts The options for the project
24
24
  */
25
- export async function build(projectOpts) {
26
- printHeader("Cloudflare build");
27
- showWarningOnWindows();
28
- const baseDir = projectOpts.sourceDir;
29
- const require = createRequire(import.meta.url);
30
- const openNextDistDir = dirname(require.resolve("@opennextjs/aws/index.js"));
31
- await createOpenNextConfigIfNotExistent(projectOpts);
32
- const { config, buildDir } = await compileOpenNextConfig(baseDir);
33
- ensureCloudflareConfig(config);
34
- // Initialize options
35
- const options = buildHelper.normalizeOptions(config, openNextDistDir, buildDir);
36
- logger.setLevel(options.debug ? "debug" : "info");
25
+ export async function build(options, config, projectOpts) {
37
26
  // Do not minify the code so that we can apply string replacement patch.
38
27
  // Note that wrangler will still minify the bundle.
39
28
  options.minify = false;
@@ -72,6 +61,7 @@ export async function build(projectOpts) {
72
61
  }
73
62
  }
74
63
  await createServerBundle(options);
64
+ await compileDurableObjects(options);
75
65
  await bundleServer(options);
76
66
  if (!projectOpts.skipWranglerConfigCheck) {
77
67
  await createWranglerConfigIfNotExistent(projectOpts);
@@ -79,8 +69,8 @@ export async function build(projectOpts) {
79
69
  logger.info("OpenNext build complete.");
80
70
  }
81
71
  function ensureNextjsVersionSupported(options) {
82
- if (buildHelper.compareSemver(options.nextVersion, "14.0.0") < 0) {
83
- logger.error("Next.js version unsupported, please upgrade to version 14 or greater.");
72
+ if (buildHelper.compareSemver(options.nextVersion, "<", "14.2.0")) {
73
+ logger.error("Next.js version unsupported, please upgrade to version 14.2 or greater.");
84
74
  process.exit(1);
85
75
  }
86
76
  }
@@ -3,15 +3,14 @@ import { readFile, writeFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { getPackagePath } from "@opennextjs/aws/build/helper.js";
6
+ import { ContentUpdater } from "@opennextjs/aws/plugins/content-updater.js";
6
7
  import { build } from "esbuild";
7
8
  import { patchVercelOgLibrary } from "./patches/ast/patch-vercel-og-library.js";
8
9
  import { patchWebpackRuntime } from "./patches/ast/webpack-runtime.js";
9
10
  import * as patches from "./patches/index.js";
10
11
  import { inlineBuildId } from "./patches/plugins/build-id.js";
11
- import { ContentUpdater } from "./patches/plugins/content-updater.js";
12
12
  import { inlineDynamicRequires } from "./patches/plugins/dynamic-requires.js";
13
13
  import { inlineEvalManifest } from "./patches/plugins/eval-manifest.js";
14
- import { patchFetchCacheSetMissingWaitUntil } from "./patches/plugins/fetch-cache-wait-until.js";
15
14
  import { inlineFindDir } from "./patches/plugins/find-dir.js";
16
15
  import { patchInstrumentation } from "./patches/plugins/instrumentation.js";
17
16
  import { inlineLoadManifest } from "./patches/plugins/load-manifest.js";
@@ -43,7 +42,8 @@ const optionalDependencies = [
43
42
  export async function bundleServer(buildOpts) {
44
43
  patches.copyPackageCliFiles(packageDistDir, buildOpts);
45
44
  const { appPath, outputDir, monorepoRoot } = buildOpts;
46
- const serverFiles = path.join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next/required-server-files.json");
45
+ const baseManifestPath = path.join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next");
46
+ const serverFiles = path.join(baseManifestPath, "required-server-files.json");
47
47
  const nextConfig = JSON.parse(fs.readFileSync(serverFiles, "utf-8")).config;
48
48
  console.log(`\x1b[35m⚙️ Bundling the OpenNext server...\n\x1b[0m`);
49
49
  await patchWebpackRuntime(buildOpts);
@@ -52,7 +52,7 @@ export async function bundleServer(buildOpts) {
52
52
  const packagePath = getPackagePath(buildOpts);
53
53
  const openNextServer = path.join(outputPath, packagePath, `index.mjs`);
54
54
  const openNextServerBundle = path.join(outputPath, packagePath, `handler.mjs`);
55
- const updater = new ContentUpdater();
55
+ const updater = new ContentUpdater(buildOpts);
56
56
  const result = await build({
57
57
  entryPoints: [openNextServer],
58
58
  bundle: true,
@@ -78,14 +78,13 @@ export async function bundleServer(buildOpts) {
78
78
  fixRequire(updater),
79
79
  handleOptionalDependencies(optionalDependencies),
80
80
  patchInstrumentation(updater, buildOpts),
81
- patchFetchCacheSetMissingWaitUntil(updater),
82
81
  inlineEvalManifest(updater, buildOpts),
83
82
  inlineFindDir(updater, buildOpts),
84
83
  inlineLoadManifest(updater, buildOpts),
85
84
  inlineBuildId(updater),
86
85
  patchDepdDeprecations(updater),
87
86
  patchNextMinimal(updater),
88
- // Apply updater updaters, must be the last plugin
87
+ // Apply updater updates, must be the last plugin
89
88
  updater.plugin,
90
89
  ],
91
90
  external: ["./middleware/handler.mjs"],
@@ -102,7 +101,6 @@ export async function bundleServer(buildOpts) {
102
101
  // Note: we apply an empty shim to next/dist/compiled/edge-runtime since (amongst others) it generated the following `eval`:
103
102
  // eval(getModuleCode)(module, module.exports, throwingRequire, params.context, ...Object.values(params.scopedContext));
104
103
  // which comes from https://github.com/vercel/edge-runtime/blob/6e96b55f/packages/primitives/src/primitives/load.js#L57-L63
105
- // QUESTION: Why did I encountered this but mhart didn't?
106
104
  "next/dist/compiled/edge-runtime": path.join(buildOpts.outputDir, "cloudflare-templates/shims/empty.js"),
107
105
  // `@next/env` is a library Next.js uses for loading dotenv files, for obvious reasons we need to stub it here
108
106
  // source: https://github.com/vercel/next.js/tree/0ac10d79720/packages/next-env
@@ -188,12 +186,6 @@ export async function updateWorkerBundledCode(workerOutputFile, buildOpts) {
188
186
  "'require(this.middlewareManifestPath)'",
189
187
  (code) => patches.inlineMiddlewareManifestRequire(code, buildOpts),
190
188
  ],
191
- [
192
- "`patchAsyncStorage` call",
193
- (code) => code
194
- // TODO: implement for cf (possibly in @opennextjs/aws)
195
- .replace("patchAsyncStorage();", "//patchAsyncStorage();"),
196
- ],
197
189
  [
198
190
  "`require.resolve` call",
199
191
  // workers do not support dynamic require nor require.resolve
@@ -1,6 +1,6 @@
1
1
  import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
2
2
  import type { TagCacheMetaFile } from "@opennextjs/aws/types/cache.js";
3
3
  /**
4
- * Generates SQL statements that can be used to initialise the cache assets manifest in an SQL data store.
4
+ * Generates SQL statements that can be used to initialize the cache assets manifest in an SQL data store.
5
5
  */
6
6
  export declare function compileCacheAssetsManifestSqlFile(options: BuildOptions, metaFiles: TagCacheMetaFile[]): void;
@@ -1,17 +1,15 @@
1
1
  import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  /**
4
- * Generates SQL statements that can be used to initialise the cache assets manifest in an SQL data store.
4
+ * Generates SQL statements that can be used to initialize the cache assets manifest in an SQL data store.
5
5
  */
6
6
  export function compileCacheAssetsManifestSqlFile(options, metaFiles) {
7
7
  const outputPath = path.join(options.outputDir, "cloudflare/cache-assets-manifest.sql");
8
- const tagsTable = process.env.NEXT_CACHE_D1_TAGS_TABLE || "tags";
9
- const revalidationsTable = process.env.NEXT_CACHE_D1_REVALIDATIONS_TABLE || "revalidations";
10
8
  mkdirSync(path.dirname(outputPath), { recursive: true });
11
- writeFileSync(outputPath, `CREATE TABLE IF NOT EXISTS ${JSON.stringify(tagsTable)} (tag TEXT NOT NULL, path TEXT NOT NULL, UNIQUE(tag, path) ON CONFLICT REPLACE);
12
- CREATE TABLE IF NOT EXISTS ${JSON.stringify(revalidationsTable)} (tag TEXT NOT NULL, revalidatedAt INTEGER NOT NULL, UNIQUE(tag) ON CONFLICT REPLACE);\n`);
9
+ writeFileSync(outputPath, `CREATE TABLE IF NOT EXISTS tags (tag TEXT NOT NULL, path TEXT NOT NULL, UNIQUE(tag, path) ON CONFLICT REPLACE);
10
+ CREATE TABLE IF NOT EXISTS revalidations (tag TEXT NOT NULL, revalidatedAt INTEGER NOT NULL, UNIQUE(tag) ON CONFLICT REPLACE);\n`);
13
11
  const values = metaFiles.map(({ tag, path }) => `(${JSON.stringify(tag.S)}, ${JSON.stringify(path.S)})`);
14
12
  if (values.length) {
15
- appendFileSync(outputPath, `INSERT INTO ${JSON.stringify(tagsTable)} (tag, path) VALUES ${values.join(", ")};`);
13
+ appendFileSync(outputPath, `INSERT INTO tags (tag, path) VALUES ${values.join(", ")};`);
16
14
  }
17
15
  }
@@ -0,0 +1,2 @@
1
+ import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
+ export declare function compileDurableObjects(buildOpts: BuildOptions): void;
@@ -0,0 +1,30 @@
1
+ import { createRequire } from "node:module";
2
+ import path from "node:path";
3
+ import { loadBuildId, loadPrerenderManifest } from "@opennextjs/aws/adapters/config/util.js";
4
+ import { esbuildSync, getPackagePath } from "@opennextjs/aws/build/helper.js";
5
+ export function compileDurableObjects(buildOpts) {
6
+ const _require = createRequire(import.meta.url);
7
+ const entryPoints = [
8
+ _require.resolve("@opennextjs/cloudflare/durable-objects/queue"),
9
+ _require.resolve("@opennextjs/cloudflare/durable-objects/sharded-tag-cache"),
10
+ ];
11
+ const { outputDir } = buildOpts;
12
+ const baseManifestPath = path.join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next");
13
+ // We need to change the type in aws
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ const prerenderManifest = loadPrerenderManifest(baseManifestPath);
16
+ const previewModeId = prerenderManifest.preview.previewModeId;
17
+ const BUILD_ID = loadBuildId(baseManifestPath);
18
+ return esbuildSync({
19
+ entryPoints,
20
+ bundle: true,
21
+ platform: "node",
22
+ format: "esm",
23
+ outdir: path.join(buildOpts.buildDir, "durable-objects"),
24
+ external: ["cloudflare:workers"],
25
+ define: {
26
+ "process.env.__NEXT_PREVIEW_MODE_ID": `"${previewModeId}"`,
27
+ "process.env.__NEXT_BUILD_ID": `"${BUILD_ID}"`,
28
+ },
29
+ }, buildOpts);
30
+ }
@@ -1,6 +1,6 @@
1
1
  import { cpSync, mkdirSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { CACHE_ASSET_DIR } from "../../../api/kv-cache.js";
3
+ import { CACHE_ASSET_DIR } from "../../../api/overrides/incremental-cache/kv-incremental-cache.js";
4
4
  export function copyCacheAssets(options) {
5
5
  const { outputDir } = options;
6
6
  const srcPath = join(outputDir, "cache");
@@ -1,2 +1,10 @@
1
1
  import * as buildHelper from "@opennextjs/aws/build/helper.js";
2
- export declare function createServerBundle(options: buildHelper.BuildOptions): Promise<void>;
2
+ import type { CodePatcher } from "@opennextjs/aws/build/patch/codePatcher.js";
3
+ import type { ContentUpdater } from "@opennextjs/aws/plugins/content-updater.js";
4
+ import type { Plugin } from "esbuild";
5
+ interface CodeCustomization {
6
+ additionalCodePatches?: CodePatcher[];
7
+ additionalPlugins?: (contentUpdater: ContentUpdater) => Plugin[];
8
+ }
9
+ export declare function createServerBundle(options: buildHelper.BuildOptions, codeCustomization?: CodeCustomization): Promise<void>;
10
+ export {};
@@ -8,6 +8,9 @@ import { copyTracedFiles } from "@opennextjs/aws/build/copyTracedFiles.js";
8
8
  import { generateEdgeBundle } from "@opennextjs/aws/build/edge/createEdgeBundle.js";
9
9
  import * as buildHelper from "@opennextjs/aws/build/helper.js";
10
10
  import { installDependencies } from "@opennextjs/aws/build/installDeps.js";
11
+ import { applyCodePatches } from "@opennextjs/aws/build/patch/codePatcher.js";
12
+ import { patchFetchCacheForISR, patchUnstableCacheForISR, } from "@opennextjs/aws/build/patch/patchFetchCacheISR.js";
13
+ import { patchFetchCacheSetMissingWaitUntil } from "@opennextjs/aws/build/patch/patchFetchCacheWaitUntil.js";
11
14
  import logger from "@opennextjs/aws/logger.js";
12
15
  import { minifyAll } from "@opennextjs/aws/minimize-js.js";
13
16
  import { openNextEdgePlugins } from "@opennextjs/aws/plugins/edge.js";
@@ -15,8 +18,9 @@ import { openNextExternalMiddlewarePlugin } from "@opennextjs/aws/plugins/extern
15
18
  import { openNextReplacementPlugin } from "@opennextjs/aws/plugins/replacement.js";
16
19
  import { openNextResolvePlugin } from "@opennextjs/aws/plugins/resolve.js";
17
20
  import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
21
+ import { patchResRevalidate } from "../patches/plugins/res-revalidate.js";
18
22
  import { normalizePath } from "../utils/index.js";
19
- export async function createServerBundle(options) {
23
+ export async function createServerBundle(options, codeCustomization) {
20
24
  const { config } = options;
21
25
  const foundRoutes = new Set();
22
26
  // Get all functions to build
@@ -33,7 +37,7 @@ export async function createServerBundle(options) {
33
37
  await generateEdgeBundle(name, options, fnOptions);
34
38
  }
35
39
  else {
36
- await generateBundle(name, options, fnOptions);
40
+ await generateBundle(name, options, fnOptions, codeCustomization);
37
41
  }
38
42
  });
39
43
  //TODO: throw an error if not all edge runtime routes has been bundled in a separate function
@@ -71,7 +75,7 @@ export async function createServerBundle(options) {
71
75
  patterns: ["*"],
72
76
  });
73
77
  }
74
- async function generateBundle(name, options, fnOptions) {
78
+ async function generateBundle(name, options, fnOptions, codeCustomization) {
75
79
  const { appPath, appBuildOutputPath, config, outputDir, monorepoRoot } = options;
76
80
  logger.info(`Building server function: ${name}...`);
77
81
  // Create output folder
@@ -104,22 +108,32 @@ async function generateBundle(name, options, fnOptions) {
104
108
  // Copy env files
105
109
  buildHelper.copyEnvFile(appBuildOutputPath, packagePath, outputPath);
106
110
  // Copy all necessary traced files
107
- await copyTracedFiles({
111
+ const { tracedFiles, manifests } = await copyTracedFiles({
108
112
  buildOutputPath: appBuildOutputPath,
109
113
  packagePath,
110
114
  outputDir: outputPath,
111
115
  routes: fnOptions.routes ?? ["app/page.tsx"],
112
116
  bundledNextServer: isBundled,
113
117
  });
118
+ const additionalCodePatches = codeCustomization?.additionalCodePatches ?? [];
119
+ await applyCodePatches(options, tracedFiles, manifests, [
120
+ patchFetchCacheSetMissingWaitUntil,
121
+ patchFetchCacheForISR,
122
+ patchUnstableCacheForISR,
123
+ // Cloudflare specific patches
124
+ patchResRevalidate,
125
+ ...additionalCodePatches,
126
+ ]);
114
127
  // Build Lambda code
115
128
  // note: bundle in OpenNext package b/c the adapter relies on the
116
129
  // "serverless-http" package which is not a dependency in user's
117
130
  // Next.js app.
118
- const disableNextPrebundledReact = buildHelper.compareSemver(options.nextVersion, "13.5.1") >= 0 ||
119
- buildHelper.compareSemver(options.nextVersion, "13.4.1") <= 0;
131
+ const disableNextPrebundledReact = buildHelper.compareSemver(options.nextVersion, ">=", "13.5.1") ||
132
+ buildHelper.compareSemver(options.nextVersion, "<=", "13.4.1");
120
133
  const overrides = fnOptions.override ?? {};
121
- const isBefore13413 = buildHelper.compareSemver(options.nextVersion, "13.4.13") <= 0;
122
- const isAfter141 = buildHelper.compareSemver(options.nextVersion, "14.1") >= 0;
134
+ const isBefore13413 = buildHelper.compareSemver(options.nextVersion, "<=", "13.4.13");
135
+ const isAfter141 = buildHelper.compareSemver(options.nextVersion, ">=", "14.1");
136
+ const isAfter142 = buildHelper.compareSemver(options.nextVersion, ">=", "14.2");
123
137
  const disableRouting = isBefore13413 || config.middleware?.external;
124
138
  const plugins = [
125
139
  openNextReplacementPlugin({
@@ -128,6 +142,7 @@ async function generateBundle(name, options, fnOptions) {
128
142
  deletes: [
129
143
  ...(disableNextPrebundledReact ? ["applyNextjsPrebundledReact"] : []),
130
144
  ...(disableRouting ? ["withRouting"] : []),
145
+ ...(isAfter142 ? ["patchAsyncStorage"] : []),
131
146
  ],
132
147
  }),
133
148
  openNextReplacementPlugin({
@@ -143,7 +158,10 @@ async function generateBundle(name, options, fnOptions) {
143
158
  fnName: name,
144
159
  overrides,
145
160
  }),
146
- openNextExternalMiddlewarePlugin(path.join(options.openNextDistDir, "core/edgeFunctionHandler.js")),
161
+ // `openNextExternalMiddlewarePlugin` should only be used with an external middleware
162
+ ...(config.middleware?.external
163
+ ? [openNextExternalMiddlewarePlugin(path.join(options.openNextDistDir, "core/edgeFunctionHandler.js"))]
164
+ : []),
147
165
  openNextEdgePlugins({
148
166
  nextDir: path.join(options.appBuildOutputPath, ".next"),
149
167
  isInCloudfare: true,
@@ -153,6 +171,7 @@ async function generateBundle(name, options, fnOptions) {
153
171
  await buildHelper.esbuildAsync({
154
172
  entryPoints: [path.join(options.openNextDistDir, "adapters", "server-adapter.js")],
155
173
  outfile: path.join(outputPath, packagePath, `index.${outfileExt}`),
174
+ external: ["./middleware.mjs"],
156
175
  banner: {
157
176
  js: [
158
177
  `globalThis.monorepoPackagePath = "${normalizePath(packagePath)}";`,
@@ -1,8 +1,8 @@
1
1
  import { copyFileSync, existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { getPackagePath } from "@opennextjs/aws/build/helper.js";
4
+ import { parseFile } from "@opennextjs/aws/build/patch/astCodePatcher.js";
4
5
  import { globSync } from "glob";
5
- import { parseFile } from "./util.js";
6
6
  import { patchVercelOgFallbackFont, patchVercelOgImport } from "./vercel-og.js";
7
7
  /**
8
8
  * Patches the usage of @vercel/og to be compatible with Cloudflare Workers.
@@ -1,4 +1,4 @@
1
- import { SgNode } from "@ast-grep/napi";
1
+ import { SgNode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
2
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
3
  /**
4
4
  * Patches Node.js imports for the library to be Edge imports.
@@ -7,8 +7,8 @@ export declare const vercelOgImportRule = "\nrule:\n pattern: $NODE\n kind: st
7
7
  * @returns Results of applying the rule.
8
8
  */
9
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>>[];
10
+ edits: import("@opennextjs/aws/build/patch/astCodePatcher").Edit[];
11
+ matches: SgNode[];
12
12
  };
13
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
14
  /**
@@ -18,6 +18,6 @@ export declare const vercelOgFallbackFontRule = "\nrule:\n kind: variable_decla
18
18
  * @returns Results of applying the rule.
19
19
  */
20
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>>[];
21
+ edits: import("@opennextjs/aws/build/patch/astCodePatcher").Edit[];
22
+ matches: SgNode[];
23
23
  };
@@ -1,4 +1,4 @@
1
- import { applyRule } from "./util.js";
1
+ import { applyRule } from "@opennextjs/aws/build/patch/astCodePatcher.js";
2
2
  export const vercelOgImportRule = `
3
3
  rule:
4
4
  pattern: $NODE
@@ -1,5 +1,5 @@
1
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
1
2
  import { describe, expect, it } from "vitest";
2
- import { patchCode } from "./util";
3
3
  import { vercelOgFallbackFontRule, vercelOgImportRule } from "./vercel-og";
4
4
  describe("vercelOgImportRule", () => {
5
5
  it("should rewrite a node import to an edge import", () => {
@@ -22,7 +22,7 @@
22
22
  import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
23
23
  import { join } from "node:path";
24
24
  import { getPackagePath } from "@opennextjs/aws/build/helper.js";
25
- import { patchCode } from "./util.js";
25
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
26
26
  // Inline the code when there are multiple chunks
27
27
  export function buildMultipleChunksRule(chunks) {
28
28
  return `
@@ -1,5 +1,5 @@
1
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
1
2
  import { describe, expect, test } from "vitest";
2
- import { patchCode } from "./util.js";
3
3
  import { buildMultipleChunksRule, singleChunkRule } from "./webpack-runtime.js";
4
4
  describe("webpack runtime", () => {
5
5
  describe("multiple chunks", () => {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Inline `getBuildId` as it relies on `readFileSync` that is not supported by workerd.
3
3
  */
4
- import type { ContentUpdater } from "./content-updater.js";
5
- export declare function inlineBuildId(updater: ContentUpdater): import("esbuild").Plugin;
4
+ import type { ContentUpdater, Plugin } from "@opennextjs/aws/plugins/content-updater.js";
5
+ export declare function inlineBuildId(updater: ContentUpdater): Plugin;
6
6
  export declare const rule = "\nrule:\n kind: method_definition\n has:\n field: name\n regex: ^getBuildId$\nfix: |-\n getBuildId() {\n return process.env.NEXT_BUILD_ID;\n }\n";
@@ -1,13 +1,20 @@
1
1
  /**
2
2
  * Inline `getBuildId` as it relies on `readFileSync` that is not supported by workerd.
3
3
  */
4
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
4
5
  import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
5
- import { patchCode } from "../ast/util.js";
6
6
  export function inlineBuildId(updater) {
7
- return updater.updateContent("inline-build-id", {
8
- filter: getCrossPlatformPathRegex(String.raw `/next/dist/server/next-server\.js$`, { escape: false }),
9
- contentFilter: /getBuildId\(/,
10
- }, async ({ contents }) => patchCode(contents, rule));
7
+ return updater.updateContent("inline-build-id", [
8
+ {
9
+ field: {
10
+ filter: getCrossPlatformPathRegex(String.raw `/next/dist/server/next-server\.js$`, {
11
+ escape: false,
12
+ }),
13
+ contentFilter: /getBuildId\(/,
14
+ callback: ({ contents }) => patchCode(contents, rule),
15
+ },
16
+ },
17
+ ]);
11
18
  }
12
19
  export const rule = `
13
20
  rule:
@@ -1,5 +1,5 @@
1
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
1
2
  import { describe, expect, test } from "vitest";
2
- import { patchCode } from "../ast/util.js";
3
3
  import { rule } from "./build-id.js";
4
4
  describe("getBuildId", () => {
5
5
  test("patch", () => {
@@ -1,4 +1,3 @@
1
1
  import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
- import type { Plugin } from "esbuild";
3
- import type { ContentUpdater } from "./content-updater.js";
2
+ import type { ContentUpdater, Plugin } from "@opennextjs/aws/plugins/content-updater.js";
4
3
  export declare function inlineDynamicRequires(updater: ContentUpdater, buildOpts: BuildOptions): Plugin;
@@ -1,9 +1,9 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join, posix, sep } from "node:path";
3
3
  import { getPackagePath } from "@opennextjs/aws/build/helper.js";
4
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
4
5
  import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
5
6
  import { normalizePath } from "../../utils/normalize-path.js";
6
- import { patchCode } from "../ast/util.js";
7
7
  async function getPagesManifests(serverDir) {
8
8
  try {
9
9
  return Object.values(JSON.parse(await readFile(join(serverDir, "pages-manifest.json"), "utf-8")));
@@ -35,16 +35,26 @@ function getRequires(idVariable, files, serverDir) {
35
35
  .join("\n");
36
36
  }
37
37
  export function inlineDynamicRequires(updater, buildOpts) {
38
- updater.updateContent("inline-node-module-loader", {
39
- filter: getCrossPlatformPathRegex(String.raw `/module-loader/node-module-loader\.js$`, {
40
- escape: false,
41
- }),
42
- contentFilter: /class NodeModuleLoader {/,
43
- }, async ({ contents }) => patchCode(contents, await getNodeModuleLoaderRule(buildOpts)));
44
- updater.updateContent("inline-require-page", {
45
- filter: getCrossPlatformPathRegex(String.raw `/next/dist/server/require\.js$`, { escape: false }),
46
- contentFilter: /function requirePage\(/,
47
- }, async ({ contents }) => patchCode(contents, await getRequirePageRule(buildOpts)));
38
+ updater.updateContent("inline-node-module-loader", [
39
+ {
40
+ field: {
41
+ filter: getCrossPlatformPathRegex(String.raw `/module-loader/node-module-loader\.js$`, {
42
+ escape: false,
43
+ }),
44
+ contentFilter: /class NodeModuleLoader {/,
45
+ callback: async ({ contents }) => patchCode(contents, await getNodeModuleLoaderRule(buildOpts)),
46
+ },
47
+ },
48
+ ]);
49
+ updater.updateContent("inline-require-page", [
50
+ {
51
+ field: {
52
+ filter: getCrossPlatformPathRegex(String.raw `/next/dist/server/require\.js$`, { escape: false }),
53
+ contentFilter: /function requirePage\(/,
54
+ callback: async ({ contents }) => patchCode(contents, await getRequirePageRule(buildOpts)),
55
+ },
56
+ },
57
+ ]);
48
58
  return { name: "inline-dynamic-requires", setup() { } };
49
59
  }
50
60
  async function getNodeModuleLoaderRule(buildOpts) {
@@ -3,5 +3,5 @@
3
3
  * that are not supported by workerd.
4
4
  */
5
5
  import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
6
- import type { ContentUpdater } from "./content-updater.js";
7
- export declare function inlineEvalManifest(updater: ContentUpdater, buildOpts: BuildOptions): import("esbuild").Plugin;
6
+ import type { ContentUpdater, Plugin } from "@opennextjs/aws/plugins/content-updater.js";
7
+ export declare function inlineEvalManifest(updater: ContentUpdater, buildOpts: BuildOptions): Plugin;
@@ -4,15 +4,22 @@
4
4
  */
5
5
  import { join, posix, relative, sep } from "node:path";
6
6
  import { getPackagePath } from "@opennextjs/aws/build/helper.js";
7
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
7
8
  import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
8
9
  import { glob } from "glob";
9
10
  import { normalizePath } from "../../utils/normalize-path.js";
10
- import { patchCode } from "../ast/util.js";
11
11
  export function inlineEvalManifest(updater, buildOpts) {
12
- return updater.updateContent("inline-eval-manifest", {
13
- filter: getCrossPlatformPathRegex(String.raw `/next/dist/server/load-manifest\.js$`, { escape: false }),
14
- contentFilter: /function evalManifest\(/,
15
- }, async ({ contents }) => patchCode(contents, await getRule(buildOpts)));
12
+ return updater.updateContent("inline-eval-manifest", [
13
+ {
14
+ field: {
15
+ filter: getCrossPlatformPathRegex(String.raw `/next/dist/server/load-manifest\.js$`, {
16
+ escape: false,
17
+ }),
18
+ contentFilter: /function evalManifest\(/,
19
+ callback: async ({ contents }) => patchCode(contents, await getRule(buildOpts)),
20
+ },
21
+ },
22
+ ]);
16
23
  }
17
24
  async function getRule(buildOpts) {
18
25
  const { outputDir } = buildOpts;
@@ -2,5 +2,5 @@
2
2
  * Inline `findDir` as it relies on `existsSync` which is not supported by workerd.
3
3
  */
4
4
  import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
5
- import type { ContentUpdater } from "./content-updater.js";
6
- export declare function inlineFindDir(updater: ContentUpdater, buildOpts: BuildOptions): import("esbuild").Plugin;
5
+ import type { ContentUpdater, Plugin } from "@opennextjs/aws/plugins/content-updater.js";
6
+ export declare function inlineFindDir(updater: ContentUpdater, buildOpts: BuildOptions): Plugin;
@@ -4,13 +4,18 @@
4
4
  import { existsSync } from "node:fs";
5
5
  import { join, posix, sep } from "node:path";
6
6
  import { getPackagePath } from "@opennextjs/aws/build/helper.js";
7
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
7
8
  import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
8
- import { patchCode } from "../ast/util.js";
9
9
  export function inlineFindDir(updater, buildOpts) {
10
- return updater.updateContent("inline-find-dir", {
11
- filter: getCrossPlatformPathRegex(String.raw `/next/dist/lib/find-pages-dir\.js$`, { escape: false }),
12
- contentFilter: /function findDir\(/,
13
- }, async ({ contents }) => patchCode(contents, await getRule(buildOpts)));
10
+ return updater.updateContent("inline-find-dir", [
11
+ {
12
+ field: {
13
+ filter: getCrossPlatformPathRegex(String.raw `/next/dist/lib/find-pages-dir\.js$`, { escape: false }),
14
+ contentFilter: /function findDir\(/,
15
+ callback: async ({ contents }) => patchCode(contents, await getRule(buildOpts)),
16
+ },
17
+ },
18
+ ]);
14
19
  }
15
20
  async function getRule(buildOpts) {
16
21
  const { outputDir } = buildOpts;
@@ -1,8 +1,5 @@
1
1
  import { type BuildOptions } from "@opennextjs/aws/build/helper.js";
2
- import type { ContentUpdater } from "./content-updater.js";
3
- export declare function patchInstrumentation(updater: ContentUpdater, buildOpts: BuildOptions): {
4
- name: string;
5
- setup(): void;
6
- };
2
+ import type { ContentUpdater, Plugin } from "@opennextjs/aws/plugins/content-updater.js";
3
+ export declare function patchInstrumentation(updater: ContentUpdater, buildOpts: BuildOptions): Plugin;
7
4
  export declare function getNext15Rule(builtInstrumentationPath: string | null): string;
8
5
  export declare function getNext14Rule(builtInstrumentationPath: string | null): string;