@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.
- package/dist/{chunk-4NNFIIZ4.js → chunk-HPORV62S.js} +454 -15
- package/dist/chunk-HPORV62S.js.map +1 -0
- package/dist/index.cjs +459 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -3
- package/dist/index.d.ts +97 -3
- package/dist/index.js +13 -1
- package/dist/plugin.cjs +447 -14
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-4NNFIIZ4.js.map +0 -1
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
348
|
-
|
|
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
|
-
|
|
408
|
+
parts.push(`export function get${name}Label(value: ${name}, locale?: string): string {
|
|
357
409
|
`);
|
|
358
|
-
|
|
359
|
-
|
|
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-
|
|
1114
|
+
//# sourceMappingURL=chunk-HPORV62S.js.map
|