Skip to content

Commit

Permalink
refactor: rename buildContext function to middleware
Browse files Browse the repository at this point in the history
BREAKING CHANGE: `buildContext` client initialization option is now called `middleware`
  • Loading branch information
TheEdoRan committed Oct 1, 2023
1 parent bfc685d commit 116da1d
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 21 deletions.
13 changes: 7 additions & 6 deletions packages/example-app/src/lib/safe-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ export const action = createSafeActionClient({
});

export const authAction = createSafeActionClient({
// You can provide a context builder function. In this case, context is used
// You can provide a middleware function. In this case, context is used
// for (fake) auth purposes.
buildContext: () => {
middleware() {
const userId = randomUUID();

console.log("HELLO FROM ACTION MIDDLEWARE, USER ID:", userId);

return {
userId: randomUUID(),
userId,
};
},
middleware(ctx) {
console.log("HELLO FROM ACTION MIDDLEWARE, USER ID:", ctx.userId);
},
});
11 changes: 5 additions & 6 deletions packages/next-safe-action/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This is the documentation for version 4 of the library, the current one. If you
## Features
- ✅ Pretty simple
- ✅ End to end type safety
-Context based clients
-Middleware functions (with context)
- ✅ Input validation
- ✅ Direct or hook usage from client
- ✅ Optimistic updates
Expand Down Expand Up @@ -367,7 +367,7 @@ It returns the same four keys as the regular `useAction` hook, plus one addition

### Middleware function

You can provide a middleware function when initializing a new action client. It will be called before the action is executed, but after input validatio from the client. You can return an object from this function, that will then be passed as the second argument of the server code function, when creating new Server Actions. You can safely throw an error in this function's body; if that happens, the client will receive a `serverError` result.
You can provide a middleware function when initializing a new action client. It will be called before the action is executed, but after input validation from the client. You can optionally return anything you want from this function: the returned value will be passed as `context` (second argument) to the server code function, when creating new Server Actions. You can safely throw an error in this function's body; if that happens, the client will receive a `serverError` result.

```typescript
// src/lib/safe-action.ts
Expand Down Expand Up @@ -395,7 +395,7 @@ export const authAction = createSafeActionClient({
});
```

Then, you can use the previously defined client and access the context object:
Then, you can use the previously defined client and access `context`:

```typescript
"use server"; // don't forget to add this
Expand All @@ -405,9 +405,8 @@ import { authAction } from "@/lib/safe-action";

...

// [1]: Here you have access to the context object, in this case it's just
// `{ userId }`, which comes from the return type of the `middleware` function
// declared in the previous step.
// [1]: Here you have access to the context, in this case it's just `{ userId }`,
// which comes from the return type of the `middleware` function declared in the previous step.
export const editUser = authAction(input, async (parsedInput, { userId /* [1] */ }) => {
console.log(userId); // will output: "coolest_user_id",
...
Expand Down
12 changes: 4 additions & 8 deletions packages/next-safe-action/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import { DEFAULT_SERVER_ERROR, isError, isNextNotFoundError, isNextRedirectError
*
* {@link https://github.com/TheEdoRan/next-safe-action/tree/main/packages/next-safe-action#project-configuration See an example}
*/
export const createSafeActionClient = <Context extends object>(createOpts?: {
buildContext?: () => MaybePromise<Context>;
export const createSafeActionClient = <Context>(createOpts?: {
handleServerErrorLog?: (e: Error) => MaybePromise<void>;
handleReturnedServerError?: (e: Error) => MaybePromise<{ serverError: string }>;
middleware?: (ctx: Context) => MaybePromise<void>;
middleware?: () => MaybePromise<Context>;
}) => {
// If server log function is not provided, default to `console.error` for logging
// server error messages.
Expand Down Expand Up @@ -54,12 +53,9 @@ export const createSafeActionClient = <Context extends object>(createOpts?: {
};
}

// Get the context if `buildContext` is provided, otherwise use an
// Get the context if `middleware` is provided, otherwise use an
// empty object.
const ctx = ((await Promise.resolve(createOpts?.buildContext?.())) ?? {}) as Context;

// Execute middleware code, if Promise is provided.
await Promise.resolve(createOpts?.middleware?.(ctx));
const ctx = (await Promise.resolve(createOpts?.middleware?.())) as Context;

return { data: await serverCode(parsedInput.data, ctx) };
} catch (e: unknown) {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type SafeAction<Schema extends z.ZodTypeAny, Data> = (input: z.input<Sche
/**
* Type of the function that executes server code when defining a new safe action.
*/
export type ServerCode<Schema extends z.ZodTypeAny, Data, Context extends object> = (
export type ServerCode<Schema extends z.ZodTypeAny, Data, Context> = (
parsedInput: z.input<Schema>,
ctx: Context
) => Promise<Data>;
Expand Down

0 comments on commit 116da1d

Please sign in to comment.