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 CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/server-act.svg)](https://badge.fury.io/js/server-act)
4
4
 
5
- A simple React server action builder that provides input validation with zod.
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 { z } from 'zod';
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", TUnwrapEffects extends true | false> = T extends z.ZodEffects<infer InnerType, infer Output, infer Input> ? TUnwrapEffects extends true ? InnerType[TType extends "in" ? "_input" : "_output"] : TType extends "in" ? Input : Output : T extends z.ZodType ? T[TType extends "in" ? "_input" : "_output"] : never;
11
- type InferInputType<T, TType extends "in" | "out", TUnwrapEffects extends true | false = true> = T extends UnsetMarker ? undefined : InferParserType<T, TType, TUnwrapEffects>;
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 z.ZodType>(input: ((params: {
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"> | InferInputType<TParams["_input"], "in", false>) => Promise<TOutput>>;
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: z.ZodError<InferInputType<TParams["_input"], "in">>;
54
- })>) => Promise<TState>) => (prevState: TState | TPrevState, formData: InferInputType<TParams["_input"], "in"> | InferInputType<TParams["_input"], "in", false>) => Promise<TState | TPrevState>;
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 { z } from 'zod';
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", TUnwrapEffects extends true | false> = T extends z.ZodEffects<infer InnerType, infer Output, infer Input> ? TUnwrapEffects extends true ? InnerType[TType extends "in" ? "_input" : "_output"] : TType extends "in" ? Input : Output : T extends z.ZodType ? T[TType extends "in" ? "_input" : "_output"] : never;
11
- type InferInputType<T, TType extends "in" | "out", TUnwrapEffects extends true | false = true> = T extends UnsetMarker ? undefined : InferParserType<T, TType, TUnwrapEffects>;
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 z.ZodType>(input: ((params: {
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"> | InferInputType<TParams["_input"], "in", false>) => Promise<TOutput>>;
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: z.ZodError<InferInputType<TParams["_input"], "in">>;
54
- })>) => Promise<TState>) => (prevState: TState | TPrevState, formData: InferInputType<TParams["_input"], "in"> | InferInputType<TParams["_input"], "in", false>) => Promise<TState | TPrevState>;
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.safeParseAsync(input);
70
- if (!result.success) {
71
- console.error("❌ Input validation error:", result.error.errors);
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.data
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.safeParseAsync(formData);
94
- if (!result.success) {
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.error
164
+ formErrors: getFormErrors(result.issues)
100
165
  });
101
166
  }
102
167
  return yield action({
103
168
  ctx,
104
169
  prevState,
105
170
  formData,
106
- input: result.data
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.safeParseAsync(input);
68
- if (!result.success) {
69
- console.error("❌ Input validation error:", result.error.errors);
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.data
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.safeParseAsync(formData);
92
- if (!result.success) {
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.error
162
+ formErrors: getFormErrors(result.issues)
98
163
  });
99
164
  }
100
165
  return yield action({
101
166
  ctx,
102
167
  prevState,
103
168
  formData,
104
- input: result.data
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.4.0",
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
- "devDependencies": {
47
- "bunchee": "^5.6.0",
48
- "typescript": "^5.6.3",
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
- "zod": "^3.22.2"
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",