From c90072016c633b8508191342cd6612d3a4ba475c Mon Sep 17 00:00:00 2001 From: Edoardo Ranghieri Date: Wed, 4 Sep 2024 14:29:29 +0200 Subject: [PATCH] feat: merge server error handling functions into `handleServerError` (#257) Code in this PR merges the functionality of `handleServerErrorLog` and `handleReturnedServerError` functions into a single optional initialization function called `handleServerError`. This change has been made because having two functions for server error handling is unnecessary, you can easily manage both logging and returned error within a single function. --- apps/playground/src/lib/safe-action.ts | 15 ++---- .../src/__tests__/metadata.test.ts | 2 +- .../src/__tests__/middleware.test.ts | 7 +-- .../src/__tests__/server-error.test.ts | 20 +++---- .../src/__tests__/validation-errors.test.ts | 3 +- .../next-safe-action/src/action-builder.ts | 17 +----- packages/next-safe-action/src/index.ts | 26 +++------ packages/next-safe-action/src/index.types.ts | 11 +--- .../src/safe-action-client.ts | 33 ++++-------- .../define-actions/action-result-object.md | 2 +- .../docs/define-actions/create-the-client.mdx | 53 +++++++------------ .../docs/define-actions/instance-methods.md | 2 +- website/docs/define-actions/middleware.md | 15 ++++-- website/docs/migrations/v6-to-v7.md | 2 +- website/docs/types/infer-types.md | 3 +- 15 files changed, 79 insertions(+), 132 deletions(-) diff --git a/apps/playground/src/lib/safe-action.ts b/apps/playground/src/lib/safe-action.ts index 13bb2bf0..badaa9c4 100644 --- a/apps/playground/src/lib/safe-action.ts +++ b/apps/playground/src/lib/safe-action.ts @@ -9,16 +9,11 @@ export class ActionError extends Error {} export const action = createSafeActionClient({ validationAdapter: zodAdapter(), - // You can provide a custom logging function, otherwise the lib will use `console.error` - // as the default logging system. If you want to disable server errors logging, - // just pass an empty Promise. - handleServerErrorLog: (e) => { - console.error( - "CUSTOM ERROR LOG FUNCTION, server error message:", - e.message - ); - }, - handleReturnedServerError: (e) => { + // You can provide a custom handler for server errors, otherwise the lib will use `console.error` + // as the default logging mechanism and will return the DEFAULT_SERVER_ERROR_MESSAGE for all server errors. + handleServerError: (e) => { + console.error("Action server error occurred:", e.message); + // If the error is an instance of `ActionError`, unmask the message. if (e instanceof ActionError) { return e.message; diff --git a/packages/next-safe-action/src/__tests__/metadata.test.ts b/packages/next-safe-action/src/__tests__/metadata.test.ts index a9f6fbea..65fed19f 100644 --- a/packages/next-safe-action/src/__tests__/metadata.test.ts +++ b/packages/next-safe-action/src/__tests__/metadata.test.ts @@ -8,7 +8,7 @@ import { zodAdapter } from "../adapters/zod"; const ac = createSafeActionClient({ validationAdapter: zodAdapter(), - handleServerErrorLog() {}, // disable server errors logging for these tests + handleServerError: () => DEFAULT_SERVER_ERROR_MESSAGE, // disable server errors logging for these tests defineMetadataSchema() { return z.object({ actionName: z.string(), diff --git a/packages/next-safe-action/src/__tests__/middleware.test.ts b/packages/next-safe-action/src/__tests__/middleware.test.ts index f1a7bc74..896c1968 100644 --- a/packages/next-safe-action/src/__tests__/middleware.test.ts +++ b/packages/next-safe-action/src/__tests__/middleware.test.ts @@ -6,6 +6,7 @@ import { z } from "zod"; import { createMiddleware, createSafeActionClient, + DEFAULT_SERVER_ERROR_MESSAGE, formatBindArgsValidationErrors, formatValidationErrors, returnValidationErrors, @@ -14,8 +15,8 @@ import { zodAdapter } from "../adapters/zod"; const ac = createSafeActionClient({ validationAdapter: zodAdapter(), - handleServerErrorLog() {}, // disable server errors logging for these tests - handleReturnedServerError(e) { + handleServerError(e) { + // disable server error logging for these tests return { message: e.message, }; @@ -296,7 +297,7 @@ test("server validation errors in execution result from middleware are correct", const flac = createSafeActionClient({ validationAdapter: zodAdapter(), - handleServerErrorLog() {}, // disable server errors logging for these tests + handleServerError: () => DEFAULT_SERVER_ERROR_MESSAGE, // disable server errors logging for these tests defaultValidationErrorsShape: "flattened", }); diff --git a/packages/next-safe-action/src/__tests__/server-error.test.ts b/packages/next-safe-action/src/__tests__/server-error.test.ts index 66a28580..2348cab1 100644 --- a/packages/next-safe-action/src/__tests__/server-error.test.ts +++ b/packages/next-safe-action/src/__tests__/server-error.test.ts @@ -13,8 +13,8 @@ class ActionError extends Error { const ac1 = createSafeActionClient({ validationAdapter: zodAdapter(), - handleServerErrorLog: () => {}, // disable server errors logging for these tests - handleReturnedServerError(e) { + handleServerError(e) { + // disable server error logging for these tests if (e instanceof ActionError) { return e.message; } @@ -107,15 +107,15 @@ test("error occurred with `throwServerError` set to true at the action level thr // Server error is an object with a 'message' property. const ac2 = createSafeActionClient({ validationAdapter: zodAdapter(), - handleServerErrorLog: () => {}, // disable server errors logging for these tests - handleReturnedServerError(e) { + handleServerError(e) { + // disable server errors logging for these tests return { message: e.message, }; }, }); -test("error occurred in server code function has the correct shape defined by `handleReturnedServerError`", async () => { +test("error occurred in server code function has the correct shape defined by `handleServerError`", async () => { const action = ac2.action(async () => { throw new Error("Something bad happened"); }); @@ -129,7 +129,7 @@ test("error occurred in server code function has the correct shape defined by `h assert.deepStrictEqual(actualResult, expectedResult); }); -test("error occurred in middleware function has the correct shape defined by `handleReturnedServerError`", async () => { +test("error occurred in middleware function has the correct shape defined by `handleServerError`", async () => { const action = ac2 .use(async ({ next }) => next()) .use(async () => { @@ -153,13 +153,13 @@ test("error occurred in middleware function has the correct shape defined by `ha // Rethrow all server errors. const ac3 = createSafeActionClient({ validationAdapter: zodAdapter(), - handleServerErrorLog: () => {}, // disable server errors logging for these tests - handleReturnedServerError(e) { + handleServerError(e) { + // disable server error logging for these tests throw e; }, }); -test("action throws if an error occurred in server code function and `handleReturnedServerError` rethrows it", async () => { +test("action throws if an error occurred in server code function and `handleServerError` rethrows it", async () => { const action = ac3.action(async () => { throw new Error("Something bad happened"); }); @@ -167,7 +167,7 @@ test("action throws if an error occurred in server code function and `handleRetu assert.rejects(() => action()); }); -test("action throws if an error occurred in middleware function and `handleReturnedServerError` rethrows it", async () => { +test("action throws if an error occurred in middleware function and `handleServerError` rethrows it", async () => { const action = ac3 .use(async ({ next }) => next()) .use(async () => { diff --git a/packages/next-safe-action/src/__tests__/validation-errors.test.ts b/packages/next-safe-action/src/__tests__/validation-errors.test.ts index d80797c6..db13dce0 100644 --- a/packages/next-safe-action/src/__tests__/validation-errors.test.ts +++ b/packages/next-safe-action/src/__tests__/validation-errors.test.ts @@ -171,7 +171,8 @@ test("action with invalid output data returns the default `serverError`", async test("action with invalid output data throws an error of the correct type", async () => { const tac = createSafeActionClient({ validationAdapter: zodAdapter(), - handleReturnedServerError: (e) => { + handleServerError: (e) => { + // disable server error logging for this test throw e; }, }); diff --git a/packages/next-safe-action/src/action-builder.ts b/packages/next-safe-action/src/action-builder.ts index bee4b969..ac34fb3e 100644 --- a/packages/next-safe-action/src/action-builder.ts +++ b/packages/next-safe-action/src/action-builder.ts @@ -50,10 +50,7 @@ export function actionBuilder< handleBindArgsValidationErrorsShape: HandleBindArgsValidationErrorsShapeFn; metadataSchema: MetadataSchema; metadata: MD; - handleServerErrorLog: NonNullable["handleServerErrorLog"]>; - handleReturnedServerError: NonNullable< - SafeActionClientOpts["handleReturnedServerError"] - >; + handleServerError: NonNullable["handleServerError"]>; middlewareFns: MiddlewareFn[]; ctxType: Ctx; throwValidationErrors: boolean; @@ -250,7 +247,7 @@ export function actionBuilder< // the default message. const error = isError(e) ? e : new Error(DEFAULT_SERVER_ERROR_MESSAGE); const returnedError = await Promise.resolve( - args.handleReturnedServerError(error, { + args.handleServerError(error, { clientInput: clientInputs.at(-1), // pass raw client input bindArgsClientInputs: bindArgsSchemas.length ? clientInputs.slice(0, -1) : [], ctx: currentCtx, @@ -259,16 +256,6 @@ export function actionBuilder< ); middlewareResult.serverError = returnedError; - - await Promise.resolve( - args.handleServerErrorLog(error, { - returnedError, - clientInput: clientInputs.at(-1), // pass raw client input - bindArgsClientInputs: bindArgsSchemas.length ? clientInputs.slice(0, -1) : [], - ctx: currentCtx, - metadata: args.metadata as MetadataSchema extends Schema ? Infer : undefined, - }) - ); } } }; diff --git a/packages/next-safe-action/src/index.ts b/packages/next-safe-action/src/index.ts index ea664aa1..bfd181b7 100644 --- a/packages/next-safe-action/src/index.ts +++ b/packages/next-safe-action/src/index.ts @@ -40,27 +40,17 @@ export const createSafeActionClient = < >( createOpts?: SafeActionClientOpts ) => { - // If server log function is not provided, default to `console.error` for logging - // server error messages. - const handleServerErrorLog = - createOpts?.handleServerErrorLog || - (((originalError: Error) => { - console.error("Action error:", originalError.message); - }) as unknown as NonNullable["handleServerErrorLog"]>); - - // If `handleReturnedServerError` is provided, use it to handle server error - // messages returned on the client. - // Otherwise mask the error and use a generic message. - const handleReturnedServerError = - createOpts?.handleReturnedServerError || - ((() => DEFAULT_SERVER_ERROR_MESSAGE) as unknown as NonNullable< - SafeActionClientOpts["handleReturnedServerError"] - >); + // If `handleServerError` is provided, use it, otherwise default to log to console and generic error message. + const handleServerError: NonNullable["handleServerError"]> = + createOpts?.handleServerError || + ((e) => { + console.error("Action error:", e.message); + return DEFAULT_SERVER_ERROR_MESSAGE as ServerError; + }); return new SafeActionClient({ middlewareFns: [async ({ next }) => next({ ctx: {} })], - handleServerErrorLog, - handleReturnedServerError, + handleServerError, inputSchemaFn: undefined, bindArgsSchemas: [], outputSchema: undefined, diff --git a/packages/next-safe-action/src/index.types.ts b/packages/next-safe-action/src/index.types.ts index 0cea8bfa..03a6ab3a 100644 --- a/packages/next-safe-action/src/index.types.ts +++ b/packages/next-safe-action/src/index.types.ts @@ -29,16 +29,7 @@ export type SafeActionClientOpts< > = { validationAdapter?: ValidationAdapter; defineMetadataSchema?: () => MetadataSchema; - handleReturnedServerError?: ( - error: Error, - utils: ServerErrorFunctionUtils - ) => MaybePromise; - handleServerErrorLog?: ( - originalError: Error, - utils: ServerErrorFunctionUtils & { - returnedError: ServerError; - } - ) => MaybePromise; + handleServerError?: (error: Error, utils: ServerErrorFunctionUtils) => MaybePromise; throwValidationErrors?: boolean; defaultValidationErrorsShape?: ODVES; }; diff --git a/packages/next-safe-action/src/safe-action-client.ts b/packages/next-safe-action/src/safe-action-client.ts index b37013bc..3c5cf7cf 100644 --- a/packages/next-safe-action/src/safe-action-client.ts +++ b/packages/next-safe-action/src/safe-action-client.ts @@ -31,11 +31,8 @@ export class SafeActionClient< CVE = undefined, const CBAVE = undefined, > { - readonly #handleServerErrorLog: NonNullable< - SafeActionClientOpts["handleServerErrorLog"] - >; - readonly #handleReturnedServerError: NonNullable< - SafeActionClientOpts["handleReturnedServerError"] + readonly #handleServerError: NonNullable< + SafeActionClientOpts["handleServerError"] >; readonly #middlewareFns: MiddlewareFn[]; readonly #metadataSchema: MetadataSchema; @@ -65,13 +62,12 @@ export class SafeActionClient< } & Required< Pick< SafeActionClientOpts, - "handleReturnedServerError" | "handleServerErrorLog" | "defaultValidationErrorsShape" | "throwValidationErrors" + "handleServerError" | "defaultValidationErrorsShape" | "throwValidationErrors" > > ) { this.#middlewareFns = opts.middlewareFns; - this.#handleServerErrorLog = opts.handleServerErrorLog; - this.#handleReturnedServerError = opts.handleReturnedServerError; + this.#handleServerError = opts.handleServerError; this.#metadataSchema = opts.metadataSchema; this.#metadata = opts.metadata; this.#inputSchemaFn = (opts.inputSchemaFn ?? undefined) as ISF; @@ -94,8 +90,7 @@ export class SafeActionClient< use(middlewareFn: MiddlewareFn) { return new SafeActionClient({ middlewareFns: [...this.#middlewareFns, middlewareFn], - handleReturnedServerError: this.#handleReturnedServerError, - handleServerErrorLog: this.#handleServerErrorLog, + handleServerError: this.#handleServerError, metadataSchema: this.#metadataSchema, metadata: this.#metadata, inputSchemaFn: this.#inputSchemaFn, @@ -119,8 +114,7 @@ export class SafeActionClient< metadata(data: MD) { return new SafeActionClient({ middlewareFns: this.#middlewareFns, - handleReturnedServerError: this.#handleReturnedServerError, - handleServerErrorLog: this.#handleServerErrorLog, + handleServerError: this.#handleServerError, metadataSchema: this.#metadataSchema, metadata: data, inputSchemaFn: this.#inputSchemaFn, @@ -154,8 +148,7 @@ export class SafeActionClient< ) { return new SafeActionClient({ middlewareFns: this.#middlewareFns, - handleReturnedServerError: this.#handleReturnedServerError, - handleServerErrorLog: this.#handleServerErrorLog, + handleServerError: this.#handleServerError, metadataSchema: this.#metadataSchema, metadata: this.#metadata, // @ts-expect-error @@ -196,8 +189,7 @@ export class SafeActionClient< ) { return new SafeActionClient({ middlewareFns: this.#middlewareFns, - handleReturnedServerError: this.#handleReturnedServerError, - handleServerErrorLog: this.#handleServerErrorLog, + handleServerError: this.#handleServerError, metadataSchema: this.#metadataSchema, metadata: this.#metadata, inputSchemaFn: this.#inputSchemaFn, @@ -222,8 +214,7 @@ export class SafeActionClient< outputSchema(dataSchema: OOS) { return new SafeActionClient({ middlewareFns: this.#middlewareFns, - handleReturnedServerError: this.#handleReturnedServerError, - handleServerErrorLog: this.#handleServerErrorLog, + handleServerError: this.#handleServerError, metadataSchema: this.#metadataSchema, metadata: this.#metadata, inputSchemaFn: this.#inputSchemaFn, @@ -250,8 +241,7 @@ export class SafeActionClient< utils?: SafeActionUtils ) { return actionBuilder({ - handleReturnedServerError: this.#handleReturnedServerError, - handleServerErrorLog: this.#handleServerErrorLog, + handleServerError: this.#handleServerError, middlewareFns: this.#middlewareFns, ctxType: this.#ctxType, metadataSchema: this.#metadataSchema, @@ -279,8 +269,7 @@ export class SafeActionClient< utils?: SafeActionUtils ) { return actionBuilder({ - handleReturnedServerError: this.#handleReturnedServerError, - handleServerErrorLog: this.#handleServerErrorLog, + handleServerError: this.#handleServerError, middlewareFns: this.#middlewareFns, ctxType: this.#ctxType, metadataSchema: this.#metadataSchema, diff --git a/website/docs/define-actions/action-result-object.md b/website/docs/define-actions/action-result-object.md index 8f64fcc9..9b306db5 100644 --- a/website/docs/define-actions/action-result-object.md +++ b/website/docs/define-actions/action-result-object.md @@ -10,4 +10,4 @@ Here's how action result object is structured (all keys are optional): - `data`: when execution is successful, what you returned in action's server code. - `validationErrors`: when input data doesn't pass validation, an object that contains the validation errors. Can be customized using [`defaultValidationErrorsShape`](/docs/define-actions/create-the-client#defaultvalidationerrorsshape) initialization option and/or via [`handleValidationErrorsShape`function passed to `schema` method](/docs/define-actions/validation-errors#customize-validation-errors-format). - `bindArgsValidationErrors`: when bound arguments don't pass validation, an object that contains the validation errors. Can be customized using [`defaultValidationErrorsShape`](/docs/define-actions/create-the-client#defaultvalidationerrorsshape) initialization option and/or via [`handleBindArgsValidationErrorsShape` function passed to `bindArgsSchemas` method](/docs/define-actions/validation-errors#customize-validation-errors-format). -- `serverError`: when execution fails, an error object that contains the error message, customizable by using the [`handleReturnedServerError`](/docs/define-actions/create-the-client#handlereturnedservererror) initialization function. \ No newline at end of file +- `serverError`: when execution fails, an error object that contains the error message, customizable by using the [`handleServerError`](/docs/define-actions/create-the-client#handleservererror) initialization function. \ No newline at end of file diff --git a/website/docs/define-actions/create-the-client.mdx b/website/docs/define-actions/create-the-client.mdx index 9831c9ac..7cf63e91 100644 --- a/website/docs/define-actions/create-the-client.mdx +++ b/website/docs/define-actions/create-the-client.mdx @@ -61,21 +61,29 @@ In the following section we will go through all the options that can be passed t This optional function is used to define which validation adapter should be used to validate the client input, based on the validation library of your choice. If not provided, the default `zodAdapter()` is used. -### `handleReturnedServerError?` +### `handleServerError?` -This optional function is used to customize the server error returned to the client, if one occurs during action's server execution. This includes errors thrown by the action server code, and errors thrown by the middleware. You also have access to useful properties via the `utils` object, which is the second argument of the function. +:::info +This function has been introduced in v7.9.0. Previous versions had two separate functions: `handleServerErrorLog` and `handleReturnedServerError`. The `handleServerError` function is simply a merge of the two, since having two functions for this task was unnecessary. The refactoring is super simple, you just have to combine the two functions body into one. Find out more about this in the [v7.9.0 changelog](https://github.com/TheEdoRan/next-safe-action/releases/tag/v7.9.0). +::: -Here's a simple example, changing the default message for every error thrown on the server: +This optional function handles errors that occur during action's server execution, middleware included. It's used to customize logging and the shape of the server error returned to the client. You also have access to useful properties via the `utils` object, which is the second argument of the function. If not provided, it defaults to console logging the error message and returning a generic string to the client, for all the errors (`DEFAULT_SERVER_ERROR_MESSAGE`, exported from `next-safe-action`). + +Here's a simple example, changing the default message for every error thrown on the server, while keeping the console logging: ```typescript title=src/lib/safe-action.ts import { createSafeActionClient } from "next-safe-action"; export const actionClient = createSafeActionClient({ // Can also be an async function. - handleReturnedServerError(e, utils) { + handleServerError(e, utils) { // You can access these properties inside the `utils` object. const { clientInput, bindArgsClientInputs, metadata, ctx } = utils; + // Log to console. + console.error("Action error:", e.message); + + // Return generic message return "Oh no, something went wrong!"; }, }); @@ -92,7 +100,10 @@ class MyCustomError extends Error {} export const actionClient = createSafeActionClient({ // Can also be an async function. - handleReturnedServerError(e) { + handleServerError(e) { + // Log to console. + console.error("Action error:", e.message); + // In this case, we can use the 'MyCustomError` class to unmask errors // and return them with their actual messages to the client. if (e instanceof MyCustomError) { @@ -114,40 +125,16 @@ class MyCustomError extends Error {} export const actionClient = createSafeActionClient({ // Can also be an async function. - handleReturnedServerError(e) { + handleServerError(e) { + // Log to console. + console.error("Action error:", e.message); + // Rethrow all server errors: throw e; }, }); ``` -Note that the return type of this function will determine the type of the server error that will be returned to the client. By default it is a string with the `DEFAULT_SERVER_ERROR_MESSAGE` for all errors. - -### `handleServerErrorLog?` - -This optional function is used to define how errors should be logged when one occurs while the server is executing an action. This includes errors thrown by the action server code, and errors thrown by the middleware. Here you get as the first argument the **original error object**, not the one customized by `handleReturnedServerError`, if provided. Though, you can access the `returnedError` and other useful properties inside the `utils` object, which is the second argument. - -Here's a simple example, logging error to the console while also reporting it to an error handling system: - -```typescript title=src/lib/safe-action.ts -import { createSafeActionClient } from "next-safe-action"; - -export const actionClient = createSafeActionClient({ - // Can also be an async function. - handleServerErrorLog(originalError, utils) { - // You can access these properties inside the `utils` object. - // Note that here you also have access to the custom server error defined by `handleReturnedServerError`. - const { clientInput, bindArgsClientInputs, metadata, ctx, returnedError } = utils; - - // We can, for example, also send the error to a dedicated logging system. - reportToErrorHandlingSystem(originalError); - - // And also log it to the console. - console.error("Action error:", originalError.message); - }, -}); -``` - ### `defineMetadataSchema?` This optional function is used to define the type of the metadata for safe actions. If not provided, `metadata` will default to `undefined` value. You can find more information about metadata in the [`metadata` instance method section](/docs/define-actions/instance-methods#metadata). If you define a metadata schema and you don't call the `metadata` method before defining an action, an error will be thrown. diff --git a/website/docs/define-actions/instance-methods.md b/website/docs/define-actions/instance-methods.md index 6f50d49a..9be92ec3 100644 --- a/website/docs/define-actions/instance-methods.md +++ b/website/docs/define-actions/instance-methods.md @@ -47,7 +47,7 @@ bindArgsSchemas(bindArgsSchemas: BAS, bindArgsUtils?: { handleBindArgsValidation outputSchema(outputSchema: S) => new SafeActionClient() ``` -`outputSchema` accepts a schema of type `Schema`. That schema is used to define what the safe action will return. If you don't pass an output schema when you're defining an action, the return type will be inferred instead. If validation fails, an `ActionOutputDataValidationError` is internally thrown. You can catch it inside [`handleReturnedServerError`](/docs/define-actions/create-the-client#handlereturnedservererror)/[`handleServerErrorLog`](/docs/define-actions/create-the-client#handleservererrorlog) and access the `validationErrors` property to get the validation errors. It returns a new instance of the safe action client. +`outputSchema` accepts a schema of type `Schema`. That schema is used to define what the safe action will return. If you don't pass an output schema when you're defining an action, the return type will be inferred instead. If validation fails, an `ActionOutputDataValidationError` is internally thrown. You can catch it inside [`handleServerError`](/docs/define-actions/create-the-client#handleservererror) and access the `validationErrors` property to get the validation errors. It returns a new instance of the safe action client. ### `action` / `stateAction` diff --git a/website/docs/define-actions/middleware.md b/website/docs/define-actions/middleware.md index 7d9ebdea..46fc148f 100644 --- a/website/docs/define-actions/middleware.md +++ b/website/docs/define-actions/middleware.md @@ -17,7 +17,7 @@ You can chain multiple middleware functions, that will be executed in the order Instance level is the right place when you want to share middleware behavior for all the actions you're going to define; for example when you need to log the result of actions execution, or verify if the user intending to execute the operation is authorized to do so, and if not, halt the execution at that point, by throwing an error. -Here we'll use a logging middleware in the base client and then extend it with an authorization middleware in `authActionClient`. We'll also define a safe action called `editProfile`, that will use `authActionClient` as its client. Note that the `handleReturnedServerError` function passed to the base client will also be used for `authActionClient`: +Here we'll use a logging middleware in the base client and then extend it with an authorization middleware in `authActionClient`. We'll also define a safe action called `editProfile`, that will use `authActionClient` as its client. Note that the `handleServerError` function passed to the base client will also be used for `authActionClient`: ```typescript title="src/lib/safe-action.ts" import { @@ -32,7 +32,9 @@ class ActionError extends Error {} // Base client. const actionClient = createSafeActionClient({ - handleReturnedServerError(e) { + handleServerError(e) { + console.error("Action error:", e.message); + if (e instanceof ActionError) { return e.message; } @@ -226,9 +228,12 @@ export const actionClient = createSafeActionClient({ defineMetadataSchema: () => z.object({ actionName: z.string(), }), - handleReturnedServerError: (e) => ({ - message: e.message, - }), + handleServerError: (e) => { + console.error("Action error:", e.message); + return { + message: e.message, + } + } }).use(async ({ next }) => { return next({ ctx: { foo: "bar" } }); }); diff --git a/website/docs/migrations/v6-to-v7.md b/website/docs/migrations/v6-to-v7.md index c50226f9..8d93c307 100644 --- a/website/docs/migrations/v6-to-v7.md +++ b/website/docs/migrations/v6-to-v7.md @@ -121,7 +121,7 @@ With version 7, you can chain multiple middleware functions using the [`use`](/d ### [Generic type for `serverError`](https://github.com/TheEdoRan/next-safe-action/issues/86) -The `serverError` property of the [action result object](/docs/define-actions/action-result-object) is now of generic type. By default it's a `string` with a default value of "Something went wrong while executing the operation.". You can customize error value and type using the [`handleReturnedServerError`](/docs/define-actions/create-the-client#handlereturnedservererror) initialization function, just like pre-v7. Basically, what you return from that function is what `serverError` will be on the client. +The `serverError` property of the [action result object](/docs/define-actions/action-result-object) is now of generic type. By default it's a `string` with a default value of "Something went wrong while executing the operation.". You can customize error value and type using the [`handleServerError`](/docs/define-actions/create-the-client#handleservererror) initialization function, just like pre-v7. Basically, what you return from that function is what `serverError` will be on the client. ### [Support binding additional arguments](https://github.com/TheEdoRan/next-safe-action/issues/29) diff --git a/website/docs/types/infer-types.md b/website/docs/types/infer-types.md index baa1aef7..ad4bc911 100644 --- a/website/docs/types/infer-types.md +++ b/website/docs/types/infer-types.md @@ -36,7 +36,8 @@ export const actionClient = createSafeActionClient({ actionName: z.string(), }); }, - handleReturnedServerError: (e) => { + handleServerError: (e) => { + console.error("Action error:", e.message); return { errorMessage: e.message, };