next-action-plus 0.0.0 → 1.0.2
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/LICENSE +21 -0
- package/README.md +18 -23
- package/dist/index.d.ts +33 -33
- package/dist/index.js +24 -22
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 muhgholy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -54,10 +54,10 @@ npm i zod
|
|
|
54
54
|
## Quick start
|
|
55
55
|
|
|
56
56
|
```ts
|
|
57
|
-
import {
|
|
57
|
+
import { createActionPlus } from 'next-action-plus';
|
|
58
58
|
import { z } from 'zod';
|
|
59
59
|
|
|
60
|
-
export const sayHello =
|
|
60
|
+
export const sayHello = createActionPlus()
|
|
61
61
|
.schema(z.object({ name: z.string().min(1) }))
|
|
62
62
|
.action(async ({ parsedInput }) => {
|
|
63
63
|
return { message: `Hello ${parsedInput.name}` };
|
|
@@ -83,7 +83,7 @@ Input (name) is error: String must contain at least 1 character(s)
|
|
|
83
83
|
Notes:
|
|
84
84
|
|
|
85
85
|
- Only the **first** validation issue is used to build the message.
|
|
86
|
-
- The thrown error is
|
|
86
|
+
- The thrown error is an `ActionPlusValidationError` (extends `Error`) with a developer-friendly payload.
|
|
87
87
|
- The original validator error is preserved on `error.cause`.
|
|
88
88
|
- Normalized issues are available on `error.issues`.
|
|
89
89
|
|
|
@@ -92,20 +92,20 @@ try {
|
|
|
92
92
|
await sayHello({ name: '' });
|
|
93
93
|
} catch (error) {
|
|
94
94
|
// error.message => "Input (name) is error: ..."
|
|
95
|
-
// (error as
|
|
96
|
-
// (error as
|
|
95
|
+
// (error as ActionPlusValidationError).code => "VALIDATION_ERROR"
|
|
96
|
+
// (error as ActionPlusValidationError).issues => [{ path, message, raw }]
|
|
97
97
|
// (error as any).cause => original validator error (e.g. ZodError)
|
|
98
98
|
}
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
### Customizing errors (options)
|
|
102
102
|
|
|
103
|
-
`
|
|
103
|
+
`createActionPlus` accepts options to control logging and customize thrown errors.
|
|
104
104
|
|
|
105
105
|
```ts
|
|
106
|
-
import {
|
|
106
|
+
import { createActionPlus } from 'next-action-plus';
|
|
107
107
|
|
|
108
|
-
export const client =
|
|
108
|
+
export const client = createActionPlus({
|
|
109
109
|
logger: false,
|
|
110
110
|
formatValidationError: ({ message, issues, error }) => {
|
|
111
111
|
const e = new Error(message);
|
|
@@ -129,10 +129,10 @@ This keeps the native Server Action feel.
|
|
|
129
129
|
|
|
130
130
|
```ts
|
|
131
131
|
import 'server-only';
|
|
132
|
-
import {
|
|
132
|
+
import { createActionPlus } from 'next-action-plus';
|
|
133
133
|
import { z } from 'zod';
|
|
134
134
|
|
|
135
|
-
export const updateProfile =
|
|
135
|
+
export const updateProfile = createActionPlus()
|
|
136
136
|
.schema(z.object({ displayName: z.string().min(2) }))
|
|
137
137
|
.action(async ({ parsedInput }) => {
|
|
138
138
|
// parsedInput.displayName is string
|
|
@@ -140,8 +140,6 @@ export const updateProfile = createSafeActionClient()
|
|
|
140
140
|
});
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
More: [examples/nextjs-server-action.ts](https://github.com/muhgholy/next-action-plus/blob/main/examples/nextjs-server-action.ts)
|
|
144
|
-
|
|
145
143
|
### Client Component usage
|
|
146
144
|
|
|
147
145
|
You can import a Server Action into a Client Component and call it like a normal async function.
|
|
@@ -178,10 +176,7 @@ export function SayHelloClient() {
|
|
|
178
176
|
}
|
|
179
177
|
```
|
|
180
178
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
- [examples/nextjs-server-action-for-client.ts](https://github.com/muhgholy/next-action-plus/blob/main/examples/nextjs-server-action-for-client.ts)
|
|
184
|
-
- [examples/nextjs-client-component.tsx](https://github.com/muhgholy/next-action-plus/blob/main/examples/nextjs-client-component.tsx)
|
|
179
|
+
The snippets above are the full examples.
|
|
185
180
|
|
|
186
181
|
### FormData + File uploads
|
|
187
182
|
|
|
@@ -190,10 +185,10 @@ Works with `FormData` and `File` using `zod-form-data`.
|
|
|
190
185
|
If you chain multiple schemas and the input is a `FormData`, next-action-plus will first try to find a schema that can parse the `FormData` into a plain object, then validate the remaining schemas against that object.
|
|
191
186
|
|
|
192
187
|
```ts
|
|
193
|
-
import {
|
|
188
|
+
import { createActionPlus } from 'next-action-plus';
|
|
194
189
|
import { zfd } from 'zod-form-data';
|
|
195
190
|
|
|
196
|
-
export const uploadAvatar =
|
|
191
|
+
export const uploadAvatar = createActionPlus()
|
|
197
192
|
.schema(
|
|
198
193
|
zfd.formData({
|
|
199
194
|
avatar: zfd.file(),
|
|
@@ -212,10 +207,10 @@ Add data to context in a type-safe way.
|
|
|
212
207
|
Validation runs first, then middleware runs, then your handler runs.
|
|
213
208
|
|
|
214
209
|
```ts
|
|
215
|
-
import {
|
|
210
|
+
import { createActionPlus } from 'next-action-plus';
|
|
216
211
|
import { z } from 'zod';
|
|
217
212
|
|
|
218
|
-
const client =
|
|
213
|
+
const client = createActionPlus().use(async ({ next }) => next({ ctx: { userId: 'u_123' } }));
|
|
219
214
|
|
|
220
215
|
export const deletePost = client.schema(z.object({ postId: z.string() })).action(async ({ parsedInput, ctx }) => {
|
|
221
216
|
// ctx.userId is string
|
|
@@ -241,12 +236,12 @@ If you already have a schema system, you can plug it in.
|
|
|
241
236
|
You can chain multiple schemas. If they return objects, outputs are merged.
|
|
242
237
|
|
|
243
238
|
```ts
|
|
244
|
-
import {
|
|
239
|
+
import { createActionPlus } from 'next-action-plus';
|
|
245
240
|
|
|
246
241
|
const s1 = { parse: (_: unknown) => ({ a: 'a' }) };
|
|
247
242
|
const s2 = { parse: (_: unknown) => ({ b: 2 }) };
|
|
248
243
|
|
|
249
|
-
export const demo =
|
|
244
|
+
export const demo = createActionPlus()
|
|
250
245
|
.schema(s1)
|
|
251
246
|
.schema(s2)
|
|
252
247
|
.action(async ({ parsedInput }) => {
|
|
@@ -263,7 +258,7 @@ No. It is built for the Server Actions style, but it runs in any Node 20+ runtim
|
|
|
263
258
|
|
|
264
259
|
### Do I need to learn a new pattern?
|
|
265
260
|
|
|
266
|
-
No. The API is intentionally small: `
|
|
261
|
+
No. The API is intentionally small: `createActionPlus() → .schema() → .use() → .action()`.
|
|
267
262
|
|
|
268
263
|
### Can I validate `FormData`?
|
|
269
264
|
|
package/dist/index.d.ts
CHANGED
|
@@ -22,27 +22,27 @@ type TPrettify<T> = {
|
|
|
22
22
|
} & {};
|
|
23
23
|
type TUnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
24
24
|
|
|
25
|
-
type
|
|
26
|
-
type
|
|
27
|
-
path:
|
|
25
|
+
type TActionPlusIssuePathSegment = string | number;
|
|
26
|
+
type TActionPlusIssue = {
|
|
27
|
+
path: TActionPlusIssuePathSegment[];
|
|
28
28
|
message: string;
|
|
29
29
|
raw?: unknown;
|
|
30
30
|
};
|
|
31
|
-
type
|
|
32
|
-
type
|
|
33
|
-
type
|
|
34
|
-
phase:
|
|
31
|
+
type TActionPlusErrorCode = 'VALIDATION_ERROR' | 'MIDDLEWARE_ERROR' | 'HANDLER_ERROR' | 'ACTION_ERROR';
|
|
32
|
+
type TActionPlusErrorPhase = 'validation' | 'middleware' | 'handler';
|
|
33
|
+
type TActionPlusUnknownErrorContext = {
|
|
34
|
+
phase: TActionPlusErrorPhase;
|
|
35
35
|
error: unknown;
|
|
36
36
|
input?: unknown;
|
|
37
37
|
parsedInput?: unknown;
|
|
38
38
|
ctx?: Record<string, unknown>;
|
|
39
39
|
};
|
|
40
|
-
type
|
|
40
|
+
type TActionPlusValidationErrorContext = TActionPlusUnknownErrorContext & {
|
|
41
41
|
message: string;
|
|
42
|
-
issues:
|
|
42
|
+
issues: TActionPlusIssue[];
|
|
43
43
|
};
|
|
44
|
-
type
|
|
45
|
-
type
|
|
44
|
+
type TActionPlusErrorContext = TActionPlusUnknownErrorContext | TActionPlusValidationErrorContext;
|
|
45
|
+
type TActionPlusOptions = {
|
|
46
46
|
/**
|
|
47
47
|
* Control logging when an action throws.
|
|
48
48
|
* - `false` disables logging.
|
|
@@ -54,46 +54,46 @@ type TSafeActionClientOptions = {
|
|
|
54
54
|
/**
|
|
55
55
|
* Hook called whenever an action throws (validation, middleware, or handler).
|
|
56
56
|
*/
|
|
57
|
-
onError?: (ctx:
|
|
57
|
+
onError?: (ctx: TActionPlusErrorContext) => void;
|
|
58
58
|
/**
|
|
59
59
|
* Customize the thrown error when validation fails.
|
|
60
60
|
* The returned Error will be thrown.
|
|
61
61
|
*/
|
|
62
|
-
formatValidationError?: (ctx:
|
|
62
|
+
formatValidationError?: (ctx: TActionPlusValidationErrorContext) => Error;
|
|
63
63
|
/**
|
|
64
64
|
* Customize the thrown error for non-validation failures.
|
|
65
65
|
* If omitted, the original error is re-thrown.
|
|
66
66
|
*/
|
|
67
|
-
formatError?: (ctx:
|
|
67
|
+
formatError?: (ctx: TActionPlusUnknownErrorContext) => Error;
|
|
68
68
|
/**
|
|
69
69
|
* When enabled, include `input`, `parsedInput`, and `ctx` in error details.
|
|
70
70
|
* Off by default because it can accidentally expose sensitive data.
|
|
71
71
|
*/
|
|
72
72
|
includeInputInErrorDetails?: boolean;
|
|
73
73
|
};
|
|
74
|
-
declare class
|
|
75
|
-
code:
|
|
76
|
-
phase?:
|
|
74
|
+
declare class ActionPlusError extends Error {
|
|
75
|
+
code: TActionPlusErrorCode;
|
|
76
|
+
phase?: TActionPlusErrorPhase;
|
|
77
77
|
data?: unknown;
|
|
78
78
|
cause?: unknown;
|
|
79
79
|
constructor(message: string, opts?: {
|
|
80
|
-
code:
|
|
81
|
-
phase?:
|
|
80
|
+
code: TActionPlusErrorCode;
|
|
81
|
+
phase?: TActionPlusErrorPhase;
|
|
82
82
|
cause?: unknown;
|
|
83
83
|
data?: unknown;
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
|
-
declare class
|
|
87
|
-
issues:
|
|
86
|
+
declare class ActionPlusValidationError extends ActionPlusError {
|
|
87
|
+
issues: TActionPlusIssue[];
|
|
88
88
|
constructor(message: string, opts: {
|
|
89
|
-
issues:
|
|
90
|
-
phase?:
|
|
89
|
+
issues: TActionPlusIssue[];
|
|
90
|
+
phase?: TActionPlusErrorPhase;
|
|
91
91
|
cause?: unknown;
|
|
92
92
|
data?: unknown;
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
-
declare const
|
|
96
|
-
declare const
|
|
95
|
+
declare const isActionPlusError: (error: unknown) => error is ActionPlusError;
|
|
96
|
+
declare const isActionPlusValidationError: (error: unknown) => error is ActionPlusValidationError;
|
|
97
97
|
|
|
98
98
|
type TGenericSchema = {
|
|
99
99
|
parse: (input: unknown) => unknown;
|
|
@@ -165,9 +165,9 @@ type TFormDataInput<S extends TSchema> = S extends z.ZodTypeAny ? TZodFormDataIn
|
|
|
165
165
|
type TFormDataCompatibleInput<S extends readonly TSchema[]> = S extends readonly [infer First extends TSchema, ...infer Rest extends TSchema[]] ? (TIsFormData<First> extends true ? FormData : never) | TPrettify<TUnionToIntersection<TInferIn<First>>> | (Rest['length'] extends 0 ? never : TFormDataCompatibleInput<Rest>) : Record<string, never>;
|
|
166
166
|
|
|
167
167
|
/**
|
|
168
|
-
* Class that handles
|
|
168
|
+
* Class that handles server actions with validation
|
|
169
169
|
*/
|
|
170
|
-
declare class
|
|
170
|
+
declare class ActionPlus<Schemas extends TSchema[] = [], Ctx extends Record<string, unknown> = Record<string, never>, Middlewares extends readonly TMiddlewareFn<any, any>[] = []> {
|
|
171
171
|
private schemas;
|
|
172
172
|
private middlewares;
|
|
173
173
|
private ctx;
|
|
@@ -176,18 +176,18 @@ declare class SafeActionClient<Schemas extends TSchema[] = [], Ctx extends Recor
|
|
|
176
176
|
schemas?: Schemas;
|
|
177
177
|
middlewares?: Middlewares;
|
|
178
178
|
ctx?: Ctx;
|
|
179
|
-
options?:
|
|
179
|
+
options?: TActionPlusOptions;
|
|
180
180
|
});
|
|
181
181
|
/**
|
|
182
182
|
* Adds a validation schema
|
|
183
183
|
* @param schema Validation schema
|
|
184
184
|
*/
|
|
185
|
-
schema<S extends TSchema>(schema: S):
|
|
185
|
+
schema<S extends TSchema>(schema: S): ActionPlus<[...Schemas, S], Ctx, Middlewares>;
|
|
186
186
|
/**
|
|
187
187
|
* Adds a middleware function
|
|
188
188
|
* @param middleware Middleware function
|
|
189
189
|
*/
|
|
190
|
-
use<NextCtx extends Record<string, unknown>>(middleware: TMiddlewareFn<Ctx, NextCtx>):
|
|
190
|
+
use<NextCtx extends Record<string, unknown>>(middleware: TMiddlewareFn<Ctx, NextCtx>): ActionPlus<Schemas, Ctx & NextCtx, [...Middlewares, TMiddlewareFn<Ctx, NextCtx>]>;
|
|
191
191
|
/**
|
|
192
192
|
* Creates an action with validation and middleware
|
|
193
193
|
* @param handler Action handler function
|
|
@@ -207,8 +207,8 @@ declare class SafeActionClient<Schemas extends TSchema[] = [], Ctx extends Recor
|
|
|
207
207
|
private isValidationError;
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
|
-
* Creates
|
|
210
|
+
* Creates an ActionPlus client that handles validation and execution of server actions
|
|
211
211
|
*/
|
|
212
|
-
declare const
|
|
212
|
+
declare const createActionPlus: (options?: TActionPlusOptions) => ActionPlus<[], Record<string, never>, []>;
|
|
213
213
|
|
|
214
|
-
export {
|
|
214
|
+
export { ActionPlus, ActionPlusError, ActionPlusValidationError, type TActionPlusErrorCode, type TActionPlusErrorContext, type TActionPlusErrorPhase, type TActionPlusIssue, type TActionPlusIssuePathSegment, type TActionPlusOptions, type TActionPlusUnknownErrorContext, type TActionPlusValidationErrorContext, type TFormDataCompatibleInput, type TFormDataInput, type TGenericSchema, type TGenericSchemaAsync, type TIfInstalled, type TInfer, type TInferArray, type TInferIn, type TInferInArray, type TIsAny, type TIsFormData, type TMiddlewareFn, type TPrettify, type TSchema, type TSchemaAvailable, type TStandardSchemaV1, type TStandardSchemaV1InferInput, type TStandardSchemaV1InferOutput, type TStandardSchemaV1Issue, type TStandardSchemaV1PathSegment, type TStandardSchemaV1Result, type TUnionToIntersection, type TZodAcceptsFormData, type TZodFormDataInput, type TZodFormDataSchemaFactory, createActionPlus, isActionPlusError, isActionPlusValidationError, schemaAvailable };
|
package/dist/index.js
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
// src/types/errors.ts
|
|
2
|
-
var
|
|
2
|
+
var ActionPlusError = class extends Error {
|
|
3
3
|
code;
|
|
4
4
|
phase;
|
|
5
5
|
data;
|
|
6
6
|
constructor(message, opts = { code: "ACTION_ERROR" }) {
|
|
7
7
|
super(message, { cause: opts.cause });
|
|
8
|
-
this.name = "
|
|
8
|
+
this.name = "ActionPlusError";
|
|
9
9
|
this.code = opts.code;
|
|
10
10
|
this.phase = opts.phase;
|
|
11
11
|
this.data = opts.data;
|
|
12
12
|
this.cause = opts.cause;
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
|
-
var
|
|
15
|
+
var ActionPlusValidationError = class extends ActionPlusError {
|
|
16
16
|
issues;
|
|
17
17
|
constructor(message, opts) {
|
|
18
18
|
super(message, { code: "VALIDATION_ERROR", phase: opts.phase, cause: opts.cause, data: opts.data });
|
|
19
|
-
this.name = "
|
|
19
|
+
this.name = "ActionPlusValidationError";
|
|
20
20
|
this.issues = opts.issues;
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
-
var
|
|
23
|
+
var isActionPlusError = (error) => {
|
|
24
24
|
if (typeof error !== "object" || error === null) return false;
|
|
25
25
|
if (!("code" in error)) return false;
|
|
26
26
|
const name = error.name;
|
|
27
|
-
return name === "
|
|
27
|
+
return name === "ActionPlusError" || name === "ActionPlusValidationError";
|
|
28
28
|
};
|
|
29
|
-
var
|
|
30
|
-
return typeof error === "object" && error !== null && "issues" in error && error.name === "
|
|
29
|
+
var isActionPlusValidationError = (error) => {
|
|
30
|
+
return typeof error === "object" && error !== null && "issues" in error && error.name === "ActionPlusValidationError";
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
// src/types/schema/index.ts
|
|
34
34
|
var schemaAvailable = ["zod", "generic", "genericAsync", "standard"];
|
|
35
35
|
|
|
36
36
|
// src/index.ts
|
|
37
|
-
var
|
|
37
|
+
var ActionPlus = class _ActionPlus {
|
|
38
38
|
schemas;
|
|
39
39
|
middlewares;
|
|
40
40
|
ctx;
|
|
@@ -50,7 +50,7 @@ var SafeActionClient = class _SafeActionClient {
|
|
|
50
50
|
* @param schema Validation schema
|
|
51
51
|
*/
|
|
52
52
|
schema(schema) {
|
|
53
|
-
return new
|
|
53
|
+
return new _ActionPlus({
|
|
54
54
|
schemas: [...this.schemas, schema],
|
|
55
55
|
middlewares: this.middlewares,
|
|
56
56
|
ctx: this.ctx,
|
|
@@ -62,7 +62,7 @@ var SafeActionClient = class _SafeActionClient {
|
|
|
62
62
|
* @param middleware Middleware function
|
|
63
63
|
*/
|
|
64
64
|
use(middleware) {
|
|
65
|
-
return new
|
|
65
|
+
return new _ActionPlus({
|
|
66
66
|
schemas: this.schemas,
|
|
67
67
|
middlewares: [...this.middlewares, middleware],
|
|
68
68
|
ctx: this.ctx,
|
|
@@ -104,7 +104,7 @@ var SafeActionClient = class _SafeActionClient {
|
|
|
104
104
|
const { message, issues } = this.formatValidationErrorParts(error);
|
|
105
105
|
const validationContext = { ...baseContext, message, issues };
|
|
106
106
|
this.options.onError?.(validationContext);
|
|
107
|
-
const formatted = this.options.formatValidationError?.(validationContext) ?? new
|
|
107
|
+
const formatted = this.options.formatValidationError?.(validationContext) ?? new ActionPlusValidationError(message, {
|
|
108
108
|
issues,
|
|
109
109
|
phase,
|
|
110
110
|
cause: error,
|
|
@@ -134,8 +134,10 @@ var SafeActionClient = class _SafeActionClient {
|
|
|
134
134
|
normalizeIssues(error) {
|
|
135
135
|
if (typeof error !== "object" || error === null) return [];
|
|
136
136
|
const maybe = error;
|
|
137
|
-
const
|
|
138
|
-
|
|
137
|
+
const errorsCandidate = maybe.errors;
|
|
138
|
+
const issuesCandidate = maybe.issues;
|
|
139
|
+
const rawIssues = Array.isArray(errorsCandidate) ? errorsCandidate : Array.isArray(issuesCandidate) ? issuesCandidate : [];
|
|
140
|
+
return rawIssues.filter((issue) => typeof issue === "object" && issue !== null).map((issue) => ({
|
|
139
141
|
path: this.normalizeIssuePath(issue.path),
|
|
140
142
|
message: typeof issue.message === "string" ? issue.message : String(issue.message ?? ""),
|
|
141
143
|
raw: issue
|
|
@@ -274,16 +276,16 @@ var SafeActionClient = class _SafeActionClient {
|
|
|
274
276
|
return "errors" in error || "issues" in error;
|
|
275
277
|
}
|
|
276
278
|
};
|
|
277
|
-
var
|
|
278
|
-
return new
|
|
279
|
+
var createActionPlus = (options) => {
|
|
280
|
+
return new ActionPlus({ options });
|
|
279
281
|
};
|
|
280
282
|
export {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
283
|
+
ActionPlus,
|
|
284
|
+
ActionPlusError,
|
|
285
|
+
ActionPlusValidationError,
|
|
286
|
+
createActionPlus,
|
|
287
|
+
isActionPlusError,
|
|
288
|
+
isActionPlusValidationError,
|
|
287
289
|
schemaAvailable
|
|
288
290
|
};
|
|
289
291
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/errors.ts","../src/types/schema/index.ts","../src/index.ts"],"sourcesContent":["export type TSafeActionIssuePathSegment = string | number;\r\n\r\nexport type TSafeActionIssue = {\r\n\tpath: TSafeActionIssuePathSegment[];\r\n\tmessage: string;\r\n\traw?: unknown;\r\n};\r\n\r\nexport type TSafeActionErrorCode = 'VALIDATION_ERROR' | 'MIDDLEWARE_ERROR' | 'HANDLER_ERROR' | 'ACTION_ERROR';\r\n\r\nexport type TSafeActionErrorPhase = 'validation' | 'middleware' | 'handler';\r\n\r\nexport type TSafeActionUnknownErrorContext = {\r\n\tphase: TSafeActionErrorPhase;\r\n\terror: unknown;\r\n\tinput?: unknown;\r\n\tparsedInput?: unknown;\r\n\tctx?: Record<string, unknown>;\r\n};\r\n\r\nexport type TSafeActionValidationErrorContext = TSafeActionUnknownErrorContext & {\r\n\tmessage: string;\r\n\tissues: TSafeActionIssue[];\r\n};\r\n\r\nexport type TSafeActionErrorContext = TSafeActionUnknownErrorContext | TSafeActionValidationErrorContext;\r\n\r\nexport type TSafeActionClientOptions = {\r\n\t/**\r\n\t * Control logging when an action throws.\r\n\t * - `false` disables logging.\r\n\t * - Defaults to `console`.\r\n\t */\r\n\tlogger?: false | { error: (...args: unknown[]) => void };\r\n\r\n\t/**\r\n\t * Hook called whenever an action throws (validation, middleware, or handler).\r\n\t */\r\n\tonError?: (ctx: TSafeActionErrorContext) => void;\r\n\r\n\t/**\r\n\t * Customize the thrown error when validation fails.\r\n\t * The returned Error will be thrown.\r\n\t */\r\n\tformatValidationError?: (ctx: TSafeActionValidationErrorContext) => Error;\r\n\r\n\t/**\r\n\t * Customize the thrown error for non-validation failures.\r\n\t * If omitted, the original error is re-thrown.\r\n\t */\r\n\tformatError?: (ctx: TSafeActionUnknownErrorContext) => Error;\r\n\r\n\t/**\r\n\t * When enabled, include `input`, `parsedInput`, and `ctx` in error details.\r\n\t * Off by default because it can accidentally expose sensitive data.\r\n\t */\r\n\tincludeInputInErrorDetails?: boolean;\r\n};\r\n\r\nexport class SafeActionError extends Error {\r\n\tcode: TSafeActionErrorCode;\r\n\tphase?: TSafeActionErrorPhase;\r\n\tdata?: unknown;\r\n\tdeclare cause?: unknown;\r\n\r\n\tconstructor(\r\n\t\tmessage: string,\r\n\t\topts: {\r\n\t\t\tcode: TSafeActionErrorCode;\r\n\t\t\tphase?: TSafeActionErrorPhase;\r\n\t\t\tcause?: unknown;\r\n\t\t\tdata?: unknown;\r\n\t\t} = { code: 'ACTION_ERROR' },\r\n\t) {\r\n\t\tsuper(message, { cause: opts.cause });\r\n\t\tthis.name = 'SafeActionError';\r\n\t\tthis.code = opts.code;\r\n\t\tthis.phase = opts.phase;\r\n\t\tthis.data = opts.data;\r\n\t\tthis.cause = opts.cause;\r\n\t}\r\n}\r\n\r\nexport class SafeActionValidationError extends SafeActionError {\r\n\tissues: TSafeActionIssue[];\r\n\r\n\tconstructor(\r\n\t\tmessage: string,\r\n\t\topts: {\r\n\t\t\tissues: TSafeActionIssue[];\r\n\t\t\tphase?: TSafeActionErrorPhase;\r\n\t\t\tcause?: unknown;\r\n\t\t\tdata?: unknown;\r\n\t\t},\r\n\t) {\r\n\t\tsuper(message, { code: 'VALIDATION_ERROR', phase: opts.phase, cause: opts.cause, data: opts.data });\r\n\t\tthis.name = 'SafeActionValidationError';\r\n\t\tthis.issues = opts.issues;\r\n\t}\r\n}\r\n\r\nexport const isSafeActionError = (error: unknown): error is SafeActionError => {\r\n\tif (typeof error !== 'object' || error === null) return false;\r\n\tif (!('code' in error)) return false;\r\n\tconst name = (error as { name?: unknown }).name;\r\n\treturn name === 'SafeActionError' || name === 'SafeActionValidationError';\r\n};\r\n\r\nexport const isSafeActionValidationError = (error: unknown): error is SafeActionValidationError => {\r\n\treturn typeof error === 'object' && error !== null && 'issues' in error && (error as { name?: unknown }).name === 'SafeActionValidationError';\r\n};\r\n","import type { z } from 'zod';\r\n\r\nimport type { TIfInstalled, TPrettify, TUnionToIntersection } from '../utils';\r\nimport type { TGenericSchema, TGenericSchemaAsync } from './generic';\r\nimport type { TStandardSchemaV1, TStandardSchemaV1InferInput, TStandardSchemaV1InferOutput } from './standard';\r\nimport type { TZodAcceptsFormData, TZodFormDataInput } from './zod';\r\n\r\nexport const schemaAvailable = ['zod', 'generic', 'genericAsync', 'standard'] as const;\r\nexport type TSchemaAvailable = (typeof schemaAvailable)[number];\r\n\r\nexport type TSchema = TIfInstalled<z.ZodTypeAny> | TIfInstalled<TGenericSchema> | TIfInstalled<TGenericSchemaAsync> | TStandardSchemaV1<any, any>;\r\n\r\nexport type TInfer<S extends TSchema> = S extends TIfInstalled<z.ZodTypeAny> ? z.infer<S> : S extends TIfInstalled<TGenericSchema> ? ReturnType<S['parse']> : S extends TIfInstalled<TGenericSchemaAsync> ? Awaited<ReturnType<S['parseAsync']>> : S extends TStandardSchemaV1<any, any> ? TStandardSchemaV1InferOutput<S> : never;\r\n\r\nexport type TInferIn<S extends TSchema> = S extends TIfInstalled<z.ZodTypeAny> ? z.input<S> : S extends TIfInstalled<TGenericSchema> ? Parameters<S['parse']>[0] : S extends TIfInstalled<TGenericSchemaAsync> ? Parameters<S['parseAsync']>[0] : S extends TStandardSchemaV1<any, any> ? TStandardSchemaV1InferInput<S> : never;\r\n\r\nexport type TInferArray<S extends readonly TSchema[]> = S extends readonly [infer First extends TSchema, ...infer Rest extends TSchema[]] ? [TInfer<First>, ...TInferArray<Rest>] : [];\r\n\r\nexport type TInferInArray<S extends readonly TSchema[]> = S extends readonly [infer First extends TSchema, ...infer Rest extends TSchema[]] ? [TInferIn<First>, ...TInferInArray<Rest>] : [];\r\n\r\nexport type TIsFormData<S extends TSchema> = S extends z.ZodTypeAny ? TZodAcceptsFormData<S> : S extends TStandardSchemaV1<infer Input, any> ? (FormData extends Input ? true : false) : false;\r\n\r\nexport type TFormDataInput<S extends TSchema> = S extends z.ZodTypeAny ? TZodFormDataInput<S> : S extends TStandardSchemaV1<infer Input, any> ? (FormData extends Input ? FormData | TInferIn<S> : TInferIn<S>) : TInferIn<S>;\r\n\r\nexport type TFormDataCompatibleInput<S extends readonly TSchema[]> = S extends readonly [infer First extends TSchema, ...infer Rest extends TSchema[]] ? (TIsFormData<First> extends true ? FormData : never) | TPrettify<TUnionToIntersection<TInferIn<First>>> | (Rest['length'] extends 0 ? never : TFormDataCompatibleInput<Rest>) : Record<string, never>;\r\n","import type { TSafeActionClientOptions, TSafeActionErrorPhase, TSafeActionIssue, TFormDataCompatibleInput, TFormDataInput, TInfer, TPrettify, TSchema, TMiddlewareFn, TUnionToIntersection } from './types';\r\nimport { SafeActionValidationError } from './types';\r\n\r\nexport { schemaAvailable } from './types';\r\nexport { SafeActionError, SafeActionValidationError, isSafeActionError, isSafeActionValidationError } from './types';\r\nexport type * from './types';\r\n\r\n/**\r\n * Class that handles safe server actions with validation\r\n */\r\nexport class SafeActionClient<Schemas extends TSchema[] = [], Ctx extends Record<string, unknown> = Record<string, never>, Middlewares extends readonly TMiddlewareFn<any, any>[] = []> {\r\n\tprivate schemas: Schemas;\r\n\tprivate middlewares: Middlewares;\r\n\tprivate ctx: Ctx;\r\n\tprivate options: TSafeActionClientOptions;\r\n\r\n\tconstructor(\r\n\t\toptions: {\r\n\t\t\tschemas?: Schemas;\r\n\t\t\tmiddlewares?: Middlewares;\r\n\t\t\tctx?: Ctx;\r\n\t\t\toptions?: TSafeActionClientOptions;\r\n\t\t} = {},\r\n\t) {\r\n\t\tthis.schemas = (options.schemas || []) as unknown as Schemas;\r\n\t\tthis.middlewares = (options.middlewares || []) as unknown as Middlewares;\r\n\t\tthis.ctx = (options.ctx || {}) as Ctx;\r\n\t\tthis.options = options.options ?? {};\r\n\t}\r\n\r\n\t/**\r\n\t * Adds a validation schema\r\n\t * @param schema Validation schema\r\n\t */\r\n\tschema<S extends TSchema>(schema: S): SafeActionClient<[...Schemas, S], Ctx, Middlewares> {\r\n\t\treturn new SafeActionClient({\r\n\t\t\tschemas: [...this.schemas, schema] as unknown as [...Schemas, S],\r\n\t\t\tmiddlewares: this.middlewares,\r\n\t\t\tctx: this.ctx,\r\n\t\t\toptions: this.options,\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Adds a middleware function\r\n\t * @param middleware Middleware function\r\n\t */\r\n\tuse<NextCtx extends Record<string, unknown>>(middleware: TMiddlewareFn<Ctx, NextCtx>): SafeActionClient<Schemas, Ctx & NextCtx, [...Middlewares, TMiddlewareFn<Ctx, NextCtx>]> {\r\n\t\treturn new SafeActionClient({\r\n\t\t\tschemas: this.schemas,\r\n\t\t\tmiddlewares: [...this.middlewares, middleware] as unknown as [...Middlewares, TMiddlewareFn<Ctx, NextCtx>],\r\n\t\t\tctx: this.ctx as unknown as Ctx & NextCtx,\r\n\t\t\toptions: this.options,\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Creates an action with validation and middleware\r\n\t * @param handler Action handler function\r\n\t */\r\n\taction<Output>(handler: (props: { parsedInput: Schemas extends (infer S extends TSchema)[] ? TPrettify<TUnionToIntersection<TInfer<S>>> : Record<string, never>; ctx: TPrettify<Ctx> }) => Promise<Output>): (input?: Schemas extends [infer S extends TSchema] ? TFormDataInput<S> : Schemas extends (infer _S extends TSchema)[] ? TFormDataCompatibleInput<Schemas> : unknown) => Promise<Output> {\r\n\t\treturn async (input?: unknown): Promise<Output> => {\r\n\t\t\tlet phase: TSafeActionErrorPhase = 'validation';\r\n\t\t\tlet parsedInputForErrors: unknown = undefined;\r\n\t\t\tlet ctxForErrors: unknown = undefined;\r\n\r\n\t\t\ttry {\r\n\t\t\t\t// Validate input against all schemas\r\n\t\t\t\ttype ParsedInput = Schemas extends (infer S extends TSchema)[] ? TPrettify<TUnionToIntersection<TInfer<S>>> : Record<string, never>;\r\n\t\t\t\tphase = 'validation';\r\n\t\t\t\tconst parsedInput = (await this.validateInput(input)) as ParsedInput;\r\n\t\t\t\tparsedInputForErrors = parsedInput;\r\n\r\n\t\t\t\t// Run middleware chain\r\n\t\t\t\tphase = 'middleware';\r\n\t\t\t\tconst ctx = await this.runMiddlewareChain(parsedInput);\r\n\t\t\t\tctxForErrors = ctx;\r\n\r\n\t\t\t\t// Execute handler\r\n\t\t\t\tphase = 'handler';\r\n\t\t\t\treturn await handler({ parsedInput, ctx });\r\n\t\t\t} catch (error: unknown) {\r\n\t\t\t\tconst logger = this.options.logger === undefined ? console : this.options.logger;\r\n\t\t\t\tif (logger !== false) {\r\n\t\t\t\t\tlogger.error('Action error:', error);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst includeInput = this.options.includeInputInErrorDetails === true;\r\n\t\t\t\tconst baseContext = {\r\n\t\t\t\t\tphase,\r\n\t\t\t\t\terror,\r\n\t\t\t\t\tinput: includeInput ? input : undefined,\r\n\t\t\t\t\tparsedInput: includeInput ? parsedInputForErrors : undefined,\r\n\t\t\t\t\tctx: includeInput ? (ctxForErrors as Record<string, unknown> | undefined) : undefined,\r\n\t\t\t\t};\r\n\r\n\t\t\t\t// Handle validation errors\r\n\t\t\t\tif (this.isValidationError(error)) {\r\n\t\t\t\t\tconst { message, issues } = this.formatValidationErrorParts(error);\r\n\t\t\t\t\tconst validationContext = { ...baseContext, message, issues };\r\n\t\t\t\t\tthis.options.onError?.(validationContext);\r\n\r\n\t\t\t\t\tconst formatted =\r\n\t\t\t\t\t\tthis.options.formatValidationError?.(validationContext) ??\r\n\t\t\t\t\t\tnew SafeActionValidationError(message, {\r\n\t\t\t\t\t\t\tissues,\r\n\t\t\t\t\t\t\tphase,\r\n\t\t\t\t\t\t\tcause: error,\r\n\t\t\t\t\t\t\tdata: includeInput ? { input, parsedInput: parsedInputForErrors, ctx: ctxForErrors } : undefined,\r\n\t\t\t\t\t\t});\r\n\r\n\t\t\t\t\tthrow formatted;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.options.onError?.(baseContext);\r\n\t\t\t\tconst maybeFormatted = this.options.formatError?.(baseContext);\r\n\t\t\t\tif (maybeFormatted) throw maybeFormatted;\r\n\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\tprivate normalizeIssuePath(path: unknown): Array<string | number> {\r\n\t\tif (!Array.isArray(path)) return [];\r\n\t\treturn path.map(seg => {\r\n\t\t\tif (typeof seg === 'string' || typeof seg === 'number') return seg;\r\n\t\t\tif (typeof seg === 'object' && seg !== null && 'key' in (seg as Record<string, unknown>)) {\r\n\t\t\t\tconst key = (seg as { key: unknown }).key;\r\n\t\t\t\tif (typeof key === 'string' || typeof key === 'number') return key;\r\n\t\t\t\treturn String(key);\r\n\t\t\t}\r\n\t\t\treturn String(seg);\r\n\t\t});\r\n\t}\r\n\r\n\tprivate normalizeIssues(error: unknown): TSafeActionIssue[] {\r\n\t\tif (typeof error !== 'object' || error === null) return [];\r\n\r\n\t\tconst maybe = error as {\r\n\t\t\terrors?: Array<{ path?: unknown; message?: unknown }>;\r\n\t\t\tissues?: Array<{ path?: unknown; message?: unknown }>;\r\n\t\t};\r\n\r\n\t\tconst rawIssues = (maybe.errors ?? maybe.issues ?? []) as Array<{ path?: unknown; message?: unknown }>;\r\n\t\treturn rawIssues.map(issue => ({\r\n\t\t\tpath: this.normalizeIssuePath(issue.path),\r\n\t\t\tmessage: typeof issue.message === 'string' ? issue.message : String(issue.message ?? ''),\r\n\t\t\traw: issue,\r\n\t\t}));\r\n\t}\r\n\r\n\tprivate formatValidationErrorParts(error: unknown): { message: string; issues: TSafeActionIssue[] } {\r\n\t\tconst issues = this.normalizeIssues(error);\r\n\t\tconst first = issues[0];\r\n\t\tif (!first) {\r\n\t\t\treturn { message: `Validation error: ${String(error)}`, issues: [] };\r\n\t\t}\r\n\r\n\t\tconst fieldPath = first.path.length ? first.path.join('.') : 'unknown';\r\n\t\tconst message = first.message || String(error);\r\n\t\treturn { message: `Input (${fieldPath}) is error: ${message}`, issues };\r\n\t}\r\n\r\n\tprivate async validateInput(input: unknown): Promise<unknown> {\r\n\t\tif (!this.schemas.length) return input;\r\n\r\n\t\t// zod-form-data uses `z.preprocess` and accepts FormData/URLSearchParams at runtime.\r\n\t\t// If the incoming input is FormData, try to find a single schema that can parse it into a\r\n\t\t// regular object first (regardless of ordering). Then validate *all* remaining schemas\r\n\t\t// against the same base input so schemas can validate different slices reliably.\r\n\t\tconst schemasToRun = [...this.schemas];\r\n\t\tlet baseInput: unknown = input;\r\n\r\n\t\tif (input instanceof FormData) {\r\n\t\t\tfor (let i = 0; i < schemasToRun.length; i++) {\r\n\t\t\t\tconst candidate = schemasToRun[i];\r\n\t\t\t\tconst parsed = await this.tryParseSchema(candidate, input);\r\n\t\t\t\tif (!parsed.ok) continue;\r\n\r\n\t\t\t\tschemasToRun.splice(i, 1);\r\n\t\t\t\tbaseInput = parsed.value;\r\n\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If a FormData schema consumed the input and there are no schemas left,\r\n\t\t// the parsed base input is the validated result.\r\n\t\tif (schemasToRun.length === 0) {\r\n\t\t\treturn baseInput;\r\n\t\t}\r\n\r\n\t\t// Single schema: return parsed value directly.\r\n\t\tif (schemasToRun.length === 1) {\r\n\t\t\treturn await this.parseSchema(schemasToRun[0] as TSchema, baseInput);\r\n\t\t}\r\n\r\n\t\tlet mergedObject: Record<string, unknown> | undefined;\r\n\t\tlet lastNonObject: unknown = undefined;\r\n\r\n\t\tfor (const schema of schemasToRun) {\r\n\t\t\tconst parsed = await this.parseSchema(schema, baseInput);\r\n\t\t\tif (this.isPlainObject(parsed)) {\r\n\t\t\t\tmergedObject = { ...(mergedObject ?? {}), ...(parsed as Record<string, unknown>) };\r\n\t\t\t} else {\r\n\t\t\t\tlastNonObject = parsed;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn mergedObject ?? lastNonObject;\r\n\t}\r\n\r\n\tprivate isPlainObject(value: unknown): value is Record<string, unknown> {\r\n\t\treturn typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date);\r\n\t}\r\n\r\n\tprivate async parseSchema(schema: TSchema, input: unknown): Promise<unknown> {\r\n\t\tif (schema && typeof schema === 'object') {\r\n\t\t\tconst maybeAsync = (schema as { parseAsync?: unknown }).parseAsync;\r\n\t\t\tif (typeof maybeAsync === 'function') {\r\n\t\t\t\treturn await (schema as { parseAsync: (i: unknown) => Promise<unknown> }).parseAsync(input);\r\n\t\t\t}\r\n\t\t\tconst maybeSync = (schema as { parse?: unknown }).parse;\r\n\t\t\tif (typeof maybeSync === 'function') {\r\n\t\t\t\treturn (schema as { parse: (i: unknown) => unknown }).parse(input);\r\n\t\t\t}\r\n\r\n\t\t\t// Standard Schema v1 support.\r\n\t\t\t// Note: Zod v3+ exposes a `~standard` adapter too, but we prefer Zod's native parse/parseAsync\r\n\t\t\t// when available so validation failures produce a real `ZodError`.\r\n\t\t\tconst maybeStandard = (schema as { '~standard'?: unknown })['~standard'];\r\n\t\t\tif (maybeStandard && typeof maybeStandard === 'object') {\r\n\t\t\t\tconst validate = (maybeStandard as { validate?: unknown }).validate;\r\n\t\t\t\tif (typeof validate === 'function') {\r\n\t\t\t\t\tconst result = await (validate as (v: unknown) => unknown)(input);\r\n\t\t\t\t\tif (result && typeof result === 'object' && 'issues' in result) {\r\n\t\t\t\t\t\tconst err = new Error('Validation error');\r\n\t\t\t\t\t\t(err as unknown as { issues: unknown }).issues = (result as { issues: unknown }).issues;\r\n\t\t\t\t\t\tthrow err;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (result && typeof result === 'object' && 'value' in result) {\r\n\t\t\t\t\t\treturn (result as { value: unknown }).value;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthrow new Error('Unsupported schema type');\r\n\t}\r\n\r\n\tprivate async tryParseSchema(schema: TSchema, input: unknown): Promise<{ ok: true; value: unknown } | { ok: false }> {\r\n\t\ttry {\r\n\t\t\tif (schema && typeof schema === 'object') {\r\n\t\t\t\tconst safeAsync = (schema as { safeParseAsync?: unknown }).safeParseAsync;\r\n\t\t\t\tif (typeof safeAsync === 'function') {\r\n\t\t\t\t\tconst res = await (\r\n\t\t\t\t\t\tschema as {\r\n\t\t\t\t\t\t\tsafeParseAsync: (i: unknown) => Promise<{ success: boolean; data?: unknown }>;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t).safeParseAsync(input);\r\n\t\t\t\t\treturn res.success ? { ok: true, value: res.data } : { ok: false };\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst safeSync = (schema as { safeParse?: unknown }).safeParse;\r\n\t\t\t\tif (typeof safeSync === 'function') {\r\n\t\t\t\t\tconst res = (schema as { safeParse: (i: unknown) => { success: boolean; data?: unknown } }).safeParse(input);\r\n\t\t\t\t\treturn res.success ? { ok: true, value: res.data } : { ok: false };\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Standard Schema v1 support.\r\n\t\t\t\tconst maybeStandard = (schema as { '~standard'?: unknown })['~standard'];\r\n\t\t\t\tif (maybeStandard && typeof maybeStandard === 'object') {\r\n\t\t\t\t\tconst validate = (maybeStandard as { validate?: unknown }).validate;\r\n\t\t\t\t\tif (typeof validate === 'function') {\r\n\t\t\t\t\t\tconst result = await (validate as (v: unknown) => unknown)(input);\r\n\t\t\t\t\t\tif (result && typeof result === 'object' && 'issues' in result) return { ok: false };\r\n\t\t\t\t\t\tif (result && typeof result === 'object' && 'value' in result) return { ok: true, value: (result as { value: unknown }).value };\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Fallback to throwing parse.\r\n\t\t\treturn { ok: true, value: await this.parseSchema(schema, input) };\r\n\t\t} catch {\r\n\t\t\treturn { ok: false };\r\n\t\t}\r\n\t}\r\n\r\n\tprivate async runMiddlewareChain(input: unknown): Promise<Ctx> {\r\n\t\tlet ctx = { ...(this.ctx as Record<string, unknown>) } as Ctx;\r\n\t\tlet currentIndex = 0;\r\n\t\tconst middlewares = this.middlewares as unknown as readonly TMiddlewareFn<any, any>[];\r\n\r\n\t\tconst runNext = async <NC extends Record<string, unknown> = Record<string, never>>(options?: { ctx?: NC }): Promise<Ctx & NC> => {\r\n\t\t\tif (options?.ctx) {\r\n\t\t\t\tctx = { ...ctx, ...options.ctx } as Ctx;\r\n\t\t\t}\r\n\r\n\t\t\tif (currentIndex < middlewares.length) {\r\n\t\t\t\tconst middleware = middlewares[currentIndex] as TMiddlewareFn<any, any>;\r\n\t\t\t\tcurrentIndex++;\r\n\r\n\t\t\t\treturn (await middleware({\r\n\t\t\t\t\tinput,\r\n\t\t\t\t\tctx: Object.freeze({ ...ctx }),\r\n\t\t\t\t\tnext: runNext,\r\n\t\t\t\t})) as Ctx & NC;\r\n\t\t\t}\r\n\r\n\t\t\treturn ctx as Ctx & NC;\r\n\t\t};\r\n\r\n\t\treturn await runNext();\r\n\t}\r\n\r\n\tprivate isValidationError(error: unknown): boolean {\r\n\t\tif (typeof error !== 'object' || error === null) return false;\r\n\r\n\t\tif ('name' in error) {\r\n\t\t\tconst errName = (error as { name: string }).name;\r\n\t\t\tif (errName === 'ZodError' || errName.includes('ValidationError')) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn 'errors' in error || 'issues' in error;\r\n\t}\r\n}\r\n\r\n/**\r\n * Creates a safe action client that handles validation and execution of server actions\r\n */\r\nexport const createSafeActionClient = (options?: TSafeActionClientOptions) => {\r\n\treturn new SafeActionClient({ options });\r\n};\r\n"],"mappings":";AA2DO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EAGA,YACC,SACA,OAKI,EAAE,MAAM,eAAe,GAC1B;AACD,UAAM,SAAS,EAAE,OAAO,KAAK,MAAM,CAAC;AACpC,SAAK,OAAO;AACZ,SAAK,OAAO,KAAK;AACjB,SAAK,QAAQ,KAAK;AAClB,SAAK,OAAO,KAAK;AACjB,SAAK,QAAQ,KAAK;AAAA,EACnB;AACD;AAEO,IAAM,4BAAN,cAAwC,gBAAgB;AAAA,EAC9D;AAAA,EAEA,YACC,SACA,MAMC;AACD,UAAM,SAAS,EAAE,MAAM,oBAAoB,OAAO,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,KAAK,KAAK,CAAC;AAClG,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK;AAAA,EACpB;AACD;AAEO,IAAM,oBAAoB,CAAC,UAA6C;AAC9E,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,MAAI,EAAE,UAAU,OAAQ,QAAO;AAC/B,QAAM,OAAQ,MAA6B;AAC3C,SAAO,SAAS,qBAAqB,SAAS;AAC/C;AAEO,IAAM,8BAA8B,CAAC,UAAuD;AAClG,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,YAAY,SAAU,MAA6B,SAAS;AACnH;;;ACvGO,IAAM,kBAAkB,CAAC,OAAO,WAAW,gBAAgB,UAAU;;;ACGrE,IAAM,mBAAN,MAAM,kBAA2K;AAAA,EAC/K;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACC,UAKI,CAAC,GACJ;AACD,SAAK,UAAW,QAAQ,WAAW,CAAC;AACpC,SAAK,cAAe,QAAQ,eAAe,CAAC;AAC5C,SAAK,MAAO,QAAQ,OAAO,CAAC;AAC5B,SAAK,UAAU,QAAQ,WAAW,CAAC;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAA0B,QAAgE;AACzF,WAAO,IAAI,kBAAiB;AAAA,MAC3B,SAAS,CAAC,GAAG,KAAK,SAAS,MAAM;AAAA,MACjC,aAAa,KAAK;AAAA,MAClB,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA,IACf,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAA6C,YAAkI;AAC9K,WAAO,IAAI,kBAAiB;AAAA,MAC3B,SAAS,KAAK;AAAA,MACd,aAAa,CAAC,GAAG,KAAK,aAAa,UAAU;AAAA,MAC7C,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA,IACf,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe,SAAsX;AACpY,WAAO,OAAO,UAAqC;AAClD,UAAI,QAA+B;AACnC,UAAI,uBAAgC;AACpC,UAAI,eAAwB;AAE5B,UAAI;AAGH,gBAAQ;AACR,cAAM,cAAe,MAAM,KAAK,cAAc,KAAK;AACnD,+BAAuB;AAGvB,gBAAQ;AACR,cAAM,MAAM,MAAM,KAAK,mBAAmB,WAAW;AACrD,uBAAe;AAGf,gBAAQ;AACR,eAAO,MAAM,QAAQ,EAAE,aAAa,IAAI,CAAC;AAAA,MAC1C,SAAS,OAAgB;AACxB,cAAM,SAAS,KAAK,QAAQ,WAAW,SAAY,UAAU,KAAK,QAAQ;AAC1E,YAAI,WAAW,OAAO;AACrB,iBAAO,MAAM,iBAAiB,KAAK;AAAA,QACpC;AAEA,cAAM,eAAe,KAAK,QAAQ,+BAA+B;AACjE,cAAM,cAAc;AAAA,UACnB;AAAA,UACA;AAAA,UACA,OAAO,eAAe,QAAQ;AAAA,UAC9B,aAAa,eAAe,uBAAuB;AAAA,UACnD,KAAK,eAAgB,eAAuD;AAAA,QAC7E;AAGA,YAAI,KAAK,kBAAkB,KAAK,GAAG;AAClC,gBAAM,EAAE,SAAS,OAAO,IAAI,KAAK,2BAA2B,KAAK;AACjE,gBAAM,oBAAoB,EAAE,GAAG,aAAa,SAAS,OAAO;AAC5D,eAAK,QAAQ,UAAU,iBAAiB;AAExC,gBAAM,YACL,KAAK,QAAQ,wBAAwB,iBAAiB,KACtD,IAAI,0BAA0B,SAAS;AAAA,YACtC;AAAA,YACA;AAAA,YACA,OAAO;AAAA,YACP,MAAM,eAAe,EAAE,OAAO,aAAa,sBAAsB,KAAK,aAAa,IAAI;AAAA,UACxF,CAAC;AAEF,gBAAM;AAAA,QACP;AAEA,aAAK,QAAQ,UAAU,WAAW;AAClC,cAAM,iBAAiB,KAAK,QAAQ,cAAc,WAAW;AAC7D,YAAI,eAAgB,OAAM;AAE1B,cAAM;AAAA,MACP;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,mBAAmB,MAAuC;AACjE,QAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,QAAO,CAAC;AAClC,WAAO,KAAK,IAAI,SAAO;AACtB,UAAI,OAAO,QAAQ,YAAY,OAAO,QAAQ,SAAU,QAAO;AAC/D,UAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,SAAU,KAAiC;AACzF,cAAM,MAAO,IAAyB;AACtC,YAAI,OAAO,QAAQ,YAAY,OAAO,QAAQ,SAAU,QAAO;AAC/D,eAAO,OAAO,GAAG;AAAA,MAClB;AACA,aAAO,OAAO,GAAG;AAAA,IAClB,CAAC;AAAA,EACF;AAAA,EAEQ,gBAAgB,OAAoC;AAC3D,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO,CAAC;AAEzD,UAAM,QAAQ;AAKd,UAAM,YAAa,MAAM,UAAU,MAAM,UAAU,CAAC;AACpD,WAAO,UAAU,IAAI,YAAU;AAAA,MAC9B,MAAM,KAAK,mBAAmB,MAAM,IAAI;AAAA,MACxC,SAAS,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU,OAAO,MAAM,WAAW,EAAE;AAAA,MACvF,KAAK;AAAA,IACN,EAAE;AAAA,EACH;AAAA,EAEQ,2BAA2B,OAAiE;AACnG,UAAM,SAAS,KAAK,gBAAgB,KAAK;AACzC,UAAM,QAAQ,OAAO,CAAC;AACtB,QAAI,CAAC,OAAO;AACX,aAAO,EAAE,SAAS,qBAAqB,OAAO,KAAK,CAAC,IAAI,QAAQ,CAAC,EAAE;AAAA,IACpE;AAEA,UAAM,YAAY,MAAM,KAAK,SAAS,MAAM,KAAK,KAAK,GAAG,IAAI;AAC7D,UAAM,UAAU,MAAM,WAAW,OAAO,KAAK;AAC7C,WAAO,EAAE,SAAS,UAAU,SAAS,eAAe,OAAO,IAAI,OAAO;AAAA,EACvE;AAAA,EAEA,MAAc,cAAc,OAAkC;AAC7D,QAAI,CAAC,KAAK,QAAQ,OAAQ,QAAO;AAMjC,UAAM,eAAe,CAAC,GAAG,KAAK,OAAO;AACrC,QAAI,YAAqB;AAEzB,QAAI,iBAAiB,UAAU;AAC9B,eAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC7C,cAAM,YAAY,aAAa,CAAC;AAChC,cAAM,SAAS,MAAM,KAAK,eAAe,WAAW,KAAK;AACzD,YAAI,CAAC,OAAO,GAAI;AAEhB,qBAAa,OAAO,GAAG,CAAC;AACxB,oBAAY,OAAO;AAEnB;AAAA,MACD;AAAA,IACD;AAIA,QAAI,aAAa,WAAW,GAAG;AAC9B,aAAO;AAAA,IACR;AAGA,QAAI,aAAa,WAAW,GAAG;AAC9B,aAAO,MAAM,KAAK,YAAY,aAAa,CAAC,GAAc,SAAS;AAAA,IACpE;AAEA,QAAI;AACJ,QAAI,gBAAyB;AAE7B,eAAW,UAAU,cAAc;AAClC,YAAM,SAAS,MAAM,KAAK,YAAY,QAAQ,SAAS;AACvD,UAAI,KAAK,cAAc,MAAM,GAAG;AAC/B,uBAAe,EAAE,GAAI,gBAAgB,CAAC,GAAI,GAAI,OAAmC;AAAA,MAClF,OAAO;AACN,wBAAgB;AAAA,MACjB;AAAA,IACD;AAEA,WAAO,gBAAgB;AAAA,EACxB;AAAA,EAEQ,cAAc,OAAkD;AACvE,WAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,KAAK,EAAE,iBAAiB;AAAA,EACnG;AAAA,EAEA,MAAc,YAAY,QAAiB,OAAkC;AAC5E,QAAI,UAAU,OAAO,WAAW,UAAU;AACzC,YAAM,aAAc,OAAoC;AACxD,UAAI,OAAO,eAAe,YAAY;AACrC,eAAO,MAAO,OAA4D,WAAW,KAAK;AAAA,MAC3F;AACA,YAAM,YAAa,OAA+B;AAClD,UAAI,OAAO,cAAc,YAAY;AACpC,eAAQ,OAA8C,MAAM,KAAK;AAAA,MAClE;AAKA,YAAM,gBAAiB,OAAqC,WAAW;AACvE,UAAI,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,cAAM,WAAY,cAAyC;AAC3D,YAAI,OAAO,aAAa,YAAY;AACnC,gBAAM,SAAS,MAAO,SAAqC,KAAK;AAChE,cAAI,UAAU,OAAO,WAAW,YAAY,YAAY,QAAQ;AAC/D,kBAAM,MAAM,IAAI,MAAM,kBAAkB;AACxC,YAAC,IAAuC,SAAU,OAA+B;AACjF,kBAAM;AAAA,UACP;AACA,cAAI,UAAU,OAAO,WAAW,YAAY,WAAW,QAAQ;AAC9D,mBAAQ,OAA8B;AAAA,UACvC;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC1C;AAAA,EAEA,MAAc,eAAe,QAAiB,OAAuE;AACpH,QAAI;AACH,UAAI,UAAU,OAAO,WAAW,UAAU;AACzC,cAAM,YAAa,OAAwC;AAC3D,YAAI,OAAO,cAAc,YAAY;AACpC,gBAAM,MAAM,MACX,OAGC,eAAe,KAAK;AACtB,iBAAO,IAAI,UAAU,EAAE,IAAI,MAAM,OAAO,IAAI,KAAK,IAAI,EAAE,IAAI,MAAM;AAAA,QAClE;AAEA,cAAM,WAAY,OAAmC;AACrD,YAAI,OAAO,aAAa,YAAY;AACnC,gBAAM,MAAO,OAA+E,UAAU,KAAK;AAC3G,iBAAO,IAAI,UAAU,EAAE,IAAI,MAAM,OAAO,IAAI,KAAK,IAAI,EAAE,IAAI,MAAM;AAAA,QAClE;AAGA,cAAM,gBAAiB,OAAqC,WAAW;AACvE,YAAI,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,gBAAM,WAAY,cAAyC;AAC3D,cAAI,OAAO,aAAa,YAAY;AACnC,kBAAM,SAAS,MAAO,SAAqC,KAAK;AAChE,gBAAI,UAAU,OAAO,WAAW,YAAY,YAAY,OAAQ,QAAO,EAAE,IAAI,MAAM;AACnF,gBAAI,UAAU,OAAO,WAAW,YAAY,WAAW,OAAQ,QAAO,EAAE,IAAI,MAAM,OAAQ,OAA8B,MAAM;AAAA,UAC/H;AAAA,QACD;AAAA,MACD;AAGA,aAAO,EAAE,IAAI,MAAM,OAAO,MAAM,KAAK,YAAY,QAAQ,KAAK,EAAE;AAAA,IACjE,QAAQ;AACP,aAAO,EAAE,IAAI,MAAM;AAAA,IACpB;AAAA,EACD;AAAA,EAEA,MAAc,mBAAmB,OAA8B;AAC9D,QAAI,MAAM,EAAE,GAAI,KAAK,IAAgC;AACrD,QAAI,eAAe;AACnB,UAAM,cAAc,KAAK;AAEzB,UAAM,UAAU,OAAmE,YAA8C;AAChI,UAAI,SAAS,KAAK;AACjB,cAAM,EAAE,GAAG,KAAK,GAAG,QAAQ,IAAI;AAAA,MAChC;AAEA,UAAI,eAAe,YAAY,QAAQ;AACtC,cAAM,aAAa,YAAY,YAAY;AAC3C;AAEA,eAAQ,MAAM,WAAW;AAAA,UACxB;AAAA,UACA,KAAK,OAAO,OAAO,EAAE,GAAG,IAAI,CAAC;AAAA,UAC7B,MAAM;AAAA,QACP,CAAC;AAAA,MACF;AAEA,aAAO;AAAA,IACR;AAEA,WAAO,MAAM,QAAQ;AAAA,EACtB;AAAA,EAEQ,kBAAkB,OAAyB;AAClD,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AAExD,QAAI,UAAU,OAAO;AACpB,YAAM,UAAW,MAA2B;AAC5C,UAAI,YAAY,cAAc,QAAQ,SAAS,iBAAiB,GAAG;AAClE,eAAO;AAAA,MACR;AAAA,IACD;AAEA,WAAO,YAAY,SAAS,YAAY;AAAA,EACzC;AACD;AAKO,IAAM,yBAAyB,CAAC,YAAuC;AAC7E,SAAO,IAAI,iBAAiB,EAAE,QAAQ,CAAC;AACxC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types/errors.ts","../src/types/schema/index.ts","../src/index.ts"],"sourcesContent":["export type TActionPlusIssuePathSegment = string | number;\r\n\r\nexport type TActionPlusIssue = {\r\n\tpath: TActionPlusIssuePathSegment[];\r\n\tmessage: string;\r\n\traw?: unknown;\r\n};\r\n\r\nexport type TActionPlusErrorCode = 'VALIDATION_ERROR' | 'MIDDLEWARE_ERROR' | 'HANDLER_ERROR' | 'ACTION_ERROR';\r\n\r\nexport type TActionPlusErrorPhase = 'validation' | 'middleware' | 'handler';\r\n\r\nexport type TActionPlusUnknownErrorContext = {\r\n\tphase: TActionPlusErrorPhase;\r\n\terror: unknown;\r\n\tinput?: unknown;\r\n\tparsedInput?: unknown;\r\n\tctx?: Record<string, unknown>;\r\n};\r\n\r\nexport type TActionPlusValidationErrorContext = TActionPlusUnknownErrorContext & {\r\n\tmessage: string;\r\n\tissues: TActionPlusIssue[];\r\n};\r\n\r\nexport type TActionPlusErrorContext = TActionPlusUnknownErrorContext | TActionPlusValidationErrorContext;\r\n\r\nexport type TActionPlusOptions = {\r\n\t/**\r\n\t * Control logging when an action throws.\r\n\t * - `false` disables logging.\r\n\t * - Defaults to `console`.\r\n\t */\r\n\tlogger?: false | { error: (...args: unknown[]) => void };\r\n\r\n\t/**\r\n\t * Hook called whenever an action throws (validation, middleware, or handler).\r\n\t */\r\n\tonError?: (ctx: TActionPlusErrorContext) => void;\r\n\r\n\t/**\r\n\t * Customize the thrown error when validation fails.\r\n\t * The returned Error will be thrown.\r\n\t */\r\n\tformatValidationError?: (ctx: TActionPlusValidationErrorContext) => Error;\r\n\r\n\t/**\r\n\t * Customize the thrown error for non-validation failures.\r\n\t * If omitted, the original error is re-thrown.\r\n\t */\r\n\tformatError?: (ctx: TActionPlusUnknownErrorContext) => Error;\r\n\r\n\t/**\r\n\t * When enabled, include `input`, `parsedInput`, and `ctx` in error details.\r\n\t * Off by default because it can accidentally expose sensitive data.\r\n\t */\r\n\tincludeInputInErrorDetails?: boolean;\r\n};\r\n\r\nexport class ActionPlusError extends Error {\r\n\tcode: TActionPlusErrorCode;\r\n\tphase?: TActionPlusErrorPhase;\r\n\tdata?: unknown;\r\n\tdeclare cause?: unknown;\r\n\r\n\tconstructor(\r\n\t\tmessage: string,\r\n\t\topts: {\r\n\t\t\tcode: TActionPlusErrorCode;\r\n\t\t\tphase?: TActionPlusErrorPhase;\r\n\t\t\tcause?: unknown;\r\n\t\t\tdata?: unknown;\r\n\t\t} = { code: 'ACTION_ERROR' },\r\n\t) {\r\n\t\tsuper(message, { cause: opts.cause });\r\n\t\tthis.name = 'ActionPlusError';\r\n\t\tthis.code = opts.code;\r\n\t\tthis.phase = opts.phase;\r\n\t\tthis.data = opts.data;\r\n\t\tthis.cause = opts.cause;\r\n\t}\r\n}\r\n\r\nexport class ActionPlusValidationError extends ActionPlusError {\r\n\tissues: TActionPlusIssue[];\r\n\r\n\tconstructor(\r\n\t\tmessage: string,\r\n\t\topts: {\r\n\t\t\tissues: TActionPlusIssue[];\r\n\t\t\tphase?: TActionPlusErrorPhase;\r\n\t\t\tcause?: unknown;\r\n\t\t\tdata?: unknown;\r\n\t\t},\r\n\t) {\r\n\t\tsuper(message, { code: 'VALIDATION_ERROR', phase: opts.phase, cause: opts.cause, data: opts.data });\r\n\t\tthis.name = 'ActionPlusValidationError';\r\n\t\tthis.issues = opts.issues;\r\n\t}\r\n}\r\n\r\nexport const isActionPlusError = (error: unknown): error is ActionPlusError => {\r\n\tif (typeof error !== 'object' || error === null) return false;\r\n\tif (!('code' in error)) return false;\r\n\tconst name = (error as { name?: unknown }).name;\r\n\treturn name === 'ActionPlusError' || name === 'ActionPlusValidationError';\r\n};\r\n\r\nexport const isActionPlusValidationError = (error: unknown): error is ActionPlusValidationError => {\r\n\treturn typeof error === 'object' && error !== null && 'issues' in error && (error as { name?: unknown }).name === 'ActionPlusValidationError';\r\n};\r\n","import type { z } from 'zod';\r\n\r\nimport type { TIfInstalled, TPrettify, TUnionToIntersection } from '../utils';\r\nimport type { TGenericSchema, TGenericSchemaAsync } from './generic';\r\nimport type { TStandardSchemaV1, TStandardSchemaV1InferInput, TStandardSchemaV1InferOutput } from './standard';\r\nimport type { TZodAcceptsFormData, TZodFormDataInput } from './zod';\r\n\r\nexport const schemaAvailable = ['zod', 'generic', 'genericAsync', 'standard'] as const;\r\nexport type TSchemaAvailable = (typeof schemaAvailable)[number];\r\n\r\nexport type TSchema = TIfInstalled<z.ZodTypeAny> | TIfInstalled<TGenericSchema> | TIfInstalled<TGenericSchemaAsync> | TStandardSchemaV1<any, any>;\r\n\r\nexport type TInfer<S extends TSchema> = S extends TIfInstalled<z.ZodTypeAny> ? z.infer<S> : S extends TIfInstalled<TGenericSchema> ? ReturnType<S['parse']> : S extends TIfInstalled<TGenericSchemaAsync> ? Awaited<ReturnType<S['parseAsync']>> : S extends TStandardSchemaV1<any, any> ? TStandardSchemaV1InferOutput<S> : never;\r\n\r\nexport type TInferIn<S extends TSchema> = S extends TIfInstalled<z.ZodTypeAny> ? z.input<S> : S extends TIfInstalled<TGenericSchema> ? Parameters<S['parse']>[0] : S extends TIfInstalled<TGenericSchemaAsync> ? Parameters<S['parseAsync']>[0] : S extends TStandardSchemaV1<any, any> ? TStandardSchemaV1InferInput<S> : never;\r\n\r\nexport type TInferArray<S extends readonly TSchema[]> = S extends readonly [infer First extends TSchema, ...infer Rest extends TSchema[]] ? [TInfer<First>, ...TInferArray<Rest>] : [];\r\n\r\nexport type TInferInArray<S extends readonly TSchema[]> = S extends readonly [infer First extends TSchema, ...infer Rest extends TSchema[]] ? [TInferIn<First>, ...TInferInArray<Rest>] : [];\r\n\r\nexport type TIsFormData<S extends TSchema> = S extends z.ZodTypeAny ? TZodAcceptsFormData<S> : S extends TStandardSchemaV1<infer Input, any> ? (FormData extends Input ? true : false) : false;\r\n\r\nexport type TFormDataInput<S extends TSchema> = S extends z.ZodTypeAny ? TZodFormDataInput<S> : S extends TStandardSchemaV1<infer Input, any> ? (FormData extends Input ? FormData | TInferIn<S> : TInferIn<S>) : TInferIn<S>;\r\n\r\nexport type TFormDataCompatibleInput<S extends readonly TSchema[]> = S extends readonly [infer First extends TSchema, ...infer Rest extends TSchema[]] ? (TIsFormData<First> extends true ? FormData : never) | TPrettify<TUnionToIntersection<TInferIn<First>>> | (Rest['length'] extends 0 ? never : TFormDataCompatibleInput<Rest>) : Record<string, never>;\r\n","import type { TActionPlusOptions, TActionPlusErrorPhase, TActionPlusIssue, TFormDataCompatibleInput, TFormDataInput, TInfer, TPrettify, TSchema, TMiddlewareFn, TUnionToIntersection } from './types';\r\nimport { ActionPlusValidationError } from './types';\r\n\r\nexport { schemaAvailable } from './types';\r\nexport { ActionPlusError, ActionPlusValidationError, isActionPlusError, isActionPlusValidationError } from './types';\r\nexport type * from './types';\r\n\r\n/**\r\n * Class that handles server actions with validation\r\n */\r\nexport class ActionPlus<Schemas extends TSchema[] = [], Ctx extends Record<string, unknown> = Record<string, never>, Middlewares extends readonly TMiddlewareFn<any, any>[] = []> {\r\n\tprivate schemas: Schemas;\r\n\tprivate middlewares: Middlewares;\r\n\tprivate ctx: Ctx;\r\n\tprivate options: TActionPlusOptions;\r\n\r\n\tconstructor(\r\n\t\toptions: {\r\n\t\t\tschemas?: Schemas;\r\n\t\t\tmiddlewares?: Middlewares;\r\n\t\t\tctx?: Ctx;\r\n\t\t\toptions?: TActionPlusOptions;\r\n\t\t} = {},\r\n\t) {\r\n\t\tthis.schemas = (options.schemas || []) as unknown as Schemas;\r\n\t\tthis.middlewares = (options.middlewares || []) as unknown as Middlewares;\r\n\t\tthis.ctx = (options.ctx || {}) as Ctx;\r\n\t\tthis.options = options.options ?? {};\r\n\t}\r\n\r\n\t/**\r\n\t * Adds a validation schema\r\n\t * @param schema Validation schema\r\n\t */\r\n\tschema<S extends TSchema>(schema: S): ActionPlus<[...Schemas, S], Ctx, Middlewares> {\r\n\t\treturn new ActionPlus({\r\n\t\t\tschemas: [...this.schemas, schema] as unknown as [...Schemas, S],\r\n\t\t\tmiddlewares: this.middlewares,\r\n\t\t\tctx: this.ctx,\r\n\t\t\toptions: this.options,\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Adds a middleware function\r\n\t * @param middleware Middleware function\r\n\t */\r\n\tuse<NextCtx extends Record<string, unknown>>(middleware: TMiddlewareFn<Ctx, NextCtx>): ActionPlus<Schemas, Ctx & NextCtx, [...Middlewares, TMiddlewareFn<Ctx, NextCtx>]> {\r\n\t\treturn new ActionPlus({\r\n\t\t\tschemas: this.schemas,\r\n\t\t\tmiddlewares: [...this.middlewares, middleware] as unknown as [...Middlewares, TMiddlewareFn<Ctx, NextCtx>],\r\n\t\t\tctx: this.ctx as unknown as Ctx & NextCtx,\r\n\t\t\toptions: this.options,\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Creates an action with validation and middleware\r\n\t * @param handler Action handler function\r\n\t */\r\n\taction<Output>(handler: (props: { parsedInput: Schemas extends (infer S extends TSchema)[] ? TPrettify<TUnionToIntersection<TInfer<S>>> : Record<string, never>; ctx: TPrettify<Ctx> }) => Promise<Output>): (input?: Schemas extends [infer S extends TSchema] ? TFormDataInput<S> : Schemas extends (infer _S extends TSchema)[] ? TFormDataCompatibleInput<Schemas> : unknown) => Promise<Output> {\r\n\t\treturn async (input?: unknown): Promise<Output> => {\r\n\t\t\tlet phase: TActionPlusErrorPhase = 'validation';\r\n\t\t\tlet parsedInputForErrors: unknown = undefined;\r\n\t\t\tlet ctxForErrors: unknown = undefined;\r\n\r\n\t\t\ttry {\r\n\t\t\t\t// Validate input against all schemas\r\n\t\t\t\ttype ParsedInput = Schemas extends (infer S extends TSchema)[] ? TPrettify<TUnionToIntersection<TInfer<S>>> : Record<string, never>;\r\n\t\t\t\tphase = 'validation';\r\n\t\t\t\tconst parsedInput = (await this.validateInput(input)) as ParsedInput;\r\n\t\t\t\tparsedInputForErrors = parsedInput;\r\n\r\n\t\t\t\t// Run middleware chain\r\n\t\t\t\tphase = 'middleware';\r\n\t\t\t\tconst ctx = await this.runMiddlewareChain(parsedInput);\r\n\t\t\t\tctxForErrors = ctx;\r\n\r\n\t\t\t\t// Execute handler\r\n\t\t\t\tphase = 'handler';\r\n\t\t\t\treturn await handler({ parsedInput, ctx });\r\n\t\t\t} catch (error: unknown) {\r\n\t\t\t\tconst logger = this.options.logger === undefined ? console : this.options.logger;\r\n\t\t\t\tif (logger !== false) {\r\n\t\t\t\t\tlogger.error('Action error:', error);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst includeInput = this.options.includeInputInErrorDetails === true;\r\n\t\t\t\tconst baseContext = {\r\n\t\t\t\t\tphase,\r\n\t\t\t\t\terror,\r\n\t\t\t\t\tinput: includeInput ? input : undefined,\r\n\t\t\t\t\tparsedInput: includeInput ? parsedInputForErrors : undefined,\r\n\t\t\t\t\tctx: includeInput ? (ctxForErrors as Record<string, unknown> | undefined) : undefined,\r\n\t\t\t\t};\r\n\r\n\t\t\t\t// Handle validation errors\r\n\t\t\t\tif (this.isValidationError(error)) {\r\n\t\t\t\t\tconst { message, issues } = this.formatValidationErrorParts(error);\r\n\t\t\t\t\tconst validationContext = { ...baseContext, message, issues };\r\n\t\t\t\t\tthis.options.onError?.(validationContext);\r\n\r\n\t\t\t\t\tconst formatted =\r\n\t\t\t\t\t\tthis.options.formatValidationError?.(validationContext) ??\r\n\t\t\t\t\t\tnew ActionPlusValidationError(message, {\r\n\t\t\t\t\t\t\tissues,\r\n\t\t\t\t\t\t\tphase,\r\n\t\t\t\t\t\t\tcause: error,\r\n\t\t\t\t\t\t\tdata: includeInput ? { input, parsedInput: parsedInputForErrors, ctx: ctxForErrors } : undefined,\r\n\t\t\t\t\t\t});\r\n\r\n\t\t\t\t\tthrow formatted;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.options.onError?.(baseContext);\r\n\t\t\t\tconst maybeFormatted = this.options.formatError?.(baseContext);\r\n\t\t\t\tif (maybeFormatted) throw maybeFormatted;\r\n\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\tprivate normalizeIssuePath(path: unknown): Array<string | number> {\r\n\t\tif (!Array.isArray(path)) return [];\r\n\t\treturn path.map(seg => {\r\n\t\t\tif (typeof seg === 'string' || typeof seg === 'number') return seg;\r\n\t\t\tif (typeof seg === 'object' && seg !== null && 'key' in (seg as Record<string, unknown>)) {\r\n\t\t\t\tconst key = (seg as { key: unknown }).key;\r\n\t\t\t\tif (typeof key === 'string' || typeof key === 'number') return key;\r\n\t\t\t\treturn String(key);\r\n\t\t\t}\r\n\t\t\treturn String(seg);\r\n\t\t});\r\n\t}\r\n\r\n\tprivate normalizeIssues(error: unknown): TActionPlusIssue[] {\r\n\t\tif (typeof error !== 'object' || error === null) return [];\r\n\r\n\t\tconst maybe = error as {\r\n\t\t\terrors?: unknown;\r\n\t\t\tissues?: unknown;\r\n\t\t};\r\n\r\n\t\tconst errorsCandidate = maybe.errors;\r\n\t\tconst issuesCandidate = maybe.issues;\r\n\t\tconst rawIssues = (Array.isArray(errorsCandidate) ? errorsCandidate : Array.isArray(issuesCandidate) ? issuesCandidate : []) as unknown[];\r\n\t\treturn rawIssues\r\n\t\t\t.filter((issue): issue is Record<string, unknown> => typeof issue === 'object' && issue !== null)\r\n\t\t\t.map(issue => ({\r\n\t\t\t\tpath: this.normalizeIssuePath(issue.path),\r\n\t\t\t\tmessage: typeof issue.message === 'string' ? issue.message : String(issue.message ?? ''),\r\n\t\t\t\traw: issue,\r\n\t\t\t}));\r\n\t}\r\n\r\n\tprivate formatValidationErrorParts(error: unknown): { message: string; issues: TActionPlusIssue[] } {\r\n\t\tconst issues = this.normalizeIssues(error);\r\n\t\tconst first = issues[0];\r\n\t\tif (!first) {\r\n\t\t\treturn { message: `Validation error: ${String(error)}`, issues: [] };\r\n\t\t}\r\n\r\n\t\tconst fieldPath = first.path.length ? first.path.join('.') : 'unknown';\r\n\t\tconst message = first.message || String(error);\r\n\t\treturn { message: `Input (${fieldPath}) is error: ${message}`, issues };\r\n\t}\r\n\r\n\tprivate async validateInput(input: unknown): Promise<unknown> {\r\n\t\tif (!this.schemas.length) return input;\r\n\r\n\t\t// zod-form-data uses `z.preprocess` and accepts FormData/URLSearchParams at runtime.\r\n\t\t// If the incoming input is FormData, try to find a single schema that can parse it into a\r\n\t\t// regular object first (regardless of ordering). Then validate *all* remaining schemas\r\n\t\t// against the same base input so schemas can validate different slices reliably.\r\n\t\tconst schemasToRun = [...this.schemas];\r\n\t\tlet baseInput: unknown = input;\r\n\r\n\t\tif (input instanceof FormData) {\r\n\t\t\tfor (let i = 0; i < schemasToRun.length; i++) {\r\n\t\t\t\tconst candidate = schemasToRun[i];\r\n\t\t\t\tconst parsed = await this.tryParseSchema(candidate, input);\r\n\t\t\t\tif (!parsed.ok) continue;\r\n\r\n\t\t\t\tschemasToRun.splice(i, 1);\r\n\t\t\t\tbaseInput = parsed.value;\r\n\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If a FormData schema consumed the input and there are no schemas left,\r\n\t\t// the parsed base input is the validated result.\r\n\t\tif (schemasToRun.length === 0) {\r\n\t\t\treturn baseInput;\r\n\t\t}\r\n\r\n\t\t// Single schema: return parsed value directly.\r\n\t\tif (schemasToRun.length === 1) {\r\n\t\t\treturn await this.parseSchema(schemasToRun[0] as TSchema, baseInput);\r\n\t\t}\r\n\r\n\t\tlet mergedObject: Record<string, unknown> | undefined;\r\n\t\tlet lastNonObject: unknown = undefined;\r\n\r\n\t\tfor (const schema of schemasToRun) {\r\n\t\t\tconst parsed = await this.parseSchema(schema, baseInput);\r\n\t\t\tif (this.isPlainObject(parsed)) {\r\n\t\t\t\tmergedObject = { ...(mergedObject ?? {}), ...(parsed as Record<string, unknown>) };\r\n\t\t\t} else {\r\n\t\t\t\tlastNonObject = parsed;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn mergedObject ?? lastNonObject;\r\n\t}\r\n\r\n\tprivate isPlainObject(value: unknown): value is Record<string, unknown> {\r\n\t\treturn typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date);\r\n\t}\r\n\r\n\tprivate async parseSchema(schema: TSchema, input: unknown): Promise<unknown> {\r\n\t\tif (schema && typeof schema === 'object') {\r\n\t\t\tconst maybeAsync = (schema as { parseAsync?: unknown }).parseAsync;\r\n\t\t\tif (typeof maybeAsync === 'function') {\r\n\t\t\t\treturn await (schema as { parseAsync: (i: unknown) => Promise<unknown> }).parseAsync(input);\r\n\t\t\t}\r\n\t\t\tconst maybeSync = (schema as { parse?: unknown }).parse;\r\n\t\t\tif (typeof maybeSync === 'function') {\r\n\t\t\t\treturn (schema as { parse: (i: unknown) => unknown }).parse(input);\r\n\t\t\t}\r\n\r\n\t\t\t// Standard Schema v1 support.\r\n\t\t\t// Note: Zod v3+ exposes a `~standard` adapter too, but we prefer Zod's native parse/parseAsync\r\n\t\t\t// when available so validation failures produce a real `ZodError`.\r\n\t\t\tconst maybeStandard = (schema as { '~standard'?: unknown })['~standard'];\r\n\t\t\tif (maybeStandard && typeof maybeStandard === 'object') {\r\n\t\t\t\tconst validate = (maybeStandard as { validate?: unknown }).validate;\r\n\t\t\t\tif (typeof validate === 'function') {\r\n\t\t\t\t\tconst result = await (validate as (v: unknown) => unknown)(input);\r\n\t\t\t\t\tif (result && typeof result === 'object' && 'issues' in result) {\r\n\t\t\t\t\t\tconst err = new Error('Validation error');\r\n\t\t\t\t\t\t(err as unknown as { issues: unknown }).issues = (result as { issues: unknown }).issues;\r\n\t\t\t\t\t\tthrow err;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (result && typeof result === 'object' && 'value' in result) {\r\n\t\t\t\t\t\treturn (result as { value: unknown }).value;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthrow new Error('Unsupported schema type');\r\n\t}\r\n\r\n\tprivate async tryParseSchema(schema: TSchema, input: unknown): Promise<{ ok: true; value: unknown } | { ok: false }> {\r\n\t\ttry {\r\n\t\t\tif (schema && typeof schema === 'object') {\r\n\t\t\t\tconst safeAsync = (schema as { safeParseAsync?: unknown }).safeParseAsync;\r\n\t\t\t\tif (typeof safeAsync === 'function') {\r\n\t\t\t\t\tconst res = await (\r\n\t\t\t\t\t\tschema as {\r\n\t\t\t\t\t\t\tsafeParseAsync: (i: unknown) => Promise<{ success: boolean; data?: unknown }>;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t).safeParseAsync(input);\r\n\t\t\t\t\treturn res.success ? { ok: true, value: res.data } : { ok: false };\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst safeSync = (schema as { safeParse?: unknown }).safeParse;\r\n\t\t\t\tif (typeof safeSync === 'function') {\r\n\t\t\t\t\tconst res = (schema as { safeParse: (i: unknown) => { success: boolean; data?: unknown } }).safeParse(input);\r\n\t\t\t\t\treturn res.success ? { ok: true, value: res.data } : { ok: false };\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Standard Schema v1 support.\r\n\t\t\t\tconst maybeStandard = (schema as { '~standard'?: unknown })['~standard'];\r\n\t\t\t\tif (maybeStandard && typeof maybeStandard === 'object') {\r\n\t\t\t\t\tconst validate = (maybeStandard as { validate?: unknown }).validate;\r\n\t\t\t\t\tif (typeof validate === 'function') {\r\n\t\t\t\t\t\tconst result = await (validate as (v: unknown) => unknown)(input);\r\n\t\t\t\t\t\tif (result && typeof result === 'object' && 'issues' in result) return { ok: false };\r\n\t\t\t\t\t\tif (result && typeof result === 'object' && 'value' in result) return { ok: true, value: (result as { value: unknown }).value };\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Fallback to throwing parse.\r\n\t\t\treturn { ok: true, value: await this.parseSchema(schema, input) };\r\n\t\t} catch {\r\n\t\t\treturn { ok: false };\r\n\t\t}\r\n\t}\r\n\r\n\tprivate async runMiddlewareChain(input: unknown): Promise<Ctx> {\r\n\t\tlet ctx = { ...(this.ctx as Record<string, unknown>) } as Ctx;\r\n\t\tlet currentIndex = 0;\r\n\t\tconst middlewares = this.middlewares as unknown as readonly TMiddlewareFn<any, any>[];\r\n\r\n\t\tconst runNext = async <NC extends Record<string, unknown> = Record<string, never>>(options?: { ctx?: NC }): Promise<Ctx & NC> => {\r\n\t\t\tif (options?.ctx) {\r\n\t\t\t\tctx = { ...ctx, ...options.ctx } as Ctx;\r\n\t\t\t}\r\n\r\n\t\t\tif (currentIndex < middlewares.length) {\r\n\t\t\t\tconst middleware = middlewares[currentIndex] as TMiddlewareFn<any, any>;\r\n\t\t\t\tcurrentIndex++;\r\n\r\n\t\t\t\treturn (await middleware({\r\n\t\t\t\t\tinput,\r\n\t\t\t\t\tctx: Object.freeze({ ...ctx }),\r\n\t\t\t\t\tnext: runNext,\r\n\t\t\t\t})) as Ctx & NC;\r\n\t\t\t}\r\n\r\n\t\t\treturn ctx as Ctx & NC;\r\n\t\t};\r\n\r\n\t\treturn await runNext();\r\n\t}\r\n\r\n\tprivate isValidationError(error: unknown): boolean {\r\n\t\tif (typeof error !== 'object' || error === null) return false;\r\n\r\n\t\tif ('name' in error) {\r\n\t\t\tconst errName = (error as { name: string }).name;\r\n\t\t\tif (errName === 'ZodError' || errName.includes('ValidationError')) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn 'errors' in error || 'issues' in error;\r\n\t}\r\n}\r\n\r\n/**\r\n * Creates an ActionPlus client that handles validation and execution of server actions\r\n */\r\nexport const createActionPlus = (options?: TActionPlusOptions) => {\r\n\treturn new ActionPlus({ options });\r\n};\r\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-action-plus",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Plug-and-play, type-safe server actions with schema validation (schema-agnostic, Zod compatible).",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/muhgholy/next-action-plus.git"
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
"dist"
|
|
41
41
|
],
|
|
42
42
|
"publishConfig": {
|
|
43
|
-
"access": "public"
|
|
43
|
+
"access": "public",
|
|
44
|
+
"provenance": true
|
|
44
45
|
},
|
|
45
46
|
"scripts": {
|
|
46
47
|
"clean": "rm -rf dist",
|
|
@@ -56,9 +57,9 @@
|
|
|
56
57
|
"devDependencies": {
|
|
57
58
|
"@semantic-release/changelog": "^6.0.3",
|
|
58
59
|
"@semantic-release/commit-analyzer": "^12.0.0",
|
|
60
|
+
"@semantic-release/exec": "^6.0.3",
|
|
59
61
|
"@semantic-release/git": "^10.0.1",
|
|
60
62
|
"@semantic-release/github": "^11.0.0",
|
|
61
|
-
"@semantic-release/npm": "^12.0.0",
|
|
62
63
|
"@semantic-release/release-notes-generator": "^13.0.0",
|
|
63
64
|
"@types/node": "^22.10.2",
|
|
64
65
|
"semantic-release": "^24.0.0",
|
|
@@ -68,4 +69,4 @@
|
|
|
68
69
|
"zod-form-data": "^3.0.1",
|
|
69
70
|
"zod": "^3.22.0"
|
|
70
71
|
}
|
|
71
|
-
}
|
|
72
|
+
}
|