@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/plugin.cjs
CHANGED
|
@@ -338,11 +338,18 @@ function parseEnumValue(value, options = {}) {
|
|
|
338
338
|
// No label or extra - will fallback to value
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
|
-
|
|
341
|
+
let label;
|
|
342
|
+
if (value.label !== void 0) {
|
|
343
|
+
if (options.multiLocale && typeof value.label === "object") {
|
|
344
|
+
label = value.label;
|
|
345
|
+
} else {
|
|
346
|
+
label = resolveDisplayName2(value.label, options);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
342
349
|
return {
|
|
343
350
|
name: toEnumMemberName(value.value),
|
|
344
351
|
value: value.value,
|
|
345
|
-
label
|
|
352
|
+
label,
|
|
346
353
|
extra: value.extra
|
|
347
354
|
};
|
|
348
355
|
}
|
|
@@ -372,6 +379,9 @@ function generateEnums(schemas, options = {}) {
|
|
|
372
379
|
}
|
|
373
380
|
return enums;
|
|
374
381
|
}
|
|
382
|
+
function isMultiLocaleLabel(label) {
|
|
383
|
+
return label !== void 0 && typeof label === "object";
|
|
384
|
+
}
|
|
375
385
|
function formatEnum(enumDef) {
|
|
376
386
|
const { name, values, comment } = enumDef;
|
|
377
387
|
const parts = [];
|
|
@@ -402,28 +412,64 @@ ${enumValues}
|
|
|
402
412
|
|
|
403
413
|
`);
|
|
404
414
|
const hasLabels = values.some((v) => v.label !== void 0);
|
|
415
|
+
const hasMultiLocale = values.some((v) => isMultiLocaleLabel(v.label));
|
|
405
416
|
if (hasLabels) {
|
|
406
|
-
|
|
407
|
-
|
|
417
|
+
if (hasMultiLocale) {
|
|
418
|
+
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => {
|
|
419
|
+
if (isMultiLocaleLabel(v.label)) {
|
|
420
|
+
const locales = Object.entries(v.label).map(([locale, text]) => `${locale}: '${text}'`).join(", ");
|
|
421
|
+
return ` [${name}.${v.name}]: { ${locales} },`;
|
|
422
|
+
}
|
|
423
|
+
return ` [${name}.${v.name}]: { default: '${v.label}' },`;
|
|
424
|
+
}).join("\n");
|
|
425
|
+
parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, Record<string, string>>> = {
|
|
408
426
|
${labelEntries}
|
|
409
427
|
};
|
|
410
428
|
|
|
411
429
|
`);
|
|
412
|
-
|
|
413
|
-
parts.push(`/** Get label for ${name} value (fallback to value if no label) */
|
|
430
|
+
parts.push(`/** Get label for ${name} value with locale support */
|
|
414
431
|
`);
|
|
415
|
-
|
|
432
|
+
parts.push(`export function get${name}Label(value: ${name}, locale?: string): string {
|
|
416
433
|
`);
|
|
417
|
-
|
|
418
|
-
|
|
434
|
+
parts.push(` const labels = ${lowerFirst(name)}Labels[value];
|
|
435
|
+
`);
|
|
436
|
+
parts.push(` if (!labels) return value;
|
|
437
|
+
`);
|
|
438
|
+
parts.push(` if (locale && labels[locale]) return labels[locale];
|
|
439
|
+
`);
|
|
440
|
+
parts.push(` return Object.values(labels)[0] ?? value;
|
|
441
|
+
`);
|
|
442
|
+
parts.push(`}
|
|
443
|
+
|
|
444
|
+
`);
|
|
445
|
+
} else {
|
|
446
|
+
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${v.label}',`).join("\n");
|
|
447
|
+
parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, string>> = {
|
|
448
|
+
${labelEntries}
|
|
449
|
+
};
|
|
450
|
+
|
|
419
451
|
`);
|
|
452
|
+
parts.push(`/** Get label for ${name} value (fallback to value if no label) */
|
|
453
|
+
`);
|
|
454
|
+
parts.push(`export function get${name}Label(value: ${name}): string {
|
|
455
|
+
`);
|
|
456
|
+
parts.push(` return ${lowerFirst(name)}Labels[value] ?? value;
|
|
457
|
+
`);
|
|
458
|
+
parts.push(`}
|
|
459
|
+
|
|
460
|
+
`);
|
|
461
|
+
}
|
|
420
462
|
} else {
|
|
463
|
+
parts.push(`/** Get label for ${name} value (returns value as-is) */
|
|
464
|
+
`);
|
|
465
|
+
parts.push(`export function get${name}Label(value: ${name}): string {
|
|
466
|
+
`);
|
|
421
467
|
parts.push(` return value;
|
|
422
468
|
`);
|
|
423
|
-
|
|
424
|
-
parts.push(`}
|
|
469
|
+
parts.push(`}
|
|
425
470
|
|
|
426
471
|
`);
|
|
472
|
+
}
|
|
427
473
|
const hasExtra = values.some((v) => v.extra !== void 0);
|
|
428
474
|
if (hasExtra) {
|
|
429
475
|
const extraEntries = values.filter((v) => v.extra !== void 0).map((v) => ` [${name}.${v.name}]: ${JSON.stringify(v.extra)},`).join("\n");
|
|
@@ -537,6 +583,347 @@ function extractInlineEnums(schemas, options = {}) {
|
|
|
537
583
|
return typeAliases;
|
|
538
584
|
}
|
|
539
585
|
|
|
586
|
+
// src/validation-templates.ts
|
|
587
|
+
var DEFAULT_VALIDATION_TEMPLATES = {
|
|
588
|
+
required: {
|
|
589
|
+
ja: "${displayName}\u306F\u5FC5\u9808\u3067\u3059",
|
|
590
|
+
en: "${displayName} is required",
|
|
591
|
+
vi: "${displayName} l\xE0 b\u1EAFt bu\u1ED9c",
|
|
592
|
+
ko: "${displayName}\uC740(\uB294) \uD544\uC218\uC785\uB2C8\uB2E4",
|
|
593
|
+
zh: "${displayName}\u4E3A\u5FC5\u586B\u9879"
|
|
594
|
+
},
|
|
595
|
+
minLength: {
|
|
596
|
+
ja: "${displayName}\u306F${min}\u6587\u5B57\u4EE5\u4E0A\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
597
|
+
en: "${displayName} must be at least ${min} characters",
|
|
598
|
+
vi: "${displayName} ph\u1EA3i c\xF3 \xEDt nh\u1EA5t ${min} k\xFD t\u1EF1",
|
|
599
|
+
ko: "${displayName}\uC740(\uB294) ${min}\uC790 \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
|
|
600
|
+
zh: "${displayName}\u81F3\u5C11\u9700\u8981${min}\u4E2A\u5B57\u7B26"
|
|
601
|
+
},
|
|
602
|
+
maxLength: {
|
|
603
|
+
ja: "${displayName}\u306F${max}\u6587\u5B57\u4EE5\u5185\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
604
|
+
en: "${displayName} must be at most ${max} characters",
|
|
605
|
+
vi: "${displayName} t\u1ED1i \u0111a ${max} k\xFD t\u1EF1",
|
|
606
|
+
ko: "${displayName}\uC740(\uB294) ${max}\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
|
|
607
|
+
zh: "${displayName}\u4E0D\u80FD\u8D85\u8FC7${max}\u4E2A\u5B57\u7B26"
|
|
608
|
+
},
|
|
609
|
+
min: {
|
|
610
|
+
ja: "${displayName}\u306F${min}\u4EE5\u4E0A\u306E\u5024\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
611
|
+
en: "${displayName} must be at least ${min}",
|
|
612
|
+
vi: "${displayName} ph\u1EA3i l\u1EDBn h\u01A1n ho\u1EB7c b\u1EB1ng ${min}",
|
|
613
|
+
ko: "${displayName}\uC740(\uB294) ${min} \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
|
|
614
|
+
zh: "${displayName}\u4E0D\u80FD\u5C0F\u4E8E${min}"
|
|
615
|
+
},
|
|
616
|
+
max: {
|
|
617
|
+
ja: "${displayName}\u306F${max}\u4EE5\u4E0B\u306E\u5024\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
618
|
+
en: "${displayName} must be at most ${max}",
|
|
619
|
+
vi: "${displayName} ph\u1EA3i nh\u1ECF h\u01A1n ho\u1EB7c b\u1EB1ng ${max}",
|
|
620
|
+
ko: "${displayName}\uC740(\uB294) ${max} \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
|
|
621
|
+
zh: "${displayName}\u4E0D\u80FD\u5927\u4E8E${max}"
|
|
622
|
+
},
|
|
623
|
+
email: {
|
|
624
|
+
ja: "${displayName}\u306E\u5F62\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093",
|
|
625
|
+
en: "${displayName} is not a valid email address",
|
|
626
|
+
vi: "${displayName} kh\xF4ng ph\u1EA3i l\xE0 \u0111\u1ECBa ch\u1EC9 email h\u1EE3p l\u1EC7",
|
|
627
|
+
ko: "${displayName} \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
|
|
628
|
+
zh: "${displayName}\u4E0D\u662F\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740"
|
|
629
|
+
},
|
|
630
|
+
url: {
|
|
631
|
+
ja: "${displayName}\u306F\u6709\u52B9\u306AURL\u3067\u306F\u3042\u308A\u307E\u305B\u3093",
|
|
632
|
+
en: "${displayName} is not a valid URL",
|
|
633
|
+
vi: "${displayName} kh\xF4ng ph\u1EA3i l\xE0 URL h\u1EE3p l\u1EC7",
|
|
634
|
+
ko: "${displayName}\uC740(\uB294) \uC720\uD6A8\uD55C URL\uC774 \uC544\uB2D9\uB2C8\uB2E4",
|
|
635
|
+
zh: "${displayName}\u4E0D\u662F\u6709\u6548\u7684URL"
|
|
636
|
+
},
|
|
637
|
+
pattern: {
|
|
638
|
+
ja: "${displayName}\u306E\u5F62\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093",
|
|
639
|
+
en: "${displayName} format is invalid",
|
|
640
|
+
vi: "${displayName} kh\xF4ng \u0111\xFAng \u0111\u1ECBnh d\u1EA1ng",
|
|
641
|
+
ko: "${displayName} \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
|
|
642
|
+
zh: "${displayName}\u683C\u5F0F\u4E0D\u6B63\u786E"
|
|
643
|
+
},
|
|
644
|
+
enum: {
|
|
645
|
+
ja: "${displayName}\u306E\u5024\u304C\u7121\u52B9\u3067\u3059",
|
|
646
|
+
en: "${displayName} has an invalid value",
|
|
647
|
+
vi: "${displayName} c\xF3 gi\xE1 tr\u1ECB kh\xF4ng h\u1EE3p l\u1EC7",
|
|
648
|
+
ko: "${displayName} \uAC12\uC774 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
|
|
649
|
+
zh: "${displayName}\u7684\u503C\u65E0\u6548"
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
function mergeValidationTemplates(userTemplates) {
|
|
653
|
+
if (!userTemplates) {
|
|
654
|
+
return DEFAULT_VALIDATION_TEMPLATES;
|
|
655
|
+
}
|
|
656
|
+
const merged = {
|
|
657
|
+
required: { ...DEFAULT_VALIDATION_TEMPLATES.required },
|
|
658
|
+
minLength: { ...DEFAULT_VALIDATION_TEMPLATES.minLength },
|
|
659
|
+
maxLength: { ...DEFAULT_VALIDATION_TEMPLATES.maxLength },
|
|
660
|
+
min: { ...DEFAULT_VALIDATION_TEMPLATES.min },
|
|
661
|
+
max: { ...DEFAULT_VALIDATION_TEMPLATES.max },
|
|
662
|
+
email: { ...DEFAULT_VALIDATION_TEMPLATES.email },
|
|
663
|
+
url: { ...DEFAULT_VALIDATION_TEMPLATES.url },
|
|
664
|
+
pattern: { ...DEFAULT_VALIDATION_TEMPLATES.pattern },
|
|
665
|
+
enum: { ...DEFAULT_VALIDATION_TEMPLATES.enum }
|
|
666
|
+
};
|
|
667
|
+
for (const [key, value] of Object.entries(userTemplates)) {
|
|
668
|
+
if (value && key in merged) {
|
|
669
|
+
merged[key] = {
|
|
670
|
+
...merged[key],
|
|
671
|
+
...value
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return merged;
|
|
676
|
+
}
|
|
677
|
+
function formatValidationMessage(template, vars) {
|
|
678
|
+
let result = template;
|
|
679
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
680
|
+
result = result.replace(new RegExp(`\\$\\{${key}\\}`, "g"), String(value));
|
|
681
|
+
}
|
|
682
|
+
return result;
|
|
683
|
+
}
|
|
684
|
+
function getValidationMessages(templates, ruleType, locales, vars, fallbackLocale) {
|
|
685
|
+
const ruleTemplates = templates[ruleType];
|
|
686
|
+
const messages = {};
|
|
687
|
+
for (const locale of locales) {
|
|
688
|
+
const template = ruleTemplates[locale] ?? (fallbackLocale ? ruleTemplates[fallbackLocale] : void 0) ?? ruleTemplates["en"] ?? "";
|
|
689
|
+
messages[locale] = formatValidationMessage(template, vars);
|
|
690
|
+
}
|
|
691
|
+
return messages;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// src/rules-generator.ts
|
|
695
|
+
function getMultiLocaleDisplayName(value, locales, fallbackLocale, defaultValue) {
|
|
696
|
+
if (!value) {
|
|
697
|
+
const result2 = {};
|
|
698
|
+
for (const locale of locales) {
|
|
699
|
+
result2[locale] = defaultValue;
|
|
700
|
+
}
|
|
701
|
+
return result2;
|
|
702
|
+
}
|
|
703
|
+
if (typeof value === "string") {
|
|
704
|
+
const result2 = {};
|
|
705
|
+
for (const locale of locales) {
|
|
706
|
+
result2[locale] = value;
|
|
707
|
+
}
|
|
708
|
+
return result2;
|
|
709
|
+
}
|
|
710
|
+
const result = {};
|
|
711
|
+
for (const locale of locales) {
|
|
712
|
+
result[locale] = value[locale] ?? value[fallbackLocale] ?? value["en"] ?? defaultValue;
|
|
713
|
+
}
|
|
714
|
+
return result;
|
|
715
|
+
}
|
|
716
|
+
function generatePropertyRules(propName, property, displayName, locales, fallbackLocale, templates) {
|
|
717
|
+
const rules = [];
|
|
718
|
+
const propDef = property;
|
|
719
|
+
if (!propDef.nullable) {
|
|
720
|
+
rules.push({
|
|
721
|
+
required: true,
|
|
722
|
+
message: getValidationMessages(templates, "required", locales, { displayName: "${displayName}" }, fallbackLocale)
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
if (property.type === "Email") {
|
|
726
|
+
rules.push({
|
|
727
|
+
type: "email",
|
|
728
|
+
message: getValidationMessages(templates, "email", locales, { displayName: "${displayName}" }, fallbackLocale)
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
if (property.type === "String" || property.type === "Text" || property.type === "LongText") {
|
|
732
|
+
if (propDef.minLength) {
|
|
733
|
+
rules.push({
|
|
734
|
+
min: propDef.minLength,
|
|
735
|
+
message: getValidationMessages(templates, "minLength", locales, { displayName: "${displayName}", min: propDef.minLength }, fallbackLocale)
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
if (propDef.maxLength || propDef.length) {
|
|
739
|
+
const max = propDef.maxLength ?? propDef.length;
|
|
740
|
+
rules.push({
|
|
741
|
+
max,
|
|
742
|
+
message: getValidationMessages(templates, "maxLength", locales, { displayName: "${displayName}", max }, fallbackLocale)
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (property.type === "Int" || property.type === "BigInt" || property.type === "Float") {
|
|
747
|
+
if (propDef.min !== void 0) {
|
|
748
|
+
rules.push({
|
|
749
|
+
type: property.type === "Float" ? "number" : "integer",
|
|
750
|
+
min: propDef.min,
|
|
751
|
+
message: getValidationMessages(templates, "min", locales, { displayName: "${displayName}", min: propDef.min }, fallbackLocale)
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
if (propDef.max !== void 0) {
|
|
755
|
+
rules.push({
|
|
756
|
+
type: property.type === "Float" ? "number" : "integer",
|
|
757
|
+
max: propDef.max,
|
|
758
|
+
message: getValidationMessages(templates, "max", locales, { displayName: "${displayName}", max: propDef.max }, fallbackLocale)
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (propDef.pattern) {
|
|
763
|
+
rules.push({
|
|
764
|
+
pattern: propDef.pattern,
|
|
765
|
+
message: getValidationMessages(templates, "pattern", locales, { displayName: "${displayName}" }, fallbackLocale)
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
for (const rule of rules) {
|
|
769
|
+
const newMessage = {};
|
|
770
|
+
for (const locale of locales) {
|
|
771
|
+
const msg = rule.message[locale];
|
|
772
|
+
if (msg) {
|
|
773
|
+
newMessage[locale] = msg.replace(/\$\{displayName\}/g, displayName[locale] ?? propName);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
rule.message = newMessage;
|
|
777
|
+
}
|
|
778
|
+
return rules;
|
|
779
|
+
}
|
|
780
|
+
function generateModelRules(schema, locales, fallbackLocale, templates) {
|
|
781
|
+
const modelDisplayName = getMultiLocaleDisplayName(
|
|
782
|
+
schema.displayName,
|
|
783
|
+
locales,
|
|
784
|
+
fallbackLocale,
|
|
785
|
+
schema.name
|
|
786
|
+
);
|
|
787
|
+
const properties = {};
|
|
788
|
+
if (schema.properties) {
|
|
789
|
+
for (const [propName, property] of Object.entries(schema.properties)) {
|
|
790
|
+
const propDef = property;
|
|
791
|
+
const displayName = getMultiLocaleDisplayName(
|
|
792
|
+
propDef.displayName,
|
|
793
|
+
locales,
|
|
794
|
+
fallbackLocale,
|
|
795
|
+
propName
|
|
796
|
+
);
|
|
797
|
+
properties[propName] = {
|
|
798
|
+
displayName,
|
|
799
|
+
rules: generatePropertyRules(propName, property, displayName, locales, fallbackLocale, templates)
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return {
|
|
804
|
+
displayName: modelDisplayName,
|
|
805
|
+
properties
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
function formatRulesFile(schemaName, rules) {
|
|
809
|
+
const parts = [];
|
|
810
|
+
parts.push(`/**
|
|
811
|
+
* Auto-generated validation rules and metadata for ${schemaName}.
|
|
812
|
+
* DO NOT EDIT - This file is automatically generated and will be overwritten.
|
|
813
|
+
*/
|
|
814
|
+
|
|
815
|
+
`);
|
|
816
|
+
parts.push(`export interface LocaleMap { [locale: string]: string; }
|
|
817
|
+
|
|
818
|
+
`);
|
|
819
|
+
parts.push(`export interface ValidationRule {
|
|
820
|
+
required?: boolean;
|
|
821
|
+
type?: 'string' | 'number' | 'email' | 'url' | 'integer';
|
|
822
|
+
min?: number;
|
|
823
|
+
max?: number;
|
|
824
|
+
len?: number;
|
|
825
|
+
pattern?: RegExp;
|
|
826
|
+
message: LocaleMap;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
`);
|
|
830
|
+
parts.push(`/** Display name for ${schemaName} */
|
|
831
|
+
`);
|
|
832
|
+
parts.push(`export const ${schemaName}DisplayName: LocaleMap = ${JSON.stringify(rules.displayName, null, 2)};
|
|
833
|
+
|
|
834
|
+
`);
|
|
835
|
+
parts.push(`/** Property display names for ${schemaName} */
|
|
836
|
+
`);
|
|
837
|
+
parts.push(`export const ${schemaName}PropertyDisplayNames: Record<string, LocaleMap> = {
|
|
838
|
+
`);
|
|
839
|
+
for (const [propName, propRules] of Object.entries(rules.properties)) {
|
|
840
|
+
parts.push(` ${propName}: ${JSON.stringify(propRules.displayName)},
|
|
841
|
+
`);
|
|
842
|
+
}
|
|
843
|
+
parts.push(`};
|
|
844
|
+
|
|
845
|
+
`);
|
|
846
|
+
parts.push(`/** Validation rules for ${schemaName} (Ant Design compatible) */
|
|
847
|
+
`);
|
|
848
|
+
parts.push(`export const ${schemaName}Rules: Record<string, ValidationRule[]> = {
|
|
849
|
+
`);
|
|
850
|
+
for (const [propName, propRules] of Object.entries(rules.properties)) {
|
|
851
|
+
if (propRules.rules.length > 0) {
|
|
852
|
+
parts.push(` ${propName}: [
|
|
853
|
+
`);
|
|
854
|
+
for (const rule of propRules.rules) {
|
|
855
|
+
const ruleObj = {};
|
|
856
|
+
if (rule.required) ruleObj.required = true;
|
|
857
|
+
if (rule.type) ruleObj.type = `'${rule.type}'`;
|
|
858
|
+
if (rule.min !== void 0) ruleObj.min = rule.min;
|
|
859
|
+
if (rule.max !== void 0) ruleObj.max = rule.max;
|
|
860
|
+
if (rule.pattern) ruleObj.pattern = `/${rule.pattern}/`;
|
|
861
|
+
ruleObj.message = rule.message;
|
|
862
|
+
const ruleStr = Object.entries(ruleObj).map(([k, v]) => {
|
|
863
|
+
if (k === "type") return `${k}: ${v}`;
|
|
864
|
+
if (k === "pattern") return `${k}: ${v}`;
|
|
865
|
+
return `${k}: ${JSON.stringify(v)}`;
|
|
866
|
+
}).join(", ");
|
|
867
|
+
parts.push(` { ${ruleStr} },
|
|
868
|
+
`);
|
|
869
|
+
}
|
|
870
|
+
parts.push(` ],
|
|
871
|
+
`);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
parts.push(`};
|
|
875
|
+
|
|
876
|
+
`);
|
|
877
|
+
parts.push(`/** Get validation rules with messages for a specific locale */
|
|
878
|
+
`);
|
|
879
|
+
parts.push(`export function get${schemaName}Rules(locale: string): Record<string, Array<{ required?: boolean; type?: string; min?: number; max?: number; pattern?: RegExp; message: string }>> {
|
|
880
|
+
const result: Record<string, Array<{ required?: boolean; type?: string; min?: number; max?: number; pattern?: RegExp; message: string }>> = {};
|
|
881
|
+
for (const [prop, rules] of Object.entries(${schemaName}Rules)) {
|
|
882
|
+
result[prop] = rules.map(rule => ({
|
|
883
|
+
...rule,
|
|
884
|
+
message: rule.message[locale] ?? rule.message['en'] ?? '',
|
|
885
|
+
}));
|
|
886
|
+
}
|
|
887
|
+
return result;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
`);
|
|
891
|
+
parts.push(`/** Get display name for a specific locale */
|
|
892
|
+
`);
|
|
893
|
+
parts.push(`export function get${schemaName}DisplayName(locale: string): string {
|
|
894
|
+
return ${schemaName}DisplayName[locale] ?? ${schemaName}DisplayName['en'] ?? '${schemaName}';
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
`);
|
|
898
|
+
parts.push(`/** Get property display name for a specific locale */
|
|
899
|
+
`);
|
|
900
|
+
parts.push(`export function get${schemaName}PropertyDisplayName(property: string, locale: string): string {
|
|
901
|
+
const names = ${schemaName}PropertyDisplayNames[property];
|
|
902
|
+
return names?.[locale] ?? names?.['en'] ?? property;
|
|
903
|
+
}
|
|
904
|
+
`);
|
|
905
|
+
return parts.join("");
|
|
906
|
+
}
|
|
907
|
+
function generateRulesFiles(schemas, options = {}) {
|
|
908
|
+
const files = [];
|
|
909
|
+
const localeConfig = options.localeConfig;
|
|
910
|
+
const locales = [...localeConfig?.locales ?? ["en"]];
|
|
911
|
+
const fallbackLocale = localeConfig?.fallbackLocale ?? "en";
|
|
912
|
+
const templates = mergeValidationTemplates(options.validationTemplates);
|
|
913
|
+
for (const schema of Object.values(schemas)) {
|
|
914
|
+
if (schema.kind === "enum") continue;
|
|
915
|
+
const rules = generateModelRules(schema, locales, fallbackLocale, templates);
|
|
916
|
+
const content = formatRulesFile(schema.name, rules);
|
|
917
|
+
files.push({
|
|
918
|
+
filePath: `rules/${schema.name}.rules.ts`,
|
|
919
|
+
content,
|
|
920
|
+
types: [`${schema.name}Rules`, `${schema.name}DisplayName`],
|
|
921
|
+
overwrite: true
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
return files;
|
|
925
|
+
}
|
|
926
|
+
|
|
540
927
|
// src/generator.ts
|
|
541
928
|
var DEFAULT_OPTIONS = {
|
|
542
929
|
readonly: true,
|
|
@@ -691,11 +1078,11 @@ function generateIndexFile(schemas, enums, typeAliases) {
|
|
|
691
1078
|
function generateTypeScript(schemas, options = {}) {
|
|
692
1079
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
693
1080
|
const files = [];
|
|
694
|
-
const enums = generateEnums(schemas);
|
|
1081
|
+
const enums = generateEnums(schemas, opts);
|
|
695
1082
|
for (const enumDef of enums) {
|
|
696
1083
|
files.push(generateEnumFile(enumDef));
|
|
697
1084
|
}
|
|
698
|
-
const typeAliases = extractInlineEnums(schemas);
|
|
1085
|
+
const typeAliases = extractInlineEnums(schemas, opts);
|
|
699
1086
|
for (const alias of typeAliases) {
|
|
700
1087
|
files.push(generateTypeAliasFile(alias));
|
|
701
1088
|
}
|
|
@@ -707,6 +1094,10 @@ function generateTypeScript(schemas, options = {}) {
|
|
|
707
1094
|
if (schema.kind === "enum") continue;
|
|
708
1095
|
files.push(generateModelFile(schema.name));
|
|
709
1096
|
}
|
|
1097
|
+
if (opts.generateRules) {
|
|
1098
|
+
const rulesFiles = generateRulesFiles(schemas, opts);
|
|
1099
|
+
files.push(...rulesFiles);
|
|
1100
|
+
}
|
|
710
1101
|
files.push(generateIndexFile(schemas, enums, typeAliases));
|
|
711
1102
|
return files;
|
|
712
1103
|
}
|