server-act 0.0.6 → 0.0.8

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.
@@ -1,21 +1,22 @@
1
1
 
2
- > server-act@0.0.6 build /home/runner/work/server-act/server-act/packages/server-act
2
+ > server-act@0.0.8 build /home/runner/work/server-act/server-act/packages/server-act
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: ./src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
- CLI tsup v6.7.0
7
+ CLI tsup v7.2.0
8
8
  CLI Using tsup config: /home/runner/work/server-act/server-act/packages/server-act/tsup.config.ts
9
- CLI Target: node14
9
+ CLI Target: node16
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- ESM dist/index.mjs 3.57 KB
14
- ESM dist/index.mjs.map 8.65 KB
15
- ESM ⚡️ Build success in 24ms
16
- CJS dist/index.js 5.16 KB
17
- CJS dist/index.js.map 8.70 KB
18
- CJS ⚡️ Build success in 24ms
13
+ ESM dist/index.mjs 4.63 KB
14
+ ESM dist/index.mjs.map 11.87 KB
15
+ ESM ⚡️ Build success in 43ms
16
+ CJS dist/index.js 6.22 KB
17
+ CJS dist/index.js.map 11.92 KB
18
+ CJS ⚡️ Build success in 43ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 644ms
21
- DTS dist/index.d.ts 1.54 KB
20
+ DTS ⚡️ Build success in 1092ms
21
+ DTS dist/index.d.mts 2.12 KB
22
+ DTS dist/index.d.ts 2.12 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # server-act
2
2
 
3
+ ## 0.0.8
4
+
5
+ ### Patch Changes
6
+
7
+ - 566261e: Change form action error to ZodError
8
+ - ead7149: Prettify form action params type
9
+
10
+ ## 0.0.7
11
+
12
+ ### Patch Changes
13
+
14
+ - 50e2853: New experimental form action
15
+
3
16
  ## 0.0.6
4
17
 
5
18
  ### Patch Changes
package/README.md CHANGED
@@ -25,7 +25,7 @@ pnpm add server-act zod
25
25
 
26
26
  import { serverAct } from "server-act";
27
27
 
