diff --git a/.changeset/cloudflare-current-platform.md b/.changeset/cloudflare-current-platform.md new file mode 100644 index 000000000000..b043c68fd700 --- /dev/null +++ b/.changeset/cloudflare-current-platform.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-cloudflare': patch +--- + +fix: read the current Cloudflare platform proxy after Wrangler config reloads diff --git a/packages/adapter-cloudflare/src/virtual-cloudflare-workers.js b/packages/adapter-cloudflare/src/virtual-cloudflare-workers.js index 189a5e1ce032..3c405e64adf3 100644 --- a/packages/adapter-cloudflare/src/virtual-cloudflare-workers.js +++ b/packages/adapter-cloudflare/src/virtual-cloudflare-workers.js @@ -3,10 +3,8 @@ import { AsyncLocalStorage } from 'node:async_hooks'; const als = new AsyncLocalStorage(); -const proxy = globalThis.__sveltekit_cloudflare_platform; - function get_current_env() { - return als.getStore() ?? proxy?.env; + return als.getStore() ?? globalThis.__sveltekit_cloudflare_platform?.env; } /** @typedef {typeof CloudflareWorkersModule} Module */ @@ -15,7 +13,7 @@ export const env = new Proxy( {}, { get(_, prop) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } const inner = get_current_env(); @@ -26,7 +24,7 @@ export const env = new Proxy( }, set(_, prop, newValue) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } const inner = get_current_env(); @@ -37,7 +35,7 @@ export const env = new Proxy( }, has(_, prop) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } const inner = get_current_env(); @@ -48,7 +46,7 @@ export const env = new Proxy( }, ownKeys(_) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } const inner = get_current_env(); @@ -59,7 +57,7 @@ export const env = new Proxy( }, deleteProperty(_, prop) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } const inner = get_current_env(); @@ -70,7 +68,7 @@ export const env = new Proxy( }, defineProperty(_, prop, attr) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } const inner = get_current_env(); @@ -81,7 +79,7 @@ export const env = new Proxy( }, getOwnPropertyDescriptor(_, prop) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } const inner = get_current_env(); @@ -95,14 +93,14 @@ export const env = new Proxy( /** @type {Module['withEnv']} */ export function withEnv(newEnv, fn) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } return als.run(newEnv, fn); } /** @type {Module['withEnvAndExports']} */ export function withEnvAndExports(newEnv, _, fn) { - if (!proxy) { + if (!globalThis.__sveltekit_cloudflare_platform) { throw new Error(`Cannot access cloudflare:workers in a prerenderable route`); } return als.run(newEnv, fn); diff --git a/packages/adapter-cloudflare/test/apps/workers/test/test.js b/packages/adapter-cloudflare/test/apps/workers/test/test.js index ed75be3c7df5..ba98659416e3 100644 --- a/packages/adapter-cloudflare/test/apps/workers/test/test.js +++ b/packages/adapter-cloudflare/test/apps/workers/test/test.js @@ -1,6 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { expect, test } from '@playwright/test'; +import { location } from '../../../../../../test-utils/deploy.js'; test('worker', async ({ page }) => { await page.goto('/'); @@ -12,6 +13,32 @@ test('cloudflare:workers', async ({ request }) => { expect(await res.text()).toBe('from wrangler.jsonc'); }); +test('cloudflare:workers uses the current bindings after a wrangler config reload', async ({ + request +}) => { + test.skip(!process.env.DEV); + const config_path = path.join(location(process.cwd()), 'config/wrangler.jsonc'); + const original = fs.readFileSync(config_path, 'utf-8'); + + /** @param {string} contents */ + function write_config(contents) { + // Replace atomically so Wrangler cannot read a partially written config. + fs.writeFileSync(`${config_path}.tmp`, contents); + fs.renameSync(`${config_path}.tmp`, config_path); + } + + // Evaluate cloudflare:workers before the platform proxy is replaced. + expect(await (await request.get('/env')).text()).toBe('from wrangler.jsonc'); + + try { + write_config(original.replace('from wrangler.jsonc', 'updated binding')); + await expect.poll(async () => (await request.get('/env')).text()).toBe('updated binding'); + } finally { + write_config(original); + await expect.poll(async () => (await request.get('/env')).text()).toBe('from wrangler.jsonc'); + } +}); + test('Request.cf', async ({ request }) => { const res = await request.get('cf'); const cf = await res.json();