Skip to content

Commit f209452

Browse files
Sync kit docs (#1677)
sync kit docs Co-authored-by: svelte-docs-bot[bot] <196124396+svelte-docs-bot[bot]@users.noreply.github.com>
1 parent bc297db commit f209452

File tree

3 files changed

+117
-20
lines changed

3 files changed

+117
-20
lines changed

apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,11 +455,12 @@ Alternatively, you could use `select` and `select multiple`:
455455
456456
### Programmatic validation
457457
458-
In addition to declarative schema validation, you can programmatically mark fields as invalid inside the form handler using the `invalid` function. This is useful for cases where you can't know if something is valid until you try to perform some action:
458+
In addition to declarative schema validation, you can programmatically mark fields as invalid inside the form handler using the `invalid` function. This is useful for cases where you can't know if something is valid until you try to perform some action. Just like `redirect` or `error`, `invalid` throws. It expects a list of strings (for issues relating to the form as a whole) or standard-schema-compliant issues (for those relating to a specific field). Use the `issue` parameter for type-safe creation of such issues:
459459
460460
```js
461461
/// file: src/routes/shop/data.remote.js
462462
import * as v from 'valibot';
463+
import { invalid } from '@sveltejs/kit';
463464
import { form } from '$app/server';
464465
import * as db from '$lib/server/database';
465466

@@ -470,13 +471,13 @@ export const buyHotcakes = form(
470471
v.minValue(1, 'you must buy at least one hotcake')
471472
)
472473
}),
473-
async (data, invalid) => {
474+
async (data, issue) => {
474475
try {
475476
await db.buy(data.qty);
476477
} catch (e) {
477478
if (e.code === 'OUT_OF_STOCK') {
478479
invalid(
479-
invalid.qty(`we don't have enough hotcakes`)
480+
issue.qty(`we don't have enough hotcakes`)
480481
);
481482
}
482483
}

apps/svelte.dev/content/docs/kit/98-reference/[email protected]

