@famgia/omnify-typescript 0.0.26 → 0.0.28

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/index.cjs CHANGED
@@ -20,17 +20,23 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ DEFAULT_VALIDATION_TEMPLATES: () => DEFAULT_VALIDATION_TEMPLATES,
23
24
  enumToUnionType: () => enumToUnionType,
24
25
  extractInlineEnums: () => extractInlineEnums,
25
26
  formatEnum: () => formatEnum,
26
27
  formatInterface: () => formatInterface,
27
28
  formatProperty: () => formatProperty,
28
29
  formatTypeAlias: () => formatTypeAlias,
30
+ formatValidationMessage: () => formatValidationMessage,
29
31
  generateEnums: () => generateEnums,
30
32
  generateInterfaces: () => generateInterfaces,
33
+ generateModelRules: () => generateModelRules,
34
+ generateRulesFiles: () => generateRulesFiles,
31
35
  generateTypeScript: () => generateTypeScript,
32
36
  generateTypeScriptFiles: () => generateTypeScript,
33
37
  getPropertyType: () => getPropertyType,
38
+ getValidationMessages: () => getValidationMessages,
39
+ mergeValidationTemplates: () => mergeValidationTemplates,
34
40
  propertyToTSProperty: () => propertyToTSProperty,
35
41
  schemaToEnum: () => schemaToEnum,
36
42
  schemaToInterface: () => schemaToInterface,
@@ -357,11 +363,18 @@ function parseEnumValue(value, options = {}) {
357
363
  // No label or extra - will fallback to value
358
364
  };
359
365
  }
360
- const resolvedLabel = resolveDisplayName2(value.label, options);
366
+ let label;
367
+ if (value.label !== void 0) {
368
+ if (options.multiLocale && typeof value.label === "object") {
369
+ label = value.label;
370
+ } else {
371
+ label = resolveDisplayName2(value.label, options);
372
+ }
373
+ }
361
374
  return {
362
375
  name: toEnumMemberName(value.value),
363
376
  value: value.value,
364
- label: resolvedLabel,
377
+ label,
365
378
  extra: value.extra
366
379
  };
367
380
  }
@@ -391,6 +404,9 @@ function generateEnums(schemas, options = {}) {
391
404
  }
392
405
  return enums;
393
406
  }
