@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
@@ -1,60 +1,30 @@
1
- import { readFileSync, statSync, writeFileSync } from "node:fs";
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { getPackagePath } from "@opennextjs/aws/build/helper.js";
3
4
  import * as ts from "ts-morph";
4
5
  import { tsParseFile } from "../../utils/index.js";
5
- export function patchWranglerDeps(config) {
6
+ export function patchWranglerDeps(buildOpts) {
6
7
  console.log("# patchWranglerDeps");
7
- const distPath = getDistPath(config);
8
- // Patch .next/standalone/node_modules/next/dist/compiled/next-server/pages.runtime.prod.js
9
- //
10
- // Remove the need for an alias in wrangler.toml:
11
- //
12
- // [alias]
13
- // # critters is `require`d from `pages.runtime.prod.js` when running wrangler dev, so we need to stub it out
14
- // "critters" = "./.next/standalone/node_modules/cf/templates/shims/empty.ts"
15
- const pagesRuntimeFile = join(distPath, "compiled/next-server/pages.runtime.prod.js");
16
- const patchedPagesRuntime = readFileSync(pagesRuntimeFile, "utf-8").replace(`e.exports=require("critters")`, `e.exports={}`);
8
+ const { outputDir } = buildOpts;
9
+ const nextDistDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), "node_modules/next/dist");
10
+ const pagesRuntimeFile = join(nextDistDir, "compiled/next-server/pages.runtime.prod.js");
11
+ const patchedPagesRuntime = readFileSync(pagesRuntimeFile, "utf-8").replace(`e.exports=require("critters")`, `
12
+ try {
13
+ e.exports=require("critters");
14
+ }
15
+ catch {
16
+ console.error('critters is not installed');
17
+ }
18
+ `);
17
19
  writeFileSync(pagesRuntimeFile, patchedPagesRuntime);
18
- patchRequireReactDomServerEdge(config);
19
- // Patch .next/standalone/node_modules/next/dist/server/lib/trace/tracer.js
20
- //
21
- // Remove the need for an alias in wrangler.toml:
22
- //
23
- // [alias]
24
- // # @opentelemetry/api is `require`d when running wrangler dev, so we need to stub it out
25
- // # IMPORTANT: we shim @opentelemetry/api to the throwing shim so that it will throw right away, this is so that we throw inside the
26
- // # try block here: https://github.com/vercel/next.js/blob/9e8266a7/packages/next/src/server/lib/trace/tracer.ts#L27-L31
27
- // # causing the code to require the 'next/dist/compiled/@opentelemetry/api' module instead (which properly works)
28
- // #"@opentelemetry/api" = "./.next/standalone/node_modules/cf/templates/shims/throw.ts"
29
- const tracerFile = join(distPath, "server/lib/trace/tracer.js");
20
+ patchRequireReactDomServerEdge(nextDistDir);
21
+ // we shim @opentelemetry/api to the throwing shim so that it will throw right away, this is so that we throw inside the
22
+ // try block here: https://github.com/vercel/next.js/blob/9e8266a7/packages/next/src/server/lib/trace/tracer.ts#L27-L31
23
+ // causing the code to require the 'next/dist/compiled/@opentelemetry/api' module instead (which properly works)
24
+ const tracerFile = join(nextDistDir, "server/lib/trace/tracer.js");
30
25
  const patchedTracer = readFileSync(tracerFile, "utf-8").replaceAll(/\w+\s*=\s*require\([^/]*opentelemetry.*\)/g, `throw new Error("@opentelemetry/api")`);
31
26
  writeFileSync(tracerFile, patchedTracer);
32
27
  }
