@opennextjs/cloudflare 0.3.2 → 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.
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.js +7 -1
- package/dist/cli/build/bundle-server.d.ts +7 -0
- package/dist/cli/build/bundle-server.js +11 -2
- package/dist/cli/build/index.d.ts +1 -0
- package/dist/cli/build/index.js +69 -1
- package/dist/cli/build/patches/investigated/copy-package-cli-files.d.ts +1 -1
- package/dist/cli/build/patches/investigated/copy-package-cli-files.js +3 -2
- package/dist/cli/build/utils/extract-project-env-vars.d.ts +1 -1
- package/dist/cli/build/utils/extract-project-env-vars.js +2 -2
- package/dist/cli/build/utils/extract-project-env-vars.spec.js +10 -0
- package/dist/cli/config.d.ts +1 -0
- package/dist/cli/index.js +2 -1
- package/package.json +2 -2
- package/templates/defaults/wrangler.jsonc +18 -0
package/dist/cli/args.d.ts
CHANGED
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
|
}
|
|
@@ -4,3 +4,10 @@ import { Config } from "../config.js";
|
|
|
4
4
|
* Bundle the Open Next server.
|
|
5
5
|
*/
|
|
6
6
|
export declare function bundleServer(config: Config, openNextOptions: BuildOptions): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Gets the path of the worker.js file generated by the build process
|
|
9
|
+
*
|
|
10
|
+
* @param openNextOptions the open-next build options
|
|
11
|
+
* @returns the path of the worker.js file that the build process generates
|
|
12
|
+
*/
|
|
13
|
+
export declare function getOutputWorkerPath(openNextOptions: BuildOptions): string;
|
|
@@ -82,7 +82,7 @@ fetch = globalThis.fetch;
|
|
|
82
82
|
const CustomRequest = class extends globalThis.Request {
|
|
83
83
|
constructor(input, init) {
|
|
84
84
|
if (init) {
|
|
85
|
-
init.cache
|
|
85
|
+
delete init.cache;
|
|
86
86
|
// https://github.com/cloudflare/workerd/issues/2746
|
|
87
87
|
// https://github.com/cloudflare/workerd/issues/3245
|
|
88
88
|
Object.defineProperty(init, "body", {
|
|
@@ -106,7 +106,7 @@ globalThis.__BUILD_TIMESTAMP_MS__ = ${Date.now()};
|
|
|
106
106
|
const packagePosixPath = packagePath.split(path.sep).join(path.posix.sep);
|
|
107
107
|
fs.writeFileSync(path.join(outputPath, "handler.mjs"), `export * from "./${packagePosixPath}/handler.mjs";`);
|
|
108
108
|
}
|
|
109
|
-
console.log(`\x1b[35mWorker saved in \`${
|
|
109
|
+
console.log(`\x1b[35mWorker saved in \`${getOutputWorkerPath(openNextOptions)}\` 🚀\n\x1b[0m`);
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
112
|
* This function applies string replacements on the bundled worker code necessary to get it to run in workerd
|
|
@@ -185,3 +185,12 @@ async function patchCodeWithValidations(code, patches) {
|
|
|
185
185
|
console.log(`All ${patches.length} patches applied\n`);
|
|
186
186
|
return patchedCode;
|
|
187
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Gets the path of the worker.js file generated by the build process
|
|
190
|
+
*
|
|
191
|
+
* @param openNextOptions the open-next build options
|
|
192
|
+
* @returns the path of the worker.js file that the build process generates
|
|
193
|
+
*/
|
|
194
|
+
export function getOutputWorkerPath(openNextOptions) {
|
|
195
|
+
return path.join(openNextOptions.outputDir, "worker.js");
|
|
196
|
+
}
|
package/dist/cli/build/index.js
CHANGED
|
@@ -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
|
+
}
|
|
@@ -3,4 +3,4 @@ import { Config } from "../../../config.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Copies the template files present in the cloudflare adapter package into the standalone node_modules folder
|
|
5
5
|
*/
|
|
6
|
-
export declare function copyPackageCliFiles(packageDistDir: string, config: Config,
|
|
6
|
+
export declare function copyPackageCliFiles(packageDistDir: string, config: Config, openNextOptions: BuildOptions): void;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { getOutputWorkerPath } from "../../bundle-server.js";
|
|
3
4
|
/**
|
|
4
5
|
* Copies the template files present in the cloudflare adapter package into the standalone node_modules folder
|
|
5
6
|
*/
|
|
6
|
-
export function copyPackageCliFiles(packageDistDir, config,
|
|
7
|
+
export function copyPackageCliFiles(packageDistDir, config, openNextOptions) {
|
|
7
8
|
console.log("# copyPackageTemplateFiles");
|
|
8
9
|
const sourceDir = path.join(packageDistDir, "cli");
|
|
9
10
|
const destinationDir = path.join(config.paths.internal.package, "cli");
|
|
10
11
|
fs.cpSync(sourceDir, destinationDir, { recursive: true });
|
|
11
|
-
fs.copyFileSync(path.join(packageDistDir, "cli", "templates", "worker.js"),
|
|
12
|
+
fs.copyFileSync(path.join(packageDistDir, "cli", "templates", "worker.js"), getOutputWorkerPath(openNextOptions));
|
|
12
13
|
}
|
|
@@ -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
|
});
|
package/dist/cli/config.d.ts
CHANGED
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.
|
|
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@
|
|
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
|
+
}
|