@famgia/omnify-typescript 0.0.25 → 0.0.27

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.
@@ -117,6 +117,18 @@ function propertyToTSProperties(propertyName, property, allSchemas, options = {}
117
117
  comment: `${displayName ?? propertyName} (${field.suffix})`
118
118
  });
119
119
  }
120
+ if (customType.accessors) {
121
+ for (const accessor of customType.accessors) {
122
+ const accessorName = `${propertyName}_${toSnakeCase(accessor.name)}`;
123
+ expandedProps.push({
124
+ name: accessorName,
125
+ type: "string | null",
126
+ optional: true,
127
+ readonly: isReadonly,
128
+ comment: `${displayName ?? propertyName} (computed)`
129
+ });
130
+ }
131
+ }
120
132
  return expandedProps;
121
133
  }
122
134
  if (customType && !customType.compound) {
@@ -174,8 +186,22 @@ function propertyToTSProperties(propertyName, property, allSchemas, options = {}
174
186
  function propertyToTSProperty(propertyName, property, allSchemas, options = {}) {
175
187
  return propertyToTSProperties(propertyName, property, allSchemas, options)[0];
176
188
  }
189
+ function extractTypeReferences(type, allSchemaNames) {
190
+ const primitives = /* @__PURE__ */ new Set(["string", "number", "boolean", "unknown", "null", "undefined", "void", "never", "any"]);
191
+ const refs = [];
192
+ const cleanType = type.replace(/\[\]/g, "").replace(/\s*\|\s*null/g, "");
193
+ const parts = cleanType.split(/\s*\|\s*/);
194
+ for (const part of parts) {
195
+ const trimmed = part.trim().replace(/^['"]|['"]$/g, "");
196
+ if (!primitives.has(trimmed) && allSchemaNames.has(trimmed)) {
197
+ refs.push(trimmed);
198
+ }
199
+ }
200
+ return refs;
201
+ }
177
202
  function schemaToInterface(schema, allSchemas, options = {}) {
178
203
  const properties = [];
204
+ const allSchemaNames = new Set(Object.keys(allSchemas).filter((name) => allSchemas[name].kind !== "enum"));
179
205
  if (schema.options?.id !== false) {
180
206
  const pkType = schema.options?.idType ?? "BigInt";
181
207
  properties.push({
@@ -218,11 +244,20 @@ function schemaToInterface(schema, allSchemas, options = {}) {
218
244
  comment: "Soft delete timestamp"
219
245
  });
220
246
  }
247
+ const dependencySet = /* @__PURE__ */ new Set();
248
+ for (const prop of properties) {
249
+ for (const ref of extractTypeReferences(prop.type, allSchemaNames)) {
250
+ if (ref !== schema.name) {
251
+ dependencySet.add(ref);
252
+ }
253
+ }
254
+ }
221
255
  const schemaDisplayName = resolveDisplayName(schema.displayName, options);
222
256
  return {
223
257
  name: toInterfaceName(schema.name),
224
258
  properties,
225
- comment: schemaDisplayName ?? schema.name
259
+ comment: schemaDisplayName ?? schema.name,
260
+ dependencies: dependencySet.size > 0 ? Array.from(dependencySet).sort() : void 0
226
261
  };
227
262
  }
228
263
  function formatProperty(property) {
@@ -279,11 +314,18 @@ function parseEnumValue(value, options = {}) {
279
314
  // No label or extra - will fallback to value
280
315
  };
281
316
  }
282
- const resolvedLabel = resolveDisplayName2(value.label, options);
317
+ let label;
318
+ if (value.label !== void 0) {
319
+ if (options.multiLocale && typeof value.label === "object") {
320
+ label = value.label;
321
+ } else {
322
+ label = resolveDisplayName2(value.label, options);
323
+ }
324
+ }
283
325
  return {
284
326
  name: toEnumMemberName(value.value),
285
327
  value: value.value,
286
- label: resolvedLabel,
328
+ label,
287
329
  extra: value.extra
288
330
  };
289
331
  }
@@ -313,6 +355,9 @@ function generateEnums(schemas, options = {}) {
313
355
  }
314
356
  return enums;
315
357
  }
358
+ function isMultiLocaleLabel(label) {
359
+ return label !== void 0 && typeof label === "object";
360
+ }
316
361
  function formatEnum(enumDef) {
317
362
  const { name, values, comment } = enumDef;
318
363
  const parts = [];
@@ -343,28 +388,64 @@ ${enumValues}
343
388
 
344
389
  `);
345
390
  const hasLabels = values.some((v) => v.label !== void 0);
391
+ const hasMultiLocale = values.some((v) => isMultiLocaleLabel(v.label));
346
392
  if (hasLabels) {
347
- const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${v.label}',`).join("\n");
348
- parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, string>> = {
393
+ if (hasMultiLocale) {
394
+ const labelEntries = values.filter((v) => v.label !== void 0).map((v) => {
395
+ if (isMultiLocaleLabel(v.label)) {
396
+ const locales = Object.entries(v.label).map(([locale, text]) => `${locale}: '${text}'`).join(", ");
397
+ return ` [${name}.${v.name}]: { ${locales} },`;
398
+ }
399
+ return ` [${name}.${v.name}]: { default: '${v.label}' },`;
400
+ }).join("\n");
401
+ parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, Record<string, string>>> = {
349
402
  ${labelEntries}
350
403
  };
351
404
 
352
405
  `);
353
- }
354
- parts.push(`/** Get label for ${name} value (fallback to value if no label) */
406
+ parts.push(`/** Get label for ${name} value with locale support */
355
407
  `);
356
- parts.push(`export function get${name}Label(value: ${name}): string {
408
+ parts.push(`export function get${name}Label(value: ${name}, locale?: string): string {
357
409
  `);
358
- if (hasLabels) {
359
- parts.push(` return ${lowerFirst(name)}Labels[value] ?? value;
410
+ parts.push(` const labels = ${lowerFirst(name)}Labels[value];
411
+ `);
412
+ parts.push(` if (!labels) return value;
360
413
  `);
414
+ parts.push(` if (locale && labels[locale]) return labels[locale];
415
+ `);
416
+ parts.push(` return Object.values(labels)[0] ?? value;
417
+ `);
418
+ parts.push(`}
419
+
420
+ `);
421
+ } else {
422
+ const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${v.label}',`).join("\n");
423
+ parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, string>> = {
424
+ ${labelEntries}
425
+ };
426
+
427
+ `);
428
+ parts.push(`/** Get label for ${name} value (fallback to value if no label) */
429
+ `);
430
+ parts.push(`export function get${name}Label(value: ${name}): string {
431
+ `);
432
+ parts.push(` return ${lowerFirst(name)}Labels[value] ?? value;
433
+ `);
434
+ parts.push(`}
435
+
436
+ `);
437
+ }
361
438
  } else {
439
+ parts.push(`/** Get label for ${name} value (returns value as-is) */
440
+ `);
441
+ parts.push(`export function get${name}Label(value: ${name}): string {
442
+ `);
362
443
  parts.push(` return value;
363
444
  `);
364
- }
365
- parts.push(`}
445
+ parts.push(`}
366
446
 
367
447
  `);
448
+ }
368
449
  const hasExtra = values.some((v) => v.extra !== void 0);
369
450
  if (hasExtra) {
370
451
  const extraEntries = values.filter((v) => v.extra !== void 0).map((v) => ` [${name}.${v.name}]: ${JSON.stringify(v.extra)},`).join("\n");
@@ -486,6 +567,347 @@ function extractInlineEnums(schemas, options = {}) {
486
567
  return typeAliases;
487
568
  }
488
569
 
570
+ // src/validation-templates.ts
571
+ var DEFAULT_VALIDATION_TEMPLATES = {
572
+ required: {
573
+ ja: "${displayName}\u306F\u5FC5\u9808\u3067\u3059",
574
+ en: "${displayName} is required",
575
+ vi: "${displayName} l\xE0 b\u1EAFt bu\u1ED9c",
576
+ ko: "${displayName}\uC740(\uB294) \uD544\uC218\uC785\uB2C8\uB2E4",
577
+ zh: "${displayName}\u4E3A\u5FC5\u586B\u9879"
578
+ },
579
+ minLength: {
580
+ ja: "${displayName}\u306F${min}\u6587\u5B57\u4EE5\u4E0A\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
581
+ en: "${displayName} must be at least ${min} characters",
582
+ vi: "${displayName} ph\u1EA3i c\xF3 \xEDt nh\u1EA5t ${min} k\xFD t\u1EF1",
583
+ ko: "${displayName}\uC740(\uB294) ${min}\uC790 \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
584
+ zh: "${displayName}\u81F3\u5C11\u9700\u8981${min}\u4E2A\u5B57\u7B26"
585
+ },
586
+ maxLength: {
587
+ ja: "${displayName}\u306F${max}\u6587\u5B57\u4EE5\u5185\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
588
+ en: "${displayName} must be at most ${max} characters",
589
+ vi: "${displayName} t\u1ED1i \u0111a ${max} k\xFD t\u1EF1",
590
+ ko: "${displayName}\uC740(\uB294) ${max}\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
591
+ zh: "${displayName}\u4E0D\u80FD\u8D85\u8FC7${max}\u4E2A\u5B57\u7B26"
592
+ },
593
+ min: {
594
+ ja: "${displayName}\u306F${min}\u4EE5\u4E0A\u306E\u5024\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
595
+ en: "${displayName} must be at least ${min}",
596
+ vi: "${displayName} ph\u1EA3i l\u1EDBn h\u01A1n ho\u1EB7c b\u1EB1ng ${min}",
597
+ ko: "${displayName}\uC740(\uB294) ${min} \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
598
+ zh: "${displayName}\u4E0D\u80FD\u5C0F\u4E8E${min}"
599
+ },
600
+ max: {
601
+ ja: "${displayName}\u306F${max}\u4EE5\u4E0B\u306E\u5024\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
602
+ en: "${displayName} must be at most ${max}",
603
+ vi: "${displayName} ph\u1EA3i nh\u1ECF h\u01A1n ho\u1EB7c b\u1EB1ng ${max}",
604
+ ko: "${displayName}\uC740(\uB294) ${max} \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
605
+ zh: "${displayName}\u4E0D\u80FD\u5927\u4E8E${max}"
606
+ },
607
+ email: {
608
+ ja: "${displayName}\u306E\u5F62\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093",
609
+ en: "${displayName} is not a valid email address",
610
+ vi: "${displayName} kh\xF4ng ph\u1EA3i l\xE0 \u0111\u1ECBa ch\u1EC9 email h\u1EE3p l\u1EC7",
611
+ ko: "${displayName} \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
612
+ zh: "${displayName}\u4E0D\u662F\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740"
613
+ },
614
+ url: {
615
+ ja: "${displayName}\u306F\u6709\u52B9\u306AURL\u3067\u306F\u3042\u308A\u307E\u305B\u3093",
616
+ en: "${displayName} is not a valid URL",
617
+ vi: "${displayName} kh\xF4ng ph\u1EA3i l\xE0 URL h\u1EE3p l\u1EC7",
618
+ ko: "${displayName}\uC740(\uB294) \uC720\uD6A8\uD55C URL\uC774 \uC544\uB2D9\uB2C8\uB2E4",
619
+ zh: "${displayName}\u4E0D\u662F\u6709\u6548\u7684URL"
620
+ },
621
+ pattern: {
622
+ ja: "${displayName}\u306E\u5F62\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093",
623
+ en: "${displayName} format is invalid",
624
+ vi: "${displayName} kh\xF4ng \u0111\xFAng \u0111\u1ECBnh d\u1EA1ng",
625
+ ko: "${displayName} \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
626
+ zh: "${displayName}\u683C\u5F0F\u4E0D\u6B63\u786E"
627
+ },
628
+ enum: {
629
+ ja: "${displayName}\u306E\u5024\u304C\u7121\u52B9\u3067\u3059",
630
+ en: "${displayName} has an invalid value",
631
+ vi: "${displayName} c\xF3 gi\xE1 tr\u1ECB kh\xF4ng h\u1EE3p l\u1EC7",
632
+ ko: "${displayName} \uAC12\uC774 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
633
+ zh: "${displayName}\u7684\u503C\u65E0\u6548"
634
+ }
635
+ };
636
+ function mergeValidationTemplates(userTemplates) {
637
+ if (!userTemplates) {
638
+ return DEFAULT_VALIDATION_TEMPLATES;
639
+ }
640
+ const merged = {
641
+ required: { ...DEFAULT_VALIDATION_TEMPLATES.required },
642
+ minLength: { ...DEFAULT_VALIDATION_TEMPLATES.minLength },
643
+ maxLength: { ...DEFAULT_VALIDATION_TEMPLATES.maxLength },
644
+ min: { ...DEFAULT_VALIDATION_TEMPLATES.min },
645
+ max: { ...DEFAULT_VALIDATION_TEMPLATES.max },
646
+ email: { ...DEFAULT_VALIDATION_TEMPLATES.email },
647
+ url: { ...DEFAULT_VALIDATION_TEMPLATES.url },
648
+ pattern: { ...DEFAULT_VALIDATION_TEMPLATES.pattern },
649
+ enum: { ...DEFAULT_VALIDATION_TEMPLATES.enum }
650
+ };
651
+ for (const [key, value] of Object.entries(userTemplates)) {
652
+ if (value && key in merged) {
653
+ merged[key] = {
654
+ ...merged[key],
655
+ ...value
656
+ };
657
+ }
658
+ }
659
+ return merged;
660
+ }
661
+ function formatValidationMessage(template, vars) {
662
+ let result = template;
663
+ for (const [key, value] of Object.entries(vars)) {
664
+ result = result.replace(new RegExp(`\\$\\{${key}\\}`, "g"), String(value));
665
+ }
666
+ return result;
667
+ }
668
+ function getValidationMessages(templates, ruleType, locales, vars, fallbackLocale) {
669
+ const ruleTemplates = templates[ruleType];
670
+ const messages = {};
671
+ for (const locale of locales) {
672
+ const template = ruleTemplates[locale] ?? (fallbackLocale ? ruleTemplates[fallbackLocale] : void 0) ?? ruleTemplates["en"] ?? "";
673
+ messages[locale] = formatValidationMessage(template, vars);
674
+ }
675
+ return messages;
676
+ }
677
+
678
+ // src/rules-generator.ts
679
+ function getMultiLocaleDisplayName(value, locales, fallbackLocale, defaultValue) {
680
+ if (!value) {
681
+ const result2 = {};
682
+ for (const locale of locales) {
683
+ result2[locale] = defaultValue;
684
+ }
685
+ return result2;
686
+ }
687
+ if (typeof value === "string") {
688
+ const result2 = {};
689
+ for (const locale of locales) {
690
+ result2[locale] = value;
691
+ }
692
+ return result2;
693
+ }
694
+ const result = {};
695
+ for (const locale of locales) {
696
+ result[locale] = value[locale] ?? value[fallbackLocale] ?? value["en"] ?? defaultValue;
697
+ }
698
+ return result;
699
+ }
700
+ function generatePropertyRules(propName, property, displayName, locales, fallbackLocale, templates) {
701
+ const rules = [];
702
+ const propDef = property;
703
+ if (!propDef.nullable) {
704
+ rules.push({
705
+ required: true,
706
+ message: getValidationMessages(templates, "required", locales, { displayName: "${displayName}" }, fallbackLocale)
707
+ });
708
+ }
709
+ if (property.type === "Email") {
710
+ rules.push({
711
+ type: "email",
712
+ message: getValidationMessages(templates, "email", locales, { displayName: "${displayName}" }, fallbackLocale)
713
+ });
714
+ }
715
+ if (property.type === "String" || property.type === "Text" || property.type === "LongText") {
716
+ if (propDef.minLength) {
717
+ rules.push({
718
+ min: propDef.minLength,
719
+ message: getValidationMessages(templates, "minLength", locales, { displayName: "${displayName}", min: propDef.minLength }, fallbackLocale)
720
+ });
721
+ }
722
+ if (propDef.maxLength || propDef.length) {
723
+ const max = propDef.maxLength ?? propDef.length;
724
+ rules.push({
725
+ max,
726
+ message: getValidationMessages(templates, "maxLength", locales, { displayName: "${displayName}", max }, fallbackLocale)
727
+ });
728
+ }
729
+ }
730
+ if (property.type === "Int" || property.type === "BigInt" || property.type === "Float") {
731
+ if (propDef.min !== void 0) {
732
+ rules.push({
733
+ type: property.type === "Float" ? "number" : "integer",
734
+ min: propDef.min,
735
+ message: getValidationMessages(templates, "min", locales, { displayName: "${displayName}", min: propDef.min }, fallbackLocale)
736
+ });
737
+ }
738
+ if (propDef.max !== void 0) {
739
+ rules.push({
740
+ type: property.type === "Float" ? "number" : "integer",
741
+ max: propDef.max,
742
+ message: getValidationMessages(templates, "max", locales, { displayName: "${displayName}", max: propDef.max }, fallbackLocale)
743
+ });
744
+ }
745
+ }
746
+ if (propDef.pattern) {
747
+ rules.push({
748
+ pattern: propDef.pattern,
749
+ message: getValidationMessages(templates, "pattern", locales, { displayName: "${displayName}" }, fallbackLocale)
750
+ });
751
+ }
752
+ for (const rule of rules) {
753
+ const newMessage = {};
754
+ for (const locale of locales) {
755
+ const msg = rule.message[locale];
756
+ if (msg) {
757
+ newMessage[locale] = msg.replace(/\$\{displayName\}/g, displayName[locale] ?? propName);
758
+ }
759
+ }
760
+ rule.message = newMessage;
761
+ }
762
+ return rules;
763
+ }
764
+ function generateModelRules(schema, locales, fallbackLocale, templates) {
765
+ const modelDisplayName = getMultiLocaleDisplayName(
766
+ schema.displayName,
767
+ locales,
768
+ fallbackLocale,
769
+ schema.name
770
+ );
771
+ const properties = {};
772
+ if (schema.properties) {
773
+ for (const [propName, property] of Object.entries(schema.properties)) {
774
+ const propDef = property;
775
+ const displayName = getMultiLocaleDisplayName(
776
+ propDef.displayName,
777
+ locales,
778
+ fallbackLocale,
779
+ propName
780
+ );
781
+ properties[propName] = {
782
+ displayName,
783
+ rules: generatePropertyRules(propName, property, displayName, locales, fallbackLocale, templates)
784
+ };
785
+ }
786
+ }
787
+ return {
788
+ displayName: modelDisplayName,
789
+ properties
790
+ };
791
+ }
792
+ function formatRulesFile(schemaName, rules) {
793
+ const parts = [];
794
+ parts.push(`/**
795
+ * Auto-generated validation rules and metadata for ${schemaName}.
796
+ * DO NOT EDIT - This file is automatically generated and will be overwritten.
797
+ */
798
+
799
+ `);
800
+ parts.push(`export interface LocaleMap { [locale: string]: string; }
801
+
802
+ `);
803
+ parts.push(`export interface ValidationRule {
804
+ required?: boolean;
805
+ type?: 'string' | 'number' | 'email' | 'url' | 'integer';
806
+ min?: number;
807
+ max?: number;
808
+ len?: number;
809
+ pattern?: RegExp;
810
+ message: LocaleMap;
811
+ }
812
+
813
+ `);
814
+ parts.push(`/** Display name for ${schemaName} */
815
+ `);
816
+ parts.push(`export const ${schemaName}DisplayName: LocaleMap = ${JSON.stringify(rules.displayName, null, 2)};
817
+
818
+ `);
819
+ parts.push(`/** Property display names for ${schemaName} */
820
+ `);
821
+ parts.push(`export const ${schemaName}PropertyDisplayNames: Record<string, LocaleMap> = {
822
+ `);
823
+ for (const [propName, propRules] of Object.entries(rules.properties)) {
824
+ parts.push(` ${propName}: ${JSON.stringify(propRules.displayName)},
825
+ `);
826
+ }
827
+ parts.push(`};
828
+
829
+ `);
830
+ parts.push(`/** Validation rules for ${schemaName} (Ant Design compatible) */
831
+ `);
832
+ parts.push(`export const ${schemaName}Rules: Record<string, ValidationRule[]> = {
833
+ `);
834
+ for (const [propName, propRules] of Object.entries(rules.properties)) {
835
+ if (propRules.rules.length > 0) {
836
+ parts.push(` ${propName}: [
837
+ `);
838
+ for (const rule of propRules.rules) {
839
+ const ruleObj = {};
840
+ if (rule.required) ruleObj.required = true;
841
+ if (rule.type) ruleObj.type = `'${rule.type}'`;
842
+ if (rule.min !== void 0) ruleObj.min = rule.min;
843
+ if (rule.max !== void 0) ruleObj.max = rule.max;
844
+ if (rule.pattern) ruleObj.pattern = `/${rule.pattern}/`;
845
+ ruleObj.message = rule.message;
846
+ const ruleStr = Object.entries(ruleObj).map(([k, v]) => {
847
+ if (k === "type") return `${k}: ${v}`;
848
+ if (k === "pattern") return `${k}: ${v}`;
849
+ return `${k}: ${JSON.stringify(v)}`;
850
+ }).join(", ");
851
+ parts.push(` { ${ruleStr} },
852
+ `);
853
+ }
854
+ parts.push(` ],
855
+ `);
856
+ }
857
+ }
858
+ parts.push(`};
859
+
860
+ `);
861
+ parts.push(`/** Get validation rules with messages for a specific locale */
862
+ `);
863
+ parts.push(`export function get${schemaName}Rules(locale: string): Record<string, Array<{ required?: boolean; type?: string; min?: number; max?: number; pattern?: RegExp; message: string }>> {
864
+ const result: Record<string, Array<{ required?: boolean; type?: string; min?: number; max?: number; pattern?: RegExp; message: string }>> = {};
865
+ for (const [prop, rules] of Object.entries(${schemaName}Rules)) {
866
+ result[prop] = rules.map(rule => ({
867
+ ...rule,
868
+ message: rule.message[locale] ?? rule.message['en'] ?? '',
869
+ }));
870
+ }
871
+ return result;
872
+ }
873
+
874
+ `);
875
+ parts.push(`/** Get display name for a specific locale */
876
+ `);
877
+ parts.push(`export function get${schemaName}DisplayName(locale: string): string {
878
+ return ${schemaName}DisplayName[locale] ?? ${schemaName}DisplayName['en'] ?? '${schemaName}';
879
+ }
880
+
881
+ `);
882
+ parts.push(`/** Get property display name for a specific locale */
883
+ `);
884
+ parts.push(`export function get${schemaName}PropertyDisplayName(property: string, locale: string): string {
885
+ const names = ${schemaName}PropertyDisplayNames[property];
886
+ return names?.[locale] ?? names?.['en'] ?? property;
887
+ }
888
+ `);
889
+ return parts.join("");
890
+ }
891
+ function generateRulesFiles(schemas, options = {}) {
892
+ const files = [];
893
+ const localeConfig = options.localeConfig;
894
+ const locales = [...localeConfig?.locales ?? ["en"]];
895
+ const fallbackLocale = localeConfig?.fallbackLocale ?? "en";
896
+ const templates = mergeValidationTemplates(options.validationTemplates);
897
+ for (const schema of Object.values(schemas)) {
898
+ if (schema.kind === "enum") continue;
899
+ const rules = generateModelRules(schema, locales, fallbackLocale, templates);
900
+ const content = formatRulesFile(schema.name, rules);
901
+ files.push({
902
+ filePath: `rules/${schema.name}.rules.ts`,
903
+ content,
904
+ types: [`${schema.name}Rules`, `${schema.name}DisplayName`],
905
+ overwrite: true
906
+ });
907
+ }
908
+ return files;
909
+ }
910
+
489
911
  // src/generator.ts
490
912
  var DEFAULT_OPTIONS = {
491
913
  readonly: true,
@@ -517,6 +939,13 @@ function generateBaseInterfaceFile(schemaName, schemas, options) {
517
939
  throw new Error(`Interface not found for schema: ${schemaName}`);
518
940
  }
519
941
  const parts = [generateBaseHeader()];
942
+ if (iface.dependencies && iface.dependencies.length > 0) {
943
+ for (const dep of iface.dependencies) {
944
+ parts.push(`import type { ${dep} } from './${dep}.js';
945
+ `);
946
+ }
947
+ parts.push("\n");
948
+ }
520
949
  parts.push(formatInterface(iface));
521
950
  parts.push("\n");
522
951
  return {
@@ -633,11 +1062,11 @@ function generateIndexFile(schemas, enums, typeAliases) {
633
1062
  function generateTypeScript(schemas, options = {}) {
634
1063
  const opts = { ...DEFAULT_OPTIONS, ...options };
635
1064
  const files = [];
636
- const enums = generateEnums(schemas);
1065
+ const enums = generateEnums(schemas, opts);
637
1066
  for (const enumDef of enums) {
638
1067
  files.push(generateEnumFile(enumDef));
639
1068
  }
640
- const typeAliases = extractInlineEnums(schemas);
1069
+ const typeAliases = extractInlineEnums(schemas, opts);
641
1070
  for (const alias of typeAliases) {
642
1071
  files.push(generateTypeAliasFile(alias));
643
1072
  }
@@ -649,6 +1078,10 @@ function generateTypeScript(schemas, options = {}) {
649
1078
  if (schema.kind === "enum") continue;
650
1079
  files.push(generateModelFile(schema.name));
651
1080
  }
1081
+ if (opts.generateRules) {
1082
+ const rulesFiles = generateRulesFiles(schemas, opts);
1083
+ files.push(...rulesFiles);
1084
+ }
652
1085
  files.push(generateIndexFile(schemas, enums, typeAliases));
653
1086
  return files;
654
1087
  }
@@ -670,6 +1103,12 @@ export {
670
1103
  enumToUnionType,
671
1104
  formatTypeAlias,
672
1105
  extractInlineEnums,
1106
+ DEFAULT_VALIDATION_TEMPLATES,
1107
+ mergeValidationTemplates,
1108
+ formatValidationMessage,
1109
+ getValidationMessages,
1110
+ generateModelRules,
1111
+ generateRulesFiles,
673
1112
  generateTypeScript
674
1113
  };
675
- //# sourceMappingURL=chunk-4NNFIIZ4.js.map
1114
+ //# sourceMappingURL=chunk-HPORV62S.js.map