407
+ function isMultiLocaleLabel(label) {
408
+ return label !== void 0 && typeof label === "object";
409
+ }
394
410
  function formatEnum(enumDef) {
395
411
  const { name, values, comment } = enumDef;
396
412
  const parts = [];
@@ -421,28 +437,64 @@ ${enumValues}
421
437
 
422
438
  `);
423
439
  const hasLabels = values.some((v) => v.label !== void 0);
440
+ const hasMultiLocale = values.some((v) => isMultiLocaleLabel(v.label));
424
441
  if (hasLabels) {
425
- const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${v.label}',`).join("\n");
426
- parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, string>> = {
442
+ if (hasMultiLocale) {
443
+ const labelEntries = values.filter((v) => v.label !== void 0).map((v) => {
444
+ if (isMultiLocaleLabel(v.label)) {
445
+ const locales = Object.entries(v.label).map(([locale, text]) => `${locale}: '${text}'`).join(", ");
446
+ return ` [${name}.${v.name}]: { ${locales} },`;
447
+ }
448
+ return ` [${name}.${v.name}]: { default: '${v.label}' },`;
449
+ }).join("\n");
450
+ parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, Record<string, string>>> = {
427
451
  ${labelEntries}
428
452
  };
429
453
 
430
454
  `);
431
- }
432
- parts.push(`/** Get label for ${name} value (fallback to value if no label) */
455
+ parts.push(`/** Get label for ${name} value with locale support */
433
456
  `);
434
- parts.push(`export function get${name}Label(value: ${name}): string {
457
+ parts.push(`export function get${name}Label(value: ${name}, locale?: string): string {
435
458
  `);
436
- if (hasLabels) {
437
- parts.push(` return ${lowerFirst(name)}Labels[value] ?? value;
459
+ parts.push(` const labels = ${lowerFirst(name)}Labels[value];
460
+ `);
461
+ parts.push(` if (!labels) return value;
462
+ `);
463
+ parts.push(` if (locale && labels[locale]) return labels[locale];
464
+ `);
465
+ parts.push(` return Object.values(labels)[0] ?? value;
466
+ `);
467
+ parts.push(`}
468
+
469
+ `);
470
+ } else {
471
+ const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${v.label}',`).join("\n");
472
+ parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, string>> = {
473
+ ${labelEntries}
474
+ };
475
+
438
476
  `);
477
+ parts.push(`/** Get label for ${name} value (fallback to value if no label) */
478
+ `);
479
+ parts.push(`export function get${name}Label(value: ${name}): string {
480
+ `);
481
+ parts.push(` return ${lowerFirst(name)}Labels[value] ?? value;
482
+ `);
483
+ parts.push(`}
484
+
485
+ `);
486
+ }
439
487
  } else {
488
+ parts.push(`/** Get label for ${name} value (returns value as-is) */
489
+ `);
490
+ parts.push(`export function get${name}Label(value: ${name}): string {
491
+ `);
440
492
  parts.push(` return value;
441
493
  `);
442
- }
443
- parts.push(`}
494
+ parts.push(`}
444
495
 
445
496
  `);
497
+ }
446
498
  const hasExtra = values.some((v) => v.extra !== void 0);
447
499
  if (hasExtra) {
448
500
  const extraEntries = values.filter((v) => v.extra !== void 0).map((v) => ` [${name}.${v.name}]: ${JSON.stringify(v.extra)},`).join("\n");
@@ -564,6 +616,347 @@ function extractInlineEnums(schemas, options = {}) {
564
616
  return typeAliases;
565
617
  }
566
618
 
619
+ // src/validation-templates.ts
620
+ var DEFAULT_VALIDATION_TEMPLATES = {
621
+ required: {
622
+ ja: "${displayName}\u306F\u5FC5\u9808\u3067\u3059",
623
+ en: "${displayName} is required",
624
+ vi: "${displayName} l\xE0 b\u1EAFt bu\u1ED9c",
625
+ ko: "${displayName}\uC740(\uB294) \uD544\uC218\uC785\uB2C8\uB2E4",
626
+ zh: "${displayName}\u4E3A\u5FC5\u586B\u9879"
627
+ },
628
+ minLength: {
629
+ ja: "${displayName}\u306F${min}\u6587\u5B57\u4EE5\u4E0A\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
630
+ en: "${displayName} must be at least ${min} characters",
631
+ vi: "${displayName} ph\u1EA3i c\xF3 \xEDt nh\u1EA5t ${min} k\xFD t\u1EF1",
632
+ ko: "${displayName}\uC740(\uB294) ${min}\uC790 \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
633
+ zh: "${displayName}\u81F3\u5C11\u9700\u8981${min}\u4E2A\u5B57\u7B26"
634
+ },
635
+ maxLength: {
636
+ ja: "${displayName}\u306F${max}\u6587\u5B57\u4EE5\u5185\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
637
+ en: "${displayName} must be at most ${max} characters",
638
+ vi: "${displayName} t\u1ED1i \u0111a ${max} k\xFD t\u1EF1",
639
+ ko: "${displayName}\uC740(\uB294) ${max}\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
640
+ zh: "${displayName}\u4E0D\u80FD\u8D85\u8FC7${max}\u4E2A\u5B57\u7B26"
641
+ },
642
+ min: {
643
+ ja: "${displayName}\u306F${min}\u4EE5\u4E0A\u306E\u5024\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
644
+ en: "${displayName} must be at least ${min}",
645
+ vi: "${displayName} ph\u1EA3i l\u1EDBn h\u01A1n ho\u1EB7c b\u1EB1ng ${min}",
646
+ ko: "${displayName}\uC740(\uB294) ${min} \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
647
+ zh: "${displayName}\u4E0D\u80FD\u5C0F\u4E8E${min}"
648
+ },
649
+ max: {
650
+ ja: "${displayName}\u306F${max}\u4EE5\u4E0B\u306E\u5024\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
651
+ en: "${displayName} must be at most ${max}",
652
+ vi: "${displayName} ph\u1EA3i nh\u1ECF h\u01A1n ho\u1EB7c b\u1EB1ng ${max}",
653
+ ko: "${displayName}\uC740(\uB294) ${max} \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
654
+ zh: "${displayName}\u4E0D\u80FD\u5927\u4E8E${max}"
655
+ },
656
+ email: {
657
+ ja: "${displayName}\u306E\u5F62\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093",
658
+ en: "${displayName} is not a valid email address",
659
+ vi: "${displayName} kh\xF4ng ph\u1EA3i l\xE0 \u0111\u1ECBa ch\u1EC9 email h\u1EE3p l\u1EC7",
660
+ ko: "${displayName} \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
661
+ zh: "${displayName}\u4E0D\u662F\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740"
662
+ },
663
+ url: {
664
+ ja: "${displayName}\u306F\u6709\u52B9\u306AURL\u3067\u306F\u3042\u308A\u307E\u305B\u3093",
665
+ en: "${displayName} is not a valid URL",
666
+ vi: "${displayName} kh\xF4ng ph\u1EA3i l\xE0 URL h\u1EE3p l\u1EC7",
667
+ ko: "${displayName}\uC740(\uB294) \uC720\uD6A8\uD55C URL\uC774 \uC544\uB2D9\uB2C8\uB2E4",
668
+ zh: "${displayName}\u4E0D\u662F\u6709\u6548\u7684URL"
669
+ },
670
+ pattern: {
671
+ ja: "${displayName}\u306E\u5F62\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093",
672
+ en: "${displayName} format is invalid",
673
+ vi: "${displayName} kh\xF4ng \u0111\xFAng \u0111\u1ECBnh d\u1EA1ng",
674
+ ko: "${displayName} \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
675
+ zh: "${displayName}\u683C\u5F0F\u4E0D\u6B63\u786E"
676
+ },
677
+ enum: {
678
+ ja: "${displayName}\u306E\u5024\u304C\u7121\u52B9\u3067\u3059",
679
+ en: "${displayName} has an invalid value",
680
+ vi: "${displayName} c\xF3 gi\xE1 tr\u1ECB kh\xF4ng h\u1EE3p l\u1EC7",
681
+ ko: "${displayName} \uAC12\uC774 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
682
+ zh: "${displayName}\u7684\u503C\u65E0\u6548"
683
+ }
684
+ };
685
+ function mergeValidationTemplates(userTemplates) {
686
+ if (!userTemplates) {
687
+ return DEFAULT_VALIDATION_TEMPLATES;
688
+ }
689
+ const merged = {
690
+ required: { ...DEFAULT_VALIDATION_TEMPLATES.required },
691
+ minLength: { ...DEFAULT_VALIDATION_TEMPLATES.minLength },
692
+ maxLength: { ...DEFAULT_VALIDATION_TEMPLATES.maxLength },
693
+ min: { ...DEFAULT_VALIDATION_TEMPLATES.min },
694
+ max: { ...DEFAULT_VALIDATION_TEMPLATES.max },
695
+ email: { ...DEFAULT_VALIDATION_TEMPLATES.email },
696
+ url: { ...DEFAULT_VALIDATION_TEMPLATES.url },
697
+ pattern: { ...DEFAULT_VALIDATION_TEMPLATES.pattern },
698
+ enum: { ...DEFAULT_VALIDATION_TEMPLATES.enum }
699
+ };
700
+ for (const [key, value] of Object.entries(userTemplates)) {
701
+ if (value && key in merged) {
702
+ merged[key] = {
703
+ ...merged[key],
704
+ ...value
705
+ };
706
+ }
707
+ }
708
+ return merged;
709
+ }
710
+ function formatValidationMessage(template, vars) {
711
+ let result = template;
712
+ for (const [key, value] of Object.entries(vars)) {
713
+ result = result.replace(new RegExp(`\\$\\{${key}\\}`, "g"), String(value));
714
+ }
715
+ return result;
716
+ }
717
+ function getValidationMessages(templates, ruleType, locales, vars, fallbackLocale) {
718
+ const ruleTemplates = templates[ruleType];
719
+ const messages = {};
720
+ for (const locale of locales) {
721
+ const template = ruleTemplates[locale] ?? (fallbackLocale ? ruleTemplates[fallbackLocale] : void 0) ?? ruleTemplates["en"] ?? "";
722
+ messages[locale] = formatValidationMessage(template, vars);
723
+ }
724
+ return messages;
725
+ }
726
+
727
+ // src/rules-generator.ts
728
+ function getMultiLocaleDisplayName(value, locales, fallbackLocale, defaultValue) {
729
+ if (!value) {
730
+ const result2 = {};
731
+ for (const locale of locales) {
732
+ result2[locale] = defaultValue;
733
+ }
734
+ return result2;
735
+ }
736
+ if (typeof value === "string") {
737
+ const result2 = {};
738
+ for (const locale of locales) {
739
+ result2[locale] = value;
740
+ }
741
+ return result2;
742
+ }
743
+ const result = {};
744
+ for (const locale of locales) {
745
+ result[locale] = value[locale] ?? value[fallbackLocale] ?? value["en"] ?? defaultValue;
746
+ }
747
+ return result;
748
+ }
749
+ function generatePropertyRules(propName, property, displayName, locales, fallbackLocale, templates) {
750
+ const rules = [];
751
+ const propDef = property;
752
+ if (!propDef.nullable) {
753
+ rules.push({
754
+ required: true,
755
+ message: getValidationMessages(templates, "required", locales, { displayName: "${displayName}" }, fallbackLocale)
756
+ });
757
+ }
758
+ if (property.type === "Email") {
759
+ rules.push({
760
+ type: "email",
761
+ message: getValidationMessages(templates, "email", locales, { displayName: "${displayName}" }, fallbackLocale)
762
+ });
763
+ }
764
+ if (property.type === "String" || property.type === "Text" || property.type === "LongText") {
765
+ if (propDef.minLength) {
766
+ rules.push({
767
+ min: propDef.minLength,
768
+ message: getValidationMessages(templates, "minLength", locales, { displayName: "${displayName}", min: propDef.minLength }, fallbackLocale)
769
+ });
770
+ }
771
+ if (propDef.maxLength || propDef.length) {
772
+ const max = propDef.maxLength ?? propDef.length;
773
+ rules.push({
774
+ max,
775
+ message: getValidationMessages(templates, "maxLength", locales, { displayName: "${displayName}", max }, fallbackLocale)
776
+ });
777
+ }
778
+ }
779
+ if (property.type === "Int" || property.type === "BigInt" || property.type === "Float") {
780
+ if (propDef.min !== void 0) {
781
+ rules.push({
782
+ type: property.type === "Float" ? "number" : "integer",
783
+ min: propDef.min,
784
+ message: getValidationMessages(templates, "min", locales, { displayName: "${displayName}", min: propDef.min }, fallbackLocale)
785
+ });
786
+ }
787
+ if (propDef.max !== void 0) {
788
+ rules.push({
789
+ type: property.type === "Float" ? "number" : "integer",
790
+ max: propDef.max,
791
+ message: getValidationMessages(templates, "max", locales, { displayName: "${displayName}", max: propDef.max }, fallbackLocale)
792
+ });
793
+ }
794
+ }
795
+ if (propDef.pattern) {
796
+ rules.push({
797
+ pattern: propDef.pattern,
798
+ message: getValidationMessages(templates, "pattern", locales, { displayName: "${displayName}" }, fallbackLocale)
799
+ });
800
+ }
801
+ for (const rule of rules) {
802
+ const newMessage = {};
803
+ for (const locale of locales) {
804
+ const msg = rule.message[locale];
805
+ if (msg) {
806
+ newMessage[locale] = msg.replace(/\$\{displayName\}/g, displayName[locale] ?? propName);
807
+ }
808
+ }
809
+ rule.message = newMessage;
810
+ }
811
+ return rules;
812
+ }
813
+ function generateModelRules(schema, locales, fallbackLocale, templates) {
814
+ const modelDisplayName = getMultiLocaleDisplayName(
815
+ schema.displayName,
816
+ locales,
817
+ fallbackLocale,
818
+ schema.name
819
+ );
820
+ const properties = {};
821
+ if (schema.properties) {
822
+ for (const [propName, property] of Object.entries(schema.properties)) {
823
+ const propDef = property;
824
+ const displayName = getMultiLocaleDisplayName(
825
+ propDef.displayName,
826
+ locales,
827
+ fallbackLocale,
828
+ propName
829
+ );
830
+ properties[propName] = {
831
+ displayName,
832
+ rules: generatePropertyRules(propName, property, displayName, locales, fallbackLocale, templates)
833
+ };
834
+ }
835
+ }
836
+ return {
837
+ displayName: modelDisplayName,
838
+ properties
839
+ };
840
+ }
841
+ function formatRulesFile(schemaName, rules) {
842
+ const parts = [];
843
+ parts.push(`/**
844
+ * Auto-generated validation rules and metadata for ${schemaName}.
845
+ * DO NOT EDIT - This file is automatically generated and will be overwritten.
846
+ */
847
+
848
+ `);
849
+ parts.push(`export interface LocaleMap { [locale: string]: string; }
850
+
851
+ `);
852
+ parts.push(`export interface ValidationRule {
853
+ required?: boolean;
854
+ type?: 'string' | 'number' | 'email' | 'url' | 'integer';
855
+ min?: number;
856
+ max?: number;
857
+ len?: number;
858
+ pattern?: RegExp;
859
+ message: LocaleMap;
860
+ }
861
+
862
+ `);
863
+ parts.push(`/** Display name for ${schemaName} */
864
+ `);
865
+ parts.push(`export const ${schemaName}DisplayName: LocaleMap = ${JSON.stringify(rules.displayName, null, 2)};
866
+
867
+ `);
868
+ parts.push(`/** Property display names for ${schemaName} */
869
+ `);
870
+ parts.push(`export const ${schemaName}PropertyDisplayNames: Record<string, LocaleMap> = {
871
+ `);
872
+ for (const [propName, propRules] of Object.entries(rules.properties)) {
873
+ parts.push(` ${propName}: ${JSON.stringify(propRules.displayName)},
874
+ `);
875
+ }
876
+ parts.push(`};
877
+
878
+ `);
879
+ parts.push(`/** Validation rules for ${schemaName} (Ant Design compatible) */
880
+ `);
881
+ parts.push(`export const ${schemaName}Rules: Record<string, ValidationRule[]> = {
882
+ `);
883
+ for (const [propName, propRules] of Object.entries(rules.properties)) {
884
+ if (propRules.rules.length > 0) {
885
+ parts.push(` ${propName}: [
886
+ `);
887
+ for (const rule of propRules.rules) {
888
+ const ruleObj = {};
889
+ if (rule.required) ruleObj.required = true;
890
+ if (rule.type) ruleObj.type = `'${rule.type}'`;
891
+ if (rule.min !== void 0) ruleObj.min = rule.min;
892
+ if (rule.max !== void 0) ruleObj.max = rule.max;
893
+ if (rule.pattern) ruleObj.pattern = `/${rule.pattern}/`;
894
+ ruleObj.message = rule.message;
895
+ const ruleStr = Object.entries(ruleObj).map(([k, v]) => {
896
+ if (k === "type") return `${k}: ${v}`;
897
+ if (k === "pattern") return `${k}: ${v}`;
898
+ return `${k}: ${JSON.stringify(v)}`;
899
+ }).join(", ");
900
+ parts.push(` { ${ruleStr} },
901
+ `);
902
+ }
903
+ parts.push(` ],
904
+ `);
905
+ }
906
+ }
907
+ parts.push(`};
908
+
909
+ `);
910
+ parts.push(`/** Get validation rules with messages for a specific locale */
911
+ `);
912
+ parts.push(`export function get${schemaName}Rules(locale: string): Record<string, Array<{ required?: boolean; type?: string; min?: number; max?: number; pattern?: RegExp; message: string }>> {
913
+ const result: Record<string, Array<{ required?: boolean; type?: string; min?: number; max?: number; pattern?: RegExp; message: string }>> = {};
914
+ for (const [prop, rules] of Object.entries(${schemaName}Rules)) {
915
+ result[prop] = rules.map(rule => ({
916
+ ...rule,
917
+ message: rule.message[locale] ?? rule.message['en'] ?? '',
918
+ }));
919
+ }
920
+ return result;
921
+ }
922
+
923
+ `);
924
+ parts.push(`/** Get display name for a specific locale */
925
+ `);
926
+ parts.push(`export function get${schemaName}DisplayName(locale: string): string {
927
+ return ${schemaName}DisplayName[locale] ?? ${schemaName}DisplayName['en'] ?? '${schemaName}';
928
+ }
929
+
930
+ `);
931
+ parts.push(`/** Get property display name for a specific locale */
932
+ `);
933
+ parts.push(`export function get${schemaName}PropertyDisplayName(property: string, locale: string): string {
934
+ const names = ${schemaName}PropertyDisplayNames[property];
935
+ return names?.[locale] ?? names?.['en'] ?? property;
936
+ }
937
+ `);
938
+ return parts.join("");
939
+ }
940
+ function generateRulesFiles(schemas, options = {}) {
941
+ const files = [];
942
+ const localeConfig = options.localeConfig;
943
+ const locales = [...localeConfig?.locales ?? ["en"]];
944
+ const fallbackLocale = localeConfig?.fallbackLocale ?? "en";
945
+ const templates = mergeValidationTemplates(options.validationTemplates);
946
+ for (const schema of Object.values(schemas)) {
947
+ if (schema.kind === "enum") continue;
948
+ const rules = generateModelRules(schema, locales, fallbackLocale, templates);
949
+ const content = formatRulesFile(schema.name, rules);
950
+ files.push({
951
+ filePath: `rules/${schema.name}.rules.ts`,
952
+ content,
953
+ types: [`${schema.name}Rules`, `${schema.name}DisplayName`],
954
+ overwrite: true
955
+ });
956
+ }
957
+ return files;
958
+ }
959
+
567
960
  // src/generator.ts
568
961
  var DEFAULT_OPTIONS = {
569
962
  readonly: true,
@@ -718,11 +1111,11 @@ function generateIndexFile(schemas, enums, typeAliases) {
718
1111
  function generateTypeScript(schemas, options = {}) {
719
1112
  const opts = { ...DEFAULT_OPTIONS, ...options };
720
1113
  const files = [];
721
- const enums = generateEnums(schemas);
1114
+ const enums = generateEnums(schemas, opts);
722
1115
  for (const enumDef of enums) {
723
1116
  files.push(generateEnumFile(enumDef));
724
1117
  }
725
- const typeAliases = extractInlineEnums(schemas);
1118
+ const typeAliases = extractInlineEnums(schemas, opts);
726
1119
  for (const alias of typeAliases) {
727
1120
  files.push(generateTypeAliasFile(alias));
728
1121
  }
@@ -734,22 +1127,32 @@ function generateTypeScript(schemas, options = {}) {
734
1127
  if (schema.kind === "enum") continue;
735
1128
  files.push(generateModelFile(schema.name));
736
1129
  }
1130
+ if (opts.generateRules) {
1131
+ const rulesFiles = generateRulesFiles(schemas, opts);
1132
+ files.push(...rulesFiles);
1133
+ }
737
1134
  files.push(generateIndexFile(schemas, enums, typeAliases));
738
1135
  return files;
739
1136
  }
740
1137
  // Annotate the CommonJS export names for ESM import in node:
741
1138
  0 && (module.exports = {
1139
+ DEFAULT_VALIDATION_TEMPLATES,
742
1140
  enumToUnionType,
743
1141
  extractInlineEnums,
744
1142
  formatEnum,
745
1143
  formatInterface,
746
1144
  formatProperty,
747
1145
  formatTypeAlias,
1146
+ formatValidationMessage,
748
1147
  generateEnums,
749
1148
  generateInterfaces,
1149
+ generateModelRules,
1150
+ generateRulesFiles,
750
1151
  generateTypeScript,
751
1152
  generateTypeScriptFiles,
752
1153
  getPropertyType,
1154
+ getValidationMessages,
1155
+ mergeValidationTemplates,
753
1156
  propertyToTSProperty,
754
1157
  schemaToEnum,
755
1158
  schemaToInterface,