@opennextjs/cloudflare 0.3.3 → 0.3.4

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.
@@ -1,5 +1,6 @@
1
1
  export declare function getArgs(): {
2
2
  skipNextBuild: boolean;
3
+ skipWranglerConfigCheck: boolean;
3
4
  outputDir?: string;
4
5
  minify: boolean;
5
6
  };
package/dist/cli/args.js CHANGED
@@ -2,7 +2,7 @@ import { mkdirSync, statSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
3
  import { parseArgs } from "node:util";
4
4
  export function getArgs() {
5
- const { skipBuild, output, noMinify } = parseArgs({
5
+ const { skipBuild, skipWranglerConfigCheck, output, noMinify } = parseArgs({
6
6
  options: {
7
7
  skipBuild: {
8
8
  type: "boolean",
@@ -17,6 +17,10 @@ export function getArgs() {
17
17
  type: "boolean",
18
18
  default: false,
19
19
  },
20
+ skipWranglerConfigCheck: {
21
+ type: "boolean",
22
+ default: false,
23
+ },
20
24
  },
21
25
  allowPositionals: false,
22
26
  }).values;
@@ -27,6 +31,8 @@ export function getArgs() {
27
31
  return {
28
32
  outputDir,
29
33
  skipNextBuild: skipBuild || ["1", "true", "yes"].includes(String(process.env.SKIP_NEXT_APP_BUILD)),
34
+ skipWranglerConfigCheck: skipWranglerConfigCheck ||
35
+ ["1", "true", "yes"].includes(String(process.env.SKIP_WRANGLER_CONFIG_CHECK)),
30
36
  minify: !noMinify,
31
37
  };
32
38
  }
@@ -7,3 +7,4 @@ import type { ProjectOptions } from "../config.js";
7
7
  * @param projectOpts The options for the project
8
8
  */
9
9
  export declare function build(projectOpts: ProjectOptions): Promise<void>;
10
+ export declare function getLatestCompatDate(): Promise<string | undefined>;
@@ -1,4 +1,4 @@
1
- import { cpSync, existsSync } from "node:fs";
1
+ import { cpSync, existsSync, readFileSync, writeFileSync } 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";
@@ -76,6 +76,9 @@ export async function build(projectOpts) {
76
76
  const projConfig = getConfig(projectOpts);
77
77
  // TODO: rely on options only.
78
78
  await bundleServer(projConfig, options);
79
+ if (!projectOpts.skipWranglerConfigCheck) {
80
+ await createWranglerConfigIfNotExistent(projectOpts);
81
+ }
79
82
  logger.info("OpenNext build complete.");
80
83
  }
81
84
  /**
@@ -141,3 +144,68 @@ function ensureCloudflareConfig(config) {
141
144
  }\n\n`.replace(/^ {8}/gm, ""));
142
145
  }
143
146
  }
147
+ /**
148
+ * Creates a `wrangler.json` file for the user if a wrangler config file doesn't already exist,
149
+ * but only after asking for the user's confirmation.
150
+ *
151
+ * If the user refuses a warning is shown (which offers ways to opt out of this check to the user).
152
+ *
153
+ * Note: we generate a wrangler.json file with comments instead of using the jsonc extension,
154
+ * we decided to do that since json is more common than jsonc, wrangler also parses
155
+ * them in the same way and we also expect developers to associate `wrangler.json`
156
+ * files to the jsonc language
157
+ *
158
+ * @param projectOpts The options for the project
159
+ */
160
+ async function createWranglerConfigIfNotExistent(projectOpts) {
161
+ const possibleExts = ["toml", "json", "jsonc"];
162
+ const wranglerConfigFileExists = possibleExts.some((ext) => existsSync(join(projectOpts.sourceDir, `wrangler.${ext}`)));
163
+ if (wranglerConfigFileExists) {
164
+ return;
165
+ }
166
+ const answer = await askConfirmation("No `wrangler.(toml|json|jsonc)` config file found, do you want to create one?");
167
+ if (!answer) {
168
+ console.warn("No Wrangler config file created" +
169
+ "\n" +
170
+ "(to avoid this check use the `--skipWranglerConfigCheck` flag or set a `SKIP_WRANGLER_CONFIG_CHECK` environment variable to `yes`)");
171
+ return;
172
+ }
173
+ const wranglerConfigTemplate = readFileSync(join(getPackageTemplatesDirPath(), "defaults", "wrangler.jsonc"), "utf8");
174
+ let wranglerConfigContent = wranglerConfigTemplate;
175
+ const appName = getAppNameFromPackageJson(projectOpts.sourceDir) ?? "app-name";
176
+ if (appName) {
177
+ wranglerConfigContent = wranglerConfigContent.replace('"app-name"', JSON.stringify(appName.replaceAll("_", "-")));
178
+ }
179
+ const compatDate = await getLatestCompatDate();
180
+ if (compatDate) {
181
+ wranglerConfigContent = wranglerConfigContent.replace(/"compatibility_date": "\d{4}-\d{2}-\d{2}"/, `"compatibility_date": ${JSON.stringify(compatDate)}`);
182
+ }
183
+ writeFileSync(join(projectOpts.sourceDir, "wrangler.json"), wranglerConfigContent);
184
+ }
185
+ function getAppNameFromPackageJson(sourceDir) {
186
+ try {
187
+ const packageJsonStr = readFileSync(join(sourceDir, "package.json"), "utf8");
188
+ const packageJson = JSON.parse(packageJsonStr);
189
+ if (typeof packageJson.name === "string")
190
+ return packageJson.name;
191
+ }
192
+ catch {
193
+ /* empty */
194
+ }
195
+ }
196
+ export async function getLatestCompatDate() {
197
+ try {
198
+ const resp = await fetch(`https://registry.npmjs.org/workerd`);
199
+ const latestWorkerdVersion = (await resp.json())["dist-tags"].latest;
200
+ // The format of the workerd version is `major.yyyymmdd.patch`.
201
+ const match = latestWorkerdVersion.match(/\d+\.(\d{4})(\d{2})(\d{2})\.\d+/);
202
+ if (match) {
203
+ const [, year, month, date] = match;
204
+ const compatDate = `${year}-${month}-${date}`;
205
+ return compatDate;
206
+ }
207
+ }
208
+ catch {
209
+ /* empty */
210
+ }
211
+ }
@@ -6,7 +6,7 @@ import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
6
6
  *
7
7
  * Merged variables respect the following priority order.
8
8
  * 1. `.env.{mode}.local`
9
- * 2. `.env.local`
9
+ * 2. `.env.local` (when mode is not equal to `test`)
10
10
  * 3. `.env.{mode}`
11
11
  * 4. `.env`
12
12
  *
@@ -13,7 +13,7 @@ function readEnvFile(filePath) {
13
13
  *
14
14
  * Merged variables respect the following priority order.
15
15
  * 1. `.env.{mode}.local`
16
- * 2. `.env.local`
16
+ * 2. `.env.local` (when mode is not equal to `test`)
17
17
  * 3. `.env.{mode}`
18
18
  * 4. `.env`
19
19
  *
@@ -23,7 +23,7 @@ function readEnvFile(filePath) {
23
23
  * the env files at the root of the monorepo.
24
24
  */
25
25
  export function extractProjectEnvVars(mode, { monorepoRoot, appPath }) {
26
- return [".env", `.env.${mode}`, ".env.local", `.env.${mode}.local`]
26
+ return [".env", `.env.${mode}`, ...(mode !== "test" ? [".env.local"] : []), `.env.${mode}.local`]
27
27
  .flatMap((fileName) => [
28
28
  ...(monorepoRoot !== appPath ? [readEnvFile(path.join(monorepoRoot, fileName))] : []),
29
29
  readEnvFile(path.join(appPath, fileName)),
@@ -8,6 +8,8 @@ describe("extractProjectEnvVars", () => {
8
8
  mockFs({
9
9
  ".env": "ENV_VAR=value",
10
10
  ".env.local": "ENV_LOCAL_VAR=value",
11
+ ".env.test": "ENV_TEST_VAR=value",
12
+ ".env.test.local": "ENV_TEST_LOCAL_VAR=value",
11
13
  ".env.development": "ENV_DEV_VAR=value",
12
14
  ".env.development.local": "ENV_DEV_LOCAL_VAR=value",
13
15
  ".env.production": "ENV_PROD_VAR=value",
@@ -54,4 +56,12 @@ describe("extractProjectEnvVars", () => {
54
56
  ENV_VAR: "value",
55
57
  });
56
58
  });
59
+ it("should exclude .env.local files when extracting test env vars", () => {
60
+ const result = extractProjectEnvVars("test", options);
61
+ expect(result).toEqual({
62
+ ENV_TEST_LOCAL_VAR: "value",
63
+ ENV_TEST_VAR: "value",
64
+ ENV_VAR: "value",
65
+ });
66
+ });
57
67
  });
@@ -37,5 +37,6 @@ export type ProjectOptions = {
37
37
  sourceDir: string;
38
38
  outputDir: string;
39
39
  skipNextBuild: boolean;
40
+ skipWranglerConfigCheck: boolean;
40
41
  minify: boolean;
41
42
  };
package/dist/cli/index.js CHANGED
@@ -3,10 +3,11 @@ import { resolve } from "node:path";
3
3
  import { getArgs } from "./args.js";
4
4
  import { build } from "./build/index.js";
5
5
  const nextAppDir = process.cwd();
6
- const { skipNextBuild, outputDir, minify } = getArgs();
6
+ const { skipNextBuild, skipWranglerConfigCheck, outputDir, minify } = getArgs();
7
7
  await build({
8
8
  sourceDir: nextAppDir,
9
9
  outputDir: resolve(outputDir ?? nextAppDir, ".open-next"),
10
10
  skipNextBuild,
11
+ skipWranglerConfigCheck,
11
12
  minify,
12
13
  });
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.3",
4
+ "version": "0.3.4",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "opennextjs-cloudflare": "dist/cli/index.js"
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@dotenvx/dotenvx": "1.31.0",
64
- "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@684",
64
+ "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@688",
65
65
  "glob": "^11.0.0",
66
66
  "rimraf": "^6.0.1",
67
67
  "ts-morph": "^23.0.0",
@@ -0,0 +1,18 @@
1
+ {
2
+ "main": ".open-next/worker.js",
3
+ "name": "app-name",
4
+ "compatibility_date": "2024-12-30",
5
+ "compatibility_flags": ["nodejs_compat"],
6
+ "assets": {
7
+ "directory": ".open-next/assets",
8
+ "binding": "ASSETS"
9
+ },
10
+ "kv_namespaces": [
11
+ // Create a KV binding with the binding name "NEXT_CACHE_WORKERS_KV"
12
+ // to enable the KV based caching:
13
+ // {
14
+ // "binding": "NEXT_CACHE_WORKERS_KV",
15
+ // "id": "<BINDING_ID>"
16
+ // }
17
+ ]
18
+ }