diff --git a/README.md b/README.md
index ea5eb66..7e8573b 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-# Cloudflare Bindings for Nitro and Nuxt
+# Cloudflare Platform for Nitro and Nuxt
-This proof of concept module enables access to the Cloudflare runtime bindings in the development server of [Nitro](https://nitro.unjs.io) and [Nuxt](https://nuxt.com) using the [new `getBindingsProxy` API](https://github.com/cloudflare/workers-sdk/pull/4523) exposed by [wrangler](https://developers.cloudflare.com/workers/wrangler/) and [miniflare](https://miniflare.dev/)
+This proof of concept module enables access to the Cloudflare runtime platform in the development server of [Nitro](https://nitro.unjs.io) and [Nuxt](https://nuxt.com) using the [new `getPlatformProxy` API](https://github.com/cloudflare/workers-sdk/pull/5002) exposed by [wrangler](https://developers.cloudflare.com/workers/wrangler/) and [miniflare](https://miniflare.dev/)
> [!NOTE]
> Nitro plans to introduce a new method to allow native dev presets, meaning you can natively run [miniflare](https://miniflare.dev/) as your development server without this module or a proxy in the future!
diff --git a/examples/nitro/routes/counter.ts b/examples/nitro/routes/counter.ts
index 2987f48..37254a7 100644
--- a/examples/nitro/routes/counter.ts
+++ b/examples/nitro/routes/counter.ts
@@ -2,7 +2,7 @@ export default eventHandler(async (event) => {
const { KV } = event.context.cloudflare.env;
let ctr = (await KV.get("counter")) || 0;
- await KV.put("counter", ++ctr);
+ await KV.put("counter", ++ctr % 100);
- return { counter: ctr };
+ return `counter: ${(await KV.get("counter")) || 0}`;
});
diff --git a/examples/nitro/routes/index.ts b/examples/nitro/routes/index.ts
index af1b7d2..2aa3f43 100644
--- a/examples/nitro/routes/index.ts
+++ b/examples/nitro/routes/index.ts
@@ -1,4 +1,18 @@
-export default eventHandler(async () => {
- const { counter } = (await $fetch("/counter")) as { counter: number };
- return `
Counter: ${counter}
`;
+export default eventHandler(async (event) => {
+ const cloudflare = await event.context.cloudflare;
+
+ const logs: string[] = [];
+ const log = (str: string) => logs.push(str);
+
+ log(`Keys of cloudflare: ${Object.keys(cloudflare).join(", ")}`);
+
+ log(`Keys of cloudflare.env: ${Object.keys(cloudflare.env).join(", ")}`);
+
+ log(`Colo: ${cloudflare.request.cf.colo}`);
+
+ log(
+ `typeof cloudflare.context.waitUntil: ${typeof cloudflare.context.waitUntil}`,
+ );
+
+ return `
${logs.map((str) => `- ${str}
`).join("\n
\n")}
`;
});
diff --git a/package.json b/package.json
index 3610ef2..bb9b6a8 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"prettier": "^3.2.4",
"typescript": "^5.2.2",
"unbuild": "^2.0.0",
- "wrangler": "^3.24.0"
+ "wrangler": "^3.28.2"
},
"packageManager": "pnpm@8.10.0"
}
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b9e4fa6..498d221 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -55,8 +55,8 @@ importers:
specifier: ^2.0.0
version: 2.0.0(typescript@5.3.3)
wrangler:
- specifier: ^3.24.0
- version: 3.24.0
+ specifier: ^3.28.2
+ version: 3.28.2
examples/nitro:
devDependencies:
@@ -435,12 +435,6 @@ packages:
to-fast-properties: 2.0.0
dev: true
- /@cloudflare/kv-asset-handler@0.2.0:
- resolution: {integrity: sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A==}
- dependencies:
- mime: 3.0.0
- dev: true
-
/@cloudflare/kv-asset-handler@0.3.1:
resolution: {integrity: sha512-lKN2XCfKCmpKb86a1tl4GIwsJYDy9TGuwjhDELLmpKygQhw8X2xR4dusgpC5Tg7q1pB96Eb0rBo81kxSILQMwA==}
dependencies:
@@ -456,6 +450,15 @@ packages:
dev: true
optional: true
+ /@cloudflare/workerd-darwin-64@1.20240129.0:
+ resolution: {integrity: sha512-DfVVB5IsQLVcWPJwV019vY3nEtU88c2Qu2ST5SQxqcGivZ52imagLRK0RHCIP8PK4piSiq90qUC6ybppUsw8eg==}
+ engines: {node: '>=16'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@cloudflare/workerd-darwin-arm64@1.20231218.0:
resolution: {integrity: sha512-b39qrU1bKolCfmKFDAnX4vXcqzISkEUVE/V8sMBsFzxrIpNAbcUHBZAQPYmS/OHIGB94KjOVokvDi7J6UNurPw==}
engines: {node: '>=16'}
@@ -465,6 +468,15 @@ packages:
dev: true
optional: true
+ /@cloudflare/workerd-darwin-arm64@1.20240129.0:
+ resolution: {integrity: sha512-t0q8ABkmumG1zRM/MZ/vIv/Ysx0vTAXnQAPy/JW5aeQi/tqrypXkO9/NhPc0jbF/g/hIPrWEqpDgEp3CB7Da7Q==}
+ engines: {node: '>=16'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@cloudflare/workerd-linux-64@1.20231218.0:
resolution: {integrity: sha512-dMUF1wA+0mybm6hHNOCgY/WMNMwomPPs4I7vvYCgwHSkch0Q2Wb7TnxQZSt8d1PK/myibaBwadrlIxpjxmpz3w==}
engines: {node: '>=16'}
@@ -474,6 +486,15 @@ packages:
dev: true
optional: true
+ /@cloudflare/workerd-linux-64@1.20240129.0:
+ resolution: {integrity: sha512-sFV1uobHgDI+6CKBS/ZshQvOvajgwl6BtiYaH4PSFSpvXTmRx+A9bcug+6BnD+V4WgwxTiEO2iR97E1XuwDAVw==}
+ engines: {node: '>=16'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@cloudflare/workerd-linux-arm64@1.20231218.0:
resolution: {integrity: sha512-2s5uc8IHt0QmWyKxAr1Fy+4b8Xy0b/oUtlPnm5MrKi2gDRlZzR7JvxENPJCpCnYENydS8lzvkMiAFECPBccmyQ==}
engines: {node: '>=16'}
@@ -483,6 +504,15 @@ packages:
dev: true
optional: true
+ /@cloudflare/workerd-linux-arm64@1.20240129.0:
+ resolution: {integrity: sha512-O7q7htHaFRp8PgTqNJx1/fYc3+LnvAo6kWWB9a14C5OWak6AAZk42PNpKPx+DXTmGvI+8S1+futBGUeJ8NPDXg==}
+ engines: {node: '>=16'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@cloudflare/workerd-windows-64@1.20231218.0:
resolution: {integrity: sha512-oN5hz6TXUDB5YKUN5N3QWAv6cYz9JjTZ9g16HVyoegVFEL6/zXU3tV19MBX2IvlE11ab/mRogEv9KXVIrHfKmA==}
engines: {node: '>=16'}
@@ -492,6 +522,15 @@ packages:
dev: true
optional: true
+ /@cloudflare/workerd-windows-64@1.20240129.0:
+ resolution: {integrity: sha512-YqGno0XSqqqkDmNoGEX6M8kJlI2lEfWntbTPVtHaZlaXVR9sWfoD7TEno0NKC95cXFz+ioyFLbgbOdnfWwmVAA==}
+ engines: {node: '>=16'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@cspotcode/source-map-support@0.8.1:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
@@ -5343,8 +5382,8 @@ packages:
- utf-8-validate
dev: true
- /miniflare@3.20231218.3:
- resolution: {integrity: sha512-OrPBYWO0WnFv6DrxZ7hF8f5agZ4+xo/2qSLE0wwCJSqlFhr91dfSJautxfCOBD896nAA7Jqr5LBPEnqq3/k/JQ==}
+ /miniflare@3.20240129.2:
+ resolution: {integrity: sha512-BPUg8HsPmWQlRFUeiQk274i8M9L0gOvzbkjryuTvCX+M53EwBpP0gM2wyrRr/HokQoJcxWGh3InBu6L8+0bbPw==}
engines: {node: '>=16.13'}
hasBin: true
dependencies:
@@ -5356,7 +5395,7 @@ packages:
glob-to-regexp: 0.4.1
stoppable: 1.1.0
undici: 5.28.2
- workerd: 1.20231218.0
+ workerd: 1.20240129.0
ws: 8.16.0
youch: 3.3.3
zod: 3.22.4
@@ -8334,18 +8373,36 @@ packages:
'@cloudflare/workerd-windows-64': 1.20231218.0
dev: true
- /wrangler@3.24.0:
- resolution: {integrity: sha512-jEnqpY+9/J4VPjtuEnS2lhCPXkvbDClnMalSWaRxSx+1tiTWMJhMjtK9oyXLdO+ZUf9Q4LvFTYSPm8O1uwmnxQ==}
+ /workerd@1.20240129.0:
+ resolution: {integrity: sha512-t4pnsmjjk/u+GdVDgH2M1AFmJaBUABshYK/vT/HNrAXsHSwN6VR8Yqw0JQ845OokO34VLkuUtYQYyxHHKpdtsw==}
+ engines: {node: '>=16'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@cloudflare/workerd-darwin-64': 1.20240129.0
+ '@cloudflare/workerd-darwin-arm64': 1.20240129.0
+ '@cloudflare/workerd-linux-64': 1.20240129.0
+ '@cloudflare/workerd-linux-arm64': 1.20240129.0
+ '@cloudflare/workerd-windows-64': 1.20240129.0
+ dev: true
+
+ /wrangler@3.28.2:
+ resolution: {integrity: sha512-hlD4f2avBZuR1+qo9Um6D1prdWrSRtGTo9h6o/AKce+bHQEJWoJgJKHeLmrpZlLtHg/gGR1Xa1xzrexhuIzeJw==}
engines: {node: '>=16.17.0'}
hasBin: true
+ peerDependencies:
+ '@cloudflare/workers-types': ^4.20230914.0
+ peerDependenciesMeta:
+ '@cloudflare/workers-types':
+ optional: true
dependencies:
- '@cloudflare/kv-asset-handler': 0.2.0
+ '@cloudflare/kv-asset-handler': 0.3.1
'@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19)
'@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19)
blake3-wasm: 2.1.5
chokidar: 3.5.3
esbuild: 0.17.19
- miniflare: 3.20231218.3
+ miniflare: 3.20240129.2
nanoid: 3.3.7
path-to-regexp: 6.2.1
resolve: 1.22.8
diff --git a/src/runtime/plugin.dev.ts b/src/runtime/plugin.dev.ts
index 67b3102..bffc8fc 100644
--- a/src/runtime/plugin.dev.ts
+++ b/src/runtime/plugin.dev.ts
@@ -1,23 +1,52 @@
import type { NitroAppPlugin } from "nitropack";
// @ts-ignore
-import { useRuntimeConfig } from "#imports";
+import { useRuntimeConfig, getRequestURL } from "#imports";
export default function (nitroApp) {
- let _proxy: ReturnType;
+ let _proxy: ReturnType;
nitroApp.hooks.hook("request", async (event) => {
// Lazy initialize proxy when first request comes in
if (!_proxy) {
- _proxy = getBindingsProxy().catch((error) => {
+ _proxy = getPlatformProxy().catch((error) => {
console.error("Failed to initialize wrangler bindings proxy", error);
- return { bindings: {}, dispose: () => Promise.resolve() };
+ return {
+ env: {},
+ cf: {},
+ ctx: {
+ waitUntil() {},
+ passThroughOnException() {},
+ },
+ caches: {
+ open(): Promise {
+ const result = Promise.resolve(new Cache());
+ return result;
+ },
+ get default(): Cache {
+ return new Cache();
+ },
+ },
+ dispose: () => Promise.resolve(),
+ } as unknown as ReturnType;
});
}
- // Inject proxy bindings to the request context
+ const proxy = await _proxy;
+
+ // Inject the various cf values from the proxy in event and event.context
+
+ event.waitUntil = proxy.ctx.waitUntil;
+ (event.context as any).cf = proxy.cf;
+ (event.context as any).waitUntil = proxy.ctx.waitUntil;
+
+ const request = new Request(getRequestURL(event));
+ (request as any).cf = proxy.cf;
+
event.context.cloudflare = {
...event.context.cloudflare,
- env: (await _proxy).bindings,
+ request,
+ env: proxy.env,
+ context: proxy.ctx,
};
});
@@ -27,9 +56,9 @@ export default function (nitroApp) {
});
};
-async function getBindingsProxy() {
+async function getPlatformProxy() {
const _pkg = "wrangler"; // Bypass bundling!
- const { getBindingsProxy } = (await import(
+ const { getPlatformProxy } = (await import(
_pkg
)) as typeof import("wrangler");
@@ -37,10 +66,27 @@ async function getBindingsProxy() {
wrangler: { configPath: string; persistDir: string };
} = useRuntimeConfig();
- const proxy = await getBindingsProxy({
+ const proxy = await getPlatformProxy({
configPath: runtimeConfig.wrangler.configPath,
persist: { path: runtimeConfig.wrangler.persistDir },
});
return proxy;
}
+
+class Cache {
+ delete(): Promise {
+ const result = Promise.resolve(false);
+ return result;
+ }
+
+ match() {
+ const result = Promise.resolve(undefined);
+ return result;
+ }
+
+ put(): Promise {
+ const result = Promise.resolve();
+ return result;
+ }
+}