Skip to content

Commit d8d5172

Browse files
committed
Added JS Error class to onError event.result.error
1 parent 0a0d67b commit d8d5172

File tree

8 files changed

+75
-38
lines changed

8 files changed

+75
-38
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
### Fixed
1515

16-
- the `event.error` signature in [onError](https://superforms.rocks/concepts/events#onerror) was incorrect, it doesn't always include `App.Error`. It is now a union between `App.Error` and its default SvelteKit signature, `{ message: string }`.
16+
- the `event.result.error` signature in [onError](https://superforms.rocks/concepts/events#onerror) was incorrect, it doesn't always match `App.Error`. It is now a union between `App.Error`, The built-in JS `Error` class, and the default App.Error signature `{ message: string }`.
1717

1818
## [2.10.5] - 2024-03-18
1919

src/lib/client/superForm.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export type FormOptions<
126126
result: {
127127
type: 'error';
128128
status?: number;
129-
error: App.Error | { message: string };
129+
error: App.Error | Error | { message: string };
130130
};
131131
}) => MaybePromise<unknown | void>);
132132
onChange: (event: ChangeEvent<T>) => void;
@@ -270,16 +270,6 @@ export type ValidateOptions<
270270
schema: ValidationAdapter<Out, In>;
271271
}>;
272272

273-
type ValidationResponse<
274-
Success extends Record<string, unknown> | undefined = Record<
275-
string,
276-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
277-
any
278-
>,
279-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
280-
Invalid extends Record<string, unknown> | undefined = Record<string, any>
281-
> = { result: ActionResult<Success, Invalid> };
282-
283273
export type ChangeEvent<T extends Record<string, unknown>> =
284274
| {
285275
path: FormPath<T>;
@@ -1744,18 +1734,21 @@ export function superForm<
17441734
return chunks;
17451735
}
17461736

1747-
async function validationResponse(event: ValidationResponse) {
1737+
// event can be a record if an external request was returning JSON,
1738+
// or if it failed parsing the expected JSON.
1739+
async function validationResponse(event: { result: Record<string, unknown> }) {
17481740
let cancelled = false;
17491741
currentRequest = null;
17501742

17511743
// Check if an error was thrown in hooks, in which case it has no type.
1752-
let result: ActionResult = event.result.type
1753-
? event.result
1754-
: {
1755-
type: 'error',
1756-
status: 500,
1757-
error: event.result
1758-
};
1744+
let result: ActionResult =
1745+
'type' in event.result && 'status' in event.result
1746+
? (event.result as ActionResult)
1747+
: {
1748+
type: 'error',
1749+
status: parseInt(String(event.result.status)) || 500,
1750+
error: event.result.error instanceof Error ? event.result.error : event.result
1751+
};
17591752

17601753
const cancel = () => (cancelled = true);
17611754

src/routes/(v2)/v2/Navigation.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
'tainted-history',
5555
'files-proxy',
5656
'tainted-array',
57-
'spa-clearonsubmit'
57+
'spa-clearonsubmit',
58+
'app-error'
5859
].sort();
5960
</script>
6061

src/routes/(v2)/v2/app-error/+page.server.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { error, fail } from '@sveltejs/kit';
55

66
export const load = async () => {
77
const form = await superValidate({ name: 'some name' }, zod(userSchema));
8-
98
return { form };
109
};
1110

@@ -18,11 +17,14 @@ export const actions = {
1817
return fail(400, { form });
1918
}
2019

21-
if (form.data.exception) {
22-
throw new Error('test-error');
23-
} else {
24-
// @ts-expect-error Does not follow the App.Error shape
25-
error(502, { code: 'expected', title: 'Error title', message: 'Error' });
20+
switch (form.data.exception) {
21+
case 'error':
22+
// @ts-expect-error Does not follow the App.Error shape
23+
error(502, { code: 'expected', title: 'Error title', message: 'Error' });
24+
break;
25+
26+
case 'exception':
27+
throw new Error('test-error');
2628
}
2729
}
2830
};
Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,56 @@
11
<script lang="ts">
2-
import { defaults, superForm } from '$lib/index.js';
3-
import { userSchema } from './schema.js';
4-
import { zod } from '$lib/adapters/zod.js';
2+
import { page } from '$app/stores';
3+
import SuperDebug from '$lib/client/SuperDebug.svelte';
4+
import { superForm } from '$lib/index.js';
55
6-
const formData = defaults({ name: 'First name' }, zod(userSchema));
6+
export let data;
77
88
let error: string;
99
10-
export const spForm = superForm(formData, {
10+
export const spForm = superForm(data.form, {
1111
onError: (e) => {
12-
console.log(e.result.error);
12+
console.log(e.result);
1313
// @ts-expect-error Does not follow the App.Error shape
1414
error = 'code' in e.result.error ? e.result.error.code : e.result.error.message;
1515
}
1616
});
1717
1818
const { enhance, form } = spForm;
19+
20+
$: action =
21+
$form.exception == 'json'
22+
? '/v2/app-error/json'
23+
: $form.exception == 'plain'
24+
? '/v2/app-error/plain'
25+
: undefined;
26+
27+
// eslint-disable-next-line svelte/valid-compile
28+
$page;
1929
</script>
2030

21-
<p id="error">ERROR:{error}</p>
31+
<SuperDebug data={$form} />
32+
33+
<p id="error">ERROR:{error}:{$page.status}</p>
2234

23-
<form use:enhance method="POST">
24-
<input name="name" bind:value={$form.name} />
35+
<form method="POST" use:enhance {action}>
36+
Name: <input name="name" bind:value={$form.name} />
37+
<ul style="list-style-type:none">
38+
<li>
39+
<input type="radio" name="exception" value="error" bind:group={$form.exception} /> SvelteKit error
40+
(502)
41+
</li>
42+
<li>
43+
<input type="radio" name="exception" value="exception" bind:group={$form.exception} /> Exception
44+
(500)
45+
</li>
46+
<li>
47+
<input type="radio" name="exception" value="json" bind:group={$form.exception} /> 430 JSON response,
48+
with 429 status (429)
49+
</li>
50+
<li>
51+
<input type="radio" name="exception" value="plain" bind:group={$form.exception} /> 417 error response
52+
(500)
53+
</li>
54+
</ul>
2555
<button type="submit">Save</button>
26-
<br /><input type="checkbox" name="exception" bind:checked={$form.exception} /> Throw exception
2756
</form>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { json } from '@sveltejs/kit';
2+
import type { RequestHandler } from './$types.js';
3+
4+
export const POST: RequestHandler = async () => {
5+
return json({ code: 'rate_limited', status: 429 }, { status: 430 });
6+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { text } from '@sveltejs/kit';
2+
import type { RequestHandler } from './$types.js';
3+
4+
export const POST: RequestHandler = async () => {
5+
return text('Nope', { status: 417 });
6+
};

src/routes/(v2)/v2/app-error/schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import { z } from 'zod';
22

33
export const userSchema = z.object({
44
name: z.string(),
5-
exception: z.boolean()
5+
exception: z.enum(['error', 'exception', 'json', 'plain'])
66
});

0 commit comments

Comments
 (0)