@volverjs/form-vue 1.1.0-beta.4 → 1.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/dist/VvForm.d.ts +1 -1
- package/dist/VvFormWrapper.d.ts +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.es.js +605 -600
- package/dist/index.umd.js +1 -1
- package/dist/utils.d.ts +12 -0
- package/package.json +12 -12
- package/src/VvFormField.ts +7 -7
- package/src/VvFormTemplate.ts +117 -117
- package/src/utils.ts +198 -40
package/src/utils.ts
CHANGED
|
@@ -7,31 +7,74 @@ import {
|
|
|
7
7
|
safeParseAsync as z4SafeParseAsync,
|
|
8
8
|
formatError as z4FormatError,
|
|
9
9
|
} from 'zod/v4/core'
|
|
10
|
-
import { toJSONSchema as z4toJSONSchema } from 'zod/v4'
|
|
11
10
|
import type * as z3 from 'zod/v3'
|
|
12
11
|
import type * as z4 from 'zod/v4/core'
|
|
13
12
|
import type { FormSchema, InferSchema, VvZodError, ZodIssue } from './types'
|
|
14
13
|
|
|
14
|
+
// Helper function to determine the type of a value
|
|
15
|
+
function _getValueType(value: unknown) {
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
return 'array'
|
|
18
|
+
}
|
|
19
|
+
if (value === null) {
|
|
20
|
+
return 'null'
|
|
21
|
+
}
|
|
22
|
+
return typeof value
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Helper function to check if a value matches a schema type
|
|
26
|
+
function _isValueCompatibleWithSchema(value: unknown, subSchema: z4.JSONSchema.JSONSchema): boolean {
|
|
27
|
+
const valueType = _getValueType(value)
|
|
28
|
+
|
|
29
|
+
if (subSchema.type) {
|
|
30
|
+
return subSchema.type === valueType
|
|
31
|
+
|| (subSchema.type === 'integer' && valueType === 'number' && Number.isInteger(value as number))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// If no type specified, assume compatibility
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
|
|
15
38
|
export const isZod3Object = (value: z3.ZodTypeAny): value is z3.ZodObject<any> => {
|
|
16
39
|
return value._def.typeName === 'ZodObject'
|
|
17
40
|
}
|
|
18
41
|
|
|
42
|
+
export const isZod4Object = (value: z4.$ZodType): value is z4.$ZodObject<any> => {
|
|
43
|
+
return value._zod.def.type === 'object'
|
|
44
|
+
}
|
|
45
|
+
|
|
19
46
|
export const isZod3Default = (value: z3.ZodTypeAny): value is z3.ZodDefault<any> => {
|
|
20
47
|
return value._def.typeName === 'ZodDefault'
|
|
21
48
|
}
|
|
22
49
|
|
|
50
|
+
export const isZod4Default = (value: z4.$ZodType): value is z4.$ZodDefault<any> => {
|
|
51
|
+
return value._zod.def.type === 'default'
|
|
52
|
+
}
|
|
53
|
+
|
|
23
54
|
export const isZod3Nullable = (value: z3.ZodTypeAny): value is z3.ZodNullable<any> => {
|
|
24
55
|
return value._def.typeName === 'ZodNullable'
|
|
25
56
|
}
|
|
26
57
|
|
|
58
|
+
export const isZod4Nullable = (value: z4.$ZodType): value is z4.$ZodNullable<any> => {
|
|
59
|
+
return value._zod.def.type === 'nullable'
|
|
60
|
+
}
|
|
61
|
+
|
|
27
62
|
export const isZod3Record = (value: z3.ZodTypeAny): value is z3.ZodRecord<any, any> => {
|
|
28
63
|
return value._def.typeName === 'ZodRecord'
|
|
29
64
|
}
|
|
30
65
|
|
|
66
|
+
export const isZod4Record = (value: z4.$ZodType): value is z4.$ZodRecord<any, any> => {
|
|
67
|
+
return value._zod.def.type === 'record'
|
|
68
|
+
}
|
|
69
|
+
|
|
31
70
|
export const isZod3Array = (value: z3.ZodTypeAny): value is z3.ZodArray<any> => {
|
|
32
71
|
return value._def.typeName === 'ZodArray'
|
|
33
72
|
}
|
|
34
73
|
|
|
74
|
+
export const isZod4Array = (value: z4.$ZodType): value is z4.$ZodArray<any> => {
|
|
75
|
+
return value._zod.def.type === 'array'
|
|
76
|
+
}
|
|
77
|
+
|
|
35
78
|
export const isZod3Effects = (value: z3.ZodTypeAny): value is z3.ZodEffects<any> => {
|
|
36
79
|
return value._def.typeName === 'ZodEffects'
|
|
37
80
|
}
|
|
@@ -40,64 +83,103 @@ export const isZod3Optional = (value: z3.ZodTypeAny): value is z3.ZodOptional<an
|
|
|
40
83
|
return value._def.typeName === 'ZodOptional'
|
|
41
84
|
}
|
|
42
85
|
|
|
43
|
-
|
|
44
|
-
|
|
86
|
+
export const isZod4Optional = (value: z4.$ZodType): value is z4.$ZodOptional<any> => {
|
|
87
|
+
return value._zod.def.type === 'optional'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// zod 4 replacements for ZodEffects
|
|
91
|
+
export const isZod4Pipe = (value: z4.$ZodType): value is z4.$ZodPipe<any> => {
|
|
92
|
+
return value._zod.def.type === 'pipe'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const isZod4Transform = (value: z4.$ZodType): value is z4.$ZodTransform<any> => {
|
|
96
|
+
return value._zod.def.type === 'transform'
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function _loopOnZod3Effects<Type extends z3.ZodTypeAny>(
|
|
100
|
+
schema: Type | z3.ZodEffects<Type> | z3.ZodEffects<z3.ZodEffects<Type>>,
|
|
101
|
+
) {
|
|
102
|
+
let toReturn = schema
|
|
103
|
+
while (isZod3Effects(toReturn)) {
|
|
104
|
+
toReturn = toReturn.innerType()
|
|
105
|
+
}
|
|
106
|
+
return toReturn
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function _loopOnZod4Pipe<Type extends z4.$ZodType>(
|
|
110
|
+
schema:
|
|
111
|
+
| Type
|
|
112
|
+
| z4.$ZodPipe<Type>
|
|
113
|
+
| z4.$ZodPipe<any, Type>,
|
|
114
|
+
) {
|
|
115
|
+
let toReturn = schema
|
|
116
|
+
while (isZod4Pipe(toReturn)) {
|
|
117
|
+
if (isZod4Transform(toReturn._zod.def.out)) {
|
|
118
|
+
toReturn = toReturn._zod.def.in
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
toReturn = toReturn._zod.def.out as Type
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return toReturn
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Helper function to get the inner type of a Zod schema
|
|
128
|
+
export const getZod3SchemaInnerType = <Type extends z3.ZodTypeAny>(
|
|
45
129
|
schema:
|
|
46
130
|
| Type
|
|
47
131
|
| z3.ZodEffects<Type>
|
|
48
132
|
| z3.ZodEffects<z3.ZodEffects<Type>>
|
|
49
133
|
| z3.ZodOptional<Type>,
|
|
50
134
|
) => {
|
|
51
|
-
let toReturn = schema
|
|
52
|
-
while (isZod3Effects(toReturn)) {
|
|
53
|
-
toReturn = toReturn.innerType()
|
|
54
|
-
}
|
|
135
|
+
let toReturn = _loopOnZod3Effects(schema)
|
|
55
136
|
if (isZod3Optional(toReturn)) {
|
|
56
137
|
toReturn = toReturn._def.innerType
|
|
57
138
|
}
|
|
58
139
|
return toReturn
|
|
59
140
|
}
|
|
60
141
|
|
|
61
|
-
|
|
62
|
-
|
|
142
|
+
export const getZod4SchemaInnerType = <Type extends z4.$ZodType>(
|
|
143
|
+
schema:
|
|
144
|
+
| Type
|
|
145
|
+
| z4.$ZodPipe<Type>
|
|
146
|
+
| z4.$ZodPipe<any, Type>
|
|
147
|
+
| z4.$ZodOptional<Type>,
|
|
148
|
+
) => {
|
|
149
|
+
let toReturn = _loopOnZod4Pipe(schema)
|
|
150
|
+
if (isZod4Optional(toReturn)) {
|
|
151
|
+
toReturn = toReturn._zod.def.innerType
|
|
152
|
+
}
|
|
153
|
+
return toReturn
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Helper function to check if a Zod schema is optional
|
|
157
|
+
export const isZod3SchemaOptional = <Type extends z3.ZodTypeAny>(
|
|
63
158
|
schema:
|
|
64
159
|
| Type
|
|
65
160
|
| z3.ZodEffects<Type>
|
|
66
161
|
| z3.ZodEffects<z3.ZodEffects<Type>>
|
|
67
162
|
| z3.ZodOptional<Type>,
|
|
68
163
|
) => {
|
|
69
|
-
|
|
70
|
-
while (isZod3Effects(toReturn)) {
|
|
71
|
-
toReturn = toReturn.innerType()
|
|
72
|
-
}
|
|
164
|
+
const toReturn = _loopOnZod3Effects(schema)
|
|
73
165
|
if (isZod3Optional(toReturn)) {
|
|
74
166
|
return true
|
|
75
167
|
}
|
|
76
168
|
return false
|
|
77
169
|
}
|
|
78
170
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// Helper function to check if a value matches a schema type
|
|
91
|
-
function isValueCompatibleWithSchema(value: unknown, subSchema: z4.JSONSchema.JSONSchema): boolean {
|
|
92
|
-
const valueType = getValueType(value)
|
|
93
|
-
|
|
94
|
-
if (subSchema.type) {
|
|
95
|
-
return subSchema.type === valueType
|
|
96
|
-
|| (subSchema.type === 'integer' && valueType === 'number' && Number.isInteger(value as number))
|
|
171
|
+
export const isZod4SchemaOptional = <Type extends z4.$ZodType>(
|
|
172
|
+
schema:
|
|
173
|
+
| Type
|
|
174
|
+
| z4.$ZodPipe<Type>
|
|
175
|
+
| z4.$ZodPipe<any, Type>
|
|
176
|
+
| z4.$ZodOptional<Type>,
|
|
177
|
+
) => {
|
|
178
|
+
const toReturn = _loopOnZod4Pipe(schema)
|
|
179
|
+
if (isZod4Optional(toReturn)) {
|
|
180
|
+
return true
|
|
97
181
|
}
|
|
98
|
-
|
|
99
|
-
// If no type specified, assume compatibility
|
|
100
|
-
return true
|
|
182
|
+
return false
|
|
101
183
|
}
|
|
102
184
|
|
|
103
185
|
export function defaultObjectByJSONSchema(schema: z4.JSONSchema.JSONSchema, original?: unknown): unknown {
|
|
@@ -106,7 +188,7 @@ export function defaultObjectByJSONSchema(schema: z4.JSONSchema.JSONSchema, orig
|
|
|
106
188
|
if (original !== undefined) {
|
|
107
189
|
// First pass: find exact type match
|
|
108
190
|
for (const subSchema of schema.anyOf) {
|
|
109
|
-
if (
|
|
191
|
+
if (_isValueCompatibleWithSchema(original, subSchema as z4.JSONSchema.JSONSchema)) {
|
|
110
192
|
return defaultObjectByJSONSchema(subSchema as z4.JSONSchema.JSONSchema, original)
|
|
111
193
|
}
|
|
112
194
|
}
|
|
@@ -183,12 +265,88 @@ export const isZod4Schema = (schema: z3.ZodTypeAny | z4.$ZodType): schema is z4.
|
|
|
183
265
|
export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema, original: Partial<InferSchema<Schema>> & Record<string, unknown> = {}): Partial<InferSchema<Schema>> {
|
|
184
266
|
// zod v4
|
|
185
267
|
if (isZod4Schema(schema)) {
|
|
186
|
-
const
|
|
187
|
-
if (
|
|
268
|
+
const innerType = getZod4SchemaInnerType(schema)
|
|
269
|
+
if (!isZod4Object(innerType)) {
|
|
188
270
|
return original
|
|
189
271
|
}
|
|
190
|
-
const
|
|
191
|
-
|
|
272
|
+
const unknownKeys = innerType._zod.def.catchall && innerType._zod.def.catchall._zod.def.type !== 'never'
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
...(unknownKeys ? original : {}),
|
|
276
|
+
...Object.fromEntries(
|
|
277
|
+
('shape' in innerType._zod.def ? Object.entries(innerType._zod.def.shape) as [string, z4.$ZodType][] : []).map(
|
|
278
|
+
([key, subSchema]) => {
|
|
279
|
+
const originalValue = original[key]
|
|
280
|
+
const isOptional = isZod4SchemaOptional(subSchema)
|
|
281
|
+
let innerType = getZod4SchemaInnerType(subSchema)
|
|
282
|
+
let defaultValue: Partial<InferSchema<Schema>> | undefined
|
|
283
|
+
if (isZod4Default(innerType)) {
|
|
284
|
+
defaultValue = innerType._zod.def.defaultValue
|
|
285
|
+
innerType = innerType._zod.def.innerType
|
|
286
|
+
}
|
|
287
|
+
if (
|
|
288
|
+
originalValue === null
|
|
289
|
+
&& isZod4Nullable(innerType)
|
|
290
|
+
) {
|
|
291
|
+
return [key, originalValue]
|
|
292
|
+
}
|
|
293
|
+
if ((originalValue === undefined || originalValue === null) && isOptional) {
|
|
294
|
+
return [key, defaultValue]
|
|
295
|
+
}
|
|
296
|
+
if (innerType) {
|
|
297
|
+
const parse = z4SafeParse(subSchema, originalValue)
|
|
298
|
+
if (parse.success) {
|
|
299
|
+
return [key, parse.data ?? defaultValue]
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (
|
|
303
|
+
isZod4Array(innerType)
|
|
304
|
+
&& Array.isArray(originalValue)
|
|
305
|
+
&& originalValue.length
|
|
306
|
+
) {
|
|
307
|
+
const arrayType = getZod4SchemaInnerType(innerType._zod.def.element)
|
|
308
|
+
if (isZod4Object(arrayType)) {
|
|
309
|
+
return [
|
|
310
|
+
key,
|
|
311
|
+
originalValue.map((element: unknown) =>
|
|
312
|
+
defaultObjectBySchema(
|
|
313
|
+
arrayType,
|
|
314
|
+
(element && typeof element === 'object'
|
|
315
|
+
? element
|
|
316
|
+
: undefined) as Partial<
|
|
317
|
+
typeof arrayType
|
|
318
|
+
>,
|
|
319
|
+
),
|
|
320
|
+
),
|
|
321
|
+
]
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (isZod4Record(innerType) && originalValue) {
|
|
325
|
+
const valueType = getZod4SchemaInnerType(innerType._zod.def.valueType)
|
|
326
|
+
if (isZod4Object(valueType)) {
|
|
327
|
+
return [key, Object.keys(originalValue).reduce((acc: Record<string, unknown>, recordKey: string) => {
|
|
328
|
+
acc[recordKey] = defaultObjectBySchema(valueType, originalValue[recordKey])
|
|
329
|
+
return acc
|
|
330
|
+
}, {})]
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (isZod4Object(innerType)) {
|
|
334
|
+
return [
|
|
335
|
+
key,
|
|
336
|
+
defaultObjectBySchema(
|
|
337
|
+
innerType,
|
|
338
|
+
originalValue
|
|
339
|
+
&& typeof originalValue === 'object'
|
|
340
|
+
? originalValue
|
|
341
|
+
: defaultValue,
|
|
342
|
+
),
|
|
343
|
+
]
|
|
344
|
+
}
|
|
345
|
+
return [key, defaultValue]
|
|
346
|
+
},
|
|
347
|
+
),
|
|
348
|
+
),
|
|
349
|
+
} as Partial<InferSchema<Schema>>
|
|
192
350
|
}
|
|
193
351
|
|
|
194
352
|
// zod v3
|
|
@@ -242,7 +400,7 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
|
|
|
242
400
|
? element
|
|
243
401
|
: undefined) as Partial<
|
|
244
402
|
typeof arrayType
|
|
245
|
-
|
|
403
|
+
>,
|
|
246
404
|
),
|
|
247
405
|
),
|
|
248
406
|
]
|