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: booleanremoteFunctions: true
}
},
compilerOptions: {
experimental: {
async: boolean;
};
}
compilerOptions: {
experimental: {
async: boolean;
}
experimental: {
async: booleanasync: 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. peuvent être placés
n’importe où dans votre dossier src (sauf dans le dossier src/lib/server), et des librairies
externes peuvent également en fournir.
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/databaseet$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.sqlci-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 vv 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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (slug: stringslug) => {
const [const post: anypost] = await module "$lib/server/database"db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>sql`
SELECT * FROM post
WHERE slug = ${slug: stringslug}
`;
if (!const post: anypost) 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: anypost;
});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 vv 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 vv.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: anyw => [w: anyw.city, w: anyw]));
return (city: stringcity) => const lookup: Map<any, any>lookup.Map<any, any>.get(key: any): anyReturns 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: stringcity);
});<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 vv 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): neverRedirect 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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (slug: stringslug) => { /* ... */ });
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 vv.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 vv.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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), import vv.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 vv.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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), import vv.nonEmpty<string>(): v.NonEmptyAction<string, undefined> (+1 overload)
export nonEmpty
Creates a non-empty validation action.
nonEmpty())
}),
async ({ title: stringtitle, content: stringcontent }) => {
// Vérifie si l'utilisateur est loggué
const const user: auth.User | nulluser = 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 | nulluser) 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: stringslug = title: stringtitle.String.toLowerCase(): stringConverts 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: stringslug}, ${title: stringtitle}, ${content: stringcontent})
`;
// Redirige vers la page nouvellement créée
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): neverRedirect 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: stringslug}`);
}
)... 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...
L’attribut généré
nameutilise la notation d’objet JS (par ex.nested.array[0].value). Les clés exprimés en chaînes de caractères qui nécessitent des guillemets tels queobject['nested-array'][0].valuene sont pas supportées. Sous le capot, les noms de champs de type nombre et de type booléen (pour les checkbox) sont préfixés parb:etn:, respectivement, pour signaler à SvelteKit qu’il doit transformer les valeurs depuis des chaînes de caractères avant leur validation.
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 vv.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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
photo: v.FileSchema<undefined>photo: import vv.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 vv.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 vv.function number(): v.NumberSchema<undefined> (+1 overload)
export number
Creates a number schema.
number(),
likesDogs: v.OptionalSchema<v.BooleanSchema<undefined>, false>likesDogs: import vv.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 vv.function boolean(): v.BooleanSchema<undefined> (+1 overload)
export boolean
Creates a boolean schema.
boolean(), false)
}),
attributes: v.ArraySchema<v.StringSchema<undefined>, undefined>attributes: import vv.array<v.StringSchema<undefined>>(item: v.StringSchema<undefined>): v.ArraySchema<v.StringSchema<undefined>, undefined> (+1 overload)
export array
Creates an array schema.
array(import vv.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
checkboxest 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 vv.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 vv.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 vv.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 vv.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 vv.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
checkboxnon cochés, si aucune sélection n’est faite, alors les données serontundefined. Pour cette raison, le champlanguagesutilisev.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 vv 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 dbdb 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 vv.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 vv.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 vv.function number(): v.NumberSchema<undefined> (+1 overload)
export number
Creates a number schema.
number(),
import vv.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: anydata, invalid: anyinvalid) => {
try {
await import dbdb.buy(data: anydata.qty);
} catch (function (local var) e: unknowne) {
if (function (local var) e: unknowne.code === 'OUT_OF_STOCK') {
invalid: anyinvalid(
invalid: anyinvalid.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.tsou.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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (slug: stringslug) => { /* ... */ });
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 vv.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): neverRedirect 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 vv.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: anyresult = const externalApi: anyexternalApi.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: stringid).function set(value: void): voidOn 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: anyresult);
}
);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 vv.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: booleansuccess: 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
resultn’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[]): RemoteQueryOverrideTemporarily 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: PostnewPost, ...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
formlorsque 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 vv 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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (id: stringid) => {
const [const row: anyrow] = await module "$lib/server/database"db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>sql`
SELECT likes
FROM item
WHERE id = ${id: stringid}
`;
return const row: anyrow.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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (id: stringid) => {
await module "$lib/server/database"db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>sql`
UPDATE item
SET likes = likes + 1
WHERE id = ${id: stringid}
`;
});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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (id: stringid) => { /* ... */ });
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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (id: stringid) => {
await module "$lib/server/database"db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>sql`
UPDATE item
SET likes = likes + 1
WHERE id = ${id: stringid}
`;
const getLikes: (arg: string) => RemoteQuery<void>getLikes(id: stringid).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: Itemitem.Item.id: stringid).function updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<void>updates(const getLikes: (arg: string) => RemoteQuery<number>getLikes(const item: Itemitem.Item.id: stringid));
} catch (var error: unknownerror) {
function showToast(message: string): voidshowToast('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: Itemitem.Item.id: stringid).function updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<void>updates(
const getLikes: (arg: string) => RemoteQuery<number>getLikes(const item: Itemitem.Item.id: stringid).function withOverride(update: (current: number) => number): RemoteQueryOverrideTemporarily 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: numbern) => n: numbern + 1)
);
} catch (var error: unknownerror) {
function showToast(message: string): voidshowToast('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 vv 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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), async (slug: stringslug) => {
const [const post: anypost] = await module "$lib/server/database"db.function sql(strings: TemplateStringsArray, ...values: any[]): Promise<any[]>sql`
SELECT * FROM post
WHERE slug = ${slug: stringslug}
`;
if (!const post: anypost) 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: anypost;
});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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
async (slug: stringslug) => { /* ... */ },
{
inputs?: RemotePrerenderInputsGenerator<string> | undefinedinputs: () => [
'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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
async (slug: stringslug) => { /* ... */ },
{
inputs?: RemotePrerenderInputsGenerator<string> | undefinedinputs: () => [
'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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
async (slug: stringslug) => { /* ... */ },
{
dynamic?: boolean | undefineddynamic: true,
inputs?: RemotePrerenderInputsGenerator<string> | undefinedinputs: () => [
'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 vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(),
async (slug: stringslug) => { /* ... */ },
{
dynamic?: boolean | undefineddynamic: true,
inputs?: RemotePrerenderInputsGenerator<string> | undefinedinputs: () => [
'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: anyevent, issues: anyissues }) {
return {
message: stringmessage: '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: HandleValidationErrorhandleValidationError: 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: stringmessage: '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: stringid }: { id: stringid: 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(): RequestEventReturns 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 findUserfindUser } 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: anyuser = await const getUser: (arg: void) => RemoteQuery<any>getUser();
return {
name: anyname: const user: anyuser.name,
avatar: anyavatar: const user: anyuser.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(async () => {
const { const cookies: CookiesGet or set cookies related to the current request
cookies } = function getRequestEvent(): RequestEventReturns 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 findUserfindUser(const cookies: CookiesGet or set cookies related to the current request
cookies.Cookies.get: (name: string, opts?: CookieParseOptions) => string | undefinedGets 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
formetcommand) route,paramseturlsont 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