Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: TheEdoRan/next-safe-action
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v7.6.2
Choose a base ref
...
head repository: TheEdoRan/next-safe-action
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v7.6.3
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Aug 16, 2024

  1. fix: parallelize action callbacks execution

    TheEdoRan committed Aug 16, 2024
    Copy the full SHA
    53ddab6 View commit details
Showing with 16 additions and 9 deletions.
  1. +12 −5 packages/next-safe-action/src/action-builder.ts
  2. +4 −4 website/docs/execution/action-utils.md
17 changes: 12 additions & 5 deletions packages/next-safe-action/src/action-builder.ts
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ import type {
StateServerCodeFn,
} from "./index.types";
import { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE, isError } from "./utils";
import type { MaybePromise } from "./utils.types";
import { ActionServerValidationError, ActionValidationError, buildValidationErrors } from "./validation-errors";
import type {
BindArgsValidationErrors,
@@ -259,9 +260,11 @@ export function actionBuilder<
// Execute middleware chain + action function.
await executeMiddlewareStack();

const callbacksToExecute: MaybePromise<void>[] = [];

// If an internal framework error occurred, throw it, so it will be processed by Next.js.
if (frameworkError) {
await Promise.resolve(
callbacksToExecute.push(
utils?.onSuccess?.({
data: undefined,
metadata: args.metadata,
@@ -275,7 +278,7 @@ export function actionBuilder<
})
);

await Promise.resolve(
callbacksToExecute.push(
utils?.onSettled?.({
metadata: args.metadata,
ctx: currentCtx as Ctx,
@@ -287,6 +290,8 @@ export function actionBuilder<
})
);

await Promise.all(callbacksToExecute);

throw frameworkError;
}

@@ -323,7 +328,7 @@ export function actionBuilder<
actionResult.data = middlewareResult.data as Data;
}

await Promise.resolve(
callbacksToExecute.push(
utils?.onSuccess?.({
metadata: args.metadata,
ctx: currentCtx as Ctx,
@@ -337,7 +342,7 @@ export function actionBuilder<
})
);
} else {
await Promise.resolve(
callbacksToExecute.push(
utils?.onError?.({
metadata: args.metadata,
ctx: currentCtx as Ctx,
@@ -349,7 +354,7 @@ export function actionBuilder<
}

// onSettled, if provided, is always executed.
await Promise.resolve(
callbacksToExecute.push(
utils?.onSettled?.({
metadata: args.metadata,
ctx: currentCtx as Ctx,
@@ -361,6 +366,8 @@ export function actionBuilder<
})
);

await Promise.all(callbacksToExecute);

return actionResult;
};
},
8 changes: 4 additions & 4 deletions website/docs/execution/action-utils.md
Original file line number Diff line number Diff line change
@@ -57,8 +57,8 @@ const action = actionClient

Here is the list of callbacks, with their behavior explained. All of them are optional and have return type `void` or `Promise<void>` (async or non-async functions with no return):

| Name | Executed after |
| Name | Executed after |
| ------------ | ----------------------------------------------------------------------- |
| `onSuccess?` | Action succeeded
| `onError?` | Action errored with server or validation error(s)
| `onSettled?` | Action succeeded or errored (after `onSuccess` or `onError` call) |
| `onSuccess?` | Action succeeded |
| `onError?` | Action errored with server or validation error(s) |
| `onSettled?` | Action succeeded or errored |