28
- const sayHelloAction = serverAct
28
+ export const sayHelloAction = serverAct
29
29
  .input(
30
30
  z.object({
31
31
  name: z.string(),
@@ -64,7 +64,7 @@ export const ClientComponent = () => {
64
64
 
65
65
  import { serverAct } from "server-act";
66
66
 
67
- const sayHelloAction = serverAct
67
+ export const sayHelloAction = serverAct
68
68
  .middleware(() => {
69
69
  const userId = "...";
70
70
  return { userId };
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+
3
+ type Prettify<T> = {
4
+ [P in keyof T]: T[P];
5
+ } & {};
6
+ declare const unsetMarker: unique symbol;
7
+ type UnsetMarker = typeof unsetMarker;
8
+ type OptionalizeUndefined<T> = undefined extends T ? [param?: T] : [param: T];
9
+ type InferParserType<TParser, TType extends 'in' | 'out'> = TParser extends UnsetMarker ? undefined : TParser extends z.ZodType ? TParser[TType extends 'in' ? '_input' : '_output'] : never;
10
+ type InferContextType<T> = T extends UnsetMarker ? undefined : T;
11
+ interface ActionParams<TInput = unknown, TContext = unknown> {
12
+ _input: TInput;
13
+ _context: TContext;
14
+ }
15
+ interface ActionBuilder<TParams extends ActionParams> {
16
+ /**
17
+ * Middleware allows you to run code before the action, its return value will pass as context to the action.
18
+ */
19
+ middleware: <TContext>(middleware: () => Promise<TContext> | TContext) => ActionBuilder<{
20
+ _input: TParams['_input'];
21
+ _context: TContext;
22
+ }>;
23
+ /**
24
+ * Input validation for the action.
25
+ */
26
+ input: <TParser extends z.ZodType>(input: TParser) => ActionBuilder<{
27
+ _input: TParser;
28
+ _context: TParams['_context'];
29
+ }>;
30
+ /**
31
+ * Create an action.
32
+ */
33
+ action: <TOutput>(action: (params: {
34
+ ctx: InferContextType<TParams['_context']>;
35
+ input: InferParserType<TParams['_input'], 'out'>;
36
+ }) => Promise<TOutput>) => (...[input]: OptionalizeUndefined<InferParserType<TParams['_input'], 'in'>>) => Promise<TOutput>;
37
+ /**
38
+ * ***Experimental*** - Create an action for React `useFormState`
39
+ */
40
+ experimental_formAction: <TState>(action: (params: Prettify<{
41
+ ctx: InferContextType<TParams['_context']>;
42
+ prevState: any;
43
+ } & ({
44
+ input: InferParserType<TParams['_input'], 'out'>;
45
+ formErrors?: undefined;
46
+ } | {
47
+ input?: undefined;
48
+ formErrors: z.ZodError<InferParserType<TParams['_input'], 'in'>>;
49
+ })>) => Promise<TState>) => (prevState: TState, formData: FormData) => Promise<TState>;
50
+ }
51
+ /**
52
+ * Server action builder
53
+ */
54
+ declare const serverAct: ActionBuilder<{
55
+ _input: UnsetMarker;
56
+ _context: UnsetMarker;
57
+ }>;
58
+
59
+ export { serverAct };
package/dist/index.d.ts CHANGED
@@ -1,15 +1,18 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ type Prettify<T> = {
4
+ [P in keyof T]: T[P];
5
+ } & {};
3
6
  declare const unsetMarker: unique symbol;
4
7
  type UnsetMarker = typeof unsetMarker;
5
8
  type OptionalizeUndefined<T> = undefined extends T ? [param?: T] : [param: T];
6
9
  type InferParserType<TParser, TType extends 'in' | 'out'> = TParser extends UnsetMarker ? undefined : TParser extends z.ZodType ? TParser[TType extends 'in' ? '_input' : '_output'] : never;
7
10
  type InferContextType<T> = T extends UnsetMarker ? undefined : T;
8
- type ActionParams<TInput = unknown, TContext = unknown> = {
11
+ interface ActionParams<TInput = unknown, TContext = unknown> {
9
12
  _input: TInput;
10
13
  _context: TContext;
11
- };
12
- type ActionBuilder<TParams extends ActionParams> = {
14
+ }
15
+ interface ActionBuilder<TParams extends ActionParams> {
13
16
  /**
14
17
  * Middleware allows you to run code before the action, its return value will pass as context to the action.
15
18
  */
@@ -31,7 +34,20 @@ type ActionBuilder<TParams extends ActionParams> = {
31
34
  ctx: InferContextType<TParams['_context']>;
32
35
  input: InferParserType<TParams['_input'], 'out'>;
33
36
  }) => Promise<TOutput>) => (...[input]: OptionalizeUndefined<InferParserType<TParams['_input'], 'in'>>) => Promise<TOutput>;
34
- };
37
+ /**
38
+ * ***Experimental*** - Create an action for React `useFormState`
39
+ */
40
+ experimental_formAction: <TState>(action: (params: Prettify<{
41
+ ctx: InferContextType<TParams['_context']>;
42
+ prevState: any;
43
+ } & ({
44
+ input: InferParserType<TParams['_input'], 'out'>;
45
+ formErrors?: undefined;
46
+ } | {
47
+ input?: undefined;
48
+ formErrors: z.ZodError<InferParserType<TParams['_input'], 'in'>>;
49
+ })>) => Promise<TState>) => (prevState: TState, formData: FormData) => Promise<TState>;
50
+ }
35
51
  /**
36
52
  * Server action builder
37
53
  */
package/dist/index.js CHANGED
@@ -34,10 +34,10 @@ __export(src_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(src_exports);
36
36
 
37
- // ../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/ValidationError.js
37
+ // ../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/ValidationError.js
38
38
  var zod = __toESM(require("zod"));
39
39
 
40
- // ../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/utils/joinPath.js
40
+ // ../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/utils/joinPath.js
41
41
  var identifierRegex = /[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*/u;
42
42
  function joinPath(path) {
43
43
  if (path.length === 1) {
@@ -61,12 +61,17 @@ function escapeQuotes(str) {
61
61
  return str.replace(/"/g, '\\"');
62
62
  }
63
63
 
64
- // ../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/utils/NonEmptyArray.js
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
65
  function isNonEmptyArray(value) {
66
66
  return value.length !== 0;
67
67
  }
68
68
 
69
- // ../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/ValidationError.js
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 = ": ";
70
75
  var ValidationError = class extends Error {
71
76
  details;
72
77
  name;
@@ -79,10 +84,10 @@ var ValidationError = class extends Error {
79
84
  return this.message;
80
85
  }
81
86
  };
82
- function fromZodIssue(issue, issueSeparator, unionSeparator) {
87
+ function getMessageFromZodIssue(issue, issueSeparator, unionSeparator) {
83
88
  if (issue.code === "invalid_union") {
84
89
  return issue.unionErrors.reduce((acc, zodError) => {
85
- const newIssues = zodError.issues.map((issue2) => fromZodIssue(issue2, issueSeparator, unionSeparator)).join(issueSeparator);
90
+ const newIssues = zodError.issues.map((issue2) => getMessageFromZodIssue(issue2, issueSeparator, unionSeparator)).join(issueSeparator);
86
91
  if (!acc.includes(newIssues)) {
87
92
  acc.push(newIssues);
88
93
  }
@@ -100,10 +105,22 @@ function fromZodIssue(issue, issueSeparator, unionSeparator) {
100
105
  }
101
106
  return issue.message;
102
107
  }
108
+ function conditionallyPrefixMessage(reason, prefix, prefixSeparator) {
109
+ if (prefix !== null) {
110
+ if (reason.length > 0) {
111
+ return [prefix, reason].join(prefixSeparator);
112
+ }
113
+ return prefix;
114
+ }
115
+ if (reason.length > 0) {
116
+ return reason;
117
+ }
118
+ return PREFIX;
119
+ }
103
120
  function fromZodError(zodError, options = {}) {
104
- const { maxIssuesInMessage = 99, issueSeparator = "; ", unionSeparator = ", or ", prefixSeparator = ": ", prefix = "Validation error" } = options;
105
- const reason = zodError.errors.slice(0, maxIssuesInMessage).map((issue) => fromZodIssue(issue, issueSeparator, unionSeparator)).join(issueSeparator);
106
- const message = reason ? [prefix, reason].join(prefixSeparator) : prefix;
121
+ const { maxIssuesInMessage = MAX_ISSUES_IN_MESSAGE, issueSeparator = ISSUE_SEPARATOR, unionSeparator = UNION_SEPARATOR, prefixSeparator = PREFIX_SEPARATOR, prefix = PREFIX } = options;
122
+ const reason = zodError.errors.slice(0, maxIssuesInMessage).map((issue) => getMessageFromZodIssue(issue, issueSeparator, unionSeparator)).join(issueSeparator);
123
+ const message = conditionallyPrefixMessage(reason, prefix, prefixSeparator);
107
124
  return new ValidationError(message, zodError.errors);
108
125
  }
109
126
 
@@ -133,6 +150,20 @@ var createServerActionBuilder = (initDef = {}) => {
133
150
  }
134
151
  return await action({ ctx, input });
135
152
  };
153
+ },
154
+ experimental_formAction: (action) => {
155
+ return async (prevState, formData) => {
156
+ var _a;
157
+ const ctx = await ((_a = _def.middleware) == null ? void 0 : _a.call(_def));
158
+ if (_def.input) {
159
+ const result = _def.input.safeParse(Object.fromEntries(formData.entries()));
160
+ if (!result.success) {
161
+ return await action({ ctx, prevState, formErrors: result.error });
162
+ }
163
+ return await action({ ctx, prevState, input: result.data });
164
+ }
165
+ return await action({ ctx, prevState, input: void 0 });
166
+ };
136
167
  }
137
168
  };
138
169
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/ValidationError.js","../../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/utils/joinPath.js","../../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/utils/NonEmptyArray.js"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {type z} from 'zod';\nimport {fromZodError} from 'zod-validation-error';\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\ntype ActionParams<TInput = unknown, TContext = unknown> = {\n _input: TInput;\n _context: TContext;\n};\n\ntype 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};\ntype AnyActionBuilder = ActionBuilder<any>;\n\ntype 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 };\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';\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 fromZodIssue(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) => fromZodIssue(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}\nexport function fromZodError(zodError, options = {}) {\n const { maxIssuesInMessage = 99, issueSeparator = '; ', unionSeparator = ', or ', prefixSeparator = ': ', prefix = 'Validation error', } = options;\n const reason = zodError.errors\n .slice(0, maxIssuesInMessage)\n .map((issue) => fromZodIssue(issue, issueSeparator, unionSeparator))\n .join(issueSeparator);\n const message = reason ? [prefix, reason].join(prefixSeparator) : prefix;\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}\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"]}
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 * ***Experimental*** - Create an action for React `useFormState`\n */\n experimental_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 | {input?: undefined; formErrors: z.ZodError<InferParserType<TParams['_input'], 'in'>>}\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 experimental_formAction: (action) => {\n return async (prevState, formData) => {\n const ctx = await _def.middleware?.();\n if (_def.input) {\n const result = _def.input.safeParse(Object.fromEntries(formData.entries()));\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 CHANGED
@@ -1,7 +1,7 @@
1
- // ../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/ValidationError.js
1
+ // ../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/ValidationError.js
2
2
  import * as zod from "zod";
3
3
 
4
- // ../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/utils/joinPath.js
4
+ // ../../node_modules/.pnpm/zod-validation-error@1.5.0_zod@3.22.2/node_modules/zod-validation-error/dist/esm/utils/joinPath.js
5
5
  var identifierRegex = /[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*/u;
6
6
  function joinPath(path) {
7
7
  if (path.length === 1) {
@@ -25,12 +25,17 @@ function escapeQuotes(str) {
25
25
  return str.replace(/"/g, '\\"');
26
26
  }
27
27
 
28
- // ../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/utils/NonEmptyArray.js
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
29
  function isNonEmptyArray(value) {
30
30
  return value.length !== 0;
31
31
  }
32
32
 
33
- // ../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/ValidationError.js
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 = ": ";
34
39
  var ValidationError = class extends Error {
35
40
  details;
36
41
  name;
@@ -43,10 +48,10 @@ var ValidationError = class extends Error {
43
48
  return this.message;
44
49
  }
45
50
  };
46
- function fromZodIssue(issue, issueSeparator, unionSeparator) {
51
+ function getMessageFromZodIssue(issue, issueSeparator, unionSeparator) {
47
52
  if (issue.code === "invalid_union") {
48
53
  return issue.unionErrors.reduce((acc, zodError) => {
49
- const newIssues = zodError.issues.map((issue2) => fromZodIssue(issue2, issueSeparator, unionSeparator)).join(issueSeparator);
54
+ const newIssues = zodError.issues.map((issue2) => getMessageFromZodIssue(issue2, issueSeparator, unionSeparator)).join(issueSeparator);
50
55
  if (!acc.includes(newIssues)) {
51
56
  acc.push(newIssues);
52
57
  }
@@ -64,10 +69,22 @@ function fromZodIssue(issue, issueSeparator, unionSeparator) {
64
69
  }
65
70
  return issue.message;
66
71
  }
72
+ function conditionallyPrefixMessage(reason, prefix, prefixSeparator) {
73
+ if (prefix !== null) {
74
+ if (reason.length > 0) {
75
+ return [prefix, reason].join(prefixSeparator);
76
+ }
77
+ return prefix;
78
+ }
79
+ if (reason.length > 0) {
80
+ return reason;
81
+ }
82
+ return PREFIX;
83
+ }
67
84
  function fromZodError(zodError, options = {}) {
68
- const { maxIssuesInMessage = 99, issueSeparator = "; ", unionSeparator = ", or ", prefixSeparator = ": ", prefix = "Validation error" } = options;
69
- const reason = zodError.errors.slice(0, maxIssuesInMessage).map((issue) => fromZodIssue(issue, issueSeparator, unionSeparator)).join(issueSeparator);
70
- const message = reason ? [prefix, reason].join(prefixSeparator) : prefix;
85
+ const { maxIssuesInMessage = MAX_ISSUES_IN_MESSAGE, issueSeparator = ISSUE_SEPARATOR, unionSeparator = UNION_SEPARATOR, prefixSeparator = PREFIX_SEPARATOR, prefix = PREFIX } = options;
86
+ const reason = zodError.errors.slice(0, maxIssuesInMessage).map((issue) => getMessageFromZodIssue(issue, issueSeparator, unionSeparator)).join(issueSeparator);
87
+ const message = conditionallyPrefixMessage(reason, prefix, prefixSeparator);
71
88
  return new ValidationError(message, zodError.errors);
72
89
  }
73
90
 
@@ -97,6 +114,20 @@ var createServerActionBuilder = (initDef = {}) => {
97
114
  }
98
115
  return await action({ ctx, input });
99
116
  };
117
+ },
118
+ experimental_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(Object.fromEntries(formData.entries()));
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
+ };
100
131
  }
101
132
  };
102
133
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/ValidationError.js","../../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/node_modules/zod-validation-error/dist/esm/utils/joinPath.js","../../../node_modules/.pnpm/zod-validation-error@1.3.0_zod@3.21.4/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';\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 fromZodIssue(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) => fromZodIssue(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}\nexport function fromZodError(zodError, options = {}) {\n const { maxIssuesInMessage = 99, issueSeparator = '; ', unionSeparator = ', or ', prefixSeparator = ': ', prefix = 'Validation error', } = options;\n const reason = zodError.errors\n .slice(0, maxIssuesInMessage)\n .map((issue) => fromZodIssue(issue, issueSeparator, unionSeparator))\n .join(issueSeparator);\n const message = reason ? [prefix, reason].join(prefixSeparator) : prefix;\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}\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-explicit-any */\nimport {type z} from 'zod';\nimport {fromZodError} from 'zod-validation-error';\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\ntype ActionParams<TInput = unknown, TContext = unknown> = {\n _input: TInput;\n _context: TContext;\n};\n\ntype 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};\ntype AnyActionBuilder = ActionBuilder<any>;\n\ntype 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 };\n};\n\n/**\n * Server action builder\n */\nexport const serverAct = createServerActionBuilder();\n"],"mappings":"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","names":["issue"]}
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 * ***Experimental*** - Create an action for React `useFormState`\n */\n experimental_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 | {input?: undefined; formErrors: z.ZodError<InferParserType<TParams['_input'], 'in'>>}\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 experimental_formAction: (action) => {\n return async (prevState, formData) => {\n const ctx = await _def.middleware?.();\n if (_def.input) {\n const result = _def.input.safeParse(Object.fromEntries(formData.entries()));\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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "server-act",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "homepage": "https://github.com/chungweileong94/server-act#readme",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,17 +34,17 @@
34
34
  "author": "chungweileong94",
35
35
  "license": "MIT",
36
36
  "devDependencies": {
37
- "eslint": "^8.39.0",
38
- "eslint-config-whiteroom": "^3.1.0",
39
- "prettier": "^2.8.8",
40
- "tsup": "^6.7.0",
41
- "typescript": "^5.0.4",
42
- "zod": "^3.21.4",
43
- "zod-validation-error": "^1.3.0"
37
+ "eslint": "^8.49.0",
38
+ "eslint-config-whiteroom": "^3.3.0",
39
+ "prettier": "^3.0.3",
40
+ "tsup": "^7.2.0",
41
+ "typescript": "^5.2.2",
42
+ "zod": "^3.22.2",
43
+ "zod-validation-error": "^1.5.0"
44
44
  },
45
45
  "peerDependencies": {
46
- "typescript": "^5.0.4",
47
- "zod": "^3.21.4"
46
+ "typescript": "^5.2.2",
47
+ "zod": "^3.22.2"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "tsup",
package/src/index.test.ts CHANGED
@@ -3,59 +3,109 @@ import z from 'zod';
3
3
 
4
4
  import {serverAct} from '.';
5
5
 
6
- test('should able to create action without input', async () => {
7
- const action = serverAct.action(async () => Promise.resolve('bar'));
6
+ describe.concurrent('action', () => {
7
+ test('should able to create action without input', async () => {
8
+ const action = serverAct.action(async () => Promise.resolve('bar'));
8
9
 
9
- expectTypeOf(action).parameter(0).toBeUndefined();
10
- expectTypeOf(action).returns.resolves.toBeString();
11
- await expect(action()).resolves.toBe('bar');
12
- });
10
+ expectTypeOf(action).parameter(0).toBeUndefined();
11
+ expectTypeOf(action).returns.resolves.toBeString();
12
+ await expect(action()).resolves.toBe('bar');
13
+ });
13
14
 
14
- test('should able to create action with input', async () => {
15
- const action = serverAct.input(z.string()).action(async () => Promise.resolve('bar'));
15
+ test('should able to create action with input', async () => {
16
+ const action = serverAct.input(z.string()).action(async () => Promise.resolve('bar'));
16
17
 
17
- expectTypeOf(action).parameter(0).toBeString();
18
- expectTypeOf(action).returns.resolves.toBeString();
19
- await expect(action('foo')).resolves.toBe('bar');
20
- });
18
+ expectTypeOf(action).parameter(0).toBeString();
19
+ expectTypeOf(action).returns.resolves.toBeString();
20
+ await expect(action('foo')).resolves.toBe('bar');
21
+ });
21
22
 
22
- test('should throw error if the input is invalid', async () => {
23
- const action = serverAct.input(z.string()).action(async () => Promise.resolve('bar'));
23
+ test('should throw error if the input is invalid', async () => {
24
+ const action = serverAct.input(z.string()).action(async () => Promise.resolve('bar'));
24
25
 
25
- expectTypeOf(action).parameter(0).toBeString();
26
- expectTypeOf(action).returns.resolves.toBeString();
26
+ expectTypeOf(action).parameter(0).toBeString();
27
+ expectTypeOf(action).returns.resolves.toBeString();
27
28
 
28
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
29
- // @ts-ignore
30
- await expect(action(1)).rejects.toThrowError();
31
- });
29
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
30
+ // @ts-ignore
31
+ await expect(action(1)).rejects.toThrowError();
32
+ });
33
+
34
+ describe('middleware should be called once', () => {
35
+ const middlewareSpy = vi.fn(() => {
36
+ return {prefix: 'best'};
37
+ });
38
+
39
+ beforeEach(() => {
40
+ vi.restoreAllMocks();
41
+ });
32
42
 
33
- describe('middleware should be called once', () => {
34
- const middlewareSpy = vi.fn(() => {
35
- return {prefix: 'best'};
43
+ test('without input', async () => {
44
+ const action = serverAct.middleware(middlewareSpy).action(async ({ctx}) => Promise.resolve(`${ctx.prefix}-bar`));
45
+
46
+ expectTypeOf(action).returns.resolves.toBeString();
47
+ await expect(action()).resolves.toBe('best-bar');
48
+ expect(middlewareSpy).toBeCalledTimes(1);
49
+ });
50
+
51
+ test('with input', async () => {
52
+ const actionWithInput = serverAct
53
+ .middleware(middlewareSpy)
54
+ .input(z.string())
55
+ .action(async ({ctx, input}) => Promise.resolve(`${ctx.prefix}-${input}-bar`));
56
+
57
+ expectTypeOf(actionWithInput).parameter(0).toBeString();
58
+ expectTypeOf(actionWithInput).returns.resolves.toBeString();
59
+ await expect(actionWithInput('foo')).resolves.toBe('best-foo-bar');
60
+ expect(middlewareSpy).toBeCalledTimes(1);
61
+ });
36
62
  });
63
+ });
64
+
65
+ describe.concurrent('experimental_formAction', () => {
66
+ test('should able to create form action without input', async () => {
67
+ const action = serverAct.experimental_formAction(async () => Promise.resolve('bar'));
37
68
 
38
- beforeEach(() => {
39
- vi.restoreAllMocks();
69
+ expectTypeOf(action).parameter(0).toBeString();
70
+ expectTypeOf(action).parameter(1).toEqualTypeOf<FormData>();
71
+ expectTypeOf(action).returns.resolves.toBeString();
72
+
73
+ const formData = new FormData();
74
+ await expect(action('foo', formData)).resolves.toMatchObject('bar');
40
75
  });
41
76
 
42
- test('without input', async () => {
43
- const action = serverAct.middleware(middlewareSpy).action(async ({ctx}) => Promise.resolve(`${ctx.prefix}-bar`));
77
+ test('should able to create form action with input', async () => {
78
+ const action = serverAct
79
+ .input(z.object({foo: z.string()}))
80
+ .experimental_formAction(async () => Promise.resolve('bar'));
44
81
 
82
+ expectTypeOf(action).parameter(0).toBeString();
83
+ expectTypeOf(action).parameter(1).toEqualTypeOf<FormData>();
45
84
  expectTypeOf(action).returns.resolves.toBeString();
46
- await expect(action()).resolves.toBe('best-bar');
47
- expect(middlewareSpy).toBeCalledTimes(1);
85
+
86
+ const formData = new FormData();
87
+ formData.append('foo', 'bar');
88
+ await expect(action('foo', formData)).resolves.toMatchObject('bar');
48
89
  });
49
90
 
50
- test('with input', async () => {
51
- const actionWithInput = serverAct
52
- .middleware(middlewareSpy)
53
- .input(z.string())
54
- .action(async ({ctx, input}) => Promise.resolve(`${ctx.prefix}-${input}-bar`));
91
+ test('should return form errors if the input is invalid', async () => {
92
+ const action = serverAct
93
+ .input(z.object({foo: z.string({required_error: 'Required'})}))
94
+ .experimental_formAction(async ({formErrors}) => {
95
+ if (formErrors) {
96
+ return formErrors;
97
+ }
98
+ return Promise.resolve('bar');
99
+ });
100
+
101
+ expectTypeOf(action).parameter(0).toMatchTypeOf<string | z.ZodError<{foo: string}>>();
102
+ expectTypeOf(action).parameter(1).toEqualTypeOf<FormData>();
103
+
104
+ const formData = new FormData();
105
+ formData.append('bar', 'foo');
55
106
 
56
- expectTypeOf(actionWithInput).parameter(0).toBeString();
57
- expectTypeOf(actionWithInput).returns.resolves.toBeString();
58
- await expect(actionWithInput('foo')).resolves.toBe('best-foo-bar');
59
- expect(middlewareSpy).toBeCalledTimes(1);
107
+ const result = await action('foo', formData);
108
+ expect(result).toBeInstanceOf(z.ZodError);
109
+ expect(result).toHaveProperty('formErrors.fieldErrors', {foo: ['Required']});
60
110
  });
61
111
  });
package/src/index.ts CHANGED
@@ -1,7 +1,13 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
1
2
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
3
  import {type z} from 'zod';
3
4
  import {fromZodError} from 'zod-validation-error';
4
5
 
6
+ type Prettify<T> = {
7
+ [P in keyof T]: T[P];
8
+ // eslint-disable-next-line @typescript-eslint/ban-types
9
+ } & {};
10
+
5
11
  const unsetMarker = Symbol('unsetMarker');
6
12
  type UnsetMarker = typeof unsetMarker;
7
13
 
@@ -15,12 +21,12 @@ type InferParserType<TParser, TType extends 'in' | 'out'> = TParser extends Unse
15
21
 
16
22
  type InferContextType<T> = T extends UnsetMarker ? undefined : T;
17
23
 
18
- type ActionParams<TInput = unknown, TContext = unknown> = {
24
+ interface ActionParams<TInput = unknown, TContext = unknown> {
19
25
  _input: TInput;
20
26
  _context: TContext;
21
- };
27
+ }
22
28
 
23
- type ActionBuilder<TParams extends ActionParams> = {
29
+ interface ActionBuilder<TParams extends ActionParams> {
24
30
  /**
25
31
  * Middleware allows you to run code before the action, its return value will pass as context to the action.
26
32
  */
@@ -40,13 +46,29 @@ type ActionBuilder<TParams extends ActionParams> = {
40
46
  input: InferParserType<TParams['_input'], 'out'>;
41
47
  }) => Promise<TOutput>,
42
48
  ) => (...[input]: OptionalizeUndefined<InferParserType<TParams['_input'], 'in'>>) => Promise<TOutput>;
43
- };
49
+ /**
50
+ * ***Experimental*** - Create an action for React `useFormState`
51
+ */
52
+ experimental_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
+ | {input?: undefined; formErrors: z.ZodError<InferParserType<TParams['_input'], 'in'>>}
61
+ )
62
+ >,
63
+ ) => Promise<TState>,
64
+ ) => (prevState: TState, formData: FormData) => Promise<TState>;
65
+ }
44
66
  type AnyActionBuilder = ActionBuilder<any>;
45
67
 
46
- type ActionBuilderDef<TParams extends ActionParams<any>> = {
68
+ interface ActionBuilderDef<TParams extends ActionParams<any>> {
47
69
  input: TParams['_input'];
48
70
  middleware: (() => Promise<TParams['_context']> | TParams['_context']) | undefined;
49
- };
71
+ }
50
72
  type AnyActionBuilderDef = ActionBuilderDef<any>;
51
73
 
52
74
  const createNewServerActionBuilder = (def: Partial<AnyActionBuilderDef>) => {
@@ -79,6 +101,19 @@ const createServerActionBuilder = (
79
101
  return await action({ctx, input});
80
102
  };
81
103
  },
104
+ experimental_formAction: (action) => {
105
+ return async (prevState, formData) => {
106
+ const ctx = await _def.middleware?.();
107
+ if (_def.input) {
108
+ const result = _def.input.safeParse(Object.fromEntries(formData.entries()));
109
+ if (!result.success) {
110
+ return await action({ctx, prevState, formErrors: result.error});
111
+ }
112
+ return await action({ctx, prevState, input: result.data});
113
+ }
114
+ return await action({ctx, prevState, input: undefined});
115
+ };
116
+ },
82
117
  };
83
118
  };
84
119
 
package/tsconfig.json CHANGED
@@ -4,9 +4,12 @@
4
4
  "_version": "2.0.0",
5
5
  "compilerOptions": {
6
6
  "lib": [
7
- "ES2020"
7
+ "ES2020",
8
+ "DOM",
9
+ "DOM.Iterable"
8
10
  ],
9
- "moduleResolution": "nodenext",
11
+ "module": "NodeNext",
12
+ "moduleResolution": "NodeNext",
10
13
  "outDir": "./dist",
11
14
  "strict": true,
12
15
  "allowUnusedLabels": false,