@buildnbuzz/buzzform 0.1.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/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/adapter-BT9v2OVg.d.mts +1136 -0
- package/dist/adapter-BT9v2OVg.d.ts +1136 -0
- package/dist/chunk-DDDGBPVU.mjs +273 -0
- package/dist/chunk-DDDGBPVU.mjs.map +1 -0
- package/dist/chunk-K42S5YX3.mjs +599 -0
- package/dist/chunk-K42S5YX3.mjs.map +1 -0
- package/dist/index.d.mts +270 -0
- package/dist/index.d.ts +270 -0
- package/dist/index.js +1028 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +194 -0
- package/dist/index.mjs.map +1 -0
- package/dist/rhf.d.mts +70 -0
- package/dist/rhf.d.ts +70 -0
- package/dist/rhf.js +293 -0
- package/dist/rhf.js.map +1 -0
- package/dist/rhf.mjs +175 -0
- package/dist/rhf.mjs.map +1 -0
- package/dist/schema.d.mts +72 -0
- package/dist/schema.d.ts +72 -0
- package/dist/schema.js +768 -0
- package/dist/schema.js.map +1 -0
- package/dist/schema.mjs +63 -0
- package/dist/schema.mjs.map +1 -0
- package/dist/utils-BgwyUFGB.d.mts +233 -0
- package/dist/utils-DVLpbOoW.d.ts +233 -0
- package/dist/zod.d.mts +32 -0
- package/dist/zod.d.ts +32 -0
- package/dist/zod.js +88 -0
- package/dist/zod.js.map +1 -0
- package/dist/zod.mjs +62 -0
- package/dist/zod.mjs.map +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { F as Field, V as ValidationContext, K as FieldType, A as ArrayHelpers } from './adapter-BT9v2OVg.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Maps a BuzzForm field definition to its corresponding Zod type.
|
|
6
|
+
* Used for type inference in createSchema.
|
|
7
|
+
*
|
|
8
|
+
* Order matters for conditional types - more specific matches first.
|
|
9
|
+
*/
|
|
10
|
+
type FieldToZod<F extends Field> = F extends {
|
|
11
|
+
schema: infer S extends z.ZodTypeAny;
|
|
12
|
+
} ? S : F extends {
|
|
13
|
+
type: 'text';
|
|
14
|
+
hasMany: true;
|
|
15
|
+
} ? z.ZodArray<z.ZodString> : F extends {
|
|
16
|
+
type: 'email';
|
|
17
|
+
hasMany: true;
|
|
18
|
+
} ? z.ZodArray<z.ZodString> : F extends {
|
|
19
|
+
type: 'text';
|
|
20
|
+
} ? z.ZodString : F extends {
|
|
21
|
+
type: 'email';
|
|
22
|
+
} ? z.ZodString : F extends {
|
|
23
|
+
type: 'password';
|
|
24
|
+
} ? z.ZodString : F extends {
|
|
25
|
+
type: 'textarea';
|
|
26
|
+
} ? z.ZodString : F extends {
|
|
27
|
+
type: 'number';
|
|
28
|
+
} ? z.ZodNumber : F extends {
|
|
29
|
+
type: 'date';
|
|
30
|
+
} ? z.ZodDate : F extends {
|
|
31
|
+
type: 'datetime';
|
|
32
|
+
} ? z.ZodDate : F extends {
|
|
33
|
+
type: 'checkbox';
|
|
34
|
+
} ? z.ZodBoolean : F extends {
|
|
35
|
+
type: 'switch';
|
|
36
|
+
} ? z.ZodBoolean : F extends {
|
|
37
|
+
type: 'select';
|
|
38
|
+
hasMany: true;
|
|
39
|
+
} ? z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>> : F extends {
|
|
40
|
+
type: 'select';
|
|
41
|
+
} ? z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]> : F extends {
|
|
42
|
+
type: 'radio';
|
|
43
|
+
} ? z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]> : F extends {
|
|
44
|
+
type: 'tags';
|
|
45
|
+
} ? z.ZodArray<z.ZodString> : F extends {
|
|
46
|
+
type: 'upload';
|
|
47
|
+
hasMany: true;
|
|
48
|
+
} ? z.ZodArray<z.ZodUnion<[z.ZodType<File>, z.ZodString]>> : F extends {
|
|
49
|
+
type: 'upload';
|
|
50
|
+
} ? z.ZodUnion<[z.ZodType<File>, z.ZodString]> : z.ZodTypeAny;
|
|
51
|
+
/**
|
|
52
|
+
* Transforms an array of field definitions into the shape of a Zod object.
|
|
53
|
+
* Only includes fields with a `name` property (data fields).
|
|
54
|
+
*
|
|
55
|
+
* Uses the `const T` generic to preserve literal field names.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const fields = [
|
|
59
|
+
* { type: 'text', name: 'email' },
|
|
60
|
+
* { type: 'number', name: 'age' },
|
|
61
|
+
* ] as const;
|
|
62
|
+
*
|
|
63
|
+
* type Shape = FieldsToShape<typeof fields>;
|
|
64
|
+
* // { email: z.ZodString; age: z.ZodNumber }
|
|
65
|
+
*/
|
|
66
|
+
type FieldsToShape<T extends readonly Field[]> = {
|
|
67
|
+
[K in T[number] as K extends {
|
|
68
|
+
name: infer N extends string;
|
|
69
|
+
} ? N : never]: K extends {
|
|
70
|
+
name: string;
|
|
71
|
+
} ? FieldToZod<K> : never;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Function signature for field schema builders.
|
|
75
|
+
* Each field type has a builder that converts the field config to a Zod schema.
|
|
76
|
+
*/
|
|
77
|
+
type SchemaBuilder<TField extends Field = Field> = (field: TField) => z.ZodTypeAny;
|
|
78
|
+
/**
|
|
79
|
+
* Map of field types to their schema builders.
|
|
80
|
+
*/
|
|
81
|
+
type SchemaBuilderMap = {
|
|
82
|
+
[K in Field['type']]?: SchemaBuilder<Extract<Field, {
|
|
83
|
+
type: K;
|
|
84
|
+
}>>;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Infer the TypeScript type from a BuzzForm schema.
|
|
88
|
+
*
|
|
89
|
+
* Use this instead of `z.infer<typeof schema>` to avoid needing to import
|
|
90
|
+
* `z` from `@buildnbuzz/buzzform/zod`.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* import { createSchema, type InferSchema } from '@buildnbuzz/buzzform';
|
|
94
|
+
*
|
|
95
|
+
* const loginSchema = createSchema([
|
|
96
|
+
* { type: 'email', name: 'email', required: true },
|
|
97
|
+
* { type: 'password', name: 'password', required: true },
|
|
98
|
+
* ]);
|
|
99
|
+
*
|
|
100
|
+
* type LoginFormData = InferSchema<typeof loginSchema>;
|
|
101
|
+
* // { email: string; password: string }
|
|
102
|
+
*
|
|
103
|
+
* @see {@link https://form.buildnbuzz.com/docs/type-inference Type Inference Guide}
|
|
104
|
+
*/
|
|
105
|
+
type InferSchema<T extends z.ZodTypeAny> = z.infer<T>;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Creates a Zod schema from an array of field definitions.
|
|
109
|
+
*
|
|
110
|
+
* Provides full intellisense when writing field definitions inline.
|
|
111
|
+
* The returned schema has `.fields` attached for use in rendering.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* const loginSchema = createSchema([
|
|
115
|
+
* { type: 'email', name: 'email', required: true }, // ← Full intellisense!
|
|
116
|
+
* { type: 'password', name: 'password', minLength: 8 },
|
|
117
|
+
* ]);
|
|
118
|
+
*
|
|
119
|
+
* type LoginData = z.infer<typeof loginSchema>;
|
|
120
|
+
* // { email: string; password: string }
|
|
121
|
+
*
|
|
122
|
+
* // Use with useForm:
|
|
123
|
+
* const form = useForm({ schema: loginSchema });
|
|
124
|
+
*
|
|
125
|
+
* // Access fields for rendering:
|
|
126
|
+
* <FormRenderer fields={loginSchema.fields} />
|
|
127
|
+
*/
|
|
128
|
+
declare function createSchema<const T extends readonly Field[]>(fields: [...{
|
|
129
|
+
[K in keyof T]: T[K] extends Field ? T[K] : Field;
|
|
130
|
+
}]): z.ZodObject<FieldsToShape<T>> & {
|
|
131
|
+
fields: T;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Converts an array of field definitions to a Zod object schema.
|
|
136
|
+
* Handles all field types including layouts and nested structures.
|
|
137
|
+
*/
|
|
138
|
+
declare function fieldsToZodSchema<T extends readonly Field[]>(fields: T): z.ZodObject<FieldsToShape<T>>;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* A validation function that can be extracted from a field.
|
|
142
|
+
*/
|
|
143
|
+
type ExtractableValidationFn = (value: unknown, context: ValidationContext) => true | string | Promise<true | string>;
|
|
144
|
+
interface ExtractedValidationConfig {
|
|
145
|
+
/** The validation function (if any) */
|
|
146
|
+
fn?: ExtractableValidationFn;
|
|
147
|
+
/** Whether this is a live validation */
|
|
148
|
+
isLive: boolean;
|
|
149
|
+
/** Debounce milliseconds for live validation */
|
|
150
|
+
debounceMs?: number;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Extracts validation function and config from the unified validate property.
|
|
154
|
+
*/
|
|
155
|
+
declare function extractValidationConfig(validate?: unknown): ExtractedValidationConfig;
|
|
156
|
+
/**
|
|
157
|
+
* Applies custom validation from field.validate to a Zod schema.
|
|
158
|
+
* Standardizes the pattern across all field types.
|
|
159
|
+
*/
|
|
160
|
+
declare function applyCustomValidation(schema: z.ZodTypeAny, field: Field, fieldPath?: string): z.ZodTypeAny;
|
|
161
|
+
/**
|
|
162
|
+
* Makes a schema optional based on field type.
|
|
163
|
+
* Different field types have different "empty" representations.
|
|
164
|
+
*/
|
|
165
|
+
declare function makeOptional(schema: z.ZodTypeAny, fieldType: FieldType): z.ZodTypeAny;
|
|
166
|
+
/**
|
|
167
|
+
* Coerces a value to a number.
|
|
168
|
+
* Empty/null/undefined → undefined, otherwise Number().
|
|
169
|
+
*/
|
|
170
|
+
declare function coerceToNumber(val: unknown): number | undefined;
|
|
171
|
+
/**
|
|
172
|
+
* Coerces a value to a Date.
|
|
173
|
+
* Handles strings, numbers, and Date objects.
|
|
174
|
+
*/
|
|
175
|
+
declare function coerceToDate(val: unknown): Date | undefined;
|
|
176
|
+
/**
|
|
177
|
+
* Gets a human-readable error message for a regex pattern.
|
|
178
|
+
*/
|
|
179
|
+
declare function getPatternErrorMessage(pattern: string | RegExp): string;
|
|
180
|
+
/**
|
|
181
|
+
* Checks if a value is a File-like object.
|
|
182
|
+
*/
|
|
183
|
+
declare function isFileLike(value: unknown): value is File;
|
|
184
|
+
/**
|
|
185
|
+
* Validates file type against accept pattern.
|
|
186
|
+
*/
|
|
187
|
+
declare function isFileTypeAccepted(file: File, accept: string): boolean;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Creates a standardized set of array field manipulation methods.
|
|
191
|
+
* Abstracts the difference between getting/setting values in different form libraries.
|
|
192
|
+
*
|
|
193
|
+
* @param getArray - Function to get current array value at a path
|
|
194
|
+
* @param setArray - Function to set array value at a path
|
|
195
|
+
*/
|
|
196
|
+
declare function createArrayHelpers(getArray: (path: string) => unknown[], setArray: (path: string, value: unknown[]) => void): ArrayHelpers;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Generate a unique field ID from the field path.
|
|
200
|
+
* Converts dot notation to dashes and prefixes with 'field-'.
|
|
201
|
+
* Used for accessibility (htmlFor, id attributes).
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* generateFieldId('user.profile.email') => 'field-user-profile-email'
|
|
205
|
+
* generateFieldId('items[0].name') => 'field-items-0-name'
|
|
206
|
+
*/
|
|
207
|
+
declare function generateFieldId(path: string): string;
|
|
208
|
+
/**
|
|
209
|
+
* Safely retrieve a nested value from an object using a dot-notation path.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* getNestedValue({ user: { name: 'John' } }, 'user.name') => 'John'
|
|
213
|
+
* getNestedValue({ items: [{ id: 1 }] }, 'items.0.id') => 1
|
|
214
|
+
*/
|
|
215
|
+
declare function getNestedValue(obj: unknown, path: string): unknown;
|
|
216
|
+
/**
|
|
217
|
+
* Set a nested value in an object using a dot-notation path.
|
|
218
|
+
* Creates intermediate objects/arrays as needed.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* setNestedValue({}, 'user.name', 'John') => { user: { name: 'John' } }
|
|
222
|
+
*/
|
|
223
|
+
declare function setNestedValue<T extends Record<string, unknown>>(obj: T, path: string, value: unknown): T;
|
|
224
|
+
/**
|
|
225
|
+
* Format bytes into a human-readable string.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* formatBytes(1024) => '1 KB'
|
|
229
|
+
* formatBytes(1234567) => '1.18 MB'
|
|
230
|
+
*/
|
|
231
|
+
declare function formatBytes(bytes: number, decimals?: number): string;
|
|
232
|
+
|
|
233
|
+
export { type FieldToZod as F, type InferSchema as I, type SchemaBuilder as S, type FieldsToShape as a, type SchemaBuilderMap as b, createSchema as c, applyCustomValidation as d, extractValidationConfig as e, fieldsToZodSchema as f, coerceToNumber as g, coerceToDate as h, getPatternErrorMessage as i, isFileLike as j, isFileTypeAccepted as k, createArrayHelpers as l, makeOptional as m, generateFieldId as n, getNestedValue as o, formatBytes as p, setNestedValue as s };
|
package/dist/zod.d.mts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ZodSchema } from 'zod';
|
|
2
|
+
export { ZodSchema, z } from 'zod';
|
|
3
|
+
import { e as Resolver } from './adapter-BT9v2OVg.mjs';
|
|
4
|
+
import 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a validation resolver from a Zod schema.
|
|
8
|
+
*
|
|
9
|
+
* The resolver validates form values against the schema and returns:
|
|
10
|
+
* - `{ values }` if validation passes (with transformed/parsed data)
|
|
11
|
+
* - `{ errors }` if validation fails (with field-level error messages)
|
|
12
|
+
*
|
|
13
|
+
* @param schema - A Zod schema to validate against
|
|
14
|
+
* @returns A Resolver function compatible with BuzzForm adapters
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* import { z } from '@buildnbuzz/buzzform/zod';
|
|
18
|
+
* import { zodResolver } from '@buildnbuzz/buzzform';
|
|
19
|
+
*
|
|
20
|
+
* const schema = z.object({
|
|
21
|
+
* email: z.string().email('Invalid email'),
|
|
22
|
+
* age: z.number().min(18, 'Must be at least 18'),
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const form = useRhf({
|
|
26
|
+
* resolver: zodResolver(schema),
|
|
27
|
+
* defaultValues: { email: '', age: 0 },
|
|
28
|
+
* });
|
|
29
|
+
*/
|
|
30
|
+
declare function zodResolver<TData>(schema: ZodSchema<TData>): Resolver<TData>;
|
|
31
|
+
|
|
32
|
+
export { zodResolver };
|
package/dist/zod.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ZodSchema } from 'zod';
|
|
2
|
+
export { ZodSchema, z } from 'zod';
|
|
3
|
+
import { e as Resolver } from './adapter-BT9v2OVg.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a validation resolver from a Zod schema.
|
|
8
|
+
*
|
|
9
|
+
* The resolver validates form values against the schema and returns:
|
|
10
|
+
* - `{ values }` if validation passes (with transformed/parsed data)
|
|
11
|
+
* - `{ errors }` if validation fails (with field-level error messages)
|
|
12
|
+
*
|
|
13
|
+
* @param schema - A Zod schema to validate against
|
|
14
|
+
* @returns A Resolver function compatible with BuzzForm adapters
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* import { z } from '@buildnbuzz/buzzform/zod';
|
|
18
|
+
* import { zodResolver } from '@buildnbuzz/buzzform';
|
|
19
|
+
*
|
|
20
|
+
* const schema = z.object({
|
|
21
|
+
* email: z.string().email('Invalid email'),
|
|
22
|
+
* age: z.number().min(18, 'Must be at least 18'),
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const form = useRhf({
|
|
26
|
+
* resolver: zodResolver(schema),
|
|
27
|
+
* defaultValues: { email: '', age: 0 },
|
|
28
|
+
* });
|
|
29
|
+
*/
|
|
30
|
+
declare function zodResolver<TData>(schema: ZodSchema<TData>): Resolver<TData>;
|
|
31
|
+
|
|
32
|
+
export { zodResolver };
|
package/dist/zod.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/resolvers/zod.ts
|
|
21
|
+
var zod_exports = {};
|
|
22
|
+
__export(zod_exports, {
|
|
23
|
+
z: () => import_zod.z,
|
|
24
|
+
zodResolver: () => zodResolver
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(zod_exports);
|
|
27
|
+
var import_zod = require("zod");
|
|
28
|
+
function zodResolver(schema) {
|
|
29
|
+
return async (values) => {
|
|
30
|
+
try {
|
|
31
|
+
const parsed = await schema.parseAsync(values);
|
|
32
|
+
return {
|
|
33
|
+
values: parsed,
|
|
34
|
+
errors: {}
|
|
35
|
+
};
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (isZodError(error)) {
|
|
38
|
+
return {
|
|
39
|
+
values: {},
|
|
40
|
+
errors: mapZodErrors(error)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function mapZodErrors(error) {
|
|
48
|
+
const errors = {};
|
|
49
|
+
for (const issue of error.issues) {
|
|
50
|
+
const path = issuePath(issue);
|
|
51
|
+
if (!errors[path]) {
|
|
52
|
+
errors[path] = {
|
|
53
|
+
type: issueType(issue),
|
|
54
|
+
message: issue.message
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return errors;
|
|
59
|
+
}
|
|
60
|
+
function issuePath(issue) {
|
|
61
|
+
return issue.path.map(String).join(".");
|
|
62
|
+
}
|
|
63
|
+
function issueType(issue) {
|
|
64
|
+
switch (issue.code) {
|
|
65
|
+
case "invalid_type":
|
|
66
|
+
if (issue.received === "undefined") return "required";
|
|
67
|
+
return "type";
|
|
68
|
+
case "too_small":
|
|
69
|
+
return issue.type === "string" ? "minLength" : "min";
|
|
70
|
+
case "too_big":
|
|
71
|
+
return issue.type === "string" ? "maxLength" : "max";
|
|
72
|
+
case "invalid_string":
|
|
73
|
+
return issue.validation?.toString() || "pattern";
|
|
74
|
+
case "custom":
|
|
75
|
+
return "custom";
|
|
76
|
+
default:
|
|
77
|
+
return issue.code;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function isZodError(error) {
|
|
81
|
+
return typeof error === "object" && error !== null && "issues" in error && Array.isArray(error.issues);
|
|
82
|
+
}
|
|
83
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
84
|
+
0 && (module.exports = {
|
|
85
|
+
z,
|
|
86
|
+
zodResolver
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=zod.js.map
|
package/dist/zod.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resolvers/zod.ts"],"sourcesContent":["import type { ZodSchema, ZodError, ZodIssue } from 'zod';\r\nimport type { Resolver, FieldError, ResolverResult } from '../types';\r\n\r\n// =============================================================================\r\n// ZOD RESOLVER\r\n// =============================================================================\r\n\r\n/**\r\n * Creates a validation resolver from a Zod schema.\r\n * \r\n * The resolver validates form values against the schema and returns:\r\n * - `{ values }` if validation passes (with transformed/parsed data)\r\n * - `{ errors }` if validation fails (with field-level error messages)\r\n * \r\n * @param schema - A Zod schema to validate against\r\n * @returns A Resolver function compatible with BuzzForm adapters\r\n * \r\n * @example\r\n * import { z } from '@buildnbuzz/buzzform/zod';\r\n * import { zodResolver } from '@buildnbuzz/buzzform';\r\n * \r\n * const schema = z.object({\r\n * email: z.string().email('Invalid email'),\r\n * age: z.number().min(18, 'Must be at least 18'),\r\n * });\r\n * \r\n * const form = useRhf({\r\n * resolver: zodResolver(schema),\r\n * defaultValues: { email: '', age: 0 },\r\n * });\r\n */\r\nexport function zodResolver<TData>(\r\n schema: ZodSchema<TData>\r\n): Resolver<TData> {\r\n return async (values: TData): Promise<ResolverResult<TData>> => {\r\n try {\r\n // Parse and validate - this also transforms the data\r\n const parsed = await schema.parseAsync(values);\r\n\r\n return {\r\n values: parsed,\r\n errors: {},\r\n };\r\n } catch (error) {\r\n // Handle Zod validation errors\r\n if (isZodError(error)) {\r\n return {\r\n values: {} as TData,\r\n errors: mapZodErrors(error),\r\n };\r\n }\r\n\r\n // Re-throw unexpected errors\r\n throw error;\r\n }\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// ERROR MAPPING\r\n// =============================================================================\r\n\r\n/**\r\n * Maps Zod validation errors to our FieldError format.\r\n * Handles nested paths (e.g., \"address.city\", \"items.0.name\").\r\n */\r\nfunction mapZodErrors(error: ZodError): Record<string, FieldError> {\r\n const errors: Record<string, FieldError> = {};\r\n\r\n for (const issue of error.issues) {\r\n const path = issuePath(issue);\r\n\r\n // Only set the first error for each path\r\n if (!errors[path]) {\r\n errors[path] = {\r\n type: issueType(issue),\r\n message: issue.message,\r\n };\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * Convert Zod issue path to dot-notation string.\r\n * ['address', 'city'] → 'address.city'\r\n * ['items', 0, 'name'] → 'items.0.name'\r\n */\r\nfunction issuePath(issue: ZodIssue): string {\r\n return issue.path.map(String).join('.');\r\n}\r\n\r\n/**\r\n * Map Zod issue code to a simpler type string.\r\n */\r\nfunction issueType(issue: ZodIssue): string {\r\n switch (issue.code) {\r\n case 'invalid_type':\r\n if (issue.received === 'undefined') return 'required';\r\n return 'type';\r\n case 'too_small':\r\n return issue.type === 'string' ? 'minLength' : 'min';\r\n case 'too_big':\r\n return issue.type === 'string' ? 'maxLength' : 'max';\r\n case 'invalid_string':\r\n return issue.validation?.toString() || 'pattern';\r\n case 'custom':\r\n return 'custom';\r\n default:\r\n return issue.code;\r\n }\r\n}\r\n\r\n/**\r\n * Type guard to check if an error is a ZodError.\r\n */\r\nfunction isZodError(error: unknown): error is ZodError {\r\n return (\r\n typeof error === 'object' &&\r\n error !== null &&\r\n 'issues' in error &&\r\n Array.isArray((error as ZodError).issues)\r\n );\r\n}\r\n\r\n// =============================================================================\r\n// RE-EXPORTS FOR CONVENIENCE\r\n// =============================================================================\r\n\r\nexport type { ZodSchema } from 'zod';\r\nexport { z } from 'zod';"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmIA,iBAAkB;AApGX,SAAS,YACZ,QACe;AACf,SAAO,OAAO,WAAkD;AAC5D,QAAI;AAEA,YAAM,SAAS,MAAM,OAAO,WAAW,MAAM;AAE7C,aAAO;AAAA,QACH,QAAQ;AAAA,QACR,QAAQ,CAAC;AAAA,MACb;AAAA,IACJ,SAAS,OAAO;AAEZ,UAAI,WAAW,KAAK,GAAG;AACnB,eAAO;AAAA,UACH,QAAQ,CAAC;AAAA,UACT,QAAQ,aAAa,KAAK;AAAA,QAC9B;AAAA,MACJ;AAGA,YAAM;AAAA,IACV;AAAA,EACJ;AACJ;AAUA,SAAS,aAAa,OAA6C;AAC/D,QAAM,SAAqC,CAAC;AAE5C,aAAW,SAAS,MAAM,QAAQ;AAC9B,UAAM,OAAO,UAAU,KAAK;AAG5B,QAAI,CAAC,OAAO,IAAI,GAAG;AACf,aAAO,IAAI,IAAI;AAAA,QACX,MAAM,UAAU,KAAK;AAAA,QACrB,SAAS,MAAM;AAAA,MACnB;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX;AAOA,SAAS,UAAU,OAAyB;AACxC,SAAO,MAAM,KAAK,IAAI,MAAM,EAAE,KAAK,GAAG;AAC1C;AAKA,SAAS,UAAU,OAAyB;AACxC,UAAQ,MAAM,MAAM;AAAA,IAChB,KAAK;AACD,UAAI,MAAM,aAAa,YAAa,QAAO;AAC3C,aAAO;AAAA,IACX,KAAK;AACD,aAAO,MAAM,SAAS,WAAW,cAAc;AAAA,IACnD,KAAK;AACD,aAAO,MAAM,SAAS,WAAW,cAAc;AAAA,IACnD,KAAK;AACD,aAAO,MAAM,YAAY,SAAS,KAAK;AAAA,IAC3C,KAAK;AACD,aAAO;AAAA,IACX;AACI,aAAO,MAAM;AAAA,EACrB;AACJ;AAKA,SAAS,WAAW,OAAmC;AACnD,SACI,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACZ,MAAM,QAAS,MAAmB,MAAM;AAEhD;","names":[]}
|
package/dist/zod.mjs
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/resolvers/zod.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
function zodResolver(schema) {
|
|
4
|
+
return async (values) => {
|
|
5
|
+
try {
|
|
6
|
+
const parsed = await schema.parseAsync(values);
|
|
7
|
+
return {
|
|
8
|
+
values: parsed,
|
|
9
|
+
errors: {}
|
|
10
|
+
};
|
|
11
|
+
} catch (error) {
|
|
12
|
+
if (isZodError(error)) {
|
|
13
|
+
return {
|
|
14
|
+
values: {},
|
|
15
|
+
errors: mapZodErrors(error)
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function mapZodErrors(error) {
|
|
23
|
+
const errors = {};
|
|
24
|
+
for (const issue of error.issues) {
|
|
25
|
+
const path = issuePath(issue);
|
|
26
|
+
if (!errors[path]) {
|
|
27
|
+
errors[path] = {
|
|
28
|
+
type: issueType(issue),
|
|
29
|
+
message: issue.message
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return errors;
|
|
34
|
+
}
|
|
35
|
+
function issuePath(issue) {
|
|
36
|
+
return issue.path.map(String).join(".");
|
|
37
|
+
}
|
|
38
|
+
function issueType(issue) {
|
|
39
|
+
switch (issue.code) {
|
|
40
|
+
case "invalid_type":
|
|
41
|
+
if (issue.received === "undefined") return "required";
|
|
42
|
+
return "type";
|
|
43
|
+
case "too_small":
|
|
44
|
+
return issue.type === "string" ? "minLength" : "min";
|
|
45
|
+
case "too_big":
|
|
46
|
+
return issue.type === "string" ? "maxLength" : "max";
|
|
47
|
+
case "invalid_string":
|
|
48
|
+
return issue.validation?.toString() || "pattern";
|
|
49
|
+
case "custom":
|
|
50
|
+
return "custom";
|
|
51
|
+
default:
|
|
52
|
+
return issue.code;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function isZodError(error) {
|
|
56
|
+
return typeof error === "object" && error !== null && "issues" in error && Array.isArray(error.issues);
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
z,
|
|
60
|
+
zodResolver
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=zod.mjs.map
|
package/dist/zod.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resolvers/zod.ts"],"sourcesContent":["import type { ZodSchema, ZodError, ZodIssue } from 'zod';\r\nimport type { Resolver, FieldError, ResolverResult } from '../types';\r\n\r\n// =============================================================================\r\n// ZOD RESOLVER\r\n// =============================================================================\r\n\r\n/**\r\n * Creates a validation resolver from a Zod schema.\r\n * \r\n * The resolver validates form values against the schema and returns:\r\n * - `{ values }` if validation passes (with transformed/parsed data)\r\n * - `{ errors }` if validation fails (with field-level error messages)\r\n * \r\n * @param schema - A Zod schema to validate against\r\n * @returns A Resolver function compatible with BuzzForm adapters\r\n * \r\n * @example\r\n * import { z } from '@buildnbuzz/buzzform/zod';\r\n * import { zodResolver } from '@buildnbuzz/buzzform';\r\n * \r\n * const schema = z.object({\r\n * email: z.string().email('Invalid email'),\r\n * age: z.number().min(18, 'Must be at least 18'),\r\n * });\r\n * \r\n * const form = useRhf({\r\n * resolver: zodResolver(schema),\r\n * defaultValues: { email: '', age: 0 },\r\n * });\r\n */\r\nexport function zodResolver<TData>(\r\n schema: ZodSchema<TData>\r\n): Resolver<TData> {\r\n return async (values: TData): Promise<ResolverResult<TData>> => {\r\n try {\r\n // Parse and validate - this also transforms the data\r\n const parsed = await schema.parseAsync(values);\r\n\r\n return {\r\n values: parsed,\r\n errors: {},\r\n };\r\n } catch (error) {\r\n // Handle Zod validation errors\r\n if (isZodError(error)) {\r\n return {\r\n values: {} as TData,\r\n errors: mapZodErrors(error),\r\n };\r\n }\r\n\r\n // Re-throw unexpected errors\r\n throw error;\r\n }\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// ERROR MAPPING\r\n// =============================================================================\r\n\r\n/**\r\n * Maps Zod validation errors to our FieldError format.\r\n * Handles nested paths (e.g., \"address.city\", \"items.0.name\").\r\n */\r\nfunction mapZodErrors(error: ZodError): Record<string, FieldError> {\r\n const errors: Record<string, FieldError> = {};\r\n\r\n for (const issue of error.issues) {\r\n const path = issuePath(issue);\r\n\r\n // Only set the first error for each path\r\n if (!errors[path]) {\r\n errors[path] = {\r\n type: issueType(issue),\r\n message: issue.message,\r\n };\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * Convert Zod issue path to dot-notation string.\r\n * ['address', 'city'] → 'address.city'\r\n * ['items', 0, 'name'] → 'items.0.name'\r\n */\r\nfunction issuePath(issue: ZodIssue): string {\r\n return issue.path.map(String).join('.');\r\n}\r\n\r\n/**\r\n * Map Zod issue code to a simpler type string.\r\n */\r\nfunction issueType(issue: ZodIssue): string {\r\n switch (issue.code) {\r\n case 'invalid_type':\r\n if (issue.received === 'undefined') return 'required';\r\n return 'type';\r\n case 'too_small':\r\n return issue.type === 'string' ? 'minLength' : 'min';\r\n case 'too_big':\r\n return issue.type === 'string' ? 'maxLength' : 'max';\r\n case 'invalid_string':\r\n return issue.validation?.toString() || 'pattern';\r\n case 'custom':\r\n return 'custom';\r\n default:\r\n return issue.code;\r\n }\r\n}\r\n\r\n/**\r\n * Type guard to check if an error is a ZodError.\r\n */\r\nfunction isZodError(error: unknown): error is ZodError {\r\n return (\r\n typeof error === 'object' &&\r\n error !== null &&\r\n 'issues' in error &&\r\n Array.isArray((error as ZodError).issues)\r\n );\r\n}\r\n\r\n// =============================================================================\r\n// RE-EXPORTS FOR CONVENIENCE\r\n// =============================================================================\r\n\r\nexport type { ZodSchema } from 'zod';\r\nexport { z } from 'zod';"],"mappings":";AAmIA,SAAS,SAAS;AApGX,SAAS,YACZ,QACe;AACf,SAAO,OAAO,WAAkD;AAC5D,QAAI;AAEA,YAAM,SAAS,MAAM,OAAO,WAAW,MAAM;AAE7C,aAAO;AAAA,QACH,QAAQ;AAAA,QACR,QAAQ,CAAC;AAAA,MACb;AAAA,IACJ,SAAS,OAAO;AAEZ,UAAI,WAAW,KAAK,GAAG;AACnB,eAAO;AAAA,UACH,QAAQ,CAAC;AAAA,UACT,QAAQ,aAAa,KAAK;AAAA,QAC9B;AAAA,MACJ;AAGA,YAAM;AAAA,IACV;AAAA,EACJ;AACJ;AAUA,SAAS,aAAa,OAA6C;AAC/D,QAAM,SAAqC,CAAC;AAE5C,aAAW,SAAS,MAAM,QAAQ;AAC9B,UAAM,OAAO,UAAU,KAAK;AAG5B,QAAI,CAAC,OAAO,IAAI,GAAG;AACf,aAAO,IAAI,IAAI;AAAA,QACX,MAAM,UAAU,KAAK;AAAA,QACrB,SAAS,MAAM;AAAA,MACnB;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX;AAOA,SAAS,UAAU,OAAyB;AACxC,SAAO,MAAM,KAAK,IAAI,MAAM,EAAE,KAAK,GAAG;AAC1C;AAKA,SAAS,UAAU,OAAyB;AACxC,UAAQ,MAAM,MAAM;AAAA,IAChB,KAAK;AACD,UAAI,MAAM,aAAa,YAAa,QAAO;AAC3C,aAAO;AAAA,IACX,KAAK;AACD,aAAO,MAAM,SAAS,WAAW,cAAc;AAAA,IACnD,KAAK;AACD,aAAO,MAAM,SAAS,WAAW,cAAc;AAAA,IACnD,KAAK;AACD,aAAO,MAAM,YAAY,SAAS,KAAK;AAAA,IAC3C,KAAK;AACD,aAAO;AAAA,IACX;AACI,aAAO,MAAM;AAAA,EACrB;AACJ;AAKA,SAAS,WAAW,OAAmC;AACnD,SACI,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACZ,MAAM,QAAS,MAAmB,MAAM;AAEhD;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@buildnbuzz/buzzform",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Simple React form library for shadcn/ui. Declare fields, customize rendering, get live validation with minimal boilerplate.",
|
|
5
|
+
"author": "Parth Lad <parth@buildnbuzz.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/buildnbuzz/buzzform.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://form.buildnbuzz.com",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"react",
|
|
14
|
+
"forms",
|
|
15
|
+
"shadcn",
|
|
16
|
+
"nextjs",
|
|
17
|
+
"react-hook-form",
|
|
18
|
+
"zod"
|
|
19
|
+
],
|
|
20
|
+
"main": "dist/index.js",
|
|
21
|
+
"module": "dist/index.mjs",
|
|
22
|
+
"types": "dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"import": {
|
|
26
|
+
"types": "./dist/index.d.mts",
|
|
27
|
+
"default": "./dist/index.mjs"
|
|
28
|
+
},
|
|
29
|
+
"require": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"./schema": {
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./dist/schema.d.mts",
|
|
37
|
+
"default": "./dist/schema.mjs"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"types": "./dist/schema.d.ts",
|
|
41
|
+
"default": "./dist/schema.js"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"./rhf": {
|
|
45
|
+
"import": {
|
|
46
|
+
"types": "./dist/rhf.d.mts",
|
|
47
|
+
"default": "./dist/rhf.mjs"
|
|
48
|
+
},
|
|
49
|
+
"require": {
|
|
50
|
+
"types": "./dist/rhf.d.ts",
|
|
51
|
+
"default": "./dist/rhf.js"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"./zod": {
|
|
55
|
+
"import": {
|
|
56
|
+
"types": "./dist/zod.d.mts",
|
|
57
|
+
"default": "./dist/zod.mjs"
|
|
58
|
+
},
|
|
59
|
+
"require": {
|
|
60
|
+
"types": "./dist/zod.d.ts",
|
|
61
|
+
"default": "./dist/zod.js"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"files": [
|
|
66
|
+
"dist",
|
|
67
|
+
"README.md",
|
|
68
|
+
"LICENSE"
|
|
69
|
+
],
|
|
70
|
+
"sideEffects": false,
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"nanoid": "^5.0.9"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"react": "^18 || ^19",
|
|
76
|
+
"react-hook-form": "^7.0.0",
|
|
77
|
+
"zod": "^3.0.0"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"zod": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"react-hook-form": {
|
|
84
|
+
"optional": true
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@eslint/js": "^9.39.2",
|
|
89
|
+
"@types/node": "^22.15.3",
|
|
90
|
+
"@types/react": "^19.2.2",
|
|
91
|
+
"@types/react-dom": "^19.2.2",
|
|
92
|
+
"eslint": "^9.39.1",
|
|
93
|
+
"react": "^19.0.0",
|
|
94
|
+
"react-hook-form": "^7.69.0",
|
|
95
|
+
"tsup": "^8.3.5",
|
|
96
|
+
"typescript": "^5.9.2",
|
|
97
|
+
"typescript-eslint": "^8.51.0",
|
|
98
|
+
"zod": "^3.25.0"
|
|
99
|
+
},
|
|
100
|
+
"publishConfig": {
|
|
101
|
+
"access": "public"
|
|
102
|
+
},
|
|
103
|
+
"scripts": {
|
|
104
|
+
"build": "tsup",
|
|
105
|
+
"dev": "tsup --watch",
|
|
106
|
+
"lint": "eslint .",
|
|
107
|
+
"type-check": "tsc --noEmit"
|
|
108
|
+
}
|
|
109
|
+
}
|