Fonctions distantes
Disponible depuis la version 2.27
Les fonctions distantes (remote functions) sont un outil pour communiquer de manière typée entre le client et le serveur. Elles peuvent être appelées depuis n’importe où dans votre application, mais sont toujours exécutées sur le serveur, ce qui signifie qu’elles peuvent accéder de manière sécurisée aux modules réservés au serveur contenant des choses comme des variables d’environnement ou des clients de base de données.
Combinées avec le support expérimental de Svelte pour await
,
elles vous permettent de charger et de manipuler les données directement au sein de vos composants.
Cette fonctionnalité est actuellement expérimentale, ce qui signifie qu’elle contient très
certainement des bugs, et peut être modifiée à tout moment. Vous devez l’activer en ajoutant
l’option kit.experimental.remoteFunctions
dans votre fichier svelte.config.js
, et de manière
optionnelle en ajoutant l’option kit.experimental.remoteFunctions
dans votre svelte.config.js
:
/** @type {import('@sveltejs/kit').Config} */
const const config: {
kit: {
experimental: {
remoteFunctions: boolean;
};
};
compilerOptions: {
experimental: {
async: boolean;
};
};
}
config = {
kit: {
experimental: {
remoteFunctions: boolean;
};
}
kit: {
experimental: {
remoteFunctions: boolean;
}
experimental: {
remoteFunctions: boolean
remoteFunctions: true
}
},
compilerOptions: {
experimental: {
async: boolean;
};
}
compilerOptions: {
experimental: {
async: boolean;
}
experimental: {
async: boolean
async: true
}
}
};
export default const config: {
kit: {
experimental: {
remoteFunctions: boolean;
};
};
compilerOptions: {
experimental: {
async: boolean;
};
};
}
config;
Aperçu
Les fonctions distantes (remote) sont exportées depuis un fichier .remote.js
ou .remote.ts
, et
sont disponibles en quatre versions : query
, form
, command
, et prerender
. Sur le client, les
fonctions exportées sont transformées en wrappers autour de fetch
qui invoquent leur contrepartie
sur le serveur en utilisant un endpoint HTTP généré. Les fichiers .remote.
doivent être placés
dans le dossier src
.
query
La fonction query
vous permet de lire des données dynamiques depuis le serveur (pour les données
statiques, envisagez plutôt l’utilisation de prerender
) :
import { function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query } from '$app/server';
import * as module "$lib/server/database"
db from '$lib/server/database';
export const const getPosts: RemoteQueryFunction<void, any[]>
getPosts = query<any[]>(fn: () => MaybePromise<any[]>): RemoteQueryFunction<void, any[]> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(async () => {
const const posts: any[]
posts = await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
SELECT title, slug
FROM post
ORDER BY published_at
DESC
`;
return const posts: any[]
posts;
});
Tout au long de cette page, vous verrez des imports depuis des modules fictifs comme
$lib/server/database
et$lib/server/auth
. Ces imports n’existent que pour illustrer les propos — vous pouvez bien sûr utiliser n’importe quel client de base de données et n’importe quel système d’authentification.La fonction
db.sql
ci-dessus est une fonction de gabarit étiquété qui échappe toute valeur interpolée.
La query renvoyée par getPosts
fonctionne comme une
Promise
qui résout des posts
:
<script>
import { getPosts } from './data.remote';
</script>
<h1>Articles récents</h1>
<ul>
{#each await getPosts() as { title, slug }}
<li><a href="/blog/{slug}">{title}</a></li>
{/each}
</ul>
<script lang="ts">
import { getPosts } from './data.remote';
</script>
<h1>Articles récents</h1>
<ul>
{#each await getPosts() as { title, slug }}
<li><a href="/blog/{slug}">{title}</a></li>
{/each}
</ul>
Tant que la promesse n’est pas résolue — et si elle échoue — la
<svelte:boundary>
la plus proche sera invoquée.
Bien que l’utilisation de await
soit recommandée, vous pouvez également utiliser en alternative
les propriétés loading
, error
et current
de la query :
<script>
import { getPosts } from './data.remote';
const query = getPosts();
</script>
<h1>Articles récents</h1>
{#if query.error}
<p>oups !</p>
{:else if query.loading}
<p>chargement...</p>
{:else}
<ul>
{#each query.current as { title, slug }}
<li><a href="/blog/{slug}">{title}</a></li>
{/each}
</ul>
{/if}
<script lang="ts">
import { getPosts } from './data.remote';
const query = getPosts();
</script>
<h1>Articles récents</h1>
{#if query.error}
<p>oups !</p>
{:else if query.loading}
<p>chargement...</p>
{:else}
<ul>
{#each query.current as { title, slug }}
<li><a href="/blog/{slug}">{title}</a></li>
{/each}
</ul>
{/if}
Pour le reste de ce document, nous utiliserons la forme
await
.
Arguments de query
Les fonctions query
peuvent accepter un argument, comme le slug
d’un article individuel :
<script>
import { getPost } from '../data.remote';
let { params } = $props();
const post = $derived(await getPost(params.slug));
</script>
<h1>{post.title}</h1>
<div>{@html post.content}</div>
<script lang="ts">
import { getPost } from '../data.remote';
let { params } = $props();
const post = $derived(await getPost(params.slug));
</script>
<h1>{post.title}</h1>
<div>{@html post.content}</div>
Puisque getPost
expose un endpoint HTTP, il est important de valider cet argument pour garantir
qu’il est du type attendu. Pour cela, nous pouvons utiliser n’importe quelle librairie de validation
de Standard Schema, comme Zod ou
Valibot :
import * as import v
v from 'valibot';
import { function error(status: number, body: App.Error): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error } from '@sveltejs/kit';
import { function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query } from '$app/server';
import * as module "$lib/server/database"
db from '$lib/server/database';
export const const getPosts: RemoteQueryFunction<void, void>
getPosts = query<void>(fn: () => MaybePromise<void>): RemoteQueryFunction<void, void> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(async () => { /* ... */ });
export const const getPost: RemoteQueryFunction<string, any>
getPost = query<v.StringSchema<undefined>, any>(schema: v.StringSchema<undefined>, fn: (arg: string) => any): RemoteQueryFunction<string, any> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (slug: string
slug) => {
const [const post: any
post] = await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
SELECT * FROM post
WHERE slug = ${slug: string
slug}
`;
if (!const post: any
post) function error(status: number, body?: {
message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error(404, 'Not found');
return const post: any
post;
});
L’argument et la valeur de retour sont tous deux sérialisés avec
devalue, qui gère des types comme Date
et Map
(et
également des types personnalisés que vous pouvez définir dans votre transport
hook) en plus du JSON.
Mettre les queries à jour
Toute query peut être rafraîchie via sa méthode refresh
, qui récupère la valeur la plus récente
depuis le serveur :
<button onclick={() => getPosts().refresh()}>
Vérifier s'il y a des nouveaux articles
</button>
Les queries sont mises en cache tant qu’elles sont sur la page, ce qui veut dire que
getPosts() === getPosts()
. Cela signifie que vous n’avez pas besoin d’une référence commeconst posts = getPosts()
pour mettre à jour la query.
query.batch
query.batch
fonctionne comme query
à l’exception du fait qu’il regroupe les requêtes se
produisant lors de la même micro-tâche. Ceci résout le bien nommé problème n+1 : plutôt que chaque
requête résulte en un appel séparé à la base de données (par exemple), les requêtes simultanées sont
regroupées.
Sur le serveur, le callback reçoit un tableau des arguments avec lesquels la fonction a été appelée.
Il doit renvoyer une fonction de signature (input: Input, index: number) => Output
. SvelteKit
exécutera alors cette fonction avec chacun des arguments d’entrée pour résoudre les appels
individuels et leurs résultats.
import * as import v
v from 'valibot';
import { function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query } from '$app/server';
import * as module "$lib/server/database"
db from '$lib/server/database';
export const const getWeather: RemoteQueryFunction<string, any>
getWeather = function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query.function query.batch<v.StringSchema<undefined>, any>(schema: v.StringSchema<undefined>, fn: (args: string[]) => MaybePromise<(arg: string, idx: number) => any>): RemoteQueryFunction<string, any> (+1 overload)
Creates a batch query function that collects multiple calls and executes them in a single request
See Remote functions for full documentation.
batch(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (cities: string[]
cities) => {
const const weather: any[]
weather = await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
SELECT * FROM weather
WHERE city = ANY(${cities: string[]
cities})
`;
const const lookup: Map<any, any>
lookup = new var Map: MapConstructor
new <any, any>(iterable?: Iterable<readonly [any, any]> | null | undefined) => Map<any, any> (+3 overloads)
Map(const weather: any[]
weather.Array<any>.map<[any, any]>(callbackfn: (value: any, index: number, array: any[]) => [any, any], thisArg?: any): [any, any][]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
map(w: any
w => [w: any
w.city, w: any
w]));
return (city: string
city) => const lookup: Map<any, any>
lookup.Map<any, any>.get(key: any): any
Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(city: string
city);
});
<script>
import CityWeather from './CityWeather.svelte';
import { getWeather } from './weather.remote.js';
let { cities } = $props();
let limit = $state(5);
</script>
<h2>Weather</h2>
{#each cities.slice(0, limit) as city}
<h3>{city.name}</h3>
<CityWeather weather={await getWeather(city.id)} />
{/each}
{#if cities.length > limit}
<button onclick={() => limit += 5}>
Charger plus
</button>
{/if}
<script lang="ts">
import CityWeather from './CityWeather.svelte';
import { getWeather } from './weather.remote.js';
let { cities } = $props();
let limit = $state(5);
</script>
<h2>Weather</h2>
{#each cities.slice(0, limit) as city}
<h3>{city.name}</h3>
<CityWeather weather={await getWeather(city.id)} />
{/each}
{#if cities.length > limit}
<button onclick={() => limit += 5}>
Charger plus
</button>
{/if}
form
La fonction form
facilite l’écriture de données sur le serveur. Elle prend un callback qui reçoit
l’objet data
construit à partir du
FormData
soumis...
import * as import v
v from 'valibot';
import { function error(status: number, body: App.Error): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error, function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never
Redirect a request. When called during request handling, SvelteKit will return a redirect response.
Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.
Most common status codes:
303 See Other
: redirect as a GET request (often used after a form POST request)
307 Temporary Redirect
: redirect will keep the request method
308 Permanent Redirect
: redirect will keep the request method, SEO will be transferred to the new page
redirect } from '@sveltejs/kit';
import { function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query, function form<Output>(fn: () => MaybePromise<Output>): RemoteForm<void, Output> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form } from '$app/server';
import * as module "$lib/server/database"
db from '$lib/server/database';
import * as module "$lib/server/auth"
auth from '$lib/server/auth';
export const const getPosts: RemoteQueryFunction<void, void>
getPosts = query<void>(fn: () => MaybePromise<void>): RemoteQueryFunction<void, void> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(async () => { /* ... */ });
export const const getPost: RemoteQueryFunction<string, void>
getPost = query<v.StringSchema<undefined>, void>(schema: v.StringSchema<undefined>, fn: (arg: string) => MaybePromise<void>): RemoteQueryFunction<string, void> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (slug: string
slug) => { /* ... */ });
export const const createPost: RemoteForm<{
title: string;
content: string;
}, never>
createPost = form<v.ObjectSchema<{
readonly title: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
readonly content: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
}, undefined>, never>(validate: v.ObjectSchema<...>, fn: (data: {
...;
}) => Promise<...>): RemoteForm<...> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form(
import v
v.object<{
readonly title: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
readonly content: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
}>(entries: {
readonly title: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
readonly content: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
}): v.ObjectSchema<...> (+1 overload)
export object
Creates an object schema.
Hint: This schema removes unknown entries. The output will only include the
entries you specify. To include unknown entries, use looseObject
. To
return an issue for unknown entries, use strictObject
. To include and
validate unknown entries, use objectWithRest
.
object({
title: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>
title: import v
v.pipe<v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>>(schema: v.StringSchema<undefined>, item1: v.NonEmptyAction<string, undefined> | v.PipeAction<string, string, v.NonEmptyIssue<...>>): v.SchemaWithPipe<...> (+20 overloads)
export pipe
Adds a pipeline to a schema, that can validate and transform its input.
pipe(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), import v
v.nonEmpty<string>(): v.NonEmptyAction<string, undefined> (+1 overload)
export nonEmpty
Creates a non-empty validation action.
nonEmpty()),
content: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>
content:import v
v.pipe<v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>>(schema: v.StringSchema<undefined>, item1: v.NonEmptyAction<string, undefined> | v.PipeAction<string, string, v.NonEmptyIssue<...>>): v.SchemaWithPipe<...> (+20 overloads)
export pipe
Adds a pipeline to a schema, that can validate and transform its input.
pipe(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), import v
v.nonEmpty<string>(): v.NonEmptyAction<string, undefined> (+1 overload)
export nonEmpty
Creates a non-empty validation action.
nonEmpty())
}),
async ({ title: string
title, content: string
content }) => {
// Vérifie si l'utilisateur est loggué
const const user: auth.User | null
user = await module "$lib/server/auth"
auth.function getUser(): Promise<auth.User | null>
Récupère les informations de l’utilisateur à partir des cookies, en utilisant getRequestEvent
getUser();
if (!const user: auth.User | null
user) function error(status: number, body?: {
message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error(401, 'Unauthorized');
const const slug: string
slug = title: string
title.String.toLowerCase(): string
Converts all the alphabetic characters in a string to lowercase.
toLowerCase().String.replace(searchValue: {
[Symbol.replace](string: string, replaceValue: string): string;
}, replaceValue: string): string (+3 overloads)
Passes a string and
{@linkcode
replaceValue
}
to the [Symbol.replace]
method on
{@linkcode
searchValue
}
. This method is expected to implement its own replacement algorithm.
replace(/ /g, '-');
// Insère dans la base de données
await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
INSERT INTO post (slug, title, content)
VALUES (${const slug: string
slug}, ${title: string
title}, ${content: string
content})
`;
// Redirige vers la page nouvellement créée
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never
Redirect a request. When called during request handling, SvelteKit will return a redirect response.
Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.
Most common status codes:
303 See Other
: redirect as a GET request (often used after a form POST request)
307 Temporary Redirect
: redirect will keep the request method
308 Permanent Redirect
: redirect will keep the request method, SEO will be transferred to the new page
redirect(303, `/blog/${const slug: string
slug}`);
}
)
... et renvoie un objet qui peut être distribué sur un élément <form>
. Le callback est appelée à
chaque fois que le formulaire est soumis.
<script>
import { createPost } from '../data.remote';
</script>
<h1>Créer un nouvel article</h1>
<form {...createPost}>
<!-- le contenu du formulaire est défini ici -->
<button>Publier !</button>
</form>
<script lang="ts">
import { createPost } from '../data.remote';
</script>
<h1>Créer un nouvel article</h1>
<form {...createPost}>
<!-- le contenu du formulaire est défini ici -->
<button>Publier !</button>
</form>
L’objet de formulaire contient les propriétés method
et action
qui lui permettent de fonctionner
sans JavaScriptt (c-à-d il soumet les données et recharge la page). Il possède également un
attachement qui améliore progressivement le formulaire lorsque JavaScript
est disponible, lui permettant de soumettre les données sans recharger entièrement la page.
Comme avec query
, si le callback utilise les data
soumises, celles-ci doivent être
validées en passant un Standard Schema en
tant que premier argument au form
.
Champs
Un formulaire est composé d’un ensemble de champs, qui sont définis par le schéma. Dans le cas
d’un createPost
, nous avons deux champs, title
et content
, qui sont tous deux des chaînes de
caractères. Pour récupérer les attributs d’un champ, exécutez sa méthode as(...)
, en précisant
quel type
d’input utiliser :
<form {...createPost}>
<label>
<h2>Titre</h2>
<input {...createPost.fields.title.as('text')} />
</label>
<label>
<h2>Écrivez votre article</h2>
<textarea {...createPost.fields.content.as('text')}></textarea>
</label>
<button>Publier !</button>
</form>
Ces attributs permettent à SvelteKit de définit le type correct d’input, de définir un name
utilisé pour construire les data
passées au gestionnaire, de remplir la value
du formulaire (par
exemple à la suite de l’échec d’une soumission, permettant de sauvegarder l’utilisateur ou
l’utilisatrice sans avoir besoin de tout ré-écrire), et de définir l’état
aria-invalid
Les champs peuvent être imbriqués dans des objets et des tableaux, et leurs valeurs peuvent être des
chaînes de caractères, des nombres, des booléens ou des objets File
. Par exemple, si votre schéma
ressemble à ceci...
const const datingProfile: v.ObjectSchema<{
readonly name: v.StringSchema<undefined>;
readonly photo: v.FileSchema<undefined>;
readonly info: v.ObjectSchema<{
readonly height: v.NumberSchema<undefined>;
readonly likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
}, undefined>;
readonly attributes: v.ArraySchema<...>;
}, undefined>
datingProfile = import v
v.object<{
readonly name: v.StringSchema<undefined>;
readonly photo: v.FileSchema<undefined>;
readonly info: v.ObjectSchema<{
readonly height: v.NumberSchema<undefined>;
readonly likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
}, undefined>;
readonly attributes: v.ArraySchema<...>;
}>(entries: {
readonly name: v.StringSchema<undefined>;
readonly photo: v.FileSchema<undefined>;
readonly info: v.ObjectSchema<{
readonly height: v.NumberSchema<undefined>;
readonly likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
}, undefined>;
readonly attributes: v.ArraySchema<...>;
}): v.ObjectSchema<...> (+1 overload)
export object
Creates an object schema.
Hint: This schema removes unknown entries. The output will only include the
entries you specify. To include unknown entries, use looseObject
. To
return an issue for unknown entries, use strictObject
. To include and
validate unknown entries, use objectWithRest
.
object({
name: v.StringSchema<undefined>
name: import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
photo: v.FileSchema<undefined>
photo: import v
v.function file(): v.FileSchema<undefined> (+1 overload)
export file
Creates a file schema.
file(),
info: v.ObjectSchema<{
readonly height: v.NumberSchema<undefined>;
readonly likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
}, undefined>
info: import v
v.object<{
readonly height: v.NumberSchema<undefined>;
readonly likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
}>(entries: {
readonly height: v.NumberSchema<undefined>;
readonly likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
}): v.ObjectSchema<...> (+1 overload)
export object
Creates an object schema.
Hint: This schema removes unknown entries. The output will only include the
entries you specify. To include unknown entries, use looseObject
. To
return an issue for unknown entries, use strictObject
. To include and
validate unknown entries, use objectWithRest
.
object({
height: v.NumberSchema<undefined>
height: import v
v.function number(): v.NumberSchema<undefined> (+1 overload)
export number
Creates a number schema.
number(),
likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>
likesDogs: import v
v.optional<v.BooleanSchema<undefined>, false>(wrapped: v.BooleanSchema<undefined>, default_: false): v.OptionalSchema<v.BooleanSchema<undefined>, false> (+1 overload)
export optional
Creates an optional schema.
optional(import v
v.function boolean(): v.BooleanSchema<undefined> (+1 overload)
export boolean
Creates a boolean schema.
boolean(), false)
}),
attributes: v.ArraySchema<v.StringSchema<undefined>, undefined>
attributes: import v
v.array<v.StringSchema<undefined>>(item: v.StringSchema<undefined>): v.ArraySchema<v.StringSchema<undefined>, undefined> (+1 overload)
export array
Creates an array schema.
array(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string())
});
export const const createProfile: RemoteForm<{
name: string;
photo: File;
info: {
height: number;
likesDogs?: boolean | undefined;
};
attributes: string[];
}, void>
createProfile = form<v.ObjectSchema<{
readonly name: v.StringSchema<undefined>;
readonly photo: v.FileSchema<undefined>;
readonly info: v.ObjectSchema<{
readonly height: v.NumberSchema<undefined>;
readonly likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
}, undefined>;
readonly attributes: v.ArraySchema<...>;
}, undefined>, void>(validate: v.ObjectSchema<...>, fn: (data: {
...;
}) => MaybePromise<...>): RemoteForm<...> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form(const datingProfile: v.ObjectSchema<{
readonly name: v.StringSchema<undefined>;
readonly photo: v.FileSchema<undefined>;
readonly info: v.ObjectSchema<{
readonly height: v.NumberSchema<undefined>;
readonly likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
}, undefined>;
readonly attributes: v.ArraySchema<...>;
}, undefined>
datingProfile, (data: {
name: string;
photo: File;
info: {
height: number;
likesDogs: boolean;
};
attributes: string[];
}
data) => { /* ... */ });
... votre formulaire pourrait avoir cette forme là :
<script>
import { createProfile } from './data.remote';
const { name, photo, info, attributes } = createProfile.fields;
</script>
<form {...createProfile} enctype="multipart/form-data">
<label>
<input {...name.as('text')} /> Nom
</label>
<label>
<input {...photo.as('file')} /> Photo
</label>
<label>
<input {...info.height.as('number')} /> Hauteur (cm)
</label>
<label>
<input {...info.likesDogs.as('checkbox')} /> J'aime les chiens
</label>
<h2>Mes meilleures compétences</h2>
<input {...attributes[0].as('text')} />
<input {...attributes[1].as('text')} />
<input {...attributes[2].as('text')} />
<button>envoyer</button>
</form>
Puisque notre formulaire contient un input file
, nous avons ajouté un attribut
enctype="multipart/form-data"
. Les valeurs de info.height
et info.likesDogs
sont transformées
en nombre et booléen respectivement.
Si un input
checkbox
est non coché, sa valeur n’est pas incluses dans l’objetFormData
à partir duquelSvelteKit construit les données. Ainsi, nous devons rendre la valeur optionnelle dans votre schéma. Avec Valibot cela signifie l’utilisation dev.optional(v.boolean(), false)
plutôt que justev.boolean()
, tandis qu’avec Zod, cela signifie l’utilisation dez.coerce.boolean<boolean>()
.
Dans le cas d’inputs radio
et checkbox
qui appartiennent tous au même champ, la value
doit
être précisée en tant que second argument de .as(...)
:
export const const survey: RemoteForm<{
operatingSystem: "windows" | "mac" | "linux";
languages?: ("html" | "css" | "js")[] | undefined;
}, void>
survey = form<v.ObjectSchema<{
readonly operatingSystem: v.PicklistSchema<["windows", "mac", "linux"], undefined>;
readonly languages: v.OptionalSchema<v.ArraySchema<v.PicklistSchema<["html", "css", "js"], undefined>, undefined>, readonly []>;
}, undefined>, void>(validate: v.ObjectSchema<...>, fn: (data: {
...;
}) => MaybePromise<...>): RemoteForm<...> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form(
import v
v.object<{
readonly operatingSystem: v.PicklistSchema<["windows", "mac", "linux"], undefined>;
readonly languages: v.OptionalSchema<v.ArraySchema<v.PicklistSchema<["html", "css", "js"], undefined>, undefined>, readonly []>;
}>(entries: {
readonly operatingSystem: v.PicklistSchema<["windows", "mac", "linux"], undefined>;
readonly languages: v.OptionalSchema<v.ArraySchema<v.PicklistSchema<["html", "css", "js"], undefined>, undefined>, readonly []>;
}): v.ObjectSchema<...> (+1 overload)
export object
Creates an object schema.
Hint: This schema removes unknown entries. The output will only include the
entries you specify. To include unknown entries, use looseObject
. To
return an issue for unknown entries, use strictObject
. To include and
validate unknown entries, use objectWithRest
.
object({
operatingSystem: v.PicklistSchema<["windows", "mac", "linux"], undefined>
operatingSystem: import v
v.picklist<["windows", "mac", "linux"]>(options: ["windows", "mac", "linux"]): v.PicklistSchema<["windows", "mac", "linux"], undefined> (+1 overload)
export picklist
Creates a picklist schema.
picklist(['windows', 'mac', 'linux']),
languages: v.OptionalSchema<v.ArraySchema<v.PicklistSchema<["html", "css", "js"], undefined>, undefined>, readonly []>
languages: import v
v.optional<v.ArraySchema<v.PicklistSchema<["html", "css", "js"], undefined>, undefined>, readonly []>(wrapped: v.ArraySchema<v.PicklistSchema<["html", "css", "js"], undefined>, undefined>, default_: readonly []): v.OptionalSchema<...> (+1 overload)
export optional
Creates an optional schema.
optional(import v
v.array<v.PicklistSchema<["html", "css", "js"], undefined>>(item: v.PicklistSchema<["html", "css", "js"], undefined>): v.ArraySchema<v.PicklistSchema<["html", "css", "js"], undefined>, undefined> (+1 overload)
export array
Creates an array schema.
array(import v
v.picklist<["html", "css", "js"]>(options: ["html", "css", "js"]): v.PicklistSchema<["html", "css", "js"], undefined> (+1 overload)
export picklist
Creates a picklist schema.
picklist(['html', 'css', 'js'])), [])
}),
(data: {
operatingSystem: "windows" | "mac" | "linux";
languages: ("html" | "css" | "js")[];
}
data) => { /* ... */ }
);
<form {...survey}>
<h2>Quel système d'exploitation utilisez-vous ?</h2>
{#each ['windows', 'mac', 'linux'] as os}
<label>
<input {...survey.fields.operatingSystem.as('radio', os)}>
{os}
</label>
{/each}
<h2>Dans quels langages écrivez-vous du code ?</h2>
{#each ['html', 'css', 'js'] as language}
<label>
<input {...survey.fields.languages.as('checkbox', language)}>
{language}
</label>
{/each}
<button>envoyer</button>
</form>
De manière alternative, vous pouvez également utiliser select
et select multiple
:
<form {...survey}>
<h2>Quel système d'exploitation utilisez-vous ?</h2>
<select {...survey.fields.operatingSystem.as('select')}>
<option>windows</option>
<option>mac</option>
<option>linux</option>
</select>
<h2>Dans quels langages écrivez-vous du code ?</h2>
<select {...survey.fields.languages.as('select multiple')}>
<option>html</option>
<option>css</option>
<option>js</option>
</select>
<button>envoyer</button>
</form>
Comme pour les inputs
checkbox
non cochés, si aucune sélection n’est faite, alors les données serontundefined
. Pour cette raison, le champlanguages
utilisev.optional(v.array(...), [])
, plutôt que simplementv.array(...)
.
Validation programmatique
En plus de la validation de schéma déclarative, vous pouvez programmatiquement marquer des champs
comme invalides au sein du gestionnaire de formulaire en utilisant la fonction invalid
. Cela sert
dans les cas où vous ne pouvez savoir si quelque chose est valide avant d’avoir effectué certaines
actions :
import * as import v
v from 'valibot';
import { function form<Output>(fn: () => MaybePromise<Output>): RemoteForm<void, Output> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form } from '$app/server';
import * as import db
db from '$lib/server/database';
export const const buyHotcakes: RemoteForm<RemoteFormInput, unknown>
buyHotcakes = form<RemoteFormInput, unknown>(validate: "unchecked", fn: (data: RemoteFormInput) => unknown): RemoteForm<RemoteFormInput, unknown> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form(
import v
v.object<{
readonly qty: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, "vous devez acheter au moins un gâteau">]>;
}>(entries: {
readonly qty: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, "vous devez acheter au moins un gâteau">]>;
}): v.ObjectSchema<...> (+1 overload)
export object
Creates an object schema.
Hint: This schema removes unknown entries. The output will only include the
entries you specify. To include unknown entries, use looseObject
. To
return an issue for unknown entries, use strictObject
. To include and
validate unknown entries, use objectWithRest
.
object({
qty: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, "vous devez acheter au moins un gâteau">]>
qty: import v
v.pipe<v.NumberSchema<undefined>, v.MinValueAction<number, 1, "vous devez acheter au moins un gâteau">>(schema: v.NumberSchema<undefined>, item1: v.MinValueAction<number, 1, "vous devez acheter au moins un gâteau"> | v.PipeAction<...>): v.SchemaWithPipe<...> (+20 overloads)
export pipe
Adds a pipeline to a schema, that can validate and transform its input.
pipe(
import v
v.function number(): v.NumberSchema<undefined> (+1 overload)
export number
Creates a number schema.
number(),
import v
v.minValue<number, 1, "vous devez acheter au moins un gâteau">(requirement: 1, message: "vous devez acheter au moins un gâteau"): v.MinValueAction<number, 1, "vous devez acheter au moins un gâteau"> (+1 overload)
export minValue
Creates a min value validation action.
minValue(1, 'vous devez acheter au moins un gâteau')
)
}),
async (data: any
data, invalid: any
invalid) => {
try {
await import db
db.buy(data: any
data.qty);
} catch (function (local var) e: unknown
e) {
if (function (local var) e: unknown
e.code === 'OUT_OF_STOCK') {
invalid: any
invalid(
invalid: any
invalid.qty(`nous n'avons pas assez de gâteaux`)
);
}
}
}
);
La fonction invalid
fonctionne à la fois comme une fonction et comme un proxy :
- Appelez
invalid(issue1, issue2, ...issueN)
pour jeter une erreur de validation - Si une erreur est une
string
, elle s’applique au formulaire en tant que tel (et sera affichée dansfields.allIssues()
) - Utilisez
invalid.fieldName(message)
pour créer une erreur pour un champ particulier. Commefields
, ceci est typé et vous pouvez utiliser la syntaxe classique d’accès aux propriétés pour créer des erreurs concernant des objets imbriqués (par ex.invalid.profile.email('L\'e-mail existe déjà'')
ouinvalid.items[0].qty('Stock insuffisant')
))
Validation
Si les données soumises ne correspondent pas au schéma, le callback ne sera pas exécuté. À la place,
chaque méthode issues()
d’un champ invalide renverra un tableau d’objets { message: string }
, et
l’attribut aria-invalid
(renvoyé depuis as(...)
) sera défini comme true
:
<form {...createPost}>
<label>
<h2>Title</h2>
{#each createPost.fields.title.issues() as issue}
<p class="issue">{issue.message}</p>
{/each}
<input {...createPost.fields.title.as('text')} />
</label>
<label>
<h2>Écrivez votre article</h2>
{#each createPost.fields.content.issues() as issue}
<p class="issue">{issue.message}</p>
{/each}
<textarea {...createPost.fields.content.as('text')}></textarea>
</label>
<button>Publier !</button>
</form>
Vous n’avez pas besoin d’attendre la fin de la soumission du formulaire pour valider les données —
vous pouvez appeler validate()
programmatiquement, par exemple dans un callback oninput
(qui va
valider les données à chaque touche du clavier) ou dans un callback onchange
:
<form {...createPost} oninput={() => createPost.validate()}>
<!-- -->
</form>
Par défaut, les problèmes sont ignorés s’ils concernent des contrôles de formulaires avec lesquels
il n’y a pas encore eu d’interaction. Pour valider tous les inputs, appelez validate({ includeUntouched: true })
.
Pour les validations côté client, vous pouvez préciser un schéma preflight qui va remplir les
issues()
et empêcher que les données soient envoyées au serveur si celles-ci ne sont pas validées
:
<script>
import * as v from 'valibot';
import { createPost } from '../data.remote';
const schema = v.object({
title: v.pipe(v.string(), v.nonEmpty()),
content: v.pipe(v.string(), v.nonEmpty())
});
</script>
<h1>Créer un nouvel article</h1>
<form {...createPost.preflight(schema)}>
<!-- -->
</form>
Le schéma preflight peut être le même objet que votre schéma utilisé sur le serveur, si cela est pertinent, même s’il ne sera pas capable de faire des validations devant être faites côté serveur comme “cette valeur existe déjà dans la base de données” par exemple. Notez que vous ne pouvez pas exporter un schéma depuis un fichier
.remote.ts
ou.remote.js
, le schéma doit alors être exporté depuis un module partagé, ou depuis le block<script module>
du composant contenant le<form>
.
Pour obtenir une liste de tous les problèmes, plutôt qu’uniquement ceux appartenant à un champ
particulier, vous pouvez utiliser la méthode fields.allIssues()
:
{#each createPost.fields.allIssues() as issue}
<p>{issue.message}</p>
{/each}
Récupérer/définir des inputs
Chaque champ a une méthode value()
qui reflète sa valeur actuelle. Lorsque quelqu’un interagit
avec le formulaire, la valeur est automatiquement mise à jour :
<form {...createPost}>
<!-- -->
</form>
<div class="preview">
<h2>{createPost.fields.title.value()}</h2>
<div>{@html render(createPost.fields.content.value())}</div>
</div>
De plus, createPost.fields
renvoie un objet { title, content }
.
Vous pouvez mettre à jour un champ (ou une collection de champs) via la méthode set(...)
:
<script>
import { createPost } from '../data.remote';
// ceci...
createPost.fields.set({
title: 'Mon nouvel article de blog',
content: 'Lorem ipsum dolor sit amet...'
});
// ...est équivalent à ceci :
createPost.fields.title.set('Mon nouvel article de blog');
createPost.fields.content.set('Lorem ipsum dolor sit amet');
</script>
Gérer les données sensibles
Dans le cas d’une soumission de formulaire non-améliorée-progressivement (c-à-d lorsque JavaScript
n’est pas disponible, quelqu’en soit la raison), value()
est également rempli si les données
soumises sont invalides, afin que l’utilisateur ou l’utilisatrice n’ait pas besoin de re-remplir
entièrement le formulaire.
Vous pouvez empêcher que des données sensibles (comme des mots de passe ou des numéros de carte bancaire) soient renvoyés au client en utilisant un nom commençant par un tiret-bas :
<form {...register}>
<label>
Nom
<input {...register.fields.username.as('text')} />
</label>
<label>
Mot de passe
<input {...register.fields._password.as('password')} />
</label>
<button>S'inscrire !</button>
</form>
Dans cet exemple, si les données ne sont pas validées, seul le premier <input>
sera rempli lorsque
la page sera rechargée.
Mutations single-flight
Par défaut, toutes les queries utilisées sur la page (en plus de toutes fonction load
) sont
automatiquement mises à jour à la suite d’une soumission de formulaire. Ceci assure que tout soit à
jour, mais est également inefficace : beaucoup de queries seront inchangées, et cela requiert un
deuxième aller-retour vers le serveur pour obtenir les données à jour.
À la place, nous pouvons préciser quelles queries devraient être mises à jour en réponse à une soumission particulière de formulaire. On appelle cela une mutation single-flight (mutation sur un seul aller-retour), et il y a deux manières de faire. La première est de rafraîchir la query sur le serveur, dans le gestionnaire de formulaire :
export const const getPosts: RemoteQueryFunction<void, void>
getPosts = query<void>(fn: () => MaybePromise<void>): RemoteQueryFunction<void, void> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(async () => { /* ... */ });
export const const getPost: RemoteQueryFunction<string, void>
getPost = query<v.StringSchema<undefined>, void>(schema: v.StringSchema<undefined>, fn: (arg: string) => MaybePromise<void>): RemoteQueryFunction<string, void> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (slug: string
slug) => { /* ... */ });
export const const createPost: RemoteForm<{}, never>
createPost = form<v.ObjectSchema<{}, undefined>, never>(validate: v.ObjectSchema<{}, undefined>, fn: (data: {}) => Promise<never>): RemoteForm<{}, never> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form(
import v
v.object<{}>(entries: {}): v.ObjectSchema<{}, undefined> (+1 overload)
export object
Creates an object schema.
Hint: This schema removes unknown entries. The output will only include the
entries you specify. To include unknown entries, use looseObject
. To
return an issue for unknown entries, use strictObject
. To include and
validate unknown entries, use objectWithRest
.
object({/* ... */}),
async (data: {}
data) => {
// la logique du formulaire se place ici...
// Met à jour `getPosts()` sur le serveur, et
// renvoie les données au client avec le résultat
// de `createPost`
await const getPosts: (arg: void) => RemoteQuery<void>
getPosts().function refresh(): Promise<void>
On the client, this function will re-fetch the query from the server.
On the server, this can be called in the context of a command
or form
and the refreshed data will accompany the action response back to the client.
This prevents SvelteKit needing to refresh all queries on the page in a second server round-trip.
refresh();
// Redirige vers la page nouvellement créée
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never
Redirect a request. When called during request handling, SvelteKit will return a redirect response.
Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.
Most common status codes:
303 See Other
: redirect as a GET request (often used after a form POST request)
307 Temporary Redirect
: redirect will keep the request method
308 Permanent Redirect
: redirect will keep the request method, SEO will be transferred to the new page
redirect(303, `/blog/${const slug: ""
slug}`);
}
);
export const const updatePost: RemoteForm<{}, void>
updatePost = form<v.ObjectSchema<{}, undefined>, void>(validate: v.ObjectSchema<{}, undefined>, fn: (data: {}) => MaybePromise<void>): RemoteForm<{}, void> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form(
import v
v.object<{}>(entries: {}): v.ObjectSchema<{}, undefined> (+1 overload)
export object
Creates an object schema.
Hint: This schema removes unknown entries. The output will only include the
entries you specify. To include unknown entries, use looseObject
. To
return an issue for unknown entries, use strictObject
. To include and
validate unknown entries, use objectWithRest
.
object({/* ... */}),
async (data: {}
data) => {
// la logique de formulaire s'écrit ici...
const const result: any
result = const externalApi: any
externalApi.update(const post: {
id: string;
}
post);
// L'API nous donne déjà l'article mis à jour,
// il n'y donc pas besoin de le rafraîchir, nous pouvons le définir directement
await const getPost: (arg: string) => RemoteQuery<void>
getPost(const post: {
id: string;
}
post.id: string
id).function set(value: void): void
On the client, this function will update the value of the query without re-fetching it.
On the server, this can be called in the context of a command
or form
and the specified data will accompany the action response back to the client.
const result: any
result);
}
);La seconde est de conduire la mutation single-flight depuis le client, ce que nous verrons dans la
section sur enhance
.
Renvois et redirections
L’exemple ci-dessus utilise redirect(...)
, qui redirige l’utilisateur ou
l’utilisatrice vers la page nouvellement créée. De manière alternative, le callback pourrait
également renvoyer les données, auquel cas elles seraient disponibles en tant que
createPost.result
:
export const const createPost: RemoteForm<{}, {
success: boolean;
}>
createPost = form<v.ObjectSchema<{}, undefined>, {
success: boolean;
}>(validate: v.ObjectSchema<{}, undefined>, fn: (data: {}) => MaybePromise<{
success: boolean;
}>): RemoteForm<{}, {
success: boolean;
}> (+2 overloads)
Creates a form object that can be spread onto a <form>
element.
See Remote functions for full documentation.
form(
import v
v.object<{}>(entries: {}): v.ObjectSchema<{}, undefined> (+1 overload)
export object
Creates an object schema.
Hint: This schema removes unknown entries. The output will only include the
entries you specify. To include unknown entries, use looseObject
. To
return an issue for unknown entries, use strictObject
. To include and
validate unknown entries, use objectWithRest
.
object({/* ... */}),
async (data: {}
data) => {
// ...
return { success: boolean
success: true };
}
);
<script>
import { createPost } from '../data.remote';
</script>
<h1>Créer un nouvel article</h1>
<form {...createPost}>
<!-- -->
</form>
{#if createPost.result?.success}
<p>Publié avec succès !</p>
{/if}
<script lang="ts">
import { createPost } from '../data.remote';
</script>
<h1>Créer un nouvel article</h1>
<form {...createPost}>
<!-- -->
</form>
{#if createPost.result?.success}
<p>Publié avec succès !</p>
{/if}
Cette valeur est éphémère — elle disparaîtra si vous re-soumettez le formulaire, si vous naviguez sur une autre page, ou si vous rechargez la page.
La valeur de
result
n’indique pas nécessairement un succès — elle peut également contenir des erreurs de validation, ainsi que des données permettant de re-remplir le formulaire en cas de rechargement de la page.
Si une erreur se produit lors de la soumission, la page +error.svelte
la plus proche sera
affichée.
enhance
Nous pouvons personnaliser ce qui se produit lorsque le formulaire est soumis grâce à la méthode
enhance
:
<script>
import { createPost } from '../data.remote';
import { showToast } from '$lib/toast';
</script>
<h1>Créer un nouvel article</h1>
<form {...createPost.enhance(async ({ form, data, submit }) => {
try {
await submit();
form.reset();
showToast('Publié avec succès !');
} catch (error) {
showToast('Oh non ! Quelque chose s\'est mal passé !');
}
})}>
<!-- -->
</form>
<script lang="ts">
import { createPost } from '../data.remote';
import { showToast } from '$lib/toast';
</script>
<h1>Créer un nouvel article</h1>
<form {...createPost.enhance(async ({ form, data, submit }) => {
try {
await submit();
form.reset();
showToast('Publié avec succès !');
} catch (error) {
showToast('Oh non ! Quelque chose s\'est mal passé !');
}
})}>
<!-- -->
</form>
Lorsque vous utilisez
enhance
, le<form>
n’est pas automatiquement réinitialisé — vous devez appelerform.reset()
si vous souhaitez nettoyer les inputs.
Le callback reçoit l’élément form
, la data
qu’il contient, et une fonction submit
.
Pour activer les mutations single-flight depuis le client, utilisez
submit().updates(...})
. Par exemple, si la query getPosts()
était utilisée sur cette page, nous
pourrions la mettre à jour de cette manière :
await function submit(): Promise<any> & {
updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<any>;
}
submit().function updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<any>
updates(function getPosts(): RemoteQuery<Post[]>
getPosts());
Nous pouvons aussi surcharger les données courantes pendant que la soumission est en cours de traitement :
await function submit(): Promise<any> & {
updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<any>;
}
submit().function updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<any>
updates(
function getPosts(): RemoteQuery<Post[]>
getPosts().function withOverride(update: (current: Post[]) => Post[]): RemoteQueryOverride
Temporarily override the value of a query. This is used with the updates
method of a command or enhanced form submission to provide optimistic updates.
<script>
import { getTodos, addTodo } from './todos.remote.js';
const todos = getTodos();
</script>
<form {...addTodo.enhance(async ({ data, submit }) => {
await submit().updates(
todos.withOverride((todos) => [...todos, { text: data.get('text') }])
);
})}>
<input type="text" name="text" />
<button type="submit">Add Todo</button>
</form>
withOverride((posts: Post[]
posts) => [const newPost: Post
newPost, ...posts: Post[]
posts])
);
La surcharge sera appliquée immédiatement, et annulée lorsque la soumission se termine (ou échoue).
Instances multiples de formulaire
Certains formulaires peuvent être répétés au sein d’une liste. Dans ce cas, vous pouvez créer des
instances séparées d’une fonction de formulaire via for(id)
pour les garder en isolation.
<script>
import { getTodos, modifyTodo } from '../data.remote';
</script>
<h1>À faire</h1>
{#each await getTodos() as todo}
{@const modify = modifyTodo.for(todo.id)}
<form {...modify}>
<!-- -->
<button disabled={!!modify.pending}>enregistrer les changements</button>
</form>
{/each}
<script lang="ts">
import { getTodos, modifyTodo } from '../data.remote';
</script>
<h1>À faire</h1>
{#each await getTodos() as todo}
{@const modify = modifyTodo.for(todo.id)}
<form {...modify}>
<!-- -->
<button disabled={!!modify.pending}>enregistrer les changements</button>
</form>
{/each}
buttonProps
Par défaut, soumettre un formulaire va envoyer une requête à l’URL indiquée par l’attribut
action
de l’élément <form>
, ce qui dans le cas d’une fonction distante est une propriété sur l’objet de
formulaire généré par SvelteKit.
Il est possible pour un <button>
au sein d’un <form>
d’envoyer la requête à une URL
différente, en utilisant l’attribut
formaction
.
Par exemple, vous pourriez avoir un seul formulaire vous permettant de vous connecter ou de vous
inscrire, selon le bouton sur lequel vous cliquez.
Cet attribut existe dans la propriété buttonProps
d’un objet de formulaire :
<script>
import { login, register } from '$lib/auth';
</script>
<form {...login}>
<label>
Votre nom d'utilisateur
<input {...login.fields.username.as('text')} />
</label>
<label>
Votre mot de passe
<input {...login.fields._password.as('password')} />
</label>
<button>se connecter</button>
<button {...register.buttonProps}>s'inscrire</button>
</form>
<script lang="ts">
import { login, register } from '$lib/auth';
</script>
<form {...login}>
<label>
Votre nom d'utilisateur
<input {...login.fields.username.as('text')} />
</label>
<label>
Votre mot de passe
<input {...login.fields._password.as('password')} />
</label>
<button>se connecter</button>
<button {...register.buttonProps}>s'inscrire</button>
</form>
Comme l’objet de formulaire lui-même, buttonProps
possède une méthode enhance
permettant de
personnaliser la soumission du formulaire.
command
La fonction command
, comme form
, vous permet d’écrire des données sur le serveur. À la
différence de form
, elle n’est pas spécifique à un élément et peut être appelée depuis n’importe
où.
Privilégiez l’usage de
form
lorsque c’est possible, puisqu’elle continue de fonctionner lorsque JavaScript est désactivé ou a échoué à se charger.
Comme avec query
et form
, si la fonction accepte un argument, celui-ci devrait être
validé en fournissant un Standard Schema en
tant que premier argument à command
.
import * as import v
v from 'valibot';
import { function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query, function command<Output>(fn: () => Output): RemoteCommand<void, Output> (+2 overloads)
Creates a remote command. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
command } from '$app/server';
import * as module "$lib/server/database"
db from '$lib/server/database';
export const const getLikes: RemoteQueryFunction<string, any>
getLikes = query<v.StringSchema<undefined>, any>(schema: v.StringSchema<undefined>, fn: (arg: string) => any): RemoteQueryFunction<string, any> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (id: string
id) => {
const [const row: any
row] = await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
SELECT likes
FROM item
WHERE id = ${id: string
id}
`;
return const row: any
row.likes;
});
export const const addLike: RemoteCommand<string, Promise<void>>
addLike = command<v.StringSchema<undefined>, Promise<void>>(validate: v.StringSchema<undefined>, fn: (arg: string) => Promise<void>): RemoteCommand<string, Promise<void>> (+2 overloads)
Creates a remote command. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
command(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (id: string
id) => {
await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
UPDATE item
SET likes = likes + 1
WHERE id = ${id: string
id}
`;
});
Vous pouvez maintenant simplement appeler addLike
, depuis (par exemple) un gestionnaire
d’évènement :
<script>
import { getLikes, addLike } from './likes.remote';
import { showToast } from '$lib/toast';
let { item } = $props();
</script>
<button
onclick={async () => {
try {
await addLike(item.id);
} catch (error) {
showToast('Quelque chose s\'est mal passé !');
}
}}
>
ajouter un like
</button>
<p>likes : {await getLikes(item.id)}</p>
<script lang="ts">
import { getLikes, addLike } from './likes.remote';
import { showToast } from '$lib/toast';
let { item } = $props();
</script>
<button
onclick={async () => {
try {
await addLike(item.id);
} catch (error) {
showToast('Quelque chose s\'est mal passé !');
}
}}
>
ajouter un like
</button>
<p>likes : {await getLikes(item.id)}</p>
Les commandes ne peuvent pas être appelées lors du rendu.
Mettre à jour les queries
Pour mettre à jour getLikes(item.id)
, ou toute autre query, nous avons besoin de préciser à
SvelteKit quelles queries nécessitent d’être rafraîchies (au contraire de form
, qui invalide
tout par défaut, pour se rapprocher du comportement natif d’une soumission de formulaire).
Nous faisons cela soit au sein de la commande elle-même...
export const const getLikes: RemoteQueryFunction<string, void>
getLikes = query<v.StringSchema<undefined>, void>(schema: v.StringSchema<undefined>, fn: (arg: string) => MaybePromise<void>): RemoteQueryFunction<string, void> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (id: string
id) => { /* ... */ });
export const const addLike: RemoteCommand<string, Promise<void>>
addLike = command<v.StringSchema<undefined>, Promise<void>>(validate: v.StringSchema<undefined>, fn: (arg: string) => Promise<void>): RemoteCommand<string, Promise<void>> (+2 overloads)
Creates a remote command. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
command(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (id: string
id) => {
await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
UPDATE item
SET likes = likes + 1
WHERE id = ${id: string
id}
`;
const getLikes: (arg: string) => RemoteQuery<void>
getLikes(id: string
id).function refresh(): Promise<void>
On the client, this function will re-fetch the query from the server.
On the server, this can be called in the context of a command
or form
and the refreshed data will accompany the action response back to the client.
This prevents SvelteKit needing to refresh all queries on the page in a second server round-trip.
refresh();
// Comme au sein des fonctions de formulaire, nous pouvons aussi faire
// getLikes(id).set(...)
// dans le cas où vous avez déjà le résultat
});
... soit lorsque nous l’exécutons :
try {
await const addLike: (arg: string) => Promise<void> & {
updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<...>;
}
addLike(const item: Item
item.Item.id: string
id).function updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<void>
updates(const getLikes: (arg: string) => RemoteQuery<number>
getLikes(const item: Item
item.Item.id: string
id));
} catch (var error: unknown
error) {
function showToast(message: string): void
showToast('Quelque chose s\'est mal passé !');
}
Comme précédemment, nous pouvons utiliser withOverride
pour faire des mises à jour optimistes :
try {
await const addLike: (arg: string) => Promise<void> & {
updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<...>;
}
addLike(const item: Item
item.Item.id: string
id).function updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<void>
updates(
const getLikes: (arg: string) => RemoteQuery<number>
getLikes(const item: Item
item.Item.id: string
id).function withOverride(update: (current: number) => number): RemoteQueryOverride
Temporarily override the value of a query. This is used with the updates
method of a command or enhanced form submission to provide optimistic updates.
<script>
import { getTodos, addTodo } from './todos.remote.js';
const todos = getTodos();
</script>
<form {...addTodo.enhance(async ({ data, submit }) => {
await submit().updates(
todos.withOverride((todos) => [...todos, { text: data.get('text') }])
);
})}>
<input type="text" name="text" />
<button type="submit">Add Todo</button>
</form>
withOverride((n: number
n) => n: number
n + 1)
);
} catch (var error: unknown
error) {
function showToast(message: string): void
showToast('Quelque chose s\'est mal passé !');
}
prerender
La fonction prerender
est similaire à query
, sauf qu’elle sera exécutée lors de la compilation
pour pré-rendre le résultat. Utilisez cette fonction pour des données qui changent au plus une fois
par déploiement.
import { function prerender<Output>(fn: () => MaybePromise<Output>, options?: {
inputs?: RemotePrerenderInputsGenerator<void>;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<void, Output> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender } from '$app/server';
import * as module "$lib/server/database"
db from '$lib/server/database';
export const const getPosts: RemotePrerenderFunction<void, any[]>
getPosts = prerender<any[]>(fn: () => MaybePromise<any[]>, options?: {
inputs?: RemotePrerenderInputsGenerator<void>;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<...> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender(async () => {
const const posts: any[]
posts = await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
SELECT title, slug
FROM post
ORDER BY published_at
DESC
`;
return const posts: any[]
posts;
});
Vous pouvez utiliser des fonctions prerender
sur des pages par ailleurs dynamiques, permettant le
pré-rendu partiel de vos données. Ceci permet une navigation très rapide, puisque les données
prérendues peuvent être stockées sur un CDN à côté de vos autres assets statiques.
Dans le navigateur, les données pré-rendues sont sauvegardées en utilisant l’API
Cache
. Ce cache survit aux rechargements de
page, et sera nettoyé lorsque l’utilisateur ou l’utilisatrice visitera pour la première fois une
nouveau déploiement de votre application.
Lorsque la page entière a
export const prerender = true
, vous ne pouvez pas utiliser de queries, puisqu’elles sont dynamiques.
Arguments de prerender
Comme avec les queries, les fonctions prerender
peuvent accepter un argument, qui devrait être
validé avec un Standard Schema :
import * as import v
v from 'valibot';
import { function error(status: number, body: App.Error): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error } from '@sveltejs/kit';
import { function prerender<Output>(fn: () => MaybePromise<Output>, options?: {
inputs?: RemotePrerenderInputsGenerator<void>;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<void, Output> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender } from '$app/server';
import * as module "$lib/server/database"
db from '$lib/server/database';
export const const getPosts: RemotePrerenderFunction<void, void>
getPosts = prerender<void>(fn: () => MaybePromise<void>, options?: {
inputs?: RemotePrerenderInputsGenerator<void>;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<...> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender(async () => { /* ... */ });
export const const getPost: RemotePrerenderFunction<string, any>
getPost = prerender<v.StringSchema<undefined>, any>(schema: v.StringSchema<undefined>, fn: (arg: string) => any, options?: {
inputs?: RemotePrerenderInputsGenerator<string> | undefined;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<...> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender(import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (slug: string
slug) => {
const [const post: any
post] = await module "$lib/server/database"
db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>
sql`
SELECT * FROM post
WHERE slug = ${slug: string
slug}
`;
if (!const post: any
post) function error(status: number, body?: {
message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error(404, 'Not found');
return const post: any
post;
});
Tout appel à getPost(...)
identifié par le crawler de SvelteKit lors du pré-rendu des
pages sera automatiquement enregistré, mais vous pouvez également préciser
avec quelles valeurs chaque appel devrait être fait en utilisant l’option inputs
:
export const const getPost: RemotePrerenderFunction<string, void>
getPost = prerender<v.StringSchema<undefined>, void>(schema: v.StringSchema<undefined>, fn: (arg: string) => MaybePromise<void>, options?: {
inputs?: RemotePrerenderInputsGenerator<string> | undefined;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<...> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender(
import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
async (slug: string
slug) => { /* ... */ },
{
inputs?: RemotePrerenderInputsGenerator<string> | undefined
inputs: () => [
'premier-article',
'deuxième-article',
'troisième-article'
]
}
);
export const const getPost: RemotePrerenderFunction<string, void>
getPost = prerender<v.StringSchema<undefined>, void>(schema: v.StringSchema<undefined>, fn: (arg: string) => MaybePromise<void>, options?: {
inputs?: RemotePrerenderInputsGenerator<string> | undefined;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<...> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender(
import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
async (slug: string
slug) => { /* ... */ },
{
inputs?: RemotePrerenderInputsGenerator<string> | undefined
inputs: () => [
'premier-article',
'deuxième-article',
'troisième-article'
]
}
);
Svelte ne supporte pas encore le rendu asynchrone côté serveur, et il est donc probable que vous n’appeliez les fonctions distantes que depuis le serveur, plutôt que lors du pré-rendu. À cause de cela, vous aurez besoin d’utiliser
inputs
, pour le moment. Nous travaillons activement sur point bloquant.
Par défaut, les fonctions de pré-rendu sont exclues de votre bundle de compilation, ce qui signifie
que vous ne pouvez pas les exécuter avec des arguments qui n’ont pas été pré-rendus. Vous pouvez
définir dynamic: true
pour changer ce comportement :
export const const getPost: RemotePrerenderFunction<string, void>
getPost = prerender<v.StringSchema<undefined>, void>(schema: v.StringSchema<undefined>, fn: (arg: string) => MaybePromise<void>, options?: {
inputs?: RemotePrerenderInputsGenerator<string> | undefined;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<...> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender(
import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
async (slug: string
slug) => { /* ... */ },
{
dynamic?: boolean | undefined
dynamic: true,
inputs?: RemotePrerenderInputsGenerator<string> | undefined
inputs: () => [
'premier-article',
'deuxième-article',
'troisième-article'
]
}
);
export const const getPost: RemotePrerenderFunction<string, void>
getPost = prerender<v.StringSchema<undefined>, void>(schema: v.StringSchema<undefined>, fn: (arg: string) => MaybePromise<void>, options?: {
inputs?: RemotePrerenderInputsGenerator<string> | undefined;
dynamic?: boolean;
} | undefined): RemotePrerenderFunction<...> (+2 overloads)
Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
prerender(
import v
v.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
async (slug: string
slug) => { /* ... */ },
{
dynamic?: boolean | undefined
dynamic: true,
inputs?: RemotePrerenderInputsGenerator<string> | undefined
inputs: () => [
'premier-article',
'deuxième-article',
'troisième-article'
]
}
);
Gestion des erreurs de validation
Tant que vous ne passez pas de données invalides à vos fonctions distantes, il n’y a que deux
raisons pour lesquelles l’argument passé à une command
, une query
ou une prerender
échouerait
à la validation :
- la signature de la fonction a changé entre deux déploiements, et certains utilisateurs ou utilisatrices sont actuellement sur une version ancienne de votre application
- quelqu’un est en train d’essayer d’attaquer votre site en testant les endpoints que vous exposez avec des données malformées
Dans le second cas, nous ne voulons pas donner à l’attaquant d’indices, c’est pourquoi SvelteKit va
générer une réponse générique 400 Bad Request. Vous pouvez contrôler le
message en implémentant le hook serveur
handleValidationError
, qui, comme
handleError
, doit renvoyer un objet
App.Error
(qui est défini par défaut à { message: string }
) :
/** @type {import('@sveltejs/kit').HandleValidationError} */
export function function handleValidationError({ event, issues }: {
event: any;
issues: any;
}): {
message: string;
}
handleValidationError({ event: any
event, issues: any
issues }) {
return {
message: string
message: 'Bien tenté, hacker !'
};
}
import type { type HandleValidationError<Issue extends StandardSchemaV1.Issue = StandardSchemaV1.Issue> = (input: {
issues: Issue[];
event: RequestEvent;
}) => MaybePromise<App.Error>
The handleValidationError
hook runs when the argument to a remote function fails validation.
It will be called with the validation issues and the event, and must return an object shape that matches App.Error
.
HandleValidationError } from '@sveltejs/kit';
export const const handleValidationError: HandleValidationError
handleValidationError: type HandleValidationError<Issue extends StandardSchemaV1.Issue = StandardSchemaV1.Issue> = (input: {
issues: Issue[];
event: RequestEvent;
}) => MaybePromise<App.Error>
The handleValidationError
hook runs when the argument to a remote function fails validation.
It will be called with the validation issues and the event, and must return an object shape that matches App.Error
.
HandleValidationError = ({ event: RequestEvent<Record<string, string>, string | null>
event, issues: StandardSchemaV1.Issue[]
issues }) => {
return {
App.Error.message: string
message: 'Bien tenté, hacker !'
};
};
Si vous savez ce que vous faites et souhaitez vous passer de validation, vous pouvez passer la
chaîne de caractères 'unchecked'
à la place du schéma :
import { function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query } from '$app/server';
export const const getStuff: RemoteQueryFunction<{
id: string;
}, void>
getStuff = query<{
id: string;
}, void>(validate: "unchecked", fn: (arg: {
id: string;
}) => MaybePromise<void>): RemoteQueryFunction<{
id: string;
}, void> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query('unchecked', async ({ id: string
id }: { id: string
id: string }) => {
// la forme peut ne pas être ce que pense TypeScript
// puisque des personnes mal intentionnées pourraient
// appeler cette fonction avec d'autres arguments
});
Utiliser getRequestEvent
Dans une fonction query
, form
ou command
, vous pouvez utiliser
getRequestEvent
pour obtenir l’objet
RequestEvent
courant. Ceci permet de construire simplement des
abstractions pour interagir avec des cookies, par exemple :
import { function getRequestEvent(): RequestEvent
Returns the current RequestEvent
. Can be used inside server hooks, server load
functions, actions, and endpoints (and functions called by them).
In environments without AsyncLocalStorage
, this must be called synchronously (i.e. not after an await
).
getRequestEvent, function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query } from '$app/server';
import { import findUser
findUser } from '$lib/server/database';
export const const getProfile: RemoteQueryFunction<void, {
name: any;
avatar: any;
}>
getProfile = query<{
name: any;
avatar: any;
}>(fn: () => MaybePromise<{
name: any;
avatar: any;
}>): RemoteQueryFunction<void, {
name: any;
avatar: any;
}> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(async () => {
const const user: any
user = await const getUser: (arg: void) => RemoteQuery<any>
getUser();
return {
name: any
name: const user: any
user.name,
avatar: any
avatar: const user: any
user.avatar
};
});
// cette query pourrait être appelée depuis plusieurs endroits,
// mais cette fonction ne sera exécutée qu'une fois par requête
const const getUser: RemoteQueryFunction<void, any>
getUser = query<any>(fn: () => any): RemoteQueryFunction<void, any> (+2 overloads)
Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch
call.
See Remote functions for full documentation.
query(() => {
const { const cookies: Cookies
Get or set cookies related to the current request
cookies } = function getRequestEvent(): RequestEvent
Returns the current RequestEvent
. Can be used inside server hooks, server load
functions, actions, and endpoints (and functions called by them).
In environments without AsyncLocalStorage
, this must be called synchronously (i.e. not after an await
).
getRequestEvent();
return await import findUser
findUser(const cookies: Cookies
Get or set cookies related to the current request
cookies.Cookies.get: (name: string, opts?: CookieParseOptions) => string | undefined
Gets a cookie that was previously set with cookies.set
, or from the request headers.
get('session_id'));
});
Notez que certaines propriétés de RequestEvent
sont différentes au sein des fonctions distantes :
- vous ne pouvez pas définir d’en-têtes (si ce n’est écrire dans des cookies, et uniquement dans des
fonctions
form
etcommand
) route
,params
eturl
sont relatives à la page depuis laquelle la fonction distante a été appelée, et non l’URL du endpoint que SvelteKit crée pour la fonction distante. Les queries ne sont pas ré-exécutées lorsque l’utilisateur ou l’utilisatrice navigue (à moins que l’argument de la query ait changé suite à une navigation), vous devriez donc être conscient•e de la façon dont vous utilisez ces valeurs. En particulier, ne les utilisez jamais pour déterminer si oui ou non une personne est autorisée à accéder à certaines données.
Redirections
Au sein d’une fonction query
, form
ou prerender
, il est possible d’utiliser la fonction
redirect(...)
. Ce n’est pas possible au sein d’une fonction
command
, car vous devriez éviter de rediriger à cet endroit. (Si vous avez absolument besoin de le
faire, vous pouvez toujours renvoyer un objet { redirect: location }
et gérer la redirection côté
client.)
Modifier cette page sur Github llms.txt