From 376290674b4d0a285f720c3139f53e8ee2601950 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 16 Sep 2025 16:57:50 -0400 Subject: [PATCH 1/2] chore: bump kit --- apps/svelte.dev/package.json | 2 +- pnpm-lock.yaml | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/svelte.dev/package.json b/apps/svelte.dev/package.json index 1030ff7177..e6bc3a452f 100644 --- a/apps/svelte.dev/package.json +++ b/apps/svelte.dev/package.json @@ -52,7 +52,7 @@ "@supabase/supabase-js": "^2.43.4", "@sveltejs/adapter-vercel": "^5.10.2", "@sveltejs/enhanced-img": "^0.8.1", - "@sveltejs/kit": "^2.38.0", + "@sveltejs/kit": "^2.42.0", "@sveltejs/site-kit": "workspace:*", "@sveltejs/vite-plugin-svelte": "^6.1.3", "@types/cookie": "^0.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 48b2360845..c31f57c991 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ importers: version: 2.0.0(svelte@5.38.2) '@sveltejs/amp': specifier: ^1.1.5 - version: 1.1.5(@sveltejs/kit@2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4))) + version: 1.1.5(@sveltejs/kit@2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4))) '@sveltejs/repl': specifier: workspace:* version: link:../../packages/repl @@ -52,7 +52,7 @@ importers: version: 1.3.2 '@vercel/speed-insights': specifier: ^1.1.0 - version: 1.1.0(@sveltejs/kit@2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2) + version: 1.1.0(@sveltejs/kit@2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2) '@webcontainer/api': specifier: ^1.1.5 version: 1.1.9 @@ -113,13 +113,13 @@ importers: version: 2.43.4 '@sveltejs/adapter-vercel': specifier: ^5.10.2 - version: 5.10.2(@sveltejs/kit@2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(rollup@4.46.4) + version: 5.10.2(@sveltejs/kit@2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(rollup@4.46.4) '@sveltejs/enhanced-img': specifier: ^0.8.1 version: 0.8.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(rollup@4.46.4)(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) '@sveltejs/kit': - specifier: ^2.38.0 - version: 2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) + specifier: ^2.42.0 + version: 2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) '@sveltejs/site-kit': specifier: workspace:* version: link:../../packages/site-kit @@ -1343,8 +1343,8 @@ packages: '@opentelemetry/api': optional: true - '@sveltejs/kit@2.38.0': - resolution: {integrity: sha512-iLmykJOv4PAZvuC0niq1HUoK/LZdfsTW1CpkPAAnroYeYiV7Bp73Eeh/As8u0Y1n/2IDM+p9cdoHYufcpvkXkQ==} + '@sveltejs/kit@2.42.0': + resolution: {integrity: sha512-ujAqGi88jAHL0eC5OAuH/w9X8uyPEJnFM4Pq6hjO0QARtlVPMKRd5yL5tQ4V9Ts+EHE5JH60CIUAhuUGUxwBUQ==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -4052,9 +4052,9 @@ snapshots: dependencies: '@sveltejs/kit': 2.34.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@24.3.0)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@24.3.0)(lightningcss@1.30.1)(tsx@4.20.4)) - '@sveltejs/adapter-vercel@5.10.2(@sveltejs/kit@2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(rollup@4.46.4)': + '@sveltejs/adapter-vercel@5.10.2(@sveltejs/kit@2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(rollup@4.46.4)': dependencies: - '@sveltejs/kit': 2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) + '@sveltejs/kit': 2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) '@vercel/nft': 0.30.0(rollup@4.46.4) esbuild: 0.25.9 transitivePeerDependencies: @@ -4062,9 +4062,9 @@ snapshots: - rollup - supports-color - '@sveltejs/amp@1.1.5(@sveltejs/kit@2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))': + '@sveltejs/amp@1.1.5(@sveltejs/kit@2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))': dependencies: - '@sveltejs/kit': 2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) + '@sveltejs/kit': 2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) '@sveltejs/enhanced-img@0.8.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(rollup@4.46.4)(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4))': dependencies: @@ -4117,7 +4117,7 @@ snapshots: svelte: 5.38.2 vite: 7.0.4(@types/node@24.3.0)(lightningcss@1.30.1)(tsx@4.20.4) - '@sveltejs/kit@2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4))': + '@sveltejs/kit@2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4))': dependencies: '@standard-schema/spec': 1.0.0 '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) @@ -4299,9 +4299,9 @@ snapshots: - rollup - supports-color - '@vercel/speed-insights@1.1.0(@sveltejs/kit@2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)': + '@vercel/speed-insights@1.1.0(@sveltejs/kit@2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)': optionalDependencies: - '@sveltejs/kit': 2.38.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) + '@sveltejs/kit': 2.42.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)))(svelte@5.38.2)(vite@7.0.4(@types/node@20.19.6)(lightningcss@1.30.1)(tsx@4.20.4)) svelte: 5.38.2 '@vitest/expect@3.2.4': From 2cea882a0f33c6d14780ad56226a277751bf0fe1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:56:21 +0200 Subject: [PATCH 2/2] Sync `kit` docs (#1539) sync kit docs Co-authored-by: svelte-docs-bot[bot] <196124396+svelte-docs-bot[bot]@users.noreply.github.com> --- .../20-core-concepts/60-remote-functions.md | 282 +++++++++++++++--- .../docs/kit/98-reference/10-@sveltejs-kit.md | 105 ++++++- .../docs/kit/98-reference/20-$app-server.md | 36 ++- 3 files changed, 361 insertions(+), 62 deletions(-) diff --git a/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md b/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md index 2d6364e690..ae9fd05324 100644 --- a/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md +++ b/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md @@ -228,7 +228,7 @@ export const getWeather = query.batch(v.string(), async (cities) => { ## form -The `form` function makes it easy to write data to the server. It takes a callback that receives the current [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)... +The `form` function makes it easy to write data to the server. It takes a callback that receives `data` constructed from the submitted [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)... ```ts @@ -260,30 +260,28 @@ export const getPosts = query(async () => { /* ... */ }); export const getPost = query(v.string(), async (slug) => { /* ... */ }); -export const createPost = form(async (data) => { - // Check the user is logged in - const user = await auth.getUser(); - if (!user) error(401, 'Unauthorized'); - - const title = data.get('title'); - const content = data.get('content'); - - // Check the data is valid - if (typeof title !== 'string' || typeof content !== 'string') { - error(400, 'Title and content are required'); +export const createPost = form( + v.object({ + title: v.pipe(v.string(), v.nonEmpty()), + content:v.pipe(v.string(), v.nonEmpty()) + }), + async ({ title, content }) => { + // Check the user is logged in + const user = await auth.getUser(); + if (!user) error(401, 'Unauthorized'); + + const slug = title.toLowerCase().replace(/ /g, '-'); + + // Insert into the database + await db.sql` + INSERT INTO post (slug, title, content) + VALUES (${slug}, ${title}, ${content}) + `; + + // Redirect to the newly created page + redirect(303, `/blog/${slug}`); } - - const slug = title.toLowerCase().replace(/ /g, '-'); - - // Insert into the database - await db.sql` - INSERT INTO post (slug, title, content) - VALUES (${slug}, ${title}, ${content}) - `; - - // Redirect to the newly created page - redirect(303, `/blog/${slug}`); -}); +); ``` ...and returns an object that can be spread onto a `
` element. The callback is called whenever the form is submitted. @@ -311,7 +309,184 @@ export const createPost = form(async (data) => {
``` -The form object contains `method` and `action` properties that allow it to work without JavaScript (i.e. it submits data and reloads the page). It also has an `onsubmit` handler that progressively enhances the form when JavaScript is available, submitting data *without* reloading the entire page. +As with `query`, if the callback uses the submitted `data`, it should be [validated](#query-Query-arguments) by passing a [Standard Schema](https://standardschema.dev) as the first argument to `form`. The one difference is to `query` is that the schema inputs must all be of type `string` or `File`, since that's all the original `FormData` provides. You can however coerce the value into a different type — how to do that depends on the validation library you use. + +```ts +/// file: src/routes/count.remote.js +import * as v from 'valibot'; +import { form } from '$app/server'; + +export const setCount = form( + v.object({ + // Valibot: + count: v.pipe(v.string(), v.transform((s) => Number(s)), v.number()), + // Zod: + // count: v.coerce.number() + }), + async ({ count }) => { + // ... + } +); +``` + +The `name` attributes on the form controls must correspond to the properties of the schema — `title` and `content` in this case. If you schema contains objects, use object notation: + +```svelte + + + +{#each jobs as job, idx} + + +{/each} +``` + +To indicate a repeated field, use a `[]` suffix: + +```svelte + + + +``` + +If you'd like type safety and autocomplete when setting `name` attributes, use the form object's `field` method: + +```svelte + +``` + +This will error during typechecking if `title` does not exist on your schema. + +The form object contains `method` and `action` properties that allow it to work without JavaScript (i.e. it submits data and reloads the page). It also has an [attachment](/docs/svelte/@attach) that progressively enhances the form when JavaScript is available, submitting data *without* reloading the entire page. + +### Validation + +If the submitted data doesn't pass the schema, the callback will not run. Instead, the form object's `issues` object will be populated: + +```svelte +
+ + + + + +
+``` + +You don't need to wait until the form is submitted to validate the data — you can call `validate()` programmatically, for example in an `oninput` callback (which will validate the data on every keystroke) or an `onchange` callback: + +```svelte +
createPost.validate()}> + +
+``` + +By default, issues will be ignored if they belong to form controls that haven't yet been interacted with. To validate _all_ inputs, call `validate({ includeUntouched: true })`. + +For client-side validation, you can specify a _preflight_ schema which will populate `issues` and prevent data being sent to the server if the data doesn't validate: + +```svelte + + +

Create a new post

+ +
+ +
+``` + +> [!NOTE] The preflight schema can be the same object as your server-side schema, if appropriate, though it won't be able to do server-side checks like 'this value already exists in the database'. Note that you cannot export a schema from a `.remote.ts` or `.remote.js` file, so the schema must either be exported from a shared module, or from a `