summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/fuzzy-jobs-explain.md12
-rw-r--r--packages/integrations/cloudflare/README.md6
-rw-r--r--packages/integrations/cloudflare/src/index.ts18
-rw-r--r--packages/integrations/cloudflare/src/runtime.ts11
-rw-r--r--packages/integrations/cloudflare/src/server.advanced.ts28
-rw-r--r--packages/integrations/cloudflare/src/server.directory.ts53
-rw-r--r--packages/integrations/cloudflare/test/cf.test.js2
-rw-r--r--packages/integrations/cloudflare/test/fixtures/runtime/astro.config.mjs8
-rw-r--r--packages/integrations/cloudflare/test/fixtures/runtime/package.json9
-rw-r--r--packages/integrations/cloudflare/test/fixtures/runtime/src/pages/index.astro15
-rw-r--r--packages/integrations/cloudflare/test/runtime.test.js38
-rw-r--r--pnpm-lock.yaml9
12 files changed, 176 insertions, 33 deletions
diff --git a/.changeset/fuzzy-jobs-explain.md b/.changeset/fuzzy-jobs-explain.md
new file mode 100644
index 000000000..e15f46130
--- /dev/null
+++ b/.changeset/fuzzy-jobs-explain.md
@@ -0,0 +1,12 @@
+---
+'@astrojs/cloudflare': minor
+---
+
+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;
+```
diff --git a/packages/integrations/cloudflare/README.md b/packages/integrations/cloudflare/README.md
index 45f8e01ba..61db6effc 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/index.ts b/packages/integrations/cloudflare/src/index.ts
index 336f747cc..aa55af3d4 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 = {
@@ -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 });
diff --git a/packages/integrations/cloudflare/src/runtime.ts b/packages/integrations/cloudflare/src/runtime.ts
index cd3dfff47..7791f6f1c 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<T = unknown> = {
@@ -21,6 +22,16 @@ export type PagesRuntime<T = unknown, U = unknown> = {
cf?: IncomingRequestCfProperties;
};
+/**
+ * @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';
+ * - getRuntime(Astro.request);
+ *
+ * + const runtime = Astro.locals.runtime;
+ * ```
+ */
export function getRuntime<T = unknown, U = unknown>(
request: Request
): WorkerRuntime<T> | PagesRuntime<T, U> {
diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts
index 9758b8b19..1f0fff8fc 100644
--- a/packages/integrations/cloudflare/src/server.advanced.ts
+++ b/packages/integrations/cloudflare/src/server.advanced.ts
@@ -12,10 +12,21 @@ type Env = {
name: string;
};
+interface WorkerRuntime {
+ runtime: {
+ waitUntil: (promise: Promise<any>) => void;
+ env: Env;
+ cf: CFRequest['cf'];
+ caches: typeof caches;
+ };
+}
+
export function createExports(manifest: SSRManifest) {
const app = new App(manifest);
const fetch = async (request: Request & CFRequest, env: Env, context: ExecutionContext) => {
+ // 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);
@@ -32,6 +43,9 @@ export function createExports(manifest: SSRManifest) {
Symbol.for('astro.clientAddress'),
request.headers.get('cf-connecting-ip')
);
+
+ // `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',
@@ -42,7 +56,19 @@ export function createExports(manifest: SSRManifest) {
context.waitUntil(promise);
},
});
- let response = await app.render(request, routeData);
+
+ const locals: WorkerRuntime = {
+ runtime: {
+ waitUntil: (promise: Promise<any>) => {
+ context.waitUntil(promise);
+ },
+ env: env,
+ cf: request.cf,
+ caches: caches,
+ },
+ };
+
+ 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 3e9531a56..d4e4094de 100644
--- a/packages/integrations/cloudflare/src/server.directory.ts
+++ b/packages/integrations/cloudflare/src/server.directory.ts
@@ -7,28 +7,30 @@ if (!isNode) {
process.env = getProcessEnvProxy();
}
+interface FunctionRuntime {
+ runtime: {
+ waitUntil: (promise: Promise<any>) => void;
+ env: EventContext<unknown, string, unknown>['env'];
+ cf: CFRequest['cf'];
+ caches: typeof caches;
+ };
+}
+
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<unknown, any, unknown>['waitUntil'];
- } & Record<string, unknown>) => {
- process.env = runtimeEnv.env as any;
+ const onRequest = async (context: EventContext<unknown, string, unknown>) => {
+ 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'
+ process.env = env as any;
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<unknown, string, unknown>['env']).ASSETS.fetch(
- request
- );
+ return env.ASSETS.fetch(request);
}
let routeData = app.match(request, { matchNotFound: true });
@@ -38,17 +40,32 @@ export function createExports(manifest: SSRManifest) {
Symbol.for('astro.clientAddress'),
request.headers.get('cf-connecting-ip')
);
+
+ // `getRuntime()` is deprecated, currently available additionally to new Astro.locals.runtime
+ // TODO: remove `getRuntime()` in Astro 3.0
Reflect.set(request, Symbol.for('runtime'), {
- ...runtimeEnv,
+ ...context,
waitUntil: (promise: Promise<any>) => {
- runtimeEnv.waitUntil(promise);
+ context.waitUntil(promise);
},
name: 'cloudflare',
next,
caches,
cf: request.cf,
});
- let response = await app.render(request, routeData);
+
+ const locals: FunctionRuntime = {
+ runtime: {
+ waitUntil: (promise: Promise<any>) => {
+ context.waitUntil(promise);
+ },
+ env: context.env,
+ cf: request.cf,
+ caches: caches,
+ },
+ };
+
+ let response = await app.render(request, routeData, locals);
if (app.setCookieHeaders) {
for (const setCookieHeader of app.setCookieHeaders(response)) {
diff --git a/packages/integrations/cloudflare/test/cf.test.js b/packages/integrations/cloudflare/test/cf.test.js
index 559df5c76..f8ab9c02f 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/fixtures/runtime/astro.config.mjs b/packages/integrations/cloudflare/test/fixtures/runtime/astro.config.mjs
new file mode 100644
index 000000000..f92829843
--- /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 000000000..71ac16647
--- /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 000000000..320e8e162
--- /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;
+---
+<html>
+ <head>
+ <title>Testing</title>
+ </head>
+ <body>
+ <h1>Testing</h1>
+ <div id="cf">{JSON.stringify(runtime.cf)}</div>
+ <div id="env">{JSON.stringify(env)}</div>
+ <div id="hasCache">{!!runtime.caches}</div>
+ </body>
+</html>
diff --git a/packages/integrations/cloudflare/test/runtime.test.js b/packages/integrations/cloudflare/test/runtime.test.js
new file mode 100644
index 000000000..243c1dd67
--- /dev/null
+++ b/packages/integrations/cloudflare/test/runtime.test.js
@@ -0,0 +1,38 @@
+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: 8793 });
+ await cli.ready;
+ });
+
+ after(async () => {
+ await cli.stop();
+ });
+
+ it('has CF and Caches', async () => {
+ let res = await fetch(`http://localhost:8793/`);
+ expect(res.status).to.equal(200);
+ let html = await res.text();
+ let $ = cheerio.load(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');
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ec389bfce..b57d14b75 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':