use-server-action 1.1.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -32
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/{server-action-HthxxP-Y.d.mts → server-action-Cm80HhlX.d.mts} +18 -0
- package/dist/{server-action-HthxxP-Y.d.ts → server-action-Cm80HhlX.d.ts} +18 -0
- package/dist/server.d.mts +220 -37
- package/dist/server.d.ts +220 -37
- package/dist/server.js +92 -4
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +90 -3
- package/dist/server.mjs.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -16,26 +16,30 @@ npm install use-server-action
|
|
|
16
16
|
// app/actions.ts
|
|
17
17
|
"use server";
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { createAction, createContextMiddleware } from "use-server-action/server";
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
// Simple action
|
|
22
|
+
export const createUser = createAction<{ name: string }>()
|
|
23
|
+
.handle(async (ctx, input) => {
|
|
24
|
+
const user = await db.user.create({ data: { name: input.name } });
|
|
25
|
+
return { ok: true, data: user };
|
|
26
|
+
});
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
// With authentication middleware
|
|
29
|
+
const withAuth = createContextMiddleware(async (next, ctx, ...args) => {
|
|
30
|
+
const user = await getUser();
|
|
31
|
+
if (!user) {
|
|
32
|
+
return { ok: false, message: "Unauthorized", code: "UNAUTHORIZED" };
|
|
33
|
+
}
|
|
34
|
+
return next({ ...ctx, user }, ...args);
|
|
28
35
|
});
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
await db.user.delete({ where: { id } });
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
return error("Failed to delete user", "DELETE_FAILED");
|
|
37
|
-
}
|
|
38
|
-
};
|
|
37
|
+
export const deleteUser = createAction<{ id: string }>()
|
|
38
|
+
.use(withAuth)
|
|
39
|
+
.handle(async (ctx, input) => {
|
|
40
|
+
await db.user.delete({ where: { id: input.id, ownerId: ctx.user.id } });
|
|
41
|
+
return { ok: true, data: { deleted: true } };
|
|
42
|
+
});
|
|
39
43
|
```
|
|
40
44
|
|
|
41
45
|
### 2. Use in a client component
|
|
@@ -47,26 +51,14 @@ import { useServerAction } from "use-server-action";
|
|
|
47
51
|
import { createUser } from "./actions";
|
|
48
52
|
|
|
49
53
|
export function CreateUserForm() {
|
|
50
|
-
const {
|
|
51
|
-
execute,
|
|
52
|
-
data,
|
|
53
|
-
error,
|
|
54
|
-
isPending,
|
|
55
|
-
isSuccess,
|
|
56
|
-
isError,
|
|
57
|
-
reset,
|
|
58
|
-
} = useServerAction({
|
|
54
|
+
const { execute, data, error, isPending, isSuccess, isError } = useServerAction({
|
|
59
55
|
action: createUser,
|
|
60
|
-
onSuccess: (user) =>
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
onError: (message, code) => {
|
|
64
|
-
console.error(`Error [${code}]:`, message);
|
|
65
|
-
},
|
|
56
|
+
onSuccess: (user) => console.log("User created:", user),
|
|
57
|
+
onError: (message, code) => console.error(`Error [${code}]:`, message),
|
|
66
58
|
});
|
|
67
59
|
|
|
68
60
|
return (
|
|
69
|
-
<form action={(formData) => execute(formData.get("name") as string)}>
|
|
61
|
+
<form action={(formData) => execute({ name: formData.get("name") as string })}>
|
|
70
62
|
<input name="name" placeholder="Name" disabled={isPending} />
|
|
71
63
|
<button type="submit" disabled={isPending}>
|
|
72
64
|
{isPending ? "Creating..." : "Create User"}
|
|
@@ -78,6 +70,14 @@ export function CreateUserForm() {
|
|
|
78
70
|
}
|
|
79
71
|
```
|
|
80
72
|
|
|
73
|
+
## Features
|
|
74
|
+
|
|
75
|
+
- **Type-safe** - Full TypeScript support with inferred types for context and inputs
|
|
76
|
+
- **Middleware support** - Chain middleware with `createAction().use(middleware)`
|
|
77
|
+
- **Context accumulation** - Middleware can add typed context for downstream handlers
|
|
78
|
+
- **Automatic error handling** - Thrown errors are caught and returned as error results
|
|
79
|
+
- **Zod validation** - Built-in `withZodValidation` middleware for input validation
|
|
80
|
+
|
|
81
81
|
## Documentation
|
|
82
82
|
|
|
83
83
|
You can view the documentation [here](https://use-server-action.jackh.sh)
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as ServerActionResult } from './server-action-
|
|
2
|
-
export { b as ServerActionError, c as ServerActionFn, a as ServerActionSuccess } from './server-action-
|
|
1
|
+
import { S as ServerActionResult } from './server-action-Cm80HhlX.mjs';
|
|
2
|
+
export { b as ServerActionError, c as ServerActionFn, a as ServerActionSuccess } from './server-action-Cm80HhlX.mjs';
|
|
3
3
|
|
|
4
4
|
type UseServerActionInput<P extends unknown[], T> = {
|
|
5
5
|
action: (...args: P) => Promise<ServerActionResult<T>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as ServerActionResult } from './server-action-
|
|
2
|
-
export { b as ServerActionError, c as ServerActionFn, a as ServerActionSuccess } from './server-action-
|
|
1
|
+
import { S as ServerActionResult } from './server-action-Cm80HhlX.js';
|
|
2
|
+
export { b as ServerActionError, c as ServerActionFn, a as ServerActionSuccess } from './server-action-Cm80HhlX.js';
|
|
3
3
|
|
|
4
4
|
type UseServerActionInput<P extends unknown[], T> = {
|
|
5
5
|
action: (...args: P) => Promise<ServerActionResult<T>>;
|
|
@@ -17,6 +17,24 @@ type ServerActionOptions = {
|
|
|
17
17
|
/**
|
|
18
18
|
* Wraps an async function to return a standardized ServerActionResult.
|
|
19
19
|
* Catches any thrown errors and converts them to error results.
|
|
20
|
+
*
|
|
21
|
+
* @deprecated Use `createAction().input(schema).handle(fn)` instead.
|
|
22
|
+
* The new API provides better type inference and built-in validation.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* // Old way (deprecated):
|
|
27
|
+
* const myAction = serverAction(async (input: MyInput) => {
|
|
28
|
+
* return await doSomething(input);
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // New way:
|
|
32
|
+
* const myAction = createAction()
|
|
33
|
+
* .input(mySchema)
|
|
34
|
+
* .handle(async (ctx, input) => {
|
|
35
|
+
* return { ok: true, data: await doSomething(input) };
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
20
38
|
*/
|
|
21
39
|
declare function serverAction<P extends unknown[], T>(fn: (...args: P) => Promise<T>, options?: ServerActionOptions): ServerActionFn<P, T>;
|
|
22
40
|
/**
|
|
@@ -17,6 +17,24 @@ type ServerActionOptions = {
|
|
|
17
17
|
/**
|
|
18
18
|
* Wraps an async function to return a standardized ServerActionResult.
|
|
19
19
|
* Catches any thrown errors and converts them to error results.
|
|
20
|
+
*
|
|
21
|
+
* @deprecated Use `createAction().input(schema).handle(fn)` instead.
|
|
22
|
+
* The new API provides better type inference and built-in validation.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* // Old way (deprecated):
|
|
27
|
+
* const myAction = serverAction(async (input: MyInput) => {
|
|
28
|
+
* return await doSomething(input);
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // New way:
|
|
32
|
+
* const myAction = createAction()
|
|
33
|
+
* .input(mySchema)
|
|
34
|
+
* .handle(async (ctx, input) => {
|
|
35
|
+
* return { ok: true, data: await doSomething(input) };
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
20
38
|
*/
|
|
21
39
|
declare function serverAction<P extends unknown[], T>(fn: (...args: P) => Promise<T>, options?: ServerActionOptions): ServerActionFn<P, T>;
|
|
22
40
|
/**
|
package/dist/server.d.mts
CHANGED
|
@@ -1,11 +1,191 @@
|
|
|
1
|
-
import { S as ServerActionResult } from './server-action-
|
|
2
|
-
export { b as ServerActionError, c as ServerActionFn, a as ServerActionSuccess, e as error, f as isError, i as isSuccess, s as serverAction, d as success, u as unwrap, g as unwrapOr } from './server-action-
|
|
1
|
+
import { S as ServerActionResult } from './server-action-Cm80HhlX.mjs';
|
|
2
|
+
export { b as ServerActionError, c as ServerActionFn, a as ServerActionSuccess, e as error, f as isError, i as isSuccess, s as serverAction, d as success, u as unwrap, g as unwrapOr } from './server-action-Cm80HhlX.mjs';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Base context type - all contexts extend from this
|
|
6
|
+
*/
|
|
7
|
+
type BaseContext = Record<string, unknown>;
|
|
4
8
|
/**
|
|
5
9
|
* A middleware function that wraps a server action.
|
|
6
10
|
* Receives the next function in the chain and the parameters passed to the action.
|
|
7
11
|
*/
|
|
8
12
|
type Middleware<P extends unknown[], T> = (next: (...params: P) => Promise<ServerActionResult<T>>, ...params: P) => Promise<ServerActionResult<T>>;
|
|
13
|
+
/**
|
|
14
|
+
* A context-aware middleware that can receive context from previous middleware
|
|
15
|
+
* and add new context for downstream middleware.
|
|
16
|
+
*
|
|
17
|
+
* @template P - The parameter types for the action
|
|
18
|
+
* @template T - The return type of the action
|
|
19
|
+
* @template CtxIn - The context type this middleware expects to receive
|
|
20
|
+
* @template CtxOut - The context type this middleware adds (merged with CtxIn for next)
|
|
21
|
+
*/
|
|
22
|
+
type ContextMiddleware<P extends unknown[], T, CtxIn extends BaseContext = BaseContext, CtxOut extends BaseContext = BaseContext> = (next: (ctx: CtxIn & CtxOut, ...params: P) => Promise<ServerActionResult<T>>, ctx: CtxIn, ...params: P) => Promise<ServerActionResult<T>>;
|
|
23
|
+
/**
|
|
24
|
+
* A Zod-like schema interface for validation.
|
|
25
|
+
* Works with Zod, Valibot, or any schema library with a compatible safeParse method.
|
|
26
|
+
*/
|
|
27
|
+
type ValidationSchema<T> = {
|
|
28
|
+
safeParse(data: unknown): {
|
|
29
|
+
success: true;
|
|
30
|
+
data: T;
|
|
31
|
+
} | {
|
|
32
|
+
success: false;
|
|
33
|
+
error: {
|
|
34
|
+
message?: string;
|
|
35
|
+
errors?: Array<{
|
|
36
|
+
message: string;
|
|
37
|
+
}>;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
type WithValidationOptions = {
|
|
42
|
+
/** Error code to return on validation failure. Defaults to "VALIDATION_ERROR" */
|
|
43
|
+
code?: string;
|
|
44
|
+
/** Custom error message formatter */
|
|
45
|
+
formatError?: (error: {
|
|
46
|
+
message?: string;
|
|
47
|
+
errors?: Array<{
|
|
48
|
+
message: string;
|
|
49
|
+
}>;
|
|
50
|
+
}) => string;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Creates a type-safe context-aware middleware.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* type User = { id: string; name: string };
|
|
59
|
+
*
|
|
60
|
+
* const withAuth = createContextMiddleware<
|
|
61
|
+
* [string], // Parameters
|
|
62
|
+
* SomeReturnType, // Return type
|
|
63
|
+
* {}, // Input context (none required)
|
|
64
|
+
* { user: User } // Output context (adds user)
|
|
65
|
+
* >(async (next, ctx, input) => {
|
|
66
|
+
* const user = await authenticate();
|
|
67
|
+
* if (!user) {
|
|
68
|
+
* return { ok: false, message: "Unauthorized", code: "UNAUTHORIZED" };
|
|
69
|
+
* }
|
|
70
|
+
* // Pass the new context with user added
|
|
71
|
+
* return next({ ...ctx, user }, input);
|
|
72
|
+
* });
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
declare function createContextMiddleware<P extends unknown[], T, CtxIn extends BaseContext = BaseContext, CtxOut extends BaseContext = BaseContext>(handler: ContextMiddleware<P, T, CtxIn, CtxOut>): ContextMiddleware<P, T, CtxIn, CtxOut>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A builder for creating server actions with type-safe context accumulation.
|
|
79
|
+
*
|
|
80
|
+
* @template TInput - The input parameters as a tuple type
|
|
81
|
+
* @template TContext - The accumulated context type from all middleware
|
|
82
|
+
*/
|
|
83
|
+
declare class ActionBuilder<TInput extends unknown[] = unknown[], TContext extends BaseContext = {}> {
|
|
84
|
+
private middlewares;
|
|
85
|
+
private constructor();
|
|
86
|
+
/**
|
|
87
|
+
* Create a new ActionBuilder instance
|
|
88
|
+
*/
|
|
89
|
+
static create<TInput extends unknown[]>(): ActionBuilder<TInput, {}>;
|
|
90
|
+
/**
|
|
91
|
+
* Add a context-aware middleware to the chain.
|
|
92
|
+
* The middleware receives the accumulated context and can add new context.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* const withUser = createContextMiddleware(async (next, ctx, ...args) => {
|
|
97
|
+
* const user = await getUser();
|
|
98
|
+
* if (!user) {
|
|
99
|
+
* return { ok: false, message: "Unauthorized", code: "UNAUTHORIZED" };
|
|
100
|
+
* }
|
|
101
|
+
* return next({ ...ctx, user }, ...args);
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* const action = createAction<[{ name: string }]>()
|
|
105
|
+
* .use(withUser)
|
|
106
|
+
* .handle(async (ctx, input) => {
|
|
107
|
+
* // ctx.user is fully typed!
|
|
108
|
+
* });
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
use<CtxOut extends BaseContext>(middleware: ContextMiddleware<TInput, any, TContext, CtxOut>): ActionBuilder<TInput, TContext & CtxOut>;
|
|
112
|
+
/**
|
|
113
|
+
* Add a regular (non-context) middleware to the chain.
|
|
114
|
+
* The middleware can transform input/output but doesn't modify context.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* const withLogging = createMiddleware(async (next, ...args) => {
|
|
119
|
+
* console.log("Args:", args);
|
|
120
|
+
* const result = await next(...args);
|
|
121
|
+
* console.log("Result:", result);
|
|
122
|
+
* return result;
|
|
123
|
+
* });
|
|
124
|
+
*
|
|
125
|
+
* const action = createAction<[string]>()
|
|
126
|
+
* .use(withLogging)
|
|
127
|
+
* .handle(async (ctx, input) => { ... });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
use(middleware: Middleware<TInput, any>): ActionBuilder<TInput, TContext>;
|
|
131
|
+
/**
|
|
132
|
+
* Define the action handler. This finalizes the builder and returns the executable action.
|
|
133
|
+
* The handler receives the accumulated context and input parameters.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* const action = createAction<[{ name: string; email: string }]>()
|
|
138
|
+
* .use(withUser)
|
|
139
|
+
* .handle(async (ctx, input) => {
|
|
140
|
+
* // ctx and input are fully typed
|
|
141
|
+
* return { ok: true, data: result };
|
|
142
|
+
* });
|
|
143
|
+
*
|
|
144
|
+
* // Call the action
|
|
145
|
+
* const result = await action({ name: "John", email: "john@example.com" });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
handle<TOutput>(handler: (ctx: TContext, ...args: TInput) => Promise<ServerActionResult<TOutput>>): (...args: TInput) => Promise<ServerActionResult<TOutput>>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Converts a type to a tuple of arguments.
|
|
152
|
+
* - `void` becomes `[]` (no args)
|
|
153
|
+
* - Single type `T` becomes `[T]`
|
|
154
|
+
* - Tuple type `[A, B]` stays as `[A, B]`
|
|
155
|
+
*/
|
|
156
|
+
type ToArgs<T> = [T] extends [void] ? [] : T extends unknown[] ? T : [T];
|
|
157
|
+
/**
|
|
158
|
+
* Creates a new action builder with type-safe context accumulation.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* // Single input parameter
|
|
163
|
+
* const createUser = createAction<{ name: string; email: string }>()
|
|
164
|
+
* .use(withUser)
|
|
165
|
+
* .handle(async (ctx, input) => {
|
|
166
|
+
* await db.users.create({ ...input, createdBy: ctx.user.id });
|
|
167
|
+
* return { ok: true, data: { success: true } };
|
|
168
|
+
* });
|
|
169
|
+
*
|
|
170
|
+
* // Multiple input parameters (use tuple)
|
|
171
|
+
* const updateUser = createAction<[string, { name: string }]>()
|
|
172
|
+
* .use(withUser)
|
|
173
|
+
* .handle(async (ctx, id, data) => {
|
|
174
|
+
* await db.users.update(id, data);
|
|
175
|
+
* return { ok: true, data: { success: true } };
|
|
176
|
+
* });
|
|
177
|
+
*
|
|
178
|
+
* // With validation middleware
|
|
179
|
+
* const createPost = createAction<z.infer<typeof postSchema>>()
|
|
180
|
+
* .use(withZodValidation(postSchema))
|
|
181
|
+
* .use(withUser)
|
|
182
|
+
* .handle(async (ctx, input) => {
|
|
183
|
+
* return { ok: true, data: await db.posts.create(input) };
|
|
184
|
+
* });
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
declare function createAction<TInput = void>(): ActionBuilder<ToArgs<TInput>, {}>;
|
|
188
|
+
|
|
9
189
|
/**
|
|
10
190
|
* Creates a type-safe middleware function.
|
|
11
191
|
*
|
|
@@ -24,77 +204,80 @@ declare function createMiddleware<P extends unknown[], T>(handler: Middleware<P,
|
|
|
24
204
|
* Applies middleware to a server action.
|
|
25
205
|
* Middleware is executed in order (first middleware wraps second, etc).
|
|
26
206
|
*
|
|
207
|
+
* @deprecated Use `createAction().input(schema).use(middleware).handle(fn)` instead.
|
|
208
|
+
* This provides better type inference and a more composable API.
|
|
209
|
+
*
|
|
27
210
|
* @example
|
|
28
211
|
* ```ts
|
|
212
|
+
* // Old way (deprecated):
|
|
29
213
|
* const protectedAction = applyMiddleware(
|
|
30
214
|
* myServerAction,
|
|
31
215
|
* [withAuth, withLogging, withValidation]
|
|
32
216
|
* );
|
|
217
|
+
*
|
|
218
|
+
* // New way:
|
|
219
|
+
* const protectedAction = createAction()
|
|
220
|
+
* .input(schema)
|
|
221
|
+
* .use(withAuth)
|
|
222
|
+
* .use(withLogging)
|
|
223
|
+
* .handle(async (ctx, input) => { ... });
|
|
33
224
|
* ```
|
|
34
225
|
*/
|
|
35
226
|
declare function applyMiddleware<P extends unknown[], T>(action: (...params: P) => Promise<ServerActionResult<T>>, middleware: Middleware<P, T>[]): (...params: P) => Promise<ServerActionResult<T>>;
|
|
36
227
|
/**
|
|
37
228
|
* Composes multiple middleware into a single middleware.
|
|
38
229
|
*
|
|
230
|
+
* @deprecated Use `createAction().use(mw1).use(mw2).handle(fn)` instead.
|
|
231
|
+
* The builder pattern provides better type inference for chained middleware.
|
|
232
|
+
*
|
|
39
233
|
* @example
|
|
40
234
|
* ```ts
|
|
235
|
+
* // Old way (deprecated):
|
|
41
236
|
* const combined = composeMiddleware(withAuth, withLogging, withValidation);
|
|
42
237
|
* const protectedAction = applyMiddleware(myAction, [combined]);
|
|
238
|
+
*
|
|
239
|
+
* // New way:
|
|
240
|
+
* const protectedAction = createAction()
|
|
241
|
+
* .input(schema)
|
|
242
|
+
* .use(withAuth)
|
|
243
|
+
* .use(withLogging)
|
|
244
|
+
* .handle(async (ctx, input) => { ... });
|
|
43
245
|
* ```
|
|
44
246
|
*/
|
|
45
247
|
declare function composeMiddleware<P extends unknown[], T>(...middleware: Middleware<P, T>[]): Middleware<P, T>;
|
|
46
|
-
/**
|
|
47
|
-
* A Zod-like schema interface for validation.
|
|
48
|
-
* Works with Zod, Valibot, or any schema library with a compatible safeParse method.
|
|
49
|
-
*/
|
|
50
|
-
type ValidationSchema<T> = {
|
|
51
|
-
safeParse(data: unknown): {
|
|
52
|
-
success: true;
|
|
53
|
-
data: T;
|
|
54
|
-
} | {
|
|
55
|
-
success: false;
|
|
56
|
-
error: {
|
|
57
|
-
message?: string;
|
|
58
|
-
errors?: Array<{
|
|
59
|
-
message: string;
|
|
60
|
-
}>;
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
};
|
|
64
|
-
type WithValidationOptions = {
|
|
65
|
-
/** Error code to return on validation failure. Defaults to "VALIDATION_ERROR" */
|
|
66
|
-
code?: string;
|
|
67
|
-
/** Custom error message formatter */
|
|
68
|
-
formatError?: (error: {
|
|
69
|
-
message?: string;
|
|
70
|
-
errors?: Array<{
|
|
71
|
-
message: string;
|
|
72
|
-
}>;
|
|
73
|
-
}) => string;
|
|
74
|
-
};
|
|
75
248
|
/**
|
|
76
249
|
* Creates a middleware that validates the first parameter against a schema.
|
|
77
250
|
* Works with Zod, Valibot, or any library with a compatible safeParse method.
|
|
78
251
|
*
|
|
252
|
+
* @deprecated Use `createAction().input(schema).handle(fn)` instead.
|
|
253
|
+
* The `.input()` method provides automatic type inference from the schema.
|
|
254
|
+
*
|
|
79
255
|
* @example
|
|
80
256
|
* ```ts
|
|
81
257
|
* import { z } from "zod";
|
|
82
|
-
* import { withValidation, applyMiddleware } from "use-server-action/server";
|
|
83
258
|
*
|
|
84
|
-
* const
|
|
259
|
+
* const schema = z.object({
|
|
85
260
|
* name: z.string().min(1),
|
|
86
261
|
* email: z.string().email(),
|
|
87
262
|
* });
|
|
88
263
|
*
|
|
264
|
+
* // Old way (deprecated):
|
|
89
265
|
* const createUser = applyMiddleware(
|
|
90
|
-
* serverAction(async (input: z.infer<typeof
|
|
266
|
+
* serverAction(async (input: z.infer<typeof schema>) => {
|
|
91
267
|
* return await db.user.create({ data: input });
|
|
92
268
|
* }),
|
|
93
|
-
* [
|
|
269
|
+
* [withZodValidation(schema)]
|
|
94
270
|
* );
|
|
271
|
+
*
|
|
272
|
+
* // New way:
|
|
273
|
+
* const createUser = createAction()
|
|
274
|
+
* .input(schema) // Type is inferred automatically!
|
|
275
|
+
* .handle(async (ctx, input) => {
|
|
276
|
+
* return { ok: true, data: await db.user.create({ data: input }) };
|
|
277
|
+
* });
|
|
95
278
|
* ```
|
|
96
279
|
*/
|
|
97
|
-
declare function
|
|
280
|
+
declare function withZodValidation<TInput, T>(schema: ValidationSchema<TInput>, options?: WithValidationOptions): Middleware<[TInput], T>;
|
|
98
281
|
/**
|
|
99
282
|
* Creates a middleware that logs action calls and results.
|
|
100
283
|
*/
|
|
@@ -104,4 +287,4 @@ declare function withLogging<P extends unknown[], T>(logger?: {
|
|
|
104
287
|
onError?: (message: string, code: string | undefined, params: P) => void;
|
|
105
288
|
}): Middleware<P, T>;
|
|
106
289
|
|
|
107
|
-
export { type Middleware, ServerActionResult, type ValidationSchema, type WithValidationOptions, applyMiddleware, composeMiddleware, createMiddleware, withLogging,
|
|
290
|
+
export { type BaseContext, type ContextMiddleware, type Middleware, ServerActionResult, type ValidationSchema, type WithValidationOptions, applyMiddleware, composeMiddleware, createAction, createContextMiddleware, createMiddleware, withLogging, withZodValidation };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,11 +1,191 @@
|
|
|
1
|
-
import { S as ServerActionResult } from './server-action-
|
|
2
|
-
export { b as ServerActionError, c as ServerActionFn, a as ServerActionSuccess, e as error, f as isError, i as isSuccess, s as serverAction, d as success, u as unwrap, g as unwrapOr } from './server-action-
|
|
1
|
+
import { S as ServerActionResult } from './server-action-Cm80HhlX.js';
|
|
2
|
+
export { b as ServerActionError, c as ServerActionFn, a as ServerActionSuccess, e as error, f as isError, i as isSuccess, s as serverAction, d as success, u as unwrap, g as unwrapOr } from './server-action-Cm80HhlX.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Base context type - all contexts extend from this
|
|
6
|
+
*/
|
|
7
|
+
type BaseContext = Record<string, unknown>;
|
|
4
8
|
/**
|
|
5
9
|
* A middleware function that wraps a server action.
|
|
6
10
|
* Receives the next function in the chain and the parameters passed to the action.
|
|
7
11
|
*/
|
|
8
12
|
type Middleware<P extends unknown[], T> = (next: (...params: P) => Promise<ServerActionResult<T>>, ...params: P) => Promise<ServerActionResult<T>>;
|
|
13
|
+
/**
|
|
14
|
+
* A context-aware middleware that can receive context from previous middleware
|
|
15
|
+
* and add new context for downstream middleware.
|
|
16
|
+
*
|
|
17
|
+
* @template P - The parameter types for the action
|
|
18
|
+
* @template T - The return type of the action
|
|
19
|
+
* @template CtxIn - The context type this middleware expects to receive
|
|
20
|
+
* @template CtxOut - The context type this middleware adds (merged with CtxIn for next)
|
|
21
|
+
*/
|
|
22
|
+
type ContextMiddleware<P extends unknown[], T, CtxIn extends BaseContext = BaseContext, CtxOut extends BaseContext = BaseContext> = (next: (ctx: CtxIn & CtxOut, ...params: P) => Promise<ServerActionResult<T>>, ctx: CtxIn, ...params: P) => Promise<ServerActionResult<T>>;
|
|
23
|
+
/**
|
|
24
|
+
* A Zod-like schema interface for validation.
|
|
25
|
+
* Works with Zod, Valibot, or any schema library with a compatible safeParse method.
|
|
26
|
+
*/
|
|
27
|
+
type ValidationSchema<T> = {
|
|
28
|
+
safeParse(data: unknown): {
|
|
29
|
+
success: true;
|
|
30
|
+
data: T;
|
|
31
|
+
} | {
|
|
32
|
+
success: false;
|
|
33
|
+
error: {
|
|
34
|
+
message?: string;
|
|
35
|
+
errors?: Array<{
|
|
36
|
+
message: string;
|
|
37
|
+
}>;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
type WithValidationOptions = {
|
|
42
|
+
/** Error code to return on validation failure. Defaults to "VALIDATION_ERROR" */
|
|
43
|
+
code?: string;
|
|
44
|
+
/** Custom error message formatter */
|
|
45
|
+
formatError?: (error: {
|
|
46
|
+
message?: string;
|
|
47
|
+
errors?: Array<{
|
|
48
|
+
message: string;
|
|
49
|
+
}>;
|
|
50
|
+
}) => string;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Creates a type-safe context-aware middleware.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* type User = { id: string; name: string };
|
|
59
|
+
*
|
|
60
|
+
* const withAuth = createContextMiddleware<
|
|
61
|
+
* [string], // Parameters
|
|
62
|
+
* SomeReturnType, // Return type
|
|
63
|
+
* {}, // Input context (none required)
|
|
64
|
+
* { user: User } // Output context (adds user)
|
|
65
|
+
* >(async (next, ctx, input) => {
|
|
66
|
+
* const user = await authenticate();
|
|
67
|
+
* if (!user) {
|
|
68
|
+
* return { ok: false, message: "Unauthorized", code: "UNAUTHORIZED" };
|
|
69
|
+
* }
|
|
70
|
+
* // Pass the new context with user added
|
|
71
|
+
* return next({ ...ctx, user }, input);
|
|
72
|
+
* });
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
declare function createContextMiddleware<P extends unknown[], T, CtxIn extends BaseContext = BaseContext, CtxOut extends BaseContext = BaseContext>(handler: ContextMiddleware<P, T, CtxIn, CtxOut>): ContextMiddleware<P, T, CtxIn, CtxOut>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A builder for creating server actions with type-safe context accumulation.
|
|
79
|
+
*
|
|
80
|
+
* @template TInput - The input parameters as a tuple type
|
|
81
|
+
* @template TContext - The accumulated context type from all middleware
|
|
82
|
+
*/
|
|
83
|
+
declare class ActionBuilder<TInput extends unknown[] = unknown[], TContext extends BaseContext = {}> {
|
|
84
|
+
private middlewares;
|
|
85
|
+
private constructor();
|
|
86
|
+
/**
|
|
87
|
+
* Create a new ActionBuilder instance
|
|
88
|
+
*/
|
|
89
|
+
static create<TInput extends unknown[]>(): ActionBuilder<TInput, {}>;
|
|
90
|
+
/**
|
|
91
|
+
* Add a context-aware middleware to the chain.
|
|
92
|
+
* The middleware receives the accumulated context and can add new context.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* const withUser = createContextMiddleware(async (next, ctx, ...args) => {
|
|
97
|
+
* const user = await getUser();
|
|
98
|
+
* if (!user) {
|
|
99
|
+
* return { ok: false, message: "Unauthorized", code: "UNAUTHORIZED" };
|
|
100
|
+
* }
|
|
101
|
+
* return next({ ...ctx, user }, ...args);
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* const action = createAction<[{ name: string }]>()
|
|
105
|
+
* .use(withUser)
|
|
106
|
+
* .handle(async (ctx, input) => {
|
|
107
|
+
* // ctx.user is fully typed!
|
|
108
|
+
* });
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
use<CtxOut extends BaseContext>(middleware: ContextMiddleware<TInput, any, TContext, CtxOut>): ActionBuilder<TInput, TContext & CtxOut>;
|
|
112
|
+
/**
|
|
113
|
+
* Add a regular (non-context) middleware to the chain.
|
|
114
|
+
* The middleware can transform input/output but doesn't modify context.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* const withLogging = createMiddleware(async (next, ...args) => {
|
|
119
|
+
* console.log("Args:", args);
|
|
120
|
+
* const result = await next(...args);
|
|
121
|
+
* console.log("Result:", result);
|
|
122
|
+
* return result;
|
|
123
|
+
* });
|
|
124
|
+
*
|
|
125
|
+
* const action = createAction<[string]>()
|
|
126
|
+
* .use(withLogging)
|
|
127
|
+
* .handle(async (ctx, input) => { ... });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
use(middleware: Middleware<TInput, any>): ActionBuilder<TInput, TContext>;
|
|
131
|
+
/**
|
|
132
|
+
* Define the action handler. This finalizes the builder and returns the executable action.
|
|
133
|
+
* The handler receives the accumulated context and input parameters.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* const action = createAction<[{ name: string; email: string }]>()
|
|
138
|
+
* .use(withUser)
|
|
139
|
+
* .handle(async (ctx, input) => {
|
|
140
|
+
* // ctx and input are fully typed
|
|
141
|
+
* return { ok: true, data: result };
|
|
142
|
+
* });
|
|
143
|
+
*
|
|
144
|
+
* // Call the action
|
|
145
|
+
* const result = await action({ name: "John", email: "john@example.com" });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
handle<TOutput>(handler: (ctx: TContext, ...args: TInput) => Promise<ServerActionResult<TOutput>>): (...args: TInput) => Promise<ServerActionResult<TOutput>>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Converts a type to a tuple of arguments.
|
|
152
|
+
* - `void` becomes `[]` (no args)
|
|
153
|
+
* - Single type `T` becomes `[T]`
|
|
154
|
+
* - Tuple type `[A, B]` stays as `[A, B]`
|
|
155
|
+
*/
|
|
156
|
+
type ToArgs<T> = [T] extends [void] ? [] : T extends unknown[] ? T : [T];
|
|
157
|
+
/**
|
|
158
|
+
* Creates a new action builder with type-safe context accumulation.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* // Single input parameter
|
|
163
|
+
* const createUser = createAction<{ name: string; email: string }>()
|
|
164
|
+
* .use(withUser)
|
|
165
|
+
* .handle(async (ctx, input) => {
|
|
166
|
+
* await db.users.create({ ...input, createdBy: ctx.user.id });
|
|
167
|
+
* return { ok: true, data: { success: true } };
|
|
168
|
+
* });
|
|
169
|
+
*
|
|
170
|
+
* // Multiple input parameters (use tuple)
|
|
171
|
+
* const updateUser = createAction<[string, { name: string }]>()
|
|
172
|
+
* .use(withUser)
|
|
173
|
+
* .handle(async (ctx, id, data) => {
|
|
174
|
+
* await db.users.update(id, data);
|
|
175
|
+
* return { ok: true, data: { success: true } };
|
|
176
|
+
* });
|
|
177
|
+
*
|
|
178
|
+
* // With validation middleware
|
|
179
|
+
* const createPost = createAction<z.infer<typeof postSchema>>()
|
|
180
|
+
* .use(withZodValidation(postSchema))
|
|
181
|
+
* .use(withUser)
|
|
182
|
+
* .handle(async (ctx, input) => {
|
|
183
|
+
* return { ok: true, data: await db.posts.create(input) };
|
|
184
|
+
* });
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
declare function createAction<TInput = void>(): ActionBuilder<ToArgs<TInput>, {}>;
|
|
188
|
+
|
|
9
189
|
/**
|
|
10
190
|
* Creates a type-safe middleware function.
|
|
11
191
|
*
|
|
@@ -24,77 +204,80 @@ declare function createMiddleware<P extends unknown[], T>(handler: Middleware<P,
|
|
|
24
204
|
* Applies middleware to a server action.
|
|
25
205
|
* Middleware is executed in order (first middleware wraps second, etc).
|
|
26
206
|
*
|
|
207
|
+
* @deprecated Use `createAction().input(schema).use(middleware).handle(fn)` instead.
|
|
208
|
+
* This provides better type inference and a more composable API.
|
|
209
|
+
*
|
|
27
210
|
* @example
|
|
28
211
|
* ```ts
|
|
212
|
+
* // Old way (deprecated):
|
|
29
213
|
* const protectedAction = applyMiddleware(
|
|
30
214
|
* myServerAction,
|
|
31
215
|
* [withAuth, withLogging, withValidation]
|
|
32
216
|
* );
|
|
217
|
+
*
|
|
218
|
+
* // New way:
|
|
219
|
+
* const protectedAction = createAction()
|
|
220
|
+
* .input(schema)
|
|
221
|
+
* .use(withAuth)
|
|
222
|
+
* .use(withLogging)
|
|
223
|
+
* .handle(async (ctx, input) => { ... });
|
|
33
224
|
* ```
|
|
34
225
|
*/
|
|
35
226
|
declare function applyMiddleware<P extends unknown[], T>(action: (...params: P) => Promise<ServerActionResult<T>>, middleware: Middleware<P, T>[]): (...params: P) => Promise<ServerActionResult<T>>;
|
|
36
227
|
/**
|
|
37
228
|
* Composes multiple middleware into a single middleware.
|
|
38
229
|
*
|
|
230
|
+
* @deprecated Use `createAction().use(mw1).use(mw2).handle(fn)` instead.
|
|
231
|
+
* The builder pattern provides better type inference for chained middleware.
|
|
232
|
+
*
|
|
39
233
|
* @example
|
|
40
234
|
* ```ts
|
|
235
|
+
* // Old way (deprecated):
|
|
41
236
|
* const combined = composeMiddleware(withAuth, withLogging, withValidation);
|
|
42
237
|
* const protectedAction = applyMiddleware(myAction, [combined]);
|
|
238
|
+
*
|
|
239
|
+
* // New way:
|
|
240
|
+
* const protectedAction = createAction()
|
|
241
|
+
* .input(schema)
|
|
242
|
+
* .use(withAuth)
|
|
243
|
+
* .use(withLogging)
|
|
244
|
+
* .handle(async (ctx, input) => { ... });
|
|
43
245
|
* ```
|
|
44
246
|
*/
|
|
45
247
|
declare function composeMiddleware<P extends unknown[], T>(...middleware: Middleware<P, T>[]): Middleware<P, T>;
|
|
46
|
-
/**
|
|
47
|
-
* A Zod-like schema interface for validation.
|
|
48
|
-
* Works with Zod, Valibot, or any schema library with a compatible safeParse method.
|
|
49
|
-
*/
|
|
50
|
-
type ValidationSchema<T> = {
|
|
51
|
-
safeParse(data: unknown): {
|
|
52
|
-
success: true;
|
|
53
|
-
data: T;
|
|
54
|
-
} | {
|
|
55
|
-
success: false;
|
|
56
|
-
error: {
|
|
57
|
-
message?: string;
|
|
58
|
-
errors?: Array<{
|
|
59
|
-
message: string;
|
|
60
|
-
}>;
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
};
|
|
64
|
-
type WithValidationOptions = {
|
|
65
|
-
/** Error code to return on validation failure. Defaults to "VALIDATION_ERROR" */
|
|
66
|
-
code?: string;
|
|
67
|
-
/** Custom error message formatter */
|
|
68
|
-
formatError?: (error: {
|
|
69
|
-
message?: string;
|
|
70
|
-
errors?: Array<{
|
|
71
|
-
message: string;
|
|
72
|
-
}>;
|
|
73
|
-
}) => string;
|
|
74
|
-
};
|
|
75
248
|
/**
|
|
76
249
|
* Creates a middleware that validates the first parameter against a schema.
|
|
77
250
|
* Works with Zod, Valibot, or any library with a compatible safeParse method.
|
|
78
251
|
*
|
|
252
|
+
* @deprecated Use `createAction().input(schema).handle(fn)` instead.
|
|
253
|
+
* The `.input()` method provides automatic type inference from the schema.
|
|
254
|
+
*
|
|
79
255
|
* @example
|
|
80
256
|
* ```ts
|
|
81
257
|
* import { z } from "zod";
|
|
82
|
-
* import { withValidation, applyMiddleware } from "use-server-action/server";
|
|
83
258
|
*
|
|
84
|
-
* const
|
|
259
|
+
* const schema = z.object({
|
|
85
260
|
* name: z.string().min(1),
|
|
86
261
|
* email: z.string().email(),
|
|
87
262
|
* });
|
|
88
263
|
*
|
|
264
|
+
* // Old way (deprecated):
|
|
89
265
|
* const createUser = applyMiddleware(
|
|
90
|
-
* serverAction(async (input: z.infer<typeof
|
|
266
|
+
* serverAction(async (input: z.infer<typeof schema>) => {
|
|
91
267
|
* return await db.user.create({ data: input });
|
|
92
268
|
* }),
|
|
93
|
-
* [
|
|
269
|
+
* [withZodValidation(schema)]
|
|
94
270
|
* );
|
|
271
|
+
*
|
|
272
|
+
* // New way:
|
|
273
|
+
* const createUser = createAction()
|
|
274
|
+
* .input(schema) // Type is inferred automatically!
|
|
275
|
+
* .handle(async (ctx, input) => {
|
|
276
|
+
* return { ok: true, data: await db.user.create({ data: input }) };
|
|
277
|
+
* });
|
|
95
278
|
* ```
|
|
96
279
|
*/
|
|
97
|
-
declare function
|
|
280
|
+
declare function withZodValidation<TInput, T>(schema: ValidationSchema<TInput>, options?: WithValidationOptions): Middleware<[TInput], T>;
|
|
98
281
|
/**
|
|
99
282
|
* Creates a middleware that logs action calls and results.
|
|
100
283
|
*/
|
|
@@ -104,4 +287,4 @@ declare function withLogging<P extends unknown[], T>(logger?: {
|
|
|
104
287
|
onError?: (message: string, code: string | undefined, params: P) => void;
|
|
105
288
|
}): Middleware<P, T>;
|
|
106
289
|
|
|
107
|
-
export { type Middleware, ServerActionResult, type ValidationSchema, type WithValidationOptions, applyMiddleware, composeMiddleware, createMiddleware, withLogging,
|
|
290
|
+
export { type BaseContext, type ContextMiddleware, type Middleware, ServerActionResult, type ValidationSchema, type WithValidationOptions, applyMiddleware, composeMiddleware, createAction, createContextMiddleware, createMiddleware, withLogging, withZodValidation };
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
"use server";
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -22,6 +23,8 @@ var server_exports = {};
|
|
|
22
23
|
__export(server_exports, {
|
|
23
24
|
applyMiddleware: () => applyMiddleware,
|
|
24
25
|
composeMiddleware: () => composeMiddleware,
|
|
26
|
+
createAction: () => createAction,
|
|
27
|
+
createContextMiddleware: () => createContextMiddleware,
|
|
25
28
|
createMiddleware: () => createMiddleware,
|
|
26
29
|
error: () => error,
|
|
27
30
|
isError: () => isError,
|
|
@@ -31,7 +34,7 @@ __export(server_exports, {
|
|
|
31
34
|
unwrap: () => unwrap,
|
|
32
35
|
unwrapOr: () => unwrapOr,
|
|
33
36
|
withLogging: () => withLogging,
|
|
34
|
-
|
|
37
|
+
withZodValidation: () => withZodValidation
|
|
35
38
|
});
|
|
36
39
|
module.exports = __toCommonJS(server_exports);
|
|
37
40
|
|
|
@@ -75,7 +78,90 @@ function unwrapOr(result, defaultValue) {
|
|
|
75
78
|
return defaultValue;
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
// src/server/middleware.ts
|
|
81
|
+
// src/server/context-middleware.ts
|
|
82
|
+
var CONTEXT_MIDDLEWARE = /* @__PURE__ */ Symbol("contextMiddleware");
|
|
83
|
+
function isContextMiddleware(fn) {
|
|
84
|
+
return typeof fn === "function" && fn[CONTEXT_MIDDLEWARE] === true;
|
|
85
|
+
}
|
|
86
|
+
function createContextMiddleware(handler) {
|
|
87
|
+
handler[CONTEXT_MIDDLEWARE] = true;
|
|
88
|
+
return handler;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/server/action-builder.ts
|
|
92
|
+
var ActionBuilder = class _ActionBuilder {
|
|
93
|
+
constructor(middlewares = []) {
|
|
94
|
+
this.middlewares = [];
|
|
95
|
+
this.middlewares = middlewares;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Create a new ActionBuilder instance
|
|
99
|
+
*/
|
|
100
|
+
static create() {
|
|
101
|
+
return new _ActionBuilder();
|
|
102
|
+
}
|
|
103
|
+
use(middleware) {
|
|
104
|
+
return new _ActionBuilder([
|
|
105
|
+
...this.middlewares,
|
|
106
|
+
middleware
|
|
107
|
+
]);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Define the action handler. This finalizes the builder and returns the executable action.
|
|
111
|
+
* The handler receives the accumulated context and input parameters.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* const action = createAction<[{ name: string; email: string }]>()
|
|
116
|
+
* .use(withUser)
|
|
117
|
+
* .handle(async (ctx, input) => {
|
|
118
|
+
* // ctx and input are fully typed
|
|
119
|
+
* return { ok: true, data: result };
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* // Call the action
|
|
123
|
+
* const result = await action({ name: "John", email: "john@example.com" });
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
handle(handler) {
|
|
127
|
+
const middlewares = [...this.middlewares];
|
|
128
|
+
return async (...args) => {
|
|
129
|
+
const finalHandler = async (ctx, ...a) => {
|
|
130
|
+
return handler(ctx, ...a);
|
|
131
|
+
};
|
|
132
|
+
const chain = middlewares.reduceRight((next, mw) => {
|
|
133
|
+
if (isContextMiddleware(mw)) {
|
|
134
|
+
return async (ctx, ...a) => {
|
|
135
|
+
return mw(
|
|
136
|
+
async (newCtx, ...params) => next(newCtx, ...params),
|
|
137
|
+
ctx,
|
|
138
|
+
...a
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
} else {
|
|
142
|
+
return async (ctx, ...a) => {
|
|
143
|
+
return mw(
|
|
144
|
+
async (...params) => next(ctx, ...params),
|
|
145
|
+
...a
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}, finalHandler);
|
|
150
|
+
try {
|
|
151
|
+
return await chain({}, ...args);
|
|
152
|
+
} catch (err) {
|
|
153
|
+
const message = err instanceof Error ? err.message : "Unknown error";
|
|
154
|
+
const code = err instanceof Error ? err.name : "UNKNOWN_ERROR";
|
|
155
|
+
return { ok: false, message, code };
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
function createAction() {
|
|
161
|
+
return ActionBuilder.create();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/server/middleware-utils.ts
|
|
79
165
|
function createMiddleware(handler) {
|
|
80
166
|
return handler;
|
|
81
167
|
}
|
|
@@ -94,7 +180,7 @@ function composeMiddleware(...middleware) {
|
|
|
94
180
|
return chain(...params);
|
|
95
181
|
};
|
|
96
182
|
}
|
|
97
|
-
function
|
|
183
|
+
function withZodValidation(schema, options = {}) {
|
|
98
184
|
const { code = "VALIDATION_ERROR", formatError } = options;
|
|
99
185
|
return async (next, input) => {
|
|
100
186
|
const result = schema.safeParse(input);
|
|
@@ -121,6 +207,8 @@ function withLogging(logger = {}) {
|
|
|
121
207
|
0 && (module.exports = {
|
|
122
208
|
applyMiddleware,
|
|
123
209
|
composeMiddleware,
|
|
210
|
+
createAction,
|
|
211
|
+
createContextMiddleware,
|
|
124
212
|
createMiddleware,
|
|
125
213
|
error,
|
|
126
214
|
isError,
|
|
@@ -130,6 +218,6 @@ function withLogging(logger = {}) {
|
|
|
130
218
|
unwrap,
|
|
131
219
|
unwrapOr,
|
|
132
220
|
withLogging,
|
|
133
|
-
|
|
221
|
+
withZodValidation
|
|
134
222
|
});
|
|
135
223
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/index.ts","../src/server/server-action.ts","../src/server/middleware.ts"],"sourcesContent":["export {\n serverAction,\n success,\n error,\n isSuccess,\n isError,\n unwrap,\n unwrapOr,\n} from \"./server-action\";\nexport type {\n ServerActionResult,\n ServerActionSuccess,\n ServerActionError,\n ServerActionFn,\n} from \"./server-action\";\n\nexport {\n createMiddleware,\n applyMiddleware,\n composeMiddleware,\n withValidation,\n withLogging,\n} from \"./middleware\";\nexport type {\n Middleware,\n ValidationSchema,\n WithValidationOptions,\n} from \"./middleware\";\n","\"use server\";\n\nexport type ServerActionSuccess<T> = {\n ok: true;\n data: T;\n};\n\nexport type ServerActionError = {\n ok: false;\n message: string;\n code?: string;\n};\n\nexport type ServerActionResult<T> = ServerActionSuccess<T> | ServerActionError;\n\nexport function success<T>(data: T): ServerActionSuccess<T> {\n return { ok: true, data };\n}\n\nexport function error(message: string, code?: string): ServerActionError {\n return { ok: false, message, code };\n}\n\nexport type ServerActionFn<P extends unknown[], T> = (\n ...args: P\n) => Promise<ServerActionResult<T>>;\n\ntype ServerActionOptions = {\n onError?: (error: unknown) => void;\n};\n\n/**\n * Wraps an async function to return a standardized ServerActionResult.\n * Catches any thrown errors and converts them to error results.\n */\nexport function serverAction<P extends unknown[], T>(\n fn: (...args: P) => Promise<T>,\n options?: ServerActionOptions,\n): ServerActionFn<P, T> {\n return async (...args: P): Promise<ServerActionResult<T>> => {\n try {\n const data = await fn(...args);\n return success(data);\n } catch (err) {\n options?.onError?.(err);\n\n if (err instanceof Error) {\n return error(err.message, err.name);\n }\n\n return error(\"An unexpected error occurred\", \"UNKNOWN_ERROR\");\n }\n };\n}\n\n/**\n * Type guard to check if a result is successful\n */\nexport function isSuccess<T>(\n result: ServerActionResult<T>,\n): result is ServerActionSuccess<T> {\n return result.ok === true;\n}\n\n/**\n * Type guard to check if a result is an error\n */\nexport function isError<T>(\n result: ServerActionResult<T>,\n): result is ServerActionError {\n return result.ok === false;\n}\n\n/**\n * Unwraps a successful result or throws the error message\n */\nexport function unwrap<T>(result: ServerActionResult<T>): T {\n if (result.ok) {\n return result.data;\n }\n throw new Error(result.message);\n}\n\n/**\n * Unwraps a successful result or returns a default value\n */\nexport function unwrapOr<T>(result: ServerActionResult<T>, defaultValue: T): T {\n if (result.ok) {\n return result.data;\n }\n return defaultValue;\n}\n","\"use server\";\n\nimport type { ServerActionResult } from \"./server-action\";\n\n/**\n * A middleware function that wraps a server action.\n * Receives the next function in the chain and the parameters passed to the action.\n */\nexport type Middleware<P extends unknown[], T> = (\n next: (...params: P) => Promise<ServerActionResult<T>>,\n ...params: P\n) => Promise<ServerActionResult<T>>;\n\n/**\n * Creates a type-safe middleware function.\n *\n * @example\n * ```ts\n * const withLogging = createMiddleware(async (next, ...params) => {\n * console.log(\"Calling action with:\", params);\n * const result = await next(...params);\n * console.log(\"Result:\", result);\n * return result;\n * });\n * ```\n */\nexport function createMiddleware<P extends unknown[], T>(\n handler: Middleware<P, T>,\n): Middleware<P, T> {\n return handler;\n}\n\n/**\n * Applies middleware to a server action.\n * Middleware is executed in order (first middleware wraps second, etc).\n *\n * @example\n * ```ts\n * const protectedAction = applyMiddleware(\n * myServerAction,\n * [withAuth, withLogging, withValidation]\n * );\n * ```\n */\nexport function applyMiddleware<P extends unknown[], T>(\n action: (...params: P) => Promise<ServerActionResult<T>>,\n middleware: Middleware<P, T>[],\n): (...params: P) => Promise<ServerActionResult<T>> {\n return middleware.reduceRight(\n (next, mw) =>\n (...params: P) =>\n mw(next, ...params),\n action,\n );\n}\n\n/**\n * Composes multiple middleware into a single middleware.\n *\n * @example\n * ```ts\n * const combined = composeMiddleware(withAuth, withLogging, withValidation);\n * const protectedAction = applyMiddleware(myAction, [combined]);\n * ```\n */\nexport function composeMiddleware<P extends unknown[], T>(\n ...middleware: Middleware<P, T>[]\n): Middleware<P, T> {\n return (next, ...params) => {\n const chain = middleware.reduceRight(\n (nextFn, mw) =>\n (...p: P) =>\n mw(nextFn, ...p),\n next,\n );\n return chain(...params);\n };\n}\n\n/**\n * A Zod-like schema interface for validation.\n * Works with Zod, Valibot, or any schema library with a compatible safeParse method.\n */\nexport type ValidationSchema<T> = {\n safeParse(data: unknown):\n | { success: true; data: T }\n | { success: false; error: { message?: string; errors?: Array<{ message: string }> } };\n};\n\nexport type WithValidationOptions = {\n /** Error code to return on validation failure. Defaults to \"VALIDATION_ERROR\" */\n code?: string;\n /** Custom error message formatter */\n formatError?: (error: {\n message?: string;\n errors?: Array<{ message: string }>;\n }) => string;\n};\n\n/**\n * Creates a middleware that validates the first parameter against a schema.\n * Works with Zod, Valibot, or any library with a compatible safeParse method.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { withValidation, applyMiddleware } from \"use-server-action/server\";\n *\n * const CreateUserSchema = z.object({\n * name: z.string().min(1),\n * email: z.string().email(),\n * });\n *\n * const createUser = applyMiddleware(\n * serverAction(async (input: z.infer<typeof CreateUserSchema>) => {\n * return await db.user.create({ data: input });\n * }),\n * [withValidation(CreateUserSchema)]\n * );\n * ```\n */\nexport function withValidation<TInput, T>(\n schema: ValidationSchema<TInput>,\n options: WithValidationOptions = {},\n): Middleware<[TInput], T> {\n const { code = \"VALIDATION_ERROR\", formatError } = options;\n\n return async (next, input) => {\n const result = schema.safeParse(input);\n\n if (!result.success) {\n const message = formatError\n ? formatError(result.error)\n : result.error.errors?.[0]?.message ??\n result.error.message ??\n \"Validation failed\";\n\n return { ok: false, message, code };\n }\n\n return next(result.data);\n };\n}\n\n/**\n * Creates a middleware that logs action calls and results.\n */\nexport function withLogging<P extends unknown[], T>(\n logger: {\n onCall?: (params: P) => void;\n onSuccess?: (data: T, params: P) => void;\n onError?: (\n message: string,\n code: string | undefined,\n params: P,\n ) => void;\n } = {},\n): Middleware<P, T> {\n return async (next, ...params) => {\n logger.onCall?.(params);\n const result = await next(...params);\n if (result.ok) {\n logger.onSuccess?.(result.data, params);\n } else {\n logger.onError?.(result.message, result.code, params);\n }\n return result;\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACeO,SAAS,QAAW,MAAiC;AACxD,SAAO,EAAE,IAAI,MAAM,KAAK;AAC5B;AAEO,SAAS,MAAM,SAAiB,MAAkC;AACrE,SAAO,EAAE,IAAI,OAAO,SAAS,KAAK;AACtC;AAcO,SAAS,aACZ,IACA,SACoB;AACpB,SAAO,UAAU,SAA4C;AACzD,QAAI;AACA,YAAM,OAAO,MAAM,GAAG,GAAG,IAAI;AAC7B,aAAO,QAAQ,IAAI;AAAA,IACvB,SAAS,KAAK;AACV,eAAS,UAAU,GAAG;AAEtB,UAAI,eAAe,OAAO;AACtB,eAAO,MAAM,IAAI,SAAS,IAAI,IAAI;AAAA,MACtC;AAEA,aAAO,MAAM,gCAAgC,eAAe;AAAA,IAChE;AAAA,EACJ;AACJ;AAKO,SAAS,UACZ,QACgC;AAChC,SAAO,OAAO,OAAO;AACzB;AAKO,SAAS,QACZ,QAC2B;AAC3B,SAAO,OAAO,OAAO;AACzB;AAKO,SAAS,OAAU,QAAkC;AACxD,MAAI,OAAO,IAAI;AACX,WAAO,OAAO;AAAA,EAClB;AACA,QAAM,IAAI,MAAM,OAAO,OAAO;AAClC;AAKO,SAAS,SAAY,QAA+B,cAAoB;AAC3E,MAAI,OAAO,IAAI;AACX,WAAO,OAAO;AAAA,EAClB;AACA,SAAO;AACX;;;ACjEO,SAAS,iBACZ,SACgB;AAChB,SAAO;AACX;AAcO,SAAS,gBACZ,QACA,YACgD;AAChD,SAAO,WAAW;AAAA,IACd,CAAC,MAAM,OACH,IAAI,WACA,GAAG,MAAM,GAAG,MAAM;AAAA,IAC1B;AAAA,EACJ;AACJ;AAWO,SAAS,qBACT,YACa;AAChB,SAAO,CAAC,SAAS,WAAW;AACxB,UAAM,QAAQ,WAAW;AAAA,MACrB,CAAC,QAAQ,OACL,IAAI,MACA,GAAG,QAAQ,GAAG,CAAC;AAAA,MACvB;AAAA,IACJ;AACA,WAAO,MAAM,GAAG,MAAM;AAAA,EAC1B;AACJ;AA4CO,SAAS,eACZ,QACA,UAAiC,CAAC,GACX;AACvB,QAAM,EAAE,OAAO,oBAAoB,YAAY,IAAI;AAEnD,SAAO,OAAO,MAAM,UAAU;AAC1B,UAAM,SAAS,OAAO,UAAU,KAAK;AAErC,QAAI,CAAC,OAAO,SAAS;AACjB,YAAM,UAAU,cACV,YAAY,OAAO,KAAK,IACxB,OAAO,MAAM,SAAS,CAAC,GAAG,WAC1B,OAAO,MAAM,WACb;AAEN,aAAO,EAAE,IAAI,OAAO,SAAS,KAAK;AAAA,IACtC;AAEA,WAAO,KAAK,OAAO,IAAI;AAAA,EAC3B;AACJ;AAKO,SAAS,YACZ,SAQI,CAAC,GACW;AAChB,SAAO,OAAO,SAAS,WAAW;AAC9B,WAAO,SAAS,MAAM;AACtB,UAAM,SAAS,MAAM,KAAK,GAAG,MAAM;AACnC,QAAI,OAAO,IAAI;AACX,aAAO,YAAY,OAAO,MAAM,MAAM;AAAA,IAC1C,OAAO;AACH,aAAO,UAAU,OAAO,SAAS,OAAO,MAAM,MAAM;AAAA,IACxD;AACA,WAAO;AAAA,EACX;AACJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/server/index.ts","../src/server/server-action.ts","../src/server/context-middleware.ts","../src/server/action-builder.ts","../src/server/middleware-utils.ts"],"sourcesContent":["\"use server\";\n\n// Server action utilities\nexport {\n serverAction,\n success,\n error,\n isSuccess,\n isError,\n unwrap,\n unwrapOr,\n} from \"./server-action\";\nexport type {\n ServerActionResult,\n ServerActionSuccess,\n ServerActionError,\n ServerActionFn,\n} from \"./server-action\";\n\n// Types\nexport type {\n BaseContext,\n ContextMiddleware,\n Middleware,\n ValidationSchema,\n WithValidationOptions,\n} from \"./types\";\n\n// Context middleware\nexport { createContextMiddleware } from \"./context-middleware\";\n\n// Action builder\nexport { createAction } from \"./action-builder\";\n\n// Middleware utilities\nexport {\n createMiddleware,\n applyMiddleware,\n composeMiddleware,\n withZodValidation,\n withLogging,\n} from \"./middleware-utils\";\n","\"use server\";\n\nexport type ServerActionSuccess<T> = {\n ok: true;\n data: T;\n};\n\nexport type ServerActionError = {\n ok: false;\n message: string;\n code?: string;\n};\n\nexport type ServerActionResult<T> = ServerActionSuccess<T> | ServerActionError;\n\nexport function success<T>(data: T): ServerActionSuccess<T> {\n return { ok: true, data };\n}\n\nexport function error(message: string, code?: string): ServerActionError {\n return { ok: false, message, code };\n}\n\nexport type ServerActionFn<P extends unknown[], T> = (\n ...args: P\n) => Promise<ServerActionResult<T>>;\n\ntype ServerActionOptions = {\n onError?: (error: unknown) => void;\n};\n\n/**\n * Wraps an async function to return a standardized ServerActionResult.\n * Catches any thrown errors and converts them to error results.\n *\n * @deprecated Use `createAction().input(schema).handle(fn)` instead.\n * The new API provides better type inference and built-in validation.\n *\n * @example\n * ```ts\n * // Old way (deprecated):\n * const myAction = serverAction(async (input: MyInput) => {\n * return await doSomething(input);\n * });\n *\n * // New way:\n * const myAction = createAction()\n * .input(mySchema)\n * .handle(async (ctx, input) => {\n * return { ok: true, data: await doSomething(input) };\n * });\n * ```\n */\nexport function serverAction<P extends unknown[], T>(\n fn: (...args: P) => Promise<T>,\n options?: ServerActionOptions,\n): ServerActionFn<P, T> {\n return async (...args: P): Promise<ServerActionResult<T>> => {\n try {\n const data = await fn(...args);\n return success(data);\n } catch (err) {\n options?.onError?.(err);\n\n if (err instanceof Error) {\n return error(err.message, err.name);\n }\n\n return error(\"An unexpected error occurred\", \"UNKNOWN_ERROR\");\n }\n };\n}\n\n/**\n * Type guard to check if a result is successful\n */\nexport function isSuccess<T>(\n result: ServerActionResult<T>,\n): result is ServerActionSuccess<T> {\n return result.ok === true;\n}\n\n/**\n * Type guard to check if a result is an error\n */\nexport function isError<T>(\n result: ServerActionResult<T>,\n): result is ServerActionError {\n return result.ok === false;\n}\n\n/**\n * Unwraps a successful result or throws the error message\n */\nexport function unwrap<T>(result: ServerActionResult<T>): T {\n if (result.ok) {\n return result.data;\n }\n throw new Error(result.message);\n}\n\n/**\n * Unwraps a successful result or returns a default value\n */\nexport function unwrapOr<T>(result: ServerActionResult<T>, defaultValue: T): T {\n if (result.ok) {\n return result.data;\n }\n return defaultValue;\n}\n","\"use server\";\n\nimport type { BaseContext, ContextMiddleware } from \"./types\";\n\n/**\n * Symbol to identify context-aware middleware at runtime\n */\nexport const CONTEXT_MIDDLEWARE = Symbol(\"contextMiddleware\");\n\n/**\n * Check if a middleware is context-aware\n */\nexport function isContextMiddleware(fn: unknown): boolean {\n return typeof fn === \"function\" && (fn as any)[CONTEXT_MIDDLEWARE] === true;\n}\n\n/**\n * Creates a type-safe context-aware middleware.\n *\n * @example\n * ```ts\n * type User = { id: string; name: string };\n *\n * const withAuth = createContextMiddleware<\n * [string], // Parameters\n * SomeReturnType, // Return type\n * {}, // Input context (none required)\n * { user: User } // Output context (adds user)\n * >(async (next, ctx, input) => {\n * const user = await authenticate();\n * if (!user) {\n * return { ok: false, message: \"Unauthorized\", code: \"UNAUTHORIZED\" };\n * }\n * // Pass the new context with user added\n * return next({ ...ctx, user }, input);\n * });\n * ```\n */\nexport function createContextMiddleware<\n P extends unknown[],\n T,\n CtxIn extends BaseContext = BaseContext,\n CtxOut extends BaseContext = BaseContext,\n>(\n handler: ContextMiddleware<P, T, CtxIn, CtxOut>,\n): ContextMiddleware<P, T, CtxIn, CtxOut> {\n (handler as any)[CONTEXT_MIDDLEWARE] = true;\n return handler;\n}\n","\"use server\";\n\nimport type { ServerActionResult } from \"./server-action\";\nimport type {\n BaseContext,\n ContextMiddleware,\n Middleware,\n} from \"./types\";\nimport { isContextMiddleware } from \"./context-middleware\";\n\n/**\n * A builder for creating server actions with type-safe context accumulation.\n *\n * @template TInput - The input parameters as a tuple type\n * @template TContext - The accumulated context type from all middleware\n */\nclass ActionBuilder<\n TInput extends unknown[] = unknown[],\n TContext extends BaseContext = {},\n> {\n private middlewares: Array<\n ContextMiddleware<any, any, any, any> | Middleware<any, any>\n > = [];\n\n private constructor(\n middlewares: Array<\n ContextMiddleware<any, any, any, any> | Middleware<any, any>\n > = [],\n ) {\n this.middlewares = middlewares;\n }\n\n /**\n * Create a new ActionBuilder instance\n */\n static create<TInput extends unknown[]>(): ActionBuilder<TInput, {}> {\n return new ActionBuilder<TInput, {}>();\n }\n\n /**\n * Add a context-aware middleware to the chain.\n * The middleware receives the accumulated context and can add new context.\n *\n * @example\n * ```ts\n * const withUser = createContextMiddleware(async (next, ctx, ...args) => {\n * const user = await getUser();\n * if (!user) {\n * return { ok: false, message: \"Unauthorized\", code: \"UNAUTHORIZED\" };\n * }\n * return next({ ...ctx, user }, ...args);\n * });\n *\n * const action = createAction<[{ name: string }]>()\n * .use(withUser)\n * .handle(async (ctx, input) => {\n * // ctx.user is fully typed!\n * });\n * ```\n */\n use<CtxOut extends BaseContext>(\n middleware: ContextMiddleware<TInput, any, TContext, CtxOut>,\n ): ActionBuilder<TInput, TContext & CtxOut>;\n\n /**\n * Add a regular (non-context) middleware to the chain.\n * The middleware can transform input/output but doesn't modify context.\n *\n * @example\n * ```ts\n * const withLogging = createMiddleware(async (next, ...args) => {\n * console.log(\"Args:\", args);\n * const result = await next(...args);\n * console.log(\"Result:\", result);\n * return result;\n * });\n *\n * const action = createAction<[string]>()\n * .use(withLogging)\n * .handle(async (ctx, input) => { ... });\n * ```\n */\n use(middleware: Middleware<TInput, any>): ActionBuilder<TInput, TContext>;\n\n use(middleware: any): any {\n return new ActionBuilder<TInput, TContext>([\n ...this.middlewares,\n middleware,\n ]);\n }\n\n /**\n * Define the action handler. This finalizes the builder and returns the executable action.\n * The handler receives the accumulated context and input parameters.\n *\n * @example\n * ```ts\n * const action = createAction<[{ name: string; email: string }]>()\n * .use(withUser)\n * .handle(async (ctx, input) => {\n * // ctx and input are fully typed\n * return { ok: true, data: result };\n * });\n *\n * // Call the action\n * const result = await action({ name: \"John\", email: \"john@example.com\" });\n * ```\n */\n handle<TOutput>(\n handler: (\n ctx: TContext,\n ...args: TInput\n ) => Promise<ServerActionResult<TOutput>>,\n ): (...args: TInput) => Promise<ServerActionResult<TOutput>> {\n const middlewares = [...this.middlewares];\n\n return async (...args: TInput): Promise<ServerActionResult<TOutput>> => {\n // Build the middleware chain\n type CtxNextFn = (\n ctx: BaseContext,\n ...args: TInput\n ) => Promise<ServerActionResult<TOutput>>;\n\n const finalHandler: CtxNextFn = async (ctx, ...a) => {\n return handler(ctx as TContext, ...a);\n };\n\n // Build chain from right to left (last middleware wraps closest to handler)\n const chain = middlewares.reduceRight<CtxNextFn>((next, mw) => {\n if (isContextMiddleware(mw)) {\n // Context middleware: (next, ctx, ...params) => ...\n return async (ctx, ...a) => {\n return (mw as ContextMiddleware<TInput, TOutput, any, any>)(\n async (newCtx, ...params) => next(newCtx, ...(params as TInput)),\n ctx,\n ...a,\n );\n };\n } else {\n // Regular middleware: (next, ...params) => ...\n // Pass context through unchanged\n return async (ctx, ...a) => {\n return (mw as Middleware<TInput, TOutput>)(\n async (...params) => next(ctx, ...(params as TInput)),\n ...a,\n );\n };\n }\n }, finalHandler);\n\n // Start with empty context\n try {\n return await chain({}, ...args);\n } catch (err) {\n const message =\n err instanceof Error ? err.message : \"Unknown error\";\n const code =\n err instanceof Error ? err.name : \"UNKNOWN_ERROR\";\n return { ok: false, message, code };\n }\n };\n }\n}\n\n/**\n * Converts a type to a tuple of arguments.\n * - `void` becomes `[]` (no args)\n * - Single type `T` becomes `[T]`\n * - Tuple type `[A, B]` stays as `[A, B]`\n */\ntype ToArgs<T> = [T] extends [void] ? [] : T extends unknown[] ? T : [T];\n\n/**\n * Creates a new action builder with type-safe context accumulation.\n *\n * @example\n * ```ts\n * // Single input parameter\n * const createUser = createAction<{ name: string; email: string }>()\n * .use(withUser)\n * .handle(async (ctx, input) => {\n * await db.users.create({ ...input, createdBy: ctx.user.id });\n * return { ok: true, data: { success: true } };\n * });\n *\n * // Multiple input parameters (use tuple)\n * const updateUser = createAction<[string, { name: string }]>()\n * .use(withUser)\n * .handle(async (ctx, id, data) => {\n * await db.users.update(id, data);\n * return { ok: true, data: { success: true } };\n * });\n *\n * // With validation middleware\n * const createPost = createAction<z.infer<typeof postSchema>>()\n * .use(withZodValidation(postSchema))\n * .use(withUser)\n * .handle(async (ctx, input) => {\n * return { ok: true, data: await db.posts.create(input) };\n * });\n * ```\n */\nexport function createAction<TInput = void>(): ActionBuilder<ToArgs<TInput>, {}> {\n return ActionBuilder.create<ToArgs<TInput>>();\n}\n","\"use server\";\n\nimport type { ServerActionResult } from \"./server-action\";\nimport type { Middleware, ValidationSchema, WithValidationOptions } from \"./types\";\n\n/**\n * Creates a type-safe middleware function.\n *\n * @example\n * ```ts\n * const withLogging = createMiddleware(async (next, ...params) => {\n * console.log(\"Calling action with:\", params);\n * const result = await next(...params);\n * console.log(\"Result:\", result);\n * return result;\n * });\n * ```\n */\nexport function createMiddleware<P extends unknown[], T>(\n handler: Middleware<P, T>,\n): Middleware<P, T> {\n return handler;\n}\n\n/**\n * Applies middleware to a server action.\n * Middleware is executed in order (first middleware wraps second, etc).\n *\n * @deprecated Use `createAction().input(schema).use(middleware).handle(fn)` instead.\n * This provides better type inference and a more composable API.\n *\n * @example\n * ```ts\n * // Old way (deprecated):\n * const protectedAction = applyMiddleware(\n * myServerAction,\n * [withAuth, withLogging, withValidation]\n * );\n *\n * // New way:\n * const protectedAction = createAction()\n * .input(schema)\n * .use(withAuth)\n * .use(withLogging)\n * .handle(async (ctx, input) => { ... });\n * ```\n */\nexport function applyMiddleware<P extends unknown[], T>(\n action: (...params: P) => Promise<ServerActionResult<T>>,\n middleware: Middleware<P, T>[],\n): (...params: P) => Promise<ServerActionResult<T>> {\n return middleware.reduceRight(\n (next, mw) =>\n (...params: P) =>\n mw(next, ...params),\n action,\n );\n}\n\n/**\n * Composes multiple middleware into a single middleware.\n *\n * @deprecated Use `createAction().use(mw1).use(mw2).handle(fn)` instead.\n * The builder pattern provides better type inference for chained middleware.\n *\n * @example\n * ```ts\n * // Old way (deprecated):\n * const combined = composeMiddleware(withAuth, withLogging, withValidation);\n * const protectedAction = applyMiddleware(myAction, [combined]);\n *\n * // New way:\n * const protectedAction = createAction()\n * .input(schema)\n * .use(withAuth)\n * .use(withLogging)\n * .handle(async (ctx, input) => { ... });\n * ```\n */\nexport function composeMiddleware<P extends unknown[], T>(\n ...middleware: Middleware<P, T>[]\n): Middleware<P, T> {\n return (next, ...params) => {\n const chain = middleware.reduceRight(\n (nextFn, mw) =>\n (...p: P) =>\n mw(nextFn, ...p),\n next,\n );\n return chain(...params);\n };\n}\n\n/**\n * Creates a middleware that validates the first parameter against a schema.\n * Works with Zod, Valibot, or any library with a compatible safeParse method.\n *\n * @deprecated Use `createAction().input(schema).handle(fn)` instead.\n * The `.input()` method provides automatic type inference from the schema.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n *\n * const schema = z.object({\n * name: z.string().min(1),\n * email: z.string().email(),\n * });\n *\n * // Old way (deprecated):\n * const createUser = applyMiddleware(\n * serverAction(async (input: z.infer<typeof schema>) => {\n * return await db.user.create({ data: input });\n * }),\n * [withZodValidation(schema)]\n * );\n *\n * // New way:\n * const createUser = createAction()\n * .input(schema) // Type is inferred automatically!\n * .handle(async (ctx, input) => {\n * return { ok: true, data: await db.user.create({ data: input }) };\n * });\n * ```\n */\nexport function withZodValidation<TInput, T>(\n schema: ValidationSchema<TInput>,\n options: WithValidationOptions = {},\n): Middleware<[TInput], T> {\n const { code = \"VALIDATION_ERROR\", formatError } = options;\n\n return async (next, input) => {\n const result = schema.safeParse(input);\n\n if (!result.success) {\n const message = formatError\n ? formatError(result.error)\n : (result.error.errors?.[0]?.message ??\n result.error.message ??\n \"Validation failed\");\n\n return { ok: false, message, code };\n }\n\n return next(result.data);\n };\n}\n\n/**\n * Creates a middleware that logs action calls and results.\n */\nexport function withLogging<P extends unknown[], T>(\n logger: {\n onCall?: (params: P) => void;\n onSuccess?: (data: T, params: P) => void;\n onError?: (\n message: string,\n code: string | undefined,\n params: P,\n ) => void;\n } = {},\n): Middleware<P, T> {\n return async (next, ...params) => {\n logger.onCall?.(params);\n const result = await next(...params);\n if (result.ok) {\n logger.onSuccess?.(result.data, params);\n } else {\n logger.onError?.(result.message, result.code, params);\n }\n return result;\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/server.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
1
3
|
// src/server/server-action.ts
|
|
2
4
|
function success(data) {
|
|
3
5
|
return { ok: true, data };
|
|
@@ -38,7 +40,90 @@ function unwrapOr(result, defaultValue) {
|
|
|
38
40
|
return defaultValue;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
// src/server/middleware.ts
|
|
43
|
+
// src/server/context-middleware.ts
|
|
44
|
+
var CONTEXT_MIDDLEWARE = /* @__PURE__ */ Symbol("contextMiddleware");
|
|
45
|
+
function isContextMiddleware(fn) {
|
|
46
|
+
return typeof fn === "function" && fn[CONTEXT_MIDDLEWARE] === true;
|
|
47
|
+
}
|
|
48
|
+
function createContextMiddleware(handler) {
|
|
49
|
+
handler[CONTEXT_MIDDLEWARE] = true;
|
|
50
|
+
return handler;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/server/action-builder.ts
|
|
54
|
+
var ActionBuilder = class _ActionBuilder {
|
|
55
|
+
constructor(middlewares = []) {
|
|
56
|
+
this.middlewares = [];
|
|
57
|
+
this.middlewares = middlewares;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a new ActionBuilder instance
|
|
61
|
+
*/
|
|
62
|
+
static create() {
|
|
63
|
+
return new _ActionBuilder();
|
|
64
|
+
}
|
|
65
|
+
use(middleware) {
|
|
66
|
+
return new _ActionBuilder([
|
|
67
|
+
...this.middlewares,
|
|
68
|
+
middleware
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Define the action handler. This finalizes the builder and returns the executable action.
|
|
73
|
+
* The handler receives the accumulated context and input parameters.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* const action = createAction<[{ name: string; email: string }]>()
|
|
78
|
+
* .use(withUser)
|
|
79
|
+
* .handle(async (ctx, input) => {
|
|
80
|
+
* // ctx and input are fully typed
|
|
81
|
+
* return { ok: true, data: result };
|
|
82
|
+
* });
|
|
83
|
+
*
|
|
84
|
+
* // Call the action
|
|
85
|
+
* const result = await action({ name: "John", email: "john@example.com" });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
handle(handler) {
|
|
89
|
+
const middlewares = [...this.middlewares];
|
|
90
|
+
return async (...args) => {
|
|
91
|
+
const finalHandler = async (ctx, ...a) => {
|
|
92
|
+
return handler(ctx, ...a);
|
|
93
|
+
};
|
|
94
|
+
const chain = middlewares.reduceRight((next, mw) => {
|
|
95
|
+
if (isContextMiddleware(mw)) {
|
|
96
|
+
return async (ctx, ...a) => {
|
|
97
|
+
return mw(
|
|
98
|
+
async (newCtx, ...params) => next(newCtx, ...params),
|
|
99
|
+
ctx,
|
|
100
|
+
...a
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
} else {
|
|
104
|
+
return async (ctx, ...a) => {
|
|
105
|
+
return mw(
|
|
106
|
+
async (...params) => next(ctx, ...params),
|
|
107
|
+
...a
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}, finalHandler);
|
|
112
|
+
try {
|
|
113
|
+
return await chain({}, ...args);
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const message = err instanceof Error ? err.message : "Unknown error";
|
|
116
|
+
const code = err instanceof Error ? err.name : "UNKNOWN_ERROR";
|
|
117
|
+
return { ok: false, message, code };
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
function createAction() {
|
|
123
|
+
return ActionBuilder.create();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/server/middleware-utils.ts
|
|
42
127
|
function createMiddleware(handler) {
|
|
43
128
|
return handler;
|
|
44
129
|
}
|
|
@@ -57,7 +142,7 @@ function composeMiddleware(...middleware) {
|
|
|
57
142
|
return chain(...params);
|
|
58
143
|
};
|
|
59
144
|
}
|
|
60
|
-
function
|
|
145
|
+
function withZodValidation(schema, options = {}) {
|
|
61
146
|
const { code = "VALIDATION_ERROR", formatError } = options;
|
|
62
147
|
return async (next, input) => {
|
|
63
148
|
const result = schema.safeParse(input);
|
|
@@ -83,6 +168,8 @@ function withLogging(logger = {}) {
|
|
|
83
168
|
export {
|
|
84
169
|
applyMiddleware,
|
|
85
170
|
composeMiddleware,
|
|
171
|
+
createAction,
|
|
172
|
+
createContextMiddleware,
|
|
86
173
|
createMiddleware,
|
|
87
174
|
error,
|
|
88
175
|
isError,
|
|
@@ -92,6 +179,6 @@ export {
|
|
|
92
179
|
unwrap,
|
|
93
180
|
unwrapOr,
|
|
94
181
|
withLogging,
|
|
95
|
-
|
|
182
|
+
withZodValidation
|
|
96
183
|
};
|
|
97
184
|
//# sourceMappingURL=server.mjs.map
|
package/dist/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/server-action.ts","../src/server/middleware.ts"],"sourcesContent":["\"use server\";\n\nexport type ServerActionSuccess<T> = {\n ok: true;\n data: T;\n};\n\nexport type ServerActionError = {\n ok: false;\n message: string;\n code?: string;\n};\n\nexport type ServerActionResult<T> = ServerActionSuccess<T> | ServerActionError;\n\nexport function success<T>(data: T): ServerActionSuccess<T> {\n return { ok: true, data };\n}\n\nexport function error(message: string, code?: string): ServerActionError {\n return { ok: false, message, code };\n}\n\nexport type ServerActionFn<P extends unknown[], T> = (\n ...args: P\n) => Promise<ServerActionResult<T>>;\n\ntype ServerActionOptions = {\n onError?: (error: unknown) => void;\n};\n\n/**\n * Wraps an async function to return a standardized ServerActionResult.\n * Catches any thrown errors and converts them to error results.\n */\nexport function serverAction<P extends unknown[], T>(\n fn: (...args: P) => Promise<T>,\n options?: ServerActionOptions,\n): ServerActionFn<P, T> {\n return async (...args: P): Promise<ServerActionResult<T>> => {\n try {\n const data = await fn(...args);\n return success(data);\n } catch (err) {\n options?.onError?.(err);\n\n if (err instanceof Error) {\n return error(err.message, err.name);\n }\n\n return error(\"An unexpected error occurred\", \"UNKNOWN_ERROR\");\n }\n };\n}\n\n/**\n * Type guard to check if a result is successful\n */\nexport function isSuccess<T>(\n result: ServerActionResult<T>,\n): result is ServerActionSuccess<T> {\n return result.ok === true;\n}\n\n/**\n * Type guard to check if a result is an error\n */\nexport function isError<T>(\n result: ServerActionResult<T>,\n): result is ServerActionError {\n return result.ok === false;\n}\n\n/**\n * Unwraps a successful result or throws the error message\n */\nexport function unwrap<T>(result: ServerActionResult<T>): T {\n if (result.ok) {\n return result.data;\n }\n throw new Error(result.message);\n}\n\n/**\n * Unwraps a successful result or returns a default value\n */\nexport function unwrapOr<T>(result: ServerActionResult<T>, defaultValue: T): T {\n if (result.ok) {\n return result.data;\n }\n return defaultValue;\n}\n","\"use server\";\n\nimport type { ServerActionResult } from \"./server-action\";\n\n/**\n * A middleware function that wraps a server action.\n * Receives the next function in the chain and the parameters passed to the action.\n */\nexport type Middleware<P extends unknown[], T> = (\n next: (...params: P) => Promise<ServerActionResult<T>>,\n ...params: P\n) => Promise<ServerActionResult<T>>;\n\n/**\n * Creates a type-safe middleware function.\n *\n * @example\n * ```ts\n * const withLogging = createMiddleware(async (next, ...params) => {\n * console.log(\"Calling action with:\", params);\n * const result = await next(...params);\n * console.log(\"Result:\", result);\n * return result;\n * });\n * ```\n */\nexport function createMiddleware<P extends unknown[], T>(\n handler: Middleware<P, T>,\n): Middleware<P, T> {\n return handler;\n}\n\n/**\n * Applies middleware to a server action.\n * Middleware is executed in order (first middleware wraps second, etc).\n *\n * @example\n * ```ts\n * const protectedAction = applyMiddleware(\n * myServerAction,\n * [withAuth, withLogging, withValidation]\n * );\n * ```\n */\nexport function applyMiddleware<P extends unknown[], T>(\n action: (...params: P) => Promise<ServerActionResult<T>>,\n middleware: Middleware<P, T>[],\n): (...params: P) => Promise<ServerActionResult<T>> {\n return middleware.reduceRight(\n (next, mw) =>\n (...params: P) =>\n mw(next, ...params),\n action,\n );\n}\n\n/**\n * Composes multiple middleware into a single middleware.\n *\n * @example\n * ```ts\n * const combined = composeMiddleware(withAuth, withLogging, withValidation);\n * const protectedAction = applyMiddleware(myAction, [combined]);\n * ```\n */\nexport function composeMiddleware<P extends unknown[], T>(\n ...middleware: Middleware<P, T>[]\n): Middleware<P, T> {\n return (next, ...params) => {\n const chain = middleware.reduceRight(\n (nextFn, mw) =>\n (...p: P) =>\n mw(nextFn, ...p),\n next,\n );\n return chain(...params);\n };\n}\n\n/**\n * A Zod-like schema interface for validation.\n * Works with Zod, Valibot, or any schema library with a compatible safeParse method.\n */\nexport type ValidationSchema<T> = {\n safeParse(data: unknown):\n | { success: true; data: T }\n | { success: false; error: { message?: string; errors?: Array<{ message: string }> } };\n};\n\nexport type WithValidationOptions = {\n /** Error code to return on validation failure. Defaults to \"VALIDATION_ERROR\" */\n code?: string;\n /** Custom error message formatter */\n formatError?: (error: {\n message?: string;\n errors?: Array<{ message: string }>;\n }) => string;\n};\n\n/**\n * Creates a middleware that validates the first parameter against a schema.\n * Works with Zod, Valibot, or any library with a compatible safeParse method.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { withValidation, applyMiddleware } from \"use-server-action/server\";\n *\n * const CreateUserSchema = z.object({\n * name: z.string().min(1),\n * email: z.string().email(),\n * });\n *\n * const createUser = applyMiddleware(\n * serverAction(async (input: z.infer<typeof CreateUserSchema>) => {\n * return await db.user.create({ data: input });\n * }),\n * [withValidation(CreateUserSchema)]\n * );\n * ```\n */\nexport function withValidation<TInput, T>(\n schema: ValidationSchema<TInput>,\n options: WithValidationOptions = {},\n): Middleware<[TInput], T> {\n const { code = \"VALIDATION_ERROR\", formatError } = options;\n\n return async (next, input) => {\n const result = schema.safeParse(input);\n\n if (!result.success) {\n const message = formatError\n ? formatError(result.error)\n : result.error.errors?.[0]?.message ??\n result.error.message ??\n \"Validation failed\";\n\n return { ok: false, message, code };\n }\n\n return next(result.data);\n };\n}\n\n/**\n * Creates a middleware that logs action calls and results.\n */\nexport function withLogging<P extends unknown[], T>(\n logger: {\n onCall?: (params: P) => void;\n onSuccess?: (data: T, params: P) => void;\n onError?: (\n message: string,\n code: string | undefined,\n params: P,\n ) => void;\n } = {},\n): Middleware<P, T> {\n return async (next, ...params) => {\n logger.onCall?.(params);\n const result = await next(...params);\n if (result.ok) {\n logger.onSuccess?.(result.data, params);\n } else {\n logger.onError?.(result.message, result.code, params);\n }\n return result;\n };\n}\n"],"mappings":";AAeO,SAAS,QAAW,MAAiC;AACxD,SAAO,EAAE,IAAI,MAAM,KAAK;AAC5B;AAEO,SAAS,MAAM,SAAiB,MAAkC;AACrE,SAAO,EAAE,IAAI,OAAO,SAAS,KAAK;AACtC;AAcO,SAAS,aACZ,IACA,SACoB;AACpB,SAAO,UAAU,SAA4C;AACzD,QAAI;AACA,YAAM,OAAO,MAAM,GAAG,GAAG,IAAI;AAC7B,aAAO,QAAQ,IAAI;AAAA,IACvB,SAAS,KAAK;AACV,eAAS,UAAU,GAAG;AAEtB,UAAI,eAAe,OAAO;AACtB,eAAO,MAAM,IAAI,SAAS,IAAI,IAAI;AAAA,MACtC;AAEA,aAAO,MAAM,gCAAgC,eAAe;AAAA,IAChE;AAAA,EACJ;AACJ;AAKO,SAAS,UACZ,QACgC;AAChC,SAAO,OAAO,OAAO;AACzB;AAKO,SAAS,QACZ,QAC2B;AAC3B,SAAO,OAAO,OAAO;AACzB;AAKO,SAAS,OAAU,QAAkC;AACxD,MAAI,OAAO,IAAI;AACX,WAAO,OAAO;AAAA,EAClB;AACA,QAAM,IAAI,MAAM,OAAO,OAAO;AAClC;AAKO,SAAS,SAAY,QAA+B,cAAoB;AAC3E,MAAI,OAAO,IAAI;AACX,WAAO,OAAO;AAAA,EAClB;AACA,SAAO;AACX;;;ACjEO,SAAS,iBACZ,SACgB;AAChB,SAAO;AACX;AAcO,SAAS,gBACZ,QACA,YACgD;AAChD,SAAO,WAAW;AAAA,IACd,CAAC,MAAM,OACH,IAAI,WACA,GAAG,MAAM,GAAG,MAAM;AAAA,IAC1B;AAAA,EACJ;AACJ;AAWO,SAAS,qBACT,YACa;AAChB,SAAO,CAAC,SAAS,WAAW;AACxB,UAAM,QAAQ,WAAW;AAAA,MACrB,CAAC,QAAQ,OACL,IAAI,MACA,GAAG,QAAQ,GAAG,CAAC;AAAA,MACvB;AAAA,IACJ;AACA,WAAO,MAAM,GAAG,MAAM;AAAA,EAC1B;AACJ;AA4CO,SAAS,eACZ,QACA,UAAiC,CAAC,GACX;AACvB,QAAM,EAAE,OAAO,oBAAoB,YAAY,IAAI;AAEnD,SAAO,OAAO,MAAM,UAAU;AAC1B,UAAM,SAAS,OAAO,UAAU,KAAK;AAErC,QAAI,CAAC,OAAO,SAAS;AACjB,YAAM,UAAU,cACV,YAAY,OAAO,KAAK,IACxB,OAAO,MAAM,SAAS,CAAC,GAAG,WAC1B,OAAO,MAAM,WACb;AAEN,aAAO,EAAE,IAAI,OAAO,SAAS,KAAK;AAAA,IACtC;AAEA,WAAO,KAAK,OAAO,IAAI;AAAA,EAC3B;AACJ;AAKO,SAAS,YACZ,SAQI,CAAC,GACW;AAChB,SAAO,OAAO,SAAS,WAAW;AAC9B,WAAO,SAAS,MAAM;AACtB,UAAM,SAAS,MAAM,KAAK,GAAG,MAAM;AACnC,QAAI,OAAO,IAAI;AACX,aAAO,YAAY,OAAO,MAAM,MAAM;AAAA,IAC1C,OAAO;AACH,aAAO,UAAU,OAAO,SAAS,OAAO,MAAM,MAAM;AAAA,IACxD;AACA,WAAO;AAAA,EACX;AACJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/server/server-action.ts","../src/server/context-middleware.ts","../src/server/action-builder.ts","../src/server/middleware-utils.ts"],"sourcesContent":["\"use server\";\n\nexport type ServerActionSuccess<T> = {\n ok: true;\n data: T;\n};\n\nexport type ServerActionError = {\n ok: false;\n message: string;\n code?: string;\n};\n\nexport type ServerActionResult<T> = ServerActionSuccess<T> | ServerActionError;\n\nexport function success<T>(data: T): ServerActionSuccess<T> {\n return { ok: true, data };\n}\n\nexport function error(message: string, code?: string): ServerActionError {\n return { ok: false, message, code };\n}\n\nexport type ServerActionFn<P extends unknown[], T> = (\n ...args: P\n) => Promise<ServerActionResult<T>>;\n\ntype ServerActionOptions = {\n onError?: (error: unknown) => void;\n};\n\n/**\n * Wraps an async function to return a standardized ServerActionResult.\n * Catches any thrown errors and converts them to error results.\n *\n * @deprecated Use `createAction().input(schema).handle(fn)` instead.\n * The new API provides better type inference and built-in validation.\n *\n * @example\n * ```ts\n * // Old way (deprecated):\n * const myAction = serverAction(async (input: MyInput) => {\n * return await doSomething(input);\n * });\n *\n * // New way:\n * const myAction = createAction()\n * .input(mySchema)\n * .handle(async (ctx, input) => {\n * return { ok: true, data: await doSomething(input) };\n * });\n * ```\n */\nexport function serverAction<P extends unknown[], T>(\n fn: (...args: P) => Promise<T>,\n options?: ServerActionOptions,\n): ServerActionFn<P, T> {\n return async (...args: P): Promise<ServerActionResult<T>> => {\n try {\n const data = await fn(...args);\n return success(data);\n } catch (err) {\n options?.onError?.(err);\n\n if (err instanceof Error) {\n return error(err.message, err.name);\n }\n\n return error(\"An unexpected error occurred\", \"UNKNOWN_ERROR\");\n }\n };\n}\n\n/**\n * Type guard to check if a result is successful\n */\nexport function isSuccess<T>(\n result: ServerActionResult<T>,\n): result is ServerActionSuccess<T> {\n return result.ok === true;\n}\n\n/**\n * Type guard to check if a result is an error\n */\nexport function isError<T>(\n result: ServerActionResult<T>,\n): result is ServerActionError {\n return result.ok === false;\n}\n\n/**\n * Unwraps a successful result or throws the error message\n */\nexport function unwrap<T>(result: ServerActionResult<T>): T {\n if (result.ok) {\n return result.data;\n }\n throw new Error(result.message);\n}\n\n/**\n * Unwraps a successful result or returns a default value\n */\nexport function unwrapOr<T>(result: ServerActionResult<T>, defaultValue: T): T {\n if (result.ok) {\n return result.data;\n }\n return defaultValue;\n}\n","\"use server\";\n\nimport type { BaseContext, ContextMiddleware } from \"./types\";\n\n/**\n * Symbol to identify context-aware middleware at runtime\n */\nexport const CONTEXT_MIDDLEWARE = Symbol(\"contextMiddleware\");\n\n/**\n * Check if a middleware is context-aware\n */\nexport function isContextMiddleware(fn: unknown): boolean {\n return typeof fn === \"function\" && (fn as any)[CONTEXT_MIDDLEWARE] === true;\n}\n\n/**\n * Creates a type-safe context-aware middleware.\n *\n * @example\n * ```ts\n * type User = { id: string; name: string };\n *\n * const withAuth = createContextMiddleware<\n * [string], // Parameters\n * SomeReturnType, // Return type\n * {}, // Input context (none required)\n * { user: User } // Output context (adds user)\n * >(async (next, ctx, input) => {\n * const user = await authenticate();\n * if (!user) {\n * return { ok: false, message: \"Unauthorized\", code: \"UNAUTHORIZED\" };\n * }\n * // Pass the new context with user added\n * return next({ ...ctx, user }, input);\n * });\n * ```\n */\nexport function createContextMiddleware<\n P extends unknown[],\n T,\n CtxIn extends BaseContext = BaseContext,\n CtxOut extends BaseContext = BaseContext,\n>(\n handler: ContextMiddleware<P, T, CtxIn, CtxOut>,\n): ContextMiddleware<P, T, CtxIn, CtxOut> {\n (handler as any)[CONTEXT_MIDDLEWARE] = true;\n return handler;\n}\n","\"use server\";\n\nimport type { ServerActionResult } from \"./server-action\";\nimport type {\n BaseContext,\n ContextMiddleware,\n Middleware,\n} from \"./types\";\nimport { isContextMiddleware } from \"./context-middleware\";\n\n/**\n * A builder for creating server actions with type-safe context accumulation.\n *\n * @template TInput - The input parameters as a tuple type\n * @template TContext - The accumulated context type from all middleware\n */\nclass ActionBuilder<\n TInput extends unknown[] = unknown[],\n TContext extends BaseContext = {},\n> {\n private middlewares: Array<\n ContextMiddleware<any, any, any, any> | Middleware<any, any>\n > = [];\n\n private constructor(\n middlewares: Array<\n ContextMiddleware<any, any, any, any> | Middleware<any, any>\n > = [],\n ) {\n this.middlewares = middlewares;\n }\n\n /**\n * Create a new ActionBuilder instance\n */\n static create<TInput extends unknown[]>(): ActionBuilder<TInput, {}> {\n return new ActionBuilder<TInput, {}>();\n }\n\n /**\n * Add a context-aware middleware to the chain.\n * The middleware receives the accumulated context and can add new context.\n *\n * @example\n * ```ts\n * const withUser = createContextMiddleware(async (next, ctx, ...args) => {\n * const user = await getUser();\n * if (!user) {\n * return { ok: false, message: \"Unauthorized\", code: \"UNAUTHORIZED\" };\n * }\n * return next({ ...ctx, user }, ...args);\n * });\n *\n * const action = createAction<[{ name: string }]>()\n * .use(withUser)\n * .handle(async (ctx, input) => {\n * // ctx.user is fully typed!\n * });\n * ```\n */\n use<CtxOut extends BaseContext>(\n middleware: ContextMiddleware<TInput, any, TContext, CtxOut>,\n ): ActionBuilder<TInput, TContext & CtxOut>;\n\n /**\n * Add a regular (non-context) middleware to the chain.\n * The middleware can transform input/output but doesn't modify context.\n *\n * @example\n * ```ts\n * const withLogging = createMiddleware(async (next, ...args) => {\n * console.log(\"Args:\", args);\n * const result = await next(...args);\n * console.log(\"Result:\", result);\n * return result;\n * });\n *\n * const action = createAction<[string]>()\n * .use(withLogging)\n * .handle(async (ctx, input) => { ... });\n * ```\n */\n use(middleware: Middleware<TInput, any>): ActionBuilder<TInput, TContext>;\n\n use(middleware: any): any {\n return new ActionBuilder<TInput, TContext>([\n ...this.middlewares,\n middleware,\n ]);\n }\n\n /**\n * Define the action handler. This finalizes the builder and returns the executable action.\n * The handler receives the accumulated context and input parameters.\n *\n * @example\n * ```ts\n * const action = createAction<[{ name: string; email: string }]>()\n * .use(withUser)\n * .handle(async (ctx, input) => {\n * // ctx and input are fully typed\n * return { ok: true, data: result };\n * });\n *\n * // Call the action\n * const result = await action({ name: \"John\", email: \"john@example.com\" });\n * ```\n */\n handle<TOutput>(\n handler: (\n ctx: TContext,\n ...args: TInput\n ) => Promise<ServerActionResult<TOutput>>,\n ): (...args: TInput) => Promise<ServerActionResult<TOutput>> {\n const middlewares = [...this.middlewares];\n\n return async (...args: TInput): Promise<ServerActionResult<TOutput>> => {\n // Build the middleware chain\n type CtxNextFn = (\n ctx: BaseContext,\n ...args: TInput\n ) => Promise<ServerActionResult<TOutput>>;\n\n const finalHandler: CtxNextFn = async (ctx, ...a) => {\n return handler(ctx as TContext, ...a);\n };\n\n // Build chain from right to left (last middleware wraps closest to handler)\n const chain = middlewares.reduceRight<CtxNextFn>((next, mw) => {\n if (isContextMiddleware(mw)) {\n // Context middleware: (next, ctx, ...params) => ...\n return async (ctx, ...a) => {\n return (mw as ContextMiddleware<TInput, TOutput, any, any>)(\n async (newCtx, ...params) => next(newCtx, ...(params as TInput)),\n ctx,\n ...a,\n );\n };\n } else {\n // Regular middleware: (next, ...params) => ...\n // Pass context through unchanged\n return async (ctx, ...a) => {\n return (mw as Middleware<TInput, TOutput>)(\n async (...params) => next(ctx, ...(params as TInput)),\n ...a,\n );\n };\n }\n }, finalHandler);\n\n // Start with empty context\n try {\n return await chain({}, ...args);\n } catch (err) {\n const message =\n err instanceof Error ? err.message : \"Unknown error\";\n const code =\n err instanceof Error ? err.name : \"UNKNOWN_ERROR\";\n return { ok: false, message, code };\n }\n };\n }\n}\n\n/**\n * Converts a type to a tuple of arguments.\n * - `void` becomes `[]` (no args)\n * - Single type `T` becomes `[T]`\n * - Tuple type `[A, B]` stays as `[A, B]`\n */\ntype ToArgs<T> = [T] extends [void] ? [] : T extends unknown[] ? T : [T];\n\n/**\n * Creates a new action builder with type-safe context accumulation.\n *\n * @example\n * ```ts\n * // Single input parameter\n * const createUser = createAction<{ name: string; email: string }>()\n * .use(withUser)\n * .handle(async (ctx, input) => {\n * await db.users.create({ ...input, createdBy: ctx.user.id });\n * return { ok: true, data: { success: true } };\n * });\n *\n * // Multiple input parameters (use tuple)\n * const updateUser = createAction<[string, { name: string }]>()\n * .use(withUser)\n * .handle(async (ctx, id, data) => {\n * await db.users.update(id, data);\n * return { ok: true, data: { success: true } };\n * });\n *\n * // With validation middleware\n * const createPost = createAction<z.infer<typeof postSchema>>()\n * .use(withZodValidation(postSchema))\n * .use(withUser)\n * .handle(async (ctx, input) => {\n * return { ok: true, data: await db.posts.create(input) };\n * });\n * ```\n */\nexport function createAction<TInput = void>(): ActionBuilder<ToArgs<TInput>, {}> {\n return ActionBuilder.create<ToArgs<TInput>>();\n}\n","\"use server\";\n\nimport type { ServerActionResult } from \"./server-action\";\nimport type { Middleware, ValidationSchema, WithValidationOptions } from \"./types\";\n\n/**\n * Creates a type-safe middleware function.\n *\n * @example\n * ```ts\n * const withLogging = createMiddleware(async (next, ...params) => {\n * console.log(\"Calling action with:\", params);\n * const result = await next(...params);\n * console.log(\"Result:\", result);\n * return result;\n * });\n * ```\n */\nexport function createMiddleware<P extends unknown[], T>(\n handler: Middleware<P, T>,\n): Middleware<P, T> {\n return handler;\n}\n\n/**\n * Applies middleware to a server action.\n * Middleware is executed in order (first middleware wraps second, etc).\n *\n * @deprecated Use `createAction().input(schema).use(middleware).handle(fn)` instead.\n * This provides better type inference and a more composable API.\n *\n * @example\n * ```ts\n * // Old way (deprecated):\n * const protectedAction = applyMiddleware(\n * myServerAction,\n * [withAuth, withLogging, withValidation]\n * );\n *\n * // New way:\n * const protectedAction = createAction()\n * .input(schema)\n * .use(withAuth)\n * .use(withLogging)\n * .handle(async (ctx, input) => { ... });\n * ```\n */\nexport function applyMiddleware<P extends unknown[], T>(\n action: (...params: P) => Promise<ServerActionResult<T>>,\n middleware: Middleware<P, T>[],\n): (...params: P) => Promise<ServerActionResult<T>> {\n return middleware.reduceRight(\n (next, mw) =>\n (...params: P) =>\n mw(next, ...params),\n action,\n );\n}\n\n/**\n * Composes multiple middleware into a single middleware.\n *\n * @deprecated Use `createAction().use(mw1).use(mw2).handle(fn)` instead.\n * The builder pattern provides better type inference for chained middleware.\n *\n * @example\n * ```ts\n * // Old way (deprecated):\n * const combined = composeMiddleware(withAuth, withLogging, withValidation);\n * const protectedAction = applyMiddleware(myAction, [combined]);\n *\n * // New way:\n * const protectedAction = createAction()\n * .input(schema)\n * .use(withAuth)\n * .use(withLogging)\n * .handle(async (ctx, input) => { ... });\n * ```\n */\nexport function composeMiddleware<P extends unknown[], T>(\n ...middleware: Middleware<P, T>[]\n): Middleware<P, T> {\n return (next, ...params) => {\n const chain = middleware.reduceRight(\n (nextFn, mw) =>\n (...p: P) =>\n mw(nextFn, ...p),\n next,\n );\n return chain(...params);\n };\n}\n\n/**\n * Creates a middleware that validates the first parameter against a schema.\n * Works with Zod, Valibot, or any library with a compatible safeParse method.\n *\n * @deprecated Use `createAction().input(schema).handle(fn)` instead.\n * The `.input()` method provides automatic type inference from the schema.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n *\n * const schema = z.object({\n * name: z.string().min(1),\n * email: z.string().email(),\n * });\n *\n * // Old way (deprecated):\n * const createUser = applyMiddleware(\n * serverAction(async (input: z.infer<typeof schema>) => {\n * return await db.user.create({ data: input });\n * }),\n * [withZodValidation(schema)]\n * );\n *\n * // New way:\n * const createUser = createAction()\n * .input(schema) // Type is inferred automatically!\n * .handle(async (ctx, input) => {\n * return { ok: true, data: await db.user.create({ data: input }) };\n * });\n * ```\n */\nexport function withZodValidation<TInput, T>(\n schema: ValidationSchema<TInput>,\n options: WithValidationOptions = {},\n): Middleware<[TInput], T> {\n const { code = \"VALIDATION_ERROR\", formatError } = options;\n\n return async (next, input) => {\n const result = schema.safeParse(input);\n\n if (!result.success) {\n const message = formatError\n ? formatError(result.error)\n : (result.error.errors?.[0]?.message ??\n result.error.message ??\n \"Validation failed\");\n\n return { ok: false, message, code };\n }\n\n return next(result.data);\n };\n}\n\n/**\n * Creates a middleware that logs action calls and results.\n */\nexport function withLogging<P extends unknown[], T>(\n logger: {\n onCall?: (params: P) => void;\n onSuccess?: (data: T, params: P) => void;\n onError?: (\n message: string,\n code: string | undefined,\n params: P,\n ) => void;\n } = {},\n): Middleware<P, T> {\n return async (next, ...params) => {\n logger.onCall?.(params);\n const result = await next(...params);\n if (result.ok) {\n logger.onSuccess?.(result.data, params);\n } else {\n logger.onError?.(result.message, result.code, params);\n }\n return result;\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "use-server-action",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A React hook for working with Next.js server actions",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/jackh-sh/use-server-action.git"
|
|
11
|
+
},
|
|
8
12
|
"exports": {
|
|
9
13
|
".": {
|
|
10
14
|
"import": {
|