Skip to content

Commit 2fb4341

Browse files
committed
Exceptions throw in hooks are now handled properly by onError.
Fixes #292
1 parent 7c23d5c commit 2fb4341

File tree

5 files changed

+50
-11
lines changed

5 files changed

+50
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
- Tainted fields were set to undefined when not needed, unwantingly triggering client-side validation.
1717
- Schema transformations now updates the form data depending on input type. Checkboxes, radio buttons and selects updates the data immediately. Other inputs waits until blurred. ([#298](https://github.com/ciscoheat/sveltekit-superforms/issues/298))
1818
- In [SPA mode](https://superforms.rocks/concepts/spa), the `novalidate` attribute now only disables the browser validation constraints, not the entire client-side validation. ([#297](https://github.com/ciscoheat/sveltekit-superforms/discussions/297))
19+
- Exceptions throw in hooks are now handled properly by `onError`. Status will always be 500 though. ([#292](https://github.com/ciscoheat/sveltekit-superforms/issues/292))
1920

2021
## [1.11.0] - 2023-11-28
2122

src/hooks.server.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { error, type Handle } from '@sveltejs/kit';
2+
3+
export const handle: Handle = async ({ event, resolve }) => {
4+
if (
5+
event.request.method === 'POST' &&
6+
event.request.url.includes('?throw-hooks-error')
7+
) {
8+
throw error(403, {
9+
message: 'Hooks error'
10+
});
11+
}
12+
13+
return await resolve(event);
14+
};

src/lib/client/formEnhance.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import {
1313
import type { z, AnyZodObject } from 'zod';
1414
import { stringify } from 'devalue';
1515
import type { Entity } from '../schemaEntity.js';
16-
import type { FormOptions, SuperForm } from './index.js';
16+
import {
17+
defaultOnError,
18+
type FormOptions,
19+
type SuperForm
20+
} from './index.js';
1721
import { clientValidation, validateField } from './clientValidation.js';
1822
import { Form } from './form.js';
1923
import { onDestroy } from 'svelte';
@@ -423,7 +427,14 @@ export function formEnhance<T extends AnyZodObject, M>(
423427
}
424428

425429
async function validationResponse(event: ValidationResponse) {
426-
const result = event.result;
430+
// Check if an error was thrown in hooks, in which case it has no type.
431+
const result: ActionResult = event.result.type
432+
? event.result
433+
: {
434+
type: 'error',
435+
status: 500,
436+
error: event.result
437+
};
427438

428439
currentRequest = null;
429440
let cancelled = false;
@@ -505,8 +516,14 @@ export function formEnhance<T extends AnyZodObject, M>(
505516
if (options.onError !== 'apply') {
506517
const data = { result, message };
507518

508-
for (const event of formEvents.onError) {
509-
if (event !== 'apply') await event(data);
519+
for (const onErrorEvent of formEvents.onError) {
520+
if (
521+
onErrorEvent !== 'apply' &&
522+
(onErrorEvent != defaultOnError ||
523+
!options.flashMessage?.onError)
524+
) {
525+
await onErrorEvent(data);
526+
}
510527
}
511528
}
512529
}

src/lib/client/index.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ export type FormOptions<T extends ZodValidation<AnyZodObject>, M> = Partial<{
159159
};
160160
}>;
161161

162+
export const defaultOnError = (event: { result: { error: unknown } }) => {
163+
console.warn(
164+
'Unhandled Superform error, use onError event to handle it:',
165+
event.result.error
166+
);
167+
};
168+
162169
const defaultFormOptions = {
163170
applyAction: true,
164171
invalidateAll: true,
@@ -174,12 +181,7 @@ const defaultFormOptions = {
174181
onResult: undefined,
175182
onUpdate: undefined,
176183
onUpdated: undefined,
177-
onError: (event: { result: { error: unknown } }) => {
178-
console.warn(
179-
'Unhandled Superform error, use onError event to handle it:',
180-
event.result.error
181-
);
182-
},
184+
onError: defaultOnError,
183185
dataType: 'form',
184186
validators: undefined,
185187
defaultValidator: 'keep',

src/routes/tests/flash-onerror/+page.svelte

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import * as flashModule from 'sveltekit-flash-message/client';
55
import SuperDebug from '$lib/client/SuperDebug.svelte';
66
import { schema } from './schema';
7+
import { page } from '$app/stores';
78
89
export let data: PageData;
910
@@ -17,13 +18,17 @@
1718
}
1819
}
1920
});
21+
22+
$: action = $page.url.searchParams.has('throw-hooks-error')
23+
? '?throw-hooks-error'
24+
: '';
2025
</script>
2126

2227
<SuperDebug data={{ $form, $errors, $tainted }} />
2328

2429
{#if $message}<h4>{$message}</h4>{/if}
2530

26-
<form method="POST" use:enhance>
31+
<form method="POST" {action} use:enhance>
2732
<label>
2833
Name: <input name="name" bind:value={$form.name} />
2934
{#if $errors.name}<span class="invalid">{$errors.name}</span>{/if}

0 commit comments

Comments
 (0)