@volverjs/form-vue 1.1.2-beta.1 → 1.1.2-beta.3

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@volverjs/form-vue",
3
3
  "type": "module",
4
- "version": "1.1.2-beta.1",
4
+ "version": "1.1.2-beta.3",
5
5
  "description": "Vue 3 Forms with @volverjs/ui-vue",
6
6
  "author": "8 Wave S.r.l.",
7
7
  "license": "MIT",
@@ -50,35 +50,38 @@
50
50
  "node": ">= 16.x"
51
51
  },
52
52
  "peerDependencies": {
53
- "@volverjs/ui-vue": "^0.0.11",
54
- "@vueuse/core": "^13.0.0",
53
+ "@volverjs/ui-vue": "^0.0.12",
54
+ "@vueuse/core": "^14.0.0",
55
55
  "dot-prop": "^10.0.0",
56
56
  "vue": "^3.5.0",
57
57
  "zod": "^3.25.0 || ^4.0.0"
58
58
  },
59
59
  "devDependencies": {
60
- "@antfu/eslint-config": "^5.4.1",
61
- "@nabla/vite-plugin-eslint": "^2.0.6",
62
- "@playwright/experimental-ct-vue": "^1.55.1",
60
+ "@antfu/eslint-config": "^9.0.0",
61
+ "@nabla/vite-plugin-eslint": "^3.0.1",
62
+ "@playwright/experimental-ct-vue": "^1.60.0",
63
63
  "@testing-library/vue": "^8.1.0",
64
- "@vitejs/plugin-vue": "^6.0.1",
65
- "@volverjs/style": "^0.1.22",
66
- "@volverjs/ui-vue": "^0.0.11",
67
- "@vue/compiler-sfc": "^3.5.22",
68
- "@vue/runtime-core": "^3.5.22",
69
- "@vue/test-utils": "^2.4.6",
70
- "@vueuse/core": "^13.9.0",
64
+ "@vitejs/plugin-vue": "^6.0.6",
65
+ "@volverjs/style": "^0.1.23",
66
+ "@volverjs/ui-vue": "^0.0.12",
67
+ "@vue/compiler-dom": "^3.5.34",
68
+ "@vue/compiler-sfc": "^3.5.34",
69
+ "@vue/language-core": "^3.2.8",
70
+ "@vue/runtime-core": "^3.5.34",
71
+ "@vue/shared": "^3.5.34",
72
+ "@vue/test-utils": "^2.4.10",
73
+ "@vueuse/core": "^14.3.0",
71
74
  "copy": "^0.3.2",
72
- "dot-prop": "^10.0.0",
73
- "eslint": "^9.36.0",
74
- "happy-dom": "^19.0.2",
75
- "typescript": "^5.9.3",
76
- "vite": "^7.1.9",
77
- "vite-plugin-dts": "^4.5.4",
78
- "vite-plugin-externalize-deps": "^0.9.0",
79
- "vitest": "^3.2.4",
80
- "vue": "^3.5.22",
81
- "zod": "^4.1.11"
75
+ "dot-prop": "^10.1.0",
76
+ "eslint": "^10.3.0",
77
+ "happy-dom": "^20.9.0",
78
+ "typescript": "^6.0.3",
79
+ "vite": "^8.0.12",
80
+ "vite-plugin-dts": "^5.0.0",
81
+ "vite-plugin-externalize-deps": "^0.10.0",
82
+ "vitest": "^4.1.6",
83
+ "vue": "^3.5.34",
84
+ "zod": "^4.4.3"
82
85
  },
83
86
  "scripts": {
84
87
  "lint": "eslint .",
@@ -86,11 +89,11 @@
86
89
  "type-check": "tsc --noEmit",
87
90
  "dev": "vite build --watch",
88
91
  "build": "vite build",
89
- "test": "pnpm run build && pnpm run test-vitest && pnpm run test-playwright",
90
- "test-vitest": "vitest run",
91
- "test-vitest-watch": "vitest",
92
- "test-playwright": "playwright test -c playwright-ct.config.ts",
93
- "test-playwright:ui": "playwright test -c playwright-ct.config.ts --ui",
92
+ "test": "pnpm run build && pnpm run test:vitest && pnpm run test:playwright",
93
+ "test:vitest": "vitest run",
94
+ "test:vitest:watch": "vitest",
95
+ "test:playwright": "playwright test -c playwright-ct.config.ts",
96
+ "test:playwright:ui": "playwright test -c playwright-ct.config.ts --ui",
94
97
  "credits": "npx @opengovsg/credits-generator"
95
98
  }
96
99
  }
@@ -241,7 +241,7 @@ export function defineFormFieldsGroup<Schema extends FormSchema, Type = undefine
241
241
  })
242
242
  const invalids = computed(() => {
243
243
  return namesKeys.value.reduce<Record<string, boolean>>((acc, name) => {
244
- acc[name] = Boolean(errors.value?.[namesKeysMap.value[name]])
244
+ acc[name] = Boolean(errors.value?.[namesMap.value[name]])
245
245
  return acc
246
246
  }, {})
247
247
  })
