@typia/utils 13.0.0-dev.20260426 → 13.0.0-dev.20260427-2

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.
@@ -200,29 +200,29 @@ export namespace LlmSchemaConverter {
200
200
  },
201
201
  };
202
202
 
203
- const convertConstant = (
204
- input: OpenApi.IJsonSchema.IConstant,
205
- ): ILlmSchema | null => {
206
- if (input.const === null)
207
- return {
208
- type: "null",
209
- };
210
- if (typeof input.const === "boolean")
211
- return {
212
- type: "boolean",
213
- enum: [input.const],
214
- };
215
- if (typeof input.const === "string")
216
- return {
217
- type: "string",
218
- enum: [input.const],
219
- };
220
- if (typeof input.const === "number")
221
- return {
222
- type: Number.isInteger(input.const) ? "integer" : "number",
223
- enum: [input.const],
224
- };
225
- return null;
203
+ const visitConstant = (input: OpenApi.IJsonSchema): void => {
204
+ const insert = (value: any): void => {
205
+ const matched:
206
+ | ILlmSchema.IString
207
+ | ILlmSchema.INumber
208
+ | ILlmSchema.IBoolean
209
+ | undefined = union.find(
210
+ (u) =>
211
+ (u as (IJsonSchemaAttribute & { type: string }) | undefined)
212
+ ?.type === typeof value,
213
+ ) as ILlmSchema.IString | undefined;
214
+ if (matched !== undefined) {
215
+ matched.enum ??= [];
216
+ matched.enum.push(value);
217
+ } else
218
+ union.push({
219
+ type: typeof value as "number",
220
+ enum: [value],
221
+ });
222
+ };
223
+ if (OpenApiTypeChecker.isConstant(input)) insert(input.const);
224
+ else if (OpenApiTypeChecker.isOneOf(input))
225
+ input.oneOf.forEach(visitConstant);
226
226
  };
227
227
  const visit = (input: OpenApi.IJsonSchema, accessor: string): void => {
228
228
  if (OpenApiTypeChecker.isOneOf(input)) {
@@ -347,9 +347,6 @@ export namespace LlmSchemaConverter {
347
347
  items: items.value,
348
348
  },
349
349
  );
350
- } else if (OpenApiTypeChecker.isConstant(input)) {
351
- const constant: ILlmSchema | null = convertConstant(input);
352
- if (constant !== null) union.push(constant);
353
350
  } else if (OpenApiTypeChecker.isString(input))
354
351
  union.push(
355
352
  props.config.strict === true
@@ -371,8 +368,8 @@ export namespace LlmSchemaConverter {
371
368
  union.push({ ...input });
372
369
  };
373
370
 
371
+ visitConstant(props.schema);
374
372
  visit(props.schema, props.accessor ?? "$input.schema");
375
- const normalized: ILlmSchema[] = normalizeLlmUnion(union);
376
373
 
377
374
  if (reasons.length > 0)
378
375
  return {
@@ -383,7 +380,7 @@ export namespace LlmSchemaConverter {
383
380
  reasons,
384
381
  },
385
382
  };
386
- else if (normalized.length === 0)
383
+ else if (union.length === 0)
387
384
  return {
388
385
  // unknown type
389
386
  success: true,
@@ -392,25 +389,25 @@ export namespace LlmSchemaConverter {
392
389
  type: undefined,
393
390
  },
394
391
  };
395
- else if (normalized.length === 1)
392
+ else if (union.length === 1)
396
393
  return {
397
394
  // single type
398
395
  success: true,
399
396
  value: {
400
397
  ...attribute,
401
- ...normalized[0],
398
+ ...union[0],
402
399
  description:
403
400
  props.config.strict === true &&
404
- LlmTypeChecker.isReference(normalized[0]!)
401
+ LlmTypeChecker.isReference(union[0]!)
405
402
  ? undefined
406
- : (normalized[0]!.description ?? attribute.description),
403
+ : (union[0]!.description ?? attribute.description),
407
404
  },
408
405
  };
409
406
  return {
410
407
  success: true,
411
408
  value: {
412
409
  ...attribute,
413
- anyOf: normalized.map((u) => ({
410
+ anyOf: union.map((u) => ({
414
411
  ...u,
415
412
  description:
416
413
  props.config.strict === true && LlmTypeChecker.isReference(u)
@@ -420,8 +417,8 @@ export namespace LlmSchemaConverter {
420
417
  "x-discriminator":
421
418
  OpenApiTypeChecker.isOneOf(props.schema) &&
422
419
  props.schema.discriminator !== undefined &&
423
- props.schema.oneOf.length === normalized.length &&
424
- normalized.every(
420
+ props.schema.oneOf.length === union.length &&
421
+ union.every(
425
422
  (e) => LlmTypeChecker.isReference(e) || LlmTypeChecker.isNull(e),
426
423
  )
427
424
  ? {
@@ -436,11 +433,7 @@ export namespace LlmSchemaConverter {
436
433
  ],
437
434
  ),
438
435
  )
439
- : discriminatorMapping({
440
- propertyName: props.schema.discriminator.propertyName,
441
- refs: normalized.filter(LlmTypeChecker.isReference),
442
- $defs: props.$defs,
443
- }),
436
+ : undefined,
444
437
  }
445
438
  : undefined,
446
439
  },
@@ -599,118 +592,6 @@ export namespace LlmSchemaConverter {
599
592
  };
600
593
  }
601
594
 
602
- const discriminatorMapping = (props: {
603
- propertyName: string;
604
- refs: ILlmSchema.IReference[];
605
- $defs: Record<string, ILlmSchema>;
606
- }): Record<string, string> | undefined => {
607
- const entries: Array<[string, string]> = props.refs.flatMap((ref) => {
608
- const key: string =
609
- ref.$ref.split("#/$defs/")[1] ?? ref.$ref.split("/").at(-1)!;
610
- const schema: ILlmSchema | undefined = props.$defs[key];
611
- if (!schema || !LlmTypeChecker.isObject(schema)) return [];
612
- const literals: string[] = llmDiscriminatorLiterals(
613
- schema.properties[props.propertyName],
614
- props.$defs,
615
- );
616
- return literals.map((literal) => [literal, ref.$ref] as [string, string]);
617
- });
618
- return entries.length !== 0 ? Object.fromEntries(entries) : undefined;
619
- };
620
-
621
- const llmDiscriminatorLiterals = (
622
- schema: ILlmSchema | undefined,
623
- $defs: Record<string, ILlmSchema>,
624
- ): string[] => {
625
- if (schema === undefined) return [];
626
- if (LlmTypeChecker.isReference(schema)) {
627
- const key: string =
628
- schema.$ref.split("#/$defs/")[1] ?? schema.$ref.split("/").at(-1)!;
629
- return llmDiscriminatorLiterals($defs[key], $defs);
630
- }
631
- if (LlmTypeChecker.isString(schema)) return schema.enum ?? [];
632
- if (LlmTypeChecker.isAnyOf(schema))
633
- return schema.anyOf.flatMap((child) => llmDiscriminatorLiterals(child, $defs));
634
- return [];
635
- };
636
-
637
- const normalizeLlmUnion = (union: ILlmSchema[]): ILlmSchema[] => {
638
- if (union.length <= 1) return union;
639
- if (union.every(isEnumOnlyString)) {
640
- return [
641
- {
642
- type: "string",
643
- enum: uniqueEnumValues(union.flatMap((schema) => schema.enum ?? [])),
644
- },
645
- ];
646
- }
647
- if (union.every(isEnumOnlyBoolean)) {
648
- return [
649
- {
650
- type: "boolean",
651
- enum: uniqueEnumValues(union.flatMap((schema) => schema.enum ?? [])),
652
- },
653
- ];
654
- }
655
- if (union.every(isEnumOnlyInteger)) {
656
- return [
657
- {
658
- type: "integer",
659
- enum: uniqueEnumValues(union.flatMap((schema) => schema.enum ?? [])),
660
- },
661
- ];
662
- }
663
- if (union.every(isEnumOnlyNumber)) {
664
- return [
665
- {
666
- type: "number",
667
- enum: uniqueEnumValues(union.flatMap((schema) => schema.enum ?? [])),
668
- },
669
- ];
670
- }
671
- return union;
672
- };
673
-
674
- const isEnumOnlyString = (
675
- schema: ILlmSchema,
676
- ): schema is ILlmSchema.IString & { enum: string[] } =>
677
- LlmTypeChecker.isString(schema) &&
678
- Array.isArray(schema.enum) &&
679
- schema.enum.length !== 0 &&
680
- primitiveSchemaHasOnlyEnum(schema);
681
-
682
- const isEnumOnlyBoolean = (
683
- schema: ILlmSchema,
684
- ): schema is ILlmSchema.IBoolean & { enum: boolean[] } =>
685
- LlmTypeChecker.isBoolean(schema) &&
686
- Array.isArray(schema.enum) &&
687
- schema.enum.length !== 0 &&
688
- primitiveSchemaHasOnlyEnum(schema);
689
-
690
- const isEnumOnlyInteger = (
691
- schema: ILlmSchema,
692
- ): schema is ILlmSchema.IInteger & { enum: number[] } =>
693
- LlmTypeChecker.isInteger(schema) &&
694
- Array.isArray(schema.enum) &&
695
- schema.enum.length !== 0 &&
696
- primitiveSchemaHasOnlyEnum(schema);
697
-
698
- const isEnumOnlyNumber = (
699
- schema: ILlmSchema,
700
- ): schema is ILlmSchema.INumber & { enum: number[] } =>
701
- LlmTypeChecker.isNumber(schema) &&
702
- Array.isArray(schema.enum) &&
703
- schema.enum.length !== 0 &&
704
- primitiveSchemaHasOnlyEnum(schema);
705
-
706
- const primitiveSchemaHasOnlyEnum = (schema: ILlmSchema): boolean =>
707
- Object.entries(schema).every(([key, value]) => {
708
- if (value === undefined) return true;
709
- return key === "type" || key === "enum";
710
- });
711
-
712
- const uniqueEnumValues = <T>(values: T[]): T[] => Array.from(new Set(values));
713
-
714
595
  const validateStrict = (
715
596
  schema: OpenApi.IJsonSchema,
716
597
  accessor: string,
@@ -532,13 +532,10 @@ export namespace OpenApiV3_1Upgrader {
532
532
  items: undefined!,
533
533
  prefixItems: schema.prefixItems.map(convertSchema(components)),
534
534
  additionalItems:
535
- schema.items !== undefined &&
536
- Array.isArray(schema.items) === false
537
- ? convertSchema(components)(schema.items)
538
- : typeof schema.additionalItems === "object" &&
539
- schema.additionalItems !== null
540
- ? convertSchema(components)(schema.additionalItems)
541
- : schema.additionalItems,
535
+ typeof schema.additionalItems === "object" &&
536
+ schema.additionalItems !== null
537
+ ? convertSchema(components)(schema.additionalItems)
538
+ : schema.additionalItems,
542
539
  },
543
540
  });
544
541
  else if (schema.items === undefined)
@@ -301,10 +301,10 @@ function findMatchingObjectInAnyOf(
301
301
  if (!LlmTypeChecker.isObject(resolved)) continue;
302
302
  const propSchema: ILlmSchema | undefined = resolved.properties?.[key];
303
303
  if (propSchema === undefined) continue;
304
- const literals: string[] = discriminatorLiterals(propSchema, $defs);
304
+ const resolvedProp: ILlmSchema = resolveSchema(propSchema, $defs);
305
305
  if (
306
- typeof discriminatorValue === "string" &&
307
- literals.includes(discriminatorValue)
306
+ LlmTypeChecker.isString(resolvedProp) &&
307
+ resolvedProp.enum?.includes(discriminatorValue as string)
308
308
  ) {
309
309
  return s;
310
310
  }
@@ -312,21 +312,3 @@ function findMatchingObjectInAnyOf(
312
312
 
313
313
  return undefined;
314
314
  }
315
-
316
- function discriminatorLiterals(
317
- schema: ILlmSchema,
318
- $defs: Record<string, ILlmSchema> | undefined,
319
- ): string[] {
320
- const resolved: ILlmSchema = resolveSchema(schema, $defs);
321
- if (LlmTypeChecker.isString(resolved)) return resolved.enum ?? [];
322
- if (
323
- "const" in resolved &&
324
- typeof (resolved as { const?: unknown }).const === "string"
325
- ) {
326
- return [(resolved as { const: string }).const];
327
- }
328
- if (LlmTypeChecker.isAnyOf(resolved)) {
329
- return resolved.anyOf.flatMap((child) => discriminatorLiterals(child, $defs));
330
- }
331
- return [];
332
- }