Lines changed: 110 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import {
1212
VERSION,
1313
error,
1414
fail,
15+
invalid,
1516
isActionFailure,
1617
isHttpError,
1718
isRedirect,
19+
isValidationError,
1820
json,
1921
normalizeUrl,
2022
redirect,
@@ -128,6 +130,48 @@ function fail<T = undefined>(
128130

129131

130132

133+
## invalid
134+
135+
<blockquote class="since note">
136+
137+
Available since 2.47.3
138+
139+
</blockquote>
140+
141+
Use this to throw a validation error to imperatively fail form validation.
142+
Can be used in combination with `issue` passed to form actions to create field-specific issues.
143+
144+
```ts
145+
import { invalid } from '@sveltejs/kit';
146+
import { form } from '$app/server';
147+
import { tryLogin } from '$lib/server/auth';
148+
import * as v from 'valibot';
149+
150+
export const login = form(
151+
v.object({ name: v.string(), _password: v.string() }),
152+
async ({ name, _password }) => {
153+
const success = tryLogin(name, _password);
154+
if (!success) {
155+
invalid('Incorrect username or password');
156+
}
157+
158+
// ...
159+
}
160+
);
161+
```
162+
163+
<div class="ts-block">
164+
165+
```dts
166+
function invalid(
167+
...issues: (StandardSchemaV1.Issue | string)[]
168+
): never;
169+
```
170+
171+
</div>
172+
173+
174+
131175
## isActionFailure
132176

133177
Checks whether this is an action failure thrown by `fail`.
@@ -175,6 +219,26 @@ function isRedirect(e: unknown): e is Redirect_1;
175219

176220

177221

222+
## isValidationError
223+
224+
<blockquote class="since note">
225+
226+
Available since 2.47.3
227+
228+
</blockquote>
229+
230+
Checks whether this is an validation error thrown by `invalid`.
231+
232+
<div class="ts-block">
233+
234+
```dts
235+
function isValidationError(e: unknown): e is ActionFailure;
236+
```
237+
238+
</div>
239+
240+
241+
178242
## json
179243

180244
Create a JSON `Response` object from the supplied data.
@@ -1253,22 +1317,37 @@ The content of the error.
12531317
</div>
12541318
</div></div>
12551319

1256-
## Invalid
1320+
## InvalidField
12571321

12581322
A function and proxy object used to imperatively create validation errors in form handlers.
12591323

1260-
Call `invalid(issue1, issue2, ...issueN)` to throw a validation error.
1261-
If an issue is a `string`, it applies to the form as a whole (and will show up in `fields.allIssues()`)
1262-
Access properties to create field-specific issues: `invalid.fieldName('message')`.
1324+
Access properties to create field-specific issues: `issue.fieldName('message')`.
12631325
The type structure mirrors the input data structure for type-safe field access.
1326+
Call `invalid(issue.foo(...), issue.nested.bar(...))` to throw a validation error.
12641327

12651328
<div class="ts-block">
12661329

12671330
```dts
1268-
type Invalid<Input = any> = ((
1269-
...issues: Array<string | StandardSchemaV1.Issue>
1270-
) => never) &
1271-
InvalidField<Input>;
1331+
type InvalidField<T> =
1332+
WillRecurseIndefinitely<T> extends true
1333+
? Record<string | number, any>
1334+
: NonNullable<T> extends
1335+
| string
1336+
| number
1337+
| boolean
1338+
| File
1339+
? (message: string) => StandardSchemaV1.Issue
1340+
: NonNullable<T> extends Array<infer U>
1341+
? {
1342+
[K in number]: InvalidField<U>;
1343+
} & ((message: string) => StandardSchemaV1.Issue)
1344+
: NonNullable<T> extends RemoteFormInput
1345+
? {
1346+
[K in keyof T]-?: InvalidField<T[K]>;
1347+
} & ((
1348+
message: string
1349+
) => StandardSchemaV1.Issue)
1350+
: Record<string, never>;
12721351
```
12731352

12741353
</div>
@@ -2361,8 +2440,6 @@ type RemoteForm<
23612440
includeUntouched?: boolean;
23622441
/** Set this to `true` to only run the `preflight` validation. */
23632442
preflightOnly?: boolean;
2364-
/** Perform validation as if the form was submitted by the given button. */
2365-
submitter?: HTMLButtonElement | HTMLInputElement;
23662443
}): Promise<void>;
23672444
/** The result of the form submission */
23682445
get result(): Output | undefined;
@@ -3641,6 +3718,29 @@ decode: (data: U) => T;
36413718
<div class="ts-block-property-details"></div>
36423719
</div></div>
36433720

3721+
## ValidationError
3722+
3723+
A validation error thrown by `invalid`.
3724+
3725+
<div class="ts-block">
3726+
3727+
```dts
3728+
interface ValidationError {/*…*/}
3729+
```
3730+
3731+
<div class="ts-block-property">
3732+
3733+
```dts
3734+
issues: StandardSchemaV1.Issue[];
3735+
```
3736+
3737+
<div class="ts-block-property-details">
3738+
3739+
The validation issues
3740+
3741+
</div>
3742+
</div></div>
3743+
36443744

36453745

36463746
## Private types

apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,7 @@ See [Remote functions](/docs/kit/remote-functions#form) for full documentation.
8282

8383
```dts
8484
function form<Output>(
85-
fn: (
86-
invalid: import('@sveltejs/kit').Invalid<void>
87-
) => MaybePromise<Output>
85+
fn: () => MaybePromise<Output>
8886
): RemoteForm<void, Output>;
8987
```
9088

@@ -97,7 +95,7 @@ function form<Input extends RemoteFormInput, Output>(
9795
validate: 'unchecked',
9896
fn: (
9997
data: Input,
100-
invalid: import('@sveltejs/kit').Invalid<Input>
98+
issue: InvalidField<Input>
10199
) => MaybePromise<Output>
102100
): RemoteForm<Input, Output>;
103101
```
@@ -117,9 +115,7 @@ function form<
117115
validate: Schema,
118116
fn: (
119117
data: StandardSchemaV1.InferOutput<Schema>,
120-
invalid: import('@sveltejs/kit').Invalid<
121-
StandardSchemaV1.InferInput<Schema>
122-
>
118+
issue: InvalidField<StandardSchemaV1.InferInput<Schema>>
123119
) => MaybePromise<Output>
124120
): RemoteForm<StandardSchemaV1.InferInput<Schema>, Output>;
125121
```

0 commit comments

Comments
 (0)