server-act 1.1.2 → 1.1.4
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/dist/index.d.mts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +99 -166
- package/dist/index.mjs +98 -130
- package/package.json +26 -11
- package/.eslintrc.json +0 -11
- package/.prettierrc.json +0 -15
- package/.turbo/turbo-build.log +0 -22
- package/CHANGELOG.md +0 -74
- package/README.md +0 -141
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/src/index.test.ts +0 -110
- package/src/index.ts +0 -130
- package/tsconfig.json +0 -30
- package/tsup.config.ts +0 -11
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Chung Wei Leong
|
|
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/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
declare const unsetMarker: unique symbol;
|
|
4
|
+
type UnsetMarker = typeof unsetMarker;
|
|
3
5
|
type Prettify<T> = {
|
|
4
6
|
[P in keyof T]: T[P];
|
|
5
7
|
} & {};
|
|
6
|
-
declare const unsetMarker: unique symbol;
|
|
7
|
-
type UnsetMarker = typeof unsetMarker;
|
|
8
8
|
type OptionalizeUndefined<T> = undefined extends T ? [param?: T] : [param: T];
|
|
9
|
-
type InferParserType<
|
|
9
|
+
type InferParserType<T, TType extends 'in' | 'out'> = T extends z.ZodEffects<infer I, any, any> ? I[TType extends 'in' ? '_input' : '_output'] : T extends z.ZodType ? T[TType extends 'in' ? '_input' : '_output'] : never;
|
|
10
|
+
type InferInputType<T, TType extends 'in' | 'out'> = T extends UnsetMarker ? undefined : InferParserType<T, TType>;
|
|
10
11
|
type InferContextType<T> = T extends UnsetMarker ? undefined : T;
|
|
11
12
|
interface ActionParams<TInput = unknown, TContext = unknown> {
|
|
12
13
|
_input: TInput;
|
|
@@ -32,8 +33,8 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
32
33
|
*/
|
|
33
34
|
action: <TOutput>(action: (params: {
|
|
34
35
|
ctx: InferContextType<TParams['_context']>;
|
|
35
|
-
input:
|
|
36
|
-
}) => Promise<TOutput>) => (...[input]: OptionalizeUndefined<
|
|
36
|
+
input: InferInputType<TParams['_input'], 'out'>;
|
|
37
|
+
}) => Promise<TOutput>) => (...[input]: OptionalizeUndefined<InferInputType<TParams['_input'], 'in'>>) => Promise<TOutput>;
|
|
37
38
|
/**
|
|
38
39
|
* Create an action for React `useFormState`
|
|
39
40
|
*/
|
|
@@ -41,11 +42,11 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
41
42
|
ctx: InferContextType<TParams['_context']>;
|
|
42
43
|
prevState: any;
|
|
43
44
|
} & ({
|
|
44
|
-
input:
|
|
45
|
+
input: InferInputType<TParams['_input'], 'out'>;
|
|
45
46
|
formErrors?: undefined;
|
|
46
47
|
} | {
|
|
47
48
|
input?: undefined;
|
|
48
|
-
formErrors: z.ZodError<
|
|
49
|
+
formErrors: z.ZodError<InferInputType<TParams['_input'], 'in'>>;
|
|
49
50
|
})>) => Promise<TState>) => (prevState: TState, formData: FormData) => Promise<TState>;
|
|
50
51
|
}
|
|
51
52
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
declare const unsetMarker: unique symbol;
|
|
4
|
+
type UnsetMarker = typeof unsetMarker;
|
|
3
5
|
type Prettify<T> = {
|
|
4
6
|
[P in keyof T]: T[P];
|
|
5
7
|
} & {};
|
|
6
|
-
declare const unsetMarker: unique symbol;
|
|
7
|
-
type UnsetMarker = typeof unsetMarker;
|
|
8
8
|
type OptionalizeUndefined<T> = undefined extends T ? [param?: T] : [param: T];
|
|
9
|
-
type InferParserType<
|
|
9
|
+
type InferParserType<T, TType extends 'in' | 'out'> = T extends z.ZodEffects<infer I, any, any> ? I[TType extends 'in' ? '_input' : '_output'] : T extends z.ZodType ? T[TType extends 'in' ? '_input' : '_output'] : never;
|
|
10
|
+
type InferInputType<T, TType extends 'in' | 'out'> = T extends UnsetMarker ? undefined : InferParserType<T, TType>;
|
|
10
11
|
type InferContextType<T> = T extends UnsetMarker ? undefined : T;
|
|
11
12
|
interface ActionParams<TInput = unknown, TContext = unknown> {
|
|
12
13
|
_input: TInput;
|
|
@@ -32,8 +33,8 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
32
33
|
*/
|
|
33
34
|
action: <TOutput>(action: (params: {
|
|
34
35
|
ctx: InferContextType<TParams['_context']>;
|
|
35
|
-
input:
|
|
36
|
-
}) => Promise<TOutput>) => (...[input]: OptionalizeUndefined<
|
|
36
|
+
input: InferInputType<TParams['_input'], 'out'>;
|
|
37
|
+
}) => Promise<TOutput>) => (...[input]: OptionalizeUndefined<InferInputType<TParams['_input'], 'in'>>) => Promise<TOutput>;
|
|
37
38
|
/**
|
|
38
39
|
* Create an action for React `useFormState`
|
|
39
40
|
*/
|
|
@@ -41,11 +42,11 @@ interface ActionBuilder<TParams extends ActionParams> {
|
|
|
41
42
|
ctx: InferContextType<TParams['_context']>;
|
|
42
43
|
prevState: any;
|
|
43
44
|
} & ({
|
|
44
|
-
input:
|
|
45
|
+
input: InferInputType<TParams['_input'], 'out'>;
|
|
45
46
|
formErrors?: undefined;
|
|
46
47
|
} | {
|
|
47
48
|
input?: undefined;
|
|
48
|
-
formErrors: z.ZodError<
|
|
49
|
+
formErrors: z.ZodError<InferInputType<TParams['_input'], 'in'>>;
|
|
49
50
|
})>) => Promise<TState>) => (prevState: TState, formData: FormData) => Promise<TState>;
|
|
50
51
|
}
|
|
51
52
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,175 +1,108 @@
|
|
|
1
|
-
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/index.ts
|
|
31
|
-
var src_exports = {};
|
|
32
|
-
__export(src_exports, {
|
|
33
|
-
serverAct: () => serverAct
|
|
34
|
-
});
|
|
35
|
-
module.exports = __toCommonJS(src_exports);
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
36
2
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return path[0].toString();
|
|
45
|
-
}
|
|
46
|
-
return path.reduce((acc, item) => {
|
|
47
|
-
if (typeof item === "number") {
|
|
48
|
-
return acc + "[" + item.toString() + "]";
|
|
49
|
-
}
|
|
50
|
-
if (item.includes('"')) {
|
|
51
|
-
return acc + '["' + escapeQuotes(item) + '"]';
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-explicit-any */ function asyncGeneratorStep(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;
|
|
52
10
|
}
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return acc + separator + item;
|
|
58
|
-
}, "");
|
|
59
|
-
}
|
|
60
|
-
function escapeQuotes(str) {
|
|
61
|
-
return str.replace(/"/g, '\\"');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// ../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/utils/NonEmptyArray.js
|
|
65
|
-
function isNonEmptyArray(value) {
|
|
66
|
-
return value.length !== 0;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// ../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/ValidationError.js
|
|
70
|
-
var MAX_ISSUES_IN_MESSAGE = 99;
|
|
71
|
-
var ISSUE_SEPARATOR = "; ";
|
|
72
|
-
var UNION_SEPARATOR = ", or ";
|
|
73
|
-
var PREFIX = "Validation error";
|
|
74
|
-
var PREFIX_SEPARATOR = ": ";
|
|
75
|
-
var ValidationError = class extends Error {
|
|
76
|
-
details;
|
|
77
|
-
name;
|
|
78
|
-
constructor(message, details = []) {
|
|
79
|
-
super(message);
|
|
80
|
-
this.details = details;
|
|
81
|
-
this.name = "ZodValidationError";
|
|
82
|
-
}
|
|
83
|
-
toString() {
|
|
84
|
-
return this.message;
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
function getMessageFromZodIssue(issue, issueSeparator, unionSeparator) {
|
|
88
|
-
if (issue.code === "invalid_union") {
|
|
89
|
-
return issue.unionErrors.reduce((acc, zodError) => {
|
|
90
|
-
const newIssues = zodError.issues.map((issue2) => getMessageFromZodIssue(issue2, issueSeparator, unionSeparator)).join(issueSeparator);
|
|
91
|
-
if (!acc.includes(newIssues)) {
|
|
92
|
-
acc.push(newIssues);
|
|
93
|
-
}
|
|
94
|
-
return acc;
|
|
95
|
-
}, []).join(unionSeparator);
|
|
96
|
-
}
|
|
97
|
-
if (isNonEmptyArray(issue.path)) {
|
|
98
|
-
if (issue.path.length === 1) {
|
|
99
|
-
const identifier = issue.path[0];
|
|
100
|
-
if (typeof identifier === "number") {
|
|
101
|
-
return `${issue.message} at index ${identifier}`;
|
|
102
|
-
}
|
|
11
|
+
if (info.done) {
|
|
12
|
+
resolve(value);
|
|
13
|
+
} else {
|
|
14
|
+
Promise.resolve(value).then(_next, _throw);
|
|
103
15
|
}
|
|
104
|
-
return `${issue.message} at "${joinPath(issue.path)}"`;
|
|
105
|
-
}
|
|
106
|
-
return issue.message;
|
|
107
16
|
}
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
17
|
+
function _async_to_generator(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(gen, resolve, reject, _next, _throw, "next", value);
|
|
24
|
+
}
|
|
25
|
+
function _throw(err) {
|
|
26
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
27
|
+
}
|
|
28
|
+
_next(undefined);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
119
31
|
}
|
|
120
|
-
function
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
32
|
+
function _extends() {
|
|
33
|
+
_extends = Object.assign || function(target) {
|
|
34
|
+
for(var i = 1; i < arguments.length; i++){
|
|
35
|
+
var source = arguments[i];
|
|
36
|
+
for(var key in source){
|
|
37
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
38
|
+
target[key] = source[key];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return target;
|
|
43
|
+
};
|
|
44
|
+
return _extends.apply(this, arguments);
|
|
125
45
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
var unsetMarker = Symbol("unsetMarker");
|
|
129
|
-
var createNewServerActionBuilder = (def) => {
|
|
130
|
-
return createServerActionBuilder(def);
|
|
46
|
+
const createNewServerActionBuilder = (def)=>{
|
|
47
|
+
return createServerActionBuilder(def);
|
|
131
48
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return
|
|
162
|
-
|
|
163
|
-
|
|
49
|
+
const createServerActionBuilder = (initDef = {})=>{
|
|
50
|
+
const _def = _extends({
|
|
51
|
+
input: undefined,
|
|
52
|
+
middleware: undefined
|
|
53
|
+
}, initDef);
|
|
54
|
+
return {
|
|
55
|
+
middleware: (middleware)=>createNewServerActionBuilder(_extends({}, _def, {
|
|
56
|
+
middleware
|
|
57
|
+
})),
|
|
58
|
+
input: (input)=>createNewServerActionBuilder(_extends({}, _def, {
|
|
59
|
+
input
|
|
60
|
+
})),
|
|
61
|
+
action: (action)=>{
|
|
62
|
+
return /*#__PURE__*/ _async_to_generator(function*(input) {
|
|
63
|
+
const ctx = yield _def.middleware == null ? void 0 : _def.middleware.call(_def);
|
|
64
|
+
if (_def.input) {
|
|
65
|
+
const result = _def.input.safeParse(input);
|
|
66
|
+
if (!result.success) {
|
|
67
|
+
console.error('❌ Input validation error:', result.error.errors);
|
|
68
|
+
throw new Error('Input validation error');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return yield action({
|
|
72
|
+
ctx,
|
|
73
|
+
input
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
formAction: (action)=>{
|
|
78
|
+
return /*#__PURE__*/ _async_to_generator(function*(prevState, formData) {
|
|
79
|
+
const ctx = yield _def.middleware == null ? void 0 : _def.middleware.call(_def);
|
|
80
|
+
if (_def.input) {
|
|
81
|
+
const result = _def.input.safeParse(formData);
|
|
82
|
+
if (!result.success) {
|
|
83
|
+
return yield action({
|
|
84
|
+
ctx,
|
|
85
|
+
prevState,
|
|
86
|
+
formErrors: result.error
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return yield action({
|
|
90
|
+
ctx,
|
|
91
|
+
prevState,
|
|
92
|
+
input: result.data
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return yield action({
|
|
96
|
+
ctx,
|
|
97
|
+
prevState,
|
|
98
|
+
input: undefined
|
|
99
|
+
});
|
|
100
|
+
});
|
|
164
101
|
}
|
|
165
|
-
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
};
|
|
102
|
+
};
|
|
169
103
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
//# sourceMappingURL=index.js.map
|
|
104
|
+
/**
|
|
105
|
+
* Server action builder
|
|
106
|
+
*/ const serverAct = createServerActionBuilder();
|
|
107
|
+
|
|
108
|
+
exports.serverAct = serverAct;
|
package/dist/index.mjs
CHANGED
|
@@ -1,138 +1,106 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return path[0].toString();
|
|
9
|
-
}
|
|
10
|
-
return path.reduce((acc, item) => {
|
|
11
|
-
if (typeof item === "number") {
|
|
12
|
-
return acc + "[" + item.toString() + "]";
|
|
13
|
-
}
|
|
14
|
-
if (item.includes('"')) {
|
|
15
|
-
return acc + '["' + escapeQuotes(item) + '"]';
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-explicit-any */ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
16
8
|
}
|
|
17
|
-
if (
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return acc + separator + item;
|
|
22
|
-
}, "");
|
|
23
|
-
}
|
|
24
|
-
function escapeQuotes(str) {
|
|
25
|
-
return str.replace(/"/g, '\\"');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// ../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/utils/NonEmptyArray.js
|
|
29
|
-
function isNonEmptyArray(value) {
|
|
30
|
-
return value.length !== 0;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// ../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/ValidationError.js
|
|
34
|
-
var MAX_ISSUES_IN_MESSAGE = 99;
|
|
35
|
-
var ISSUE_SEPARATOR = "; ";
|
|
36
|
-
var UNION_SEPARATOR = ", or ";
|
|
37
|
-
var PREFIX = "Validation error";
|
|
38
|
-
var PREFIX_SEPARATOR = ": ";
|
|
39
|
-
var ValidationError = class extends Error {
|
|
40
|
-
details;
|
|
41
|
-
name;
|
|
42
|
-
constructor(message, details = []) {
|
|
43
|
-
super(message);
|
|
44
|
-
this.details = details;
|
|
45
|
-
this.name = "ZodValidationError";
|
|
46
|
-
}
|
|
47
|
-
toString() {
|
|
48
|
-
return this.message;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
function getMessageFromZodIssue(issue, issueSeparator, unionSeparator) {
|
|
52
|
-
if (issue.code === "invalid_union") {
|
|
53
|
-
return issue.unionErrors.reduce((acc, zodError) => {
|
|
54
|
-
const newIssues = zodError.issues.map((issue2) => getMessageFromZodIssue(issue2, issueSeparator, unionSeparator)).join(issueSeparator);
|
|
55
|
-
if (!acc.includes(newIssues)) {
|
|
56
|
-
acc.push(newIssues);
|
|
57
|
-
}
|
|
58
|
-
return acc;
|
|
59
|
-
}, []).join(unionSeparator);
|
|
60
|
-
}
|
|
61
|
-
if (isNonEmptyArray(issue.path)) {
|
|
62
|
-
if (issue.path.length === 1) {
|
|
63
|
-
const identifier = issue.path[0];
|
|
64
|
-
if (typeof identifier === "number") {
|
|
65
|
-
return `${issue.message} at index ${identifier}`;
|
|
66
|
-
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
67
13
|
}
|
|
68
|
-
return `${issue.message} at "${joinPath(issue.path)}"`;
|
|
69
|
-
}
|
|
70
|
-
return issue.message;
|
|
71
14
|
}
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
83
29
|
}
|
|
84
|
-
function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
30
|
+
function _extends() {
|
|
31
|
+
_extends = Object.assign || function(target) {
|
|
32
|
+
for(var i = 1; i < arguments.length; i++){
|
|
33
|
+
var source = arguments[i];
|
|
34
|
+
for(var key in source){
|
|
35
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
36
|
+
target[key] = source[key];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return target;
|
|
41
|
+
};
|
|
42
|
+
return _extends.apply(this, arguments);
|
|
89
43
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
var unsetMarker = Symbol("unsetMarker");
|
|
93
|
-
var createNewServerActionBuilder = (def) => {
|
|
94
|
-
return createServerActionBuilder(def);
|
|
44
|
+
const createNewServerActionBuilder = (def)=>{
|
|
45
|
+
return createServerActionBuilder(def);
|
|
95
46
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
47
|
+
const createServerActionBuilder = (initDef = {})=>{
|
|
48
|
+
const _def = _extends({
|
|
49
|
+
input: undefined,
|
|
50
|
+
middleware: undefined
|
|
51
|
+
}, initDef);
|
|
52
|
+
return {
|
|
53
|
+
middleware: (middleware)=>createNewServerActionBuilder(_extends({}, _def, {
|
|
54
|
+
middleware
|
|
55
|
+
})),
|
|
56
|
+
input: (input)=>createNewServerActionBuilder(_extends({}, _def, {
|
|
57
|
+
input
|
|
58
|
+
})),
|
|
59
|
+
action: (action)=>{
|
|
60
|
+
return /*#__PURE__*/ _async_to_generator(function*(input) {
|
|
61
|
+
const ctx = yield _def.middleware == null ? void 0 : _def.middleware.call(_def);
|
|
62
|
+
if (_def.input) {
|
|
63
|
+
const result = _def.input.safeParse(input);
|
|
64
|
+
if (!result.success) {
|
|
65
|
+
console.error('❌ Input validation error:', result.error.errors);
|
|
66
|
+
throw new Error('Input validation error');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return yield action({
|
|
70
|
+
ctx,
|
|
71
|
+
input
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
formAction: (action)=>{
|
|
76
|
+
return /*#__PURE__*/ _async_to_generator(function*(prevState, formData) {
|
|
77
|
+
const ctx = yield _def.middleware == null ? void 0 : _def.middleware.call(_def);
|
|
78
|
+
if (_def.input) {
|
|
79
|
+
const result = _def.input.safeParse(formData);
|
|
80
|
+
if (!result.success) {
|
|
81
|
+
return yield action({
|
|
82
|
+
ctx,
|
|
83
|
+
prevState,
|
|
84
|
+
formErrors: result.error
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return yield action({
|
|
88
|
+
ctx,
|
|
89
|
+
prevState,
|
|
90
|
+
input: result.data
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return yield action({
|
|
94
|
+
ctx,
|
|
95
|
+
prevState,
|
|
96
|
+
input: undefined
|
|
97
|
+
});
|
|
98
|
+
});
|
|
114
99
|
}
|
|
115
|
-
|
|
116
|
-
};
|
|
117
|
-
},
|
|
118
|
-
formAction: (action) => {
|
|
119
|
-
return async (prevState, formData) => {
|
|
120
|
-
var _a;
|
|
121
|
-
const ctx = await ((_a = _def.middleware) == null ? void 0 : _a.call(_def));
|
|
122
|
-
if (_def.input) {
|
|
123
|
-
const result = _def.input.safeParse(formData);
|
|
124
|
-
if (!result.success) {
|
|
125
|
-
return await action({ ctx, prevState, formErrors: result.error });
|
|
126
|
-
}
|
|
127
|
-
return await action({ ctx, prevState, input: result.data });
|
|
128
|
-
}
|
|
129
|
-
return await action({ ctx, prevState, input: void 0 });
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
};
|
|
100
|
+
};
|
|
133
101
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Server action builder
|
|
104
|
+
*/ const serverAct = createServerActionBuilder();
|
|
105
|
+
|
|
106
|
+
export { serverAct };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "server-act",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"homepage": "https://github.com/chungweileong94/server-act#readme",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,15 +11,25 @@
|
|
|
11
11
|
},
|
|
12
12
|
"main": "dist/index.js",
|
|
13
13
|
"module": "dist/index.mjs",
|
|
14
|
-
"types": "dist/index.d.ts",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
15
|
"exports": {
|
|
16
16
|
".": {
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
"import": {
|
|
18
|
+
"types": "./dist/index.d.mts",
|
|
19
|
+
"default": "./dist/index.mjs"
|
|
20
|
+
},
|
|
21
|
+
"require": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"default": "./dist/index.js"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
22
26
|
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"package.json",
|
|
30
|
+
"LICENSE",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
23
33
|
"keywords": [
|
|
24
34
|
"next",
|
|
25
35
|
"nextjs",
|
|
@@ -34,21 +44,26 @@
|
|
|
34
44
|
"author": "chungweileong94",
|
|
35
45
|
"license": "MIT",
|
|
36
46
|
"devDependencies": {
|
|
47
|
+
"bunchee": "^4.3.3",
|
|
37
48
|
"eslint": "^8.49.0",
|
|
38
49
|
"eslint-config-whiteroom": "^3.3.0",
|
|
39
50
|
"prettier": "^3.0.3",
|
|
40
|
-
"tsup": "^7.2.0",
|
|
41
51
|
"typescript": "^5.2.2",
|
|
42
52
|
"zod": "^3.22.2",
|
|
43
|
-
"zod-form-data": "^2.0.2"
|
|
44
|
-
"zod-validation-error": "^1.5.0"
|
|
53
|
+
"zod-form-data": "^2.0.2"
|
|
45
54
|
},
|
|
46
55
|
"peerDependencies": {
|
|
47
56
|
"typescript": "^5.2.2",
|
|
48
57
|
"zod": "^3.22.2"
|
|
49
58
|
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"typescript": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
50
64
|
"scripts": {
|
|
51
|
-
"build": "
|
|
65
|
+
"build": "bunchee",
|
|
66
|
+
"dev": "bunchee -w",
|
|
52
67
|
"test": "vitest run",
|
|
53
68
|
"lint": "eslint src --ext .ts"
|
|
54
69
|
}
|
package/.eslintrc.json
DELETED
package/.prettierrc.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"arrowParens": "always",
|
|
3
|
-
"bracketSpacing": false,
|
|
4
|
-
"htmlWhitespaceSensitivity": "css",
|
|
5
|
-
"insertPragma": false,
|
|
6
|
-
"bracketSameLine": false,
|
|
7
|
-
"jsxSingleQuote": false,
|
|
8
|
-
"printWidth": 120,
|
|
9
|
-
"proseWrap": "preserve",
|
|
10
|
-
"quoteProps": "as-needed",
|
|
11
|
-
"semi": true,
|
|
12
|
-
"singleQuote": true,
|
|
13
|
-
"trailingComma": "all",
|
|
14
|
-
"useTabs": false
|
|
15
|
-
}
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> server-act@1.1.2 build /home/runner/work/server-act/server-act/packages/server-act
|
|
3
|
-
> tsup
|
|
4
|
-
|
|
5
|
-
[34mCLI[39m Building entry: ./src/index.ts
|
|
6
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
|
-
[34mCLI[39m tsup v7.2.0
|
|
8
|
-
[34mCLI[39m Using tsup config: /home/runner/work/server-act/server-act/packages/server-act/tsup.config.ts
|
|
9
|
-
[34mCLI[39m Target: node16
|
|
10
|
-
[34mCLI[39m Cleaning output folder
|
|
11
|
-
[34mESM[39m Build start
|
|
12
|
-
[34mCJS[39m Build start
|
|
13
|
-
[32mESM[39m [1mdist/index.mjs [22m[32m4.59 KB[39m
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[32m11.97 KB[39m
|
|
15
|
-
[32mESM[39m ⚡️ Build success in 29ms
|
|
16
|
-
[32mCJS[39m [1mdist/index.js [22m[32m6.18 KB[39m
|
|
17
|
-
[32mCJS[39m [1mdist/index.js.map [22m[32m12.02 KB[39m
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in 30ms
|
|
19
|
-
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in 1345ms
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m2.17 KB[39m
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m2.17 KB[39m
|
package/CHANGELOG.md
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# server-act
|
|
2
|
-
|
|
3
|
-
## 1.1.2
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- a832b11: Improve form errors type infer
|
|
8
|
-
|
|
9
|
-
## 1.1.1
|
|
10
|
-
|
|
11
|
-
### Patch Changes
|
|
12
|
-
|
|
13
|
-
- 8d5b6e5: Fixed zod error type in `formAction` when using FormData
|
|
14
|
-
|
|
15
|
-
## 1.1.0
|
|
16
|
-
|
|
17
|
-
### Minor Changes
|
|
18
|
-
|
|
19
|
-
- 48b9164: Remove formData parsing for `formAction`
|
|
20
|
-
|
|
21
|
-
## 1.0.0
|
|
22
|
-
|
|
23
|
-
### Major Changes
|
|
24
|
-
|
|
25
|
-
- b4318a8: Get `formAction` out of experimental!
|
|
26
|
-
|
|
27
|
-
## 0.0.10
|
|
28
|
-
|
|
29
|
-
### Patch Changes
|
|
30
|
-
|
|
31
|
-
- a2ab457: Fixed form action doc
|
|
32
|
-
|
|
33
|
-
## 0.0.9
|
|
34
|
-
|
|
35
|
-
### Patch Changes
|
|
36
|
-
|
|
37
|
-
- d8682f2: Documentation for experimental form action
|
|
38
|
-
|
|
39
|
-
## 0.0.8
|
|
40
|
-
|
|
41
|
-
### Patch Changes
|
|
42
|
-
|
|
43
|
-
- 566261e: Change form action error to ZodError
|
|
44
|
-
- ead7149: Prettify form action params type
|
|
45
|
-
|
|
46
|
-
## 0.0.7
|
|
47
|
-
|
|
48
|
-
### Patch Changes
|
|
49
|
-
|
|
50
|
-
- 50e2853: New experimental form action
|
|
51
|
-
|
|
52
|
-
## 0.0.6
|
|
53
|
-
|
|
54
|
-
### Patch Changes
|
|
55
|
-
|
|
56
|
-
- fedd1d4: Update README
|
|
57
|
-
|
|
58
|
-
## 0.0.5
|
|
59
|
-
|
|
60
|
-
### Patch Changes
|
|
61
|
-
|
|
62
|
-
- 7e5d9c9: Support middleware
|
|
63
|
-
|
|
64
|
-
## 0.0.1
|
|
65
|
-
|
|
66
|
-
### Patch Changes
|
|
67
|
-
|
|
68
|
-
- 01d52a7: First Release!
|
|
69
|
-
|
|
70
|
-
## 0.0.1
|
|
71
|
-
|
|
72
|
-
### Patch Changes
|
|
73
|
-
|
|
74
|
-
- First Release!
|
package/README.md
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
# Server-Act
|
|
2
|
-
|
|
3
|
-
[](https://badge.fury.io/js/server-act)
|
|
4
|
-
|
|
5
|
-
A simple React server action builder that provides input validation with zod.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# npm
|
|
11
|
-
npm install server-act zod
|
|
12
|
-
|
|
13
|
-
# yarn
|
|
14
|
-
yarn add server-act zod
|
|
15
|
-
|
|
16
|
-
# pnpm
|
|
17
|
-
pnpm add server-act zod
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Usage
|
|
21
|
-
|
|
22
|
-
```ts
|
|
23
|
-
// action.ts
|
|
24
|
-
"use server";
|
|
25
|
-
|
|
26
|
-
import { serverAct } from "server-act";
|
|
27
|
-
import { z } from "zod";
|
|
28
|
-
|
|
29
|
-
export const sayHelloAction = serverAct
|
|
30
|
-
.input(
|
|
31
|
-
z.object({
|
|
32
|
-
name: z.string(),
|
|
33
|
-
})
|
|
34
|
-
)
|
|
35
|
-
.action(async ({ input }) => {
|
|
36
|
-
return `Hello, ${input.name}`;
|
|
37
|
-
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
```tsx
|
|
41
|
-
// client-component.tsx
|
|
42
|
-
"use client";
|
|
43
|
-
|
|
44
|
-
import { sayHelloAction } from "./action";
|
|
45
|
-
|
|
46
|
-
export const ClientComponent = () => {
|
|
47
|
-
const onClick = () => {
|
|
48
|
-
const message = await sayHelloAction({ name: "John" });
|
|
49
|
-
console.log(message); // Hello, John
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<div>
|
|
54
|
-
<button onClick={onClick}>Trigger action</button>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
};
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### With Middleware
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
// action.ts
|
|
64
|
-
"use server";
|
|
65
|
-
|
|
66
|
-
import { serverAct } from "server-act";
|
|
67
|
-
import { z } from "zod";
|
|
68
|
-
|
|
69
|
-
export const sayHelloAction = serverAct
|
|
70
|
-
.middleware(() => {
|
|
71
|
-
const userId = "...";
|
|
72
|
-
return { userId };
|
|
73
|
-
})
|
|
74
|
-
.input(
|
|
75
|
-
z.object({
|
|
76
|
-
name: z.string(),
|
|
77
|
-
})
|
|
78
|
-
)
|
|
79
|
-
.action(async ({ ctx, input }) => {
|
|
80
|
-
console.log("User ID", ctx.userId);
|
|
81
|
-
return `Hello, ${input.name}`;
|
|
82
|
-
});
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### `useFormState` Support
|
|
86
|
-
|
|
87
|
-
> `useFormState` Documentation:
|
|
88
|
-
>
|
|
89
|
-
> - https://nextjs.org/docs/app/building-your-application/data-fetching/forms-and-mutations#error-handling
|
|
90
|
-
> - https://react.dev/reference/react-dom/hooks/useFormState
|
|
91
|
-
|
|
92
|
-
We recommend using [zod-form-data](https://www.npmjs.com/package/zod-form-data) for input validation.
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
// action.ts;
|
|
96
|
-
"use server";
|
|
97
|
-
|
|
98
|
-
import { serverAct } from "server-act";
|
|
99
|
-
import { z } from "zod";
|
|
100
|
-
import { zfd } from "zod-form-data";
|
|
101
|
-
|
|
102
|
-
export const sayHelloAction = serverAct
|
|
103
|
-
.middleware(requestTimeMiddleware)
|
|
104
|
-
.input(
|
|
105
|
-
zfd.formData({
|
|
106
|
-
name: zfd.text(
|
|
107
|
-
z
|
|
108
|
-
.string({ required_error: `You haven't told me your name` })
|
|
109
|
-
.nonempty({ message: "You need to tell me your name!" })
|
|
110
|
-
),
|
|
111
|
-
})
|
|
112
|
-
)
|
|
113
|
-
.formAction(async ({ input, formErrors, ctx }) => {
|
|
114
|
-
if (formErrors) {
|
|
115
|
-
return { formErrors: formErrors.formErrors.fieldErrors };
|
|
116
|
-
}
|
|
117
|
-
return { message: `Hello, ${input.name}!` };
|
|
118
|
-
});
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
```tsx
|
|
122
|
-
// client-component.tsx
|
|
123
|
-
"use client";
|
|
124
|
-
|
|
125
|
-
import { sayHelloAction } from "./action";
|
|
126
|
-
|
|
127
|
-
export const ClientComponent = () => {
|
|
128
|
-
const [state, dispatch] = useFormState(sayHelloAction, { formErrors: {} });
|
|
129
|
-
|
|
130
|
-
return (
|
|
131
|
-
<form action={dispatch}>
|
|
132
|
-
<input name="name" required />
|
|
133
|
-
{state.formErrors?.name?.map((error) => <p key={error}>{error}</p>)}
|
|
134
|
-
|
|
135
|
-
<button type="submit">Submit</button>
|
|
136
|
-
|
|
137
|
-
{!!state.message && <p>{state.message}</p>}
|
|
138
|
-
</form>
|
|
139
|
-
);
|
|
140
|
-
};
|
|
141
|
-
```
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/ValidationError.js","../../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/utils/joinPath.js","../../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/utils/NonEmptyArray.js"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {type z} from 'zod';\nimport {fromZodError} from 'zod-validation-error';\n\ntype Prettify<T> = {\n [P in keyof T]: T[P];\n // eslint-disable-next-line @typescript-eslint/ban-types\n} & {};\n\nconst unsetMarker = Symbol('unsetMarker');\ntype UnsetMarker = typeof unsetMarker;\n\ntype OptionalizeUndefined<T> = undefined extends T ? [param?: T] : [param: T];\n\ntype InferParserType<TParser, TType extends 'in' | 'out'> = TParser extends UnsetMarker\n ? undefined\n : TParser extends z.ZodType\n ? TParser[TType extends 'in' ? '_input' : '_output']\n : never;\n\ntype InferContextType<T> = T extends UnsetMarker ? undefined : T;\n\ninterface ActionParams<TInput = unknown, TContext = unknown> {\n _input: TInput;\n _context: TContext;\n}\n\ninterface ActionBuilder<TParams extends ActionParams> {\n /**\n * Middleware allows you to run code before the action, its return value will pass as context to the action.\n */\n middleware: <TContext>(\n middleware: () => Promise<TContext> | TContext,\n ) => ActionBuilder<{_input: TParams['_input']; _context: TContext}>;\n /**\n * Input validation for the action.\n */\n input: <TParser extends z.ZodType>(input: TParser) => ActionBuilder<{_input: TParser; _context: TParams['_context']}>;\n /**\n * Create an action.\n */\n action: <TOutput>(\n action: (params: {\n ctx: InferContextType<TParams['_context']>;\n input: InferParserType<TParams['_input'], 'out'>;\n }) => Promise<TOutput>,\n ) => (...[input]: OptionalizeUndefined<InferParserType<TParams['_input'], 'in'>>) => Promise<TOutput>;\n /**\n * Create an action for React `useFormState`\n */\n formAction: <TState>(\n action: (\n params: Prettify<\n {\n ctx: InferContextType<TParams['_context']>;\n prevState: any; // FIXME: This supposes to be `TState`, but we can't, as it will break the type.\n } & (\n | {input: InferParserType<TParams['_input'], 'out'>; formErrors?: undefined}\n | {\n input?: undefined;\n formErrors: z.ZodError<\n TParams['_input'] extends z.ZodEffects<infer T, unknown, unknown>\n ? InferParserType<T, 'in'>\n : InferParserType<TParams['_input'], 'in'>\n >;\n }\n )\n >,\n ) => Promise<TState>,\n ) => (prevState: TState, formData: FormData) => Promise<TState>;\n}\ntype AnyActionBuilder = ActionBuilder<any>;\n\ninterface ActionBuilderDef<TParams extends ActionParams<any>> {\n input: TParams['_input'];\n middleware: (() => Promise<TParams['_context']> | TParams['_context']) | undefined;\n}\ntype AnyActionBuilderDef = ActionBuilderDef<any>;\n\nconst createNewServerActionBuilder = (def: Partial<AnyActionBuilderDef>) => {\n return createServerActionBuilder(def);\n};\n\nconst createServerActionBuilder = (\n initDef: Partial<AnyActionBuilderDef> = {},\n): ActionBuilder<{\n _input: UnsetMarker;\n _context: UnsetMarker;\n}> => {\n const _def: ActionBuilderDef<{_input: z.ZodType | undefined; _context: undefined}> = {\n input: undefined,\n middleware: undefined,\n ...initDef,\n };\n return {\n middleware: (middleware) => createServerActionBuilder({..._def, middleware}) as AnyActionBuilder,\n input: (input) => createNewServerActionBuilder({..._def, input}) as AnyActionBuilder,\n action: (action) => {\n return async (input) => {\n const ctx = await _def.middleware?.();\n if (_def.input) {\n const result = _def.input.safeParse(input);\n if (!result.success) {\n throw fromZodError(result.error);\n }\n }\n return await action({ctx, input});\n };\n },\n formAction: (action) => {\n return async (prevState, formData) => {\n const ctx = await _def.middleware?.();\n if (_def.input) {\n const result = _def.input.safeParse(formData);\n if (!result.success) {\n return await action({ctx, prevState, formErrors: result.error});\n }\n return await action({ctx, prevState, input: result.data});\n }\n return await action({ctx, prevState, input: undefined});\n };\n },\n };\n};\n\n/**\n * Server action builder\n */\nexport const serverAct = createServerActionBuilder();\n","import * as zod from 'zod';\nimport { joinPath } from './utils/joinPath';\nimport { isNonEmptyArray } from './utils/NonEmptyArray';\nconst MAX_ISSUES_IN_MESSAGE = 99;\nconst ISSUE_SEPARATOR = '; ';\nconst UNION_SEPARATOR = ', or ';\nconst PREFIX = 'Validation error';\nconst PREFIX_SEPARATOR = ': ';\nexport class ValidationError extends Error {\n details;\n name;\n constructor(message, details = []) {\n super(message);\n this.details = details;\n this.name = 'ZodValidationError';\n }\n toString() {\n return this.message;\n }\n}\nfunction getMessageFromZodIssue(issue, issueSeparator, unionSeparator) {\n if (issue.code === 'invalid_union') {\n return issue.unionErrors\n .reduce((acc, zodError) => {\n const newIssues = zodError.issues\n .map((issue) => getMessageFromZodIssue(issue, issueSeparator, unionSeparator))\n .join(issueSeparator);\n if (!acc.includes(newIssues)) {\n acc.push(newIssues);\n }\n return acc;\n }, [])\n .join(unionSeparator);\n }\n if (isNonEmptyArray(issue.path)) {\n if (issue.path.length === 1) {\n const identifier = issue.path[0];\n if (typeof identifier === 'number') {\n return `${issue.message} at index ${identifier}`;\n }\n }\n return `${issue.message} at \"${joinPath(issue.path)}\"`;\n }\n return issue.message;\n}\nfunction conditionallyPrefixMessage(reason, prefix, prefixSeparator) {\n if (prefix !== null) {\n if (reason.length > 0) {\n return [prefix, reason].join(prefixSeparator);\n }\n return prefix;\n }\n if (reason.length > 0) {\n return reason;\n }\n return PREFIX;\n}\nexport function fromZodIssue(issue, options = {}) {\n const { issueSeparator = ISSUE_SEPARATOR, unionSeparator = UNION_SEPARATOR, prefixSeparator = PREFIX_SEPARATOR, prefix = PREFIX, } = options;\n const reason = getMessageFromZodIssue(issue, issueSeparator, unionSeparator);\n const message = conditionallyPrefixMessage(reason, prefix, prefixSeparator);\n return new ValidationError(message, [issue]);\n}\nexport function fromZodError(zodError, options = {}) {\n const { maxIssuesInMessage = MAX_ISSUES_IN_MESSAGE, issueSeparator = ISSUE_SEPARATOR, unionSeparator = UNION_SEPARATOR, prefixSeparator = PREFIX_SEPARATOR, prefix = PREFIX, } = options;\n const reason = zodError.errors\n .slice(0, maxIssuesInMessage)\n .map((issue) => getMessageFromZodIssue(issue, issueSeparator, unionSeparator))\n .join(issueSeparator);\n const message = conditionallyPrefixMessage(reason, prefix, prefixSeparator);\n return new ValidationError(message, zodError.errors);\n}\nexport const toValidationError = (options = {}) => (err) => {\n if (err instanceof zod.ZodError) {\n return fromZodError(err, options);\n }\n if (err instanceof Error) {\n return err;\n }\n return new Error('Unknown error');\n};\nexport function isValidationError(err) {\n return err instanceof ValidationError;\n}\nexport function isValidationErrorLike(err) {\n return err instanceof Error && err.name === 'ZodValidationError';\n}\nexport const errorMap = (issue, ctx) => {\n const error = fromZodIssue({\n ...issue,\n message: issue.message ?? ctx.defaultError,\n });\n return {\n message: error.message,\n };\n};\n","const identifierRegex = /[$_\\p{ID_Start}][$\\u200c\\u200d\\p{ID_Continue}]*/u;\nexport function joinPath(path) {\n if (path.length === 1) {\n return path[0].toString();\n }\n return path.reduce((acc, item) => {\n if (typeof item === 'number') {\n return acc + '[' + item.toString() + ']';\n }\n if (item.includes('\"')) {\n return acc + '[\"' + escapeQuotes(item) + '\"]';\n }\n if (!identifierRegex.test(item)) {\n return acc + '[\"' + item + '\"]';\n }\n const separator = acc.length === 0 ? '' : '.';\n return acc + separator + item;\n }, '');\n}\nfunction escapeQuotes(str) {\n return str.replace(/\"/g, '\\\\\"');\n}\n","export function isNonEmptyArray(value) {\n return value.length !== 0;\n}\n"],"mappings":"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","names":["issue"]}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/ValidationError.js","../../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/utils/joinPath.js","../../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/utils/NonEmptyArray.js","../src/index.ts"],"sourcesContent":["import * as zod from 'zod';\nimport { joinPath } from './utils/joinPath';\nimport { isNonEmptyArray } from './utils/NonEmptyArray';\nconst MAX_ISSUES_IN_MESSAGE = 99;\nconst ISSUE_SEPARATOR = '; ';\nconst UNION_SEPARATOR = ', or ';\nconst PREFIX = 'Validation error';\nconst PREFIX_SEPARATOR = ': ';\nexport class ValidationError extends Error {\n details;\n name;\n constructor(message, details = []) {\n super(message);\n this.details = details;\n this.name = 'ZodValidationError';\n }\n toString() {\n return this.message;\n }\n}\nfunction getMessageFromZodIssue(issue, issueSeparator, unionSeparator) {\n if (issue.code === 'invalid_union') {\n return issue.unionErrors\n .reduce((acc, zodError) => {\n const newIssues = zodError.issues\n .map((issue) => getMessageFromZodIssue(issue, issueSeparator, unionSeparator))\n .join(issueSeparator);\n if (!acc.includes(newIssues)) {\n acc.push(newIssues);\n }\n return acc;\n }, [])\n .join(unionSeparator);\n }\n if (isNonEmptyArray(issue.path)) {\n if (issue.path.length === 1) {\n const identifier = issue.path[0];\n if (typeof identifier === 'number') {\n return `${issue.message} at index ${identifier}`;\n }\n }\n return `${issue.message} at \"${joinPath(issue.path)}\"`;\n }\n return issue.message;\n}\nfunction conditionallyPrefixMessage(reason, prefix, prefixSeparator) {\n if (prefix !== null) {\n if (reason.length > 0) {\n return [prefix, reason].join(prefixSeparator);\n }\n return prefix;\n }\n if (reason.length > 0) {\n return reason;\n }\n return PREFIX;\n}\nexport function fromZodIssue(issue, options = {}) {\n const { issueSeparator = ISSUE_SEPARATOR, unionSeparator = UNION_SEPARATOR, prefixSeparator = PREFIX_SEPARATOR, prefix = PREFIX, } = options;\n const reason = getMessageFromZodIssue(issue, issueSeparator, unionSeparator);\n const message = conditionallyPrefixMessage(reason, prefix, prefixSeparator);\n return new ValidationError(message, [issue]);\n}\nexport function fromZodError(zodError, options = {}) {\n const { maxIssuesInMessage = MAX_ISSUES_IN_MESSAGE, issueSeparator = ISSUE_SEPARATOR, unionSeparator = UNION_SEPARATOR, prefixSeparator = PREFIX_SEPARATOR, prefix = PREFIX, } = options;\n const reason = zodError.errors\n .slice(0, maxIssuesInMessage)\n .map((issue) => getMessageFromZodIssue(issue, issueSeparator, unionSeparator))\n .join(issueSeparator);\n const message = conditionallyPrefixMessage(reason, prefix, prefixSeparator);\n return new ValidationError(message, zodError.errors);\n}\nexport const toValidationError = (options = {}) => (err) => {\n if (err instanceof zod.ZodError) {\n return fromZodError(err, options);\n }\n if (err instanceof Error) {\n return err;\n }\n return new Error('Unknown error');\n};\nexport function isValidationError(err) {\n return err instanceof ValidationError;\n}\nexport function isValidationErrorLike(err) {\n return err instanceof Error && err.name === 'ZodValidationError';\n}\nexport const errorMap = (issue, ctx) => {\n const error = fromZodIssue({\n ...issue,\n message: issue.message ?? ctx.defaultError,\n });\n return {\n message: error.message,\n };\n};\n","const identifierRegex = /[$_\\p{ID_Start}][$\\u200c\\u200d\\p{ID_Continue}]*/u;\nexport function joinPath(path) {\n if (path.length === 1) {\n return path[0].toString();\n }\n return path.reduce((acc, item) => {\n if (typeof item === 'number') {\n return acc + '[' + item.toString() + ']';\n }\n if (item.includes('\"')) {\n return acc + '[\"' + escapeQuotes(item) + '\"]';\n }\n if (!identifierRegex.test(item)) {\n return acc + '[\"' + item + '\"]';\n }\n const separator = acc.length === 0 ? '' : '.';\n return acc + separator + item;\n }, '');\n}\nfunction escapeQuotes(str) {\n return str.replace(/\"/g, '\\\\\"');\n}\n","export function isNonEmptyArray(value) {\n return value.length !== 0;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {type z} from 'zod';\nimport {fromZodError} from 'zod-validation-error';\n\ntype Prettify<T> = {\n [P in keyof T]: T[P];\n // eslint-disable-next-line @typescript-eslint/ban-types\n} & {};\n\nconst unsetMarker = Symbol('unsetMarker');\ntype UnsetMarker = typeof unsetMarker;\n\ntype OptionalizeUndefined<T> = undefined extends T ? [param?: T] : [param: T];\n\ntype InferParserType<TParser, TType extends 'in' | 'out'> = TParser extends UnsetMarker\n ? undefined\n : TParser extends z.ZodType\n ? TParser[TType extends 'in' ? '_input' : '_output']\n : never;\n\ntype InferContextType<T> = T extends UnsetMarker ? undefined : T;\n\ninterface ActionParams<TInput = unknown, TContext = unknown> {\n _input: TInput;\n _context: TContext;\n}\n\ninterface ActionBuilder<TParams extends ActionParams> {\n /**\n * Middleware allows you to run code before the action, its return value will pass as context to the action.\n */\n middleware: <TContext>(\n middleware: () => Promise<TContext> | TContext,\n ) => ActionBuilder<{_input: TParams['_input']; _context: TContext}>;\n /**\n * Input validation for the action.\n */\n input: <TParser extends z.ZodType>(input: TParser) => ActionBuilder<{_input: TParser; _context: TParams['_context']}>;\n /**\n * Create an action.\n */\n action: <TOutput>(\n action: (params: {\n ctx: InferContextType<TParams['_context']>;\n input: InferParserType<TParams['_input'], 'out'>;\n }) => Promise<TOutput>,\n ) => (...[input]: OptionalizeUndefined<InferParserType<TParams['_input'], 'in'>>) => Promise<TOutput>;\n /**\n * Create an action for React `useFormState`\n */\n formAction: <TState>(\n action: (\n params: Prettify<\n {\n ctx: InferContextType<TParams['_context']>;\n prevState: any; // FIXME: This supposes to be `TState`, but we can't, as it will break the type.\n } & (\n | {input: InferParserType<TParams['_input'], 'out'>; formErrors?: undefined}\n | {\n input?: undefined;\n formErrors: z.ZodError<\n TParams['_input'] extends z.ZodEffects<infer T, unknown, unknown>\n ? InferParserType<T, 'in'>\n : InferParserType<TParams['_input'], 'in'>\n >;\n }\n )\n >,\n ) => Promise<TState>,\n ) => (prevState: TState, formData: FormData) => Promise<TState>;\n}\ntype AnyActionBuilder = ActionBuilder<any>;\n\ninterface ActionBuilderDef<TParams extends ActionParams<any>> {\n input: TParams['_input'];\n middleware: (() => Promise<TParams['_context']> | TParams['_context']) | undefined;\n}\ntype AnyActionBuilderDef = ActionBuilderDef<any>;\n\nconst createNewServerActionBuilder = (def: Partial<AnyActionBuilderDef>) => {\n return createServerActionBuilder(def);\n};\n\nconst createServerActionBuilder = (\n initDef: Partial<AnyActionBuilderDef> = {},\n): ActionBuilder<{\n _input: UnsetMarker;\n _context: UnsetMarker;\n}> => {\n const _def: ActionBuilderDef<{_input: z.ZodType | undefined; _context: undefined}> = {\n input: undefined,\n middleware: undefined,\n ...initDef,\n };\n return {\n middleware: (middleware) => createServerActionBuilder({..._def, middleware}) as AnyActionBuilder,\n input: (input) => createNewServerActionBuilder({..._def, input}) as AnyActionBuilder,\n action: (action) => {\n return async (input) => {\n const ctx = await _def.middleware?.();\n if (_def.input) {\n const result = _def.input.safeParse(input);\n if (!result.success) {\n throw fromZodError(result.error);\n }\n }\n return await action({ctx, input});\n };\n },\n formAction: (action) => {\n return async (prevState, formData) => {\n const ctx = await _def.middleware?.();\n if (_def.input) {\n const result = _def.input.safeParse(formData);\n if (!result.success) {\n return await action({ctx, prevState, formErrors: result.error});\n }\n return await action({ctx, prevState, input: result.data});\n }\n return await action({ctx, prevState, input: undefined});\n };\n },\n };\n};\n\n/**\n * Server action builder\n */\nexport const serverAct = createServerActionBuilder();\n"],"mappings":"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","names":["issue"]}
|
package/src/index.test.ts
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import {test, expect, expectTypeOf, vi, beforeEach, describe} from 'vitest';
|
|
2
|
-
import {z} from 'zod';
|
|
3
|
-
import {zfd} from 'zod-form-data';
|
|
4
|
-
|
|
5
|
-
import {serverAct} from '.';
|
|
6
|
-
|
|
7
|
-
describe.concurrent('action', () => {
|
|
8
|
-
test('should able to create action without input', async () => {
|
|
9
|
-
const action = serverAct.action(async () => Promise.resolve('bar'));
|
|
10
|
-
|
|
11
|
-
expectTypeOf(action).parameter(0).toBeUndefined();
|
|
12
|
-
expectTypeOf(action).returns.resolves.toBeString();
|
|
13
|
-
await expect(action()).resolves.toBe('bar');
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('should able to create action with input', async () => {
|
|
17
|
-
const action = serverAct.input(z.string()).action(async () => Promise.resolve('bar'));
|
|
18
|
-
|
|
19
|
-
expectTypeOf(action).parameter(0).toBeString();
|
|
20
|
-
expectTypeOf(action).returns.resolves.toBeString();
|
|
21
|
-
await expect(action('foo')).resolves.toBe('bar');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('should throw error if the input is invalid', async () => {
|
|
25
|
-
const action = serverAct.input(z.string()).action(async () => Promise.resolve('bar'));
|
|
26
|
-
|
|
27
|
-
expectTypeOf(action).parameter(0).toBeString();
|
|
28
|
-
expectTypeOf(action).returns.resolves.toBeString();
|
|
29
|
-
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
31
|
-
// @ts-ignore
|
|
32
|
-
await expect(action(1)).rejects.toThrowError();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
describe('middleware should be called once', () => {
|
|
36
|
-
const middlewareSpy = vi.fn(() => {
|
|
37
|
-
return {prefix: 'best'};
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
vi.restoreAllMocks();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('without input', async () => {
|
|
45
|
-
const action = serverAct.middleware(middlewareSpy).action(async ({ctx}) => Promise.resolve(`${ctx.prefix}-bar`));
|
|
46
|
-
|
|
47
|
-
expectTypeOf(action).returns.resolves.toBeString();
|
|
48
|
-
await expect(action()).resolves.toBe('best-bar');
|
|
49
|
-
expect(middlewareSpy).toBeCalledTimes(1);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('with input', async () => {
|
|
53
|
-
const actionWithInput = serverAct
|
|
54
|
-
.middleware(middlewareSpy)
|
|
55
|
-
.input(z.string())
|
|
56
|
-
.action(async ({ctx, input}) => Promise.resolve(`${ctx.prefix}-${input}-bar`));
|
|
57
|
-
|
|
58
|
-
expectTypeOf(actionWithInput).parameter(0).toBeString();
|
|
59
|
-
expectTypeOf(actionWithInput).returns.resolves.toBeString();
|
|
60
|
-
await expect(actionWithInput('foo')).resolves.toBe('best-foo-bar');
|
|
61
|
-
expect(middlewareSpy).toBeCalledTimes(1);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe.concurrent('formAction', () => {
|
|
67
|
-
test('should able to create form action without input', async () => {
|
|
68
|
-
const action = serverAct.formAction(async () => Promise.resolve('bar'));
|
|
69
|
-
|
|
70
|
-
expectTypeOf(action).parameter(0).toBeString();
|
|
71
|
-
expectTypeOf(action).parameter(1).toEqualTypeOf<FormData>();
|
|
72
|
-
expectTypeOf(action).returns.resolves.toBeString();
|
|
73
|
-
|
|
74
|
-
const formData = new FormData();
|
|
75
|
-
await expect(action('foo', formData)).resolves.toMatchObject('bar');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('should able to create form action with input', async () => {
|
|
79
|
-
const action = serverAct.input(zfd.formData({foo: zfd.text()})).formAction(async () => Promise.resolve('bar'));
|
|
80
|
-
|
|
81
|
-
expectTypeOf(action).parameter(0).toBeString();
|
|
82
|
-
expectTypeOf(action).parameter(1).toEqualTypeOf<FormData>();
|
|
83
|
-
expectTypeOf(action).returns.resolves.toBeString();
|
|
84
|
-
|
|
85
|
-
const formData = new FormData();
|
|
86
|
-
formData.append('foo', 'bar');
|
|
87
|
-
await expect(action('foo', formData)).resolves.toMatchObject('bar');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test('should return form errors if the input is invalid', async () => {
|
|
91
|
-
const action = serverAct
|
|
92
|
-
.input(zfd.formData({foo: zfd.text(z.string({required_error: 'Required'}))}))
|
|
93
|
-
.formAction(async ({formErrors}) => {
|
|
94
|
-
if (formErrors) {
|
|
95
|
-
return formErrors;
|
|
96
|
-
}
|
|
97
|
-
return Promise.resolve('bar');
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
expectTypeOf(action).parameter(0).toMatchTypeOf<string | z.ZodError<{foo: string}>>();
|
|
101
|
-
expectTypeOf(action).parameter(1).toEqualTypeOf<FormData>();
|
|
102
|
-
|
|
103
|
-
const formData = new FormData();
|
|
104
|
-
formData.append('bar', 'foo');
|
|
105
|
-
|
|
106
|
-
const result = await action('foo', formData);
|
|
107
|
-
expect(result).toBeInstanceOf(z.ZodError);
|
|
108
|
-
expect(result).toHaveProperty('formErrors.fieldErrors', {foo: ['Required']});
|
|
109
|
-
});
|
|
110
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
import {type z} from 'zod';
|
|
4
|
-
import {fromZodError} from 'zod-validation-error';
|
|
5
|
-
|
|
6
|
-
type Prettify<T> = {
|
|
7
|
-
[P in keyof T]: T[P];
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
9
|
-
} & {};
|
|
10
|
-
|
|
11
|
-
const unsetMarker = Symbol('unsetMarker');
|
|
12
|
-
type UnsetMarker = typeof unsetMarker;
|
|
13
|
-
|
|
14
|
-
type OptionalizeUndefined<T> = undefined extends T ? [param?: T] : [param: T];
|
|
15
|
-
|
|
16
|
-
type InferParserType<TParser, TType extends 'in' | 'out'> = TParser extends UnsetMarker
|
|
17
|
-
? undefined
|
|
18
|
-
: TParser extends z.ZodType
|
|
19
|
-
? TParser[TType extends 'in' ? '_input' : '_output']
|
|
20
|
-
: never;
|
|
21
|
-
|
|
22
|
-
type InferContextType<T> = T extends UnsetMarker ? undefined : T;
|
|
23
|
-
|
|
24
|
-
interface ActionParams<TInput = unknown, TContext = unknown> {
|
|
25
|
-
_input: TInput;
|
|
26
|
-
_context: TContext;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface ActionBuilder<TParams extends ActionParams> {
|
|
30
|
-
/**
|
|
31
|
-
* Middleware allows you to run code before the action, its return value will pass as context to the action.
|
|
32
|
-
*/
|
|
33
|
-
middleware: <TContext>(
|
|
34
|
-
middleware: () => Promise<TContext> | TContext,
|
|
35
|
-
) => ActionBuilder<{_input: TParams['_input']; _context: TContext}>;
|
|
36
|
-
/**
|
|
37
|
-
* Input validation for the action.
|
|
38
|
-
*/
|
|
39
|
-
input: <TParser extends z.ZodType>(input: TParser) => ActionBuilder<{_input: TParser; _context: TParams['_context']}>;
|
|
40
|
-
/**
|
|
41
|
-
* Create an action.
|
|
42
|
-
*/
|
|
43
|
-
action: <TOutput>(
|
|
44
|
-
action: (params: {
|
|
45
|
-
ctx: InferContextType<TParams['_context']>;
|
|
46
|
-
input: InferParserType<TParams['_input'], 'out'>;
|
|
47
|
-
}) => Promise<TOutput>,
|
|
48
|
-
) => (...[input]: OptionalizeUndefined<InferParserType<TParams['_input'], 'in'>>) => Promise<TOutput>;
|
|
49
|
-
/**
|
|
50
|
-
* Create an action for React `useFormState`
|
|
51
|
-
*/
|
|
52
|
-
formAction: <TState>(
|
|
53
|
-
action: (
|
|
54
|
-
params: Prettify<
|
|
55
|
-
{
|
|
56
|
-
ctx: InferContextType<TParams['_context']>;
|
|
57
|
-
prevState: any; // FIXME: This supposes to be `TState`, but we can't, as it will break the type.
|
|
58
|
-
} & (
|
|
59
|
-
| {input: InferParserType<TParams['_input'], 'out'>; formErrors?: undefined}
|
|
60
|
-
| {
|
|
61
|
-
input?: undefined;
|
|
62
|
-
formErrors: z.ZodError<
|
|
63
|
-
TParams['_input'] extends z.ZodEffects<infer T, unknown, unknown>
|
|
64
|
-
? InferParserType<T, 'in'>
|
|
65
|
-
: InferParserType<TParams['_input'], 'in'>
|
|
66
|
-
>;
|
|
67
|
-
}
|
|
68
|
-
)
|
|
69
|
-
>,
|
|
70
|
-
) => Promise<TState>,
|
|
71
|
-
) => (prevState: TState, formData: FormData) => Promise<TState>;
|
|
72
|
-
}
|
|
73
|
-
type AnyActionBuilder = ActionBuilder<any>;
|
|
74
|
-
|
|
75
|
-
interface ActionBuilderDef<TParams extends ActionParams<any>> {
|
|
76
|
-
input: TParams['_input'];
|
|
77
|
-
middleware: (() => Promise<TParams['_context']> | TParams['_context']) | undefined;
|
|
78
|
-
}
|
|
79
|
-
type AnyActionBuilderDef = ActionBuilderDef<any>;
|
|
80
|
-
|
|
81
|
-
const createNewServerActionBuilder = (def: Partial<AnyActionBuilderDef>) => {
|
|
82
|
-
return createServerActionBuilder(def);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const createServerActionBuilder = (
|
|
86
|
-
initDef: Partial<AnyActionBuilderDef> = {},
|
|
87
|
-
): ActionBuilder<{
|
|
88
|
-
_input: UnsetMarker;
|
|
89
|
-
_context: UnsetMarker;
|
|
90
|
-
}> => {
|
|
91
|
-
const _def: ActionBuilderDef<{_input: z.ZodType | undefined; _context: undefined}> = {
|
|
92
|
-
input: undefined,
|
|
93
|
-
middleware: undefined,
|
|
94
|
-
...initDef,
|
|
95
|
-
};
|
|
96
|
-
return {
|
|
97
|
-
middleware: (middleware) => createServerActionBuilder({..._def, middleware}) as AnyActionBuilder,
|
|
98
|
-
input: (input) => createNewServerActionBuilder({..._def, input}) as AnyActionBuilder,
|
|
99
|
-
action: (action) => {
|
|
100
|
-
return async (input) => {
|
|
101
|
-
const ctx = await _def.middleware?.();
|
|
102
|
-
if (_def.input) {
|
|
103
|
-
const result = _def.input.safeParse(input);
|
|
104
|
-
if (!result.success) {
|
|
105
|
-
throw fromZodError(result.error);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return await action({ctx, input});
|
|
109
|
-
};
|
|
110
|
-
},
|
|
111
|
-
formAction: (action) => {
|
|
112
|
-
return async (prevState, formData) => {
|
|
113
|
-
const ctx = await _def.middleware?.();
|
|
114
|
-
if (_def.input) {
|
|
115
|
-
const result = _def.input.safeParse(formData);
|
|
116
|
-
if (!result.success) {
|
|
117
|
-
return await action({ctx, prevState, formErrors: result.error});
|
|
118
|
-
}
|
|
119
|
-
return await action({ctx, prevState, input: result.data});
|
|
120
|
-
}
|
|
121
|
-
return await action({ctx, prevState, input: undefined});
|
|
122
|
-
};
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Server action builder
|
|
129
|
-
*/
|
|
130
|
-
export const serverAct = createServerActionBuilder();
|
package/tsconfig.json
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
-
"display": "Strictest",
|
|
4
|
-
"_version": "2.0.0",
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"lib": [
|
|
7
|
-
"ES2020",
|
|
8
|
-
"DOM",
|
|
9
|
-
"DOM.Iterable"
|
|
10
|
-
],
|
|
11
|
-
"module": "NodeNext",
|
|
12
|
-
"moduleResolution": "NodeNext",
|
|
13
|
-
"outDir": "./dist",
|
|
14
|
-
"strict": true,
|
|
15
|
-
"allowUnusedLabels": false,
|
|
16
|
-
"allowUnreachableCode": false,
|
|
17
|
-
"exactOptionalPropertyTypes": true,
|
|
18
|
-
"noFallthroughCasesInSwitch": true,
|
|
19
|
-
"noImplicitOverride": true,
|
|
20
|
-
"noImplicitReturns": true,
|
|
21
|
-
"noPropertyAccessFromIndexSignature": true,
|
|
22
|
-
"noUncheckedIndexedAccess": true,
|
|
23
|
-
"noUnusedLocals": true,
|
|
24
|
-
"noUnusedParameters": true,
|
|
25
|
-
"checkJs": true,
|
|
26
|
-
"esModuleInterop": true,
|
|
27
|
-
"skipLibCheck": true,
|
|
28
|
-
"forceConsistentCasingInFileNames": true
|
|
29
|
-
}
|
|
30
|
-
}
|