@opennextjs/cloudflare 1.5.3 → 1.6.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.
@@ -0,0 +1,7 @@
1
+ import type yargs from "yargs";
2
+ /**
3
+ * Add the `build` command to yargs configuration.
4
+ *
5
+ * Consumes 1 positional parameter.
6
+ */
7
+ export declare function addBuildCommand<T extends yargs.Argv>(y: T): yargs.Argv<{}>;
@@ -0,0 +1,38 @@
1
+ import { build as buildImpl } from "../build/build.js";
2
+ import { compileConfig, getNormalizedOptions, nextAppDir, printHeaders, readWranglerConfig, withWranglerOptions, withWranglerPassthroughArgs, } from "./utils.js";
3
+ /**
4
+ * Implementation of the `opennextjs-cloudflare build` command.
5
+ *
6
+ * @param args
7
+ */
8
+ async function buildCommand(args) {
9
+ printHeaders("build");
10
+ const { config, buildDir } = await compileConfig();
11
+ const options = getNormalizedOptions(config, buildDir);
12
+ const wranglerConfig = readWranglerConfig(args);
13
+ await buildImpl(options, config, { ...args, minify: !args.noMinify, sourceDir: nextAppDir }, wranglerConfig);
14
+ }
15
+ /**
16
+ * Add the `build` command to yargs configuration.
17
+ *
18
+ * Consumes 1 positional parameter.
19
+ */
20
+ export function addBuildCommand(y) {
21
+ return y.command("build", "Build an OpenNext Cloudflare worker", (c) => withWranglerOptions(c)
22
+ .option("skipNextBuild", {
23
+ type: "boolean",
24
+ alias: ["skipBuild", "s"],
25
+ default: ["1", "true", "yes"].includes(String(process.env.SKIP_NEXT_APP_BUILD)),
26
+ desc: "Skip building the Next.js app",
27
+ })
28
+ .option("noMinify", {
29
+ type: "boolean",
30
+ default: false,
31
+ desc: "Disable worker minification",
32
+ })
33
+ .option("skipWranglerConfigCheck", {
34
+ type: "boolean",
35
+ default: ["1", "true", "yes"].includes(String(process.env.SKIP_WRANGLER_CONFIG_CHECK)),
36
+ desc: "Skip checking for a Wrangler config",
37
+ }), (args) => buildCommand(withWranglerPassthroughArgs(args)));
38
+ }
@@ -1,6 +1,16 @@
1
- import { BuildOptions } from "@opennextjs/aws/build/helper.js";
2
- import type { OpenNextConfig } from "../../api/config.js";
3
- export declare function deploy(options: BuildOptions, config: OpenNextConfig, deployOptions: {
4
- passthroughArgs: string[];
5
- cacheChunkSize?: number;
6
- }): Promise<void>;
1
+ import type yargs from "yargs";
2
+ import type { WithWranglerArgs } from "./utils.js";
3
+ /**
4
+ * Implementation of the `opennextjs-cloudflare deploy` command.
5
+ *
6
+ * @param args
7
+ */
8
+ export declare function deployCommand(args: WithWranglerArgs<{
9
+ cacheChunkSize: number;
10
+ }>): Promise<void>;
11
+ /**
12
+ * Add the `deploy` command to yargs configuration.
13
+ *
14
+ * Consumes 1 positional parameter.
15
+ */
16
+ export declare function addDeployCommand<T extends yargs.Argv>(y: T): yargs.Argv<{}>;
@@ -1,22 +1,33 @@
1
1
  import { DEPLOYMENT_MAPPING_ENV_NAME } from "../templates/skew-protection.js";
2
- import { getWranglerEnvironmentFlag, runWrangler } from "../utils/run-wrangler.js";
2
+ import { runWrangler } from "../utils/run-wrangler.js";
3
3
  import { getEnvFromPlatformProxy, quoteShellMeta } from "./helpers.js";
4
- import { populateCache } from "./populate-cache.js";
4
+ import { populateCache, withPopulateCacheOptions } from "./populate-cache.js";
5
5
  import { getDeploymentMapping } from "./skew-protection.js";
