server-act 1.4.0 → 1.5.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 +3 -1
- package/dist/index.d.mts +12 -7
- package/dist/index.d.ts +12 -7
- package/dist/index.js +75 -9
- package/dist/index.mjs +75 -9
- package/package.json +19 -7
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/server-act)
|
|
4
4
|
|
|
5
|
-
A simple React server action builder that provides input validation
|
|
5
|
+
A simple React server action builder that provides input validation.
|
|
6
|
+
|
|
7
|
+
You can use any validation library that supports [Standard Schema](https://standardschema.dev/).
|
|
6
8
|
|
|
7
9
|
## Installation
|
|
8
10
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
|
|
3
|
+
declare function getFormErrors(issues: ReadonlyArray<StandardSchemaV1.Issue>): {
|
|
4
|
+
messages: string[];
|
|
5
|
+
fieldErrors: Record<string, string[]>;
|
|
6
|
+
};
|
|
2
7
|
|
|
3
8
|
declare const unsetMarker: unique symbol;
|
|
4
9
|
type UnsetMarker = typeof unsetMarker;
|
|
@@ -7,8 +12,8 @@ type Prettify<T> = {
|
|
|
7
12
|
[P in keyof T]: T[P];
|
|
8
13
|
} & {};
|
|
9
14
|
type SanitizeFunctionParam<T extends (param: any) => any> = T extends (param: infer P) => infer R ? Equals<P, undefined> extends true ? () => R : Equals<P, P | undefined> extends true ? (param?: P) => R : (param: P) => R : never;
|
|
10
|
-
type InferParserType<T, TType extends "in" | "out"
|
|
11
|
-
type InferInputType<T, TType extends "in" | "out"
|
|
15
|
+
type InferParserType<T, TType extends "in" | "out"> = T extends StandardSchemaV1 ? TType extends "in" ? StandardSchemaV1.InferInput<T> : StandardSchemaV1.InferOutput<T> : never;
|
|
16
|
+
type InferInputType<T, TType extends "in" | "out"> = T extends UnsetMarker ? undefined : InferParserType<T, TType>;
|
|
12
17
|
type InferContextType<T> = T extends UnsetMarker ? undefined : T;
|
|
13
18
|
interface ActionParams<TInput = unknown, TContext = unknown> {
|
|
14
19
|
_input: TInput;
|
|
@@ -25,7 +30,7 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
25
30
|
/**
|
|
26
31
|
* Input validation for the action.
|
|
27
32
|
*/
|
|
28
|
-
input: <TParser extends
|
|
33
|
+
input: <TParser extends StandardSchemaV1>(input: ((params: {
|
|
29
34
|
ctx: InferContextType<TParams["_context"]>;
|
|
30
35
|
}) => Promise<TParser> | TParser) | TParser) => Omit<ActionBuilder<{
|
|
31
36
|
_input: TParser;
|
|
@@ -37,7 +42,7 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
37
42
|
action: <TOutput>(action: (params: {
|
|
38
43
|
ctx: InferContextType<TParams["_context"]>;
|
|
39
44
|
input: InferInputType<TParams["_input"], "out">;
|
|
40
|
-
}) => Promise<TOutput>) => SanitizeFunctionParam<(input: InferInputType<TParams["_input"], "in">
|
|
45
|
+
}) => Promise<TOutput>) => SanitizeFunctionParam<(input: InferInputType<TParams["_input"], "in">) => Promise<TOutput>>;
|
|
41
46
|
/**
|
|
42
47
|
* Create an action for React `useActionState`
|
|
43
48
|
*/
|
|
@@ -50,8 +55,8 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
50
55
|
formErrors?: undefined;
|
|
51
56
|
} | {
|
|
52
57
|
input?: undefined;
|
|
53
|
-
formErrors:
|
|
54
|
-
})>) => Promise<TState>) => (prevState: TState | TPrevState, formData: InferInputType<TParams["_input"], "in">
|
|
58
|
+
formErrors: ReturnType<typeof getFormErrors>;
|
|
59
|
+
})>) => Promise<TState>) => (prevState: TState | TPrevState, formData: InferInputType<TParams["_input"], "in">) => Promise<TState | TPrevState>;
|
|
55
60
|
}
|
|
56
61
|
/**
|
|
57
62
|
* Server action builder
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
|
|
3
|
+
declare function getFormErrors(issues: ReadonlyArray<StandardSchemaV1.Issue>): {
|
|
4
|
+
messages: string[];
|
|
5
|
+
fieldErrors: Record<string, string[]>;
|
|
6
|
+
};
|
|
2
7
|
|
|
3
8
|
declare const unsetMarker: unique symbol;
|
|
4
9
|
type UnsetMarker = typeof unsetMarker;
|
|
@@ -7,8 +12,8 @@ type Prettify<T> = {
|
|
|
7
12
|
[P in keyof T]: T[P];
|
|
8
13
|
} & {};
|
|
9
14
|
type SanitizeFunctionParam<T extends (param: any) => any> = T extends (param: infer P) => infer R ? Equals<P, undefined> extends true ? () => R : Equals<P, P | undefined> extends true ? (param?: P) => R : (param: P) => R : never;
|
|
10
|
-
type InferParserType<T, TType extends "in" | "out"
|
|
11
|
-
type InferInputType<T, TType extends "in" | "out"
|
|
15
|
+
type InferParserType<T, TType extends "in" | "out"> = T extends StandardSchemaV1 ? TType extends "in" ? StandardSchemaV1.InferInput<T> : StandardSchemaV1.InferOutput<T> : never;
|
|
16
|
+
type InferInputType<T, TType extends "in" | "out"> = T extends UnsetMarker ? undefined : InferParserType<T, TType>;
|
|
12
17
|
type InferContextType<T> = T extends UnsetMarker ? undefined : T;
|
|
13
18
|
interface ActionParams<TInput = unknown, TContext = unknown> {
|
|
14
19
|
_input: TInput;
|
|
@@ -25,7 +30,7 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
25
30
|
/**
|
|
26
31
|
* Input validation for the action.
|
|
27
32
|
*/
|
|
28
|
-
input: <TParser extends
|
|
33
|
+
input: <TParser extends StandardSchemaV1>(input: ((params: {
|
|
29
34
|
ctx: InferContextType<TParams["_context"]>;
|
|
30
35
|
}) => Promise<TParser> | TParser) | TParser) => Omit<ActionBuilder<{
|
|
31
36
|
_input: TParser;
|
|
@@ -37,7 +42,7 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
37
42
|
action: <TOutput>(action: (params: {
|
|
38
43
|
ctx: InferContextType<TParams["_context"]>;
|
|
39
44
|
input: InferInputType<TParams["_input"], "out">;
|
|
40
|
-
}) => Promise<TOutput>) => SanitizeFunctionParam<(input: InferInputType<TParams["_input"], "in">
|
|
45
|
+
}) => Promise<TOutput>) => SanitizeFunctionParam<(input: InferInputType<TParams["_input"], "in">) => Promise<TOutput>>;
|
|
41
46
|
/**
|
|
42
47
|
* Create an action for React `useActionState`
|
|
43
48
|
*/
|
|
@@ -50,8 +55,8 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
50
55
|
formErrors?: undefined;
|
|
51
56
|
} | {
|
|
52
57
|
input?: undefined;
|
|
53
|
-
formErrors:
|
|
54
|
-
})>) => Promise<TState>) => (prevState: TState | TPrevState, formData: InferInputType<TParams["_input"], "in">
|
|
58
|
+
formErrors: ReturnType<typeof getFormErrors>;
|
|
59
|
+
})>) => Promise<TState>) => (prevState: TState | TPrevState, formData: InferInputType<TParams["_input"], "in">) => Promise<TState | TPrevState>;
|
|
55
60
|
}
|
|
56
61
|
/**
|
|
57
62
|
* Server action builder
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
|
|
3
|
+
var utils = require('@standard-schema/utils');
|
|
4
|
+
|
|
5
|
+
function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
|
|
6
|
+
try {
|
|
7
|
+
var info = gen[key](arg);
|
|
8
|
+
var value = info.value;
|
|
9
|
+
} catch (error) {
|
|
10
|
+
reject(error);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (info.done) {
|
|
14
|
+
resolve(value);
|
|
15
|
+
} else {
|
|
16
|
+
Promise.resolve(value).then(_next, _throw);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function _async_to_generator$1(fn) {
|
|
20
|
+
return function() {
|
|
21
|
+
var self = this, args = arguments;
|
|
22
|
+
return new Promise(function(resolve, reject) {
|
|
23
|
+
var gen = fn.apply(self, args);
|
|
24
|
+
function _next(value) {
|
|
25
|
+
asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "next", value);
|
|
26
|
+
}
|
|
27
|
+
function _throw(err) {
|
|
28
|
+
asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "throw", err);
|
|
29
|
+
}
|
|
30
|
+
_next(undefined);
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function standardValidate(schema, input) {
|
|
35
|
+
return _standardValidate.apply(this, arguments);
|
|
36
|
+
}
|
|
37
|
+
function _standardValidate() {
|
|
38
|
+
_standardValidate = _async_to_generator$1(function*(schema, input) {
|
|
39
|
+
let result = schema["~standard"].validate(input);
|
|
40
|
+
if (result instanceof Promise) result = yield result;
|
|
41
|
+
return result;
|
|
42
|
+
});
|
|
43
|
+
return _standardValidate.apply(this, arguments);
|
|
44
|
+
}
|
|
45
|
+
function getFormErrors(issues) {
|
|
46
|
+
const messages = [];
|
|
47
|
+
const fieldErrors = {};
|
|
48
|
+
for (const issue of issues){
|
|
49
|
+
const dotPath = utils.getDotPath(issue);
|
|
50
|
+
if (dotPath) {
|
|
51
|
+
if (fieldErrors[dotPath]) {
|
|
52
|
+
fieldErrors[dotPath].push(issue.message);
|
|
53
|
+
} else {
|
|
54
|
+
fieldErrors[dotPath] = [
|
|
55
|
+
issue.message
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
messages.push(issue.message);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
messages,
|
|
64
|
+
fieldErrors
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
3
68
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
4
69
|
try {
|
|
5
70
|
var info = gen[key](arg);
|
|
@@ -66,14 +131,14 @@ function createServerActionBuilder(initDef = {}) {
|
|
|
66
131
|
const inputSchema = typeof _def.input === "function" ? yield _def.input({
|
|
67
132
|
ctx
|
|
68
133
|
}) : _def.input;
|
|
69
|
-
const result = yield inputSchema
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
throw new Error("Input validation error");
|
|
134
|
+
const result = yield standardValidate(inputSchema, input);
|
|
135
|
+
if (result.issues) {
|
|
136
|
+
throw new utils.SchemaError(result.issues);
|
|
73
137
|
}
|
|
138
|
+
// biome-ignore lint/suspicious/noExplicitAny: It's fine
|
|
74
139
|
return yield action({
|
|
75
140
|
ctx,
|
|
76
|
-
input: result.
|
|
141
|
+
input: result.value
|
|
77
142
|
});
|
|
78
143
|
}
|
|
79
144
|
return yield action({
|
|
@@ -90,20 +155,21 @@ function createServerActionBuilder(initDef = {}) {
|
|
|
90
155
|
const inputSchema = typeof _def.input === "function" ? yield _def.input({
|
|
91
156
|
ctx
|
|
92
157
|
}) : _def.input;
|
|
93
|
-
const result = yield inputSchema
|
|
94
|
-
if (
|
|
158
|
+
const result = yield standardValidate(inputSchema, formData);
|
|
159
|
+
if (result.issues) {
|
|
95
160
|
return yield action({
|
|
96
161
|
ctx,
|
|
97
162
|
prevState,
|
|
98
163
|
formData,
|
|
99
|
-
formErrors: result.
|
|
164
|
+
formErrors: getFormErrors(result.issues)
|
|
100
165
|
});
|
|
101
166
|
}
|
|
102
167
|
return yield action({
|
|
103
168
|
ctx,
|
|
104
169
|
prevState,
|
|
105
170
|
formData,
|
|
106
|
-
|
|
171
|
+
// biome-ignore lint/suspicious/noExplicitAny: It's fine
|
|
172
|
+
input: result.value
|
|
107
173
|
});
|
|
108
174
|
}
|
|
109
175
|
return yield action({
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,68 @@
|
|
|
1
|
+
import { getDotPath, SchemaError } from '@standard-schema/utils';
|
|
2
|
+
|
|
3
|
+
function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
|
|
4
|
+
try {
|
|
5
|
+
var info = gen[key](arg);
|
|
6
|
+
var value = info.value;
|
|
7
|
+
} catch (error) {
|
|
8
|
+
reject(error);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (info.done) {
|
|
12
|
+
resolve(value);
|
|
13
|
+
} else {
|
|
14
|
+
Promise.resolve(value).then(_next, _throw);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function _async_to_generator$1(fn) {
|
|
18
|
+
return function() {
|
|
19
|
+
var self = this, args = arguments;
|
|
20
|
+
return new Promise(function(resolve, reject) {
|
|
21
|
+
var gen = fn.apply(self, args);
|
|
22
|
+
function _next(value) {
|
|
23
|
+
asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "next", value);
|
|
24
|
+
}
|
|
25
|
+
function _throw(err) {
|
|
26
|
+
asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "throw", err);
|
|
27
|
+
}
|
|
28
|
+
_next(undefined);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function standardValidate(schema, input) {
|
|
33
|
+
return _standardValidate.apply(this, arguments);
|
|
34
|
+
}
|
|
35
|
+
function _standardValidate() {
|
|
36
|
+
_standardValidate = _async_to_generator$1(function*(schema, input) {
|
|
37
|
+
let result = schema["~standard"].validate(input);
|
|
38
|
+
if (result instanceof Promise) result = yield result;
|
|
39
|
+
return result;
|
|
40
|
+
});
|
|
41
|
+
return _standardValidate.apply(this, arguments);
|
|
42
|
+
}
|
|
43
|
+
function getFormErrors(issues) {
|
|
44
|
+
const messages = [];
|
|
45
|
+
const fieldErrors = {};
|
|
46
|
+
for (const issue of issues){
|
|
47
|
+
const dotPath = getDotPath(issue);
|
|
48
|
+
if (dotPath) {
|
|
49
|
+
if (fieldErrors[dotPath]) {
|
|
50
|
+
fieldErrors[dotPath].push(issue.message);
|
|
51
|
+
} else {
|
|
52
|
+
fieldErrors[dotPath] = [
|
|
53
|
+
issue.message
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
messages.push(issue.message);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
messages,
|
|
62
|
+
fieldErrors
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
1
66
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
67
|
try {
|
|
3
68
|
var info = gen[key](arg);
|
|
@@ -64,14 +129,14 @@ function createServerActionBuilder(initDef = {}) {
|
|
|
64
129
|
const inputSchema = typeof _def.input === "function" ? yield _def.input({
|
|
65
130
|
ctx
|
|
66
131
|
}) : _def.input;
|
|
67
|
-
const result = yield inputSchema
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
throw new Error("Input validation error");
|
|
132
|
+
const result = yield standardValidate(inputSchema, input);
|
|
133
|
+
if (result.issues) {
|
|
134
|
+
throw new SchemaError(result.issues);
|
|
71
135
|
}
|
|
136
|
+
// biome-ignore lint/suspicious/noExplicitAny: It's fine
|
|
72
137
|
return yield action({
|
|
73
138
|
ctx,
|
|
74
|
-
input: result.
|
|
139
|
+
input: result.value
|
|
75
140
|
});
|
|
76
141
|
}
|
|
77
142
|
return yield action({
|
|
@@ -88,20 +153,21 @@ function createServerActionBuilder(initDef = {}) {
|
|
|
88
153
|
const inputSchema = typeof _def.input === "function" ? yield _def.input({
|
|
89
154
|
ctx
|
|
90
155
|
}) : _def.input;
|
|
91
|
-
const result = yield inputSchema
|
|
92
|
-
if (
|
|
156
|
+
const result = yield standardValidate(inputSchema, formData);
|
|
157
|
+
if (result.issues) {
|
|
93
158
|
return yield action({
|
|
94
159
|
ctx,
|
|
95
160
|
prevState,
|
|
96
161
|
formData,
|
|
97
|
-
formErrors: result.
|
|
162
|
+
formErrors: getFormErrors(result.issues)
|
|
98
163
|
});
|
|
99
164
|
}
|
|
100
165
|
return yield action({
|
|
101
166
|
ctx,
|
|
102
167
|
prevState,
|
|
103
168
|
formData,
|
|
104
|
-
|
|
169
|
+
// biome-ignore lint/suspicious/noExplicitAny: It's fine
|
|
170
|
+
input: result.value
|
|
105
171
|
});
|
|
106
172
|
}
|
|
107
173
|
return yield action({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "server-act",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"homepage": "https://github.com/chungweileong94/server-act#readme",
|
|
5
5
|
"author": "chungweileong94",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,21 +43,33 @@
|
|
|
43
43
|
"server action",
|
|
44
44
|
"action"
|
|
45
45
|
],
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"zod": "^3.22.2",
|
|
50
|
-
"zod-form-data": "^2.0.2"
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@standard-schema/spec": "^1.0.0",
|
|
48
|
+
"@standard-schema/utils": "^0.3.0"
|
|
51
49
|
},
|
|
52
50
|
"peerDependencies": {
|
|
53
51
|
"typescript": ">=5.0.0",
|
|
54
|
-
"
|
|
52
|
+
"valibot": "^1.0.0",
|
|
53
|
+
"zod": "^3.24.0"
|
|
55
54
|
},
|
|
56
55
|
"peerDependenciesMeta": {
|
|
57
56
|
"typescript": {
|
|
58
57
|
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"zod": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"valibot": {
|
|
63
|
+
"optional": true
|
|
59
64
|
}
|
|
60
65
|
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"bunchee": "^6.2.0",
|
|
68
|
+
"typescript": "^5.6.3",
|
|
69
|
+
"valibot": "1.0.0-rc.0",
|
|
70
|
+
"zod": "^3.24.2",
|
|
71
|
+
"zod-form-data": "^2.0.2"
|
|
72
|
+
},
|
|
61
73
|
"scripts": {
|
|
62
74
|
"build": "bunchee",
|
|
63
75
|
"dev": "bunchee -w",
|