diff --git a/.changeset/shaggy-bobcats-battle.md b/.changeset/shaggy-bobcats-battle.md new file mode 100644 index 00000000..489a389f --- /dev/null +++ b/.changeset/shaggy-bobcats-battle.md @@ -0,0 +1,17 @@ +--- +"@opennextjs/cloudflare": patch +--- + +Adds support for passing options to `initOpenNextCloudflareForDev()`. This allows you to configure how your Cloudflare bindings will behave during [local development](https://opennext.js.org/cloudflare/get-started#11-develop-locally). + +For example, the below configuration will persist the local state of bindings to a custom directory. Which can be useful if you want to share the state between different apps that reuse the same bindings in a monorepo. + +```ts +initOpenNextCloudflareForDev({ + persist: { + path: "../../.wrangler/state/v3/custom-dir", + }, +}); +``` + +You can find the configuration type with it's available options [here](https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/src/api/integrations/platform/index.ts#L32) in the Wrangler source code. diff --git a/packages/cloudflare/src/api/cloudflare-context.ts b/packages/cloudflare/src/api/cloudflare-context.ts index 279b74f5..367eb07a 100644 --- a/packages/cloudflare/src/api/cloudflare-context.ts +++ b/packages/cloudflare/src/api/cloudflare-context.ts @@ -1,5 +1,7 @@ import type { Context, RunningCodeOptions } from "node:vm"; +import type { GetPlatformProxyOptions } from "wrangler"; + import type { DurableObjectQueueHandler } from "./durable-objects/queue"; import { DOShardedTagCache } from "./durable-objects/sharded-tag-cache"; @@ -206,12 +208,20 @@ async function getCloudflareContextAsync< * with the open-next Cloudflare adapter * * Note: this function should only be called inside the Next.js config file, and although async it doesn't need to be `await`ed + * @param options options on how the function should operate and if/where to persist the platform data */ -export async function initOpenNextCloudflareForDev() { +export async function initOpenNextCloudflareForDev(options?: GetPlatformProxyOptions) { const shouldInitializationRun = shouldContextInitializationRun(); if (!shouldInitializationRun) return; - const context = await getCloudflareContextFromWrangler(); + if (options?.environment && process.env.NEXT_DEV_WRANGLER_ENV) { + console.warn( + `'initOpenNextCloudflareForDev' has been called with an environment option while NEXT_DEV_WRANGLER_ENV is set.` + + ` NEXT_DEV_WRANGLER_ENV will be ignored and the environment will be set to: '${options.environment}'` + ); + } + + const context = await getCloudflareContextFromWrangler(options); addCloudflareContextToNodejsGlobal(context); @@ -290,12 +300,16 @@ async function monkeyPatchVmModuleEdgeContext(cloudflareContext: CloudflareConte async function getCloudflareContextFromWrangler< CfProperties extends Record = IncomingRequestCfProperties, Context = ExecutionContext, ->(): Promise> { +>(options?: GetPlatformProxyOptions): Promise> { // Note: we never want wrangler to be bundled in the Next.js app, that's why the import below looks like it does const { getPlatformProxy } = await import(/* webpackIgnore: true */ `${"__wrangler".replaceAll("_", "")}`); + + // This allows the selection of a wrangler environment while running in next dev mode + const environment = options?.environment ?? process.env.NEXT_DEV_WRANGLER_ENV; + const { env, cf, ctx } = await getPlatformProxy({ - // This allows the selection of a wrangler environment while running in next dev mode - environment: process.env.NEXT_DEV_WRANGLER_ENV, + ...options, + environment, }); return { env,