33
- /**
34
- * Next.js saves the node_modules/next/dist directory in either the standaloneApp path or in the
35
- * standaloneRoot path, this depends on where the next dependency is actually saved (
36
- * https://github.com/vercel/next.js/blob/39e06c75/packages/next/src/build/webpack-config.ts#L103-L104
37
- * ) and can depend on the package manager used, if it is using workspaces, etc...
38
- *
39
- * This function checks the two potential paths for the dist directory and returns the first that it finds,
40
- * it throws an error if it can't find either
41
- *
42
- * @param config
43
- * @returns the node_modules/next/dist directory path
44
- */
45
- function getDistPath(config) {
46
- for (const root of [config.paths.output.standaloneApp, config.paths.output.standaloneRoot]) {
47
- try {
48
- const distPath = join(root, "node_modules/next/dist");
49
- if (statSync(distPath).isDirectory())
50
- return distPath;
51
- }
52
- catch {
53
- /* empty */
54
- }
55
- }
56
- throw new Error("Unexpected error: unable to detect the node_modules/next/dist directory");
57
- }
58
28
  /**
59
29
  * `react-dom` v>=19 has a `server.edge` export: https://github.com/facebook/react/blob/a160102f3/packages/react-dom/package.json#L79
60
30
  * but version of `react-dom` <= 18 do not have this export but have a `server.browser` export instead: https://github.com/facebook/react/blob/8a015b68/packages/react-dom/package.json#L49
@@ -70,10 +40,9 @@ function getDistPath(config) {
70
40
  * it's not clear what code and how might be rely on this require call)
71
41
  *
72
42
  */
