@@ -51,27 +51,32 @@ export function useSubmission<T extends Array<any>, U>(
51
51
}
52
52
53
53
export function useAction < T extends Array < any > , U > ( action : Action < T , U > ) {
54
- const router = useRouter ( ) ;
55
- return ( ...args : Parameters < Action < T , U > > ) => action . apply ( router , args ) ;
54
+ const r = useRouter ( ) ;
55
+ return ( ...args : Parameters < Action < T , U > > ) => action . apply ( { r } , args ) ;
56
56
}
57
57
58
58
export function action < T extends Array < any > , U = void > (
59
59
fn : ( ...args : T ) => Promise < U > ,
60
60
name ?: string
61
61
) : Action < T , U > {
62
- function mutate ( this : RouterContext , ...variables : T ) {
63
- const router = this ;
62
+ function mutate ( this : { r : RouterContext , f ?: HTMLFormElement } , ...variables : T ) {
63
+ const router = this . r ;
64
+ const form = this . f ;
64
65
const p = (
65
66
router . singleFlight && ( fn as any ) . withOptions
66
67
? ( fn as any ) . withOptions ( { headers : { "X-Single-Flight" : "true" } } )
67
68
: fn
68
69
) ( ...variables ) ;
69
- const [ result , setResult ] = createSignal < { data ?: U } > ( ) ;
70
+ const [ result , setResult ] = createSignal < { data ?: U , error ?: any } > ( ) ;
70
71
let submission : Submission < T , U > ;
71
- async function handler ( res : any ) {
72
- const data = await handleResponse ( res as any , router . navigatorFactory ( ) ) ;
73
- data ? setResult ( { data } ) : submission . clear ( ) ;
74
- return data ;
72
+ function handler ( error ?: boolean ) {
73
+ return async ( res : any ) => {
74
+ const result = await handleResponse ( res , error , router . navigatorFactory ( ) ) ;
75
+ if ( ! result ) return submission . clear ( ) ;
76
+ setResult ( result ) ;
77
+ if ( result . error && ! form ) throw result . error ;
78
+ return result . data ;
79
+ } ;
75
80
}
76
81
router . submissions [ 1 ] ( s => [
77
82
...s ,
@@ -81,6 +86,9 @@ export function action<T extends Array<any>, U = void>(
81
86
get result ( ) {
82
87
return result ( ) ?. data ;
83
88
} ,
89
+ get error ( ) {
90
+ return result ( ) ?. error ;
91
+ } ,
84
92
get pending ( ) {
85
93
return ! result ( ) ;
86
94
} ,
@@ -90,11 +98,11 @@ export function action<T extends Array<any>, U = void>(
90
98
retry ( ) {
91
99
setResult ( undefined ) ;
92
100
const p = fn ( ...variables ) ;
93
- return p . then ( handler , handler ) ;
101
+ return p . then ( handler ( ) , handler ( true ) ) ;
94
102
}
95
103
} )
96
104
] ) ;
97
- return p . then ( handler , handler ) ;
105
+ return p . then ( handler ( ) , handler ( true ) ) ;
98
106
}
99
107
100
108
const url : string =
@@ -134,7 +142,7 @@ function toAction<T extends Array<any>, U>(fn: Function, url: string): Action<T,
134
142
const hashString = ( s : string ) =>
135
143
s . split ( "" ) . reduce ( ( a , b ) => ( ( a << 5 ) - a + b . charCodeAt ( 0 ) ) | 0 , 0 ) ;
136
144
137
- async function handleResponse ( response : Response , navigate : Navigator ) {
145
+ async function handleResponse ( response : unknown , error : boolean | undefined , navigate : Navigator ) {
138
146
let data : any ;
139
147
let keys : string [ ] | undefined ;
140
148
let invalidateKeys : string [ ] | undefined ;
@@ -162,10 +170,11 @@ async function handleResponse(response: Response, navigate: Navigator) {
162
170
navigate ( locationUrl ) ;
163
171
}
164
172
}
165
- } else data = response ;
173
+ } else if ( error ) return { error : response } ;
174
+ else data = response ;
166
175
// invalidate
167
176
cacheKeyOp ( invalidateKeys , entry => ( entry [ 0 ] = 0 ) ) ;
168
177
// trigger revalidation
169
178
await revalidate ( keys , false ) ;
170
- return data ;
179
+ return data != null ? { data } : undefined ;
171
180
}