Skip to content

Commit 769a372

Browse files
committedJun 20, 2024
feat(validation-errors): support throwing validation errors via init option
1 parent 75e92f5 commit 769a372

File tree

6 files changed

+30
-3
lines changed

6 files changed

+30
-3
lines changed
 

‎packages/next-safe-action/src/action-builder.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type {
1616
} from "./index.types";
1717
import type { InferArray, InferInArray } from "./utils";
1818
import { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE, isError, zodValidate } from "./utils";
19-
import { buildValidationErrors } from "./validation-errors";
19+
import { ActionValidationError, buildValidationErrors } from "./validation-errors";
2020
import type {
2121
BindArgsValidationErrors,
2222
HandleBindArgsValidationErrorsShapeFn,
@@ -46,6 +46,7 @@ export function actionBuilder<
4646
middlewareFns: MiddlewareFn<ServerError, any, any, any>[];
4747
ctxType: Ctx;
4848
validationStrategy: "typeschema" | "zod";
49+
throwValidationErrors: boolean;
4950
}) {
5051
const bindArgsSchemas = (args.bindArgsSchemas ?? []) as BAS;
5152

@@ -281,6 +282,9 @@ export function actionBuilder<
281282
const actionResult: SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data> = {};
282283

283284
if (typeof middlewareResult.validationErrors !== "undefined") {
285+
if (args.throwValidationErrors) {
286+
throw new ActionValidationError(middlewareResult.validationErrors as CVE);
287+
}
284288
actionResult.validationErrors = middlewareResult.validationErrors as CVE;
285289
}
286290

‎packages/next-safe-action/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111

1212
export { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE } from "./utils";
1313
export {
14+
ActionValidationError,
1415
flattenBindArgsValidationErrors,
1516
flattenValidationErrors,
1617
formatBindArgsValidationErrors,
@@ -63,6 +64,7 @@ export const createSafeActionClient = <
6364
metadataSchema: createOpts?.defineMetadataSchema?.(),
6465
metadata: undefined as MetadataSchema extends Schema ? Infer<MetadataSchema> : undefined,
6566
defaultValidationErrorsShape: (createOpts?.defaultValidationErrorsShape ?? "formatted") as ODVES,
67+
throwValidationErrors: Boolean(createOpts?.throwValidationErrors),
6668
handleValidationErrorsShape:
6769
createOpts?.defaultValidationErrorsShape === "flattened" ? flattenValidationErrors : formatValidationErrors,
6870
handleBindArgsValidationErrorsShape:

‎packages/next-safe-action/src/index.types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type SafeActionClientOpts<
1919
handleServerErrorLog?: (e: Error) => MaybePromise<void>;
2020
handleReturnedServerError?: (e: Error) => MaybePromise<ServerError>;
2121
defineMetadataSchema?: () => MetadataSchema;
22+
throwValidationErrors?: boolean;
2223
defaultValidationErrorsShape?: ODVES;
2324
};
2425

‎packages/next-safe-action/src/safe-action-client.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export class SafeActionClient<
4444
readonly #handleValidationErrorsShape: HandleValidationErrorsShapeFn<S, CVE>;
4545
readonly #handleBindArgsValidationErrorsShape: HandleBindArgsValidationErrorsShapeFn<BAS, CBAVE>;
4646
readonly #defaultValidationErrorsShape: ODVES;
47+
readonly #throwValidationErrors: boolean;
4748

4849
constructor(
4950
opts: {
@@ -59,7 +60,7 @@ export class SafeActionClient<
5960
} & Required<
6061
Pick<
6162
SafeActionClientOpts<ServerError, any, ODVES>,
62-
"handleReturnedServerError" | "handleServerErrorLog" | "defaultValidationErrorsShape"
63+
"handleReturnedServerError" | "handleServerErrorLog" | "defaultValidationErrorsShape" | "throwValidationErrors"
6364
>
6465
>
6566
) {
@@ -74,6 +75,7 @@ export class SafeActionClient<
7475
this.#handleValidationErrorsShape = opts.handleValidationErrorsShape;
7576
this.#handleBindArgsValidationErrorsShape = opts.handleBindArgsValidationErrorsShape;
7677
this.#defaultValidationErrorsShape = opts.defaultValidationErrorsShape;
78+
this.#throwValidationErrors = opts.throwValidationErrors;
7779
}
7880

7981
/**
@@ -96,6 +98,7 @@ export class SafeActionClient<
9698
handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape,
9799
ctxType: undefined as NextCtx,
98100
defaultValidationErrorsShape: this.#defaultValidationErrorsShape,
101+
throwValidationErrors: this.#throwValidationErrors,
99102
});
100103
}
101104

@@ -119,6 +122,7 @@ export class SafeActionClient<
119122
handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape,
120123
ctxType: undefined as Ctx,
121124
defaultValidationErrorsShape: this.#defaultValidationErrorsShape,
125+
throwValidationErrors: this.#throwValidationErrors,
122126
});
123127
}
124128

@@ -160,6 +164,7 @@ export class SafeActionClient<
160164
handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape,
161165
ctxType: undefined as Ctx,
162166
defaultValidationErrorsShape: this.#defaultValidationErrorsShape,
167+
throwValidationErrors: this.#throwValidationErrors,
163168
});
164169
}
165170

@@ -193,6 +198,7 @@ export class SafeActionClient<
193198
this.#handleBindArgsValidationErrorsShape) as HandleBindArgsValidationErrorsShapeFn<OBAS, OCBAVE>,
194199
ctxType: undefined as Ctx,
195200
defaultValidationErrorsShape: this.#defaultValidationErrorsShape,
201+
throwValidationErrors: this.#throwValidationErrors,
196202
});
197203
}
198204

@@ -219,6 +225,7 @@ export class SafeActionClient<
219225
bindArgsSchemas: this.#bindArgsSchemas,
220226
handleValidationErrorsShape: this.#handleValidationErrorsShape,
221227
handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape,
228+
throwValidationErrors: this.#throwValidationErrors,
222229
}).action(serverCodeFn, cb);
223230
}
224231

@@ -246,6 +253,7 @@ export class SafeActionClient<
246253
bindArgsSchemas: this.#bindArgsSchemas,
247254
handleValidationErrorsShape: this.#handleValidationErrorsShape,
248255
handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape,
256+
throwValidationErrors: this.#throwValidationErrors,
249257
}).stateAction(serverCodeFn, cb);
250258
}
251259
}

‎packages/next-safe-action/src/typeschema.ts

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111

1212
export { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE } from "./utils";
1313
export {
14+
ActionValidationError,
1415
flattenBindArgsValidationErrors,
1516
flattenValidationErrors,
1617
formatBindArgsValidationErrors,
@@ -63,6 +64,7 @@ export const createSafeActionClient = <
6364
metadataSchema: createOpts?.defineMetadataSchema?.(),
6465
metadata: undefined as MetadataSchema extends Schema ? Infer<MetadataSchema> : undefined,
6566
defaultValidationErrorsShape: (createOpts?.defaultValidationErrorsShape ?? "formatted") as ODVES,
67+
throwValidationErrors: Boolean(createOpts?.throwValidationErrors),
6668
handleValidationErrorsShape:
6769
createOpts?.defaultValidationErrorsShape === "flattened" ? flattenValidationErrors : formatValidationErrors,
6870
handleBindArgsValidationErrorsShape:

‎packages/next-safe-action/src/validation-errors.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,22 @@ export class ActionServerValidationError<S extends Schema> extends Error {
5656
public kind: string;
5757
public validationErrors: ValidationErrors<S>;
5858
constructor(validationErrors: ValidationErrors<S>) {
59-
super("Action server validation error");
59+
super("Server Action server validation error(s) occurred");
6060
this.validationErrors = validationErrors;
6161
this.kind = "__actionServerValidationError";
6262
}
6363
}
6464

65+
// This class is internally used to throw validation errors in action's server code function, using
66+
// `returnValidationErrors`.
67+
export class ActionValidationError<CVE> extends Error {
68+
public validationErrors: CVE;
69+
constructor(validationErrors: CVE) {
70+
super("Server Action validation error(s) occurred");
71+
this.validationErrors = validationErrors;
72+
}
73+
}
74+
6575
/**
6676
* Return custom validation errors to the client from the action's server code function.
6777
* Code declared after this function invocation will not be executed.

0 commit comments

Comments
 (0)
Please sign in to comment.