diff --git a/.changeset/kind-carrots-deliver.md b/.changeset/kind-carrots-deliver.md new file mode 100644 index 000000000000..3e59bbc5d6e6 --- /dev/null +++ b/.changeset/kind-carrots-deliver.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-cloudflare': major +--- + +feat: support specifically building for Cloudflare Workers Static Assets diff --git a/README.md b/README.md index ada896b1fa99..23b1395bd036 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ Web development, streamlined. Read the [documentation](https://svelte.dev/docs/k | [@sveltejs/kit](packages/kit) | [Changelog](packages/kit/CHANGELOG.md) | | [@sveltejs/adapter-auto](packages/adapter-auto) | [Changelog](packages/adapter-auto/CHANGELOG.md) | | [@sveltejs/adapter-cloudflare](packages/adapter-cloudflare) | [Changelog](packages/adapter-cloudflare/CHANGELOG.md) | -| [@sveltejs/adapter-cloudflare-workers](packages/adapter-cloudflare-workers) | [Changelog](packages/adapter-cloudflare-workers/CHANGELOG.md) | | [@sveltejs/adapter-netlify](packages/adapter-netlify) | [Changelog](packages/adapter-netlify/CHANGELOG.md) | | [@sveltejs/adapter-node](packages/adapter-node) | [Changelog](packages/adapter-node/CHANGELOG.md) | | [@sveltejs/adapter-static](packages/adapter-static) | [Changelog](packages/adapter-static/CHANGELOG.md) | diff --git a/documentation/docs/25-build-and-deploy/20-adapters.md b/documentation/docs/25-build-and-deploy/20-adapters.md index c12df05964a2..62f0cc20fb8a 100644 --- a/documentation/docs/25-build-and-deploy/20-adapters.md +++ b/documentation/docs/25-build-and-deploy/20-adapters.md @@ -6,8 +6,7 @@ Before you can deploy your SvelteKit app, you need to _adapt_ it for your deploy Official adapters exist for a variety of platforms — these are documented on the following pages: -- [`@sveltejs/adapter-cloudflare`](adapter-cloudflare) for Cloudflare Pages -- [`@sveltejs/adapter-cloudflare-workers`](adapter-cloudflare-workers) for Cloudflare Workers +- [`@sveltejs/adapter-cloudflare`](adapter-cloudflare) for Cloudflare Workers and Cloudflare Pages - [`@sveltejs/adapter-netlify`](adapter-netlify) for Netlify - [`@sveltejs/adapter-node`](adapter-node) for Node servers - [`@sveltejs/adapter-static`](adapter-static) for static site generation (SSG) diff --git a/documentation/docs/25-build-and-deploy/60-adapter-cloudflare.md b/documentation/docs/25-build-and-deploy/60-adapter-cloudflare.md index c963795b61da..a8fbb725d9d2 100644 --- a/documentation/docs/25-build-and-deploy/60-adapter-cloudflare.md +++ b/documentation/docs/25-build-and-deploy/60-adapter-cloudflare.md @@ -2,22 +2,21 @@ title: Cloudflare Pages --- -To deploy to [Cloudflare Pages](https://pages.cloudflare.com/), use [`adapter-cloudflare`](https://github.com/sveltejs/kit/tree/main/packages/adapter-cloudflare). +To deploy to [Cloudflare Workers](https://workers.cloudflare.com/) or [Cloudflare Pages](https://pages.cloudflare.com/), use [`adapter-cloudflare`](https://github.com/sveltejs/kit/tree/main/packages/adapter-cloudflare). -This adapter will be installed by default when you use [`adapter-auto`](adapter-auto). If you plan on staying with Cloudflare Pages, you can switch from [`adapter-auto`](adapter-auto) to using this adapter directly so that `event.platform` is emulated during local development, type declarations are automatically applied, and the ability to set Cloudflare-specific options is provided. +This adapter will be installed by default when you use [`adapter-auto`](adapter-auto). If you plan on staying with Cloudflare, you can switch from [`adapter-auto`](adapter-auto) to using this adapter directly so that `event.platform` is emulated during local development, type declarations are automatically applied, and the ability to set Cloudflare-specific options is provided. ## Comparisons -- `adapter-cloudflare` – supports all SvelteKit features; builds for [Cloudflare Pages](https://blog.cloudflare.com/cloudflare-pages-goes-full-stack/) -- `adapter-cloudflare-workers` – supports all SvelteKit features; builds for Cloudflare Workers -- `adapter-static` – only produces client-side static assets; compatible with Cloudflare Pages +- `adapter-cloudflare` – supports all SvelteKit features; builds for Cloudflare Workers Static Assets and Cloudflare Pages +- `adapter-cloudflare-workers` – deprecated. Supports all SvelteKit features; builds for Cloudflare Workers Sites +- `adapter-static` – only produces client-side static assets; compatible with Cloudflare Workers Static Assets and Cloudflare Pages ## Usage Install with `npm i -D @sveltejs/adapter-cloudflare`, then add the adapter to your `svelte.config.js`: ```js -// @errors: 2307 /// file: svelte.config.js import adapter from '@sveltejs/adapter-cloudflare'; @@ -25,14 +24,16 @@ export default { kit: { adapter: adapter({ // See below for an explanation of these options - routes: { - include: ['/*'], - exclude: [''] - }, + config: undefined, platformProxy: { configPath: undefined, environment: undefined, persist: undefined + }, + fallback: 'plaintext', + routes: { + include: ['/*'], + exclude: [''] } }) } @@ -41,9 +42,31 @@ export default { ## Options +### config + +Path to your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). If you would like to use a Wrangler configuration filename other than `wrangler.jsonc`, `wrangler.json`, or `wrangler.toml` you can specify it using this option. + +### platformProxy + +Preferences for the emulated `platform.env` local bindings. See the [getPlatformProxy](https://developers.cloudflare.com/workers/wrangler/api/#parameters-1) Wrangler API documentation for a full list of options. + +### fallback + +Whether to render a plaintext 404.html page or a rendered SPA fallback page for non-matching asset requests. + +For Cloudflare Workers, the default behaviour is to return a null-body 404-status response for non-matching assets requests. However, if the [`assets.not_found_handling`](https://developers.cloudflare.com/workers/static-assets/routing/#2-not_found_handling) Wrangler configuration setting is set to `"404-page"`, this page will be served if a request fails to match an asset. If `assets.not_found_handling` is set to `"single-page-application"`, the adapter will render a SPA fallback index.html page regardless of the `fallback` option specified. + +For Cloudflare Pages, this page will only be served when a request that matches an entry in `routes.exclude` fails to match an asset. + +Most of the time `plaintext` is sufficient, but if you are using `routes.exclude` to manually +exclude a set of prerendered pages without exceeding the 100 route limit, you may wish to +use `spa` instead to avoid showing an unstyled 404 page to users. + +See Cloudflare Pages' [Not Found behaviour](https://developers.cloudflare.com/pages/configuration/serving-pages/#not-found-behavior) for more info. + ### routes -Allows you to customise the [`_routes.json`](https://developers.cloudflare.com/pages/functions/routing/#create-a-_routesjson-file) file generated by `adapter-cloudflare`. +Only for Cloudflare Pages. Allows you to customise the [`_routes.json`](https://developers.cloudflare.com/pages/functions/routing/#create-a-_routesjson-file) file generated by `adapter-cloudflare`. - `include` defines routes that will invoke a function, and defaults to `['/*']` - `exclude` defines routes that will _not_ invoke a function — this is a faster and cheaper way to serve your app's static assets. This array can include the following special values: @@ -54,23 +77,52 @@ Allows you to customise the [`_routes.json`](https://developers.cloudflare.com/p You can have up to 100 `include` and `exclude` rules combined. Generally you can omit the `routes` options, but if (for example) your `` paths exceed that limit, you may find it helpful to manually create an `exclude` list that includes `'/articles/*'` instead of the auto-generated `['/articles/foo', '/articles/bar', '/articles/baz', ...]`. -### platformProxy +## Cloudflare Workers -Preferences for the emulated `platform.env` local bindings. See the [getPlatformProxy](https://developers.cloudflare.com/workers/wrangler/api/#parameters-1) Wrangler API documentation for a full list of options. +### Basic configuration + +When building for Cloudflare Workers, this adapter expects to find a [Wrangler configuration file](https://developers.cloudflare.com/workers/configuration/sites/configuration/) in the project root. It should look something like this: + +```jsonc +/// file: wrangler.jsonc +{ + "name": "", + "main": ".svelte-kit/cloudflare/_worker.js", + "compatibility_date": "2025-01-01", + "assets": { + "binding": "ASSETS", + "directory": ".svelte-kit/cloudflare", + } +} +``` + +### Deployment + +Please follow the [framework guide](https://developers.cloudflare.com/workers/frameworks/framework-guides/svelte/) for Cloudflare Workers to begin. + +## Cloudflare Pages -## Deployment +### Deployment Please follow the [Get Started Guide](https://developers.cloudflare.com/pages/get-started/) for Cloudflare Pages to begin. -When configuring your project settings, you must use the following settings: +If you're using the [Git integration](https://developers.cloudflare.com/pages/get-started/git-integration/), your build settings should look like this: - **Framework preset** – SvelteKit - **Build command** – `npm run build` or `vite build` - **Build output directory** – `.svelte-kit/cloudflare` +### Further reading + +You may wish to refer to [Cloudflare's documentation for deploying a SvelteKit site on Cloudflare Pages](https://developers.cloudflare.com/pages/framework-guides/deploy-a-svelte-kit-site/). + +### Notes + +Functions contained in the [`/functions` directory](https://developers.cloudflare.com/pages/functions/routing/) at the project's root will _not_ be included in the deployment. Instead, functions should be implemented as [server endpoints](routing#server) in your SvelteKit app, which is compiled to a [single `_worker.js` file](https://developers.cloudflare.com/pages/functions/advanced-mode/). + ## Runtime APIs -The [`env`](https://developers.cloudflare.com/workers/runtime-apis/fetch-event#parameters) object contains your project's [bindings](https://developers.cloudflare.com/pages/functions/bindings/), which consist of KV/DO namespaces, etc. It is passed to SvelteKit via the `platform` property, along with [`context`](https://developers.cloudflare.com/workers/runtime-apis/context/), [`caches`](https://developers.cloudflare.com/workers/runtime-apis/cache/), and [`cf`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties), meaning that you can access it in hooks and endpoints: +The [`env`](https://developers.cloudflare.com/workers/runtime-apis/fetch-event#parameters) object contains your project's [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/), which consist of KV/DO namespaces, etc. It is passed to SvelteKit via the `platform` property, along with [`context`](https://developers.cloudflare.com/workers/runtime-apis/context/), [`caches`](https://developers.cloudflare.com/workers/runtime-apis/cache/), and [`cf`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties), meaning that you can access it in hooks and endpoints: ```js // @errors: 7031 @@ -101,26 +153,20 @@ declare global { export {}; ``` -### Testing Locally +### Testing locally -Cloudflare Workers specific values in the `platform` property are emulated during dev and preview modes. Local [bindings](https://developers.cloudflare.com/pages/functions/bindings/) are created based on your [Wrangler configuration file](https://developers.cloudflare.com/pages/functions/wrangler-configuration/#local-development) and are used to populate `platform.env` during development and preview. Use the adapter config [`platformProxy` option](#Options-platformProxy) to change your preferences for the bindings. +Cloudflare specific values in the `platform` property are emulated during dev and preview modes. Local [bindings](https://developers.cloudflare.com/workers/wrangler/configuration/#bindings) are created based on your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/) and are used to populate `platform.env` during development and preview. Use the adapter config [`platformProxy` option](#Options-platformProxy) to change your preferences for the bindings. -For testing the build, you should use [Wrangler](https://developers.cloudflare.com/workers/wrangler/) **version 3**. Once you have built your site, run `wrangler pages dev .svelte-kit/cloudflare`. +For testing the build, you should use [Wrangler](https://developers.cloudflare.com/workers/wrangler/) **version 4**. Once you have built your site, run `wrangler dev .svelte-kit/cloudflare` if you're testing for Cloudflare Workers or `wrangler pages dev .svelte-kit/cloudflare` for Cloudflare Pages. -## Notes - -Functions contained in the [`/functions` directory](https://developers.cloudflare.com/pages/functions/routing/) at the project's root will _not_ be included in the deployment. Instead, functions should be implemented as [server endpoints](routing#server) in your SvelteKit app, which is compiled to a [single `_worker.js` file](https://developers.cloudflare.com/pages/functions/advanced-mode/). +## `_headers` and `_redirects` -The [`_headers`](https://developers.cloudflare.com/pages/configuration/headers/) and [`_redirects`](https://developers.cloudflare.com/pages/configuration/redirects/) files specific to Cloudflare Pages can be used for static asset responses (like images) by putting them into the project root folder. +The [`_headers`](https://developers.cloudflare.com/pages/configuration/headers/) and [`_redirects`](https://developers.cloudflare.com/pages/configuration/redirects/) files specific can be used for static asset responses (like images) by putting them into the project root folder. However, they will have no effect on responses dynamically rendered by SvelteKit, which should return custom headers or redirect responses from [server endpoints](routing#server) or with the [`handle`](hooks#Server-hooks-handle) hook. ## Troubleshooting -### Further reading - -You may wish to refer to [Cloudflare's documentation for deploying a SvelteKit site](https://developers.cloudflare.com/pages/framework-guides/deploy-a-svelte-kit-site/). - ### Node.js compatibility If you would like to enable [Node.js compatibility](https://developers.cloudflare.com/workers/runtime-apis/nodejs/), you can add the `nodejs_compat` compatibility flag to your Wrangler configuration file: @@ -139,3 +185,45 @@ When deploying your application, the server generated by SvelteKit is bundled in ### Accessing the file system You can't use `fs` in Cloudflare Workers — you must [prerender](page-options#prerender) the routes in question. + +## Migrating from Workers Sites to Workers Static Assets + +Cloudflare no longer recommends using [Workers Sites](https://developers.cloudflare.com/workers/configuration/sites/configuration/) and instead recommends using [Workers Static Assets](https://developers.cloudflare.com/workers/static-assets/). To migrate, replace `@sveltejs/adapter-cloudflare-workers` with `@sveltejs/adapter-cloudflare` and remove all `site` configuration settings from your Wrangler configuration file, then add the `assets.directory` and `assets.binding` configuration settings: + +### svelte.config.js + +```js +/// file: svelte.config.js +---import adapter from '@sveltejs/adapter-cloudflare-workers';--- ++++import adapter from '@sveltejs/adapter-cloudflare';+++ + +export default { + kit: { + adapter: adapter() + } +}; +``` + +### wrangler.toml + +```toml +/// file: wrangler.toml +---site.bucket = ".cloudflare/public"--- ++++assets.directory = ".cloudflare/public" +assets.binding = "ASSETS"+++ +``` + +### wrangler.jsonc + +```jsonc +/// file: wrangler.jsonc +{ +--- "site": { + "bucket": ".cloudflare/public" + },--- ++++ "assets": { + "directory": ".cloudflare/public", + "binding": "ASSETS" + }+++ +} +``` \ No newline at end of file diff --git a/documentation/docs/25-build-and-deploy/70-adapter-cloudflare-workers.md b/documentation/docs/25-build-and-deploy/70-adapter-cloudflare-workers.md index 71197d9daabe..f346b1d83572 100644 --- a/documentation/docs/25-build-and-deploy/70-adapter-cloudflare-workers.md +++ b/documentation/docs/25-build-and-deploy/70-adapter-cloudflare-workers.md @@ -2,9 +2,9 @@ title: Cloudflare Workers --- -To deploy to [Cloudflare Workers](https://workers.cloudflare.com/), use [`adapter-cloudflare-workers`](https://github.com/sveltejs/kit/tree/main/packages/adapter-cloudflare-workers). +> [!NOTE] `adapter-cloudflare-workers` has been deprecated in favour of [`adapter-cloudflare`](adapter-cloudflare). We recommend using `adapter-cloudflare` to deploy to Cloudflare Workers with [Static Assets](https://developers.cloudflare.com/workers/static-assets/) since Cloudflare Workers Sites will be deprecated in favour of it. -> [!NOTE] Unless you have a specific reason to use `adapter-cloudflare-workers`, it's recommended that you use [`adapter-cloudflare`](adapter-cloudflare) instead. Both adapters have equivalent functionality, but Cloudflare Pages offers features like GitHub integration with automatic builds and deploys, preview deployments, instant rollback and so on. +To deploy to [Cloudflare Workers](https://workers.cloudflare.com/) with [Workers Sites](https://developers.cloudflare.com/workers/configuration/sites/), use `adapter-cloudflare-workers`. ## Usage @@ -28,7 +28,7 @@ export default { ### config -Path to your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). If you would like to use a Wrangler configuration filename other than `wrangler.jsonc`, you can specify it using this option. +Path to your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). If you would like to use a Wrangler configuration filename other than `wrangler.jsonc`, `wrangler.json`, or `wrangler.toml` you can specify it using this option. ### platformProxy @@ -112,7 +112,7 @@ export {}; Cloudflare Workers specific values in the `platform` property are emulated during dev and preview modes. Local [bindings](https://developers.cloudflare.com/workers/wrangler/configuration/#bindings) are created based on your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/) and are used to populate `platform.env` during development and preview. Use the adapter config [`platformProxy` option](#Options-platformProxy) to change your preferences for the bindings. -For testing the build, you should use [Wrangler](https://developers.cloudflare.com/workers/wrangler/) **version 3**. Once you have built your site, run `wrangler dev`. +For testing the build, you should use [Wrangler](https://developers.cloudflare.com/workers/wrangler/) **version 4**. Once you have built your site, run `wrangler dev`. ## Troubleshooting diff --git a/eslint.config.js b/eslint.config.js index f780ffd104d9..8444424cd723 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -30,6 +30,7 @@ export default [ '@typescript-eslint/no-floating-promises': 'error' }, ignores: [ + 'packages/adapter-cloudflare/test/apps/**/*', 'packages/adapter-node/rollup.config.js', 'packages/adapter-node/tests/smoke.spec_disabled.js', 'packages/adapter-static/test/apps/**/*', diff --git a/packages/adapter-cloudflare-workers/CHANGELOG.md b/packages/adapter-cloudflare-workers/CHANGELOG.md deleted file mode 100644 index 30314f9e5c91..000000000000 --- a/packages/adapter-cloudflare-workers/CHANGELOG.md +++ /dev/null @@ -1,761 +0,0 @@ -# @sveltejs/adapter-cloudflare-workers - -## 2.9.0 -### Minor Changes - - -- feat: support wrangler 4 ([#13580](https://github.com/sveltejs/kit/pull/13580)) - - -### Patch Changes - -- Updated dependencies [[`001bc04dece9b0983efc2187225772c19d135345`](https://github.com/sveltejs/kit/commit/001bc04dece9b0983efc2187225772c19d135345)]: - - @sveltejs/kit@2.19.2 - -## 2.8.0 -### Minor Changes - - -- feat: support `.jsonc` Wrangler configuration files ([#13467](https://github.com/sveltejs/kit/pull/13467)) - - -### Patch Changes - -- Updated dependencies [[`28cf64589a331ea4770c0883216c5e16d1de7496`](https://github.com/sveltejs/kit/commit/28cf64589a331ea4770c0883216c5e16d1de7496), [`ef1e8047225e7a79c6d121d8ed1a571e5ea44f08`](https://github.com/sveltejs/kit/commit/ef1e8047225e7a79c6d121d8ed1a571e5ea44f08), [`2e6527b92875976b79cc00e7b75ee0ad8b69a239`](https://github.com/sveltejs/kit/commit/2e6527b92875976b79cc00e7b75ee0ad8b69a239), [`0c0172e1463218fe63a67c587173bb3065a53c49`](https://github.com/sveltejs/kit/commit/0c0172e1463218fe63a67c587173bb3065a53c49)]: - - @sveltejs/kit@2.17.3 - -## 2.7.1 -### Patch Changes - - -- fix: prevent Vitest from hanging, which was not fully addressed in [#12830](https://github.com/sveltejs/kit/pull/12830) ([#13373](https://github.com/sveltejs/kit/pull/13373)) - -- Updated dependencies [[`09296d0f19c8d1ff57d699e637bd1beabb69d438`](https://github.com/sveltejs/kit/commit/09296d0f19c8d1ff57d699e637bd1beabb69d438), [`d62ed39a431f0db3db4dd90bf6b17ed2a2a2de79`](https://github.com/sveltejs/kit/commit/d62ed39a431f0db3db4dd90bf6b17ed2a2a2de79), [`f30352f874790b9de0bd0eba985a21aef23e158e`](https://github.com/sveltejs/kit/commit/f30352f874790b9de0bd0eba985a21aef23e158e), [`180fa3467e195065c0a25206c6328a908e6952d7`](https://github.com/sveltejs/kit/commit/180fa3467e195065c0a25206c6328a908e6952d7), [`5906e9708965b848b468d0014999c36272dc8d50`](https://github.com/sveltejs/kit/commit/5906e9708965b848b468d0014999c36272dc8d50), [`d62ed39a431f0db3db4dd90bf6b17ed2a2a2de79`](https://github.com/sveltejs/kit/commit/d62ed39a431f0db3db4dd90bf6b17ed2a2a2de79)]: - - @sveltejs/kit@2.17.0 - -## 2.7.0 -### Minor Changes - - -- feat: support `wrangler.json` config file ([#13151](https://github.com/sveltejs/kit/pull/13151)) - - -### Patch Changes - -- Updated dependencies [[`11a9f66922199ee5925cc71c0efc513376753754`](https://github.com/sveltejs/kit/commit/11a9f66922199ee5925cc71c0efc513376753754), [`3d9e03a8a55a539b02c76d44df4874e4642bbd17`](https://github.com/sveltejs/kit/commit/3d9e03a8a55a539b02c76d44df4874e4642bbd17)]: - - @sveltejs/kit@2.11.0 - -## 2.6.0 -### Minor Changes - - -- chore: upgrade esbuild to 0.24.0 ([#12270](https://github.com/sveltejs/kit/pull/12270)) - - -### Patch Changes - -- Updated dependencies [[`d030f4bb285e70844d09b3f0c87809bae43014b8`](https://github.com/sveltejs/kit/commit/d030f4bb285e70844d09b3f0c87809bae43014b8), [`67dd214863cbc5852eb0e8512efbb7bad5358e8a`](https://github.com/sveltejs/kit/commit/67dd214863cbc5852eb0e8512efbb7bad5358e8a)]: - - @sveltejs/kit@2.9.0 - -## 2.5.6 -### Patch Changes - - -- docs: update URLs for new svelte.dev site ([#12857](https://github.com/sveltejs/kit/pull/12857)) - -- Updated dependencies [[`dcbe4222a194c5f90cfc0fc020cf065f7a4e4c46`](https://github.com/sveltejs/kit/commit/dcbe4222a194c5f90cfc0fc020cf065f7a4e4c46), [`4cdbf76fbbf0c0ce7f574ef69c8daddcf954d39d`](https://github.com/sveltejs/kit/commit/4cdbf76fbbf0c0ce7f574ef69c8daddcf954d39d), [`3a9b78f04786898ca93f6d4b75ab18d26bc45192`](https://github.com/sveltejs/kit/commit/3a9b78f04786898ca93f6d4b75ab18d26bc45192), [`723eb8b31e6a22c82f730c30e485386c8676b746`](https://github.com/sveltejs/kit/commit/723eb8b31e6a22c82f730c30e485386c8676b746), [`8ec471c875345b751344e67580ff1b772ef2735b`](https://github.com/sveltejs/kit/commit/8ec471c875345b751344e67580ff1b772ef2735b)]: - - @sveltejs/kit@2.7.3 - -## 2.5.5 -### Patch Changes - - -- fix: correctly handle relative paths when fetching assets on the server ([#12113](https://github.com/sveltejs/kit/pull/12113)) - -- Updated dependencies [[`df48fc6ede3859beabaae9fd7c6f722215bb8a42`](https://github.com/sveltejs/kit/commit/df48fc6ede3859beabaae9fd7c6f722215bb8a42), [`5780deba8e3ebd0e2b0abea029068ad0c6daf6ad`](https://github.com/sveltejs/kit/commit/5780deba8e3ebd0e2b0abea029068ad0c6daf6ad), [`6f9aefdb8699fc126d76a88471602cb9a80822eb`](https://github.com/sveltejs/kit/commit/6f9aefdb8699fc126d76a88471602cb9a80822eb), [`8aa95b4b3431e79f62f580abdcdcb157b4de86cd`](https://github.com/sveltejs/kit/commit/8aa95b4b3431e79f62f580abdcdcb157b4de86cd)]: - - @sveltejs/kit@2.7.0 - -## 2.5.4 -### Patch Changes - - -- chore: configure provenance in a simpler manner ([#12570](https://github.com/sveltejs/kit/pull/12570)) - -- Updated dependencies [[`087a43d391fc38b8c008fb39a804dc6988974101`](https://github.com/sveltejs/kit/commit/087a43d391fc38b8c008fb39a804dc6988974101)]: - - @sveltejs/kit@2.5.22 - -## 2.5.3 -### Patch Changes - - -- chore: package provenance ([#12567](https://github.com/sveltejs/kit/pull/12567)) - -- Updated dependencies [[`4930a8443caa53bcecee7b690cd28e429b1c8a20`](https://github.com/sveltejs/kit/commit/4930a8443caa53bcecee7b690cd28e429b1c8a20)]: - - @sveltejs/kit@2.5.21 - -## 2.5.2 -### Patch Changes - - -- fix: correctly return static assets if base path is set ([#12075](https://github.com/sveltejs/kit/pull/12075)) - -## 2.5.1 -### Patch Changes - - -- fix: copy `.eot`, `.otf`, `.ttf`, `.woff`, and `woff2` font files when bundling ([#12439](https://github.com/sveltejs/kit/pull/12439)) - -## 2.5.0 -### Minor Changes - - -- chore(deps): upgrade to esbuild 0.21 ([#12415](https://github.com/sveltejs/kit/pull/12415)) - - -### Patch Changes - -- Updated dependencies [[`84298477a014ec471839adf7a4448d91bc7949e4`](https://github.com/sveltejs/kit/commit/84298477a014ec471839adf7a4448d91bc7949e4), [`5645614f497931f587b7cb8b3c885fce892a6a72`](https://github.com/sveltejs/kit/commit/5645614f497931f587b7cb8b3c885fce892a6a72), [`84298477a014ec471839adf7a4448d91bc7949e4`](https://github.com/sveltejs/kit/commit/84298477a014ec471839adf7a4448d91bc7949e4)]: - - @sveltejs/kit@2.5.18 - -## 2.4.1 - -### Patch Changes - -- chore: add keywords for discovery in npm search ([#12330](https://github.com/sveltejs/kit/pull/12330)) - -- Updated dependencies [[`25acb1d9fce998dccd8050b93cf4142c2b082611`](https://github.com/sveltejs/kit/commit/25acb1d9fce998dccd8050b93cf4142c2b082611), [`642c4a4aff4351b786fe6274aa2f0bf7d905faf9`](https://github.com/sveltejs/kit/commit/642c4a4aff4351b786fe6274aa2f0bf7d905faf9), [`0a0e9aa897123ebec50af08e9385b2ca4fc5bb28`](https://github.com/sveltejs/kit/commit/0a0e9aa897123ebec50af08e9385b2ca4fc5bb28)]: - - @sveltejs/kit@2.5.11 - -## 2.4.0 - -### Minor Changes - -- chore(deps): upgrade esbuild ([#12118](https://github.com/sveltejs/kit/pull/12118)) - -### Patch Changes - -- Updated dependencies [[`bbab296f6fcc05af6b999182798bcdedabbaa4c9`](https://github.com/sveltejs/kit/commit/bbab296f6fcc05af6b999182798bcdedabbaa4c9)]: - - @sveltejs/kit@2.5.6 - -## 2.3.0 - -### Minor Changes - -- feat: support platform emulation configuration via the `platformProxy` adapter option ([#12011](https://github.com/sveltejs/kit/pull/12011)) - -## 2.2.1 - -### Patch Changes - -- fix: add `workerd` to esbuild conditions ([#12069](https://github.com/sveltejs/kit/pull/12069)) - -## 2.2.0 - -### Minor Changes - -- feat: emulate Cloudflare Workers bindings and incoming request properties in `event.platform` for `dev` and `preview` ([#11974](https://github.com/sveltejs/kit/pull/11974)) - -### Patch Changes - -- Updated dependencies [[`4562275ed42964148df03c79434172024897c08c`](https://github.com/sveltejs/kit/commit/4562275ed42964148df03c79434172024897c08c)]: - - @sveltejs/kit@2.5.4 - -## 2.1.0 - -### Minor Changes - -- feat: more helpful errors when using incompatible Node modules ([#11673](https://github.com/sveltejs/kit/pull/11673)) - -- feat: support compatible node modules without prefixes ([#11672](https://github.com/sveltejs/kit/pull/11672)) - -- feat: Add Node.js compatibility ([#10544](https://github.com/sveltejs/kit/pull/10544)) - -### Patch Changes - -- Updated dependencies [[`288f731c8a5b20cadb9e219f9583f3f16bf8c7b8`](https://github.com/sveltejs/kit/commit/288f731c8a5b20cadb9e219f9583f3f16bf8c7b8)]: - - @sveltejs/kit@2.4.0 - -## 2.0.3 - -### Patch Changes - -- chore: upgrade esbuild to 0.19.11 ([#11632](https://github.com/sveltejs/kit/pull/11632)) - -## 2.0.2 - -### Patch Changes - -- fix: serve static files in `_app` from function, if not already handled ([#11593](https://github.com/sveltejs/kit/pull/11593)) - -- Updated dependencies [[`553e14c8320ad9c6ebb3c554c35f1482755c9555`](https://github.com/sveltejs/kit/commit/553e14c8320ad9c6ebb3c554c35f1482755c9555), [`48576de0dc8b1fbbab7954113004540ea4e76935`](https://github.com/sveltejs/kit/commit/48576de0dc8b1fbbab7954113004540ea4e76935)]: - - @sveltejs/kit@2.3.2 - -## 2.0.1 - -### Patch Changes - -- chore: update primary branch from master to main ([`47779436c5f6c4d50011d0ef8b2709a07c0fec5d`](https://github.com/sveltejs/kit/commit/47779436c5f6c4d50011d0ef8b2709a07c0fec5d)) - -- Updated dependencies [[`47779436c5f6c4d50011d0ef8b2709a07c0fec5d`](https://github.com/sveltejs/kit/commit/47779436c5f6c4d50011d0ef8b2709a07c0fec5d), [`16961e8cd3fa6a7f382153b1ff056bc2aae9b31b`](https://github.com/sveltejs/kit/commit/16961e8cd3fa6a7f382153b1ff056bc2aae9b31b), [`197e01f95652f511160f38b37b9da73a124ecd48`](https://github.com/sveltejs/kit/commit/197e01f95652f511160f38b37b9da73a124ecd48), [`102e4a5ae5b29624302163faf5a20c94a64a5b2c`](https://github.com/sveltejs/kit/commit/102e4a5ae5b29624302163faf5a20c94a64a5b2c), [`f8e3d8b9728c9f1ab63389342c31d7246b6f9db6`](https://github.com/sveltejs/kit/commit/f8e3d8b9728c9f1ab63389342c31d7246b6f9db6)]: - - @sveltejs/kit@2.0.4 - -## 2.0.0 - -### Major Changes - -- breaking: require SvelteKit 2 ([#11316](https://github.com/sveltejs/kit/pull/11316)) - -- chore: upgrade esbuild ([#11122](https://github.com/sveltejs/kit/pull/11122)) - -### Patch Changes - -- fix: declare the adapter plugin options as optional ([#11246](https://github.com/sveltejs/kit/pull/11246)) - -## 1.2.3 - -### Patch Changes - -- fix: correctly map prerendered pages when base path is set ([#11245](https://github.com/sveltejs/kit/pull/11245)) - -- Updated dependencies [[`bd383f576`](https://github.com/sveltejs/kit/commit/bd383f576592948a2a96b357118cdc7598a8b61c), [`b6a0be712`](https://github.com/sveltejs/kit/commit/b6a0be712644bca4bbd7bec194c1bff682e39d71), [`ded16305b`](https://github.com/sveltejs/kit/commit/ded16305b4c180a697c457ca1b2bec249b4b38fb), [`15422d21d`](https://github.com/sveltejs/kit/commit/15422d21d08a1484f92490da5dd4b77ca7332c23)]: - - @sveltejs/kit@1.28.0 - -## 1.2.2 - -### Patch Changes - -- fix: retain URL query string for trailing slash redirects to prerendered pages ([#11142](https://github.com/sveltejs/kit/pull/11142)) - -- Updated dependencies [[`a7f8bdcfa`](https://github.com/sveltejs/kit/commit/a7f8bdcfabce5cda85dd073a21d0afb6138a7a08), [`a4d91304e`](https://github.com/sveltejs/kit/commit/a4d91304eebc08bf2e748d83a46d3548a546e3ab)]: - - @sveltejs/kit@1.27.7 - -## 1.2.1 - -### Patch Changes - -- fix: correctly check url pathnames for trailing slashes ([#10968](https://github.com/sveltejs/kit/pull/10968)) - -## 1.2.0 - -### Minor Changes - -- feat: add cloudflare's `request.cf` object to the `event.platform` property ([#10873](https://github.com/sveltejs/kit/pull/10873)) - -## 1.1.4 - -### Patch Changes - -- fix: mark `cloudflare:` packages as external ([#10404](https://github.com/sveltejs/kit/pull/10404)) - -- Updated dependencies [[`0f0049810`](https://github.com/sveltejs/kit/commit/0f00498100361ef0a4ea8b0b4e8465e442fa22a6), [`6f36aefe1`](https://github.com/sveltejs/kit/commit/6f36aefe13bf55cfaef14166c60ecee989061ddd)]: - - @sveltejs/kit@1.22.4 - -## 1.1.3 - -### Patch Changes - -- chore: upgrade to esbuild 0.18.11 ([#10330](https://github.com/sveltejs/kit/pull/10330)) - -- Updated dependencies [[`23d1df702`](https://github.com/sveltejs/kit/commit/23d1df702f0fd77983040404352d8d83fd1dd8a1), [`486a971fe`](https://github.com/sveltejs/kit/commit/486a971fe7c375aae1585f1fa2505e28f86f4b8e)]: - - @sveltejs/kit@1.22.2 - -## 1.1.2 - -### Patch Changes - -- fix: Copy .wasm files during build ([#9940](https://github.com/sveltejs/kit/pull/9940)) - -- Updated dependencies [[`50acb22ca`](https://github.com/sveltejs/kit/commit/50acb22caf2901283e044cdfda36db6f07b3e0ae), [`2e6da9496`](https://github.com/sveltejs/kit/commit/2e6da9496bdace2c65040b9d1845c44801ca868c), [`a81106b3a`](https://github.com/sveltejs/kit/commit/a81106b3a817829c41e048207d6253e63988c58c), [`a6338a0b1`](https://github.com/sveltejs/kit/commit/a6338a0b124f54bda7ba3fe64be1d6173e118d00), [`4a85b7f08`](https://github.com/sveltejs/kit/commit/4a85b7f0820d35c7830c00afe1df3c94fcbf8c3d), [`26d2b7f8f`](https://github.com/sveltejs/kit/commit/26d2b7f8f5ca29c60ef61b936ff86deaeb1636ce), [`bc70b4e63`](https://github.com/sveltejs/kit/commit/bc70b4e636fcbd9593356996bf737e014ff8c238), [`ab9f57721`](https://github.com/sveltejs/kit/commit/ab9f57721fca146af7c4eb41f4875fafa5dfc0d2)]: - - @sveltejs/kit@1.17.0 - -## 1.1.1 - -### Patch Changes - -- chore: update all dependencies with minor version bumps ([#9761](https://github.com/sveltejs/kit/pull/9761)) - -## 1.1.0 - -### Minor Changes - -- feat: use `es2022` target ([#9293](https://github.com/sveltejs/kit/pull/9293)) - -### Patch Changes - -- Updated dependencies [[`2b647fd8`](https://github.com/sveltejs/kit/commit/2b647fd85be028bc5775894567ee8b13f91411a7), [`fbe4fe76`](https://github.com/sveltejs/kit/commit/fbe4fe768140abac09bd66edd12c77787cafc2c5), [`744dc81c`](https://github.com/sveltejs/kit/commit/744dc81c6b0d8cade087df733c6d3d3f1281e68c)]: - - @sveltejs/kit@1.10.0 - -## 1.0.6 - -### Patch Changes - -- feat: expose `App.Platform` interface automatically ([#8531](https://github.com/sveltejs/kit/pull/8531)) - -- docs: move adapter docs to site ([#8531](https://github.com/sveltejs/kit/pull/8531)) - -- fix: amend `App.Platform` ([#8531](https://github.com/sveltejs/kit/pull/8531)) - -## 1.0.5 - -### Patch Changes - -- fix: publish missing files ([#8532](https://github.com/sveltejs/kit/pull/8532)) - -## 1.0.4 - -### Patch Changes - -- chore: remove superfluous main field from package.json ([#8519](https://github.com/sveltejs/kit/pull/8519)) - -- Updated dependencies [[`7e2d3405`](https://github.com/sveltejs/kit/commit/7e2d34056e99f371e22406d941b764df365a2649)]: - - @sveltejs/kit@1.1.1 - -## 1.0.3 - -### Patch Changes - -- fix: don't load ambient worker types ([#8483](https://github.com/sveltejs/kit/pull/8483)) - -## 1.0.2 - -### Patch Changes - -- docs: add note about inability to access file system at runtime ([#8441](https://github.com/sveltejs/kit/pull/8441)) - -- Updated dependencies [[`9c01c32e`](https://github.com/sveltejs/kit/commit/9c01c32ef72bbed630fadcb8283f8f8533ced5e1), [`b6ca02a6`](https://github.com/sveltejs/kit/commit/b6ca02a684dbf13a3138b552e2d2be64697f2254), [`130abe43`](https://github.com/sveltejs/kit/commit/130abe43cef2cfbaf922aa16b20cbd4332a07c15), [`c4137536`](https://github.com/sveltejs/kit/commit/c4137536f2c6572eaeec1a82ccea0852f5be6b98), [`40464efa`](https://github.com/sveltejs/kit/commit/40464efab172a17f0b637d7dadea30d77ef1ed10), [`ce028470`](https://github.com/sveltejs/kit/commit/ce0284708184198efdd30f3ff72fd579cef830b4)]: - - @sveltejs/kit@1.0.12 - -## 1.0.1 - -### Patch Changes - -- chore: update @cloudflare/kv-asset-handler ([`30e1130e`](https://github.com/sveltejs/kit/commit/30e1130ef84e56a77be5cb1136d5c53edef6e5f9)) -- Updated dependencies [[`fab0de4f`](https://github.com/sveltejs/kit/commit/fab0de4f06ac5b1e9b049e106889b193975c1c29), [`89b8d94b`](https://github.com/sveltejs/kit/commit/89b8d94b1b20d586e1ca525c30d07587c3f2d8f2)]: - - @sveltejs/kit@1.0.2 - -## 1.0.0 - -### Major Changes - -First major release, see below for the history of changes that lead up to this. -Starting from now all releases follow semver and changes will be listed as Major/Minor/Patch - -## 1.0.0-next.65 - -### Patch Changes - -- breaking: remove warnings/errors about removed/changed APIs ([#8019](https://github.com/sveltejs/kit/pull/8019)) -- Updated dependencies [[`f42604a2`](https://github.com/sveltejs/kit/commit/f42604a2b4c04026d3d8bad95807720b79529539)]: - - @sveltejs/kit@1.0.0-next.589 - -## 1.0.0-next.64 - -### Patch Changes - -- chore: add peerDependencies, add more specific next version ([#8141](https://github.com/sveltejs/kit/pull/8141)) - -## 1.0.0-next.63 - -### Patch Changes - -- fix: revert platform change from browser to neutral ([#8122](https://github.com/sveltejs/kit/pull/8122)) - -## 1.0.0-next.62 - -### Patch Changes - -- fix: set esbuild platform to neutral ([#8083](https://github.com/sveltejs/kit/pull/8083)) - -## 1.0.0-next.61 - -### Patch Changes - -- update esbuild to ^0.16.3 ([#7543](https://github.com/sveltejs/kit/pull/7543)) - -## 1.0.0-next.60 - -### Patch Changes - -- update dependencies ([#7355](https://github.com/sveltejs/kit/pull/7355)) - -## 1.0.0-next.59 - -### Patch Changes - -- Use config.kit.paths.base prefix for static assets ([#4448](https://github.com/sveltejs/kit/pull/4448)) - -## 1.0.0-next.58 - -### Patch Changes - -- Add config option to set custom `wrangler.toml` file name ([#7104](https://github.com/sveltejs/kit/pull/7104)) - -## 1.0.0-next.57 - -### Patch Changes - -- Include ambient.d.ts files in adapter packages. ([#6917](https://github.com/sveltejs/kit/pull/6917)) - -## 1.0.0-next.56 - -### Patch Changes - -- chore: bump esbuild ([#6829](https://github.com/sveltejs/kit/pull/6829)) - -## 1.0.0-next.55 - -### Patch Changes - -- Update to esbuild 0.15 ([#6740](https://github.com/sveltejs/kit/pull/6740)) - -## 1.0.0-next.54 - -### Patch Changes - -- feat: Moved hooks.js initialization from Server.respond into Server.init ([#6179](https://github.com/sveltejs/kit/pull/6179)) - -## 1.0.0-next.53 - -### Patch Changes - -- expose caches on platform ([#5887](https://github.com/sveltejs/kit/pull/5887)) - -## 1.0.0-next.52 - -### Patch Changes - -- Initialise `env` ([#5663](https://github.com/sveltejs/kit/pull/5663)) - -## 1.0.0-next.51 - -### Patch Changes - -- breaking: remove writeStatic to align with Vite ([#5618](https://github.com/sveltejs/kit/pull/5618)) - -## 1.0.0-next.50 - -### Patch Changes - -- Update dependencies ([#5005](https://github.com/sveltejs/kit/pull/5005)) - -## 1.0.0-next.49 - -### Patch Changes - -- breaking: Don't pass arbitrary options to esbuild ([#4639](https://github.com/sveltejs/kit/pull/4639)) - -## 1.0.0-next.48 - -### Patch Changes - -- Expose App interfaces ([#5386](https://github.com/sveltejs/kit/pull/5386)) - -## 1.0.0-next.47 - -### Patch Changes - -- chore: upgrade TypeScript to 4.7.4 ([#5414](https://github.com/sveltejs/kit/pull/5414)) - -## 1.0.0-next.46 - -### Patch Changes - -- Generate sourcemaps for server-side functions when bundling with esbuild ([#5258](https://github.com/sveltejs/kit/pull/5258)) - -## 1.0.0-next.45 - -### Patch Changes - -- Simplify example wrangler.toml, and fix outdated README ([#5187](https://github.com/sveltejs/kit/pull/5187)) - -## 1.0.0-next.44 - -### Patch Changes - -- Update dependencies ([#5121](https://github.com/sveltejs/kit/pull/5121)) - -## 1.0.0-next.43 - -### Patch Changes - -- Update adapter entrypoint typings to be NodeNext/ESNext-compatible ([#5111](https://github.com/sveltejs/kit/pull/5111)) - -## 1.0.0-next.42 - -### Patch Changes - -- only serve `_app/immutable` with immutable cache header, not `_app/version.json` ([#5051](https://github.com/sveltejs/kit/pull/5051)) - -## 1.0.0-next.41 - -### Patch Changes - -- Add types to pkg.exports ([#5045](https://github.com/sveltejs/kit/pull/5045)) - -## 1.0.0-next.40 - -### Patch Changes - -- breaking: support Wrangler 2, drop Wrangler 1 ([#4887](https://github.com/sveltejs/kit/pull/4887)) - -## 1.0.0-next.39 - -### Patch Changes - -- breaking: Remove try-catch around server.respond ([#4738](https://github.com/sveltejs/kit/pull/4738)) - -## 1.0.0-next.38 - -### Patch Changes - -- - Fix an issue related to prerendered pages incorrectly resolving in @sveltejs/adapter-cloudflare-workers ([#4626](https://github.com/sveltejs/kit/pull/4626)) - -## 1.0.0-next.37 - -### Patch Changes - -- Breaking: refactor implementation from "Service Worker" pattern to "Module Worker" used in adapter-cloudflare ([#4276](https://github.com/sveltejs/kit/pull/4276)) - - #### add the following to your wrangler.toml - - ```toml - [build.upload] - format = "modules" - main = "./worker.mjs" - ``` - -## 1.0.0-next.36 - -### Patch Changes - -- Provide getClientAddress function ([#4289](https://github.com/sveltejs/kit/pull/4289)) - -## 1.0.0-next.35 - -### Patch Changes - -- breaking: replace builder.prerender() with builder.writePrerendered() and builder.prerendered ([#4192](https://github.com/sveltejs/kit/pull/4192)) ([#4229](https://github.com/sveltejs/kit/pull/4229)) - -## 1.0.0-next.34 - -### Patch Changes - -- breaking: rename `app.render` to `server.respond` ([#4034](https://github.com/sveltejs/kit/pull/4034)) - -## 1.0.0-next.33 - -### Patch Changes - -- revert change to Cloudflare ES target version ([#3847](https://github.com/sveltejs/kit/pull/3847)) - -## 1.0.0-next.32 - -### Patch Changes - -- Fix Cloudflare adapter targets ([#3827](https://github.com/sveltejs/kit/pull/3827)) - -## 1.0.0-next.31 - -### Patch Changes - -- update to Vite 2.8 and esbuild 0.14 ([#3791](https://github.com/sveltejs/kit/pull/3791)) - -## 1.0.0-next.30 - -### Patch Changes - -- Breaking: change app.render signature to (request: Request) => Promise ([#3384](https://github.com/sveltejs/kit/pull/3384)) - -## 1.0.0-next.29 - -### Patch Changes - -- Add immutable cache headers to generated assets ([#3222](https://github.com/sveltejs/kit/pull/3222)) - -## 1.0.0-next.28 - -### Patch Changes - -- use path/posix to resolve relative paths for esmodules ([#3212](https://github.com/sveltejs/kit/pull/3212)) - -## 1.0.0-next.27 - -### Patch Changes - -- Overhaul adapter API ([#2931](https://github.com/sveltejs/kit/pull/2931)) -- Remove esbuild options ([#2931](https://github.com/sveltejs/kit/pull/2931)) -- Update adapters to provide app.render with a url ([#3133](https://github.com/sveltejs/kit/pull/3133)) - -## 1.0.0-next.26 - -### Patch Changes - -- update to esbuild 0.13.15 and other dependency updates ([#2957](https://github.com/sveltejs/kit/pull/2957)) - -## 1.0.0-next.25 - -### Patch Changes - -- chore: upgrade `@cloudflare/kv-asset-handler` ([#2650](https://github.com/sveltejs/kit/pull/2650)) - -## 1.0.0-next.24 - -### Patch Changes - -- update dependencies ([#2574](https://github.com/sveltejs/kit/pull/2574)) - -## 1.0.0-next.23 - -### Patch Changes - -- update to vite 2.6.0 and esbuild 0.13 ([#2522](https://github.com/sveltejs/kit/pull/2522)) - -## 1.0.0-next.22 - -### Patch Changes - -- chore: add links to repository and homepage to package.json ([#2425](https://github.com/sveltejs/kit/pull/2425)) - -## 1.0.0-next.21 - -### Patch Changes - -- chore: export package.json from adapters ([#2351](https://github.com/sveltejs/kit/pull/2351)) - -## 1.0.0-next.20 - -### Patch Changes - -- Support assigning multiple values to a header ([#2313](https://github.com/sveltejs/kit/pull/2313)) - -## 1.0.0-next.19 - -### Patch Changes - -- Ensure the raw body is an Uint8Array before passing it to request handlers ([#2215](https://github.com/sveltejs/kit/pull/2215)) - -## 1.0.0-next.18 - -### Patch Changes - -- d81de603: revert adapters automatically updating .gitignore ([#1924](https://github.com/sveltejs/kit/pull/1924)) - -## 1.0.0-next.17 - -### Patch Changes - -- e9f78999: fix: include esbuild config in adapter type definition ([#1954](https://github.com/sveltejs/kit/pull/1954)) - -## 1.0.0-next.16 - -### Patch Changes - -- e6995797: feat(adapters): expose esbuild configuration ([#1914](https://github.com/sveltejs/kit/pull/1914)) - -## 1.0.0-next.15 - -### Patch Changes - -- 4720b67: Default body parsing to binary ([#1890](https://github.com/sveltejs/kit/pull/1890)) - -## 1.0.0-next.14 - -### Patch Changes - -- 7faf52f: Update and consolidate checks for binary body types ([#1687](https://github.com/sveltejs/kit/pull/1687)) - -## 1.0.0-next.13 - -### Patch Changes - -- 9f0c54a: Externalize app initialization to adapters ([#1804](https://github.com/sveltejs/kit/pull/1804)) - -## 1.0.0-next.12 - -### Patch Changes - -- c51ab7d: Upgrade esbuild to ^0.12.5 ([#1627](https://github.com/sveltejs/kit/pull/1627)) - -## 1.0.0-next.11 - -### Patch Changes - -- edc307d: Remove peerDependencies due to pnpm bug ([#1621](https://github.com/sveltejs/kit/pull/1621)) -- 2636e68: Attempt to fix peerDependencies specification ([#1620](https://github.com/sveltejs/kit/pull/1620)) - -## 1.0.0-next.10 - -### Patch Changes - -- 028abd9: Pass validated svelte config to adapter adapt function ([#1559](https://github.com/sveltejs/kit/pull/1559)) -- Updated dependencies [6372690] -- Updated dependencies [c3d36a3] -- Updated dependencies [bf77940] -- Updated dependencies [2172469] -- Updated dependencies [028abd9] - - @sveltejs/kit@1.0.0-next.110 - -## 1.0.0-next.9 - -### Patch Changes - -- 71e293d: change toml parser to support dotted keys and other language features added after the TOML v0.4.0 spec ([#1509](https://github.com/sveltejs/kit/pull/1509)) -- dca4946: Make kit a peerDependency of the adapters ([#1505](https://github.com/sveltejs/kit/pull/1505)) -- Updated dependencies [261ee1c] -- Updated dependencies [ec156c6] -- Updated dependencies [586785d] - - @sveltejs/kit@1.0.0-next.109 - -## 1.0.0-next.8 - -### Patch Changes - -- dad93fc: Fix workspace dependencies ([#1434](https://github.com/sveltejs/kit/pull/1434)) - -## 1.0.0-next.7 - -### Patch Changes - -- 11e7840: Ensure rawBody is a string or Uint8Array ([#1382](https://github.com/sveltejs/kit/pull/1382)) - -## 0.0.2-next.6 - -### Patch Changes - -- c6fde99: Convert to ESM ([#1323](https://github.com/sveltejs/kit/pull/1323)) - -## 0.0.2-next.5 - -### Patch Changes - -- 9e67505: Add es2020 target to esbuild function to solve Unexpected character '#' error ([#1287](https://github.com/sveltejs/kit/pull/1287)) - -## 0.0.2-next.4 - -### Patch Changes - -- 2e72a94: Add type declarations ([#1230](https://github.com/sveltejs/kit/pull/1230)) - -## 0.0.2-next.3 - -### Patch Changes - -- b372d61: Generate required package.json ([#1116](https://github.com/sveltejs/kit/pull/1116)) - -## 0.0.2-next.2 - -### Patch Changes - -- 1237eb3: Pass rawBody to SvelteKit, bundle worker with esbuild ([#1109](https://github.com/sveltejs/kit/pull/1109)) - -## 0.0.2-next.1 - -### Patch Changes - -- 4325b39: Aligns request/response API of cloudflare-workers adapter with others ([#946](https://github.com/sveltejs/kit/pull/946)) - -## 0.0.2-next.0 - -### Patch Changes - -- e890031: Fix dev/prod deps (oops) ([#749](https://github.com/sveltejs/kit/pull/749)) diff --git a/packages/adapter-cloudflare-workers/README.md b/packages/adapter-cloudflare-workers/README.md deleted file mode 100644 index a3805020a4aa..000000000000 --- a/packages/adapter-cloudflare-workers/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# adapter-cloudflare-workers - -SvelteKit adapter that creates a Cloudflare Workers site using a function for dynamic server rendering. - -**Requires [Wrangler v2](https://developers.cloudflare.com/workers/wrangler/get-started/).** Wrangler v1 is no longer supported. - -## Docs - -[Docs](https://svelte.dev/docs/kit/adapter-cloudflare-workers) - -## Changelog - -[The Changelog for this package is available on GitHub](https://github.com/sveltejs/kit/blob/main/packages/adapter-cloudflare-workers/CHANGELOG.md). diff --git a/packages/adapter-cloudflare-workers/ambient.d.ts b/packages/adapter-cloudflare-workers/ambient.d.ts deleted file mode 100644 index fbd01afd6557..000000000000 --- a/packages/adapter-cloudflare-workers/ambient.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CacheStorage, IncomingRequestCfProperties } from '@cloudflare/workers-types'; - -declare global { - namespace App { - export interface Platform { - context: { - waitUntil(promise: Promise): void; - }; - caches: CacheStorage; - cf?: IncomingRequestCfProperties; - } - } -} diff --git a/packages/adapter-cloudflare-workers/files/_package.json b/packages/adapter-cloudflare-workers/files/_package.json deleted file mode 100644 index bc4c8d4aabac..000000000000 --- a/packages/adapter-cloudflare-workers/files/_package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "private": true, - "version": "0.0.1", - "description": "Worker site generated by SvelteKit", - "main": "index.js", - "dependencies": { - "@cloudflare/kv-asset-handler": "~0.1.3" - } -} diff --git a/packages/adapter-cloudflare-workers/files/entry.js b/packages/adapter-cloudflare-workers/files/entry.js deleted file mode 100644 index 5f022e5096b9..000000000000 --- a/packages/adapter-cloudflare-workers/files/entry.js +++ /dev/null @@ -1,136 +0,0 @@ -import { Server } from 'SERVER'; -import { manifest, prerendered, base_path } from 'MANIFEST'; -import { getAssetFromKV, mapRequestToAsset } from '@cloudflare/kv-asset-handler'; -import static_asset_manifest_json from '__STATIC_CONTENT_MANIFEST'; -const static_asset_manifest = JSON.parse(static_asset_manifest_json); - -const server = new Server(manifest); - -const app_path = `/${manifest.appPath}`; - -const immutable = `${app_path}/immutable/`; -const version_file = `${app_path}/version.json`; - -export default { - /** - * @param {Request} req - * @param {any} env - * @param {any} context - */ - async fetch(req, env, context) { - await server.init({ env }); - - const url = new URL(req.url); - - // static assets - if (url.pathname.startsWith(app_path)) { - /** @type {Response} */ - const res = await get_asset_from_kv(req, env, context); - if (is_error(res.status)) return res; - - const cache_control = url.pathname.startsWith(immutable) - ? 'public, immutable, max-age=31536000' - : 'no-cache'; - - return new Response(res.body, { - headers: { - // include original headers, minus cache-control which - // is overridden, and etag which is no longer useful - 'cache-control': cache_control, - 'content-type': res.headers.get('content-type'), - 'x-robots-tag': 'noindex' - } - }); - } - - let { pathname, search } = url; - try { - pathname = decodeURIComponent(pathname); - } catch { - // ignore invalid URI - } - - const stripped_pathname = pathname.replace(/\/$/, ''); - - // prerendered pages and /static files - let is_static_asset = false; - const filename = stripped_pathname.slice(base_path.length + 1); - if (filename) { - is_static_asset = - manifest.assets.has(filename) || - manifest.assets.has(filename + '/index.html') || - filename in manifest._.server_assets || - filename + '/index.html' in manifest._.server_assets; - } - - let location = pathname.at(-1) === '/' ? stripped_pathname : pathname + '/'; - - if ( - is_static_asset || - prerendered.has(pathname) || - pathname === version_file || - pathname.startsWith(immutable) - ) { - return get_asset_from_kv(req, env, context, (request, options) => { - if (prerendered.has(pathname)) { - url.pathname = '/' + prerendered.get(pathname).file; - return new Request(url.toString(), request); - } - - return mapRequestToAsset(request, options); - }); - } else if (location && prerendered.has(location)) { - if (search) location += search; - return new Response('', { - status: 308, - headers: { - location - } - }); - } - - // dynamically-generated pages - return await server.respond(req, { - platform: { - env, - context, - // @ts-expect-error lib.dom is interfering with workers-types - caches, - // @ts-expect-error req is actually a Cloudflare request not a standard request - cf: req.cf - }, - getClientAddress() { - return req.headers.get('cf-connecting-ip'); - } - }); - } -}; - -/** - * @param {Request} req - * @param {any} env - * @param {any} context - */ -async function get_asset_from_kv(req, env, context, map = mapRequestToAsset) { - return await getAssetFromKV( - { - request: req, - waitUntil(promise) { - return context.waitUntil(promise); - } - }, - { - ASSET_NAMESPACE: env.__STATIC_CONTENT, - ASSET_MANIFEST: static_asset_manifest, - mapRequestToAsset: map - } - ); -} - -/** - * @param {number} status - * @returns {boolean} - */ -function is_error(status) { - return status > 399; -} diff --git a/packages/adapter-cloudflare-workers/index.d.ts b/packages/adapter-cloudflare-workers/index.d.ts deleted file mode 100644 index 878b48649d5e..000000000000 --- a/packages/adapter-cloudflare-workers/index.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Adapter } from '@sveltejs/kit'; -import './ambient.js'; -import { GetPlatformProxyOptions } from 'wrangler'; - -export default function plugin(options?: AdapterOptions): Adapter; - -export interface AdapterOptions { - /** - * Path to your {@link https://developers.cloudflare.com/workers/wrangler/configuration/ | Wrangler configuration file}. - */ - config?: string; - /** - * Config object passed to {@link https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy | getPlatformProxy} - * during development and preview. - */ - platformProxy?: GetPlatformProxyOptions; -} diff --git a/packages/adapter-cloudflare-workers/index.js b/packages/adapter-cloudflare-workers/index.js deleted file mode 100644 index 5d13539cd915..000000000000 --- a/packages/adapter-cloudflare-workers/index.js +++ /dev/null @@ -1,223 +0,0 @@ -import { execSync } from 'node:child_process'; -import { writeFileSync } from 'node:fs'; -import { posix, dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import esbuild from 'esbuild'; -import { getPlatformProxy, unstable_readConfig } from 'wrangler'; - -// list from https://developers.cloudflare.com/workers/runtime-apis/nodejs/ -const compatible_node_modules = [ - 'assert', - 'async_hooks', - 'buffer', - 'crypto', - 'diagnostics_channel', - 'events', - 'path', - 'process', - 'stream', - 'string_decoder', - 'util' -]; - -/** @type {import('./index.js').default} */ -export default function ({ config, platformProxy = {} } = {}) { - return { - name: '@sveltejs/adapter-cloudflare-workers', - - async adapt(builder) { - const { main, site, compatibility_flags } = validate_config(builder, config); - - const files = fileURLToPath(new URL('./files', import.meta.url).href); - const tmp = builder.getBuildDirectory('cloudflare-workers-tmp'); - - builder.rimraf(site.bucket); - builder.rimraf(dirname(main)); - - builder.log.info('Installing worker dependencies...'); - builder.copy(`${files}/_package.json`, `${tmp}/package.json`); - - // TODO would be cool if we could make this step unnecessary somehow - const stdout = execSync('npm install', { cwd: tmp }); - builder.log.info(stdout.toString()); - - builder.log.minor('Generating worker...'); - const relativePath = posix.relative(tmp, builder.getServerDirectory()); - - builder.copy(`${files}/entry.js`, `${tmp}/entry.js`, { - replace: { - SERVER: `${relativePath}/index.js`, - MANIFEST: './manifest.js' - } - }); - - let prerendered_entries = Array.from(builder.prerendered.pages.entries()); - - if (builder.config.kit.paths.base) { - prerendered_entries = prerendered_entries.map(([path, { file }]) => [ - path, - { file: `${builder.config.kit.paths.base}/${file}` } - ]); - } - - writeFileSync( - `${tmp}/manifest.js`, - `export const manifest = ${builder.generateManifest({ relativePath })};\n\n` + - `export const prerendered = new Map(${JSON.stringify(prerendered_entries)});\n\n` + - `export const base_path = ${JSON.stringify(builder.config.kit.paths.base)};\n` - ); - - const external = ['__STATIC_CONTENT_MANIFEST', 'cloudflare:*']; - if (compatibility_flags && compatibility_flags.includes('nodejs_compat')) { - external.push(...compatible_node_modules.map((id) => `node:${id}`)); - } - - try { - const result = await esbuild.build({ - platform: 'browser', - // https://github.com/cloudflare/workers-sdk/blob/a12b2786ce745f24475174bcec994ad691e65b0f/packages/wrangler/src/deployment-bundle/bundle.ts#L35-L36 - conditions: ['workerd', 'worker', 'browser'], - sourcemap: 'linked', - target: 'es2022', - entryPoints: [`${tmp}/entry.js`], - outfile: main, - bundle: true, - external, - alias: Object.fromEntries(compatible_node_modules.map((id) => [id, `node:${id}`])), - format: 'esm', - loader: { - '.wasm': 'copy', - '.woff': 'copy', - '.woff2': 'copy', - '.ttf': 'copy', - '.eot': 'copy', - '.otf': 'copy' - }, - logLevel: 'silent' - }); - - if (result.warnings.length > 0) { - const formatted = await esbuild.formatMessages(result.warnings, { - kind: 'warning', - color: true - }); - - console.error(formatted.join('\n')); - } - } catch (error) { - for (const e of error.errors) { - for (const node of e.notes) { - const match = - /The package "(.+)" wasn't found on the file system but is built into node/.exec( - node.text - ); - - if (match) { - node.text = `Cannot use "${match[1]}" when deploying to Cloudflare.`; - } - } - } - - const formatted = await esbuild.formatMessages(error.errors, { - kind: 'error', - color: true - }); - - console.error(formatted.join('\n')); - - throw new Error( - `Bundling with esbuild failed with ${error.errors.length} ${ - error.errors.length === 1 ? 'error' : 'errors' - }` - ); - } - - builder.log.minor('Copying assets...'); - const bucket_dir = `${site.bucket}${builder.config.kit.paths.base}`; - builder.writeClient(bucket_dir); - builder.writePrerendered(bucket_dir); - }, - - emulate() { - // 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(platformProxy); - const platform = /** @type {App.Platform} */ ({ - env: proxy.env, - context: proxy.ctx, - caches: proxy.caches, - cf: proxy.cf - }); - /** @type {Record} */ - const env = {}; - const prerender_platform = /** @type {App.Platform} */ (/** @type {unknown} */ ({ env })); - for (const key in proxy.env) { - Object.defineProperty(env, key, { - get: () => { - throw new Error(`Cannot access platform.env.${key} in a prerenderable route`); - } - }); - } - return { platform, prerender_platform }; - }; - - /** @type {{ platform: App.Platform, prerender_platform: App.Platform }} */ - let emulated; - - return { - platform: async ({ prerender }) => { - emulated ??= await get_emulated(); - return prerender ? emulated.prerender_platform : emulated.platform; - } - }; - } - }; -} - -/** - * @param {import('@sveltejs/kit').Builder} builder - * @param {string} config_file - * @returns {import('wrangler').Unstable_Config} - */ -function validate_config(builder, config_file = undefined) { - const wrangler_config = unstable_readConfig({ config: config_file }); - - if (!wrangler_config.configPath) { - builder.log.error( - 'Consult https://developers.cloudflare.com/workers/platform/sites/configuration on how to setup your site' - ); - builder.log( - ` -Sample wrangler.jsonc: -{ - "name": "", - "account_id": "", - "main": "./.cloudflare/worker.js", - "site": { - "bucket": "./.cloudflare/public" - }, - "build": { - "command": "npm run build" - }, - "compatibility_date": "2021-11-12" -} - `.trim() - ); - throw new Error('Missing a Wrangler configuration file'); - } - - if (!wrangler_config.site?.bucket) { - throw new Error( - `You must specify the \`site.bucket\` key in ${wrangler_config.configPath}. Consult https://developers.cloudflare.com/workers/platform/sites/configuration` - ); - } - - if (!wrangler_config.main) { - throw new Error( - `You must specify the \`main\` key in ${wrangler_config.configPath}. Consult https://developers.cloudflare.com/workers/platform/sites/configuration` - ); - } - - return wrangler_config; -} diff --git a/packages/adapter-cloudflare-workers/internal.d.ts b/packages/adapter-cloudflare-workers/internal.d.ts deleted file mode 100644 index 3877ad52f4a5..000000000000 --- a/packages/adapter-cloudflare-workers/internal.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -declare module 'SERVER' { - export { Server } from '@sveltejs/kit'; -} - -declare module 'MANIFEST' { - import { SSRManifest } from '@sveltejs/kit'; - - export const manifest: SSRManifest; - export const prerendered: Map; - export const base_path: string; -} - -declare module '__STATIC_CONTENT_MANIFEST' { - const json: string; - export default json; -} diff --git a/packages/adapter-cloudflare-workers/package.json b/packages/adapter-cloudflare-workers/package.json deleted file mode 100644 index 581343d9ed3d..000000000000 --- a/packages/adapter-cloudflare-workers/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "@sveltejs/adapter-cloudflare-workers", - "version": "2.9.0", - "description": "SvelteKit adapter that creates a Cloudflare Workers site using a function for dynamic server rendering", - "keywords": [ - "adapter", - "cloudflare workers", - "deploy", - "hosting", - "svelte", - "sveltekit" - ], - "repository": { - "type": "git", - "url": "https://github.com/sveltejs/kit", - "directory": "packages/adapter-cloudflare-workers" - }, - "license": "MIT", - "homepage": "https://svelte.dev", - "type": "module", - "exports": { - ".": { - "types": "./index.d.ts", - "import": "./index.js" - }, - "./package.json": "./package.json" - }, - "types": "index.d.ts", - "files": [ - "ambient.d.ts", - "files", - "index.js", - "index.d.ts" - ], - "scripts": { - "lint": "prettier --check .", - "format": "pnpm lint --write", - "check": "tsc --skipLibCheck" - }, - "dependencies": { - "@cloudflare/workers-types": "^4.20250312.0", - "esbuild": "^0.24.0" - }, - "devDependencies": { - "@cloudflare/kv-asset-handler": "^0.4.0", - "@sveltejs/kit": "workspace:^", - "@types/node": "^18.19.48", - "typescript": "^5.3.3" - }, - "peerDependencies": { - "@sveltejs/kit": "^2.0.0", - "wrangler": "^3.91.0 || ^4.0.0" - } -} diff --git a/packages/adapter-cloudflare-workers/tsconfig.json b/packages/adapter-cloudflare-workers/tsconfig.json deleted file mode 100644 index e4cdc5abd1b7..000000000000 --- a/packages/adapter-cloudflare-workers/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "noEmit": true, - "noImplicitAny": true, - "target": "es2022", - "module": "node16", - "moduleResolution": "node16", - "allowSyntheticDefaultImports": true, - "baseUrl": ".", - "paths": { - "@sveltejs/kit": ["../kit/types/index"] - } - }, - "include": ["**/*.js", "internal.d.ts"] -} diff --git a/packages/adapter-cloudflare/README.md b/packages/adapter-cloudflare/README.md index fa00adbf1c94..fb8ce1266e61 100644 --- a/packages/adapter-cloudflare/README.md +++ b/packages/adapter-cloudflare/README.md @@ -1,6 +1,6 @@ # adapter-cloudflare -[Adapter](https://svelte.dev/docs/kit/building-your-app) for building SvelteKit applications on [Cloudflare Pages](https://developers.cloudflare.com/pages/) with [Workers integration](https://developers.cloudflare.com/pages/platform/functions). +[Adapter](https://svelte.dev/docs/kit/building-your-app) for building SvelteKit applications on [Cloudflare Workers](https://developers.cloudflare.com/workers/) with [static assets](https://developers.cloudflare.com/workers/static-assets/) or [Cloudflare Pages](https://developers.cloudflare.com/pages/) with [Workers integration](https://developers.cloudflare.com/pages/functions/). ## Docs diff --git a/packages/adapter-cloudflare/ambient.d.ts b/packages/adapter-cloudflare/ambient.d.ts index fbd01afd6557..9bee6700f8ac 100644 --- a/packages/adapter-cloudflare/ambient.d.ts +++ b/packages/adapter-cloudflare/ambient.d.ts @@ -1,11 +1,14 @@ -import { CacheStorage, IncomingRequestCfProperties } from '@cloudflare/workers-types'; +import { + CacheStorage, + IncomingRequestCfProperties, + ExecutionContext +} from '@cloudflare/workers-types'; declare global { namespace App { export interface Platform { - context: { - waitUntil(promise: Promise): void; - }; + env: unknown; + context: ExecutionContext; caches: CacheStorage; cf?: IncomingRequestCfProperties; } diff --git a/packages/adapter-cloudflare/index.d.ts b/packages/adapter-cloudflare/index.d.ts index a1cacb498e24..0c02fb786cee 100644 --- a/packages/adapter-cloudflare/index.d.ts +++ b/packages/adapter-cloudflare/index.d.ts @@ -6,20 +6,36 @@ export default function plugin(options?: AdapterOptions): Adapter; export interface AdapterOptions { /** - * Whether to render a plaintext 404.html page, or a rendered SPA fallback page. This page will - * only be served when a request that matches an entry in `routes.exclude` fails to match an asset. + * Path to your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). + */ + config?: string; + /** + * Whether to render a plaintext 404.html page or a rendered SPA fallback page + * for non-matching asset requests. + * + * For Cloudflare Workers, the default behaviour is to return a null-body + * 404-status response for non-matching assets requests. However, if the + * [`assets.not_found_handling`](https://developers.cloudflare.com/workers/static-assets/routing/#2-not_found_handling) + * Wrangler configuration setting is set to `"404-page"`, this page will be + * served if a request fails to match an asset. If `assets.not_found_handling` + * is set to `"single-page-application"`, the adapter will render a SPA fallback + * index.html page regardless of the `fallback` option specified. + * + * For Cloudflare Pages, this page will only be served when a request that + * matches an entry in `routes.exclude` fails to match an asset. * * Most of the time `plaintext` is sufficient, but if you are using `routes.exclude` to manually * exclude a set of prerendered pages without exceeding the 100 route limit, you may wish to * use `spa` instead to avoid showing an unstyled 404 page to users. * + * See [Cloudflare Pages' Not Found behavior](https://developers.cloudflare.com/pages/configuration/serving-pages/#not-found-behavior) for more info. + * * @default 'plaintext' */ fallback?: 'plaintext' | 'spa'; /** - * Customize the automatically-generated `_routes.json` file. - * https://developers.cloudflare.com/pages/platform/functions/routing/#create-a-_routesjson-file + * Only for Cloudflare Pages. Customize the automatically-generated [`_routes.json`](https://developers.cloudflare.com/pages/platform/functions/routing/#create-a-_routesjson-file) file. */ routes?: { /** @@ -45,7 +61,7 @@ export interface AdapterOptions { }; /** - * Config object passed to {@link https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy | getPlatformProxy} + * Config object passed to [`getPlatformProxy`](https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy) * during development and preview. */ platformProxy?: GetPlatformProxyOptions; diff --git a/packages/adapter-cloudflare/index.js b/packages/adapter-cloudflare/index.js index 085aa8b26c80..39260432c9d8 100644 --- a/packages/adapter-cloudflare/index.js +++ b/packages/adapter-cloudflare/index.js @@ -1,7 +1,8 @@ import { copyFileSync, existsSync, writeFileSync } from 'node:fs'; -import * as path from 'node:path'; +import path from 'node:path'; +import process from 'node:process'; import { fileURLToPath } from 'node:url'; -import { getPlatformProxy } from 'wrangler'; +import { getPlatformProxy, unstable_readConfig } from 'wrangler'; /** @type {import('./index.js').default} */ export default function (options = {}) { @@ -10,7 +11,7 @@ export default function (options = {}) { async adapt(builder) { if (existsSync('_routes.json')) { throw new Error( - "Cloudflare's _routes.json should be configured in svelte.config.js. See https://svelte.dev/docs/kit/adapter-cloudflare#Options-routes" + "Cloudflare Pages' _routes.json should be configured in svelte.config.js. See https://svelte.dev/docs/kit/adapter-cloudflare#Options-routes" ); } @@ -26,56 +27,87 @@ export default function (options = {}) { ); } + const wrangler_config = validate_config(options.config); + const building_for_cloudflare_pages = is_building_for_cloudflare_pages(wrangler_config); + + let dest = builder.getBuildDirectory('cloudflare'); + let worker_dest = `${dest}/_worker.js`; + let assets_binding = 'ASSETS'; + + if (building_for_cloudflare_pages) { + if (wrangler_config.pages_build_output_dir) { + dest = wrangler_config.pages_build_output_dir; + } + } else { + if (wrangler_config.main) { + worker_dest = wrangler_config.main; + } + if (wrangler_config.assets?.directory) { + dest = wrangler_config.assets.directory; + } + if (wrangler_config.assets?.binding) { + assets_binding = wrangler_config.assets.binding; + } + } + const files = fileURLToPath(new URL('./files', import.meta.url).href); - const dest = builder.getBuildDirectory('cloudflare'); const tmp = builder.getBuildDirectory('cloudflare-tmp'); builder.rimraf(dest); + builder.rimraf(worker_dest); builder.mkdirp(dest); builder.mkdirp(tmp); - // generate plaintext 404.html first which can then be overridden by prerendering, if the user defined such a page - const fallback = path.join(dest, '404.html'); - if (options.fallback === 'spa') { - await builder.generateFallback(fallback); - } else { - writeFileSync(fallback, 'Not Found'); + // client assets and prerendered pages + const assets_dest = `${dest}${builder.config.kit.paths.base}`; + if ( + building_for_cloudflare_pages || + wrangler_config.assets?.not_found_handling === '404-page' + ) { + // generate plaintext 404.html first which can then be overridden by prerendering, if the user defined such a page + const fallback = path.join(assets_dest, '404.html'); + if (options.fallback === 'spa') { + await builder.generateFallback(fallback); + } else { + writeFileSync(fallback, 'Not Found'); + } + } + const client_assets = builder.writeClient(assets_dest); + builder.writePrerendered(assets_dest); + if ( + !building_for_cloudflare_pages && + wrangler_config.assets?.not_found_handling === 'single-page-application' + ) { + await builder.generateFallback(path.join(assets_dest, 'index.html')); } - const dest_dir = `${dest}${builder.config.kit.paths.base}`; - const written_files = builder.writeClient(dest_dir); - builder.writePrerendered(dest_dir); - - const relativePath = path.posix.relative(dest, builder.getServerDirectory()); + // worker + const worker_dest_dir = path.dirname(worker_dest); writeFileSync( `${tmp}/manifest.js`, - `export const manifest = ${builder.generateManifest({ relativePath })};\n\n` + + `export const manifest = ${builder.generateManifest({ relativePath: path.posix.relative(tmp, builder.getServerDirectory()) })};\n\n` + `export const prerendered = new Set(${JSON.stringify(builder.prerendered.paths)});\n\n` + `export const base_path = ${JSON.stringify(builder.config.kit.paths.base)};\n` ); - builder.copy(`${files}/worker.js`, `${dest}/_worker.js`, { + builder.copy(`${files}/worker.js`, worker_dest, { replace: { - SERVER: `${relativePath}/index.js`, - MANIFEST: `${path.posix.relative(dest, tmp)}/manifest.js` + SERVER: `${path.posix.relative(worker_dest_dir, builder.getServerDirectory())}/index.js`, + MANIFEST: `${path.posix.relative(worker_dest_dir, tmp)}/manifest.js`, + ASSETS: assets_binding } }); - writeFileSync( - `${dest}/_routes.json`, - JSON.stringify(get_routes_json(builder, written_files, options.routes ?? {}), null, '\t') - ); - + // _headers if (existsSync('_headers')) { copyFileSync('_headers', `${dest}/_headers`); } - writeFileSync(`${dest}/_headers`, generate_headers(builder.getAppPath()), { flag: 'a' }); + // _redirects if (existsSync('_redirects')) { copyFileSync('_redirects', `${dest}/_redirects`); } - if (builder.prerendered.redirects.size > 0) { writeFileSync(`${dest}/_redirects`, generate_redirects(builder.prerendered.redirects), { flag: 'a' @@ -83,6 +115,13 @@ export default function (options = {}) { } writeFileSync(`${dest}/.assetsignore`, generate_assetsignore(), { flag: 'a' }); + + if (building_for_cloudflare_pages) { + writeFileSync( + `${dest}/_routes.json`, + JSON.stringify(get_routes_json(builder, client_assets, options.routes ?? {}), null, '\t') + ); + } }, emulate() { // we want to invoke `getPlatformProxy` only once, but await it only when it is accessed. @@ -169,7 +208,7 @@ function get_routes_json(builder, assets, { include = ['/*'], exclude = ['' const excess = include.length + exclude.length - 100; if (excess > 0) { - const message = `Function includes/excludes exceeds _routes.json limits (see https://developers.cloudflare.com/pages/platform/functions/routing/#limits). Dropping ${excess} exclude rules — this will cause unnecessary function invocations.`; + const message = `Cloudflare Pages Functions' includes/excludes exceeds _routes.json limits (see https://developers.cloudflare.com/pages/platform/functions/routing/#limits). Dropping ${excess} exclude rules — this will cause unnecessary function invocations.`; builder.log.warn(message); exclude.length -= excess; @@ -220,3 +259,53 @@ _headers _redirects `; } + +/** + * @param {string} config_file + * @returns {import('wrangler').Unstable_Config} + */ +function validate_config(config_file = undefined) { + const wrangler_config = unstable_readConfig({ config: config_file }); + + // we don't support workers sites + if (wrangler_config.site) { + throw new Error( + `You must remove all \`site\` keys in ${wrangler_config.configPath}. Consult https://svelte.dev/docs/kit/adapter-cloudflare#Migrating-from-Workers-Sites-to-Workers-Static-Assets` + ); + } + + if (is_building_for_cloudflare_pages(wrangler_config)) { + return wrangler_config; + } + + // probably deploying to Cloudflare Workers + if (wrangler_config.main || wrangler_config.assets) { + if (!wrangler_config.assets?.directory) { + throw new Error( + `You must specify the \`assets.directory\` key in ${wrangler_config.configPath}. Consult https://developers.cloudflare.com/workers/static-assets/binding/#directory` + ); + } + + if (!wrangler_config.assets?.binding) { + throw new Error( + `You must specify the \`assets.binding\` key in ${wrangler_config.configPath}. Consult https://developers.cloudflare.com/workers/static-assets/binding/#binding` + ); + } + } + + return wrangler_config; +} + +/** + * @param {import('wrangler').Unstable_Config} wrangler_config + * @returns {boolean} + */ +function is_building_for_cloudflare_pages(wrangler_config) { + return ( + !!process.env.CF_PAGES || + !wrangler_config.configPath || + !!wrangler_config.pages_build_output_dir || + !wrangler_config.main || + !wrangler_config.assets + ); +} diff --git a/packages/adapter-cloudflare/package.json b/packages/adapter-cloudflare/package.json index 4c787c346e61..2d3aa42a802b 100644 --- a/packages/adapter-cloudflare/package.json +++ b/packages/adapter-cloudflare/package.json @@ -37,13 +37,15 @@ "lint": "prettier --check .", "format": "pnpm lint --write", "check": "tsc --skipLibCheck", - "prepublishOnly": "pnpm build" + "prepublishOnly": "pnpm build", + "test": "pnpm build && pnpm -r --workspace-concurrency 1 --filter=\"./test/**\" test" }, "dependencies": { "@cloudflare/workers-types": "^4.20250312.0", "worktop": "0.8.0-next.18" }, "devDependencies": { + "@playwright/test": "^1.44.1", "@sveltejs/kit": "workspace:^", "@types/node": "^18.19.48", "esbuild": "^0.24.0", @@ -51,6 +53,6 @@ }, "peerDependencies": { "@sveltejs/kit": "^2.0.0", - "wrangler": "^3.87.0 || ^4.0.0" + "wrangler": "^4.0.0" } } diff --git a/packages/adapter-cloudflare/src/worker.js b/packages/adapter-cloudflare/src/worker.js index c3c27a0b041f..a2ea423c1653 100644 --- a/packages/adapter-cloudflare/src/worker.js +++ b/packages/adapter-cloudflare/src/worker.js @@ -9,11 +9,19 @@ const app_path = `/${manifest.appPath}`; const immutable = `${app_path}/immutable/`; const version_file = `${app_path}/version.json`; -/** @type {import('worktop/cfw').Module.Worker<{ ASSETS: import('worktop/cfw.durable').Durable.Object }>} */ -const worker = { +export default { + /** + * @param {Request} req + * @param {{ ASSETS: { fetch: typeof fetch } }} env + * @param {ExecutionContext} context + * @returns {Promise} + */ async fetch(req, env, context) { - // @ts-ignore - await server.init({ env }); + await server.init({ + // @ts-expect-error env contains environment variables and bindings + env + }); + // skip cache if "cache-control: no-cache" in request let pragma = req.headers.get('cache-control') || ''; let res = !pragma.includes('no-cache') && (await Cache.lookup(req)); @@ -28,7 +36,7 @@ const worker = { const stripped_pathname = pathname.replace(/\/$/, ''); - // prerendered pages and /static files + // files in /static, the service worker, and Vite imported server assets let is_static_asset = false; const filename = stripped_pathname.slice(base_path.length + 1); if (filename) { @@ -49,6 +57,7 @@ const worker = { ) { res = await env.ASSETS.fetch(req); } else if (location && prerendered.has(location)) { + // trailing slash redirect for prerendered pages if (search) location += search; res = new Response('', { status: 308, @@ -59,8 +68,14 @@ const worker = { } else { // dynamically-generated pages res = await server.respond(req, { - // @ts-ignore - platform: { env, context, caches, cf: req.cf }, + platform: { + env, + context, + // @ts-expect-error webworker types from worktop are not compatible with Cloudflare Workers types + caches, + // @ts-expect-error the type is correct but ts is confused because platform.cf uses the type from index.ts while req.cf uses the type from index.d.ts + cf: req.cf + }, getClientAddress() { return req.headers.get('cf-connecting-ip'); } @@ -73,5 +88,3 @@ const worker = { return pragma && res.status < 400 ? Cache.save(req, res, context) : res; } }; - -export default worker; diff --git a/packages/adapter-cloudflare-workers/.gitignore b/packages/adapter-cloudflare/test/apps/pages/.gitignore similarity index 50% rename from packages/adapter-cloudflare-workers/.gitignore rename to packages/adapter-cloudflare/test/apps/pages/.gitignore index 9daa8247da45..1bd7b63de4b6 100644 --- a/packages/adapter-cloudflare-workers/.gitignore +++ b/packages/adapter-cloudflare/test/apps/pages/.gitignore @@ -1,2 +1,4 @@ .DS_Store node_modules +/.svelte-kit +/.wrangler \ No newline at end of file diff --git a/packages/adapter-cloudflare/test/apps/pages/package.json b/packages/adapter-cloudflare/test/apps/pages/package.json new file mode 100644 index 000000000000..af7c37ad2003 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/package.json @@ -0,0 +1,21 @@ +{ + "name": "test-cloudflare-pages", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "wrangler pages dev .svelte-kit/cloudflare --port 8787", + "prepare": "svelte-kit sync || echo ''", + "test": "playwright test" + }, + "devDependencies": { + "@sveltejs/kit": "workspace:^", + "@sveltejs/vite-plugin-svelte": "^5.0.1", + "server-side-dep": "file:server-side-dep", + "svelte": "^5.23.1", + "vite": "^6.0.11", + "wrangler": "^4.0.0" + }, + "type": "module" +} diff --git a/packages/adapter-cloudflare/test/apps/pages/playwright.config.js b/packages/adapter-cloudflare/test/apps/pages/playwright.config.js new file mode 100644 index 000000000000..33d36b651014 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/playwright.config.js @@ -0,0 +1 @@ +export { config as default } from '../../utils.js'; diff --git a/packages/adapter-cloudflare/test/apps/pages/server-side-dep/index.d.ts b/packages/adapter-cloudflare/test/apps/pages/server-side-dep/index.d.ts new file mode 100644 index 000000000000..0e1188e04a67 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/server-side-dep/index.d.ts @@ -0,0 +1 @@ +export function sum(a: number, b: number): number; diff --git a/packages/adapter-cloudflare/test/apps/pages/server-side-dep/index.js b/packages/adapter-cloudflare/test/apps/pages/server-side-dep/index.js new file mode 100644 index 000000000000..568b90577d43 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/server-side-dep/index.js @@ -0,0 +1,4 @@ +/** @type {import('./index.js').sum} */ +export function sum(a, b) { + return a + b; +} diff --git a/packages/adapter-cloudflare/test/apps/pages/server-side-dep/package.json b/packages/adapter-cloudflare/test/apps/pages/server-side-dep/package.json new file mode 100644 index 000000000000..5b26c9d1855a --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/server-side-dep/package.json @@ -0,0 +1,11 @@ +{ + "name": "server-side-dep", + "version": "0.0.1", + "type": "module", + "exports": { + ".": { + "default": "./index.js", + "types": "./index.d.ts" + } + } +} diff --git a/packages/adapter-cloudflare/test/apps/pages/src/app.html b/packages/adapter-cloudflare/test/apps/pages/src/app.html new file mode 100644 index 000000000000..d533c5e31716 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/src/app.html @@ -0,0 +1,11 @@ + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/adapter-cloudflare/test/apps/pages/src/routes/+page.server.js b/packages/adapter-cloudflare/test/apps/pages/src/routes/+page.server.js new file mode 100644 index 000000000000..2e1aac593126 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/src/routes/+page.server.js @@ -0,0 +1,7 @@ +import { sum } from 'server-side-dep'; + +export function load() { + return { + sum: sum(1, 2) + }; +} diff --git a/packages/adapter-cloudflare/test/apps/pages/src/routes/+page.svelte b/packages/adapter-cloudflare/test/apps/pages/src/routes/+page.svelte new file mode 100644 index 000000000000..d5e339683387 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/src/routes/+page.svelte @@ -0,0 +1,5 @@ + + +

Sum: {data.sum}

diff --git a/packages/adapter-cloudflare/test/apps/pages/svelte.config.js b/packages/adapter-cloudflare/test/apps/pages/svelte.config.js new file mode 100644 index 000000000000..20cd2b3ff5b8 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/svelte.config.js @@ -0,0 +1,10 @@ +import adapter from '../../../index.js'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: { + adapter: adapter() + } +}; + +export default config; diff --git a/packages/adapter-cloudflare/test/apps/pages/test/test.js b/packages/adapter-cloudflare/test/apps/pages/test/test.js new file mode 100644 index 000000000000..aab7cbca568a --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/test/test.js @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test'; + +test('worker works', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('h1')).toContainText('Sum: 3'); +}); diff --git a/packages/adapter-cloudflare/test/apps/pages/tsconfig.json b/packages/adapter-cloudflare/test/apps/pages/tsconfig.json new file mode 100644 index 000000000000..34380ebc986e --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + }, + "extends": "./.svelte-kit/tsconfig.json" +} diff --git a/packages/adapter-cloudflare/test/apps/pages/vite.config.js b/packages/adapter-cloudflare/test/apps/pages/vite.config.js new file mode 100644 index 000000000000..29ad08debe6a --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/pages/vite.config.js @@ -0,0 +1,11 @@ +import { sveltekit } from '@sveltejs/kit/vite'; + +/** @type {import('vite').UserConfig} */ +const config = { + build: { + minify: false + }, + plugins: [sveltekit()] +}; + +export default config; diff --git a/packages/adapter-cloudflare/test/apps/workers/.gitignore b/packages/adapter-cloudflare/test/apps/workers/.gitignore new file mode 100644 index 000000000000..f9ee23cc8621 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +node_modules +/.svelte-kit +/.wrangler +/dist \ No newline at end of file diff --git a/packages/adapter-cloudflare/test/apps/workers/package.json b/packages/adapter-cloudflare/test/apps/workers/package.json new file mode 100644 index 000000000000..43cf8da6bd9f --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/package.json @@ -0,0 +1,21 @@ +{ + "name": "test-cloudflare-workers", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "wrangler dev dist/index.js", + "prepare": "svelte-kit sync || echo ''", + "test": "playwright test" + }, + "devDependencies": { + "@sveltejs/kit": "workspace:^", + "@sveltejs/vite-plugin-svelte": "^5.0.1", + "server-side-dep": "file:server-side-dep", + "svelte": "^5.23.1", + "vite": "^6.0.11", + "wrangler": "^4.0.0" + }, + "type": "module" +} diff --git a/packages/adapter-cloudflare/test/apps/workers/playwright.config.js b/packages/adapter-cloudflare/test/apps/workers/playwright.config.js new file mode 100644 index 000000000000..33d36b651014 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/playwright.config.js @@ -0,0 +1 @@ +export { config as default } from '../../utils.js'; diff --git a/packages/adapter-cloudflare/test/apps/workers/server-side-dep/index.d.ts b/packages/adapter-cloudflare/test/apps/workers/server-side-dep/index.d.ts new file mode 100644 index 000000000000..0e1188e04a67 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/server-side-dep/index.d.ts @@ -0,0 +1 @@ +export function sum(a: number, b: number): number; diff --git a/packages/adapter-cloudflare/test/apps/workers/server-side-dep/index.js b/packages/adapter-cloudflare/test/apps/workers/server-side-dep/index.js new file mode 100644 index 000000000000..568b90577d43 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/server-side-dep/index.js @@ -0,0 +1,4 @@ +/** @type {import('./index.js').sum} */ +export function sum(a, b) { + return a + b; +} diff --git a/packages/adapter-cloudflare/test/apps/workers/server-side-dep/package.json b/packages/adapter-cloudflare/test/apps/workers/server-side-dep/package.json new file mode 100644 index 000000000000..5b26c9d1855a --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/server-side-dep/package.json @@ -0,0 +1,11 @@ +{ + "name": "server-side-dep", + "version": "0.0.1", + "type": "module", + "exports": { + ".": { + "default": "./index.js", + "types": "./index.d.ts" + } + } +} diff --git a/packages/adapter-cloudflare/test/apps/workers/src/app.html b/packages/adapter-cloudflare/test/apps/workers/src/app.html new file mode 100644 index 000000000000..d533c5e31716 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/src/app.html @@ -0,0 +1,11 @@ + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.server.js b/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.server.js new file mode 100644 index 000000000000..2e1aac593126 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.server.js @@ -0,0 +1,7 @@ +import { sum } from 'server-side-dep'; + +export function load() { + return { + sum: sum(1, 2) + }; +} diff --git a/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.svelte b/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.svelte new file mode 100644 index 000000000000..d5e339683387 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/src/routes/+page.svelte @@ -0,0 +1,5 @@ + + +

Sum: {data.sum}

diff --git a/packages/adapter-cloudflare/test/apps/workers/svelte.config.js b/packages/adapter-cloudflare/test/apps/workers/svelte.config.js new file mode 100644 index 000000000000..20cd2b3ff5b8 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/svelte.config.js @@ -0,0 +1,10 @@ +import adapter from '../../../index.js'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: { + adapter: adapter() + } +}; + +export default config; diff --git a/packages/adapter-cloudflare/test/apps/workers/test/test.js b/packages/adapter-cloudflare/test/apps/workers/test/test.js new file mode 100644 index 000000000000..aab7cbca568a --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/test/test.js @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test'; + +test('worker works', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('h1')).toContainText('Sum: 3'); +}); diff --git a/packages/adapter-cloudflare/test/apps/workers/tsconfig.json b/packages/adapter-cloudflare/test/apps/workers/tsconfig.json new file mode 100644 index 000000000000..34380ebc986e --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + }, + "extends": "./.svelte-kit/tsconfig.json" +} diff --git a/packages/adapter-cloudflare/test/apps/workers/vite.config.js b/packages/adapter-cloudflare/test/apps/workers/vite.config.js new file mode 100644 index 000000000000..29ad08debe6a --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/vite.config.js @@ -0,0 +1,11 @@ +import { sveltekit } from '@sveltejs/kit/vite'; + +/** @type {import('vite').UserConfig} */ +const config = { + build: { + minify: false + }, + plugins: [sveltekit()] +}; + +export default config; diff --git a/packages/adapter-cloudflare/test/apps/workers/wrangler.jsonc b/packages/adapter-cloudflare/test/apps/workers/wrangler.jsonc new file mode 100644 index 000000000000..1f2cb073f7b6 --- /dev/null +++ b/packages/adapter-cloudflare/test/apps/workers/wrangler.jsonc @@ -0,0 +1,7 @@ +{ + "main": "./dist/index.js", + "assets": { + "directory": "./dist/public", + "binding": "ASSETS" + } +} diff --git a/packages/adapter-cloudflare/test/utils.js b/packages/adapter-cloudflare/test/utils.js new file mode 100644 index 000000000000..719822d7aa53 --- /dev/null +++ b/packages/adapter-cloudflare/test/utils.js @@ -0,0 +1,28 @@ +import { devices } from '@playwright/test'; +import process from 'node:process'; + +/** @type {import('@playwright/test').PlaywrightTestConfig} */ +export const config = { + forbidOnly: !!process.env.CI, + // generous timeouts on CI + timeout: process.env.CI ? 45000 : 15000, + webServer: { + command: 'pnpm build && pnpm preview', + port: 8787 + }, + retries: process.env.CI ? 2 : 0, + projects: [ + { + name: 'chromium' + } + ], + use: { + ...devices['Desktop Chrome'], + screenshot: 'only-on-failure', + trace: 'retain-on-failure' + }, + workers: process.env.CI ? 2 : undefined, + reporter: 'list', + testDir: 'test', + testMatch: /(.+\.)?(test|spec)\.[jt]s/ +}; diff --git a/packages/adapter-cloudflare/tsconfig.json b/packages/adapter-cloudflare/tsconfig.json index b258035a3555..dea57ac8d9a4 100644 --- a/packages/adapter-cloudflare/tsconfig.json +++ b/packages/adapter-cloudflare/tsconfig.json @@ -10,7 +10,10 @@ "baseUrl": ".", "paths": { "@sveltejs/kit": ["../kit/types/index"] - } + }, + // taken from the Cloudflare Workers TypeScript template https://github.com/cloudflare/workers-sdk/blob/main/packages/create-cloudflare/templates/hello-world/ts/tsconfig.json + "lib": ["es2021"], + "types": ["@cloudflare/workers-types"] }, - "include": ["index.js", "internal.d.ts", "src/worker.js"] + "include": ["index.js", "utils.js", "test/utils.js", "internal.d.ts", "src/worker.js"] } diff --git a/playgrounds/basic/package.json b/playgrounds/basic/package.json index a36379053856..fab80ccaef95 100644 --- a/playgrounds/basic/package.json +++ b/playgrounds/basic/package.json @@ -17,7 +17,6 @@ "devDependencies": { "@sveltejs/adapter-auto": "workspace:*", "@sveltejs/adapter-cloudflare": "workspace:*", - "@sveltejs/adapter-cloudflare-workers": "workspace:*", "@sveltejs/adapter-netlify": "workspace:*", "@sveltejs/adapter-node": "workspace:*", "@sveltejs/adapter-static": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ce13f0751d3..9cf137954cd0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,9 +64,12 @@ importers: specifier: 0.8.0-next.18 version: 0.8.0-next.18 wrangler: - specifier: ^3.87.0 || ^4.0.0 + specifier: ^4.0.0 version: 4.0.0(@cloudflare/workers-types@4.20250312.0) devDependencies: + '@playwright/test': + specifier: ^1.44.1 + version: 1.44.1 '@sveltejs/kit': specifier: workspace:^ version: link:../kit @@ -80,30 +83,47 @@ importers: specifier: ^5.3.3 version: 5.6.3 - packages/adapter-cloudflare-workers: - dependencies: - '@cloudflare/workers-types': - specifier: ^4.20250312.0 - version: 4.20250312.0 - esbuild: - specifier: ^0.24.0 - version: 0.24.2 + packages/adapter-cloudflare/test/apps/pages: + devDependencies: + '@sveltejs/kit': + specifier: workspace:^ + version: link:../../../../kit + '@sveltejs/vite-plugin-svelte': + specifier: ^5.0.1 + version: 5.0.1(svelte@5.23.1)(vite@6.0.11(@types/node@18.19.50)(lightningcss@1.24.1)) + server-side-dep: + specifier: file:server-side-dep + version: file:packages/adapter-cloudflare/test/apps/pages/server-side-dep + svelte: + specifier: ^5.23.1 + version: 5.23.1 + vite: + specifier: ^6.0.11 + version: 6.0.11(@types/node@18.19.50)(lightningcss@1.24.1) wrangler: - specifier: ^3.91.0 || ^4.0.0 + specifier: ^4.0.0 version: 4.0.0(@cloudflare/workers-types@4.20250312.0) + + packages/adapter-cloudflare/test/apps/workers: devDependencies: - '@cloudflare/kv-asset-handler': - specifier: ^0.4.0 - version: 0.4.0 '@sveltejs/kit': specifier: workspace:^ - version: link:../kit - '@types/node': - specifier: ^18.19.48 - version: 18.19.50 - typescript: - specifier: ^5.3.3 - version: 5.6.3 + version: link:../../../../kit + '@sveltejs/vite-plugin-svelte': + specifier: ^5.0.1 + version: 5.0.1(svelte@5.23.1)(vite@6.0.11(@types/node@18.19.50)(lightningcss@1.24.1)) + server-side-dep: + specifier: file:server-side-dep + version: file:packages/adapter-cloudflare/test/apps/workers/server-side-dep + svelte: + specifier: ^5.23.1 + version: 5.23.1 + vite: + specifier: ^6.0.11 + version: 6.0.11(@types/node@18.19.50)(lightningcss@1.24.1) + wrangler: + specifier: ^4.0.0 + version: 4.0.0(@cloudflare/workers-types@4.20250312.0) packages/adapter-netlify: dependencies: @@ -1124,9 +1144,6 @@ importers: '@sveltejs/adapter-cloudflare': specifier: workspace:* version: link:../../packages/adapter-cloudflare - '@sveltejs/adapter-cloudflare-workers': - specifier: workspace:* - version: link:../../packages/adapter-cloudflare-workers '@sveltejs/adapter-netlify': specifier: workspace:* version: link:../../packages/adapter-netlify @@ -3067,6 +3084,12 @@ packages: engines: {node: '>=10'} hasBin: true + server-side-dep@file:packages/adapter-cloudflare/test/apps/pages/server-side-dep: + resolution: {directory: packages/adapter-cloudflare/test/apps/pages/server-side-dep, type: directory} + + server-side-dep@file:packages/adapter-cloudflare/test/apps/workers/server-side-dep: + resolution: {directory: packages/adapter-cloudflare/test/apps/workers/server-side-dep, type: directory} + set-cookie-parser@2.6.0: resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} @@ -5362,6 +5385,10 @@ snapshots: semver@7.7.1: {} + server-side-dep@file:packages/adapter-cloudflare/test/apps/pages/server-side-dep: {} + + server-side-dep@file:packages/adapter-cloudflare/test/apps/workers/server-side-dep: {} + set-cookie-parser@2.6.0: {} sharp@0.33.5: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a390bbed591a..3ecf23a8fd4b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - 'packages/*' + - 'packages/adapter-cloudflare/test/apps/*' - 'packages/adapter-static/test/apps/*' - 'packages/kit/test/apps/*' - 'packages/kit/test/prerendering/*'