73
- function patchRequireReactDomServerEdge(config) {
74
- const distPath = getDistPath(config);
43
+ function patchRequireReactDomServerEdge(nextDistDir) {
75
44
  // Patch .next/standalone/node_modules/next/dist/compiled/next-server/pages.runtime.prod.js
76
- const pagesRuntimeFile = join(distPath, "compiled/next-server/pages.runtime.prod.js");
45
+ const pagesRuntimeFile = join(nextDistDir, "compiled/next-server/pages.runtime.prod.js");
77
46
  const code = readFileSync(pagesRuntimeFile, "utf-8");
78
47
  const file = tsParseFile(code);
79
48
  // we need to update this function: `e=>{"use strict";e.exports=require("react-dom/server.edge")}`
@@ -125,21 +94,21 @@ function patchRequireReactDomServerEdge(config) {
125
94
  return;
126
95
  }
127
96
  arrowFunction.setBodyText(`
128
- "use strict";
129
- let ReactDOMServer;
130
- try {
131
- ReactDOMServer = require('react-dom/server.edge');
132
- } catch (error) {
133
- if (
134
- error.code !== 'MODULE_NOT_FOUND' &&
135
- error.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED'
136
- ) {
137
- throw error;
138
- }
139
- ReactDOMServer = require('react-dom/server.browser');
140
- }
141
- ${parameterName}.exports = ReactDOMServer;
142
- `.replace(/\ns*/g, " "));
97
+ // OpenNext patch
98
+ let ReactDOMServer;
99
+ try {
100
+ ReactDOMServer = require('react-dom/server.edge');
101
+ } catch (error) {
102
+ if (
103
+ error.code !== 'MODULE_NOT_FOUND' &&
104
+ error.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED'
105
+ ) {
106
+ throw error;
107
+ }
108
+ ReactDOMServer = require('react-dom/server.browser');
109
+ }
110
+ ${parameterName}.exports = ReactDOMServer;
111
+ `);
143
112
  });
144
113
  const updatedCode = file.print();
145
114
  writeFileSync(pagesRuntimeFile, updatedCode);
@@ -1,4 +1,4 @@
1
- import type { ProjectOptions } from "../../config.js";
1
+ import type { ProjectOptions } from "../../project-options.js";
2
2
  /**
3
3
  * Creates a `wrangler.json` file for the user if a wrangler config file doesn't already exist,
4
4
  * but only after asking for the user's confirmation.
@@ -0,0 +1,7 @@
1
+ export type ProjectOptions = {
2
+ sourceDir: string;
3
+ outputDir: string;
4
+ skipNextBuild: boolean;
5
+ skipWranglerConfigCheck: boolean;
6
+ minify: boolean;
7
+ };
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@opennextjs/cloudflare",
3
3
  "description": "Cloudflare builder for next apps",
4
- "version": "0.3.10",
4
+ "version": "0.4.0",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "opennextjs-cloudflare": "dist/cli/index.js"
@@ -61,16 +61,16 @@
61
61
  "vitest": "^2.1.1"
62
62
  },
63
63
  "dependencies": {
64
- "@ast-grep/napi": "^0.33.1",
64
+ "@ast-grep/napi": "^0.34.1",
65
65
  "@dotenvx/dotenvx": "1.31.0",
66
- "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@704",
66
+ "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@712",
67
67
  "enquirer": "^2.4.1",
68
68
  "glob": "^11.0.0",
69
69
  "ts-morph": "^23.0.0",
70
70
  "yaml": "^2.7.0"
71
71
  },
72
72
  "peerDependencies": {
73
- "wrangler": "^3.103.0"
73
+ "wrangler": "^3.105.0"
74
74
  },
75
75
  "scripts": {
76
76
  "clean": "rimraf dist",
@@ -1,42 +0,0 @@
1
- // Note: this symbol needs to be kept in sync with the one used in `src/cli/templates/worker.ts`
2
- const cloudflareContextSymbol = Symbol.for("__cloudflare-context__");
3
- /**
4
- * Utility to get the current Cloudflare context
5
- *
6
- * @returns the cloudflare context
7
- */
8
- export async function getCloudflareContext() {
9
- const global = globalThis;
10
- const cloudflareContext = global[cloudflareContextSymbol];
11
- if (!cloudflareContext) {
12
- // the cloudflare context is initialized by the worker and is always present in production/preview,
13
- // so, it not being present means that the application is running under `next dev`
14
- return getCloudflareContextInNextDev();
15
- }
16
- return cloudflareContext;
17
- }
18
- const cloudflareContextInNextDevSymbol = Symbol.for("__next-dev/cloudflare-context__");
19
- /**
20
- * Gets a local proxy version of the cloudflare context (created using `getPlatformProxy`) when
21
- * running in the standard next dev server (via `next dev`)
22
- *
23
- * @returns the local proxy version of the cloudflare context
24
- */
25
- async function getCloudflareContextInNextDev() {
26
- const global = globalThis;
27
- if (!global[cloudflareContextInNextDevSymbol]) {
28
- // Note: we never want wrangler to be bundled in the Next.js app, that's why the import below looks like it does
29
- const { getPlatformProxy } = await import(
30
- /* webpackIgnore: true */ `${"__wrangler".replaceAll("_", "")}`);
31
- const { env, cf, ctx } = await getPlatformProxy({
32
- // This allows the selection of a wrangler environment while running in next dev mode
33
- environment: process.env.NEXT_DEV_WRANGLER_ENV,
34
- });
35
- global[cloudflareContextInNextDevSymbol] = {
36
- env,
37
- cf: cf,
38
- ctx: ctx,
39
- };
40
- }
41
- return global[cloudflareContextInNextDevSymbol];
42
- }
@@ -1,42 +0,0 @@
1
- export type Config = {
2
- build: {
3
- skipNextBuild: boolean;
4
- shouldMinify: boolean;
5
- };
6
- paths: {
7
- source: {
8
- root: string;
9
- dotNext: string;
10
- standaloneRoot: string;
11
- };
12
- output: {
13
- root: string;
14
- assets: string;
15
- dotNext: string;
16
- standaloneRoot: string;
17
- standaloneApp: string;
18
- standaloneAppDotNext: string;
19
- standaloneAppServer: string;
20
- };
21
- internal: {
22
- package: string;
23
- templates: string;
24
- };
25
- };
26
- internalPackageName: string;
27
- };
28
- /**
29
- * Computes the configuration.
30
- *
31
- * @param projectOpts The options for the project
32
- * @returns The configuration, see `Config`
33
- */
34
- export declare function getConfig(projectOpts: ProjectOptions): Config;
35
- export declare function containsDotNextDir(folder: string): boolean;
36
- export type ProjectOptions = {
37
- sourceDir: string;
38
- outputDir: string;
39
- skipNextBuild: boolean;
40
- skipWranglerConfigCheck: boolean;
41
- minify: boolean;
42
- };
@@ -1,92 +0,0 @@
1
- import { readdirSync, statSync } from "node:fs";
2
- import { join, relative } from "node:path";
3
- const PACKAGE_NAME = "@opennextjs/cloudflare";
4
- /**
5
- * Computes the configuration.
6
- *
7
- * @param projectOpts The options for the project
8
- * @returns The configuration, see `Config`
9
- */
10
- export function getConfig(projectOpts) {
11
- const sourceDirDotNext = join(projectOpts.sourceDir, ".next");
12
- const dotNext = join(projectOpts.outputDir, ".next");
13
- const appPath = getNextjsApplicationPath(dotNext).replace(/\/$/, "");
14
- const standaloneRoot = join(dotNext, "standalone");
15
- const standaloneApp = join(standaloneRoot, appPath);
16
- const standaloneAppDotNext = join(standaloneApp, ".next");
17
- const standaloneAppServer = join(standaloneAppDotNext, "server");
18
- const nodeModules = join(standaloneApp, "node_modules");
19
- const internalPackage = join(nodeModules, ...PACKAGE_NAME.split("/"));
20
- const internalTemplates = join(internalPackage, "cli/templates");
21
- return {
22
- build: {
23
- skipNextBuild: projectOpts.skipNextBuild,
24
- shouldMinify: projectOpts.minify,
25
- },
26
- paths: {
27
- source: {
28
- root: projectOpts.sourceDir,
29
- dotNext: sourceDirDotNext,
30
- standaloneRoot: join(sourceDirDotNext, "standalone"),
31
- },
32
- output: {
33
- root: projectOpts.outputDir,
34
- assets: join(projectOpts.outputDir, "assets"),
35
- dotNext,
36
- standaloneRoot,
37
- standaloneApp,
38
- standaloneAppDotNext,
39
- standaloneAppServer,
40
- },
41
- internal: {
42
- package: internalPackage,
43
- templates: internalTemplates,
44
- },
45
- },
46
- internalPackageName: PACKAGE_NAME,
47
- };
48
- }
49
- export function containsDotNextDir(folder) {
50
- try {
51
- return statSync(join(folder, ".next")).isDirectory();
52
- }
53
- catch {
54
- return false;
55
- }
56
- }
57
- /**
58
- * It basically tries to find the path that the application is under inside the `.next/standalone` directory, using the `.next/server` directory
59
- * presence as the condition that needs to be met.
60
- *
61
- * For example:
62
- * When I build the api application the `.next/server` directory is located in:
63
- * `<dotNextDir>/standalone/next-apps/api/.next/server`
64
- * and the function here given the `dotNextDir` returns `next-apps/api`
65
- */
66
- function getNextjsApplicationPath(dotNextDir) {
67
- const serverPath = findServerParentPath(dotNextDir);
68
- if (!serverPath) {
69
- throw new Error(`Unexpected Error: no \`.next/server\` folder could be found in \`${serverPath}\``);
70
- }
71
- return relative(join(dotNextDir, "standalone"), serverPath);
72
- }
73
- function findServerParentPath(parentPath) {
74
- try {
75
- if (statSync(join(parentPath, ".next/server")).isDirectory()) {
76
- return parentPath;
77
- }
78
- }
79
- catch {
80
- /* empty */
81
- }
82
- const folders = readdirSync(parentPath);
83
- for (const folder of folders) {
84
- const subFolder = join(parentPath, folder);
85
- if (statSync(join(parentPath, folder)).isDirectory()) {
86
- const dirServerPath = findServerParentPath(subFolder);
87
- if (dirServerPath) {
88
- return dirServerPath;
89
- }
90
- }
91
- }
92
- }