@effect-app/vue-components 4.0.0-beta.2 → 4.0.0-beta.21
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/types/components/OmegaForm/OmegaAutoGen.vue.d.ts +1 -1
- package/dist/types/components/OmegaForm/OmegaFormStuff.d.ts +11 -11
- package/dist/types/components/OmegaForm/useOmegaForm.d.ts +2 -4
- package/dist/types/utils/index.d.ts +3 -4
- package/dist/vue-components.es.js +14 -13
- package/dist/vue-components.es10.js +131 -129
- package/dist/vue-components.es11.js +2 -2
- package/dist/vue-components.es12.js +382 -340
- package/dist/vue-components.es16.js +4 -723
- package/dist/vue-components.es17.js +10 -140
- package/dist/vue-components.es18.js +55 -4
- package/dist/vue-components.es19.js +54 -11
- package/dist/vue-components.es2.js +18 -17
- package/dist/vue-components.es20.js +6 -3
- package/dist/vue-components.es21.js +6 -24
- package/dist/vue-components.es22.js +3 -4
- package/dist/vue-components.es23.js +3 -8
- package/dist/vue-components.es24.js +2 -55
- package/dist/vue-components.es25.js +2 -69
- package/dist/vue-components.es26.js +2 -6
- package/dist/vue-components.es27.js +2 -6
- package/dist/vue-components.es28.js +17 -3
- package/dist/vue-components.es29.js +11 -3
- package/dist/vue-components.es3.js +11 -10
- package/dist/vue-components.es30.js +29 -2
- package/dist/vue-components.es31.js +4 -2
- package/dist/vue-components.es32.js +1 -1
- package/dist/vue-components.es33.js +1 -1
- package/dist/vue-components.es34.js +111 -17
- package/dist/vue-components.es36.js +7 -318
- package/dist/vue-components.es37.js +31 -560
- package/dist/vue-components.es39.js +190 -50
- package/dist/vue-components.es41.js +4 -4
- package/dist/vue-components.es42.js +23 -4
- package/dist/vue-components.es43.js +5 -24
- package/dist/vue-components.es44.js +20 -74
- package/dist/vue-components.es45.js +29 -39
- package/dist/vue-components.es46.js +21 -313
- package/dist/vue-components.es47.js +11 -98
- package/dist/vue-components.es48.js +5 -31
- package/dist/vue-components.es49.js +19 -2
- package/dist/vue-components.es5.js +1 -1
- package/dist/vue-components.es50.js +9 -2
- package/dist/vue-components.es51.js +31 -2
- package/dist/vue-components.es52.js +47 -110
- package/dist/{vue-components.es75.js → vue-components.es53.js} +5 -5
- package/dist/vue-components.es54.js +11 -7
- package/dist/vue-components.es55.js +64 -31
- package/dist/{vue-components.es93.js → vue-components.es56.js} +1 -1
- package/dist/vue-components.es57.js +15 -190
- package/dist/{vue-components.es95.js → vue-components.es58.js} +3 -3
- package/dist/vue-components.es59.js +28 -37
- package/dist/vue-components.es60.js +39 -80
- package/dist/vue-components.es61.js +2 -41
- package/dist/vue-components.es62.js +44 -5
- package/dist/vue-components.es63.js +2 -4
- package/dist/vue-components.es7.js +35 -35
- package/package.json +10 -10
- package/src/components/OmegaForm/OmegaAutoGen.vue +25 -30
- package/src/components/OmegaForm/OmegaErrorsInternal.vue +2 -3
- package/src/components/OmegaForm/OmegaFormStuff.ts +311 -301
- package/src/components/OmegaForm/OmegaInternalInput.vue +3 -1
- package/src/components/OmegaForm/useOmegaForm.ts +30 -32
- package/src/utils/index.ts +4 -8
- package/dist/vue-components.es100.js +0 -4
- package/dist/vue-components.es35.js +0 -13
- package/dist/vue-components.es38.js +0 -29
- package/dist/vue-components.es40.js +0 -66
- package/dist/vue-components.es64.js +0 -25
- package/dist/vue-components.es65.js +0 -7
- package/dist/vue-components.es66.js +0 -23
- package/dist/vue-components.es67.js +0 -32
- package/dist/vue-components.es68.js +0 -24
- package/dist/vue-components.es69.js +0 -14
- package/dist/vue-components.es70.js +0 -7
- package/dist/vue-components.es71.js +0 -21
- package/dist/vue-components.es72.js +0 -11
- package/dist/vue-components.es73.js +0 -33
- package/dist/vue-components.es74.js +0 -50
- package/dist/vue-components.es76.js +0 -103
- package/dist/vue-components.es77.js +0 -84
- package/dist/vue-components.es78.js +0 -23
- package/dist/vue-components.es79.js +0 -14
- package/dist/vue-components.es80.js +0 -115
- package/dist/vue-components.es81.js +0 -5
- package/dist/vue-components.es82.js +0 -34
- package/dist/vue-components.es83.js +0 -4
- package/dist/vue-components.es84.js +0 -4
- package/dist/vue-components.es85.js +0 -18
- package/dist/vue-components.es86.js +0 -17
- package/dist/vue-components.es87.js +0 -72
- package/dist/vue-components.es88.js +0 -10
- package/dist/vue-components.es89.js +0 -4
- package/dist/vue-components.es90.js +0 -17
- package/dist/vue-components.es91.js +0 -13
- package/dist/vue-components.es92.js +0 -67
- package/dist/vue-components.es94.js +0 -19
- package/dist/vue-components.es96.js +0 -31
- package/dist/vue-components.es97.js +0 -44
- package/dist/vue-components.es98.js +0 -4
- package/dist/vue-components.es99.js +0 -46
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import * as AST from "effect/SchemaAST"
|
|
1
|
+
import { Effect, Option, type Record, S } from "effect-app"
|
|
3
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
4
3
|
import { type DeepKeys, type DeepValue, type FieldAsyncValidateOrFn, type FieldValidateOrFn, type FormApi, type FormAsyncValidateOrFn, type FormOptions, type FormState, type FormValidateOrFn, type StandardSchemaV1, type VueFormApi } from "@tanstack/vue-form"
|
|
5
4
|
import { isObject } from "@vueuse/core"
|
|
6
|
-
import * as
|
|
5
|
+
import type * as Fiber from "effect/Fiber"
|
|
7
6
|
import { getTransformationFrom, useIntl } from "../../utils"
|
|
8
7
|
import { type OmegaFieldInternalApi } from "./InputProps"
|
|
9
8
|
import { type OF, type OmegaFormReturn } from "./useOmegaForm"
|
|
@@ -145,7 +144,7 @@ export type FormProps<From, To> =
|
|
|
145
144
|
formApi: OmegaFormParams<From, To>
|
|
146
145
|
meta: any
|
|
147
146
|
value: To
|
|
148
|
-
}) => Promise<any> | Effect.Effect<unknown, any, never>
|
|
147
|
+
}) => Promise<any> | Fiber.Fiber<any, any> | Effect.Effect<unknown, any, never>
|
|
149
148
|
}
|
|
150
149
|
|
|
151
150
|
export type OmegaFormParams<From, To> = FormApi<
|
|
@@ -262,7 +261,7 @@ export type SelectFieldMeta = BaseFieldMeta & {
|
|
|
262
261
|
export type MultipleFieldMeta = BaseFieldMeta & {
|
|
263
262
|
type: "multiple"
|
|
264
263
|
members: any[] // TODO: should be non empty array?
|
|
265
|
-
rest: readonly AST.AST[]
|
|
264
|
+
rest: readonly S.AST.AST[]
|
|
266
265
|
}
|
|
267
266
|
|
|
268
267
|
export type BooleanFieldMeta = BaseFieldMeta & {
|
|
@@ -301,34 +300,46 @@ export type CreateMeta =
|
|
|
301
300
|
}
|
|
302
301
|
& (
|
|
303
302
|
| {
|
|
304
|
-
propertySignatures: readonly AST.PropertySignature[]
|
|
303
|
+
propertySignatures: readonly S.AST.PropertySignature[]
|
|
305
304
|
property?: never
|
|
306
305
|
}
|
|
307
306
|
| {
|
|
308
307
|
propertySignatures?: never
|
|
309
|
-
property: AST.AST
|
|
308
|
+
property: S.AST.AST
|
|
310
309
|
}
|
|
311
310
|
)
|
|
312
311
|
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
312
|
+
const unwrapDeclaration = (property: S.AST.AST): S.AST.AST => {
|
|
313
|
+
let current = getTransformationFrom(property)
|
|
314
|
+
|
|
315
|
+
while (S.AST.isDeclaration(current) && current.typeParameters.length > 0) {
|
|
316
|
+
current = getTransformationFrom(current.typeParameters[0]!)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return current
|
|
316
320
|
}
|
|
317
321
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
322
|
+
const isNullishType = (property: S.AST.AST) => S.AST.isUndefined(property) || S.AST.isNull(property)
|
|
323
|
+
|
|
324
|
+
const getNullableOrUndefined = (property: S.AST.AST) =>
|
|
325
|
+
S.AST.isUnion(property)
|
|
326
|
+
? property.types.find((_) => isNullishType(_))
|
|
327
|
+
: false
|
|
328
|
+
|
|
329
|
+
export const isNullableOrUndefined = (property: false | S.AST.AST | undefined) => {
|
|
330
|
+
if (!property || !S.AST.isUnion(property)) return false
|
|
331
|
+
if (property.types.find((_) => S.AST.isUndefined(_))) {
|
|
321
332
|
return "undefined"
|
|
322
333
|
}
|
|
323
|
-
if (property.types.find((_) =>
|
|
334
|
+
if (property.types.find((_) => S.AST.isNull(_))) return "null"
|
|
324
335
|
return false
|
|
325
336
|
}
|
|
326
337
|
|
|
327
338
|
// Helper function to recursively unwrap nested unions (e.g., S.NullOr(S.NullOr(X)) -> X)
|
|
328
|
-
const unwrapNestedUnions = (types: readonly AST.AST[]): readonly AST.AST[] => {
|
|
329
|
-
const result: AST.AST[] = []
|
|
339
|
+
const unwrapNestedUnions = (types: readonly S.AST.AST[]): readonly S.AST.AST[] => {
|
|
340
|
+
const result: S.AST.AST[] = []
|
|
330
341
|
for (const type of types) {
|
|
331
|
-
if (AST.isUnion(type)) {
|
|
342
|
+
if (S.AST.isUnion(type)) {
|
|
332
343
|
// Recursively unwrap nested unions
|
|
333
344
|
const unwrapped = unwrapNestedUnions(type.types)
|
|
334
345
|
result.push(...unwrapped)
|
|
@@ -339,31 +350,108 @@ const unwrapNestedUnions = (types: readonly AST.AST[]): readonly AST.AST[] => {
|
|
|
339
350
|
return result
|
|
340
351
|
}
|
|
341
352
|
|
|
353
|
+
const getNonNullTypes = (types: readonly S.AST.AST[]) =>
|
|
354
|
+
unwrapNestedUnions(types)
|
|
355
|
+
.map(unwrapDeclaration)
|
|
356
|
+
.filter((_) => !isNullishType(_))
|
|
357
|
+
|
|
358
|
+
const getJsonSchemaAnnotation = (property: S.AST.AST): Record<string, unknown> => {
|
|
359
|
+
const jsonSchema = S.AST.resolve(property)?.jsonSchema
|
|
360
|
+
return jsonSchema && typeof jsonSchema === "object" ? jsonSchema as Record<string, unknown> : {}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const getDefaultFromAst = (property: S.AST.AST) => {
|
|
364
|
+
const link = property.context?.defaultValue?.[0] as any
|
|
365
|
+
|
|
366
|
+
if (!link?.transformation?.decode?.run) {
|
|
367
|
+
return undefined
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
const result = Effect.runSync(link.transformation.decode.run(Option.none())) as Option.Option<unknown>
|
|
372
|
+
return Option.isSome(result) ? result.value : undefined
|
|
373
|
+
} catch {
|
|
374
|
+
return undefined
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const getCheckMetas = (property: S.AST.AST): Array<Record<string, any>> => {
|
|
379
|
+
const checks = property.checks ?? []
|
|
380
|
+
|
|
381
|
+
return checks.flatMap((check) => {
|
|
382
|
+
if (check._tag === "FilterGroup") {
|
|
383
|
+
return check.checks.flatMap((inner) => {
|
|
384
|
+
const meta = inner.annotations?.meta
|
|
385
|
+
return meta && typeof meta === "object" ? [meta as Record<string, any>] : []
|
|
386
|
+
})
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const meta = check.annotations?.meta
|
|
390
|
+
return meta && typeof meta === "object" ? [meta as Record<string, any>] : []
|
|
391
|
+
})
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const getFieldMetadataFromAst = (property: S.AST.AST) => {
|
|
395
|
+
const base: Partial<FieldMeta> & Record<string, unknown> = {
|
|
396
|
+
description: S.AST.resolveDescription(property)
|
|
397
|
+
}
|
|
398
|
+
const checks = getCheckMetas(property)
|
|
399
|
+
|
|
400
|
+
if (S.AST.isString(property)) {
|
|
401
|
+
base.type = "string"
|
|
402
|
+
for (const check of checks) {
|
|
403
|
+
switch (check._tag) {
|
|
404
|
+
case "isMinLength":
|
|
405
|
+
base.minLength = check.minLength
|
|
406
|
+
break
|
|
407
|
+
case "isMaxLength":
|
|
408
|
+
base.maxLength = check.maxLength
|
|
409
|
+
break
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (S.AST.resolveTitle(property) === "Email") {
|
|
414
|
+
base.format = "email"
|
|
415
|
+
}
|
|
416
|
+
} else if (S.AST.isNumber(property)) {
|
|
417
|
+
base.type = "number"
|
|
418
|
+
for (const check of checks) {
|
|
419
|
+
switch (check._tag) {
|
|
420
|
+
case "isInt":
|
|
421
|
+
base.refinement = "int"
|
|
422
|
+
break
|
|
423
|
+
case "isGreaterThanOrEqualTo":
|
|
424
|
+
base.minimum = check.minimum
|
|
425
|
+
break
|
|
426
|
+
case "isLessThanOrEqualTo":
|
|
427
|
+
base.maximum = check.maximum
|
|
428
|
+
break
|
|
429
|
+
case "isGreaterThan":
|
|
430
|
+
base.exclusiveMinimum = check.exclusiveMinimum
|
|
431
|
+
break
|
|
432
|
+
case "isLessThan":
|
|
433
|
+
base.exclusiveMaximum = check.exclusiveMaximum
|
|
434
|
+
break
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
} else if (S.AST.isBoolean(property)) {
|
|
438
|
+
base.type = "boolean"
|
|
439
|
+
} else {
|
|
440
|
+
base.type = "unknown"
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return base
|
|
444
|
+
}
|
|
445
|
+
|
|
342
446
|
export const createMeta = <T = any>(
|
|
343
447
|
{ meta = {}, parent = "", property, propertySignatures }: CreateMeta,
|
|
344
448
|
acc: Partial<MetaRecord<T>> = {}
|
|
345
449
|
): MetaRecord<T> | FieldMeta => {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
// BUT: check for Int title annotation first - S.Int and branded Int have title "Int" or "int"
|
|
349
|
-
// and we don't want to lose that information by unwrapping
|
|
350
|
-
if (property && AST.isDeclaration(property)) {
|
|
351
|
-
const titleOnTransform = property.annotations?.title ?? ""
|
|
352
|
-
|
|
353
|
-
// only unwrap if this is NOT an Int type
|
|
354
|
-
if (titleOnTransform !== "Int" && titleOnTransform !== "int") {
|
|
355
|
-
// In v4, Declaration doesn't have a 'from' property
|
|
356
|
-
// Just return the property as-is
|
|
357
|
-
return createMeta<T>({
|
|
358
|
-
parent,
|
|
359
|
-
meta,
|
|
360
|
-
property
|
|
361
|
-
})
|
|
362
|
-
}
|
|
363
|
-
// if it's Int, fall through to process it with the Int type
|
|
450
|
+
if (property) {
|
|
451
|
+
property = unwrapDeclaration(property)
|
|
364
452
|
}
|
|
365
453
|
|
|
366
|
-
if (property && AST.isObjects(property)) {
|
|
454
|
+
if (property && S.AST.isObjects(property)) {
|
|
367
455
|
return createMeta<T>({
|
|
368
456
|
meta,
|
|
369
457
|
propertySignatures: property.propertySignatures
|
|
@@ -375,10 +463,6 @@ export const createMeta = <T = any>(
|
|
|
375
463
|
const key = parent ? `${parent}.${p.name.toString()}` : p.name.toString()
|
|
376
464
|
const nullableOrUndefined = isNullableOrUndefined(p.type)
|
|
377
465
|
|
|
378
|
-
// Check if this property has title "Int" or "int" annotation (from Int brand wrapper)
|
|
379
|
-
const propertyTitle = p.type.annotations?.title ?? ""
|
|
380
|
-
const isIntField = propertyTitle === "Int" || propertyTitle === "int"
|
|
381
|
-
|
|
382
466
|
// Determine if this field should be required:
|
|
383
467
|
// - For nullable discriminated unions, only _tag should be non-required
|
|
384
468
|
// - All other fields should calculate their required status normally
|
|
@@ -394,20 +478,11 @@ export const createMeta = <T = any>(
|
|
|
394
478
|
isRequired = !nullableOrUndefined
|
|
395
479
|
}
|
|
396
480
|
|
|
397
|
-
const typeToProcess = p.type
|
|
398
|
-
if (AST.isUnion(p.type)) {
|
|
399
|
-
|
|
400
|
-
const unwrappedTypes = unwrapNestedUnions(p.type.types)
|
|
401
|
-
const nonNullTypes = unwrappedTypes
|
|
402
|
-
.filter(
|
|
403
|
-
(t) => !AST.isUndefined(t) && !AST.isNull(t)
|
|
404
|
-
)
|
|
405
|
-
// unwraps class (Class are transformations)
|
|
406
|
-
.map(getTransformationFrom)
|
|
481
|
+
const typeToProcess = unwrapDeclaration(p.type)
|
|
482
|
+
if (S.AST.isUnion(p.type)) {
|
|
483
|
+
const nonNullTypes = getNonNullTypes(p.type.types)
|
|
407
484
|
|
|
408
|
-
const hasStructMembers = nonNullTypes.some(
|
|
409
|
-
(t) => AST.isObjects(t)
|
|
410
|
-
)
|
|
485
|
+
const hasStructMembers = nonNullTypes.some(S.AST.isObjects)
|
|
411
486
|
|
|
412
487
|
if (hasStructMembers) {
|
|
413
488
|
// Only create parent meta for non-NullOr unions to avoid duplicates
|
|
@@ -422,7 +497,7 @@ export const createMeta = <T = any>(
|
|
|
422
497
|
|
|
423
498
|
// Process each non-null type and merge their metadata
|
|
424
499
|
for (const nonNullType of nonNullTypes) {
|
|
425
|
-
if (AST.isObjects(nonNullType)) {
|
|
500
|
+
if (S.AST.isObjects(nonNullType)) {
|
|
426
501
|
// For discriminated unions (multiple branches):
|
|
427
502
|
// - If the parent union is nullable, only _tag should be non-required
|
|
428
503
|
// - All other fields maintain their normal required status based on their own types
|
|
@@ -439,8 +514,7 @@ export const createMeta = <T = any>(
|
|
|
439
514
|
}
|
|
440
515
|
}
|
|
441
516
|
} else {
|
|
442
|
-
|
|
443
|
-
const arrayTypes = nonNullTypes.filter(AST.isArrays)
|
|
517
|
+
const arrayTypes = nonNullTypes.filter(S.AST.isArrays)
|
|
444
518
|
if (arrayTypes.length > 0) {
|
|
445
519
|
const arrayType = arrayTypes[0] // Take the first array type
|
|
446
520
|
|
|
@@ -454,8 +528,8 @@ export const createMeta = <T = any>(
|
|
|
454
528
|
|
|
455
529
|
// If the array has struct elements, also create metadata for their properties
|
|
456
530
|
if (arrayType.rest && arrayType.rest.length > 0) {
|
|
457
|
-
const restElement = arrayType.rest[0]
|
|
458
|
-
if (AST.isObjects(restElement)) {
|
|
531
|
+
const restElement = unwrapDeclaration(arrayType.rest[0]!)
|
|
532
|
+
if (S.AST.isObjects(restElement)) {
|
|
459
533
|
for (const prop of restElement.propertySignatures) {
|
|
460
534
|
const propKey = `${key}.${prop.name.toString()}`
|
|
461
535
|
|
|
@@ -473,12 +547,12 @@ export const createMeta = <T = any>(
|
|
|
473
547
|
acc[propKey as NestedKeyOf<T>] = propMeta as FieldMeta
|
|
474
548
|
|
|
475
549
|
if (
|
|
476
|
-
propMeta.type === "multiple" && AST.isArrays(prop.type) && prop
|
|
550
|
+
propMeta.type === "multiple" && S.AST.isArrays(prop.type) && prop
|
|
477
551
|
.type
|
|
478
552
|
.rest && prop.type.rest.length > 0
|
|
479
553
|
) {
|
|
480
|
-
const nestedRestElement = prop.type.rest[0]
|
|
481
|
-
if (AST.isObjects(nestedRestElement)) {
|
|
554
|
+
const nestedRestElement = unwrapDeclaration(prop.type.rest[0]!)
|
|
555
|
+
if (S.AST.isObjects(nestedRestElement)) {
|
|
482
556
|
for (const nestedProp of nestedRestElement.propertySignatures) {
|
|
483
557
|
const nestedPropKey = `${propKey}.${nestedProp.name.toString()}`
|
|
484
558
|
|
|
@@ -513,34 +587,32 @@ export const createMeta = <T = any>(
|
|
|
513
587
|
}
|
|
514
588
|
}
|
|
515
589
|
} else {
|
|
516
|
-
|
|
517
|
-
const unwrappedTypeToProcess = getTransformationFrom(typeToProcess)
|
|
518
|
-
if (AST.isObjects(unwrappedTypeToProcess)) {
|
|
590
|
+
if (S.AST.isObjects(typeToProcess)) {
|
|
519
591
|
Object.assign(
|
|
520
592
|
acc,
|
|
521
593
|
createMeta<T>({
|
|
522
594
|
parent: key,
|
|
523
|
-
propertySignatures:
|
|
595
|
+
propertySignatures: typeToProcess.propertySignatures,
|
|
524
596
|
meta: { required: isRequired, nullableOrUndefined }
|
|
525
597
|
})
|
|
526
598
|
)
|
|
527
|
-
} else if (AST.isArrays(p.type)) {
|
|
599
|
+
} else if (S.AST.isArrays(p.type)) {
|
|
528
600
|
// Check if it has struct elements
|
|
529
601
|
const hasStructElements = p.type.rest.length > 0
|
|
530
|
-
&& AST.isObjects(p.type.rest[0])
|
|
602
|
+
&& S.AST.isObjects(unwrapDeclaration(p.type.rest[0]!))
|
|
531
603
|
|
|
532
604
|
if (hasStructElements) {
|
|
533
605
|
// For arrays with struct elements, only create meta for nested fields, not the array itself
|
|
534
|
-
const elementType = p.type.rest[0]
|
|
535
|
-
if (AST.isObjects(elementType)) {
|
|
606
|
+
const elementType = unwrapDeclaration(p.type.rest[0]!)
|
|
607
|
+
if (S.AST.isObjects(elementType)) {
|
|
536
608
|
// Process each property in the array element
|
|
537
609
|
for (const prop of elementType.propertySignatures) {
|
|
538
610
|
const propKey = `${key}.${prop.name.toString()}`
|
|
539
611
|
|
|
540
612
|
// Check if the property is another array
|
|
541
|
-
if (AST.isArrays(prop.type) && prop.type.rest.length > 0) {
|
|
542
|
-
const nestedElementType = prop.type.rest[0]
|
|
543
|
-
if (AST.isObjects(nestedElementType)) {
|
|
613
|
+
if (S.AST.isArrays(prop.type) && prop.type.rest.length > 0) {
|
|
614
|
+
const nestedElementType = unwrapDeclaration(prop.type.rest[0]!)
|
|
615
|
+
if (S.AST.isObjects(nestedElementType)) {
|
|
544
616
|
// Array with struct elements - process nested fields
|
|
545
617
|
for (const nestedProp of nestedElementType.propertySignatures) {
|
|
546
618
|
const nestedKey = `${propKey}.${nestedProp.name.toString()}`
|
|
@@ -592,9 +664,11 @@ export const createMeta = <T = any>(
|
|
|
592
664
|
parent: key,
|
|
593
665
|
property: p.type,
|
|
594
666
|
meta: {
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
667
|
+
// an empty string is valid for a S.String field, so we should not mark it as required
|
|
668
|
+
// TODO: handle this better via the createMeta minLength parsing
|
|
669
|
+
required: isRequired
|
|
670
|
+
&& (!S.AST.isString(typeToProcess) || !!getFieldMetadataFromAst(p.type).minLength),
|
|
671
|
+
nullableOrUndefined
|
|
598
672
|
}
|
|
599
673
|
})
|
|
600
674
|
|
|
@@ -607,19 +681,17 @@ export const createMeta = <T = any>(
|
|
|
607
681
|
|
|
608
682
|
if (property) {
|
|
609
683
|
const nullableOrUndefined = getNullableOrUndefined(property)
|
|
684
|
+
property = unwrapDeclaration(property)
|
|
610
685
|
|
|
611
686
|
if (!Object.hasOwnProperty.call(meta, "required")) {
|
|
612
687
|
meta["required"] = !nullableOrUndefined
|
|
613
688
|
}
|
|
614
689
|
|
|
615
|
-
if (AST.isUnion(property)) {
|
|
616
|
-
|
|
617
|
-
const
|
|
618
|
-
const nonNullType = unwrappedTypes.find(
|
|
619
|
-
(t) => !AST.isUndefined(t) && !AST.isNull(t)
|
|
620
|
-
)!
|
|
690
|
+
if (S.AST.isUnion(property)) {
|
|
691
|
+
const unwrappedTypes = unwrapNestedUnions(property.types).map(unwrapDeclaration)
|
|
692
|
+
const nonNullType = unwrappedTypes.find((t) => !isNullishType(t))!
|
|
621
693
|
|
|
622
|
-
if (AST.isObjects(nonNullType)) {
|
|
694
|
+
if (S.AST.isObjects(nonNullType)) {
|
|
623
695
|
return createMeta<T>({
|
|
624
696
|
propertySignatures: nonNullType.propertySignatures,
|
|
625
697
|
parent,
|
|
@@ -627,11 +699,11 @@ export const createMeta = <T = any>(
|
|
|
627
699
|
})
|
|
628
700
|
}
|
|
629
701
|
|
|
630
|
-
if (unwrappedTypes.every(AST.isLiteral)) {
|
|
702
|
+
if (unwrappedTypes.every((_) => isNullishType(_) || S.AST.isLiteral(_))) {
|
|
631
703
|
return {
|
|
632
704
|
...meta,
|
|
633
705
|
type: "select",
|
|
634
|
-
members: unwrappedTypes.map((t) => t.literal)
|
|
706
|
+
members: unwrappedTypes.filter(S.AST.isLiteral).map((t) => t.literal)
|
|
635
707
|
} as FieldMeta
|
|
636
708
|
}
|
|
637
709
|
|
|
@@ -645,7 +717,7 @@ export const createMeta = <T = any>(
|
|
|
645
717
|
} as FieldMeta
|
|
646
718
|
}
|
|
647
719
|
|
|
648
|
-
if (AST.isArrays(property)) {
|
|
720
|
+
if (S.AST.isArrays(property)) {
|
|
649
721
|
return {
|
|
650
722
|
...meta,
|
|
651
723
|
type: "multiple",
|
|
@@ -654,38 +726,7 @@ export const createMeta = <T = any>(
|
|
|
654
726
|
} as FieldMeta
|
|
655
727
|
}
|
|
656
728
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
meta = { ...JSONAnnotation, ...meta }
|
|
660
|
-
|
|
661
|
-
// check the title annotation BEFORE following "from" to detect refinements like S.Int
|
|
662
|
-
let titleType = property.annotations?.title ?? "unknown"
|
|
663
|
-
|
|
664
|
-
// Detect basic types from AST if no title annotation
|
|
665
|
-
if (titleType === "unknown") {
|
|
666
|
-
if (AST.isString(property)) {
|
|
667
|
-
titleType = "string"
|
|
668
|
-
} else if (AST.isNumber(property)) {
|
|
669
|
-
titleType = "number"
|
|
670
|
-
} else if (AST.isBoolean(property)) {
|
|
671
|
-
titleType = "boolean"
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
// if this is S.Int (a refinement), set the type and skip following "from"
|
|
676
|
-
// otherwise we'd lose the "Int" information and get "number" instead
|
|
677
|
-
if (titleType === "Int" || titleType === "int") {
|
|
678
|
-
meta["type"] = "number"
|
|
679
|
-
meta["refinement"] = "int"
|
|
680
|
-
// don't follow "from" for Int refinements
|
|
681
|
-
} else {
|
|
682
|
-
meta["type"] = titleType
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
// Always ensure required is set before returning
|
|
686
|
-
if (!Object.hasOwnProperty.call(meta, "required")) {
|
|
687
|
-
meta["required"] = !nullableOrUndefined
|
|
688
|
-
}
|
|
729
|
+
meta = { ...getJsonSchemaAnnotation(property), ...getFieldMetadataFromAst(property), ...meta }
|
|
689
730
|
|
|
690
731
|
return meta as FieldMeta
|
|
691
732
|
}
|
|
@@ -711,27 +752,21 @@ const flattenMeta = <T>(meta: MetaRecord<T> | FieldMeta, parentKey: string = "")
|
|
|
711
752
|
return result
|
|
712
753
|
}
|
|
713
754
|
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
const metadataFromAst = <_From, To>(
|
|
717
|
-
schema: any // v4 Schema type is complex, use any for now
|
|
755
|
+
const metadataFromAst = <From, To>(
|
|
756
|
+
schema: S.Codec<To, From, never>
|
|
718
757
|
): { meta: MetaRecord<To>; defaultValues: Record<string, any>; unionMeta: Record<string, MetaRecord<To>> } => {
|
|
719
|
-
const ast = schema.ast
|
|
758
|
+
const ast = unwrapDeclaration(schema.ast)
|
|
720
759
|
const newMeta: MetaRecord<To> = {}
|
|
721
760
|
const defaultValues: Record<string, any> = {}
|
|
722
761
|
const unionMeta: Record<string, MetaRecord<To>> = {}
|
|
723
762
|
|
|
724
763
|
// Handle root-level Union types (discriminated unions)
|
|
725
|
-
if (AST.isUnion(ast)) {
|
|
726
|
-
const types = ast.types
|
|
727
|
-
|
|
764
|
+
if (S.AST.isUnion(ast)) {
|
|
728
765
|
// Filter out null/undefined types and unwrap transformations
|
|
729
|
-
const nonNullTypes = types
|
|
730
|
-
.filter((t: any) => !AST.isUndefined(t) && !AST.isNull(t))
|
|
731
|
-
.map(getTransformationFrom)
|
|
766
|
+
const nonNullTypes = getNonNullTypes(ast.types)
|
|
732
767
|
|
|
733
768
|
// Check if this is a discriminated union (all members are structs)
|
|
734
|
-
const allStructs = nonNullTypes.every(
|
|
769
|
+
const allStructs = nonNullTypes.every(S.AST.isObjects)
|
|
735
770
|
|
|
736
771
|
if (allStructs && nonNullTypes.length > 0) {
|
|
737
772
|
// Extract discriminator values from each union member
|
|
@@ -739,14 +774,14 @@ const metadataFromAst = <_From, To>(
|
|
|
739
774
|
|
|
740
775
|
// Store metadata for each union member by its tag value
|
|
741
776
|
for (const memberType of nonNullTypes) {
|
|
742
|
-
if (AST.isObjects(memberType)) {
|
|
777
|
+
if (S.AST.isObjects(memberType)) {
|
|
743
778
|
// Find the discriminator field (usually _tag)
|
|
744
779
|
const tagProp = memberType.propertySignatures.find(
|
|
745
|
-
(p
|
|
780
|
+
(p) => p.name.toString() === "_tag"
|
|
746
781
|
)
|
|
747
782
|
|
|
748
783
|
let tagValue: string | null = null
|
|
749
|
-
if (tagProp && AST.isLiteral(tagProp.type)) {
|
|
784
|
+
if (tagProp && S.AST.isLiteral(tagProp.type)) {
|
|
750
785
|
tagValue = tagProp.type.literal as string
|
|
751
786
|
discriminatorValues.push(tagValue)
|
|
752
787
|
}
|
|
@@ -779,7 +814,7 @@ const metadataFromAst = <_From, To>(
|
|
|
779
814
|
}
|
|
780
815
|
}
|
|
781
816
|
|
|
782
|
-
if (AST.isObjects(ast)) {
|
|
817
|
+
if (S.AST.isObjects(ast)) {
|
|
783
818
|
const meta = createMeta<To>({
|
|
784
819
|
propertySignatures: ast.propertySignatures
|
|
785
820
|
})
|
|
@@ -814,10 +849,10 @@ export const duplicateSchema = <From, To>(
|
|
|
814
849
|
return schema
|
|
815
850
|
}
|
|
816
851
|
|
|
817
|
-
export const generateMetaFromSchema = <
|
|
818
|
-
schema:
|
|
852
|
+
export const generateMetaFromSchema = <From, To>(
|
|
853
|
+
schema: S.Codec<To, From, never>
|
|
819
854
|
): {
|
|
820
|
-
schema:
|
|
855
|
+
schema: S.Codec<To, From, never>
|
|
821
856
|
meta: MetaRecord<To>
|
|
822
857
|
unionMeta: Record<string, MetaRecord<To>>
|
|
823
858
|
} => {
|
|
@@ -833,167 +868,138 @@ export const generateInputStandardSchemaFromFieldMeta = (
|
|
|
833
868
|
if (!trans) {
|
|
834
869
|
trans = useIntl().trans
|
|
835
870
|
}
|
|
836
|
-
let schema:
|
|
837
|
-
|
|
871
|
+
let schema: any
|
|
838
872
|
switch (meta.type) {
|
|
839
|
-
case "string":
|
|
840
|
-
schema =
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
(s) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s) || trans("validation.email.invalid"),
|
|
848
|
-
{ title: "email format" }
|
|
849
|
-
)
|
|
850
|
-
)
|
|
851
|
-
}
|
|
873
|
+
case "string":
|
|
874
|
+
schema = meta.format === "email"
|
|
875
|
+
? S.Email.annotate({
|
|
876
|
+
message: trans("validation.email.invalid")
|
|
877
|
+
})
|
|
878
|
+
: S.String.annotate({
|
|
879
|
+
message: trans("validation.empty")
|
|
880
|
+
})
|
|
852
881
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
schema = schema.check(
|
|
858
|
-
S.makeFilter(
|
|
859
|
-
(s) => s.length >= minLen || trans("validation.string.minLength", { minLength: minLen }),
|
|
860
|
-
{ title: `minLength(${minLen})` }
|
|
861
|
-
)
|
|
862
|
-
)
|
|
863
|
-
}
|
|
882
|
+
if (meta.required) {
|
|
883
|
+
schema = schema.check(S.isMinLength(1, {
|
|
884
|
+
message: trans("validation.empty")
|
|
885
|
+
}))
|
|
864
886
|
}
|
|
865
887
|
|
|
866
888
|
if (typeof meta.maxLength === "number") {
|
|
867
|
-
schema = schema.check(
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
889
|
+
schema = schema.check(S.isMaxLength(meta.maxLength, {
|
|
890
|
+
message: trans("validation.string.maxLength", {
|
|
891
|
+
maxLength: meta.maxLength
|
|
892
|
+
})
|
|
893
|
+
}))
|
|
894
|
+
}
|
|
895
|
+
if (typeof meta.minLength === "number") {
|
|
896
|
+
schema = schema.check(S.isMinLength(meta.minLength, {
|
|
897
|
+
message: trans("validation.string.minLength", {
|
|
898
|
+
minLength: meta.minLength
|
|
899
|
+
})
|
|
900
|
+
}))
|
|
873
901
|
}
|
|
874
902
|
break
|
|
875
|
-
}
|
|
876
903
|
|
|
877
|
-
case "number":
|
|
904
|
+
case "number":
|
|
878
905
|
if (meta.refinement === "int") {
|
|
879
|
-
schema = S
|
|
906
|
+
schema = S
|
|
907
|
+
.Number
|
|
908
|
+
.annotate({
|
|
909
|
+
message: trans("validation.empty")
|
|
910
|
+
})
|
|
911
|
+
.check(S.isInt({
|
|
912
|
+
message: trans("validation.integer.expected", { actualValue: "NaN" })
|
|
913
|
+
}))
|
|
880
914
|
} else {
|
|
881
|
-
schema = S.Number
|
|
915
|
+
schema = S.Number.annotate({
|
|
916
|
+
message: trans("validation.number.expected", { actualValue: "NaN" })
|
|
917
|
+
})
|
|
918
|
+
|
|
919
|
+
if (meta.required) {
|
|
920
|
+
schema = schema.annotate({
|
|
921
|
+
message: trans("validation.empty")
|
|
922
|
+
})
|
|
923
|
+
}
|
|
882
924
|
}
|
|
883
925
|
|
|
884
|
-
// Apply numeric validations
|
|
885
926
|
if (typeof meta.minimum === "number") {
|
|
886
|
-
schema = schema.check(
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
),
|
|
893
|
-
{ title: `>=${meta.minimum}` }
|
|
894
|
-
)
|
|
895
|
-
)
|
|
927
|
+
schema = schema.check(S.isGreaterThanOrEqualTo(meta.minimum, {
|
|
928
|
+
message: trans(meta.minimum === 0 ? "validation.number.positive" : "validation.number.min", {
|
|
929
|
+
minimum: meta.minimum,
|
|
930
|
+
isExclusive: true
|
|
931
|
+
})
|
|
932
|
+
}))
|
|
896
933
|
}
|
|
897
|
-
|
|
898
934
|
if (typeof meta.maximum === "number") {
|
|
899
|
-
schema = schema.check(
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
}),
|
|
906
|
-
{ title: `<=${meta.maximum}` }
|
|
907
|
-
)
|
|
908
|
-
)
|
|
935
|
+
schema = schema.check(S.isLessThanOrEqualTo(meta.maximum, {
|
|
936
|
+
message: trans("validation.number.max", {
|
|
937
|
+
maximum: meta.maximum,
|
|
938
|
+
isExclusive: true
|
|
939
|
+
})
|
|
940
|
+
}))
|
|
909
941
|
}
|
|
910
|
-
|
|
911
942
|
if (typeof meta.exclusiveMinimum === "number") {
|
|
912
|
-
schema = schema.check(
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
),
|
|
919
|
-
{ title: `>${meta.exclusiveMinimum}` }
|
|
920
|
-
)
|
|
921
|
-
)
|
|
943
|
+
schema = schema.check(S.isGreaterThan(meta.exclusiveMinimum, {
|
|
944
|
+
message: trans(meta.exclusiveMinimum === 0 ? "validation.number.positive" : "validation.number.min", {
|
|
945
|
+
minimum: meta.exclusiveMinimum,
|
|
946
|
+
isExclusive: false
|
|
947
|
+
})
|
|
948
|
+
}))
|
|
922
949
|
}
|
|
923
|
-
|
|
924
950
|
if (typeof meta.exclusiveMaximum === "number") {
|
|
925
|
-
schema = schema.check(
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
}),
|
|
932
|
-
{ title: `<${meta.exclusiveMaximum}` }
|
|
933
|
-
)
|
|
934
|
-
)
|
|
951
|
+
schema = schema.check(S.isLessThan(meta.exclusiveMaximum, {
|
|
952
|
+
message: trans("validation.number.max", {
|
|
953
|
+
maximum: meta.exclusiveMaximum,
|
|
954
|
+
isExclusive: false
|
|
955
|
+
})
|
|
956
|
+
}))
|
|
935
957
|
}
|
|
936
958
|
break
|
|
937
|
-
|
|
959
|
+
case "select":
|
|
960
|
+
schema = S.Literals(meta.members as [any, ...any[]]).annotate({
|
|
961
|
+
message: trans("validation.not_a_valid", {
|
|
962
|
+
type: "select",
|
|
963
|
+
message: meta.members.join(", ")
|
|
964
|
+
})
|
|
965
|
+
})
|
|
938
966
|
|
|
939
|
-
case "select": {
|
|
940
|
-
// Use Literal for select options
|
|
941
|
-
if (meta.members.length === 0) {
|
|
942
|
-
schema = S.Unknown
|
|
943
|
-
} else if (meta.members.length === 1) {
|
|
944
|
-
schema = S.Literal(meta.members[0])
|
|
945
|
-
} else {
|
|
946
|
-
// v4 Union accepts an array of schemas
|
|
947
|
-
schema = S.Union(meta.members.map((m) => S.Literal(m)))
|
|
948
|
-
}
|
|
949
967
|
break
|
|
950
|
-
}
|
|
951
968
|
|
|
952
|
-
case "multiple":
|
|
953
|
-
schema = S.Array(S.String)
|
|
969
|
+
case "multiple":
|
|
970
|
+
schema = S.Array(S.String).annotate({
|
|
971
|
+
message: trans("validation.not_a_valid", {
|
|
972
|
+
type: "multiple",
|
|
973
|
+
message: meta.members.join(", ")
|
|
974
|
+
})
|
|
975
|
+
})
|
|
954
976
|
break
|
|
955
|
-
}
|
|
956
977
|
|
|
957
|
-
case "boolean":
|
|
978
|
+
case "boolean":
|
|
958
979
|
schema = S.Boolean
|
|
959
980
|
break
|
|
960
|
-
}
|
|
961
981
|
|
|
962
|
-
case "unknown":
|
|
982
|
+
case "unknown":
|
|
963
983
|
schema = S.Unknown
|
|
964
984
|
break
|
|
965
|
-
}
|
|
966
985
|
|
|
967
|
-
default:
|
|
968
|
-
|
|
986
|
+
default:
|
|
987
|
+
// For any unhandled types, use Unknown schema to prevent undefined errors
|
|
988
|
+
console.warn(`Unhandled field type: ${meta}`)
|
|
969
989
|
schema = S.Unknown
|
|
970
990
|
break
|
|
971
|
-
}
|
|
972
991
|
}
|
|
973
|
-
|
|
974
|
-
// Wrap in union with null/undefined if not required
|
|
975
992
|
if (!meta.required) {
|
|
976
|
-
|
|
977
|
-
schema = S.Union([schema, S.Null, S.Undefined])
|
|
993
|
+
schema = S.NullishOr(schema)
|
|
978
994
|
}
|
|
979
|
-
|
|
980
|
-
return
|
|
995
|
+
const result = S.toStandardSchemaV1(schema as any)
|
|
996
|
+
return result
|
|
981
997
|
}
|
|
982
998
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
// ): S.Codec<A> =>
|
|
988
|
-
// S.NullOr(schema).pipe(
|
|
989
|
-
// S.decodeTo(
|
|
990
|
-
// schema,
|
|
991
|
-
// SchemaTransformation.transform({
|
|
992
|
-
// decode: (input: A | null) => input ?? defaultValue(),
|
|
993
|
-
// encode: (output: A) => output
|
|
994
|
-
// })
|
|
995
|
-
// )
|
|
996
|
-
// )
|
|
999
|
+
export const nullableInput = <A, I, R>(
|
|
1000
|
+
schema: S.Codec<A, I, R>,
|
|
1001
|
+
_defaultValue: () => A
|
|
1002
|
+
) => S.NullOr(schema) as any
|
|
997
1003
|
|
|
998
1004
|
export type OmegaAutoGenMeta<
|
|
999
1005
|
From extends Record<PropertyKey, any>,
|
|
@@ -1039,11 +1045,11 @@ export function deepMerge(target: any, source: any) {
|
|
|
1039
1045
|
|
|
1040
1046
|
// Type definitions for schemas with fields and members
|
|
1041
1047
|
type SchemaWithFields = {
|
|
1042
|
-
fields: Record<string, S.
|
|
1048
|
+
fields: Record<string, S.Schema<any>>
|
|
1043
1049
|
}
|
|
1044
1050
|
|
|
1045
1051
|
type SchemaWithMembers = {
|
|
1046
|
-
members: readonly S.
|
|
1052
|
+
members: readonly S.Schema<any>[]
|
|
1047
1053
|
}
|
|
1048
1054
|
|
|
1049
1055
|
// Type guards to check schema types
|
|
@@ -1057,10 +1063,15 @@ function hasMembers(schema: any): schema is SchemaWithMembers {
|
|
|
1057
1063
|
|
|
1058
1064
|
// Internal implementation with WeakSet tracking
|
|
1059
1065
|
export const defaultsValueFromSchema = (
|
|
1060
|
-
schema: S.
|
|
1066
|
+
schema: S.Schema<any>,
|
|
1061
1067
|
record: Record<string, any> = {}
|
|
1062
1068
|
): any => {
|
|
1063
1069
|
const ast = schema.ast
|
|
1070
|
+
const defaultValue = getDefaultFromAst(ast)
|
|
1071
|
+
|
|
1072
|
+
if (defaultValue !== undefined) {
|
|
1073
|
+
return defaultValue
|
|
1074
|
+
}
|
|
1064
1075
|
|
|
1065
1076
|
if (isNullableOrUndefined(schema.ast) === "null") {
|
|
1066
1077
|
return null
|
|
@@ -1069,35 +1080,7 @@ export const defaultsValueFromSchema = (
|
|
|
1069
1080
|
return undefined
|
|
1070
1081
|
}
|
|
1071
1082
|
|
|
1072
|
-
//
|
|
1073
|
-
if (AST.isObjects(ast)) {
|
|
1074
|
-
const result: Record<string, any> = { ...record }
|
|
1075
|
-
|
|
1076
|
-
for (const prop of ast.propertySignatures) {
|
|
1077
|
-
const key = prop.name.toString()
|
|
1078
|
-
const propType = prop.type
|
|
1079
|
-
|
|
1080
|
-
// Get the property schema from the original schema's fields if available
|
|
1081
|
-
// This preserves schema wrappers like withDefaultConstructor
|
|
1082
|
-
let propSchema: S.Codec<any>
|
|
1083
|
-
if ((schema as any).fields && (schema as any).fields[key]) {
|
|
1084
|
-
propSchema = (schema as any).fields[key]
|
|
1085
|
-
} else {
|
|
1086
|
-
propSchema = S.make(propType)
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
// Recursively process the property to get its defaults
|
|
1090
|
-
const propValue = defaultsValueFromSchema(propSchema, record[key] || {})
|
|
1091
|
-
|
|
1092
|
-
if (propValue !== undefined) {
|
|
1093
|
-
result[key] = propValue
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
return result
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
// v3 compatible fields extraction
|
|
1083
|
+
// Check if schema has fields directly
|
|
1101
1084
|
if (hasFields(schema)) {
|
|
1102
1085
|
// Process fields and extract default values
|
|
1103
1086
|
const result: Record<string, any> = {}
|
|
@@ -1149,6 +1132,10 @@ export const defaultsValueFromSchema = (
|
|
|
1149
1132
|
return acc
|
|
1150
1133
|
}, {} as Record<string, any>)
|
|
1151
1134
|
|
|
1135
|
+
if (Object.keys(mergedMembers).length === 0) {
|
|
1136
|
+
return Object.keys(record).length > 0 ? record : undefined
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1152
1139
|
// Use reduce to properly accumulate the merged fields
|
|
1153
1140
|
return Object.entries(mergedMembers).reduce((acc, [key, value]) => {
|
|
1154
1141
|
acc[key] = defaultsValueFromSchema(value, record[key] || {})
|
|
@@ -1157,18 +1144,41 @@ export const defaultsValueFromSchema = (
|
|
|
1157
1144
|
}
|
|
1158
1145
|
|
|
1159
1146
|
if (Object.keys(record).length === 0) {
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1147
|
+
if (S.AST.isObjects(ast)) {
|
|
1148
|
+
// Process TypeLiteral fields directly to build the result object
|
|
1149
|
+
const result: Record<string, any> = { ...record }
|
|
1150
|
+
|
|
1151
|
+
for (const prop of ast.propertySignatures) {
|
|
1152
|
+
const key = prop.name.toString()
|
|
1153
|
+
const propType = prop.type
|
|
1154
|
+
|
|
1155
|
+
const propDefault = getDefaultFromAst(propType)
|
|
1156
|
+
if (propDefault !== undefined) {
|
|
1157
|
+
result[key] = propDefault
|
|
1158
|
+
continue
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// Create a schema from the property type and get its defaults
|
|
1162
|
+
const propSchema = S.make(propType)
|
|
1163
|
+
|
|
1164
|
+
// Recursively process the property - don't pas for prop processing
|
|
1165
|
+
// to allow proper unwrapping of nested structures
|
|
1166
|
+
const propValue = defaultsValueFromSchema(propSchema, record[key] || {})
|
|
1167
|
+
|
|
1168
|
+
if (propValue !== undefined) {
|
|
1169
|
+
result[key] = propValue
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
return result
|
|
1165
1174
|
}
|
|
1166
|
-
}
|
|
1167
1175
|
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1176
|
+
if (S.AST.isString(ast)) {
|
|
1177
|
+
return ""
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
if (S.AST.isBoolean(ast)) {
|
|
1181
|
+
return false
|
|
1182
|
+
}
|
|
1173
1183
|
}
|
|
1174
1184
|
}
|