@@ -76,6 +76,7 @@ export function actionBuilder<
76
76
let prevResult : PrevResult | undefined = undefined ;
77
77
const valFn = args . validationStrategy === "zod" ? zodValidate : validate ;
78
78
const parsedInputDatas : any [ ] = [ ] ;
79
+ let frameworkError : Error | null = null ;
79
80
80
81
if ( withState ) {
81
82
// Previous state is placed between bind args and main arg inputs, so it's always at the index of
@@ -93,6 +94,10 @@ export function actionBuilder<
93
94
94
95
// Execute the middleware stack.
95
96
const executeMiddlewareStack = async ( idx = 0 ) => {
97
+ if ( frameworkError ) {
98
+ return ;
99
+ }
100
+
96
101
const middlewareFn = args . middlewareFns [ idx ] ;
97
102
middlewareResult . ctx = prevCtx ;
98
103
@@ -213,8 +218,8 @@ export function actionBuilder<
213
218
// processed internally by Next.js.
214
219
if ( isRedirectError ( e ) || isNotFoundError ( e ) ) {
215
220
middlewareResult . success = true ;
216
- // If an internal framework error occurred, throw it, so it will be processed by Next.js.
217
- throw e ;
221
+ frameworkError = e ;
222
+ return ;
218
223
}
219
224
220
225
// If error is `ActionServerValidationError`, return `validationErrors` as if schema validation would fail.
@@ -242,10 +247,30 @@ export function actionBuilder<
242
247
// Execute middleware chain + action function.
243
248
await executeMiddlewareStack ( ) ;
244
249
245
- const actionResult : SafeActionResult < ServerError , S , BAS , CVE , CBAVE , Data > = { } ;
250
+ // If an internal framework error occurred, throw it, so it will be processed by Next.js.
251
+ if ( frameworkError ) {
252
+ await Promise . resolve (
253
+ cb ?. onSuccess ?.( {
254
+ data : undefined ,
255
+ clientInput : clientInputs . at ( - 1 ) as S extends Schema ? InferIn < S > : undefined ,
256
+ bindArgsClientInputs : ( bindArgsSchemas . length ? clientInputs . slice ( 0 , - 1 ) : [ ] ) as InferInArray < BAS > ,
257
+ parsedInput : parsedInputDatas . at ( - 1 ) as S extends Schema ? Infer < S > : undefined ,
258
+ bindArgsParsedInputs : parsedInputDatas . slice ( 0 , - 1 ) as InferArray < BAS > ,
259
+ } )
260
+ ) ;
246
261
247
- // This flag is needed because `onSuccess` callback is triggered even when there's no result data.
248
- let hasError = true ;
262
+ await Promise . resolve (
263
+ cb ?. onSettled ?.( {
264
+ clientInput : clientInputs . at ( - 1 ) as S extends Schema ? InferIn < S > : undefined ,
265
+ bindArgsClientInputs : ( bindArgsSchemas . length ? clientInputs . slice ( 0 , - 1 ) : [ ] ) as InferInArray < BAS > ,
266
+ result : { } ,
267
+ } )
268
+ ) ;
269
+
270
+ throw frameworkError ;
271
+ }
272
+
273
+ const actionResult : SafeActionResult < ServerError , S , BAS , CVE , CBAVE , Data > = { } ;
249
274
250
275
if ( typeof middlewareResult . validationErrors !== "undefined" ) {
251
276
actionResult . validationErrors = middlewareResult . validationErrors as CVE ;
@@ -259,17 +284,7 @@ export function actionBuilder<
259
284
actionResult . serverError = middlewareResult . serverError ;
260
285
}
261
286
262
- hasError = false ;
263
-
264
- if ( hasError ) {
265
- await Promise . resolve (
266
- cb ?. onError ?.( {
267
- clientInput : clientInputs . at ( - 1 ) as S extends Schema ? InferIn < S > : undefined ,
268
- bindArgsClientInputs : ( bindArgsSchemas . length ? clientInputs . slice ( 0 , - 1 ) : [ ] ) as InferInArray < BAS > ,
269
- error : actionResult ,
270
- } )
271
- ) ;
272
- } else {
287
+ if ( middlewareResult . success ) {
273
288
if ( typeof middlewareResult . data !== "undefined" ) {
274
289
actionResult . data = middlewareResult . data as Data ;
275
290
}
@@ -283,6 +298,14 @@ export function actionBuilder<
283
298
bindArgsParsedInputs : parsedInputDatas . slice ( 0 , - 1 ) as InferArray < BAS > ,
284
299
} )
285
300
) ;
301
+ } else {
302
+ await Promise . resolve (
303
+ cb ?. onError ?.( {
304
+ clientInput : clientInputs . at ( - 1 ) as S extends Schema ? InferIn < S > : undefined ,
305
+ bindArgsClientInputs : ( bindArgsSchemas . length ? clientInputs . slice ( 0 , - 1 ) : [ ] ) as InferInArray < BAS > ,
306
+ error : actionResult ,
307
+ } )
308
+ ) ;
286
309
}
287
310
288
311
// onSettled, if provided, is always executed.
0 commit comments