@opennextjs/cloudflare 0.3.0 → 0.3.2

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.
@@ -82,13 +82,12 @@ fetch = globalThis.fetch;
82
82
  const CustomRequest = class extends globalThis.Request {
83
83
  constructor(input, init) {
84
84
  if (init) {
85
- init = {
86
- ...init,
87
- cache: undefined,
88
- // https://github.com/cloudflare/workerd/issues/2746
89
- // https://github.com/cloudflare/workerd/issues/3245
90
- body: init.body instanceof __cf_stream.Readable ? ReadableStream.from(init.body) : init.body,
91
- };
85
+ init.cache = undefined;
86
+ // https://github.com/cloudflare/workerd/issues/2746
87
+ // https://github.com/cloudflare/workerd/issues/3245
88
+ Object.defineProperty(init, "body", {
89
+ value: init.body instanceof __cf_stream.Readable ? ReadableStream.from(init.body) : init.body;
90
+ });
92
91
  }
93
92
  super(input, init);
94
93
  }
@@ -1,4 +1,4 @@
1
- import { cpSync } from "node:fs";
1
+ import { cpSync, existsSync } from "node:fs";
2
2
  import { createRequire } from "node:module";
3
3
  import { dirname, join } from "node:path";
4
4
  import { buildNextjsApp, setStandaloneBuildMode } from "@opennextjs/aws/build/buildNextApp.js";
@@ -9,7 +9,9 @@ import { createMiddleware } from "@opennextjs/aws/build/createMiddleware.js";
9
9
  import * as buildHelper from "@opennextjs/aws/build/helper.js";
10
10
  import { printHeader, showWarningOnWindows } from "@opennextjs/aws/build/utils.js";
11
11
  import logger from "@opennextjs/aws/logger.js";
12
+ import { getPackageTemplatesDirPath } from "../../utils/get-package-templates-dir-path.js";
12
13
  import { containsDotNextDir, getConfig } from "../config.js";
14
+ import { askConfirmation } from "../utils/ask-confirmation.js";
13
15
  import { bundleServer } from "./bundle-server.js";
14
16
  import { compileEnvFiles } from "./open-next/compile-env-files.js";
15
17
  import { copyCacheAssets } from "./open-next/copyCacheAssets.js";
@@ -27,6 +29,7 @@ export async function build(projectOpts) {
27
29
  const baseDir = projectOpts.sourceDir;
28
30
  const require = createRequire(import.meta.url);
29
31
  const openNextDistDir = dirname(require.resolve("@opennextjs/aws/index.js"));
32
+ await createOpenNextConfigIfNotExistent(projectOpts);
30
33
  const { config, buildDir } = await compileOpenNextConfig(baseDir);
31
34
  ensureCloudflareConfig(config);
32
35
  // Initialize options
@@ -75,6 +78,23 @@ export async function build(projectOpts) {
75
78
  await bundleServer(projConfig, options);
76
79
  logger.info("OpenNext build complete.");
77
80
  }
81
+ /**
82
+ * Creates a `open-next.config.ts` file for the user if it doesn't exist, but only after asking for the user's confirmation.
83
+ *
84
+ * If the user refuses an error is thrown (since the file is mandatory).
85
+ *
86
+ * @param projectOpts The options for the project
87
+ */
88
+ async function createOpenNextConfigIfNotExistent(projectOpts) {
89
+ const openNextConfigPath = join(projectOpts.sourceDir, "open-next.config.ts");
90
+ if (!existsSync(openNextConfigPath)) {
91
+ const answer = await askConfirmation("Missing required `open-next.config.ts` file, do you want to create one?");
92
+ if (!answer) {
93
+ throw new Error("The `open-next.config.ts` file is required, aborting!");
94
+ }
95
+ cpSync(join(getPackageTemplatesDirPath(), "defaults", "open-next.config.ts"), openNextConfigPath);
96
+ }
97
+ }
78
98
  /**
79
99
  * Ensures open next is configured for cloudflare.
80
100
  *
@@ -94,30 +114,30 @@ function ensureCloudflareConfig(config) {
94
114
  mwUseFetchProxy: config.middleware?.override?.proxyExternalRequest === "fetch",
95
115
  };
96
116
  if (Object.values(requirements).some((satisfied) => !satisfied)) {
97
- throw new Error(`open-next.config.ts should contain:
98
- {
99
- default: {
100
- override: {
101
- wrapper: "cloudflare-node",
102
- converter: "edge",
103
- incrementalCache: "dummy" | function,
104
- tagCache: "dummy",
105
- queue: "dummy",
106
- },
107
- },
117
+ throw new Error("The `open-next.config.ts` should have a default export like this:\n\n" +
118
+ `{
119
+ default: {
120
+ override: {
121
+ wrapper: "cloudflare-node",
122
+ converter: "edge",
123
+ incrementalCache: "dummy" | function,
124
+ tagCache: "dummy",
125
+ queue: "dummy",
126
+ },
127
+ },
108
128
 
109
- middleware: {
110
- external: true,
111
- override: {
112
- wrapper: "cloudflare-edge",
113
- converter: "edge",
114
- proxyExternalRequest: "fetch",
115
- },
116
- },
129
+ middleware: {
130
+ external: true,
131
+ override: {
132
+ wrapper: "cloudflare-edge",
133
+ converter: "edge",
134
+ proxyExternalRequest: "fetch",
135
+ },
136
+ },
117
137
 
118
- "dangerous": {
119
- "enableCacheInterception": false
120
- }
121
- }`);
138
+ "dangerous": {
139
+ "enableCacheInterception": false
140
+ },
141
+ }\n\n`.replace(/^ {8}/gm, ""));
122
142
  }
123
143
  }
@@ -0,0 +1 @@
1
+ export declare function askConfirmation(message: string): Promise<boolean>;
@@ -0,0 +1,13 @@
1
+ import Enquirer from "enquirer";
2
+ export async function askConfirmation(message) {
3
+ const questionName = crypto.randomUUID();
4
+ const enquirerAnswersObject = await Enquirer.prompt({
5
+ name: questionName,
6
+ message,
7
+ type: "confirm",
8
+ initial: "y",
9
+ });
10
+ console.log("");
11
+ const answer = !!enquirerAnswersObject[questionName];
12
+ return answer;
13
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Utility for getting the resolved path to the package's templates directory
3
+ *
4
+ * @returns the resolved path of the templates directory
5
+ */
6
+ export declare function getPackageTemplatesDirPath(): string;
@@ -0,0 +1,10 @@
1
+ import * as path from "node:path";
2
+ const templatesDirPath = path.resolve(`${import.meta.dirname}/../../templates`);
3
+ /**
4
+ * Utility for getting the resolved path to the package's templates directory
5
+ *
6
+ * @returns the resolved path of the templates directory
7
+ */
8
+ export function getPackageTemplatesDirPath() {
9
+ return templatesDirPath;
10
+ }
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.0",
4
+ "version": "0.3.2",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "opennextjs-cloudflare": "dist/cli/index.js"
@@ -22,7 +22,8 @@
22
22
  },
23
23
  "files": [
24
24
  "README.md",
25
- "dist"
25
+ "dist",
26
+ "templates"
26
27
  ],
27
28
  "repository": {
28
29
  "type": "git",
@@ -44,29 +45,29 @@
44
45
  "@cloudflare/workers-types": "^4.20240925.0",
45
46
  "@eslint/js": "^9.11.1",
46
47
  "@tsconfig/strictest": "^2.0.5",
48
+ "@types/mock-fs": "^4.13.4",
47
49
  "@types/node": "^22.2.0",
48
50
  "esbuild": "^0.23.0",
49
- "eslint": "^9.11.1",
50
51
  "eslint-plugin-import": "^2.31.0",
51
52
  "eslint-plugin-simple-import-sort": "^12.1.1",
52
53
  "eslint-plugin-unicorn": "^55.0.0",
53
- "glob": "^11.0.0",
54
+ "eslint": "^9.11.1",
54
55
  "globals": "^15.9.0",
56
+ "mock-fs": "^5.4.1",
55
57
  "next": "14.2.11",
56
- "package-manager-detector": "^0.2.0",
57
- "typescript": "^5.5.4",
58
58
  "typescript-eslint": "^8.7.0",
59
- "vitest": "^2.1.1",
60
- "mock-fs": "^5.4.1",
61
- "@types/mock-fs": "^4.13.4"
59
+ "typescript": "^5.5.4",
60
+ "vitest": "^2.1.1"
62
61
  },
63
62
  "dependencies": {
63
+ "@dotenvx/dotenvx": "1.31.0",
64
64
  "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@684",
65
+ "glob": "^11.0.0",
66
+ "rimraf": "^6.0.1",
65
67
  "ts-morph": "^23.0.0",
66
- "@dotenvx/dotenvx": "1.31.0"
68
+ "enquirer": "^2.4.1"
67
69
  },
68
70
  "peerDependencies": {
69
- "rimraf": "^6.0.1",
70
71
  "wrangler": "^3.99.0"
71
72
  },
72
73
  "scripts": {
@@ -0,0 +1,30 @@
1
+ // default open-next.config.ts file created by @opennextjs/cloudflare
2
+
3
+ import cache from "@opennextjs/cloudflare/kvCache";
4
+
5
+ const config = {
6
+ default: {
7
+ override: {
8
+ wrapper: "cloudflare-node",
9
+ converter: "edge",
10
+ incrementalCache: async () => cache,
11
+ tagCache: "dummy",
12
+ queue: "dummy",
13
+ },
14
+ },
15
+
16
+ middleware: {
17
+ external: true,
18
+ override: {
19
+ wrapper: "cloudflare-edge",
20
+ converter: "edge",
21
+ proxyExternalRequest: "fetch",
22
+ },
23
+ },
24
+
25
+ dangerous: {
26
+ enableCacheInterception: false,
27
+ },
28
+ };
29
+
30
+ export default config;