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.4
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.7.0
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on Aug 18, 2024

  1. feat(middleware): make createMiddleware function stable

    Rename exported `experimental_createMiddleware` function to `createMiddleware`, making it stable
    API.
    TheEdoRan committed Aug 18, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    TheEdoRan Edoardo Ranghieri
    Copy the full SHA
    d9d326e View commit details
4 changes: 2 additions & 2 deletions packages/next-safe-action/src/__tests__/middleware.test.ts
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ import assert from "node:assert";
import { test } from "node:test";
import { z } from "zod";
import {
createMiddleware,
createSafeActionClient,
experimental_createMiddleware,
formatBindArgsValidationErrors,
formatValidationErrors,
returnValidationErrors,
@@ -397,7 +397,7 @@ test("overridden formatted validation errors in execution result from middleware
});

test("standalone middleware extends context", async () => {
const myMiddleware = experimental_createMiddleware<{ ctx: { foo: string } }>().define(async ({ next }) => {
const myMiddleware = createMiddleware<{ ctx: { foo: string } }>().define(async ({ next }) => {
return next({ ctx: { baz: "qux" } });
});

2 changes: 1 addition & 1 deletion packages/next-safe-action/src/index.ts
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ import {
formatValidationErrors,
} from "./validation-errors";

export { createMiddleware as experimental_createMiddleware } from "./middleware";
export { createMiddleware } from "./middleware";
export { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE } from "./utils";
export {
ActionValidationError,
14 changes: 7 additions & 7 deletions website/docs/safe-action-client/middleware.md
Original file line number Diff line number Diff line change
@@ -243,17 +243,17 @@ export const testAction = actionClient
## Create standalone middleware

:::info
Experimental feature
Since version 7.7.0, this API is stable, so it was renamed from `experimental_createMiddleware` to `createMiddleware`.
:::

Starting from version 7.6.0, you can create standalone middleware functions using the built-in `experimental_createMiddleware()` function. It's labeled as experimental because the API could change in the future, but it's perfectly fine to use it, as it's a pretty simple function that just wraps the creation of middleware.
Starting from version 7.6.0, you can create standalone middleware functions using the built-in `createMiddleware()` function.

Thanks to this feature, and the previously mentioned [context extension](#extend-context), you can now define standalone middleware functions and even publish them as packages, if you want to.

Here's how to use `experimental_createMiddleware()`:
Here's how to use `createMiddleware()`:

```typescript title="src/lib/safe-action.ts"
import { createSafeActionClient, experimental_createMiddleware } from "next-safe-action";
import { createSafeActionClient, createMiddleware } from "next-safe-action";
import { z } from "zod";

export const actionClient = createSafeActionClient({
@@ -268,14 +268,14 @@ export const actionClient = createSafeActionClient({
});

// This middleware works with any client.
const myMiddleware1 = experimental_createMiddleware().define(async ({ next }) => {
const myMiddleware1 = createMiddleware().define(async ({ next }) => {
// Do something useful here...
return next({ ctx: { baz: "qux" } });
});

// This middleware works with clients that at minimum have `ctx.foo`, `metadata.actionName`
// and `serverError.message` properties. More information below. *
const myMiddleware2 = experimental_createMiddleware<{
const myMiddleware2 = createMiddleware<{
ctx: { foo: string }; // [1]
metadata: { actionName: string }; // [2]
serverError: { message: string } // [3]
@@ -290,4 +290,4 @@ export const actionClientWithMyMiddleware = actionClient.use(myMiddleware1).use(

An action defined using the `actionClientWithMyMiddleware` will contain `foo`, `baz` and `john` in its context.

\* Note that you can pass, **but not required to**, an object with two generic properties to the `experimental_createMiddleware()` function: `ctx` \[1\], `metadata` \[2\] and `serverError` \[3\]. Those keys are optional, and you should only provide them if you want your middleware to require **at minimum** the shape you passed in as generic. By doing that, following the above example, you can then access `ctx.foo` and `metadata.actionName` in the middleware you're defining, and by awaiting the `next` function you'll see that `serverError` is an object with the `message` property. If you pass a middleware that requires those properties to a client that doesn't have them, you'll get an error in `use()` method.
\* Note that you can pass, **but not required to**, an object with two generic properties to the `createMiddleware()` function: `ctx` \[1\], `metadata` \[2\] and `serverError` \[3\]. Those keys are optional, and you should only provide them if you want your middleware to require **at minimum** the shape you passed in as generic. By doing that, following the above example, you can then access `ctx.foo` and `metadata.actionName` in the middleware you're defining, and by awaiting the `next` function you'll see that `serverError` is an object with the `message` property. If you pass a middleware that requires those properties to a client that doesn't have them, you'll get an error in `use()` method.
4 changes: 2 additions & 2 deletions website/docs/types/infer-types.md
Original file line number Diff line number Diff line change
@@ -11,11 +11,11 @@ Suppose we have declared this safe action client:

```typescript title="src/lib/safe-action.ts"
import { z } from "zod";
import { createSafeActionClient, experimental_createMiddleware } from "next-safe-action";
import { createSafeActionClient, createMiddleware } from "next-safe-action";
import { getSessionData } from "@/services/auth"

// Here we declare a standalone auth middleware.
export const authMiddleware = experimental_createMiddleware<{
export const authMiddleware = createMiddleware<{
ctx: { sessionToken: string };
metadata: { actionName: string };
}>().define(async ({ ctx, next }) => {