Skip to content

Commit

Permalink
chore(website): update documentation for handleServerError
Browse files Browse the repository at this point in the history
  • Loading branch information
TheEdoRan committed Sep 4, 2024
1 parent ce3f6f0 commit b65bbeb
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 42 deletions.
2 changes: 1 addition & 1 deletion website/docs/define-actions/action-result-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
- `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.
53 changes: 20 additions & 33 deletions website/docs/define-actions/create-the-client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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!";
},
});
Expand All @@ -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) {
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion website/docs/define-actions/instance-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
15 changes: 10 additions & 5 deletions website/docs/define-actions/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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" } });
});
Expand Down
2 changes: 1 addition & 1 deletion website/docs/migrations/v6-to-v7.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
3 changes: 2 additions & 1 deletion website/docs/types/infer-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down

0 comments on commit b65bbeb

Please sign in to comment.