@@ -334,10 +334,7 @@ const initialForms = new WeakMap<
334334> ( ) ;
335335
336336const defaultOnError = ( event : { result : { error : unknown } } ) => {
337- console . warn (
338- 'Unhandled error caught by Superforms, use onError event to handle it:' ,
339- event . result . error
340- ) ;
337+ throw event . result . error ;
341338} ;
342339
343340const defaultFormOptions = {
@@ -660,6 +657,16 @@ export function superForm<
660657 return options . SPA === true || typeof options . SPA === 'object' ;
661658 }
662659
660+ function Form_errorStatus ( defaultStatus ?: number ) {
661+ return (
662+ defaultStatus ||
663+ ( typeof options . SPA === 'boolean' || typeof options . SPA === 'string'
664+ ? undefined
665+ : options . SPA ?. failStatus ) ||
666+ 500
667+ ) ;
668+ }
669+
663670 async function Form_validate (
664671 opts : {
665672 adapter ?: FormOptions < T , M > [ 'validators' ] ;
@@ -1633,11 +1640,7 @@ export function superForm<
16331640 function clientValidationResult ( validation : SuperFormValidated < T , M , In > ) {
16341641 const validationResult = { ...validation , posted : true } ;
16351642
1636- const status = validationResult . valid
1637- ? 200
1638- : ( ( typeof options . SPA === 'boolean' || typeof options . SPA === 'string'
1639- ? undefined
1640- : options . SPA ?. failStatus ) ?? 400 ) ;
1643+ const status = validationResult . valid ? 200 : Form_errorStatus ( ) ;
16411644
16421645 const data = { form : validationResult } ;
16431646
@@ -1665,6 +1668,46 @@ export function superForm<
16651668 }
16661669 }
16671670
1671+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1672+ async function triggerOnError ( result : { type : 'error' ; status ?: number ; error : any } ) {
1673+ if ( options . applyAction ) {
1674+ if ( options . onError == 'apply' ) {
1675+ await applyAction ( result ) ;
1676+ } else {
1677+ // Transform to failure, to avoid data loss
1678+ // Set the data to the error result, so it will be
1679+ // picked up in page.subscribe in superForm.
1680+ const failResult = {
1681+ type : 'failure' ,
1682+ status : Form_errorStatus ( Math . floor ( result . status ?? NaN ) ) ,
1683+ data : result
1684+ } as const ;
1685+ await applyAction ( failResult ) ;
1686+ }
1687+ }
1688+
1689+ // Check if the error message should be replaced
1690+ if ( options . onError !== 'apply' ) {
1691+ const data = { result, message : Message } ;
1692+
1693+ for ( const onErrorEvent of formEvents . onError ) {
1694+ if (
1695+ onErrorEvent !== 'apply' &&
1696+ ( onErrorEvent != defaultOnError || ! options . flashMessage ?. onError )
1697+ ) {
1698+ await onErrorEvent ( data ) ;
1699+ }
1700+ }
1701+ }
1702+
1703+ if ( options . flashMessage && options . flashMessage . onError ) {
1704+ await options . flashMessage . onError ( {
1705+ result,
1706+ flashMessage : options . flashMessage . module . getFlash ( page )
1707+ } ) ;
1708+ }
1709+ }
1710+
16681711 function cancel (
16691712 opts : { resetTimers ?: boolean } = {
16701713 resetTimers : true
@@ -1689,7 +1732,12 @@ export function superForm<
16891732 currentRequest = submit . controller ;
16901733
16911734 for ( const event of formEvents . onSubmit ) {
1692- await event ( submit ) ;
1735+ try {
1736+ await event ( submit ) ;
1737+ } catch ( error ) {
1738+ cancel ( ) ;
1739+ triggerOnError ( { type : 'error' , error, status : Form_errorStatus ( ) } ) ;
1740+ }
16931741 }
16941742 }
16951743
@@ -1821,7 +1869,7 @@ export function superForm<
18211869 ? ( event . result as ActionResult )
18221870 : {
18231871 type : 'error' ,
1824- status : parseInt ( String ( event . result . status ) ) || 500 ,
1872+ status : Form_errorStatus ( parseInt ( String ( event . result . status ) ) ) ,
18251873 error : event . result . error instanceof Error ? event . result . error : event . result
18261874 } ;
18271875
@@ -1843,15 +1891,27 @@ export function superForm<
18431891 cancel ( ) ;
18441892 } ) ;
18451893
1894+ function setErrorResult ( error : unknown , data : { result : ActionResult } ) {
1895+ data . result = {
1896+ type : 'error' ,
1897+ error,
1898+ status : result . status && result . status >= 400 ? result . status : Form_errorStatus ( )
1899+ } ;
1900+ }
1901+
18461902 for ( const event of formEvents . onResult ) {
1847- await event ( data ) ;
1903+ try {
1904+ await event ( data ) ;
1905+ } catch ( error ) {
1906+ setErrorResult ( error , data ) ;
1907+ }
18481908 }
18491909
18501910 // In case it was modified in the event
18511911 result = data . result ;
18521912
18531913 if ( ! cancelled ) {
1854- if ( ( result . type === 'success' || result . type == 'failure' ) && result . data ) {
1914+ if ( ( result . type === 'success' || result . type === 'failure' ) && result . data ) {
18551915 const forms = Context_findValidationForms ( result . data ) ;
18561916 if ( ! forms . length ) {
18571917 throw new SuperFormError (
@@ -1871,7 +1931,11 @@ export function superForm<
18711931 } ;
18721932
18731933 for ( const event of formEvents . onUpdate ) {
1874- await event ( data ) ;
1934+ try {
1935+ await event ( data ) ;
1936+ } catch ( error ) {
1937+ setErrorResult ( error , data ) ;
1938+ }
18751939 }
18761940
18771941 // In case it was modified in the event
@@ -1907,46 +1971,7 @@ export function superForm<
19071971 await Form_updateFromActionResult ( result ) ;
19081972 }
19091973 } else {
1910- // Error result
1911- if ( options . applyAction ) {
1912- if ( options . onError == 'apply' ) {
1913- await applyAction ( result ) ;
1914- } else {
1915- // Transform to failure, to avoid data loss
1916- // Set the data to the error result, so it will be
1917- // picked up in page.subscribe in superForm.
1918- const failResult = {
1919- type : 'failure' ,
1920- status : Math . floor ( result . status || 500 ) ,
1921- data : result
1922- } as const ;
1923- await applyAction ( failResult ) ;
1924- }
1925- }
1926-
1927- // Check if the error message should be replaced
1928- if ( options . onError !== 'apply' ) {
1929- const data = { result, message : Message } ;
1930-
1931- for ( const onErrorEvent of formEvents . onError ) {
1932- if (
1933- onErrorEvent !== 'apply' &&
1934- ( onErrorEvent != defaultOnError || ! options . flashMessage ?. onError )
1935- ) {
1936- await onErrorEvent ( data ) ;
1937- }
1938- }
1939- }
1940- }
1941-
1942- // Trigger flash message event if there was an error
1943- if ( options . flashMessage ) {
1944- if ( result . type == 'error' && options . flashMessage . onError ) {
1945- await options . flashMessage . onError ( {
1946- result,
1947- flashMessage : options . flashMessage . module . getFlash ( page )
1948- } ) ;
1949- }
1974+ await triggerOnError ( result ) ;
19501975 }
19511976 }
19521977 }
0 commit comments