@opennextjs/cloudflare 0.0.0-e2c4535 → 0.0.0-e62af72

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.
package/README.md CHANGED
@@ -1,39 +1,65 @@
1
- # Next.js builder for Cloudflare
1
+ # OpenNext for Cloudflare
2
2
 
3
- How to update a Next.js application to run on Cloudflare.
3
+ Deploy Next.js apps to Cloudflare!
4
4
 
5
- ## Configure your app
5
+ OpenNext for Cloudflare is Cloudflare specific adapter that enables deployment of Next.js applications to Cloudflare.
6
6
 
7
- - add the following `devDependencies` to the `package.json`:
7
+ ## Getting started
8
8
 
9
- ```bash
10
- pnpm add -D wrangler@latest @opennextjs/cloudflare
11
- ```
9
+ You can use [`create-next-app`](https://nextjs.org/docs/pages/api-reference/cli/create-next-app) to start a new application or take an existing Next.js application and deploy it to Cloudflare using the following few steps:
12
10
 
13
- ## Serve your app
11
+ ## Configure your app
14
12
 
15
- - build the app and adapt it for Cloudflare
13
+ - add the following `devDependencies` to the `package.json`:
16
14
 
17
15
  ```bash
18
- pnpx cloudflare
16
+ pnpm add -D wrangler@latest @opennextjs/cloudflare
19
17
  ```
20
18
 
21
19
  - add a `wrangler.toml` at the root of your project
22
20
 
23
21
  ```toml
24
22
  #:schema node_modules/wrangler/config-schema.json
25
- name = "<app-name>"
23
+ name = "<your-app-name>"
26
24
  main = ".worker-next/index.mjs"
27
25
 
28
- compatibility_date = "2024-08-29"
29
- compatibility_flags = ["nodejs_compat_v2"]
26
+ compatibility_date = "2024-09-23"
27
+ compatibility_flags = ["nodejs_compat"]
30
28
 
31
29
  # Use the new Workers + Assets to host the static frontend files
32
30
  experimental_assets = { directory = ".worker-next/assets", binding = "ASSETS" }
33
31
  ```
34
32
 
33
+ ## Local development
34
+
35
+ - you can use the regular `next` CLI to start the Next.js dev server:
36
+
37
+ ## Local preview
38
+
39
+ Run the following commands to preview the production build of your application locally:
40
+
41
+ - build the app and adapt it for Cloudflare
42
+
43
+ ```bash
44
+ pnpx cloudflare
45
+ ```
46
+
35
47
  - Preview the app in Wrangler
36
48
 
37
49
  ```bash
38
50
  pnpm wrangler dev
39
51
  ```
52
+
53
+ ## Deploy your app
54
+
55
+ Deploy your application to production with the following:
56
+
57
+ - build the app and adapt it for Cloudflare
58
+
59
+ ```bash
60
+ pnpx cloudflare
61
+ ```
62
+
63
+ ```bash
64
+ pnpm wrangler deploy
65
+ ```
@@ -0,0 +1,32 @@
1
+ // src/api/get-cloudflare-context.ts
2
+ import "server-only";
3
+ var cloudflareContextSymbol = Symbol.for("__cloudflare-context__");
4
+ async function getCloudflareContext() {
5
+ const global = globalThis;
6
+ const cloudflareContext = global[cloudflareContextSymbol];
7
+ if (!cloudflareContext) {
8
+ return getCloudflareContextInNextDev();
9
+ }
10
+ return cloudflareContext;
11
+ }
12
+ var cloudflareContextInNextDevSymbol = Symbol.for("__next-dev/cloudflare-context__");
13
+ async function getCloudflareContextInNextDev() {
14
+ const global = globalThis;
15
+ if (!global[cloudflareContextInNextDevSymbol]) {
16
+ const { getPlatformProxy } = await import(
17
+ /* webpackIgnore: true */
18
+ `${"__wrangler".replaceAll("_", "")}`
19
+ );
20
+ const { env, cf, ctx } = await getPlatformProxy();
21
+ global[cloudflareContextInNextDevSymbol] = {
22
+ env,
23
+ cf,
24
+ ctx
25
+ };
26
+ }
27
+ return global[cloudflareContextInNextDevSymbol];
28
+ }
29
+
30
+ export {
31
+ getCloudflareContext
32
+ };
@@ -0,0 +1,26 @@
1
+ declare global {
2
+ interface CloudflareEnv {
3
+ }
4
+ }
5
+ type CloudflareContext<CfProperties extends Record<string, unknown> = IncomingRequestCfProperties, Context = ExecutionContext> = {
6
+ /**
7
+ * the worker's [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/)
8
+ */
9
+ env: CloudflareEnv;
10
+ /**
11
+ * the request's [cf properties](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties)
12
+ */
13
+ cf: CfProperties;
14
+ /**
15
+ * the current [execution context](https://developers.cloudflare.com/workers/runtime-apis/context)
16
+ */
17
+ ctx: Context;
18
+ };
19
+ /**
20
+ * Utility to get the current Cloudflare context
21
+ *
22
+ * @returns the cloudflare context
23
+ */
24
+ declare function getCloudflareContext<CfProperties extends Record<string, unknown> = IncomingRequestCfProperties, Context = ExecutionContext>(): Promise<CloudflareContext<CfProperties, Context>>;
25
+
26
+ export { type CloudflareContext, getCloudflareContext };
@@ -0,0 +1,6 @@
1
+ import {
2
+ getCloudflareContext
3
+ } from "./chunk-VTBEIZPQ.mjs";
4
+ export {
5
+ getCloudflareContext
6
+ };
@@ -0,0 +1 @@
1
+ export { CloudflareContext, getCloudflareContext } from './get-cloudflare-context.mjs';
@@ -0,0 +1,6 @@
1
+ import {
2
+ getCloudflareContext
3
+ } from "./chunk-VTBEIZPQ.mjs";
4
+ export {
5
+ getCloudflareContext
6
+ };
@@ -0,0 +1,48 @@
1
+ import "./chunk-UJCSKKID.mjs";
2
+
3
+ // src/cli/cache-handler.ts
4
+ var CfWorkersKvCacheHandler = class _CfWorkersKvCacheHandler {
5
+ constructor(ctx) {
6
+ this.ctx = ctx;
7
+ }
8
+ static maybeKVNamespace = void 0;
9
+ async get(key) {
10
+ if (_CfWorkersKvCacheHandler.maybeKVNamespace === void 0) {
11
+ return null;
12
+ }
13
+ console.log(`[Cf] Getting cache[${key}]`);
14
+ try {
15
+ return await _CfWorkersKvCacheHandler.maybeKVNamespace.get(key, "json") ?? null;
16
+ } catch (e) {
17
+ console.error(`Failed to get value for key = ${key}: ${e}`);
18
+ return null;
19
+ }
20
+ }
21
+ async set(key, entry, ctx) {
22
+ if (_CfWorkersKvCacheHandler.maybeKVNamespace === void 0) {
23
+ return;
24
+ }
25
+ console.log(`[Cf] Setting cache[${key}]`);
26
+ try {
27
+ const data = {
28
+ lastModified: Date.now(),
29
+ value: entry
30
+ };
31
+ await _CfWorkersKvCacheHandler.maybeKVNamespace.put(key, JSON.stringify(data));
32
+ } catch (e) {
33
+ console.error(`Failed to set value for key = ${key}: ${e}`);
34
+ }
35
+ }
36
+ async revalidateTag(tags) {
37
+ if (_CfWorkersKvCacheHandler.maybeKVNamespace === void 0) {
38
+ return;
39
+ }
40
+ tags = [tags].flat();
41
+ console.log(`[Cf] revalidateTag ${JSON.stringify(tags)}}`);
42
+ }
43
+ resetRequestCache() {
44
+ }
45
+ };
46
+ export {
47
+ CfWorkersKvCacheHandler as default
48
+ };
@@ -0,0 +1,30 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ export {
28
+ __commonJS,
29
+ __toESM
30
+ };
@@ -1,29 +1,8 @@
1
1
  #!/usr/bin/env node
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __commonJS = (cb, mod) => function __require() {
9
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
2
+ import {
3
+ __commonJS,
4
+ __toESM
5
+ } from "./chunk-UJCSKKID.mjs";
27
6
 
28
7
  // ../../node_modules/.pnpm/balanced-match@1.0.2/node_modules/balanced-match/index.js
29
8
  var require_balanced_match = __commonJS({
@@ -234,10 +213,10 @@ var require_brace_expansion = __commonJS({
234
213
  }
235
214
  });
236
215
 
237
- // src/index.ts
216
+ // src/cli/index.ts
238
217
  import { resolve as resolve2 } from "node:path";
239
218
 
240
- // src/args.ts
219
+ // src/cli/args.ts
241
220
  import { mkdirSync, statSync } from "node:fs";
242
221
  import { parseArgs } from "node:util";
243
222
  import { resolve } from "node:path";
@@ -267,15 +246,15 @@ function getArgs() {
267
246
  skipBuild: skipBuild2 || ["1", "true", "yes"].includes(String(process.env.SKIP_NEXT_APP_BUILD))
268
247
  };
269
248
  }
270
- function assertDirArg(path6, argName, make) {
249
+ function assertDirArg(path13, argName, make) {
271
250
  let dirStats;
272
251
  try {
273
- dirStats = statSync(path6);
252
+ dirStats = statSync(path13);
274
253
  } catch {
275
254
  if (!make) {
276
255
  throw new Error(`Error: the provided${argName ? ` "${argName}"` : ""} input is not a valid path`);
277
256
  }
278
- mkdirSync(path6);
257
+ mkdirSync(path13);
279
258
  return;
280
259
  }
281
260
  if (!dirStats.isDirectory()) {
@@ -283,13 +262,13 @@ function assertDirArg(path6, argName, make) {
283
262
  }
284
263
  }
285
264
 
286
- // src/index.ts
265
+ // src/cli/index.ts
287
266
  import { existsSync as existsSync4 } from "node:fs";
288
267
 
289
- // src/build/build.ts
268
+ // src/cli/build/index.ts
290
269
  import { rm } from "node:fs/promises";
291
270
 
292
- // src/build/build-next-app.ts
271
+ // src/cli/build/build-next-app.ts
293
272
  import { execSync } from "node:child_process";
294
273
  function buildNextjsApp(nextAppDir2) {
295
274
  runNextBuildCommand("pnpm", nextAppDir2);
@@ -308,28 +287,30 @@ function runNextBuildCommand(packager, nextAppDir2) {
308
287
  });
309
288
  }
310
289
 
311
- // src/build/build-worker.ts
290
+ // src/cli/build/build-worker.ts
312
291
  import { build } from "esbuild";
313
292
  import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
314
293
  import { cp, readFile, writeFile } from "node:fs/promises";
294
+ import path10 from "node:path";
295
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
315
296
 
316
- // src/build/patches/investigated/patch-require.ts
297
+ // src/cli/build/patches/investigated/patch-require.ts
317
298
  function patchRequire(code) {
318
299
  console.log("# patchRequire");
319
300
  return code.replace(/__require\d?\(/g, "require(").replace(/__require\d?\./g, "require.");
320
301
  }
321
302
 
322
- // src/build/patches/investigated/copy-templates.ts
323
- import path from "node:path";
303
+ // src/cli/build/patches/investigated/copy-package-cli-files.ts
324
304
  import { cpSync } from "node:fs";
325
- function copyTemplates(srcDir, nextjsAppPaths) {
326
- console.log("# copyTemplates");
327
- const destDir = path.join(nextjsAppPaths.standaloneAppDir, "node_modules/cf/templates");
328
- cpSync(srcDir, destDir, { recursive: true });
329
- return destDir;
305
+ import path from "node:path";
306
+ function copyPackageCliFiles(packageDistDir2, config) {
307
+ console.log("# copyPackageTemplateFiles");
308
+ const sourceDir = path.join(packageDistDir2, "cli");
309
+ const destinationDir = path.join(config.paths.internalPackage, "cli");
310
+ cpSync(sourceDir, destinationDir, { recursive: true });
330
311
  }
331
312
 
332
- // src/build/patches/to-investigate/patch-read-file.ts
313
+ // src/cli/build/patches/to-investigate/patch-read-file.ts
333
314
  import { readFileSync } from "node:fs";
334
315
 
335
316
  // ../../node_modules/.pnpm/minimatch@10.0.1/node_modules/minimatch/dist/esm/index.js
@@ -4184,12 +4165,12 @@ var PathBase = class {
4184
4165
  /**
4185
4166
  * Get the Path object referenced by the string path, resolved from this Path
4186
4167
  */
4187
- resolve(path6) {
4188
- if (!path6) {
4168
+ resolve(path13) {
4169
+ if (!path13) {
4189
4170
  return this;
4190
4171
  }
4191
- const rootPath = this.getRootString(path6);
4192
- const dir = path6.substring(rootPath.length);
4172
+ const rootPath = this.getRootString(path13);
4173
+ const dir = path13.substring(rootPath.length);
4193
4174
  const dirParts = dir.split(this.splitSep);
4194
4175
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
4195
4176
  return result;
@@ -4941,8 +4922,8 @@ var PathWin32 = class _PathWin32 extends PathBase {
4941
4922
  /**
4942
4923
  * @internal
4943
4924
  */
4944
- getRootString(path6) {
4945
- return win32.parse(path6).root;
4925
+ getRootString(path13) {
4926
+ return win32.parse(path13).root;
4946
4927
  }
4947
4928
  /**
4948
4929
  * @internal
@@ -4988,8 +4969,8 @@ var PathPosix = class _PathPosix extends PathBase {
4988
4969
  /**
4989
4970
  * @internal
4990
4971
  */
4991
- getRootString(path6) {
4992
- return path6.startsWith("/") ? "/" : "";
4972
+ getRootString(path13) {
4973
+ return path13.startsWith("/") ? "/" : "";
4993
4974
  }
4994
4975
  /**
4995
4976
  * @internal
@@ -5078,11 +5059,11 @@ var PathScurryBase = class {
5078
5059
  /**
5079
5060
  * Get the depth of a provided path, string, or the cwd
5080
5061
  */
5081
- depth(path6 = this.cwd) {
5082
- if (typeof path6 === "string") {
5083
- path6 = this.cwd.resolve(path6);
5062
+ depth(path13 = this.cwd) {
5063
+ if (typeof path13 === "string") {
5064
+ path13 = this.cwd.resolve(path13);
5084
5065
  }
5085
- return path6.depth();
5066
+ return path13.depth();
5086
5067
  }
5087
5068
  /**
5088
5069
  * Return the cache of child entries. Exposed so subclasses can create
@@ -5569,9 +5550,9 @@ var PathScurryBase = class {
5569
5550
  process2();
5570
5551
  return results;
5571
5552
  }
5572
- chdir(path6 = this.cwd) {
5553
+ chdir(path13 = this.cwd) {
5573
5554
  const oldCwd = this.cwd;
5574
- this.cwd = typeof path6 === "string" ? this.cwd.resolve(path6) : path6;
5555
+ this.cwd = typeof path13 === "string" ? this.cwd.resolve(path13) : path13;
5575
5556
  this.cwd[setAsCwd](oldCwd);
5576
5557
  }
5577
5558
  };
@@ -5927,8 +5908,8 @@ var MatchRecord = class {
5927
5908
  }
5928
5909
  // match, absolute, ifdir
5929
5910
  entries() {
5930
- return [...this.store.entries()].map(([path6, n]) => [
5931
- path6,
5911
+ return [...this.store.entries()].map(([path13, n]) => [
5912
+ path13,
5932
5913
  !!(n & 2),
5933
5914
  !!(n & 1)
5934
5915
  ]);
@@ -6133,9 +6114,9 @@ var GlobUtil = class {
6133
6114
  signal;
6134
6115
  maxDepth;
6135
6116
  includeChildMatches;
6136
- constructor(patterns, path6, opts) {
6117
+ constructor(patterns, path13, opts) {
6137
6118
  this.patterns = patterns;
6138
- this.path = path6;
6119
+ this.path = path13;
6139
6120
  this.opts = opts;
6140
6121
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
6141
6122
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -6154,11 +6135,11 @@ var GlobUtil = class {
6154
6135
  });
6155
6136
  }
6156
6137
  }
6157
- #ignored(path6) {
6158
- return this.seen.has(path6) || !!this.#ignore?.ignored?.(path6);
6138
+ #ignored(path13) {
6139
+ return this.seen.has(path13) || !!this.#ignore?.ignored?.(path13);
6159
6140
  }
6160
- #childrenIgnored(path6) {
6161
- return !!this.#ignore?.childrenIgnored?.(path6);
6141
+ #childrenIgnored(path13) {
6142
+ return !!this.#ignore?.childrenIgnored?.(path13);
6162
6143
  }
6163
6144
  // backpressure mechanism
6164
6145
  pause() {
@@ -6373,8 +6354,8 @@ var GlobUtil = class {
6373
6354
  };
6374
6355
  var GlobWalker = class extends GlobUtil {
6375
6356
  matches = /* @__PURE__ */ new Set();
6376
- constructor(patterns, path6, opts) {
6377
- super(patterns, path6, opts);
6357
+ constructor(patterns, path13, opts) {
6358
+ super(patterns, path13, opts);
6378
6359
  }
6379
6360
  matchEmit(e) {
6380
6361
  this.matches.add(e);
@@ -6411,8 +6392,8 @@ var GlobWalker = class extends GlobUtil {
6411
6392
  };
6412
6393
  var GlobStream = class extends GlobUtil {
6413
6394
  results;
6414
- constructor(patterns, path6, opts) {
6415
- super(patterns, path6, opts);
6395
+ constructor(patterns, path13, opts) {
6396
+ super(patterns, path13, opts);
6416
6397
  this.results = new Minipass({
6417
6398
  signal: this.signal,
6418
6399
  objectMode: true
@@ -6705,17 +6686,18 @@ var glob = Object.assign(glob_, {
6705
6686
  });
6706
6687
  glob.glob = glob;
6707
6688
 
6708
- // src/build/patches/to-investigate/patch-read-file.ts
6709
- function patchReadFile(code, nextjsAppPaths) {
6689
+ // src/cli/build/patches/to-investigate/patch-read-file.ts
6690
+ import path3 from "node:path";
6691
+ function patchReadFile(code, config) {
6710
6692
  console.log("# patchReadFile");
6711
6693
  code = code.replace(
6712
6694
  "getBuildId() {",
6713
6695
  `getBuildId() {
6714
- return ${JSON.stringify(readFileSync(`${nextjsAppPaths.standaloneAppDotNextDir}/BUILD_ID`, "utf-8"))};
6696
+ return ${JSON.stringify(readFileSync(path3.join(config.paths.standaloneAppDotNext, "BUILD_ID"), "utf-8"))};
6715
6697
  `
6716
6698
  );
6717
- const manifestJsons = globSync(`${nextjsAppPaths.standaloneAppDotNextDir}/**/*-manifest.json`).map(
6718
- (file) => file.replace(nextjsAppPaths.standaloneAppDir + "/", "")
6699
+ const manifestJsons = globSync(path3.join(config.paths.standaloneAppDotNext, "**", "*-manifest.json")).map(
6700
+ (file) => file.replace(config.paths.standaloneApp + "/", "")
6719
6701
  );
6720
6702
  code = code.replace(
6721
6703
  /function loadManifest\((.+?), .+?\) {/,
@@ -6723,7 +6705,7 @@ function patchReadFile(code, nextjsAppPaths) {
6723
6705
  ${manifestJsons.map(
6724
6706
  (manifestJson) => `
6725
6707
  if ($1.endsWith("${manifestJson}")) {
6726
- return ${readFileSync(`${nextjsAppPaths.standaloneAppDir}/${manifestJson}`, "utf-8")};
6708
+ return ${readFileSync(path3.join(config.paths.standaloneApp, manifestJson), "utf-8")};
6727
6709
  }
6728
6710
  `
6729
6711
  ).join("\n")}
@@ -6733,28 +6715,34 @@ function patchReadFile(code, nextjsAppPaths) {
6733
6715
  return code;
6734
6716
  }
6735
6717
 
6736
- // src/build/patches/to-investigate/patch-find-dir.ts
6718
+ // src/cli/build/patches/to-investigate/patch-find-dir.ts
6719
+ import path4 from "node:path";
6737
6720
  import { existsSync } from "node:fs";
6738
- function patchFindDir(code, nextjsAppPaths) {
6721
+ function patchFindDir(code, config) {
6739
6722
  console.log("# patchFindDir");
6740
6723
  return code.replace(
6741
6724
  "function findDir(dir, name) {",
6742
6725
  `function findDir(dir, name) {
6743
6726
  if (dir.endsWith(".next/server")) {
6744
- if (name === "app") return ${existsSync(`${nextjsAppPaths.standaloneAppServerDir}/app`)};
6745
- if (name === "pages") return ${existsSync(`${nextjsAppPaths.standaloneAppServerDir}/pages`)};
6727
+ if (name === "app") {
6728
+ return ${existsSync(`${path4.join(config.paths.standaloneAppServer, "app")}`)};
6729
+ }
6730
+ if (name === "pages") {
6731
+ return ${existsSync(`${path4.join(config.paths.standaloneAppServer, "pages")}`)};
6732
+ }
6746
6733
  }
6747
6734
  throw new Error("Unknown findDir call: " + dir + " " + name);
6748
6735
  `
6749
6736
  );
6750
6737
  }
6751
6738
 
6752
- // src/build/patches/to-investigate/inline-next-require.ts
6739
+ // src/cli/build/patches/to-investigate/inline-next-require.ts
6753
6740
  import { readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
6754
- function inlineNextRequire(code, nextjsAppPaths) {
6741
+ import path5 from "node:path";
6742
+ function inlineNextRequire(code, config) {
6755
6743
  console.log("# inlineNextRequire");
6756
- const pagesManifestFile = `${nextjsAppPaths.standaloneAppServerDir}/pages-manifest.json`;
6757
- const appPathsManifestFile = `${nextjsAppPaths.standaloneAppServerDir}/app-paths-manifest.json`;
6744
+ const pagesManifestFile = path5.join(config.paths.standaloneAppServer, "pages-manifest.json");
6745
+ const appPathsManifestFile = path5.join(config.paths.standaloneAppServer, "app-paths-manifest.json");
6758
6746
  const pagesManifestFiles = existsSync2(pagesManifestFile) ? Object.values(JSON.parse(readFileSync2(pagesManifestFile, "utf-8"))).map(
6759
6747
  (file) => ".next/server/" + file
6760
6748
  ) : [];
@@ -6770,14 +6758,14 @@ function inlineNextRequire(code, nextjsAppPaths) {
6770
6758
  ${htmlPages.map(
6771
6759
  (htmlPage) => `
6772
6760
  if (pagePath.endsWith("${htmlPage}")) {
6773
- return ${JSON.stringify(readFileSync2(`${nextjsAppPaths.standaloneAppDir}/${htmlPage}`, "utf-8"))};
6761
+ return ${JSON.stringify(readFileSync2(path5.join(config.paths.standaloneApp, htmlPage), "utf-8"))};
6774
6762
  }
6775
6763
  `
6776
6764
  ).join("\n")}
6777
6765
  ${pageModules.map(
6778
6766
  (module) => `
6779
6767
  if (pagePath.endsWith("${module}")) {
6780
- return require("${nextjsAppPaths.standaloneAppDir}/${module}");
6768
+ return require("${path5.join(config.paths.standaloneApp, module)}");
6781
6769
  }
6782
6770
  `
6783
6771
  ).join("\n")}
@@ -6786,19 +6774,20 @@ function inlineNextRequire(code, nextjsAppPaths) {
6786
6774
  );
6787
6775
  }
6788
6776
 
6789
- // src/build/patches/to-investigate/inline-eval-manifest.ts
6790
- function inlineEvalManifest(code, nextjsAppPaths) {
6777
+ // src/cli/build/patches/to-investigate/inline-eval-manifest.ts
6778
+ import path6 from "node:path";
6779
+ function inlineEvalManifest(code, config) {
6791
6780
  console.log("# inlineEvalManifest");
6792
6781
  const manifestJss = globSync(
6793
- `${nextjsAppPaths.standaloneAppDotNextDir}/**/*_client-reference-manifest.js`
6794
- ).map((file) => file.replace(`${nextjsAppPaths.standaloneAppDir}/`, ""));
6782
+ path6.join(config.paths.standaloneAppDotNext, "**", "*_client-reference-manifest.js")
6783
+ ).map((file) => file.replace(`${config.paths.standaloneApp}/`, ""));
6795
6784
  return code.replace(
6796
6785
  /function evalManifest\((.+?), .+?\) {/,
6797
6786
  `$&
6798
6787
  ${manifestJss.map(
6799
6788
  (manifestJs) => `
6800
6789
  if ($1.endsWith("${manifestJs}")) {
6801
- require("${nextjsAppPaths.standaloneAppDir}/${manifestJs}");
6790
+ require("${path6.join(config.paths.standaloneApp, manifestJs)}");
6802
6791
  return {
6803
6792
  __RSC_MANIFEST: {
6804
6793
  "${manifestJs.replace(".next/server/app", "").replace("_client-reference-manifest.js", "")}": globalThis.__RSC_MANIFEST["${manifestJs.replace(".next/server/app", "").replace("_client-reference-manifest.js", "")}"],
@@ -6812,14 +6801,13 @@ function inlineEvalManifest(code, nextjsAppPaths) {
6812
6801
  );
6813
6802
  }
6814
6803
 
6815
- // src/build/patches/to-investigate/wrangler-deps.ts
6816
- import path3 from "node:path";
6804
+ // src/cli/build/patches/to-investigate/wrangler-deps.ts
6805
+ import path7 from "node:path";
6817
6806
  import fs, { writeFileSync } from "node:fs";
6818
- function patchWranglerDeps(paths) {
6807
+ function patchWranglerDeps(config) {
6819
6808
  console.log("# patchWranglerDeps");
6820
- console.log({ base: paths.standaloneAppDotNextDir });
6821
- const pagesRuntimeFile = path3.join(
6822
- paths.standaloneAppDir,
6809
+ const pagesRuntimeFile = path7.join(
6810
+ config.paths.standaloneApp,
6823
6811
  "node_modules",
6824
6812
  "next",
6825
6813
  "dist",
@@ -6829,8 +6817,8 @@ function patchWranglerDeps(paths) {
6829
6817
  );
6830
6818
  const patchedPagesRuntime = fs.readFileSync(pagesRuntimeFile, "utf-8").replace(`e.exports=require("critters")`, `e.exports={}`);
6831
6819
  fs.writeFileSync(pagesRuntimeFile, patchedPagesRuntime);
6832
- const tracerFile = path3.join(
6833
- paths.standaloneAppDir,
6820
+ const tracerFile = path7.join(
6821
+ config.paths.standaloneApp,
6834
6822
  "node_modules",
6835
6823
  "next",
6836
6824
  "dist",
@@ -6843,10 +6831,11 @@ function patchWranglerDeps(paths) {
6843
6831
  writeFileSync(tracerFile, pacthedTracer);
6844
6832
  }
6845
6833
 
6846
- // src/build/patches/investigated/update-webpack-chunks-file/index.ts
6834
+ // src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts
6847
6835
  import { readdirSync as readdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
6836
+ import path8 from "node:path";
6848
6837
 
6849
- // src/build/patches/investigated/update-webpack-chunks-file/get-chunk-installation-identifiers.ts
6838
+ // src/cli/build/patches/investigated/update-webpack-chunks-file/get-chunk-installation-identifiers.ts
6850
6839
  import * as ts from "ts-morph";
6851
6840
  async function getChunkInstallationIdentifiers(sourceFile) {
6852
6841
  const installChunkDeclaration = getInstallChunkDeclaration(sourceFile);
@@ -6892,7 +6881,7 @@ function getInstalledChunksDeclaration(sourceFile, installChunkDeclaration) {
6892
6881
  return installedChunksDeclaration;
6893
6882
  }
6894
6883
 
6895
- // src/build/patches/investigated/update-webpack-chunks-file/get-file-content-with-updated-webpack-f-require-code.ts
6884
+ // src/cli/build/patches/investigated/update-webpack-chunks-file/get-file-content-with-updated-webpack-f-require-code.ts
6896
6885
  import * as ts2 from "ts-morph";
6897
6886
  async function getFileContentWithUpdatedWebpackFRequireCode(sourceFile, { installedChunks, installChunk }, chunks) {
6898
6887
  const webpackFRequireFunction = sourceFile.getDescendantsOfKind(ts2.SyntaxKind.ArrowFunction).find((arrowFunction) => {
@@ -6936,7 +6925,7 @@ if(${chunkId} === ${chunk}) return ${installChunk}(require("./chunks/${chunk}.js
6936
6925
  return sourceFile.print();
6937
6926
  }
6938
6927
 
6939
- // src/build/utils/ts-parse-file.ts
6928
+ // src/cli/build/utils/ts-parse-file.ts
6940
6929
  import * as ts3 from "ts-morph";
6941
6930
  function tsParseFile(fileContent) {
6942
6931
  const project = new ts3.Project();
@@ -6944,7 +6933,7 @@ function tsParseFile(fileContent) {
6944
6933
  return sourceFile;
6945
6934
  }
6946
6935
 
6947
- // src/build/patches/investigated/update-webpack-chunks-file/get-updated-webpack-chunks-file-content.ts
6936
+ // src/cli/build/patches/investigated/update-webpack-chunks-file/get-updated-webpack-chunks-file-content.ts
6948
6937
  async function getUpdatedWebpackChunksFileContent(fileContent, chunks) {
6949
6938
  const tsSourceFile = tsParseFile(fileContent);
6950
6939
  const chunkInstallationIdentifiers = await getChunkInstallationIdentifiers(tsSourceFile);
@@ -6956,12 +6945,12 @@ async function getUpdatedWebpackChunksFileContent(fileContent, chunks) {
6956
6945
  return updatedFileContent;
6957
6946
  }
6958
6947
 
6959
- // src/build/patches/investigated/update-webpack-chunks-file/index.ts
6960
- async function updateWebpackChunksFile(nextjsAppPaths) {
6948
+ // src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts
6949
+ async function updateWebpackChunksFile(config) {
6961
6950
  console.log("# updateWebpackChunksFile");
6962
- const webpackRuntimeFile = `${nextjsAppPaths.standaloneAppServerDir}/webpack-runtime.js`;
6951
+ const webpackRuntimeFile = path8.join(config.paths.standaloneAppServer, "webpack-runtime.js");
6963
6952
  const fileContent = readFileSync3(webpackRuntimeFile, "utf-8");
6964
- const chunks = readdirSync2(`${nextjsAppPaths.standaloneAppServerDir}/chunks`).filter((chunk) => /^\d+\.js$/.test(chunk)).map((chunk) => {
6953
+ const chunks = readdirSync2(path8.join(config.paths.standaloneAppServer, "chunks")).filter((chunk) => /^\d+\.js$/.test(chunk)).map((chunk) => {
6965
6954
  console.log(` - chunk ${chunk}`);
6966
6955
  return chunk.replace(/\.js$/, "");
6967
6956
  });
@@ -6969,18 +6958,53 @@ async function updateWebpackChunksFile(nextjsAppPaths) {
6969
6958
  writeFileSync2(webpackRuntimeFile, updatedFileContent);
6970
6959
  }
6971
6960
 
6972
- // src/build/build-worker.ts
6973
- async function buildWorker(inputNextAppDir, outputDir2, nextjsAppPaths, templateSrcDir) {
6974
- const templateDir = copyTemplates(templateSrcDir, nextjsAppPaths);
6975
- const workerEntrypoint = `${templateDir}/worker.ts`;
6976
- const workerOutputFile = `${outputDir2}/index.mjs`;
6977
- const nextConfigStr = readFileSync4(nextjsAppPaths.standaloneAppDir + "/server.js", "utf8")?.match(
6961
+ // src/cli/build/patches/investigated/patch-cache.ts
6962
+ import path9 from "node:path";
6963
+ function patchCache(code, config) {
6964
+ console.log("# patchCached");
6965
+ const cacheHandler = path9.join(config.paths.internalPackage, "cli", "cache-handler.mjs");
6966
+ const patchedCode = code.replace(
6967
+ "const { cacheHandler } = this.nextConfig;",
6968
+ `const cacheHandler = null;
6969
+ CacheHandler = (await import('${cacheHandler}')).default;
6970
+ CacheHandler.maybeKVNamespace = process.env["${config.cache.kvBindingName}"];
6971
+ `
6972
+ );
6973
+ if (patchedCode === code) {
6974
+ throw new Error("Cache patch not applied");
6975
+ }
6976
+ return patchedCode;
6977
+ }
6978
+
6979
+ // src/cli/build/build-worker.ts
6980
+ var packageDistDir = path10.join(path10.dirname(fileURLToPath3(import.meta.url)), "..");
6981
+ async function buildWorker(config) {
6982
+ console.log(`\x1B[35m\u2699\uFE0F Copying files...
6983
+ \x1B[0m`);
6984
+ await cp(
6985
+ path10.join(config.paths.dotNext, "static"),
6986
+ path10.join(config.paths.builderOutput, "assets", "_next", "static"),
6987
+ {
6988
+ recursive: true
6989
+ }
6990
+ );
6991
+ const publicDir = path10.join(config.paths.nextApp, "public");
6992
+ if (existsSync3(publicDir)) {
6993
+ await cp(publicDir, path10.join(config.paths.builderOutput, "assets"), {
6994
+ recursive: true
6995
+ });
6996
+ }
6997
+ copyPackageCliFiles(packageDistDir, config);
6998
+ const templateDir = path10.join(config.paths.internalPackage, "cli", "templates");
6999
+ const workerEntrypoint = path10.join(templateDir, "worker.ts");
7000
+ const workerOutputFile = path10.join(config.paths.builderOutput, "index.mjs");
7001
+ const nextConfigStr = readFileSync4(path10.join(config.paths.standaloneApp, "/server.js"), "utf8")?.match(
6978
7002
  /const nextConfig = ({.+?})\n/
6979
7003
  )?.[1] ?? {};
6980
7004
  console.log(`\x1B[35m\u2699\uFE0F Bundling the worker file...
6981
7005
  \x1B[0m`);
6982
- patchWranglerDeps(nextjsAppPaths);
6983
- updateWebpackChunksFile(nextjsAppPaths);
7006
+ patchWranglerDeps(config);
7007
+ updateWebpackChunksFile(config);
6984
7008
  await build({
6985
7009
  entryPoints: [workerEntrypoint],
6986
7010
  bundle: true,
@@ -6993,15 +7017,15 @@ async function buildWorker(inputNextAppDir, outputDir2, nextjsAppPaths, template
6993
7017
  // Note: we apply an empty shim to next/dist/compiled/ws because it generates two `eval`s:
6994
7018
  // eval("require")("bufferutil");
6995
7019
  // eval("require")("utf-8-validate");
6996
- "next/dist/compiled/ws": `${templateDir}/shims/empty.ts`,
7020
+ "next/dist/compiled/ws": path10.join(templateDir, "shims", "empty.ts"),
6997
7021
  // Note: we apply an empty shim to next/dist/compiled/edge-runtime since (amongst others) it generated the following `eval`:
6998
7022
  // eval(getModuleCode)(module, module.exports, throwingRequire, params.context, ...Object.values(params.scopedContext));
6999
7023
  // which comes from https://github.com/vercel/edge-runtime/blob/6e96b55f/packages/primitives/src/primitives/load.js#L57-L63
7000
7024
  // QUESTION: Why did I encountered this but mhart didn't?
7001
- "next/dist/compiled/edge-runtime": `${templateDir}/shims/empty.ts`,
7025
+ "next/dist/compiled/edge-runtime": path10.join(templateDir, "shims", "empty.ts"),
7002
7026
  // `@next/env` is a library Next.js uses for loading dotenv files, for obvious reasons we need to stub it here
7003
7027
  // source: https://github.com/vercel/next.js/tree/0ac10d79720/packages/next-env
7004
- "@next/env": `${templateDir}/shims/env.ts`
7028
+ "@next/env": path10.join(templateDir, "shims", "env.ts")
7005
7029
  },
7006
7030
  define: {
7007
7031
  // config file used by Next.js, see: https://github.com/vercel/next.js/blob/68a7128/packages/next/src/build/utils.ts#L2137-L2139
@@ -7035,22 +7059,21 @@ async function buildWorker(inputNextAppDir, outputDir2, nextjsAppPaths, template
7035
7059
  // Do not crash on cache not supported
7036
7060
  // https://github.com/cloudflare/workerd/pull/2434
7037
7061
  // compatibility flag "cache_option_enabled" -> does not support "force-cache"
7038
- let isPatchedAlready = globalThis.fetch.__nextPatched;
7039
7062
  const curFetch = globalThis.fetch;
7040
7063
  globalThis.fetch = (input, init) => {
7041
- console.log("globalThis.fetch", input);
7042
- if (init) delete init.cache;
7064
+ if (init) {
7065
+ delete init.cache;
7066
+ }
7043
7067
  return curFetch(input, init);
7044
7068
  };
7045
7069
  import { Readable } from 'node:stream';
7046
- globalThis.fetch.__nextPatched = isPatchedAlready;
7047
7070
  fetch = globalThis.fetch;
7048
7071
  const CustomRequest = class extends globalThis.Request {
7049
7072
  constructor(input, init) {
7050
- console.log("CustomRequest", input);
7051
7073
  if (init) {
7052
7074
  delete init.cache;
7053
7075
  if (init.body?.__node_stream__ === true) {
7076
+ // https://github.com/cloudflare/workerd/issues/2746
7054
7077
  init.body = Readable.toWeb(init.body);
7055
7078
  }
7056
7079
  }
@@ -7059,31 +7082,22 @@ const CustomRequest = class extends globalThis.Request {
7059
7082
  };
7060
7083
  globalThis.Request = CustomRequest;
7061
7084
  Request = globalThis.Request;
7062
- `
7085
+ `
7063
7086
  }
7064
7087
  });
7065
- await updateWorkerBundledCode(workerOutputFile, nextjsAppPaths);
7066
- console.log(`\x1B[35m\u2699\uFE0F Copying asset files...
7067
- \x1B[0m`);
7068
- await cp(`${nextjsAppPaths.dotNextDir}/static`, `${outputDir2}/assets/_next/static`, {
7069
- recursive: true
7070
- });
7071
- if (existsSync3(`${inputNextAppDir}/public`)) {
7072
- await cp(`${inputNextAppDir}/public`, `${outputDir2}/assets`, {
7073
- recursive: true
7074
- });
7075
- }
7088
+ await updateWorkerBundledCode(workerOutputFile, config);
7076
7089
  console.log(`\x1B[35mWorker saved in \`${workerOutputFile}\` \u{1F680}
7077
7090
  \x1B[0m`);
7078
7091
  }
7079
- async function updateWorkerBundledCode(workerOutputFile, nextjsAppPaths) {
7092
+ async function updateWorkerBundledCode(workerOutputFile, config) {
7080
7093
  const originalCode = await readFile(workerOutputFile, "utf8");
7081
7094
  let patchedCode = originalCode;
7082
7095
  patchedCode = patchRequire(patchedCode);
7083
- patchedCode = patchReadFile(patchedCode, nextjsAppPaths);
7084
- patchedCode = inlineNextRequire(patchedCode, nextjsAppPaths);
7085
- patchedCode = patchFindDir(patchedCode, nextjsAppPaths);
7086
- patchedCode = inlineEvalManifest(patchedCode, nextjsAppPaths);
7096
+ patchedCode = patchReadFile(patchedCode, config);
7097
+ patchedCode = inlineNextRequire(patchedCode, config);
7098
+ patchedCode = patchFindDir(patchedCode, config);
7099
+ patchedCode = inlineEvalManifest(patchedCode, config);
7100
+ patchedCode = patchCache(patchedCode, config);
7087
7101
  await writeFile(workerOutputFile, patchedCode);
7088
7102
  }
7089
7103
  function createFixRequiresESBuildPlugin(templateDir) {
@@ -7091,97 +7105,102 @@ function createFixRequiresESBuildPlugin(templateDir) {
7091
7105
  name: "replaceRelative",
7092
7106
  setup(build3) {
7093
7107
  build3.onResolve({ filter: /^\.\/require-hook$/ }, (args) => ({
7094
- path: `${templateDir}/shims/empty.ts`
7108
+ path: path10.join(templateDir, "shims", "empty.ts")
7095
7109
  }));
7096
7110
  build3.onResolve({ filter: /\.\/lib\/node-fs-methods$/ }, (args) => ({
7097
- path: `${templateDir}/shims/node-fs.ts`
7111
+ path: path10.join(templateDir, "shims", "empty.ts")
7098
7112
  }));
7099
7113
  }
7100
7114
  };
7101
7115
  }
7102
7116
 
7103
- // src/nextjs-paths.ts
7117
+ // src/cli/config.ts
7104
7118
  import { readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
7105
- import path4, { relative } from "node:path";
7106
- function getNextjsAppPaths(nextAppDir2) {
7107
- const dotNextDir = getDotNextDirPath(nextAppDir2);
7108
- const appPath = getNextjsApplicationPath(dotNextDir).replace(/\/$/, "");
7109
- const standaloneAppDir = path4.join(dotNextDir, "standalone", appPath);
7119
+ import path11, { relative } from "node:path";
7120
+ var PACKAGE_NAME = "@opennextjs/cloudflare";
7121
+ var UserConfig = {
7122
+ cache: {
7123
+ bindingName: "NEXT_CACHE_WORKERS_KV"
7124
+ }
7125
+ };
7126
+ function getConfig(appDir, outputDir2) {
7127
+ const dotNext = path11.join(outputDir2, ".next");
7128
+ const appPath = getNextjsApplicationPath(dotNext).replace(/\/$/, "");
7129
+ const standaloneApp = path11.join(dotNext, "standalone", appPath);
7130
+ const standaloneAppDotNext = path11.join(standaloneApp, ".next");
7131
+ const standaloneAppServer = path11.join(standaloneAppDotNext, "server");
7132
+ const nodeModules = path11.join(standaloneApp, "node_modules");
7133
+ const internalPackage = path11.join(nodeModules, ...PACKAGE_NAME.split("/"));
7110
7134
  return {
7111
- appDir: nextAppDir2,
7112
- dotNextDir,
7113
- standaloneAppDir,
7114
- standaloneAppDotNextDir: path4.join(standaloneAppDir, ".next"),
7115
- standaloneAppServerDir: path4.join(standaloneAppDir, ".next", "server")
7135
+ paths: {
7136
+ nextApp: appDir,
7137
+ builderOutput: outputDir2,
7138
+ dotNext,
7139
+ standaloneApp,
7140
+ standaloneAppDotNext,
7141
+ standaloneAppServer,
7142
+ internalPackage
7143
+ },
7144
+ cache: {
7145
+ kvBindingName: UserConfig.cache.bindingName
7146
+ },
7147
+ internalPackageName: PACKAGE_NAME
7116
7148
  };
7117
7149
  }
7118
- function getDotNextDirPath(nextAppDir2) {
7119
- const dotNextDirPath = `${nextAppDir2}/.next`;
7150
+ function containsDotNextDir(folder) {
7120
7151
  try {
7121
- const dirStats = statSync2(dotNextDirPath);
7122
- if (!dirStats.isDirectory()) throw new Error();
7123
- } catch {
7124
- throw new Error(`Error: \`.next\` directory not found!`);
7152
+ return statSync2(path11.join(folder, ".next")).isDirectory();
7153
+ } catch (e) {
7154
+ return false;
7125
7155
  }
7126
- return dotNextDirPath;
7127
7156
  }
7128
7157
  function getNextjsApplicationPath(dotNextDir) {
7129
7158
  const serverPath = findServerParentPath(dotNextDir);
7130
7159
  if (!serverPath) {
7131
7160
  throw new Error(`Unexpected Error: no \`.next/server\` folder could be found in \`${serverPath}\``);
7132
7161
  }
7133
- return relative(`${dotNextDir}/standalone`, serverPath);
7134
- function findServerParentPath(path6) {
7135
- try {
7136
- if (statSync2(`${path6}/.next/server`).isDirectory()) {
7137
- return path6;
7138
- }
7139
- } catch {
7162
+ return relative(path11.join(dotNextDir, "standalone"), serverPath);
7163
+ }
7164
+ function findServerParentPath(parentPath) {
7165
+ try {
7166
+ if (statSync2(path11.join(parentPath, ".next", "server")).isDirectory()) {
7167
+ return parentPath;
7140
7168
  }
7141
- const files = readdirSync3(path6);
7142
- for (const file of files) {
7143
- if (statSync2(`${path6}/${file}`).isDirectory()) {
7144
- const dirServerPath = findServerParentPath(`${path6}/${file}`);
7145
- if (dirServerPath) {
7146
- return dirServerPath;
7147
- }
7169
+ } catch {
7170
+ }
7171
+ const folders = readdirSync3(parentPath);
7172
+ for (const folder of folders) {
7173
+ const subFolder = path11.join(parentPath, folder);
7174
+ if (statSync2(path11.join(parentPath, folder)).isDirectory()) {
7175
+ const dirServerPath = findServerParentPath(subFolder);
7176
+ if (dirServerPath) {
7177
+ return dirServerPath;
7148
7178
  }
7149
7179
  }
7150
7180
  }
7151
7181
  }
7152
7182
 
7153
- // src/build/build.ts
7154
- import path5 from "node:path";
7155
- import { fileURLToPath as fileURLToPath3 } from "node:url";
7156
- import { cpSync as cpSync2, rmSync } from "node:fs";
7157
- var SAVE_DIR = ".save.next";
7158
- async function build2(inputNextAppDir, opts) {
7183
+ // src/cli/build/index.ts
7184
+ import { cpSync as cpSync2 } from "node:fs";
7185
+ import path12 from "node:path";
7186
+ async function build2(appDir, opts) {
7159
7187
  if (!opts.skipBuild) {
7160
- buildNextjsApp(inputNextAppDir);
7161
- rmSync(`${inputNextAppDir}/${SAVE_DIR}`, {
7162
- recursive: true,
7163
- force: true
7164
- });
7165
- cpSync2(`${inputNextAppDir}/.next`, `${inputNextAppDir}/${SAVE_DIR}`, {
7166
- recursive: true
7167
- });
7168
- } else {
7169
- rmSync(`${inputNextAppDir}/.next`, { recursive: true, force: true });
7170
- cpSync2(`${inputNextAppDir}/${SAVE_DIR}`, `${inputNextAppDir}/.next`, {
7171
- recursive: true
7172
- });
7188
+ buildNextjsApp(appDir);
7189
+ }
7190
+ if (!containsDotNextDir(appDir)) {
7191
+ throw new Error(`.next folder not found in ${appDir}`);
7173
7192
  }
7174
- const outputDir2 = `${opts.outputDir ?? inputNextAppDir}/.worker-next`;
7193
+ const outputDir2 = path12.resolve(opts.outputDir ?? appDir, ".worker-next");
7175
7194
  await cleanDirectory(outputDir2);
7176
- const nextjsAppPaths = getNextjsAppPaths(inputNextAppDir);
7177
- const templateDir = path5.join(path5.dirname(fileURLToPath3(import.meta.url)), "templates");
7178
- await buildWorker(inputNextAppDir, outputDir2, nextjsAppPaths, templateDir);
7195
+ cpSync2(path12.join(appDir, ".next"), path12.join(outputDir2, ".next"), { recursive: true });
7196
+ const config = getConfig(appDir, outputDir2);
7197
+ await buildWorker(config);
7179
7198
  }
7180
- async function cleanDirectory(path6) {
7181
- return await rm(path6, { recursive: true, force: true });
7199
+ async function cleanDirectory(path13) {
7200
+ return await rm(path13, { recursive: true, force: true });
7182
7201
  }
7183
7202
 
7184
- // src/index.ts
7203
+ // src/cli/index.ts
7185
7204
  var nextAppDir = resolve2(".");
7186
7205
  console.log(`Building the Next.js app in the current folder (${nextAppDir})`);
7187
7206
  if (!["js", "cjs", "mjs", "ts"].some((ext2) => existsSync4(`./next.config.${ext2}`))) {
@@ -1,46 +1,64 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
1
2
  import Stream from "node:stream";
2
3
  import type { NextConfig } from "next";
3
4
  import { NodeNextRequest, NodeNextResponse } from "next/dist/server/base-http/node";
4
5
  import { MockedResponse } from "next/dist/server/lib/mock-request";
5
6
  import NextNodeServer, { NodeRequestHandler } from "next/dist/server/next-server";
6
7
  import type { IncomingMessage } from "node:http";
8
+ import { type CloudflareContext } from "../../api";
7
9
 
8
10
  const NON_BODY_RESPONSES = new Set([101, 204, 205, 304]);
9
11
 
12
+ const cloudflareContextALS = new AsyncLocalStorage<CloudflareContext>();
13
+
14
+ // Note: this symbol needs to be kept in sync with the one defined in `src/api/get-cloudflare-context.ts`
15
+ (globalThis as any)[Symbol.for("__cloudflare-context__")] = new Proxy(
16
+ {},
17
+ {
18
+ ownKeys: () => Reflect.ownKeys(cloudflareContextALS.getStore()!),
19
+ getOwnPropertyDescriptor: (_, ...args) =>
20
+ Reflect.getOwnPropertyDescriptor(cloudflareContextALS.getStore()!, ...args),
21
+ get: (_, property) => Reflect.get(cloudflareContextALS.getStore()!, property),
22
+ set: (_, property, value) => Reflect.set(cloudflareContextALS.getStore()!, property, value),
23
+ }
24
+ );
25
+
10
26
  // Injected at build time
11
27
  const nextConfig: NextConfig = JSON.parse(process.env.__NEXT_PRIVATE_STANDALONE_CONFIG ?? "{}");
12
28
 
13
29
  let requestHandler: NodeRequestHandler | null = null;
14
30
 
15
31
  export default {
16
- async fetch(request: Request, env: any, ctx: any) {
17
- if (requestHandler == null) {
18
- globalThis.process.env = { ...globalThis.process.env, ...env };
19
- requestHandler = new NextNodeServer({
20
- conf: { ...nextConfig, env },
21
- customServer: false,
22
- dev: false,
23
- dir: "",
24
- minimalMode: false,
25
- }).getRequestHandler();
26
- }
27
-
28
- const url = new URL(request.url);
29
-
30
- if (url.pathname === "/_next/image") {
31
- let imageUrl =
32
- url.searchParams.get("url") ?? "https://developers.cloudflare.com/_astro/logo.BU9hiExz.svg";
33
- if (imageUrl.startsWith("/")) {
34
- return env.ASSETS.fetch(new URL(imageUrl, request.url));
32
+ async fetch(request: Request & { cf: IncomingRequestCfProperties }, env: any, ctx: any) {
33
+ return cloudflareContextALS.run({ env, ctx, cf: request.cf }, async () => {
34
+ if (requestHandler == null) {
35
+ globalThis.process.env = { ...globalThis.process.env, ...env };
36
+ requestHandler = new NextNodeServer({
37
+ conf: { ...nextConfig, env },
38
+ customServer: false,
39
+ dev: false,
40
+ dir: "",
41
+ minimalMode: false,
42
+ }).getRequestHandler();
43
+ }
44
+
45
+ const url = new URL(request.url);
46
+
47
+ if (url.pathname === "/_next/image") {
48
+ let imageUrl =
49
+ url.searchParams.get("url") ?? "https://developers.cloudflare.com/_astro/logo.BU9hiExz.svg";
50
+ if (imageUrl.startsWith("/")) {
51
+ return env.ASSETS.fetch(new URL(imageUrl, request.url));
52
+ }
53
+ return fetch(imageUrl, { cf: { cacheEverything: true } } as any);
35
54
  }
36
- return fetch(imageUrl, { cf: { cacheEverything: true } } as any);
37
- }
38
55
 
39
- const { req, res, webResponse } = getWrappedStreams(request, ctx);
56
+ const { req, res, webResponse } = getWrappedStreams(request, ctx);
40
57
 
41
- ctx.waitUntil(requestHandler(new NodeNextRequest(req), new NodeNextResponse(res)));
58
+ ctx.waitUntil(requestHandler(new NodeNextRequest(req), new NodeNextResponse(res)));
42
59
 
43
- return await webResponse();
60
+ return await webResponse();
61
+ });
44
62
  },
45
63
  };
46
64
 
@@ -102,7 +120,6 @@ function getWrappedStreams(request: Request, ctx: any) {
102
120
  },
103
121
  set: function (val) {
104
122
  if (this.finished || this.headersSent) {
105
- console.error("headers already sent");
106
123
  return;
107
124
  }
108
125
  statusCode = val;
package/package.json CHANGED
@@ -1,8 +1,16 @@
1
1
  {
2
2
  "name": "@opennextjs/cloudflare",
3
3
  "description": "Cloudflare builder for next apps",
4
- "version": "0.0.0-e2c4535",
5
- "bin": "dist/index.mjs",
4
+ "version": "0.0.0-e62af72",
5
+ "bin": "dist/cli/index.mjs",
6
+ "main": "./dist/api/index.mjs",
7
+ "types": "./dist/api/index.d.mts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/api/index.mjs",
11
+ "types": "./dist/api/index.d.mts"
12
+ }
13
+ },
6
14
  "files": [
7
15
  "README.md",
8
16
  "dist"
@@ -23,9 +31,11 @@
23
31
  },
24
32
  "homepage": "https://github.com/opennextjs/opennextjs-cloudflare",
25
33
  "devDependencies": {
34
+ "@cloudflare/workers-types": "^4.20240919.0",
26
35
  "@types/node": "^22.2.0",
27
36
  "esbuild": "^0.23.0",
28
37
  "glob": "^11.0.0",
38
+ "next": "14.2.11",
29
39
  "tsup": "^8.2.4",
30
40
  "typescript": "^5.5.4",
31
41
  "vitest": "^2.1.1"
@@ -33,6 +43,9 @@
33
43
  "dependencies": {
34
44
  "ts-morph": "^23.0.0"
35
45
  },
46
+ "peerDependencies": {
47
+ "wrangler": "^3.78.6"
48
+ },
36
49
  "scripts": {
37
50
  "build": "tsup",
38
51
  "build:watch": "tsup --watch src",
File without changes