@@ -12,13 +12,7 @@ import type {
12
12
ServerCodeFn ,
13
13
StateServerCodeFn ,
14
14
} from "./index.types" ;
15
- import {
16
- isForbiddenError ,
17
- isFrameworkError ,
18
- isNotFoundError ,
19
- isRedirectError ,
20
- isUnauthorizedError ,
21
- } from "./next/errors" ;
15
+ import { FrameworkErrorHandler } from "./next/errors" ;
22
16
import { DEFAULT_SERVER_ERROR_MESSAGE , isError , winningBoolean } from "./utils" ;
23
17
import {
24
18
ActionMetadataValidationError ,
@@ -87,7 +81,7 @@ export function actionBuilder<
87
81
type PrevResult = SafeActionResult < ServerError , IS , BAS , CVE , CBAVE , Data > | undefined ;
88
82
let prevResult : PrevResult | undefined = undefined ;
89
83
const parsedInputDatas : any [ ] = [ ] ;
90
- let frameworkError : Error | null = null ;
84
+ const frameworkErrorHandler = new FrameworkErrorHandler ( ) ;
91
85
92
86
if ( withState ) {
93
87
// Previous state is placed between bind args and main arg inputs, so it's always at the index of
@@ -105,7 +99,7 @@ export function actionBuilder<
105
99
106
100
// Execute the middleware stack.
107
101
const executeMiddlewareStack = async ( idx = 0 ) => {
108
- if ( frameworkError ) {
102
+ if ( frameworkErrorHandler . error ) {
109
103
return ;
110
104
}
111
105
@@ -136,7 +130,7 @@ export function actionBuilder<
136
130
await executeMiddlewareStack ( idx + 1 ) ;
137
131
return middlewareResult ;
138
132
} ,
139
- } ) ;
133
+ } ) . catch ( ( e ) => frameworkErrorHandler . handleError ( e ) ) ;
140
134
// Action function.
141
135
} else {
142
136
// Validate the client inputs in parallel.
@@ -236,10 +230,10 @@ export function actionBuilder<
236
230
scfArgs [ 1 ] = { prevResult : structuredClone ( prevResult ! ) } ;
237
231
}
238
232
239
- const data = await serverCodeFn ( ...scfArgs ) ;
233
+ const data = await serverCodeFn ( ...scfArgs ) . catch ( ( e ) => frameworkErrorHandler . handleError ( e ) ) ;
240
234
241
235
// If a `outputSchema` is passed, validate the action return value.
242
- if ( typeof args . outputSchema !== "undefined" ) {
236
+ if ( typeof args . outputSchema !== "undefined" && ! frameworkErrorHandler . error ) {
243
237
const parsedData = await args . validationAdapter . validate ( args . outputSchema , data ) ;
244
238
245
239
if ( ! parsedData . success ) {
@@ -253,14 +247,6 @@ export function actionBuilder<
253
247
middlewareResult . bindArgsParsedInputs = parsedInputDatas . slice ( 0 , - 1 ) ;
254
248
}
255
249
} catch ( e : unknown ) {
256
- // next/navigation functions work by throwing an error that will be
257
- // processed internally by Next.js.
258
- if ( isFrameworkError ( e ) ) {
259
- middlewareResult . success = true ;
260
- frameworkError = e ;
261
- return ;
262
- }
263
-
264
250
// If error is `ActionServerValidationError`, return `validationErrors` as if schema validation would fail.
265
251
if ( e instanceof ActionServerValidationError ) {
266
252
const ve = e . validationErrors as ValidationErrors < IS > ;
@@ -298,7 +284,7 @@ export function actionBuilder<
298
284
const callbackPromises : ( Promise < unknown > | undefined ) [ ] = [ ] ;
299
285
300
286
// If an internal framework error occurred, throw it, so it will be processed by Next.js.
301
- if ( frameworkError ) {
287
+ if ( frameworkErrorHandler . error ) {
302
288
callbackPromises . push (
303
289
utils ?. onSuccess ?.( {
304
290
data : undefined ,
@@ -308,10 +294,10 @@ export function actionBuilder<
308
294
bindArgsClientInputs : ( bindArgsSchemas . length ? clientInputs . slice ( 0 , - 1 ) : [ ] ) as InferInArray < BAS > ,
309
295
parsedInput : parsedInputDatas . at ( - 1 ) as IS extends Schema ? Infer < IS > : undefined ,
310
296
bindArgsParsedInputs : parsedInputDatas . slice ( 0 , - 1 ) as InferArray < BAS > ,
311
- hasRedirected : isRedirectError ( frameworkError ) ,
312
- hasNotFound : isNotFoundError ( frameworkError ) ,
313
- hasForbidden : isForbiddenError ( frameworkError ) ,
314
- hasUnauthorized : isUnauthorizedError ( frameworkError ) ,
297
+ hasRedirected : frameworkErrorHandler . isRedirectError ,
298
+ hasNotFound : frameworkErrorHandler . isNotFoundError ,
299
+ hasForbidden : frameworkErrorHandler . isForbiddenError ,
300
+ hasUnauthorized : frameworkErrorHandler . isUnauthorizedError ,
315
301
} )
316
302
) ;
317
303
@@ -322,16 +308,16 @@ export function actionBuilder<
322
308
clientInput : clientInputs . at ( - 1 ) as IS extends Schema ? InferIn < IS > : undefined ,
323
309
bindArgsClientInputs : ( bindArgsSchemas . length ? clientInputs . slice ( 0 , - 1 ) : [ ] ) as InferInArray < BAS > ,
324
310
result : { } ,
325
- hasRedirected : isRedirectError ( frameworkError ) ,
326
- hasNotFound : isNotFoundError ( frameworkError ) ,
327
- hasForbidden : isForbiddenError ( frameworkError ) ,
328
- hasUnauthorized : isUnauthorizedError ( frameworkError ) ,
311
+ hasRedirected : frameworkErrorHandler . isRedirectError ,
312
+ hasNotFound : frameworkErrorHandler . isNotFoundError ,
313
+ hasForbidden : frameworkErrorHandler . isForbiddenError ,
314
+ hasUnauthorized : frameworkErrorHandler . isUnauthorizedError ,
329
315
} )
330
316
) ;
331
317
332
318
await Promise . all ( callbackPromises ) ;
333
319
334
- throw frameworkError ;
320
+ throw frameworkErrorHandler . error ;
335
321
}
336
322
337
323
const actionResult : SafeActionResult < ServerError , IS , BAS , CVE , CBAVE , Data > = { } ;
0 commit comments