@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/{chunk-SQD3KCIT.js → chunk-HPORV62S.js} +411 -14
- package/dist/chunk-HPORV62S.js.map +1 -0
- package/dist/index.cjs +416 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -3
- package/dist/index.d.ts +95 -3
- package/dist/index.js +13 -1
- package/dist/plugin.cjs +404 -13
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.js +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.js +135 -15
- package/dist/chunk-SQD3KCIT.js.map +0 -1
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
|
-
|
|
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
|
|
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
|
-
|
|
426
|
-
|
|
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
|
-
|
|
457
|
+
parts.push(`export function get${name}Label(value: ${name}, locale?: string): string {
|
|
435
458
|
`);
|
|
436
|
-
|
|
437
|
-
|
|
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,
|