From 8074629a3b3fb4e7931cf2f753d733022592dfa1 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Fri, 30 Jun 2023 17:18:30 +0200 Subject: [PATCH 01/22] add support for advanced mode --- packages/integrations/cloudflare/src/server.advanced.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index 9758b8b19566..f9e469f5c221 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -32,6 +32,7 @@ export function createExports(manifest: SSRManifest) { Symbol.for('astro.clientAddress'), request.headers.get('cf-connecting-ip') ); + // @deprecated: getRuntime() can be removed, Astro.locals.env is the new place Reflect.set(request, Symbol.for('runtime'), { env, name: 'cloudflare', @@ -42,7 +43,7 @@ export function createExports(manifest: SSRManifest) { context.waitUntil(promise); }, }); - let response = await app.render(request, routeData); + let response = await app.render(request, routeData, { env }); if (app.setCookieHeaders) { for (const setCookieHeader of app.setCookieHeaders(response)) { From 980432a0c678c1028491a1ca42912fa5dfe89cf5 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Fri, 30 Jun 2023 17:21:25 +0200 Subject: [PATCH 02/22] add support for directory mode --- .../cloudflare/src/server.directory.ts | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 3e9531a56a49..cf5465d4c5c3 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -10,16 +10,11 @@ if (!isNode) { export function createExports(manifest: SSRManifest) { const app = new App(manifest); - const onRequest = async ({ - request, - next, - ...runtimeEnv - }: { - request: Request & CFRequest; - next: (request: Request) => void; - waitUntil: EventContext['waitUntil']; - } & Record) => { - process.env = runtimeEnv.env as any; + const onRequest = async (context: EventContext) => { + const request = context.request as Request & CFRequest + const { next, env } = context + + process.env = env as any; const { pathname } = new URL(request.url); // static assets fallback, in case default _routes.json is not used @@ -38,17 +33,19 @@ export function createExports(manifest: SSRManifest) { Symbol.for('astro.clientAddress'), request.headers.get('cf-connecting-ip') ); + // @deprecated: getRuntime() can be removed, Astro.locals.env is the new place Reflect.set(request, Symbol.for('runtime'), { - ...runtimeEnv, + ...context, waitUntil: (promise: Promise) => { - runtimeEnv.waitUntil(promise); + context.waitUntil(promise); }, name: 'cloudflare', next, caches, cf: request.cf, }); - let response = await app.render(request, routeData); + + let response = await app.render(request, routeData, { env }); if (app.setCookieHeaders) { for (const setCookieHeader of app.setCookieHeaders(response)) { From 6f9d9e96ce0aca28ef173eabdc00ea1f20fb69c4 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Mon, 3 Jul 2023 19:34:34 +0200 Subject: [PATCH 03/22] use asset fallback as in cloudflare's docs --- packages/integrations/cloudflare/src/index.ts | 16 ++++++++-------- .../cloudflare/src/server.directory.ts | 6 +----- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/packages/integrations/cloudflare/src/index.ts b/packages/integrations/cloudflare/src/index.ts index 336f747cc463..80c78e71aad1 100644 --- a/packages/integrations/cloudflare/src/index.ts +++ b/packages/integrations/cloudflare/src/index.ts @@ -21,15 +21,15 @@ interface BuildConfig { export function getAdapter(isModeDirectory: boolean): AstroAdapter { return isModeDirectory ? { - name: '@astrojs/cloudflare', - serverEntrypoint: '@astrojs/cloudflare/server.directory.js', - exports: ['onRequest', 'manifest'], - } + name: '@astrojs/cloudflare', + serverEntrypoint: '@astrojs/cloudflare/server.directory.js', + exports: ['onRequest', 'manifest'], + } : { - name: '@astrojs/cloudflare', - serverEntrypoint: '@astrojs/cloudflare/server.advanced.js', - exports: ['default'], - }; + name: '@astrojs/cloudflare', + serverEntrypoint: '@astrojs/cloudflare/server.advanced.js', + exports: ['default'], + }; } const SHIM = `globalThis.process = { diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index cf5465d4c5c3..45108776b0f4 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -19,11 +19,7 @@ export function createExports(manifest: SSRManifest) { const { pathname } = new URL(request.url); // static assets fallback, in case default _routes.json is not used if (manifest.assets.has(pathname)) { - // we need this so the page does not error - // https://developers.cloudflare.com/pages/platform/functions/advanced-mode/#set-up-a-function - return (runtimeEnv.env as EventContext['env']).ASSETS.fetch( - request - ); + return env.ASSETS.fetch(request) } let routeData = app.match(request, { matchNotFound: true }); From 2551fd2c83c9d38dd7d408d3307e2c8fe6ac8157 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Wed, 5 Jul 2023 16:44:53 +0200 Subject: [PATCH 04/22] update locals --- .../cloudflare/src/server.advanced.ts | 17 ++++++++++++++++- .../cloudflare/src/server.directory.ts | 16 +++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index f9e469f5c221..acc4ed171dec 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -32,6 +32,7 @@ export function createExports(manifest: SSRManifest) { Symbol.for('astro.clientAddress'), request.headers.get('cf-connecting-ip') ); + // @deprecated: getRuntime() can be removed, Astro.locals.env is the new place Reflect.set(request, Symbol.for('runtime'), { env, @@ -43,7 +44,21 @@ export function createExports(manifest: SSRManifest) { context.waitUntil(promise); }, }); - let response = await app.render(request, routeData, { env }); + + let response = await app.render(request, routeData, { + env: env, + cf: request.cf, + runtime: { + ...context, + waitUntil: (promise: Promise) => { + context.waitUntil(promise); + }, + env: env, + name: 'cloudlare', + caches: caches, + cf: request.cf, + } + }); if (app.setCookieHeaders) { for (const setCookieHeader of app.setCookieHeaders(response)) { diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 45108776b0f4..b069ce3be3b9 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -29,6 +29,7 @@ export function createExports(manifest: SSRManifest) { Symbol.for('astro.clientAddress'), request.headers.get('cf-connecting-ip') ); + // @deprecated: getRuntime() can be removed, Astro.locals.env is the new place Reflect.set(request, Symbol.for('runtime'), { ...context, @@ -41,7 +42,20 @@ export function createExports(manifest: SSRManifest) { cf: request.cf, }); - let response = await app.render(request, routeData, { env }); + let response = await app.render(request, routeData, { + env: env, + cf: request.cf, + runtime: { + ...context, + waitUntil: (promise: Promise) => { + context.waitUntil(promise); + }, + name: 'cloudflare', + next, + caches, + cf: request.cf, + } + }); if (app.setCookieHeaders) { for (const setCookieHeader of app.setCookieHeaders(response)) { From da5c3d7ea3a1cc3e5ef86c386156e96864b01fa7 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Wed, 5 Jul 2023 17:13:17 +0200 Subject: [PATCH 05/22] come up with new runtime in `Astro.locals` --- .../cloudflare/src/server.advanced.ts | 14 ++++++-------- .../cloudflare/src/server.directory.ts | 16 +++++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index acc4ed171dec..30a97bccc1c7 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -46,17 +46,15 @@ export function createExports(manifest: SSRManifest) { }); let response = await app.render(request, routeData, { - env: env, - cf: request.cf, runtime: { - ...context, - waitUntil: (promise: Promise) => { - context.waitUntil(promise); - }, + // request: Request; // we don't need this because of Astro.request, even if they are not the same + // functionPath: string; // we don't need this + waitUntil: (promise: Promise) => context.waitUntil(promise), + // passThroughOnException: () => void; // we don't need this + // next: (input?: Request | string, init?: RequestInit) => Promise; // we don't need this env: env, - name: 'cloudlare', - caches: caches, cf: request.cf, + caches: caches, // Cloudflare Workers runtime exposes a single global cache object } }); diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index b069ce3be3b9..0e2f3e100588 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -46,14 +46,16 @@ export function createExports(manifest: SSRManifest) { env: env, cf: request.cf, runtime: { - ...context, - waitUntil: (promise: Promise) => { - context.waitUntil(promise); - }, - name: 'cloudflare', - next, - caches, + // request: Request; // we don't need this because of Astro.request, even if they are not the same + // functionPath: string; // we don't need this + waitUntil: (promise: Promise) => context.waitUntil(promise), + // passThroughOnException: () => void; // we don't need this + // next: (input?: Request | string, init?: RequestInit) => Promise; // we don't need this + env: context.env, + params: context.params, // Holds the values from dynamic routing. See CF Docs for more info. We do have Astro.props, so not sure + // data: Data; // I don't think we need this: https://community.cloudflare.com/t/what-is-context-data-in-pages-functions/476559/7 cf: request.cf, + caches: caches, // Cloudflare Workers runtime exposes a single global cache object } }); From f989dcab7e156ee581dda195ad28fb69aad6dbd3 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Sat, 29 Jul 2023 06:48:16 +0200 Subject: [PATCH 06/22] add overwrite protection --- packages/astro/src/core/endpoint/index.ts | 6 +++++- packages/astro/src/core/render/context.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts index 485190e479ca..20b6d00574c0 100644 --- a/packages/astro/src/core/endpoint/index.ts +++ b/packages/astro/src/core/endpoint/index.ts @@ -89,7 +89,11 @@ export function createAPIContext({ if (typeof val !== 'object') { throw new AstroError(AstroErrorData.LocalsNotAnObject); } else { - Reflect.set(request, clientLocalsSymbol, val); + if (Reflect.has(request, 'runtime') && !Reflect.has(val, 'runtime')) { + throw new AstroError(AstroErrorData.LocalsNoRuntime); + } else { + Reflect.set(request, clientLocalsSymbol, val); + } } }, }); diff --git a/packages/astro/src/core/render/context.ts b/packages/astro/src/core/render/context.ts index 5b26eda18e39..37687cd58b98 100644 --- a/packages/astro/src/core/render/context.ts +++ b/packages/astro/src/core/render/context.ts @@ -68,7 +68,11 @@ export async function createRenderContext( if (typeof val !== 'object') { throw new AstroError(AstroErrorData.LocalsNotAnObject); } else { - Reflect.set(request, clientLocalsSymbol, val); + if (Reflect.has(request, 'runtime') && !Reflect.has(val, 'runtime')) { + throw new AstroError(AstroErrorData.LocalsNoRuntime); + } else { + Reflect.set(request, clientLocalsSymbol, val); + } } }, }); From 88855ce46c51ae3ae931cb48c14925ba55ee0112 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Sat, 29 Jul 2023 07:01:27 +0200 Subject: [PATCH 07/22] minor cleanup --- packages/integrations/cloudflare/README.md | 6 ++--- .../cloudflare/src/server.advanced.ts | 17 ++++++------- .../cloudflare/src/server.directory.ts | 24 +++++++++---------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/packages/integrations/cloudflare/README.md b/packages/integrations/cloudflare/README.md index 45f8e01bac9f..61db6effc6ec 100644 --- a/packages/integrations/cloudflare/README.md +++ b/packages/integrations/cloudflare/README.md @@ -73,12 +73,10 @@ It's then possible to update the preview script in your `package.json` to `"prev ## Access to the Cloudflare runtime -You can access all the Cloudflare bindings and environment variables from Astro components and API routes through the adapter API. +You can access all the Cloudflare bindings and environment variables from Astro components and API routes through `Astro.locals`. ```js -import { getRuntime } from '@astrojs/cloudflare/runtime'; - -getRuntime(Astro.request); +const env = Astro.locals.runtime.env; ``` Depending on your adapter mode (advanced = worker, directory = pages), the runtime object will look a little different due to differences in the Cloudflare API. diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index 30a97bccc1c7..ecbc35f43062 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -16,7 +16,7 @@ export function createExports(manifest: SSRManifest) { const app = new App(manifest); const fetch = async (request: Request & CFRequest, env: Env, context: ExecutionContext) => { - process.env = env as any; + process.env = env as any; // would love to remove this any cast in the future const { pathname } = new URL(request.url); @@ -47,15 +47,16 @@ export function createExports(manifest: SSRManifest) { let response = await app.render(request, routeData, { runtime: { - // request: Request; // we don't need this because of Astro.request, even if they are not the same - // functionPath: string; // we don't need this - waitUntil: (promise: Promise) => context.waitUntil(promise), - // passThroughOnException: () => void; // we don't need this - // next: (input?: Request | string, init?: RequestInit) => Promise; // we don't need this + // request: Request; // not needed because we have Astro.request, thus they are minor differences + // functionPath: string; // not needed + waitUntil: (promise: Promise) => { + context.waitUntil(promise); + }, + // passThroughOnException: () => void; // probably not needed ?? env: env, cf: request.cf, - caches: caches, // Cloudflare Workers runtime exposes a single global cache object - } + caches: caches, + }, }); if (app.setCookieHeaders) { diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 0e2f3e100588..d6aa1c73c00b 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -10,11 +10,11 @@ if (!isNode) { export function createExports(manifest: SSRManifest) { const app = new App(manifest); - const onRequest = async (context: EventContext) => { - const request = context.request as Request & CFRequest + const onRequest = async (context: EventContext) => { + const request = context.request as CFRequest & Request const { next, env } = context - process.env = env as any; + process.env = env as any; // would love to remove this any cast in the future const { pathname } = new URL(request.url); // static assets fallback, in case default _routes.json is not used @@ -30,7 +30,7 @@ export function createExports(manifest: SSRManifest) { request.headers.get('cf-connecting-ip') ); - // @deprecated: getRuntime() can be removed, Astro.locals.env is the new place + // @deprecated: getRuntime() can be removed, use `Astro.locals.runtime` instead Reflect.set(request, Symbol.for('runtime'), { ...context, waitUntil: (promise: Promise) => { @@ -46,16 +46,16 @@ export function createExports(manifest: SSRManifest) { env: env, cf: request.cf, runtime: { - // request: Request; // we don't need this because of Astro.request, even if they are not the same - // functionPath: string; // we don't need this - waitUntil: (promise: Promise) => context.waitUntil(promise), - // passThroughOnException: () => void; // we don't need this - // next: (input?: Request | string, init?: RequestInit) => Promise; // we don't need this + // request: Request; // not needed because we have Astro.request, thus they are minor differences + // functionPath: string; // not needed + waitUntil: (promise: Promise) => { context.waitUntil(promise); }, + // passThroughOnException: () => void; // probably not needed ?? + // next: (input?: Request | string, init?: RequestInit) => Promise; // probably not needed ?? env: context.env, - params: context.params, // Holds the values from dynamic routing. See CF Docs for more info. We do have Astro.props, so not sure - // data: Data; // I don't think we need this: https://community.cloudflare.com/t/what-is-context-data-in-pages-functions/476559/7 + params: context.params, // Isn't that the same as Astro.props ?? + // data: Data; // Should we include it ??: https://community.cloudflare.com/t/what-is-context-data-in-pages-functions/476559/7 cf: request.cf, - caches: caches, // Cloudflare Workers runtime exposes a single global cache object + caches: caches, } }); From c7c781fbd1a38d19b189eb9bca525f4a051b73d9 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Sat, 29 Jul 2023 07:03:35 +0200 Subject: [PATCH 08/22] changeset --- .changeset/fuzzy-jobs-explain.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/fuzzy-jobs-explain.md diff --git a/.changeset/fuzzy-jobs-explain.md b/.changeset/fuzzy-jobs-explain.md new file mode 100644 index 000000000000..fd85e291021b --- /dev/null +++ b/.changeset/fuzzy-jobs-explain.md @@ -0,0 +1,9 @@ +--- +'@astrojs/cloudflare': minor +--- + +Expose the runtime bindings & environmental variabels via `Astro.locals` + + ```js + const env = Astro.locals.runtime.env; + ``` From c0e020553354a2c1f42739ef02641edc1162c9d0 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Mon, 31 Jul 2023 20:43:22 +0200 Subject: [PATCH 09/22] address review comments --- packages/astro/src/core/endpoint/index.ts | 6 +----- packages/astro/src/core/render/context.ts | 6 +----- .../integrations/cloudflare/src/server.advanced.ts | 9 ++++----- .../integrations/cloudflare/src/server.directory.ts | 13 +++++-------- 4 files changed, 11 insertions(+), 23 deletions(-) diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts index 20b6d00574c0..485190e479ca 100644 --- a/packages/astro/src/core/endpoint/index.ts +++ b/packages/astro/src/core/endpoint/index.ts @@ -89,11 +89,7 @@ export function createAPIContext({ if (typeof val !== 'object') { throw new AstroError(AstroErrorData.LocalsNotAnObject); } else { - if (Reflect.has(request, 'runtime') && !Reflect.has(val, 'runtime')) { - throw new AstroError(AstroErrorData.LocalsNoRuntime); - } else { - Reflect.set(request, clientLocalsSymbol, val); - } + Reflect.set(request, clientLocalsSymbol, val); } }, }); diff --git a/packages/astro/src/core/render/context.ts b/packages/astro/src/core/render/context.ts index 37687cd58b98..5b26eda18e39 100644 --- a/packages/astro/src/core/render/context.ts +++ b/packages/astro/src/core/render/context.ts @@ -68,11 +68,7 @@ export async function createRenderContext( if (typeof val !== 'object') { throw new AstroError(AstroErrorData.LocalsNotAnObject); } else { - if (Reflect.has(request, 'runtime') && !Reflect.has(val, 'runtime')) { - throw new AstroError(AstroErrorData.LocalsNoRuntime); - } else { - Reflect.set(request, clientLocalsSymbol, val); - } + Reflect.set(request, clientLocalsSymbol, val); } }, }); diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index ecbc35f43062..04dfef60f093 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -16,7 +16,9 @@ export function createExports(manifest: SSRManifest) { const app = new App(manifest); const fetch = async (request: Request & CFRequest, env: Env, context: ExecutionContext) => { - process.env = env as any; // would love to remove this any cast in the future + // TODO: remove this any cast in the future + // REF: the type cast to any is needed because the Cloudflare Env Type is not assignable to type 'ProcessEnv' + process.env = env as any; const { pathname } = new URL(request.url); @@ -33,7 +35,7 @@ export function createExports(manifest: SSRManifest) { request.headers.get('cf-connecting-ip') ); - // @deprecated: getRuntime() can be removed, Astro.locals.env is the new place + // @deprecated: getRuntime() can be removed in the next major release, after testing Reflect.set(request, Symbol.for('runtime'), { env, name: 'cloudflare', @@ -47,12 +49,9 @@ export function createExports(manifest: SSRManifest) { let response = await app.render(request, routeData, { runtime: { - // request: Request; // not needed because we have Astro.request, thus they are minor differences - // functionPath: string; // not needed waitUntil: (promise: Promise) => { context.waitUntil(promise); }, - // passThroughOnException: () => void; // probably not needed ?? env: env, cf: request.cf, caches: caches, diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index d6aa1c73c00b..05b5884f9250 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -14,7 +14,9 @@ export function createExports(manifest: SSRManifest) { const request = context.request as CFRequest & Request const { next, env } = context - process.env = env as any; // would love to remove this any cast in the future + // TODO: remove this any cast in the future + // REF: the type cast to any is needed because the Cloudflare Env Type is not assignable to type 'ProcessEnv' + process.env = env as any; const { pathname } = new URL(request.url); // static assets fallback, in case default _routes.json is not used @@ -30,7 +32,7 @@ export function createExports(manifest: SSRManifest) { request.headers.get('cf-connecting-ip') ); - // @deprecated: getRuntime() can be removed, use `Astro.locals.runtime` instead + // @deprecated: getRuntime() can be removed in the next major release, after testing Reflect.set(request, Symbol.for('runtime'), { ...context, waitUntil: (promise: Promise) => { @@ -46,14 +48,9 @@ export function createExports(manifest: SSRManifest) { env: env, cf: request.cf, runtime: { - // request: Request; // not needed because we have Astro.request, thus they are minor differences - // functionPath: string; // not needed waitUntil: (promise: Promise) => { context.waitUntil(promise); }, - // passThroughOnException: () => void; // probably not needed ?? - // next: (input?: Request | string, init?: RequestInit) => Promise; // probably not needed ?? env: context.env, - params: context.params, // Isn't that the same as Astro.props ?? - // data: Data; // Should we include it ??: https://community.cloudflare.com/t/what-is-context-data-in-pages-functions/476559/7 + params: context.params, // These are params from Cloudflare, possible equal to Astro.params (unvalidated) cf: request.cf, caches: caches, } From a01fc21b9310dde583bb2fcf6d72609607465937 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Mon, 31 Jul 2023 21:15:18 +0200 Subject: [PATCH 10/22] move overwrite protection to adapter --- .../cloudflare/src/server.advanced.ts | 40 ++++++++++++++--- .../cloudflare/src/server.directory.ts | 44 ++++++++++++++----- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index 04dfef60f093..3439fa1c201a 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -12,6 +12,17 @@ type Env = { name: string; }; +interface CloudflareContext { + locals: { + runtime: { + waitUntil: (promise: Promise) => void; + env: Env; + cf: CFRequest['cf']; + caches: typeof caches; + }; + }; +} + export function createExports(manifest: SSRManifest) { const app = new App(manifest); @@ -47,17 +58,32 @@ export function createExports(manifest: SSRManifest) { }, }); - let response = await app.render(request, routeData, { - runtime: { - waitUntil: (promise: Promise) => { - context.waitUntil(promise); + const cloudflareContext = {} as CloudflareContext; + + // We define a custom property, so we can check the value passed to locals + Object.defineProperty(cloudflareContext, 'locals', { + enumerable: true, + // we should protect top-level locals from being overwritten + // users should just use nested properties, e.g. locals.test = "foo" + writable: false, + configurable: false, + value: { + runtime: { + waitUntil: (promise: Promise) => { + context.waitUntil(promise); + }, + env: env, + cf: request.cf, + caches: caches, }, - env: env, - cf: request.cf, - caches: caches, }, }); + // We should freeze the runtime object, to make sure it&nested properties are not mutated + Object.freeze(cloudflareContext.locals.runtime); + + let response = await app.render(request, routeData, cloudflareContext.locals); + if (app.setCookieHeaders) { for (const setCookieHeader of app.setCookieHeaders(response)) { response.headers.append('Set-Cookie', setCookieHeader); diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 05b5884f9250..53edb5408db5 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -7,6 +7,17 @@ if (!isNode) { process.env = getProcessEnvProxy(); } +interface CloudflareContext { + locals: { + runtime: { + waitUntil: (promise: Promise) => void; + env: Env; + cf: CFRequest['cf']; + caches: typeof caches; + }; + }; +} + export function createExports(manifest: SSRManifest) { const app = new App(manifest); @@ -44,18 +55,31 @@ export function createExports(manifest: SSRManifest) { cf: request.cf, }); - let response = await app.render(request, routeData, { - env: env, - cf: request.cf, - runtime: { - waitUntil: (promise: Promise) => { context.waitUntil(promise); }, - env: context.env, - params: context.params, // These are params from Cloudflare, possible equal to Astro.params (unvalidated) - cf: request.cf, - caches: caches, - } + const cloudflareContext = {} as CloudflareContext; + + // We define a custom property, so we can check the value passed to locals + Object.defineProperty(cloudflareContext, 'locals', { + enumerable: true, + // we should protect top-level locals from being overwritten + // users should just use nested properties, e.g. locals.test = "foo" + writable: false, + configurable: false, + value: { + runtime: { + waitUntil: (promise: Promise) => { context.waitUntil(promise); }, + env: context.env, + params: context.params, // These are params from Cloudflare, possible equal to Astro.params (unvalidated) + cf: request.cf, + caches: caches, + }, + }, }); + // We should freeze the runtime object, to make sure it&nested properties are not mutated + Object.freeze(cloudflareContext.locals.runtime); + + let response = await app.render(request, routeData, cloudflareContext.locals); + if (app.setCookieHeaders) { for (const setCookieHeader of app.setCookieHeaders(response)) { response.headers.append('Set-Cookie', setCookieHeader); From 6c76c5987ab202c331570a5f953741211b43877b Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Mon, 31 Jul 2023 21:21:30 +0200 Subject: [PATCH 11/22] fix types --- packages/integrations/cloudflare/src/server.directory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 53edb5408db5..ddf684d25279 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -11,7 +11,7 @@ interface CloudflareContext { locals: { runtime: { waitUntil: (promise: Promise) => void; - env: Env; + env: EventContext['env']; cf: CFRequest['cf']; caches: typeof caches; }; From a22724c7c5cd003c6cc4a62e3435f2e510c9e627 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Mon, 7 Aug 2023 13:44:50 +0200 Subject: [PATCH 12/22] fix comment --- packages/integrations/cloudflare/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/cloudflare/src/index.ts b/packages/integrations/cloudflare/src/index.ts index 80c78e71aad1..aa55af3d4413 100644 --- a/packages/integrations/cloudflare/src/index.ts +++ b/packages/integrations/cloudflare/src/index.ts @@ -210,7 +210,7 @@ export default function createIntegration(args?: Options): AstroIntegration { } } - // // // throw the server folder in the bin + // throw the server folder in the bin const serverUrl = new URL(_buildConfig.server); await fs.promises.rm(serverUrl, { recursive: true, force: true }); From e4da967631af6ee21a8a63fe6d171c53f78688e5 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Tue, 8 Aug 2023 14:03:15 +0200 Subject: [PATCH 13/22] resolve review comments --- .../cloudflare/src/server.advanced.ts | 37 ++++--------- .../cloudflare/src/server.directory.ts | 53 +++++++------------ 2 files changed, 31 insertions(+), 59 deletions(-) diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index 3439fa1c201a..f259d69df080 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -12,15 +12,13 @@ type Env = { name: string; }; -interface CloudflareContext { - locals: { +interface WorkerRuntime { runtime: { waitUntil: (promise: Promise) => void; env: Env; cf: CFRequest['cf']; caches: typeof caches; }; - }; } export function createExports(manifest: SSRManifest) { @@ -46,7 +44,7 @@ export function createExports(manifest: SSRManifest) { request.headers.get('cf-connecting-ip') ); - // @deprecated: getRuntime() can be removed in the next major release, after testing + // @deprecated: getRuntime() can be removed in the next major release, after testing runtime in locals Reflect.set(request, Symbol.for('runtime'), { env, name: 'cloudflare', @@ -58,31 +56,18 @@ export function createExports(manifest: SSRManifest) { }, }); - const cloudflareContext = {} as CloudflareContext; - - // We define a custom property, so we can check the value passed to locals - Object.defineProperty(cloudflareContext, 'locals', { - enumerable: true, - // we should protect top-level locals from being overwritten - // users should just use nested properties, e.g. locals.test = "foo" - writable: false, - configurable: false, - value: { - runtime: { - waitUntil: (promise: Promise) => { - context.waitUntil(promise); - }, - env: env, - cf: request.cf, - caches: caches, + const locals = { + runtime: { + waitUntil: (promise: Promise) => { + context.waitUntil(promise); }, + env: env, + cf: request.cf, + caches: caches, }, - }); - - // We should freeze the runtime object, to make sure it&nested properties are not mutated - Object.freeze(cloudflareContext.locals.runtime); + } satisfies WorkerRuntime; - let response = await app.render(request, routeData, cloudflareContext.locals); + let response = await app.render(request, routeData, locals); if (app.setCookieHeaders) { for (const setCookieHeader of app.setCookieHeaders(response)) { diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index ddf684d25279..38849e320503 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -7,14 +7,12 @@ if (!isNode) { process.env = getProcessEnvProxy(); } -interface CloudflareContext { - locals: { - runtime: { - waitUntil: (promise: Promise) => void; - env: EventContext['env']; - cf: CFRequest['cf']; - caches: typeof caches; - }; +interface FunctionRuntime { + runtime: { + waitUntil: (promise: Promise) => void; + env: EventContext['env']; + cf: CFRequest['cf']; + caches: typeof caches; }; } @@ -22,8 +20,8 @@ export function createExports(manifest: SSRManifest) { const app = new App(manifest); const onRequest = async (context: EventContext) => { - const request = context.request as CFRequest & Request - const { next, env } = context + const request = context.request as CFRequest & Request; + const { next, env } = context; // TODO: remove this any cast in the future // REF: the type cast to any is needed because the Cloudflare Env Type is not assignable to type 'ProcessEnv' @@ -32,7 +30,7 @@ export function createExports(manifest: SSRManifest) { const { pathname } = new URL(request.url); // static assets fallback, in case default _routes.json is not used if (manifest.assets.has(pathname)) { - return env.ASSETS.fetch(request) + return env.ASSETS.fetch(request); } let routeData = app.match(request, { matchNotFound: true }); @@ -43,7 +41,7 @@ export function createExports(manifest: SSRManifest) { request.headers.get('cf-connecting-ip') ); - // @deprecated: getRuntime() can be removed in the next major release, after testing + // @deprecated: getRuntime() can be removed in the next major release, after testing runtime in locals Reflect.set(request, Symbol.for('runtime'), { ...context, waitUntil: (promise: Promise) => { @@ -55,30 +53,19 @@ export function createExports(manifest: SSRManifest) { cf: request.cf, }); - const cloudflareContext = {} as CloudflareContext; - - // We define a custom property, so we can check the value passed to locals - Object.defineProperty(cloudflareContext, 'locals', { - enumerable: true, - // we should protect top-level locals from being overwritten - // users should just use nested properties, e.g. locals.test = "foo" - writable: false, - configurable: false, - value: { - runtime: { - waitUntil: (promise: Promise) => { context.waitUntil(promise); }, - env: context.env, - params: context.params, // These are params from Cloudflare, possible equal to Astro.params (unvalidated) - cf: request.cf, - caches: caches, + const locals = { + runtime: { + waitUntil: (promise: Promise) => { + context.waitUntil(promise); }, + env: context.env, + params: context.params, // These are params from Cloudflare, possible equal to Astro.params (unvalidated) + cf: request.cf, + caches: caches, }, - }); + } satisfies FunctionRuntime; - // We should freeze the runtime object, to make sure it&nested properties are not mutated - Object.freeze(cloudflareContext.locals.runtime); - - let response = await app.render(request, routeData, cloudflareContext.locals); + let response = await app.render(request, routeData, locals); if (app.setCookieHeaders) { for (const setCookieHeader of app.setCookieHeaders(response)) { From e387a538fce2f0a46f110781d7f105fbe537b840 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Tue, 8 Aug 2023 14:05:51 +0200 Subject: [PATCH 14/22] update changeset --- .changeset/fuzzy-jobs-explain.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.changeset/fuzzy-jobs-explain.md b/.changeset/fuzzy-jobs-explain.md index fd85e291021b..a4b8d2b512f2 100644 --- a/.changeset/fuzzy-jobs-explain.md +++ b/.changeset/fuzzy-jobs-explain.md @@ -4,6 +4,10 @@ Expose the runtime bindings & environmental variabels via `Astro.locals` - ```js - const env = Astro.locals.runtime.env; + ```diff + - import { getRuntime } from '@astrojs/cloudflare/runtime'; + - getRuntime(Astro.request); + + + const runtime = Astro.locals.runtime; + + const env = runtime.env; ``` From 8ca265b26b442eb9e9eb236c7b7519d9aeee8cad Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Tue, 8 Aug 2023 15:15:28 +0200 Subject: [PATCH 15/22] add test --- .../cloudflare/src/server.directory.ts | 1 - .../integrations/cloudflare/test/cf.test.js | 1 + .../test/fixtures/runtime/astro.config.mjs | 8 ++++ .../test/fixtures/runtime/package.json | 9 +++++ .../fixtures/runtime/src/pages/index.astro | 15 ++++++++ .../cloudflare/test/runtime.test.js | 37 +++++++++++++++++++ pnpm-lock.yaml | 9 +++++ 7 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 packages/integrations/cloudflare/test/fixtures/runtime/astro.config.mjs create mode 100644 packages/integrations/cloudflare/test/fixtures/runtime/package.json create mode 100644 packages/integrations/cloudflare/test/fixtures/runtime/src/pages/index.astro create mode 100644 packages/integrations/cloudflare/test/runtime.test.js diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 38849e320503..8312fb0594cd 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -59,7 +59,6 @@ export function createExports(manifest: SSRManifest) { context.waitUntil(promise); }, env: context.env, - params: context.params, // These are params from Cloudflare, possible equal to Astro.params (unvalidated) cf: request.cf, caches: caches, }, diff --git a/packages/integrations/cloudflare/test/cf.test.js b/packages/integrations/cloudflare/test/cf.test.js index 559df5c7601e..8e1d4f97fc76 100644 --- a/packages/integrations/cloudflare/test/cf.test.js +++ b/packages/integrations/cloudflare/test/cf.test.js @@ -31,6 +31,7 @@ describe('Cf metadata and caches', () => { let html = await res.text(); let $ = cheerio.load(html); // console.log($('#cf').text(), html); + // console.log($('#env').text(), html); expect($('#cf').text()).to.contain('city'); expect($('#hasCache').text()).to.equal('true'); }); diff --git a/packages/integrations/cloudflare/test/fixtures/runtime/astro.config.mjs b/packages/integrations/cloudflare/test/fixtures/runtime/astro.config.mjs new file mode 100644 index 000000000000..f92829843d3c --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/runtime/astro.config.mjs @@ -0,0 +1,8 @@ +import { defineConfig } from 'astro/config'; +import cloudflare from '@astrojs/cloudflare'; + + +export default defineConfig({ + adapter: cloudflare(), + output: 'server', +}); diff --git a/packages/integrations/cloudflare/test/fixtures/runtime/package.json b/packages/integrations/cloudflare/test/fixtures/runtime/package.json new file mode 100644 index 000000000000..71ac16647693 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/runtime/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/astro-cloudflare-runtime", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/cloudflare": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/integrations/cloudflare/test/fixtures/runtime/src/pages/index.astro b/packages/integrations/cloudflare/test/fixtures/runtime/src/pages/index.astro new file mode 100644 index 000000000000..320e8e16243f --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/runtime/src/pages/index.astro @@ -0,0 +1,15 @@ +--- +const runtime = Astro.locals.runtime; +const env = runtime.env; +--- + + + Testing + + +

