diff --git a/documentation/docs/25-build-and-deploy/99-writing-adapters.md b/documentation/docs/25-build-and-deploy/99-writing-adapters.md index 204445e5e889..e3b76df224aa 100644 --- a/documentation/docs/25-build-and-deploy/99-writing-adapters.md +++ b/documentation/docs/25-build-and-deploy/99-writing-adapters.md @@ -41,8 +41,11 @@ export default function (options) { } }, vite: { - plugins: [ - // add plugins here to integrate with Vite + pre_plugins: [ + // add plugins here... + ], + post_plugins: [ + // ...or here to integrate with Vite ] } }; diff --git a/packages/adapter-cloudflare/index.js b/packages/adapter-cloudflare/index.js index 185c964ceafc..e10020400569 100644 --- a/packages/adapter-cloudflare/index.js +++ b/packages/adapter-cloudflare/index.js @@ -10,13 +10,19 @@ import { parse_redirects, append_headers } from './utils.js'; - -const name = '@sveltejs/adapter-cloudflare'; +import { ServerResponse } from 'node:http'; +import { coupleWebSocket } from 'miniflare'; +import { WebSocketServer } from 'ws'; +import { cloudflare } from '@cloudflare/vite-plugin'; +import { exactRegex } from '@rolldown/pluginutils'; +// @ts-expect-error types are private +import { dedent } from '@sveltejs/kit/internal'; /** @type {import('./index.js').default} */ export default function (options = {}) { + const node_ws_server = new WebSocketServer({ noServer: true }); return { - name, + name: '@sveltejs/adapter-cloudflare', async adapt(builder) { if ( existsSync('_routes.json') || @@ -182,7 +188,13 @@ export default function (options = {}) { // we want to invoke `getPlatformProxy` only once, but await it only when it is accessed. // If we would await it here, it would hang indefinitely because the platform proxy only resolves once a request happens const get_emulated = async () => { - const proxy = await getPlatformProxy(options.platformProxy); + // TODO - need access to the vite dev server here + // const runner = get_runner(vite, server); + // runner.import('cloudflare:workers'); + const proxy = await getPlatformProxy({ + configPath: '.svelte-kit/cloudflare-tmp/wrangler.json', + ...options.platformProxy + }); const platform = { env: proxy.env, ctx: proxy.ctx, @@ -215,10 +227,174 @@ export default function (options = {}) { supports: { read: () => true, instrumentation: () => true + }, + /** + * + * @param {WebSocketServerResponse} res + * @param {Response & { webSocket?: import('miniflare').WebSocket }} response + */ + setResponse(res, response) { + if (!response.webSocket || !res.socket || !res[WEBSOCKET_HEAD]) return false; + + const socket = res.socket; + const worker_socket = response.webSocket; + res.detachSocket(socket); + node_ws_server.handleUpgrade(res.req, socket, res[WEBSOCKET_HEAD], (client_socket) => { + void coupleWebSocket(client_socket, worker_socket); + node_ws_server.emit('connection', client_socket, res.req); + }); + + return true; + }, + vite: { + pre_plugins: [listener_plugin, virtual_modules_plugin(options)], + post_plugins: [ + // Cloudflare's plugin needs to be after SvelteKit so sveltekit's middleware + // can read the requests first and ignore them if necessary. + ...cloudflare({ + configPath: options.config, + config: (user_config) => { + // Assets are handled by SvelteKit + delete user_config.assets; + return user_config; + } + }) + ] + } + }; +} + +/** + * @param {import('./index.js').AdapterOptions} options + * @returns {import('vite').Plugin} + * */ +function virtual_modules_plugin(options) { + const modules = ['cloudflare:workers', 'virtual:todo-name-cloudflare-handler']; + /** @type {string} */ + let out_dir; + const { wrangler_config } = validate_wrangler_config(options.config); + const worker_name = wrangler_config.name ?? 'worker'; + // Rename the worker because two workers are running at once + wrangler_config.name = worker_name + '-sveltekit'; + // Point all durable objects at the worker ran by @cloudflare/vite-plugin + for (const binding of wrangler_config.durable_objects?.bindings ?? []) { + if (binding.script_name === undefined) { + binding.script_name = worker_name; + } + } + // squash warnings + if (Object.keys(wrangler_config.unsafe).length === 0) { + delete /** @type {{ unsafe?: {} }} */ (wrangler_config).unsafe; + } + + return { + name: 'vite-plugin-sveltekit-adapter-cloudflare-virtual-modules', + configResolved(config) { + const plugin = config.plugins.find((plugin) => plugin.name === 'vite-plugin-sveltekit-setup'); + const options = plugin?.api?.options; + if (!options) throw new Error('vite-plugin-sveltekit-setup not found'); + out_dir = options.kit.outDir; + }, + resolveId: { + filter: { + id: modules.map((m) => exactRegex(m)) + }, + handler(id) { + return '\0' + id; + } + }, + load: { + filter: { + id: modules.map((m) => exactRegex('\0' + m)) + }, + handler(id) { + if (id === '\0cloudflare:workers') { + return dedent` + import { getPlatformProxy } from 'wrangler'; + import { writeFileSync, mkdirSync } from 'node:fs'; + + const tmp_dir = ${JSON.stringify(out_dir + '/cloudflare-tmp')}; + mkdirSync(tmp_dir, { recursive: true }); + const tmp_config_file = tmp_dir + '/wrangler.json'; + writeFileSync(tmp_config_file, ${JSON.stringify(JSON.stringify(wrangler_config))}); + const proxy = await getPlatformProxy({ + ...${JSON.stringify(options.platformProxy ?? {})}, + configPath: tmp_config_file + }); + export const env = proxy.env; + export const waitUntil = () => {}; + // TODO - stub other exports + `; + } + } } }; } + +const WEBSOCKET_HEAD = Symbol('websocketHead'); +/** @typedef {import('http').ServerResponse & { [WEBSOCKET_HEAD]?: Buffer }} WebSocketServerResponse */ +/** @type {import('vite').Plugin} */ +const listener_plugin = { + name: 'vite-plugin-sveltekit-adapter-cloudflare-listeners', + enforce: 'post', + configureServer(server) { + return () => { + if (server.httpServer) { + const upgrade_listeners = server.httpServer + .listeners('upgrade') + .filter((listener) => listener.name !== 'hmrServerWsListener'); + + for (const listener of upgrade_listeners) { + server.httpServer.removeListener('upgrade', /** @type {() => void} */ (listener)); + } + + /** + * @param {import('vite').Connect.IncomingMessage} req + * @param {import('net').Socket} socket + * @param {Buffer} head + */ + const upgrade_handler = (req, socket, head) => { + if (req.headers['x-sveltekit-cloudflare-handle']) { + delete req.headers['x-sveltekit-cloudflare-handle']; + req.originalUrl = req.url; + + const res = new ServerResponse(req); + res.assignSocket(socket); + /** @type {WebSocketServerResponse} */ (res)[WEBSOCKET_HEAD] = head; + handler(req, res); + return; + } + for (const listener of upgrade_listeners) { + listener(req, socket, head); + } + }; + + server.httpServer.on('upgrade', upgrade_handler); + } + const sveltekit_dev_middleware = server.middlewares.stack.find( + (middleware) => + /** @type {Function} */ (middleware.handle).name === 'sveltekitDevMiddleware' + ); + if (!sveltekit_dev_middleware) { + throw new Error('@sveltekit/adapter-cloudflare could not find sveltekitDevMiddleware'); + } + const handler = /** @type {import('vite').Connect.SimpleHandleFunction} */ ( + sveltekit_dev_middleware.handle + ); + /** @type {import('vite').Connect.NextHandleFunction} */ + sveltekit_dev_middleware.handle = (req, res, next) => { + if (req.headers['x-sveltekit-cloudflare-handle']) { + delete req.headers['x-sveltekit-cloudflare-handle']; + handler(req, res); + return; + } + next(); + }; + }; + } +}; + /** * @param {string} app_dir * @param {string | undefined} content existing `_headers` file content @@ -277,7 +453,7 @@ _redirects * building_for_cloudflare_pages: boolean * }} */ -function validate_wrangler_config(config_file = undefined) { +function validate_wrangler_config(config_file) { const wrangler_config = unstable_readConfig({ config: config_file }); const building_for_cloudflare_pages = is_building_for_cloudflare_pages(wrangler_config); diff --git a/packages/adapter-cloudflare/package.json b/packages/adapter-cloudflare/package.json index 50f117f3fb8f..0ee3589bf7bd 100644 --- a/packages/adapter-cloudflare/package.json +++ b/packages/adapter-cloudflare/package.json @@ -23,6 +23,10 @@ "types": "./index.d.ts", "import": "./index.js" }, + "./worker": { + "types": "./worker.d.ts", + "import": "./worker.js" + }, "./package.json": "./package.json" }, "types": "index.d.ts", @@ -46,13 +50,19 @@ }, "devDependencies": { "@playwright/test": "catalog:", + "@rolldown/pluginutils": "^1.0.1", "@sveltejs/kit": "workspace:^", "@types/node": "catalog:", + "@types/ws": "^8.18.1", + "miniflare": "5.20260801.0-alpha", "typescript": "catalog:", - "vitest": "catalog:" + "vite": "catalog:", + "vitest": "catalog:", + "ws": "^8.21.2" }, "peerDependencies": { + "@cloudflare/vite-plugin": "^1.51.0", "@sveltejs/kit": "^3.0.0-next.0", - "wrangler": "^4.118.0" + "wrangler": "^4.119.0" } } diff --git a/packages/adapter-cloudflare/test/apps/workers/.gitignore b/packages/adapter-cloudflare/test/apps/workers/.gitignore index de2e15da78f4..63d9a515f164 100644 --- a/packages/adapter-cloudflare/test/apps/workers/.gitignore +++ b/packages/adapter-cloudflare/test/apps/workers/.gitignore @@ -5,3 +5,4 @@ node_modules # Cloudflare .wrangler /dist +worker-configuration.d.ts diff --git a/packages/adapter-cloudflare/test/apps/workers/config/wrangler.jsonc b/packages/adapter-cloudflare/test/apps/workers/config/wrangler.jsonc index 8c2d83f8c21a..d0ad76b1637f 100644 --- a/packages/adapter-cloudflare/test/apps/workers/config/wrangler.jsonc +++ b/packages/adapter-cloudflare/test/apps/workers/config/wrangler.jsonc @@ -2,10 +2,31 @@ // to test that the adapter still resolves the paths correctly { "$schema": "../node_modules/wrangler/config-schema.json", - "main": "../dist/index.js", + "name": "adapter-cloudflare-test", + "main": "../src/worker.ts", "compatibility_date": "2026-06-24", "assets": { "directory": "../dist/public", "binding": "ASSETS" - } + }, + "durable_objects": { + "bindings": [ + { + "name": "DO", + "class_name": "DO" + } + ] + }, + "exports": { + "DO": { + "type": "durable-object", + "storage": "sqlite" + } + }, + "kv_namespaces": [ + { + "binding": "KV", + "remote": false + } + ] } diff --git a/packages/adapter-cloudflare/test/apps/workers/package.json b/packages/adapter-cloudflare/test/apps/workers/package.json index 2414fec7cb50..00e7521c5ba5 100644 --- a/packages/adapter-cloudflare/test/apps/workers/package.json +++ b/packages/adapter-cloudflare/test/apps/workers/package.json @@ -6,7 +6,7 @@ "dev": "vite dev", "build": "vite build", "preview": "wrangler dev dist/index.js --config config/wrangler.jsonc", - "prepare": "svelte-kit sync || echo ''", + "prepare": "svelte-kit sync || echo ''; wrangler types --config config/wrangler.jsonc || echo ''", "test:dev": "DEV=true playwright test", "test:build": "playwright test", "test": "pnpm test:dev && pnpm test:build" diff --git a/packages/adapter-cloudflare/test/apps/workers/src/app.d.ts b/packages/adapter-cloudflare/test/apps/workers/src/app.d.ts new file mode 100644 index 000000000000..4448bb67727c --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/src/app.d.ts @@ -0,0 +1,10 @@ +declare global { + namespace App { + interface Platform { + env: Cloudflare.Env; + ctx: Cloudflare.ExecutionContext; + } + } +} + +export {}; diff --git a/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.svelte b/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.svelte index d5e339683387..7cd008c06705 100644 --- a/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.svelte +++ b/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.svelte @@ -1,5 +1,20 @@ -

Sum: {data.sum}

+ +

WebSocket message: {ws_message}

diff --git a/packages/adapter-cloudflare/test/apps/workers/src/routes/ws/+server.js b/packages/adapter-cloudflare/test/apps/workers/src/routes/ws/+server.js new file mode 100644 index 000000000000..b62a401ecd83 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/src/routes/ws/+server.js @@ -0,0 +1,6 @@ +import { env } from 'cloudflare:workers'; + +export const GET = async ({ request }) => { + const stub = env.DO.getByName('stub'); + return stub.fetch(request.url, request); +} diff --git a/packages/adapter-cloudflare/test/apps/workers/src/worker.ts b/packages/adapter-cloudflare/test/apps/workers/src/worker.ts new file mode 100644 index 000000000000..200cd77650b1 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/src/worker.ts @@ -0,0 +1,24 @@ +import { DurableObject } from 'cloudflare:workers'; +import { handler } from '../../../../worker.js'; + +export class DO extends DurableObject { + async fetch(_req: Request): Promise { + const { 0: client, 1: server } = new WebSocketPair(); + + this.ctx.acceptWebSocket(server); + setInterval(() => { + server.send(new Date().toISOString()); + }, 1000); + + return new Response(null, { + status: 101, + webSocket: client, + }); + } +} + +export default { + async fetch(request) { + return handler(request); + }, +} satisfies ExportedHandler; diff --git a/packages/adapter-cloudflare/test/apps/workers/tsconfig.json b/packages/adapter-cloudflare/test/apps/workers/tsconfig.json index 0c2092500732..bfb714a809aa 100644 --- a/packages/adapter-cloudflare/test/apps/workers/tsconfig.json +++ b/packages/adapter-cloudflare/test/apps/workers/tsconfig.json @@ -1,13 +1,4 @@ { - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "moduleResolution": "bundler" - }, - "extends": "$app/tsconfig" + "extends": "$app/tsconfig", + "include": ["src", "worker-configuration.d.ts"] } diff --git a/packages/adapter-cloudflare/test/apps/workers/vite.config.js b/packages/adapter-cloudflare/test/apps/workers/vite.config.js index 195f6c80776e..2e7d6f775655 100644 --- a/packages/adapter-cloudflare/test/apps/workers/vite.config.js +++ b/packages/adapter-cloudflare/test/apps/workers/vite.config.js @@ -11,7 +11,7 @@ const config = { adapter: adapter({ config: 'config/wrangler.jsonc' }) - }) + }), ] }; diff --git a/packages/adapter-cloudflare/tsconfig.json b/packages/adapter-cloudflare/tsconfig.json index ce628354cbad..afcbf9c5ce74 100644 --- a/packages/adapter-cloudflare/tsconfig.json +++ b/packages/adapter-cloudflare/tsconfig.json @@ -15,5 +15,5 @@ "lib": ["es2024"], "types": ["node"] }, - "include": ["index.js", "utils.js", "utils.spec.js", "vitest.config.js", "test/utils.js"] + "include": ["index.js", "worker.js", "utils.js", "utils.spec.js", "vitest.config.js", "test/utils.js"] } diff --git a/packages/adapter-cloudflare/worker.d.ts b/packages/adapter-cloudflare/worker.d.ts new file mode 100644 index 000000000000..9cd11c778278 --- /dev/null +++ b/packages/adapter-cloudflare/worker.d.ts @@ -0,0 +1 @@ +export function handler(request: Request): Response; diff --git a/packages/adapter-cloudflare/worker.js b/packages/adapter-cloudflare/worker.js new file mode 100644 index 000000000000..5b2d09db92cd --- /dev/null +++ b/packages/adapter-cloudflare/worker.js @@ -0,0 +1,9 @@ +/** + * @param {Request} request + * @returns Response + */ +export function handler(request) { + const headers = new Headers(request.headers); + headers.set('x-sveltekit-cloudflare-handle', 'true'); + return fetch(request, { headers }); +} diff --git a/packages/kit/src/exports/internal/server/index.js b/packages/kit/src/exports/internal/server/index.js index a48db594f0db..1b81e1393748 100644 --- a/packages/kit/src/exports/internal/server/index.js +++ b/packages/kit/src/exports/internal/server/index.js @@ -34,4 +34,6 @@ export { init_remote_functions } from './remote-functions.js'; export { init_tracing, otel, record_span } from './telemetry.js'; +export { dedent } from '../../../core/sync/utils.js'; + export * from '../shared.js'; diff --git a/packages/kit/src/exports/public.d.ts b/packages/kit/src/exports/public.d.ts index 64c852afbf78..c615d89b6d57 100644 --- a/packages/kit/src/exports/public.d.ts +++ b/packages/kit/src/exports/public.d.ts @@ -35,6 +35,9 @@ export { PrerenderOption } from '../types/private.js'; // @ts-ignore this is an optional peer dependency so could be missing. Written like this so dts-buddy preserves the ts-ignore type Span = import('@opentelemetry/api').Span; +// @ts-ignore see above +type ServerResponse = import('http').ServerResponse; + type AppErrorWithOptionalStatus = Omit & { status?: App.Error['status'] }; /** @@ -50,6 +53,12 @@ export interface Adapter { * @param builder An object provided by SvelteKit that contains methods for adapting the app */ adapt: (builder: Builder) => MaybePromise; + /** + * This function allows adapters to handle the low-level process of transforming a `Response` into + * the format that vite understands. + * @returns Whether the response was handled + */ + setResponse?: (res: ServerResponse, response: Response) => boolean; /** * Checks called during dev and build to determine whether specific features will work in production with this adapter. */ @@ -73,10 +82,15 @@ export interface Adapter { emulate?: () => MaybePromise; vite?: { /** - * Plugins provided by the adapter are placed before any of SvelteKit's own plugins. + * Vite plugins placed before any of SvelteKit's own plugins. + * @since 3.0.0 + */ + pre_plugins?: Plugin[]; + /** + * Vite plugins placed after any of SvelteKit's own plugins. * @since 3.0.0 */ - plugins?: Plugin[]; + post_plugins?: Plugin[]; }; } diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js index 2dec6d74d782..b2783bdf9ad7 100644 --- a/packages/kit/src/exports/vite/dev/index.js +++ b/packages/kit/src/exports/vite/dev/index.js @@ -502,7 +502,8 @@ export async function dev( // serving routes with those names. See https://github.com/vitejs/vite/issues/7363 remove_static_middlewares(vite_dev_server.middlewares); - vite_dev_server.middlewares.use(async (req, res) => { + // eslint-disable-next-line prefer-arrow-callback + vite_dev_server.middlewares.use(async function sveltekitDevMiddleware(req, res) { // Vite throws a Cannot read properties of undefined (reading 'wrapDynamicImport') // if you try to run ssr.runner.import before the server has started so // we do it inside here to avoid that @@ -651,7 +652,13 @@ export async function dev( }); } else { log_response(rendered.status, request); - setResponse(res, rendered); + let adapter_set_response = false; + if (svelte_config.kit.adapter?.setResponse) { + adapter_set_response = svelte_config.kit.adapter.setResponse(res, rendered); + } + if (!adapter_set_response) { + setResponse(res, rendered); + } } } catch (e) { const error = coalesce_to_error(e); diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index a37f5e64fa6c..8b3785807abc 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -2056,7 +2056,7 @@ function kit({ svelte_config }) { return /** @type {Plugin[]} */ ( [ - svelte_config.kit.adapter?.vite?.plugins, + svelte_config.kit.adapter?.vite?.pre_plugins, plugin_resolve_root, plugin_setup, plugin_remote_guard, @@ -2066,7 +2066,8 @@ function kit({ svelte_config }) { plugin_service_worker, plugin_service_worker_env, plugin_compile, - plugin_adapter + plugin_adapter, + svelte_config.kit.adapter?.vite?.post_plugins, ].filter(Boolean) ); } diff --git a/packages/kit/src/runtime/server/endpoint.js b/packages/kit/src/runtime/server/endpoint.js index 4d640769dcc4..fc6d244939fa 100644 --- a/packages/kit/src/runtime/server/endpoint.js +++ b/packages/kit/src/runtime/server/endpoint.js @@ -45,11 +45,12 @@ export async function render_endpoint(event, state, mod) { handler(/** @type {import('@sveltejs/kit').RequestEvent>} */ (event)) ); - if (!(response instanceof Response)) { - throw new Error( - `Invalid response from route ${event.url.pathname}: handler should return a Response object` - ); - } + // TODO: need to accept Response-like objects here, such as from a different undici version + // if (!(response instanceof Response)) { + // throw new Error( + // `Invalid response from route ${event.url.pathname}: handler should return a Response object` + // ); + // } if (state.prerendering && (!state.prerendering.inside_reroute || prerender)) { // The returned Response might have immutable Headers diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 6122f53e10aa..7472d78c9b46 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -9,6 +9,9 @@ declare module '@sveltejs/kit' { // @ts-ignore this is an optional peer dependency so could be missing. Written like this so dts-buddy preserves the ts-ignore type Span = import('@opentelemetry/api').Span; + // @ts-ignore see above + type ServerResponse = import('http').ServerResponse; + type AppErrorWithOptionalStatus = Omit & { status?: App.Error['status'] }; /** @@ -24,6 +27,12 @@ declare module '@sveltejs/kit' { * @param builder An object provided by SvelteKit that contains methods for adapting the app */ adapt: (builder: Builder) => MaybePromise; + /** + * This function allows adapters to handle the low-level process of transforming a `Response` into + * the format that vite understands. + * @returns Whether the response was handled + */ + setResponse?: (res: ServerResponse, response: Response) => boolean; /** * Checks called during dev and build to determine whether specific features will work in production with this adapter. */ @@ -47,10 +56,15 @@ declare module '@sveltejs/kit' { emulate?: () => MaybePromise; vite?: { /** - * Plugins provided by the adapter are placed before any of SvelteKit's own plugins. + * Vite plugins placed before any of SvelteKit's own plugins. + * @since 3.0.0 + */ + pre_plugins?: Plugin[]; + /** + * Vite plugins placed after any of SvelteKit's own plugins. * @since 3.0.0 */ - plugins?: Plugin[]; + post_plugins?: Plugin[]; }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a2a675ac1bdc..995458026e7f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -94,8 +94,8 @@ catalogs: specifier: ^4.1.10 version: 4.1.10 wrangler: - specifier: ^4.118.0 - version: 4.118.0 + specifier: ^4.119.0 + version: 4.119.0 importers: @@ -143,28 +143,46 @@ importers: packages/adapter-cloudflare: dependencies: + '@cloudflare/vite-plugin': + specifier: ^1.51.0 + version: 1.51.0(vite@8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0))(wrangler@4.119.0(@cloudflare/workers-types@5.20260804.1)) '@cloudflare/workers-types': specifier: ^5.20260730.1 version: 5.20260804.1 wrangler: - specifier: ^4.118.0 - version: 4.118.0(@cloudflare/workers-types@5.20260804.1) + specifier: ^4.119.0 + version: 4.119.0(@cloudflare/workers-types@5.20260804.1) devDependencies: '@playwright/test': specifier: 'catalog:' version: 1.62.1 + '@rolldown/pluginutils': + specifier: ^1.0.1 + version: 1.0.1 '@sveltejs/kit': specifier: workspace:^ version: link:../kit '@types/node': specifier: 'catalog:' version: 22.19.19 + '@types/ws': + specifier: ^8.18.1 + version: 8.18.1 + miniflare: + specifier: 5.20260801.0-alpha + version: 5.20260801.0-alpha typescript: specifier: 'catalog:' version: 6.0.3 + vite: + specifier: 'catalog:' + version: 8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0) vitest: specifier: 'catalog:' version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.19)(@vitest/browser-playwright@4.1.10)(jsdom@30.0.1)(vite@8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0)) + ws: + specifier: ^8.21.2 + version: 8.21.2 packages/adapter-cloudflare/test/apps/pages: devDependencies: @@ -185,7 +203,7 @@ importers: version: 8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0) wrangler: specifier: 'catalog:' - version: 4.118.0(@cloudflare/workers-types@5.20260804.1) + version: 4.119.0(@cloudflare/workers-types@5.20260804.1) packages/adapter-cloudflare/test/apps/workers: devDependencies: @@ -206,7 +224,7 @@ importers: version: 8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0) wrangler: specifier: 'catalog:' - version: 4.118.0(@cloudflare/workers-types@5.20260804.1) + version: 4.119.0(@cloudflare/workers-types@5.20260804.1) packages/adapter-netlify: dependencies: @@ -1662,32 +1680,39 @@ packages: workerd: optional: true - '@cloudflare/workerd-darwin-64@1.20260730.1': - resolution: {integrity: sha512-+MBHmPaiTe2KajryW0T24rZvWFxb41hD3d8anNzQqHzft6vSEb18+sp0znSwxgij7ApPhSM1+vhkNg4f3YMguA==} + '@cloudflare/vite-plugin@1.51.0': + resolution: {integrity: sha512-8ltb2RA6U1i7KGDzVsRBDa7+GvWRBNGBx0mjTxdsHh/6zgCcUPLT3I8Kwp/xUkIbInojnwh8GAtnbuLJPfcK6w==} + hasBin: true + peerDependencies: + vite: ^6.1.0 || ^7.0.0 || ^8.0.0 + wrangler: ^4.119.0 + + '@cloudflare/workerd-darwin-64@1.20260801.1': + resolution: {integrity: sha512-wuJWbXpKvncJi1P0GKS+iYpN5tHdb7JPJJ/+6ZQe8zzovHHVMkLJPNBsgWpqeUhpM3g9qTwEKd2rglNKejuh5A==} engines: {node: '>=16'} cpu: [x64] os: [darwin] - '@cloudflare/workerd-darwin-arm64@1.20260730.1': - resolution: {integrity: sha512-SBHKntPkKvNPgaCrTe99xC1CAl8ygJDzlYfK0LbuJ1muKadIw35WnhO0wu894fKBtllsVQdNzDLee+cm0ppLSQ==} + '@cloudflare/workerd-darwin-arm64@1.20260801.1': + resolution: {integrity: sha512-kwoZiTpnhNrF3+APx84Q/oAqvJ3sU9yefGagwm/ASaH/2W19x0vghkW/r4qCoHCK0WW7EPugZ+aXjgPMRtlq1Q==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] - '@cloudflare/workerd-linux-64@1.20260730.1': - resolution: {integrity: sha512-ouyPOSMbiKPeSwUJUvxtMcxGAXs2J4aPE4T5ABIYX5ClcQx5j5bbHTmnqOQEY8sAuLTPjH7dY+iB6UI5ISlwwA==} + '@cloudflare/workerd-linux-64@1.20260801.1': + resolution: {integrity: sha512-r0vAxCZH+Jih9Unm1yoyiByPNWNgawcKciOHDm5Q37ZVGOkKLsT9AtLe3yLSaul76WrKqtf+JP2n0WW32VBLJg==} engines: {node: '>=16'} cpu: [x64] os: [linux] - '@cloudflare/workerd-linux-arm64@1.20260730.1': - resolution: {integrity: sha512-YQ+Mi78U3TPdgBPtwq+Sm6rJU+Ihl2y0pjYtuuKkdmUbYzL7oLR6Xqq9wljhasnuCFICssDJaqhMep5WizYoEQ==} + '@cloudflare/workerd-linux-arm64@1.20260801.1': + resolution: {integrity: sha512-zWgpdZtSozvIgzQNmQiDSF8yEOQJUkRAWNsDXXzAAoy+fCn8YUoSibj3mpFSbZRvbUldeBEaW6SCdC2VEMkhNQ==} engines: {node: '>=16'} cpu: [arm64] os: [linux] - '@cloudflare/workerd-windows-64@1.20260730.1': - resolution: {integrity: sha512-27fAN+vUECW1oYVc1KOcHYpkL8COM2Uxtxql7TL595kxbjoqS5yckw7NLz7bTf2pALFCZWjqXDjZGJ/xbG4ZKQ==} + '@cloudflare/workerd-windows-64@1.20260801.1': + resolution: {integrity: sha512-2oQz+Ksu4ji6e/+ZoYX+tWQEcxAii2p7l+iR8kx48W1llMalaufAsmVxTlk+3/vrM7D3/2c0iK448e0UQTcIMg==} engines: {node: '>=16'} cpu: [x64] os: [win32] @@ -2921,6 +2946,9 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@typescript-eslint/eslint-plugin@8.58.0': resolution: {integrity: sha512-RLkVSiNuUP1C2ROIWfqX+YcUfLaSnxGE/8M+Y57lopVwg9VTYYfhuz15Yf1IzCKgZj6/rIbYTmJCUSqr76r0Wg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3655,8 +3683,8 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} - miniflare@5.20260730.0-alpha: - resolution: {integrity: sha512-8/dspSXDshP6nSkCpjKO7BYc2qZoYSXm7iM+QxY7qJyJpAB3onnQSaiu0cvKJlfuMGwULl55hG69FJCcCMXU1Q==} + miniflare@5.20260801.0-alpha: + resolution: {integrity: sha512-AfMrnQbJg81ESsGkGhOkHBtwTqCG+mosR+3GE+qDrhF1I/ieIvgg3ICxNyBvgHBZ3iapy6cysBQHNPykkzrfgw==} engines: {node: '>=22.0.0'} minimatch@10.2.5: @@ -4296,17 +4324,17 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - workerd@1.20260730.1: - resolution: {integrity: sha512-zmfNIjwYSWFY5chGBOjWtH3xAE7p97FTC6vR4Ep98290ho6AeAR/NVcBD274YCLEUYzqm8yxdtZlxMybU8a3jA==} + workerd@1.20260801.1: + resolution: {integrity: sha512-/g9JGTyqnHtoIscpBHqKD8swE2V4StBs2i69PmLiOhH45OP95jCFICl4F1hKlgN57rqfni5LiCitttoX5OOkVA==} engines: {node: '>=16'} hasBin: true - wrangler@4.118.0: - resolution: {integrity: sha512-9pkBw/b8zWqGx2S+oLhgHMR1M/4VOE8SynUFABnGWiSFGlcOQ4xiI/B71Xf66RYP2xzngU37IQFPtUruij3lYw==} + wrangler@4.119.0: + resolution: {integrity: sha512-ookClf+zly4DTc8pBMNrwGQzZKH8IpIYTXkjDw3XS7ZvBQ5mLYH6eOvfD5BEpk3U63zTbv91WRlo1UeRSKXa0g==} engines: {node: '>=22.0.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^5.20260730.1 + '@cloudflare/workers-types': ^5.20260801.1 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -4327,6 +4355,18 @@ packages: utf-8-validate: optional: true + ws@8.21.2: + resolution: {integrity: sha512-54dMVAo4WIe6SKy3vBgN+9bJZqqQ8IMRevAkOLQALhi49qkkQDQfWdAZ8KQlXiEabw88ARXXdUrlvtbKQX+aKw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -4522,25 +4562,38 @@ snapshots: '@cloudflare/kv-asset-handler@0.5.0': {} - '@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260730.1)': + '@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260801.1)': dependencies: unenv: 2.0.0-rc.24 optionalDependencies: - workerd: 1.20260730.1 + workerd: 1.20260801.1 - '@cloudflare/workerd-darwin-64@1.20260730.1': + '@cloudflare/vite-plugin@1.51.0(vite@8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0))(wrangler@4.119.0(@cloudflare/workers-types@5.20260804.1))': + dependencies: + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260801.1) + miniflare: 5.20260801.0-alpha + unenv: 2.0.0-rc.24 + vite: 8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0) + workerd: 1.20260801.1 + wrangler: 4.119.0(@cloudflare/workers-types@5.20260804.1) + ws: 8.21.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@cloudflare/workerd-darwin-64@1.20260801.1': optional: true - '@cloudflare/workerd-darwin-arm64@1.20260730.1': + '@cloudflare/workerd-darwin-arm64@1.20260801.1': optional: true - '@cloudflare/workerd-linux-64@1.20260730.1': + '@cloudflare/workerd-linux-64@1.20260801.1': optional: true - '@cloudflare/workerd-linux-arm64@1.20260730.1': + '@cloudflare/workerd-linux-arm64@1.20260801.1': optional: true - '@cloudflare/workerd-windows-64@1.20260730.1': + '@cloudflare/workerd-windows-64@1.20260801.1': optional: true '@cloudflare/workers-types@5.20260804.1': {} @@ -5530,6 +5583,10 @@ snapshots: '@types/trusted-types@2.0.7': {} + '@types/ws@8.18.1': + dependencies: + '@types/node': 22.19.19 + '@typescript-eslint/eslint-plugin@8.58.0(@typescript-eslint/parser@8.58.0(eslint@10.8.0(jiti@2.4.2)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.8.0(jiti@2.4.2)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -5665,7 +5722,7 @@ snapshots: sirv: 3.0.2 tinyrainbow: 3.1.0 vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.19)(@vitest/browser-playwright@4.1.10)(jsdom@30.0.1)(vite@8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0)) - ws: 8.21.0 + ws: 8.21.2 transitivePeerDependencies: - bufferutil - msw @@ -6302,12 +6359,12 @@ snapshots: mdn-data@2.27.1: {} - miniflare@5.20260730.0-alpha: + miniflare@5.20260801.0-alpha: dependencies: '@cspotcode/source-map-support': 0.8.1 sharp: 0.35.2 undici: 7.28.0 - workerd: 1.20260730.1 + workerd: 1.20260801.1 ws: 8.21.0 youch: 4.1.0-beta.10 transitivePeerDependencies: @@ -6921,24 +6978,24 @@ snapshots: word-wrap@1.2.5: {} - workerd@1.20260730.1: + workerd@1.20260801.1: optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20260730.1 - '@cloudflare/workerd-darwin-arm64': 1.20260730.1 - '@cloudflare/workerd-linux-64': 1.20260730.1 - '@cloudflare/workerd-linux-arm64': 1.20260730.1 - '@cloudflare/workerd-windows-64': 1.20260730.1 + '@cloudflare/workerd-darwin-64': 1.20260801.1 + '@cloudflare/workerd-darwin-arm64': 1.20260801.1 + '@cloudflare/workerd-linux-64': 1.20260801.1 + '@cloudflare/workerd-linux-arm64': 1.20260801.1 + '@cloudflare/workerd-windows-64': 1.20260801.1 - wrangler@4.118.0(@cloudflare/workers-types@5.20260804.1): + wrangler@4.119.0(@cloudflare/workers-types@5.20260804.1): dependencies: '@cloudflare/kv-asset-handler': 0.5.0 - '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260730.1) + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260801.1) blake3-wasm: 2.1.5 esbuild: 0.28.1 - miniflare: 5.20260730.0-alpha + miniflare: 5.20260801.0-alpha path-to-regexp: 6.3.0 unenv: 2.0.0-rc.24 - workerd: 1.20260730.1 + workerd: 1.20260801.1 optionalDependencies: '@cloudflare/workers-types': 5.20260804.1 fsevents: 2.3.3 @@ -6954,6 +7011,8 @@ snapshots: ws@8.21.0: {} + ws@8.21.2: {} + xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 3bfac531a678..f0a9f5eef2ba 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -78,7 +78,7 @@ catalog: typescript: ^6.0.3 valibot: ^1.4.2 vite: ^8.1.5 - wrangler: ^4.118.0 + wrangler: ^4.119.0 # unit test deps that should be upgraded together '@vitest/browser-playwright': ^4.1.10