diff --git a/.changeset/odd-colts-walk.md b/.changeset/odd-colts-walk.md new file mode 100644 index 00000000..1bfcf739 --- /dev/null +++ b/.changeset/odd-colts-walk.md @@ -0,0 +1,10 @@ +--- +"@opennextjs/cloudflare": patch +--- + +fix: remote flag not working for preview command's cache population + +Previously, passing the `--remote` flag when running `opennextjs-cloudflare preview --remote` would not result in the remote preview binding being populated, and would throw errors due to a missing preview flag when populating Workers KV. The remote flag is now supported for the cache popoulation step when running the preview command. + +- `opennextjs-cloudflare preview --remote` will populate the remote binding for the preview ID specified in your Wrangler config. +- `opennextjs-cloudflare preview` will continue to populate the local binding in your Wrangler config. diff --git a/examples/overrides/d1-tag-next/wrangler.e2e.jsonc b/examples/overrides/d1-tag-next/wrangler.e2e.jsonc index 499b0533..1fe491ce 100644 --- a/examples/overrides/d1-tag-next/wrangler.e2e.jsonc +++ b/examples/overrides/d1-tag-next/wrangler.e2e.jsonc @@ -15,12 +15,14 @@ { "binding": "NEXT_INC_CACHE_KV", "id": "", + "preview_id": "", }, ], "d1_databases": [ { "binding": "NEXT_TAG_CACHE_D1", "database_id": "NEXT_TAG_CACHE_D1", + "preview_database_id": "NEXT_TAG_CACHE_D1", "database_name": "NEXT_TAG_CACHE_D1", }, ], diff --git a/packages/cloudflare/src/cli/commands/deploy.ts b/packages/cloudflare/src/cli/commands/deploy.ts index 033336c6..6e89d029 100644 --- a/packages/cloudflare/src/cli/commands/deploy.ts +++ b/packages/cloudflare/src/cli/commands/deploy.ts @@ -19,7 +19,7 @@ import { * * @param args */ -export async function deployCommand(args: WithWranglerArgs<{ cacheChunkSize: number }>): Promise { +export async function deployCommand(args: WithWranglerArgs<{ cacheChunkSize?: number }>): Promise { printHeaders("deploy"); const { config } = await retrieveCompiledConfig(); @@ -39,6 +39,7 @@ export async function deployCommand(args: WithWranglerArgs<{ cacheChunkSize: num environment: args.env, wranglerConfigPath: args.wranglerConfigPath, cacheChunkSize: args.cacheChunkSize, + shouldUsePreviewId: false, }); runWrangler( diff --git a/packages/cloudflare/src/cli/commands/populate-cache.ts b/packages/cloudflare/src/cli/commands/populate-cache.ts index f4fcd110..8cc68707 100644 --- a/packages/cloudflare/src/cli/commands/populate-cache.ts +++ b/packages/cloudflare/src/cli/commands/populate-cache.ts @@ -105,10 +105,28 @@ export function getCacheAssets(opts: BuildOptions): CacheAsset[] { } type PopulateCacheOptions = { + /** + * Whether to populate the local or remote cache. + */ target: WranglerTarget; + /** + * Wrangler environment to use. + */ environment?: string; + /** + * Path to the Wrangler config file. + */ wranglerConfigPath?: string; + /** + * Chunk sizes to use when populating KV cache. Ignored for R2. + * + * @default 25 for KV + */ cacheChunkSize?: number; + /** + * Instructs Wrangler to use the preview namespace or ID defined in the Wrangler config for the remote target. + */ + shouldUsePreviewId: boolean; }; async function populateR2IncrementalCache( @@ -197,12 +215,21 @@ async function populateKVIncrementalCache( writeFileSync(chunkPath, JSON.stringify(kvMapping)); - runWrangler(options, ["kv bulk put", quoteShellMeta(chunkPath), `--binding ${KV_CACHE_BINDING_NAME}`], { - target: populateCacheOptions.target, - environment: populateCacheOptions.environment, - configPath: populateCacheOptions.wranglerConfigPath, - logging: "error", - }); + runWrangler( + options, + [ + "kv bulk put", + quoteShellMeta(chunkPath), + `--binding ${KV_CACHE_BINDING_NAME}`, + `--preview ${populateCacheOptions.shouldUsePreviewId}`, + ], + { + target: populateCacheOptions.target, + environment: populateCacheOptions.environment, + configPath: populateCacheOptions.wranglerConfigPath, + logging: "error", + } + ); rmSync(chunkPath); } @@ -228,6 +255,7 @@ function populateD1TagCache( "d1 execute", D1_TAG_BINDING_NAME, `--command "CREATE TABLE IF NOT EXISTS revalidations (tag TEXT NOT NULL, revalidatedAt INTEGER NOT NULL, UNIQUE(tag) ON CONFLICT REPLACE);"`, + `--preview ${populateCacheOptions.shouldUsePreviewId}`, ], { target: populateCacheOptions.target, @@ -301,7 +329,7 @@ export async function populateCache( */ async function populateCacheCommand( target: "local" | "remote", - args: WithWranglerArgs<{ cacheChunkSize: number }> + args: WithWranglerArgs<{ cacheChunkSize?: number }> ) { printHeaders(`populate cache - ${target}`); @@ -315,6 +343,7 @@ async function populateCacheCommand( environment: args.env, wranglerConfigPath: args.wranglerConfigPath, cacheChunkSize: args.cacheChunkSize, + shouldUsePreviewId: false, }); } @@ -345,7 +374,6 @@ export function addPopulateCacheCommand(y: T) { export function withPopulateCacheOptions(args: T) { return withWranglerOptions(args).options("cacheChunkSize", { type: "number", - default: 25, desc: "Number of entries per chunk when populating the cache", }); } diff --git a/packages/cloudflare/src/cli/commands/preview.ts b/packages/cloudflare/src/cli/commands/preview.ts index fbcc44ee..2b41dd3e 100644 --- a/packages/cloudflare/src/cli/commands/preview.ts +++ b/packages/cloudflare/src/cli/commands/preview.ts @@ -16,7 +16,9 @@ import { * * @param args */ -export async function previewCommand(args: WithWranglerArgs<{ cacheChunkSize: number }>): Promise { +export async function previewCommand( + args: WithWranglerArgs<{ cacheChunkSize?: number; remote: boolean }> +): Promise { printHeaders("preview"); const { config } = await retrieveCompiledConfig(); @@ -25,10 +27,11 @@ export async function previewCommand(args: WithWranglerArgs<{ cacheChunkSize: nu const wranglerConfig = readWranglerConfig(args); await populateCache(options, config, wranglerConfig, { - target: "local", + target: args.remote ? "remote" : "local", environment: args.env, wranglerConfigPath: args.wranglerConfigPath, cacheChunkSize: args.cacheChunkSize, + shouldUsePreviewId: args.remote, }); runWrangler(options, ["dev", ...args.wranglerArgs], { logging: "all" }); @@ -43,7 +46,13 @@ export function addPreviewCommand(y: T) { return y.command( "preview", "Preview a built OpenNext app with a Wrangler dev server", - (c) => withPopulateCacheOptions(c), + (c) => + withPopulateCacheOptions(c).option("remote", { + type: "boolean", + alias: "r", + default: false, + desc: "Run on the global Cloudflare network with access to production resources", + }), (args) => previewCommand(withWranglerPassthroughArgs(args)) ); } diff --git a/packages/cloudflare/src/cli/commands/upload.ts b/packages/cloudflare/src/cli/commands/upload.ts index 8c35fb92..b3eff12b 100644 --- a/packages/cloudflare/src/cli/commands/upload.ts +++ b/packages/cloudflare/src/cli/commands/upload.ts @@ -19,7 +19,7 @@ import { * * @param args */ -export async function uploadCommand(args: WithWranglerArgs<{ cacheChunkSize: number }>): Promise { +export async function uploadCommand(args: WithWranglerArgs<{ cacheChunkSize?: number }>): Promise { printHeaders("upload"); const { config } = await retrieveCompiledConfig(); @@ -39,6 +39,7 @@ export async function uploadCommand(args: WithWranglerArgs<{ cacheChunkSize: num environment: args.env, wranglerConfigPath: args.wranglerConfigPath, cacheChunkSize: args.cacheChunkSize, + shouldUsePreviewId: false, }); runWrangler( diff --git a/packages/cloudflare/src/cli/commands/utils.ts b/packages/cloudflare/src/cli/commands/utils.ts index 903191a0..fd42df43 100644 --- a/packages/cloudflare/src/cli/commands/utils.ts +++ b/packages/cloudflare/src/cli/commands/utils.ts @@ -131,6 +131,7 @@ type WranglerInputArgs = { configPath: string | undefined; config: string | undefined; env: string | undefined; + remote?: boolean | undefined; }; /** @@ -154,6 +155,7 @@ function getWranglerArgs(args: WranglerInputArgs & { _: (string | number)[] }): ...(args.configPath ? ["--config", args.configPath] : []), ...(args.config ? ["--config", args.config] : []), ...(args.env ? ["--env", args.env] : []), + ...(args.remote ? ["--remote"] : []), // Note: the first args in `_` will be the commands. ...args._.slice(args._[0] === "populateCache" ? 2 : 1).map((a) => `${a}`), ];