6
- export async function deploy(options, config, deployOptions) {
6
+ import { getNormalizedOptions, printHeaders, readWranglerConfig, retrieveCompiledConfig, withWranglerPassthroughArgs, } from "./utils.js";
7
+ /**
8
+ * Implementation of the `opennextjs-cloudflare deploy` command.
9
+ *
10
+ * @param args
11
+ */
12
+ export async function deployCommand(args) {
13
+ printHeaders("deploy");
14
+ const { config } = await retrieveCompiledConfig();
15
+ const options = getNormalizedOptions(config);
16
+ const wranglerConfig = readWranglerConfig(args);
7
17
  const envVars = await getEnvFromPlatformProxy({
8
- // TODO: Pass the configPath, update everywhere applicable
9
- environment: getWranglerEnvironmentFlag(deployOptions.passthroughArgs),
18
+ configPath: args.configPath,
19
+ environment: args.env,
10
20
  });
11
21
  const deploymentMapping = await getDeploymentMapping(options, config, envVars);
12
- await populateCache(options, config, {
22
+ await populateCache(options, config, wranglerConfig, {
13
23
  target: "remote",
14
- environment: getWranglerEnvironmentFlag(deployOptions.passthroughArgs),
15
- cacheChunkSize: deployOptions.cacheChunkSize,
24
+ environment: args.env,
25
+ configPath: args.configPath,
26
+ cacheChunkSize: args.cacheChunkSize,
16
27
  });
17
28
  runWrangler(options, [
18
29
  "deploy",
19
- ...deployOptions.passthroughArgs,
30
+ ...args.wranglerArgs,
20
31
  ...(deploymentMapping
21
32
  ? [`--var ${DEPLOYMENT_MAPPING_ENV_NAME}:${quoteShellMeta(JSON.stringify(deploymentMapping))}`]
22
33
  : []),
@@ -24,3 +35,11 @@ export async function deploy(options, config, deployOptions) {
24
35
  logging: "all",
25
36
  });
26
37
  }
38
+ /**
39
+ * Add the `deploy` command to yargs configuration.
40
+ *
41
+ * Consumes 1 positional parameter.
42
+ */
43
+ export function addDeployCommand(y) {
44
+ return y.command("deploy", "Deploy a built OpenNext app to Cloudflare Workers", (c) => withPopulateCacheOptions(c), (args) => deployCommand(withWranglerPassthroughArgs(args)));
45
+ }
@@ -1,5 +1,7 @@
1
1
  import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
2
2
  import type { OpenNextConfig } from "@opennextjs/aws/types/open-next.js";
3
+ import type { Unstable_Config as WranglerConfig } from "wrangler";
4
+ import type yargs from "yargs";
3
5
  import type { WranglerTarget } from "../utils/run-wrangler.js";
4
6
  export type CacheAsset = {
5
7
  isFetch: boolean;
@@ -8,8 +10,24 @@ export type CacheAsset = {
8
10
  buildId: string;
9
11
  };
10
12
  export declare function getCacheAssets(opts: BuildOptions): CacheAsset[];
11
- export declare function populateCache(options: BuildOptions, config: OpenNextConfig, populateCacheOptions: {
13
+ type PopulateCacheOptions = {
12
14
  target: WranglerTarget;
13
15
  environment?: string;
16
+ configPath?: string;
14
17
  cacheChunkSize?: number;
15
- }): Promise<void>;
18
+ };
19
+ export declare function populateCache(options: BuildOptions, config: OpenNextConfig, wranglerConfig: WranglerConfig, populateCacheOptions: PopulateCacheOptions): Promise<void>;
20
+ /**
21
+ * Add the `populateCache` command to yargs configuration, with nested commands for `local` and `remote`.
22
+ *
23
+ * Consumes 2 positional parameters.
24
+ */
25
+ export declare function addPopulateCacheCommand<T extends yargs.Argv>(y: T): yargs.Argv<{}>;
26
+ export declare function withPopulateCacheOptions<T extends yargs.Argv>(args: T): yargs.Argv<{
27
+ configPath: string | undefined;
28
+ } & {
29
+ env: string | undefined;
30
+ } & {
31
+ cacheChunkSize: number;
32
+ }>;
33
+ export {};
@@ -3,7 +3,6 @@ import path from "node:path";
3
3
  import logger from "@opennextjs/aws/logger.js";
4
4
  import { globSync } from "glob";
5
5
  import { tqdm } from "ts-tqdm";
6
- import { unstable_readConfig } from "wrangler";
7
6
  import { BINDING_NAME as KV_CACHE_BINDING_NAME, NAME as KV_CACHE_NAME, PREFIX_ENV_NAME as KV_CACHE_PREFIX_ENV_NAME, } from "../../api/overrides/incremental-cache/kv-incremental-cache.js";
8
7
  import { BINDING_NAME as R2_CACHE_BINDING_NAME, NAME as R2_CACHE_NAME, PREFIX_ENV_NAME as R2_CACHE_PREFIX_ENV_NAME, } from "../../api/overrides/incremental-cache/r2-incremental-cache.js";
9
8
  import { CACHE_DIR as STATIC_ASSETS_CACHE_DIR, NAME as STATIC_ASSETS_CACHE_NAME, } from "../../api/overrides/incremental-cache/static-assets-incremental-cache.js";
@@ -12,6 +11,7 @@ import { BINDING_NAME as D1_TAG_BINDING_NAME, NAME as D1_TAG_NAME, } from "../..
12
11
  import { normalizePath } from "../build/utils/normalize-path.js";
13
12
  import { runWrangler } from "../utils/run-wrangler.js";
14
13
  import { getEnvFromPlatformProxy, quoteShellMeta } from "./helpers.js";
14
+ import { getNormalizedOptions, printHeaders, readWranglerConfig, retrieveCompiledConfig, withWranglerOptions, withWranglerPassthroughArgs, } from "./utils.js";
15
15
  async function resolveCacheName(value) {
16
16
  return typeof value === "function" ? (await value()).name : value;
17
17
  }
@@ -51,9 +51,8 @@ export function getCacheAssets(opts) {
51
51
  }
52
52
  return assets;
53
53
  }
54
- async function populateR2IncrementalCache(options, populateCacheOptions) {
54
+ async function populateR2IncrementalCache(options, config, populateCacheOptions) {
55
55
  logger.info("\nPopulating R2 incremental cache...");
56
- const config = unstable_readConfig({ env: populateCacheOptions.environment });
57
56
  const binding = config.r2_buckets.find(({ binding }) => binding === R2_CACHE_BINDING_NAME);
58
57
  if (!binding) {
59
58
  throw new Error(`No R2 binding ${JSON.stringify(R2_CACHE_BINDING_NAME)} found!`);
@@ -82,9 +81,8 @@ async function populateR2IncrementalCache(options, populateCacheOptions) {
82
81
  }
83
82
  logger.info(`Successfully populated cache with ${assets.length} assets`);
84
83
  }
85
- async function populateKVIncrementalCache(options, populateCacheOptions) {
84
+ async function populateKVIncrementalCache(options, config, populateCacheOptions) {
86
85
  logger.info("\nPopulating KV incremental cache...");
87
- const config = unstable_readConfig({ env: populateCacheOptions.environment });
88
86
  const binding = config.kv_namespaces.find(({ binding }) => binding === KV_CACHE_BINDING_NAME);
89
87
  if (!binding) {
90
88
  throw new Error(`No KV binding ${JSON.stringify(KV_CACHE_BINDING_NAME)} found!`);
@@ -116,9 +114,8 @@ async function populateKVIncrementalCache(options, populateCacheOptions) {
116
114
  }
117
115
  logger.info(`Successfully populated cache with ${assets.length} assets`);
118
116
  }
119
- function populateD1TagCache(options, populateCacheOptions) {
117
+ function populateD1TagCache(options, config, populateCacheOptions) {
120
118
  logger.info("\nCreating D1 table if necessary...");
121
- const config = unstable_readConfig({ env: populateCacheOptions.environment });
122
119
  const binding = config.d1_databases.find(({ binding }) => binding === D1_TAG_BINDING_NAME);
123
120
  if (!binding) {
124
121
  throw new Error(`No D1 binding ${JSON.stringify(D1_TAG_BINDING_NAME)} found!`);
@@ -135,7 +132,7 @@ function populateStaticAssetsIncrementalCache(options) {
135
132
  cpSync(path.join(options.outputDir, "cache"), path.join(options.outputDir, "assets", STATIC_ASSETS_CACHE_DIR), { recursive: true });
136
133
  logger.info(`Successfully populated static assets cache`);
137
134
  }
138
- export async function populateCache(options, config, populateCacheOptions) {
135
+ export async function populateCache(options, config, wranglerConfig, populateCacheOptions) {
139
136
  const { incrementalCache, tagCache } = config.default.override ?? {};
140
137
  if (!existsSync(options.outputDir)) {
141
138
  logger.error("Unable to populate cache: Open Next build not found");
@@ -145,10 +142,10 @@ export async function populateCache(options, config, populateCacheOptions) {
145
142
  const name = await resolveCacheName(incrementalCache);
146
143
  switch (name) {
147
144
  case R2_CACHE_NAME:
148
- await populateR2IncrementalCache(options, populateCacheOptions);
145
+ await populateR2IncrementalCache(options, wranglerConfig, populateCacheOptions);
149
146
  break;
150
147
  case KV_CACHE_NAME:
151
- await populateKVIncrementalCache(options, populateCacheOptions);
148
+ await populateKVIncrementalCache(options, wranglerConfig, populateCacheOptions);
152
149
  break;
153
150
  case STATIC_ASSETS_CACHE_NAME:
154
151
  populateStaticAssetsIncrementalCache(options);
@@ -161,10 +158,45 @@ export async function populateCache(options, config, populateCacheOptions) {
161
158
  const name = await resolveCacheName(tagCache);
162
159
  switch (name) {
163
160
  case D1_TAG_NAME:
164
- populateD1TagCache(options, populateCacheOptions);
161
+ populateD1TagCache(options, wranglerConfig, populateCacheOptions);
165
162
  break;
166
163
  default:
167
164
  logger.info("Tag cache does not need populating");
168
165
  }
169
166
  }
170
167
  }
168
+ /**
169
+ * Implementation of the `opennextjs-cloudflare populateCache` command.
170
+ *
171
+ * @param args
172
+ */
173
+ async function populateCacheCommand(target, args) {
174
+ printHeaders(`populate cache - ${target}`);
175
+ const { config } = await retrieveCompiledConfig();
176
+ const options = getNormalizedOptions(config);
177
+ const wranglerConfig = readWranglerConfig(args);
178
+ await populateCache(options, config, wranglerConfig, {
179
+ target,
180
+ environment: args.env,
181
+ configPath: args.configPath,
182
+ cacheChunkSize: args.cacheChunkSize,
183
+ });
184
+ }
185
+ /**
186
+ * Add the `populateCache` command to yargs configuration, with nested commands for `local` and `remote`.
187
+ *
188
+ * Consumes 2 positional parameters.
189
+ */
190
+ export function addPopulateCacheCommand(y) {
191
+ return y.command("populateCache", "Populate the cache for a built Next.js app", (c) => c
192
+ .command("local", "Local dev server cache", (c) => withPopulateCacheOptions(c), (args) => populateCacheCommand("local", withWranglerPassthroughArgs(args)))
193
+ .command("remote", "Remote Cloudflare Worker cache", (c) => withPopulateCacheOptions(c), (args) => populateCacheCommand("remote", withWranglerPassthroughArgs(args)))
194
+ .demandCommand(1, 1));
195
+ }
196
+ export function withPopulateCacheOptions(args) {
197
+ return withWranglerOptions(args).options("cacheChunkSize", {
198
+ type: "number",
199
+ default: 25,
200
+ desc: "Number of entries per chunk when populating the cache",
201
+ });
202
+ }
@@ -1,6 +1,16 @@
1
- import { BuildOptions } from "@opennextjs/aws/build/helper.js";
2
- import type { OpenNextConfig } from "../../api/config.js";
3
- export declare function preview(options: BuildOptions, config: OpenNextConfig, previewOptions: {
4
- passthroughArgs: string[];
5
- cacheChunkSize?: number;
6
- }): Promise<void>;
1
+ import type yargs from "yargs";
2
+ import type { WithWranglerArgs } from "./utils.js";
3
+ /**
4
+ * Implementation of the `opennextjs-cloudflare preview` command.
5
+ *
6
+ * @param args
7
+ */
8
+ export declare function previewCommand(args: WithWranglerArgs<{
9
+ cacheChunkSize: number;
10
+ }>): Promise<void>;
11
+ /**
12
+ * Add the `preview` command to yargs configuration.
13
+ *
14
+ * Consumes 1 positional parameter.
15
+ */
16
+ export declare function addPreviewCommand<T extends yargs.Argv>(y: T): yargs.Argv<{}>;
@@ -1,10 +1,29 @@
1
- import { getWranglerEnvironmentFlag, runWrangler } from "../utils/run-wrangler.js";
2
- import { populateCache } from "./populate-cache.js";
3
- export async function preview(options, config, previewOptions) {
4
- await populateCache(options, config, {
1
+ import { runWrangler } from "../utils/run-wrangler.js";
2
+ import { populateCache, withPopulateCacheOptions } from "./populate-cache.js";
3
+ import { getNormalizedOptions, printHeaders, readWranglerConfig, retrieveCompiledConfig, withWranglerPassthroughArgs, } from "./utils.js";
4
+ /**
5
+ * Implementation of the `opennextjs-cloudflare preview` command.
6
+ *
7
+ * @param args
8
+ */
9
+ export async function previewCommand(args) {
10
+ printHeaders("preview");
11
+ const { config } = await retrieveCompiledConfig();
12
+ const options = getNormalizedOptions(config);
13
+ const wranglerConfig = readWranglerConfig(args);
14
+ await populateCache(options, config, wranglerConfig, {
5
15
  target: "local",
6
- environment: getWranglerEnvironmentFlag(previewOptions.passthroughArgs),
7
- cacheChunkSize: previewOptions.cacheChunkSize,
16
+ environment: args.env,
17
+ configPath: args.configPath,
18
+ cacheChunkSize: args.cacheChunkSize,
8
19
  });
9
- runWrangler(options, ["dev", ...previewOptions.passthroughArgs], { logging: "all" });
20
+ runWrangler(options, ["dev", ...args.wranglerArgs], { logging: "all" });
21
+ }
22
+ /**
23
+ * Add the `preview` command to yargs configuration.
24
+ *
25
+ * Consumes 1 positional parameter.
26
+ */
27
+ export function addPreviewCommand(y) {
28
+ return y.command("preview", "Preview a built OpenNext app with a Wrangler dev server", (c) => withPopulateCacheOptions(c), (args) => previewCommand(withWranglerPassthroughArgs(args)));
10
29
  }
@@ -1,6 +1,16 @@
1
- import { BuildOptions } from "@opennextjs/aws/build/helper.js";
2
- import type { OpenNextConfig } from "../../api/config.js";
3
- export declare function upload(options: BuildOptions, config: OpenNextConfig, uploadOptions: {
4
- passthroughArgs: string[];
5
- cacheChunkSize?: number;
6
- }): Promise<void>;
1
+ import type yargs from "yargs";
2
+ import type { WithWranglerArgs } from "./utils.js";
3
+ /**
4
+ * Implementation of the `opennextjs-cloudflare upload` command.
5
+ *
6
+ * @param args
7
+ */
8
+ export declare function uploadCommand(args: WithWranglerArgs<{
9
+ cacheChunkSize: number;
10
+ }>): Promise<void>;
11
+ /**
12
+ * Add the `upload` command to yargs configuration.
13
+ *
14
+ * Consumes 1 positional parameter.
15
+ */
16
+ export declare function addUploadCommand<T extends yargs.Argv>(y: T): yargs.Argv<{}>;
@@ -1,24 +1,43 @@
1
1
  import { DEPLOYMENT_MAPPING_ENV_NAME } from "../templates/skew-protection.js";
2
- import { getWranglerEnvironmentFlag, runWrangler } from "../utils/run-wrangler.js";
2
+ import { runWrangler } from "../utils/run-wrangler.js";
3
3
  import { getEnvFromPlatformProxy, quoteShellMeta } from "./helpers.js";
4
- import { populateCache } from "./populate-cache.js";
4
+ import { populateCache, withPopulateCacheOptions } from "./populate-cache.js";
5
5
  import { getDeploymentMapping } from "./skew-protection.js";
6
- export async function upload(options, config, uploadOptions) {
6
+ import { getNormalizedOptions, printHeaders, readWranglerConfig, retrieveCompiledConfig, withWranglerPassthroughArgs, } from "./utils.js";
7
+ /**
8
+ * Implementation of the `opennextjs-cloudflare upload` command.
9
+ *
10
+ * @param args
11
+ */
12
+ export async function uploadCommand(args) {
13
+ printHeaders("upload");
14
+ const { config } = await retrieveCompiledConfig();
15
+ const options = getNormalizedOptions(config);
16
+ const wranglerConfig = readWranglerConfig(args);
7
17
  const envVars = await getEnvFromPlatformProxy({
8
- // TODO: Pass the configPath, update everywhere applicable
9
- environment: getWranglerEnvironmentFlag(uploadOptions.passthroughArgs),
18
+ configPath: args.configPath,
19
+ environment: args.env,
10
20
  });
11
21
  const deploymentMapping = await getDeploymentMapping(options, config, envVars);
12
- await populateCache(options, config, {
22
+ await populateCache(options, config, wranglerConfig, {
13
23
  target: "remote",
14
- environment: getWranglerEnvironmentFlag(uploadOptions.passthroughArgs),
15
- cacheChunkSize: uploadOptions.cacheChunkSize,
24
+ environment: args.env,
25
+ configPath: args.configPath,
26
+ cacheChunkSize: args.cacheChunkSize,
16
27
  });
17
28
  runWrangler(options, [
18
29
  "versions upload",
19
- ...uploadOptions.passthroughArgs,
30
+ ...args.wranglerArgs,
20
31
  ...(deploymentMapping
21
32
  ? [`--var ${DEPLOYMENT_MAPPING_ENV_NAME}:${quoteShellMeta(JSON.stringify(deploymentMapping))}`]
22
33
  : []),
23
34
  ], { logging: "all" });
24
35
  }
36
+ /**
37
+ * Add the `upload` command to yargs configuration.
38
+ *
39
+ * Consumes 1 positional parameter.
40
+ */
41
+ export function addUploadCommand(y) {
42
+ return y.command("upload", "Upload a built OpenNext app to Cloudflare Workers", (c) => withPopulateCacheOptions(c), (args) => uploadCommand(withWranglerPassthroughArgs(args)));
43
+ }
@@ -0,0 +1,81 @@
1
+ import type yargs from "yargs";
2
+ import type { OpenNextConfig } from "../../api/config.js";
3
+ export type WithWranglerArgs<T = unknown> = T & {
4
+ wranglerArgs: string[];
5
+ configPath: string | undefined;
6
+ env: string | undefined;
7
+ };
8
+ export declare const nextAppDir: string;
9
+ /**
10
+ * Print headers and warnings for the CLI.
11
+ *
12
+ * @param command
13
+ */
14
+ export declare function printHeaders(command: string): void;
15
+ /**
16
+ * Compile the OpenNext config, and ensure it is for Cloudflare.
17
+ *
18
+ * @returns OpenNext config.
19
+ */
20
+ export declare function compileConfig(): Promise<{
21
+ config: import("@opennextjs/aws/types/open-next.js").OpenNextConfig;
22
+ buildDir: string;
23
+ }>;
24
+ /**
25
+ * Retrieve a compiled OpenNext config, and ensure it is for Cloudflare.
26
+ *
27
+ * @returns OpenNext config.
28
+ */
29
+ export declare function retrieveCompiledConfig(): Promise<{
30
+ config: any;
31
+ }>;
32
+ /**
33
+ * Normalize the OpenNext options and set the logging level.
34
+ *
35
+ * @param config
36
+ * @param buildDir Directory to use when building the application
37
+ * @returns Normalized options.
38
+ */
39
+ export declare function getNormalizedOptions(config: OpenNextConfig, buildDir?: string): {
40
+ appBuildOutputPath: string;
41
+ appPackageJsonPath: string;
42
+ appPath: string;
43
+ appPublicPath: string;
44
+ buildDir: string;
45
+ config: import("@opennextjs/aws/types/open-next.js").OpenNextConfig;
46
+ debug: boolean;
47
+ minify: boolean;
48
+ monorepoRoot: string;
49
+ nextVersion: string;
50
+ openNextVersion: string;
51
+ openNextDistDir: string;
52
+ outputDir: string;
53
+ packager: "bun" | "npm" | "yarn" | "pnpm";
54
+ tempBuildDir: string;
55
+ };
56
+ /**
57
+ * Read the Wrangler config.
58
+ *
59
+ * @param args Wrangler environment and config path.
60
+ * @returns Wrangler config.
61
+ */
62
+ export declare function readWranglerConfig(args: WithWranglerArgs): import("wrangler").Unstable_Config;
63
+ /**
64
+ * Adds flags for the wrangler config path and environment to the yargs configuration.
65
+ */
66
+ export declare function withWranglerOptions<T extends yargs.Argv>(args: T): yargs.Argv<{
67
+ configPath: string | undefined;
68
+ } & {
69
+ env: string | undefined;
70
+ }>;
71
+ /**
72
+ *
73
+ * @param args
74
+ * @returns The inputted args, and an array of arguments that can be given to wrangler commands, including the `--config` and `--env` args.
75
+ */
76
+ export declare function withWranglerPassthroughArgs<T extends yargs.ArgumentsCamelCase<{
77
+ configPath: string | undefined;
78
+ env: string | undefined;
79
+ }>>(args: T): T & {
80
+ wranglerArgs: string[];
81
+ };
@@ -0,0 +1,105 @@
1
+ import { existsSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import path from "node:path";
4
+ import { compileOpenNextConfig } from "@opennextjs/aws/build/compileConfig.js";
5
+ import { normalizeOptions } from "@opennextjs/aws/build/helper.js";
6
+ import { printHeader, showWarningOnWindows } from "@opennextjs/aws/build/utils.js";
7
+ import logger from "@opennextjs/aws/logger.js";
8
+ import { unstable_readConfig } from "wrangler";
9
+ import { createOpenNextConfigIfNotExistent, ensureCloudflareConfig } from "../build/utils/index.js";
10
+ export const nextAppDir = process.cwd();
11
+ /**
12
+ * Print headers and warnings for the CLI.
13
+ *
14
+ * @param command
15
+ */
16
+ export function printHeaders(command) {
17
+ printHeader(`Cloudflare ${command}`);
18
+ showWarningOnWindows();
19
+ }
20
+ /**
21
+ * Compile the OpenNext config, and ensure it is for Cloudflare.
22
+ *
23
+ * @returns OpenNext config.
24
+ */
25
+ export async function compileConfig() {
26
+ await createOpenNextConfigIfNotExistent(nextAppDir);
27
+ const { config, buildDir } = await compileOpenNextConfig(nextAppDir, undefined, { compileEdge: true });
28
+ ensureCloudflareConfig(config);
29
+ return { config, buildDir };
30
+ }
31
+ /**
32
+ * Retrieve a compiled OpenNext config, and ensure it is for Cloudflare.
33
+ *
34
+ * @returns OpenNext config.
35
+ */
36
+ export async function retrieveCompiledConfig() {
37
+ const configPath = path.join(nextAppDir, ".open-next/.build/open-next.config.edge.mjs");
38
+ if (!existsSync(configPath)) {
39
+ logger.error("Could not find compiled Open Next config, did you run the build command?");
40
+ process.exit(1);
41
+ }
42
+ const config = await import(configPath).then((mod) => mod.default);
43
+ ensureCloudflareConfig(config);
44
+ return { config };
45
+ }
46
+ /**
47
+ * Normalize the OpenNext options and set the logging level.
48
+ *
49
+ * @param config
50
+ * @param buildDir Directory to use when building the application
51
+ * @returns Normalized options.
52
+ */
53
+ export function getNormalizedOptions(config, buildDir = nextAppDir) {
54
+ const require = createRequire(import.meta.url);
55
+ const openNextDistDir = path.dirname(require.resolve("@opennextjs/aws/index.js"));
56
+ const options = normalizeOptions(config, openNextDistDir, buildDir);
57
+ logger.setLevel(options.debug ? "debug" : "info");
58
+ return options;
59
+ }
60
+ /**
61
+ * Read the Wrangler config.
62
+ *
63
+ * @param args Wrangler environment and config path.
64
+ * @returns Wrangler config.
65
+ */
66
+ export function readWranglerConfig(args) {
67
+ return unstable_readConfig({ env: args.env, config: args.configPath });
68
+ }
69
+ /**
70
+ * Adds flags for the wrangler config path and environment to the yargs configuration.
71
+ */
72
+ export function withWranglerOptions(args) {
73
+ return args
74
+ .options("configPath", {
75
+ type: "string",
76
+ alias: ["config", "c"],
77
+ desc: "Path to Wrangler configuration file",
78
+ })
79
+ .options("env", {
80
+ type: "string",
81
+ alias: "e",
82
+ desc: "Wrangler environment to use for operations",
83
+ });
84
+ }
85
+ /**
86
+ *
87
+ * @param args
88
+ * @returns An array of arguments that can be given to wrangler commands, including the `--config` and `--env` args.
89
+ */
90
+ function getWranglerArgs(args) {
91
+ return [
92
+ ...(args.configPath ? ["--config", args.configPath] : []),
93
+ ...(args.env ? ["--env", args.env] : []),
94
+ // Note: the first args in `_` will be the commands.
95
+ ...args._.slice(args._[0] === "populateCache" ? 2 : 1).map((a) => `${a}`),
96
+ ];
97
+ }
98
+ /**
99
+ *
100
+ * @param args
101
+ * @returns The inputted args, and an array of arguments that can be given to wrangler commands, including the `--config` and `--env` args.
102
+ */
103
+ export function withWranglerPassthroughArgs(args) {
104
+ return { ...args, wranglerArgs: getWranglerArgs(args) };
105
+ }
@@ -1,2 +1,10 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ export declare function runCommand(): {
3
+ [x: string]: unknown;
4
+ _: (string | number)[];
5
+ $0: string;
6
+ } | Promise<{
7
+ [x: string]: unknown;
8
+ _: (string | number)[];
9
+ $0: string;
10
+ }>;
package/dist/cli/index.js CHANGED
@@ -1,51 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module";
3
- import path from "node:path";
4
- import { compileOpenNextConfig } from "@opennextjs/aws/build/compileConfig.js";
5
- import { normalizeOptions } from "@opennextjs/aws/build/helper.js";
6
- import { printHeader, showWarningOnWindows } from "@opennextjs/aws/build/utils.js";
7
- import logger from "@opennextjs/aws/logger.js";
8
- import { unstable_readConfig } from "wrangler";
9
- import { getArgs } from "./args.js";
10
- import { build } from "./build/build.js";
11
- import { createOpenNextConfigIfNotExistent, ensureCloudflareConfig } from "./build/utils/index.js";
12
- import { deploy } from "./commands/deploy.js";
13
- import { populateCache } from "./commands/populate-cache.js";
14
- import { preview } from "./commands/preview.js";
15
- import { upload } from "./commands/upload.js";
16
- import { getWranglerConfigFlag, getWranglerEnvironmentFlag } from "./utils/run-wrangler.js";
17
- const nextAppDir = process.cwd();
18
- async function runCommand(args) {
19
- printHeader(`Cloudflare ${args.command}`);
20
- showWarningOnWindows();
21
- const baseDir = nextAppDir;
22
- const require = createRequire(import.meta.url);
23
- const openNextDistDir = path.dirname(require.resolve("@opennextjs/aws/index.js"));
24
- // TODO: retrieve the compiled version if command != build
25
- await createOpenNextConfigIfNotExistent(baseDir);
26
- const { config, buildDir } = await compileOpenNextConfig(baseDir, undefined, {
27
- compileEdge: true,
28
- });
29
- ensureCloudflareConfig(config);
30
- // Initialize options
31
- const options = normalizeOptions(config, openNextDistDir, buildDir);
32
- logger.setLevel(options.debug ? "debug" : "info");
33
- switch (args.command) {
34
- case "build": {
35
- const argv = process.argv.slice(2);
36
- const wranglerEnv = getWranglerEnvironmentFlag(argv);
37
- const wranglerConfigFile = getWranglerConfigFlag(argv);
38
- const wranglerConfig = unstable_readConfig({ env: wranglerEnv, config: wranglerConfigFile });
39
- return build(options, config, { ...args, sourceDir: baseDir }, wranglerConfig);
40
- }
41
- case "preview":
42
- return preview(options, config, args);
43
- case "deploy":
44
- return deploy(options, config, args);
45
- case "upload":
46
- return upload(options, config, args);
47
- case "populateCache":
48
- return populateCache(options, config, args);
49
- }
2
+ import yargs from "yargs";
3
+ import { addBuildCommand } from "./commands/build.js";
4
+ import { addDeployCommand } from "./commands/deploy.js";
5
+ import { addPopulateCacheCommand } from "./commands/populate-cache.js";
6
+ import { addPreviewCommand } from "./commands/preview.js";
7
+ import { addUploadCommand } from "./commands/upload.js";
8
+ export function runCommand() {
9
+ const y = yargs(process.argv.slice(2).filter((arg) => arg !== "--"))
10
+ .scriptName("opennextjs-cloudflare")
11
+ .parserConfiguration({ "unknown-options-as-args": true });
12
+ addBuildCommand(y);
13
+ addPreviewCommand(y);
14
+ addDeployCommand(y);
15
+ addUploadCommand(y);
16
+ addPopulateCacheCommand(y);
17
+ return y.demandCommand(1, 1).parse();
50
18
  }
51
- await runCommand(getArgs());
19
+ await runCommand();
@@ -175,4 +175,3 @@ export function detectContentType(buffer) {
175
175
  return BMP;
176
176
  }
177
177
  }
178
- /* eslint-enable no-var */
@@ -119,4 +119,3 @@ function populateProcessEnv(url, env) {
119
119
  process.env.DEPLOYMENT_ID = __DEPLOYMENT_ID__;
120
120
  }
121
121
  }
122
- /* eslint-enable no-var */
@@ -51,7 +51,9 @@ export function maybeGetSkewProtectionResponse(request) {
51
51
  const hostname = `${versionDomain}-${process.env.CF_WORKER_NAME}.${process.env.CF_PREVIEW_DOMAIN}.workers.dev`;
52
52
  url.hostname = hostname;
53
53
  const requestToOlderDeployment = new Request(url, request);
54
- return fetch(requestToOlderDeployment);
54
+ // Remove the origin header to prevent an error with POST requests
55
+ const headers = new Headers(request.headers);
56
+ headers.delete("origin");
57
+ return fetch(requestToOlderDeployment, { headers });
55
58
  }
56
59
  }
57
- /* eslint-enable no-var */
@@ -7,28 +7,4 @@ type WranglerOptions = {
7
7
  };
8
8
  export declare function runWrangler(options: BuildOptions, args: string[], wranglerOpts?: WranglerOptions): void;
9
9
  export declare function isWranglerTarget(v: string | undefined): v is WranglerTarget;
10
- /**
11
- * Returns the value of the flag.
12
- *
13
- * The value is retrieved for `<argName> value` or `<argName>=value`.
14
- *
15
- * @param args List of args
16
- * @param argName The arg name with leading dashes, i.e. `--env` or `-e`
17
- * @returns The value or undefined when not found
18
- */
19
- export declare function getFlagValue(args: string[], ...argNames: string[]): string | undefined;
20
- /**
21
- * Find the value of the environment flag (`--env` / `-e`) used by Wrangler.
22
- *
23
- * @param args - CLI arguments.
24
- * @returns Value of the environment flag or undefined when not found
25
- */
26
- export declare function getWranglerEnvironmentFlag(args: string[]): string | undefined;
27
- /**
28
- * Find the value of the config flag (`--config` / `-c`) used by Wrangler.
29
- *
30
- * @param args - CLI arguments.
31
- * @returns Value of the config flag or undefined when not found
32
- */
33
- export declare function getWranglerConfigFlag(args: string[]): string | undefined;
34
10
  export {};
@@ -66,49 +66,3 @@ export function runWrangler(options, args, wranglerOpts = {}) {
66
66
  export function isWranglerTarget(v) {
67
67
  return !!v && ["local", "remote"].includes(v);
68
68
  }
69
- /**
70
- * Returns the value of the flag.
71
- *
72
- * The value is retrieved for `<argName> value` or `<argName>=value`.
73
- *
74
- * @param args List of args
75
- * @param argName The arg name with leading dashes, i.e. `--env` or `-e`
76
- * @returns The value or undefined when not found
77
- */
78
- export function getFlagValue(args, ...argNames) {
79
- if (argNames.some((name) => !name.startsWith("-"))) {
80
- // Names should start with "-" or "--"
81
- throw new Error(`Invalid arg names: ${argNames}`);
82
- }
83
- for (const argName of argNames) {
84
- for (let i = 0; i <= args.length; i++) {
85
- const arg = args[i];
86
- if (!arg)
87
- continue;
88
- if (arg === argName) {
89
- return args[i + 1];
90
- }
91
- if (arg.startsWith(argName)) {
92
- return arg.split("=")[1];
93
- }
94
- }
95
- }
96
- }
97
- /**
98
- * Find the value of the environment flag (`--env` / `-e`) used by Wrangler.
99
- *
100
- * @param args - CLI arguments.
101
- * @returns Value of the environment flag or undefined when not found
102
- */
103
- export function getWranglerEnvironmentFlag(args) {
104
- return getFlagValue(args, "--env", "-e");
105
- }
106
- /**
107
- * Find the value of the config flag (`--config` / `-c`) used by Wrangler.
108
- *
109
- * @param args - CLI arguments.
110
- * @returns Value of the config flag or undefined when not found
111
- */
112
- export function getWranglerConfigFlag(args) {
113
- return getFlagValue(args, "--config", "-c");
114
- }
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": "1.5.3",
4
+ "version": "1.6.0",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "opennextjs-cloudflare": "dist/cli/index.js"
@@ -47,7 +47,8 @@
47
47
  "cloudflare": "^4.4.1",
48
48
  "enquirer": "^2.4.1",
49
49
  "glob": "^11.0.0",
50
- "ts-tqdm": "^0.8.6"
50
+ "ts-tqdm": "^0.8.6",
51
+ "yargs": "^18.0.0"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@cloudflare/workers-types": "^4.20250224.0",
@@ -56,9 +57,10 @@
56
57
  "@types/mock-fs": "^4.13.4",
57
58
  "@types/node": "^22.2.0",
58
59
  "@types/picomatch": "^4.0.0",
60
+ "@types/yargs": "^17.0.33",
59
61
  "diff": "^8.0.2",
60
62
  "esbuild": "^0.25.4",
61
- "eslint": "^9.11.1",
63
+ "eslint": "^9.31.0",
62
64
  "eslint-plugin-import": "^2.31.0",
63
65
  "eslint-plugin-simple-import-sort": "^12.1.1",
64
66
  "eslint-plugin-unicorn": "^55.0.0",
@@ -68,7 +70,7 @@
68
70
  "picomatch": "^4.0.2",
69
71
  "rimraf": "^6.0.1",
70
72
  "typescript": "^5.7.3",
71
- "typescript-eslint": "^8.7.0",
73
+ "typescript-eslint": "^8.37.0",
72
74
  "vitest": "^2.1.1"
73
75
  },
74
76
  "peerDependencies": {
@@ -1,21 +0,0 @@
1
- import type { ParseArgsConfig } from "node:util";
2
- import type { WranglerTarget } from "./utils/run-wrangler.js";
3
- export type Arguments = ({
4
- command: "build";
5
- skipNextBuild: boolean;
6
- skipWranglerConfigCheck: boolean;
7
- minify: boolean;
8
- } | {
9
- command: "preview" | "deploy" | "upload";
10
- passthroughArgs: string[];
11
- cacheChunkSize?: number;
12
- } | {
13
- command: "populateCache";
14
- target: WranglerTarget;
15
- environment?: string;
16
- cacheChunkSize?: number;
17
- }) & {
18
- outputDir?: string;
19
- };
20
- export declare function getArgs(): Arguments;
21
- export declare function getPassthroughArgs<T extends ParseArgsConfig>(args: string[], { options }: T): string[];
package/dist/cli/args.js DELETED
@@ -1,91 +0,0 @@
1
- import { mkdirSync, statSync } from "node:fs";
2
- import { resolve } from "node:path";
3
- import { parseArgs } from "node:util";
4
- import { getWranglerEnvironmentFlag, isWranglerTarget } from "./utils/run-wrangler.js";
5
- // Config for parsing CLI arguments
6
- const config = {
7
- allowPositionals: true,
8
- strict: false,
9
- options: {
10
- skipBuild: { type: "boolean", short: "s", default: false },
11
- output: { type: "string", short: "o" },
12
- noMinify: { type: "boolean", default: false },
13
- skipWranglerConfigCheck: { type: "boolean", default: false },
14
- cacheChunkSize: { type: "string" },
15
- },
16
- };
17
- export function getArgs() {
18
- const { positionals, values } = parseArgs(config);
19
- const outputDir = typeof values.output === "string" ? resolve(values.output) : undefined;
20
- if (outputDir)
21
- assertDirArg(outputDir, "output", true);
22
- switch (positionals[0]) {
23
- case "build":
24
- return {
25
- command: "build",
26
- outputDir,
27
- skipNextBuild: !!values.skipBuild || ["1", "true", "yes"].includes(String(process.env.SKIP_NEXT_APP_BUILD)),
28
- skipWranglerConfigCheck: !!values.skipWranglerConfigCheck ||
29
- ["1", "true", "yes"].includes(String(process.env.SKIP_WRANGLER_CONFIG_CHECK)),
30
- minify: !values.noMinify,
31
- };
32
- case "preview":
33
- case "deploy":
34
- case "upload":
35
- return {
36
- command: positionals[0],
37
- outputDir,
38
- passthroughArgs: getPassthroughArgs(process.argv, config),
39
- ...(values.cacheChunkSize && { cacheChunkSize: Number(values.cacheChunkSize) }),
40
- };
41
- case "populateCache":
42
- if (!isWranglerTarget(positionals[1])) {
43
- throw new Error(`Error: invalid target for populating the cache, expected 'local' | 'remote'`);
44
- }
45
- return {
46
- command: "populateCache",
47
- outputDir,
48
- target: positionals[1],
49
- environment: getWranglerEnvironmentFlag(process.argv),
50
- ...(values.cacheChunkSize && { cacheChunkSize: Number(values.cacheChunkSize) }),
51
- };
52
- default:
53
- throw new Error("Error: invalid command, expected 'build' | 'preview' | 'deploy' | 'upload' | 'populateCache'");
54
- }
55
- }
56
- export function getPassthroughArgs(args, { options = {} }) {
57
- const passthroughArgs = [];
58
- for (let i = 0; i < args.length; i++) {
59
- if (args[i] === "--") {
60
- passthroughArgs.push(...args.slice(i + 1));
61
- return passthroughArgs;
62
- }
63
- // look for `--arg(=value)`, `-arg(=value)`
64
- const [, name] = /^--?(\w[\w-]*)(=.+)?$/.exec(args[i]) ?? [];
65
- if (name && !(name in options)) {
66
- passthroughArgs.push(args[i]);
67
- // Array args can have multiple values
68
- // ref https://github.com/yargs/yargs-parser/blob/main/README.md#greedy-arrays
69
- while (i < args.length - 1 && !args[i + 1]?.startsWith("-")) {
70
- passthroughArgs.push(args[++i]);
71
- }
72
- }
73
- }
74
- return passthroughArgs;
75
- }
76
- function assertDirArg(path, argName, make) {
77
- let dirStats;
78
- try {
79
- dirStats = statSync(path);
80
- }
81
- catch {
82
- if (!make) {
83
- throw new Error(`Error: the provided${argName ? ` "${argName}"` : ""} input is not a valid path`);
84
- }
85
- mkdirSync(path);
86
- return;
87
- }
88
- if (!dirStats.isDirectory()) {
89
- throw new Error(`Error: the provided${argName ? ` "${argName}"` : ""} input is not a directory`);
90
- }
91
- }