Testing

+
{JSON.stringify(runtime.cf)}
+
{JSON.stringify(env)}
+
{!!runtime.caches}
+ + diff --git a/packages/integrations/cloudflare/test/runtime.test.js b/packages/integrations/cloudflare/test/runtime.test.js new file mode 100644 index 000000000000..df27c239988c --- /dev/null +++ b/packages/integrations/cloudflare/test/runtime.test.js @@ -0,0 +1,37 @@ +import { loadFixture, runCLI } from './test-utils.js'; +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import cloudflare from '../dist/index.js'; + +describe('Runtime Locals', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + /** @type {import('./test-utils.js').WranglerCLI} */ + let cli; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/runtime/', + output: 'server', + adapter: cloudflare(), + }); + await fixture.build(); + + cli = runCLI('./fixtures/runtime/', { silent: true, port: 8788 }); + await cli.ready; + }); + + after(async () => { + await cli.stop(); + }); + + it('has CF and Caches', async () => { + let res = await fetch(`http://localhost:8788/`); + expect(res.status).to.equal(200); + let html = await res.text(); + let $ = cheerio.load(html); + console.log($('#cf').text(), html); + expect($('#cf').text()).to.contain('city'); + expect($('#hasCache').text()).to.equal('true'); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3e47be814395..5b803af957d8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3715,6 +3715,15 @@ importers: specifier: workspace:* version: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/runtime: + dependencies: + '@astrojs/cloudflare': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/split: dependencies: '@astrojs/cloudflare': From 0cee78b6d7cf10f2ef11e0fbe3dc67d800ed09cc Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Tue, 8 Aug 2023 15:28:08 +0200 Subject: [PATCH 16/22] redo ts --- packages/integrations/cloudflare/src/server.advanced.ts | 4 ++-- packages/integrations/cloudflare/src/server.directory.ts | 4 ++-- packages/integrations/cloudflare/test/cf.test.js | 1 - packages/integrations/cloudflare/test/runtime.test.js | 3 ++- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index f259d69df080..438cb56a6ae6 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -56,7 +56,7 @@ export function createExports(manifest: SSRManifest) { }, }); - const locals = { + const locals: WorkerRuntime = { runtime: { waitUntil: (promise: Promise) => { context.waitUntil(promise); @@ -65,7 +65,7 @@ export function createExports(manifest: SSRManifest) { cf: request.cf, caches: caches, }, - } satisfies WorkerRuntime; + }; let response = await app.render(request, routeData, locals); diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 8312fb0594cd..69698375f860 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -53,7 +53,7 @@ export function createExports(manifest: SSRManifest) { cf: request.cf, }); - const locals = { + const locals: FunctionRuntime = { runtime: { waitUntil: (promise: Promise) => { context.waitUntil(promise); @@ -62,7 +62,7 @@ export function createExports(manifest: SSRManifest) { cf: request.cf, caches: caches, }, - } satisfies FunctionRuntime; + }; let response = await app.render(request, routeData, locals); diff --git a/packages/integrations/cloudflare/test/cf.test.js b/packages/integrations/cloudflare/test/cf.test.js index 8e1d4f97fc76..559df5c7601e 100644 --- a/packages/integrations/cloudflare/test/cf.test.js +++ b/packages/integrations/cloudflare/test/cf.test.js @@ -31,7 +31,6 @@ describe('Cf metadata and caches', () => { let html = await res.text(); let $ = cheerio.load(html); // console.log($('#cf').text(), html); - // console.log($('#env').text(), html); expect($('#cf').text()).to.contain('city'); expect($('#hasCache').text()).to.equal('true'); }); diff --git a/packages/integrations/cloudflare/test/runtime.test.js b/packages/integrations/cloudflare/test/runtime.test.js index df27c239988c..a90d83b7d642 100644 --- a/packages/integrations/cloudflare/test/runtime.test.js +++ b/packages/integrations/cloudflare/test/runtime.test.js @@ -30,7 +30,8 @@ describe('Runtime Locals', () => { expect(res.status).to.equal(200); let html = await res.text(); let $ = cheerio.load(html); - console.log($('#cf').text(), html); + // console.log($('#cf').text(), html); + // console.log($('#env').text(), html); expect($('#cf').text()).to.contain('city'); expect($('#hasCache').text()).to.equal('true'); }); From 35b153d53ed454b044c9341ab8c7364458a28261 Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Tue, 8 Aug 2023 17:51:33 +0200 Subject: [PATCH 17/22] fix integration test port --- packages/integrations/cloudflare/test/cf.test.js | 2 +- packages/integrations/cloudflare/test/runtime.test.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/integrations/cloudflare/test/cf.test.js b/packages/integrations/cloudflare/test/cf.test.js index 559df5c7601e..f8ab9c02f1b1 100644 --- a/packages/integrations/cloudflare/test/cf.test.js +++ b/packages/integrations/cloudflare/test/cf.test.js @@ -17,7 +17,7 @@ describe('Cf metadata and caches', () => { }); await fixture.build(); - cli = runCLI('./fixtures/cf/', { silent: true, port: 8788 }); + cli = runCLI('./fixtures/cf/', { silent: false, port: 8788 }); await cli.ready; }); diff --git a/packages/integrations/cloudflare/test/runtime.test.js b/packages/integrations/cloudflare/test/runtime.test.js index a90d83b7d642..7e74b8fc5742 100644 --- a/packages/integrations/cloudflare/test/runtime.test.js +++ b/packages/integrations/cloudflare/test/runtime.test.js @@ -17,7 +17,7 @@ describe('Runtime Locals', () => { }); await fixture.build(); - cli = runCLI('./fixtures/runtime/', { silent: true, port: 8788 }); + cli = runCLI('./fixtures/runtime/', { silent: false, port: 8791 }); await cli.ready; }); @@ -26,7 +26,7 @@ describe('Runtime Locals', () => { }); it('has CF and Caches', async () => { - let res = await fetch(`http://localhost:8788/`); + let res = await fetch(`http://localhost:8791/`); expect(res.status).to.equal(200); let html = await res.text(); let $ = cheerio.load(html); From 8eaec6684006f457b07131aab565324f73b473cb Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Tue, 8 Aug 2023 17:58:45 +0200 Subject: [PATCH 18/22] updated tests, add new port --- packages/integrations/cloudflare/test/runtime.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/integrations/cloudflare/test/runtime.test.js b/packages/integrations/cloudflare/test/runtime.test.js index 7e74b8fc5742..243c1dd67c1c 100644 --- a/packages/integrations/cloudflare/test/runtime.test.js +++ b/packages/integrations/cloudflare/test/runtime.test.js @@ -17,7 +17,7 @@ describe('Runtime Locals', () => { }); await fixture.build(); - cli = runCLI('./fixtures/runtime/', { silent: false, port: 8791 }); + cli = runCLI('./fixtures/runtime/', { silent: true, port: 8793 }); await cli.ready; }); @@ -26,13 +26,13 @@ describe('Runtime Locals', () => { }); it('has CF and Caches', async () => { - let res = await fetch(`http://localhost:8791/`); + let res = await fetch(`http://localhost:8793/`); expect(res.status).to.equal(200); let html = await res.text(); let $ = cheerio.load(html); - // console.log($('#cf').text(), html); - // console.log($('#env').text(), html); expect($('#cf').text()).to.contain('city'); + expect($('#env').text()).to.contain('SECRET_STUFF'); + expect($('#env').text()).to.contain('secret'); expect($('#hasCache').text()).to.equal('true'); }); }); From fa23b1141ff1fd570bbec310240f95ce5b7ae0dd Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Wed, 9 Aug 2023 20:32:36 +0200 Subject: [PATCH 19/22] add TODO comment --- packages/integrations/cloudflare/src/server.advanced.ts | 3 ++- packages/integrations/cloudflare/src/server.directory.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index 438cb56a6ae6..1f0fff8fceaf 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -44,7 +44,8 @@ export function createExports(manifest: SSRManifest) { request.headers.get('cf-connecting-ip') ); - // @deprecated: getRuntime() can be removed in the next major release, after testing runtime in locals + // `getRuntime()` is deprecated, currently available additionally to new Astro.locals.runtime + // TODO: remove `getRuntime()` in Astro 3.0 Reflect.set(request, Symbol.for('runtime'), { env, name: 'cloudflare', diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 69698375f860..d4e4094de57e 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -41,7 +41,8 @@ export function createExports(manifest: SSRManifest) { request.headers.get('cf-connecting-ip') ); - // @deprecated: getRuntime() can be removed in the next major release, after testing runtime in locals + // `getRuntime()` is deprecated, currently available additionally to new Astro.locals.runtime + // TODO: remove `getRuntime()` in Astro 3.0 Reflect.set(request, Symbol.for('runtime'), { ...context, waitUntil: (promise: Promise) => { From bdf5392dd888576cf7ddc55ae39820cd2618e57f Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Thu, 10 Aug 2023 16:14:49 +0200 Subject: [PATCH 20/22] update changeset --- .changeset/fuzzy-jobs-explain.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.changeset/fuzzy-jobs-explain.md b/.changeset/fuzzy-jobs-explain.md index a4b8d2b512f2..e15f46130f51 100644 --- a/.changeset/fuzzy-jobs-explain.md +++ b/.changeset/fuzzy-jobs-explain.md @@ -2,12 +2,11 @@ '@astrojs/cloudflare': minor --- -Expose the runtime bindings & environmental variabels via `Astro.locals` +The `getRuntime` utility has been deprecated and should be updated to the new [`Astro.locals`](https://docs.astro.build/en/guides/middleware/#locals) API. - ```diff - - import { getRuntime } from '@astrojs/cloudflare/runtime'; - - getRuntime(Astro.request); +```diff +- import { getRuntime } from '@astrojs/cloudflare/runtime'; +- getRuntime(Astro.request); - + const runtime = Astro.locals.runtime; - + const env = runtime.env; - ``` ++ const runtime = Astro.locals.runtime; +``` From 33049e5e8d305b8768ed88d9b3fd1469a6cd156e Mon Sep 17 00:00:00 2001 From: Alexander Niebuhr Date: Thu, 10 Aug 2023 16:18:20 +0200 Subject: [PATCH 21/22] add JSDoc --- packages/integrations/cloudflare/src/runtime.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/integrations/cloudflare/src/runtime.ts b/packages/integrations/cloudflare/src/runtime.ts index cd3dfff4755a..6da85ebcdbb2 100644 --- a/packages/integrations/cloudflare/src/runtime.ts +++ b/packages/integrations/cloudflare/src/runtime.ts @@ -1,3 +1,4 @@ +// TODO: remove `getRuntime()` in Astro 3.0 import type { Cache, CacheStorage, IncomingRequestCfProperties } from '@cloudflare/workers-types'; export type WorkerRuntime = { @@ -21,6 +22,16 @@ export type PagesRuntime = { cf?: IncomingRequestCfProperties; }; +/** + * @deprecated since version 2.0 + * The `getRuntime` utility has been deprecated and should be updated to the new [`Astro.locals`](https://docs.astro.build/en/guides/middleware/#locals) API. + * ```diff + * - import { getRuntime } from '@astrojs/cloudflare/runtime'; + * - getRuntime(Astro.request); + * + * + const runtime = Astro.locals.runtime; + * ``` + */ export function getRuntime( request: Request ): WorkerRuntime | PagesRuntime { From 45a52b2043376e7e234d338b2be01cfc0a4fc262 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Thu, 10 Aug 2023 09:54:32 -0500 Subject: [PATCH 22/22] Update packages/integrations/cloudflare/src/runtime.ts --- packages/integrations/cloudflare/src/runtime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/cloudflare/src/runtime.ts b/packages/integrations/cloudflare/src/runtime.ts index 6da85ebcdbb2..7791f6f1c6c3 100644 --- a/packages/integrations/cloudflare/src/runtime.ts +++ b/packages/integrations/cloudflare/src/runtime.ts @@ -23,7 +23,7 @@ export type PagesRuntime = { }; /** - * @deprecated since version 2.0 + * @deprecated since version 6.8.0 * The `getRuntime` utility has been deprecated and should be updated to the new [`Astro.locals`](https://docs.astro.build/en/guides/middleware/#locals) API. * ```diff * - import { getRuntime } from '@astrojs/cloudflare/runtime';