package/src/utils.ts CHANGED
@@ -27,6 +27,13 @@ function _isValueCompatibleWithSchema(value: unknown, subSchema: z4.JSONSchema.J
27
27
  const valueType = _getValueType(value)
28
28
 
29
29
  if (subSchema.type) {
30
+ // Handle type as array (e.g. ["string", "null"])
31
+ if (Array.isArray(subSchema.type)) {
32
+ return subSchema.type.some(t =>
33
+ t === valueType
34
+ || (t === 'integer' && valueType === 'number' && Number.isInteger(value as number)),
35
+ )
36
+ }
30
37
  return subSchema.type === valueType
31
38
  || (subSchema.type === 'integer' && valueType === 'number' && Number.isInteger(value as number))
32
39
  }
@@ -182,26 +189,75 @@ export const isZod4SchemaOptional = <Type extends z4.$ZodType>(
182
189
  return false
183
190
  }
184
191
 
192
+ // Helper to resolve anyOf/oneOf variants
193
+ function _resolveVariantSchema(
194
+ variants: readonly z4.JSONSchema.BaseSchema[],
195
+ original: unknown | undefined,
196
+ ): unknown {
197
+ if (variants.length === 0) {
198
+ return original ?? undefined
199
+ }
200
+ if (original !== undefined) {
201
+ // First pass: find exact type match
202
+ for (const subSchema of variants) {
203
+ if (_isValueCompatibleWithSchema(original, subSchema as z4.JSONSchema.JSONSchema)) {
204
+ return defaultObjectByJSONSchema(subSchema as z4.JSONSchema.JSONSchema, original)
205
+ }
206
+ }
207
+ // Second pass: try first schema that doesn't explicitly conflict
208
+ for (const subSchema of variants) {
209
+ const subSchemaTyped = subSchema as z4.JSONSchema.JSONSchema
210
+ if (!subSchemaTyped.type || subSchemaTyped.type === 'object') {
211
+ return defaultObjectByJSONSchema(subSchemaTyped, original)
212
+ }
213
+ }
214
+ }
215
+ // Fallback to first schema
216
+ return defaultObjectByJSONSchema(variants[0] as z4.JSONSchema.JSONSchema, original)
217
+ }
218
+
185
219
  export function defaultObjectByJSONSchema(schema: z4.JSONSchema.JSONSchema, original?: unknown): unknown {
186
- // Handle anyOf - find the best matching schema without unnecessary recursion
220
+ // Handle const fixed value
221
+ if ('const' in schema) {
222
+ return schema.const
223
+ }
224
+
225
+ // Handle anyOf
187
226
  if (schema.anyOf && Array.isArray(schema.anyOf)) {
188
- if (original !== undefined) {
189
- // First pass: find exact type match
190
- for (const subSchema of schema.anyOf) {
191
- if (_isValueCompatibleWithSchema(original, subSchema as z4.JSONSchema.JSONSchema)) {
192
- return defaultObjectByJSONSchema(subSchema as z4.JSONSchema.JSONSchema, original)
193
- }
227
+ return _resolveVariantSchema(schema.anyOf, original)
228
+ }
229
+
230
+ // Handle oneOf (semantically similar to anyOf for defaults)
231
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
232
+ return _resolveVariantSchema(schema.oneOf, original)
233
+ }
234
+
235
+ // Handle allOf — merge all sub-schemas into one and process
236
+ if (schema.allOf && Array.isArray(schema.allOf)) {
237
+ const merged: z4.JSONSchema.JSONSchema = { ...schema, allOf: undefined }
238
+ for (const subSchema of schema.allOf) {
239
+ const sub = subSchema as z4.JSONSchema.JSONSchema
240
+ if (sub.properties) {
241
+ merged.properties = { ...merged.properties as Record<string, z4.JSONSchema.JSONSchema>, ...sub.properties as Record<string, z4.JSONSchema.JSONSchema> }
194
242
  }
195
- // Second pass: try first schema that doesn't explicitly conflict
196
- for (const subSchema of schema.anyOf) {
197
- const subSchemaTyped = subSchema as z4.JSONSchema.JSONSchema
198
- if (!subSchemaTyped.type || subSchemaTyped.type === 'object') {
199
- return defaultObjectByJSONSchema(subSchemaTyped, original)
200
- }
243
+ if (sub.type && !merged.type) {
244
+ merged.type = sub.type
201
245
  }
202
246
  }
203
- // Fallback to first schema
204
- return defaultObjectByJSONSchema(schema.anyOf[0] as z4.JSONSchema.JSONSchema, original)
247
+ return defaultObjectByJSONSchema(merged, original)
248
+ }
249
+
250
+ // Handle type as array (e.g. ["string", "null"]) — check null first
251
+ if (Array.isArray(schema.type)) {
252
+ if (original === null && schema.type.includes('null')) {
253
+ return null
254
+ }
255
+ // Find the first non-null type and delegate
256
+ const nonNullType = schema.type.find(t => t !== 'null')
257
+ if (nonNullType) {
258
+ return defaultObjectByJSONSchema({ ...schema, type: nonNullType } as z4.JSONSchema.JSONSchema, original)
259
+ }
260
+ return schema.default ?? null
205
261
  }
206
262
 
207
263
  // Early return for non-object types
@@ -217,8 +273,11 @@ export function defaultObjectByJSONSchema(schema: z4.JSONSchema.JSONSchema, orig
217
273
  case 'null':
218
274
  return original === null ? original : schema.default
219
275
  case 'array':
220
- if (Array.isArray(original) && schema.items) {
221
- return original.map(item => defaultObjectByJSONSchema(schema.items as z4.JSONSchema.JSONSchema, item))
276
+ if (Array.isArray(original)) {
277
+ if (schema.items) {
278
+ return original.map(item => defaultObjectByJSONSchema(schema.items as z4.JSONSchema.JSONSchema, item))
279
+ }
280
+ return original
222
281
  }
223
282
  return schema.default
224
283
  default:
@@ -226,12 +285,11 @@ export function defaultObjectByJSONSchema(schema: z4.JSONSchema.JSONSchema, orig
226
285
  }
227
286
  }
228
287
 
229
- // Object handling with optimizations
288
+ // Object handling
230
289
  const properties = schema.properties as Record<string, z4.JSONSchema.JSONSchema>
231
290
  const isOriginalObject = original && typeof original === 'object' && !Array.isArray(original)
232
291
  const originalObj = isOriginalObject ? original as Record<string, unknown> : undefined
233
292
 
234
- // Initialize result object more efficiently
235
293
  const toReturn: Record<string, unknown> = {}
236
294
 
237
295
  // Process schema properties first
@@ -246,7 +304,6 @@ export function defaultObjectByJSONSchema(schema: z4.JSONSchema.JSONSchema, orig
246
304
 
247
305
  for (const [key, value] of Object.entries(originalObj)) {
248
306
  if (!schemaKeys.has(key)) {
249
- // Allow any additional properties as-is
250
307
  toReturn[key] = value
251
308
  }
252
309
  }
@@ -293,7 +350,7 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
293
350
  if ((originalValue === undefined || originalValue === null) && isOptional) {
294
351
  return [key, defaultValue]
295
352
  }
296
- if (innerType) {
353
+ if (innerType && originalValue !== undefined) {
297
354
  const parse = z4SafeParse(subSchema, originalValue)
298
355
  if (parse.success) {
299
356
  return [key, parse.data ?? defaultValue]
@@ -302,7 +359,6 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
302
359
  if (
303
360
  isZod4Array(innerType)
304
361
  && Array.isArray(originalValue)
305
- && originalValue.length
306
362
  ) {
307
363
  const arrayType = getZod4SchemaInnerType(innerType._zod.def.element)
308
364
  if (isZod4Object(arrayType)) {
@@ -320,6 +376,7 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
320
376
  ),
321
377
  ]
322
378
  }
379
+ return [key, originalValue]
323
380
  }
324
381
  if (isZod4Record(innerType) && originalValue) {
325
382
  const valueType = getZod4SchemaInnerType(innerType._zod.def.valueType)
@@ -329,6 +386,7 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
329
386
  return acc
330
387
  }, {})]
331
388
  }
389
+ return [key, originalValue]
332
390
  }
333
391
  if (isZod4Object(innerType)) {
334
392
  return [
@@ -378,7 +436,7 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
378
436
  if ((originalValue === undefined || originalValue === null) && isOptional) {
379
437
  return [key, defaultValue]
380
438
  }
381
- if (innerType) {
439
+ if (innerType && originalValue !== undefined) {
382
440
  const parse = subSchema.safeParse(originalValue)
383
441
  if (parse.success) {
384
442
  return [key, parse.data ?? defaultValue]
@@ -387,7 +445,6 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
387
445
  if (
388
446
  isZod3Array(innerType)
389
447
  && Array.isArray(originalValue)
390
- && originalValue.length
391
448
  ) {
392
449
  const arrayType = getZod3SchemaInnerType(innerType._def.type)
393
450
  if (isZod3Object(arrayType)) {
@@ -405,6 +462,7 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
405
462
  ),
406
463
  ]
407
464
  }
465
+ return [key, originalValue]
408
466
  }
409
467
  if (isZod3Record(innerType) && originalValue) {
410
468
  const valueType = getZod3SchemaInnerType(innerType._def.valueType)
@@ -414,6 +472,7 @@ export function defaultObjectBySchema<Schema extends FormSchema>(schema: Schema,
414
472
  return acc
415
473
  }, {})]
416
474
  }
475
+ return [key, originalValue]
417
476
  }
418
477
  if (isZod3Object(innerType)) {
419
478
  return [
File without changes
File without changes
File without changes