@famgia/omnify-typescript 0.0.67 → 0.0.69
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-4L77AHAC.js → chunk-6I4O23X6.js} +521 -66
- package/dist/chunk-6I4O23X6.js.map +1 -0
- package/dist/index.cjs +761 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +138 -2
- package/dist/index.d.ts +138 -2
- package/dist/index.js +227 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin.cjs +624 -75
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +6 -0
- package/dist/plugin.d.ts +6 -0
- package/dist/plugin.js +96 -11
- package/dist/plugin.js.map +1 -1
- package/package.json +3 -3
- package/scripts/postinstall.js +29 -40
- package/stubs/JapaneseAddressField.tsx.stub +289 -0
- package/stubs/JapaneseBankField.tsx.stub +212 -0
- package/stubs/JapaneseNameField.tsx.stub +194 -0
- package/stubs/ai-guides/checklists/react.md.stub +108 -0
- package/stubs/ai-guides/cursor/react-design.mdc.stub +289 -0
- package/stubs/ai-guides/cursor/react-form.mdc.stub +277 -0
- package/stubs/ai-guides/cursor/react-services.mdc.stub +304 -0
- package/stubs/ai-guides/cursor/react.mdc.stub +254 -0
- package/stubs/ai-guides/react/README.md.stub +221 -0
- package/stubs/ai-guides/react/antd-guide.md.stub +294 -0
- package/stubs/ai-guides/react/checklist.md.stub +108 -0
- package/stubs/ai-guides/react/datetime-guide.md.stub +137 -0
- package/stubs/ai-guides/react/design-philosophy.md.stub +363 -0
- package/stubs/ai-guides/react/i18n-guide.md.stub +211 -0
- package/stubs/ai-guides/react/laravel-integration.md.stub +181 -0
- package/stubs/ai-guides/react/service-pattern.md.stub +180 -0
- package/stubs/ai-guides/react/tanstack-query.md.stub +339 -0
- package/stubs/ai-guides/react/types-guide.md.stub +524 -0
- package/stubs/components-index.ts.stub +13 -0
- package/stubs/form-validation.ts.stub +106 -0
- package/stubs/rules/index.ts.stub +48 -0
- package/stubs/rules/kana.ts.stub +291 -0
- package/stubs/use-form-mutation.ts.stub +117 -0
- package/stubs/zod-i18n.ts.stub +32 -0
- package/ai-guides/antdesign-guide.md +0 -401
- package/ai-guides/typescript-guide.md +0 -310
- package/dist/chunk-4L77AHAC.js.map +0 -1
|
@@ -81,6 +81,10 @@ function getPropertyType(property, _allSchemas) {
|
|
|
81
81
|
return "unknown";
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
+
if (property.type === "EnumRef") {
|
|
85
|
+
const enumRefProp = property;
|
|
86
|
+
return enumRefProp.enum;
|
|
87
|
+
}
|
|
84
88
|
if (property.type === "Enum") {
|
|
85
89
|
const enumProp = property;
|
|
86
90
|
if (typeof enumProp.enum === "string") {
|
|
@@ -109,7 +113,7 @@ function propertyToTSProperties(propertyName, property, allSchemas, options = {}
|
|
|
109
113
|
for (const field of customType.expand) {
|
|
110
114
|
const fieldName = `${propertyName}_${toSnakeCase(field.suffix)}`;
|
|
111
115
|
const fieldOverride = baseProp.fields?.[field.suffix];
|
|
112
|
-
const isNullable = fieldOverride?.nullable ?? baseProp.nullable ?? false;
|
|
116
|
+
const isNullable = fieldOverride?.nullable ?? field.sql?.nullable ?? baseProp.nullable ?? false;
|
|
113
117
|
const tsType = field.typescript?.type ?? "string";
|
|
114
118
|
expandedProps.push({
|
|
115
119
|
name: fieldName,
|
|
@@ -254,12 +258,24 @@ function schemaToInterface(schema, allSchemas, options = {}) {
|
|
|
254
258
|
}
|
|
255
259
|
}
|
|
256
260
|
}
|
|
261
|
+
const enumDependencySet = /* @__PURE__ */ new Set();
|
|
262
|
+
if (schema.properties) {
|
|
263
|
+
for (const property of Object.values(schema.properties)) {
|
|
264
|
+
if (property.type === "EnumRef") {
|
|
265
|
+
const enumRefProp = property;
|
|
266
|
+
if (enumRefProp.enum) {
|
|
267
|
+
enumDependencySet.add(enumRefProp.enum);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
257
272
|
const schemaDisplayName = resolveDisplayName(schema.displayName, options);
|
|
258
273
|
return {
|
|
259
274
|
name: toInterfaceName(schema.name),
|
|
260
275
|
properties,
|
|
261
276
|
comment: schemaDisplayName ?? schema.name,
|
|
262
|
-
dependencies: dependencySet.size > 0 ? Array.from(dependencySet).sort() : void 0
|
|
277
|
+
dependencies: dependencySet.size > 0 ? Array.from(dependencySet).sort() : void 0,
|
|
278
|
+
enumDependencies: enumDependencySet.size > 0 ? Array.from(enumDependencySet).sort() : void 0
|
|
263
279
|
};
|
|
264
280
|
}
|
|
265
281
|
function formatProperty(property) {
|
|
@@ -306,7 +322,11 @@ function resolveDisplayName2(value, options = {}) {
|
|
|
306
322
|
});
|
|
307
323
|
}
|
|
308
324
|
function toEnumMemberName(value) {
|
|
309
|
-
|
|
325
|
+
let result = value.split(/[-_\s]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
326
|
+
if (/^\d/.test(result)) {
|
|
327
|
+
result = "_" + result;
|
|
328
|
+
}
|
|
329
|
+
return result;
|
|
310
330
|
}
|
|
311
331
|
function toEnumName(schemaName) {
|
|
312
332
|
return schemaName;
|
|
@@ -360,6 +380,46 @@ function generateEnums(schemas, options = {}) {
|
|
|
360
380
|
}
|
|
361
381
|
return enums;
|
|
362
382
|
}
|
|
383
|
+
function pluginEnumToTSEnum(enumDef, options = {}) {
|
|
384
|
+
const values = enumDef.values.map((v) => {
|
|
385
|
+
let label;
|
|
386
|
+
if (v.label !== void 0) {
|
|
387
|
+
if (typeof v.label === "string") {
|
|
388
|
+
label = v.label;
|
|
389
|
+
} else if (options.multiLocale) {
|
|
390
|
+
label = v.label;
|
|
391
|
+
} else {
|
|
392
|
+
label = resolveDisplayName2(v.label, options);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
name: toEnumMemberName(v.value),
|
|
397
|
+
value: v.value,
|
|
398
|
+
label,
|
|
399
|
+
extra: v.extra
|
|
400
|
+
};
|
|
401
|
+
});
|
|
402
|
+
let comment;
|
|
403
|
+
if (enumDef.displayName !== void 0) {
|
|
404
|
+
if (typeof enumDef.displayName === "string") {
|
|
405
|
+
comment = enumDef.displayName;
|
|
406
|
+
} else {
|
|
407
|
+
comment = resolveDisplayName2(enumDef.displayName, options);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
name: enumDef.name,
|
|
412
|
+
values,
|
|
413
|
+
comment: comment ?? enumDef.name
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
function generatePluginEnums(pluginEnums, options = {}) {
|
|
417
|
+
const enums = [];
|
|
418
|
+
for (const enumDef of pluginEnums.values()) {
|
|
419
|
+
enums.push(pluginEnumToTSEnum(enumDef, options));
|
|
420
|
+
}
|
|
421
|
+
return enums;
|
|
422
|
+
}
|
|
363
423
|
function isMultiLocaleLabel(label) {
|
|
364
424
|
return label !== void 0 && typeof label === "object";
|
|
365
425
|
}
|
|
@@ -380,7 +440,7 @@ ${enumValues}
|
|
|
380
440
|
`);
|
|
381
441
|
parts.push(`/** All ${name} values */
|
|
382
442
|
`);
|
|
383
|
-
parts.push(`export const ${name}Values = Object.values(${name});
|
|
443
|
+
parts.push(`export const ${name}Values = Object.values(${name}) as ${name}[];
|
|
384
444
|
|
|
385
445
|
`);
|
|
386
446
|
parts.push(`/** Type guard for ${name} */
|
|
@@ -398,10 +458,10 @@ ${enumValues}
|
|
|
398
458
|
if (hasMultiLocale) {
|
|
399
459
|
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => {
|
|
400
460
|
if (isMultiLocaleLabel(v.label)) {
|
|
401
|
-
const locales = Object.entries(v.label).map(([locale, text]) =>
|
|
461
|
+
const locales = Object.entries(v.label).map(([locale, text]) => `'${locale}': '${escapeString(text)}'`).join(", ");
|
|
402
462
|
return ` [${name}.${v.name}]: { ${locales} },`;
|
|
403
463
|
}
|
|
404
|
-
return ` [${name}.${v.name}]: { default: '${v.label}' },`;
|
|
464
|
+
return ` [${name}.${v.name}]: { default: '${escapeString(String(v.label))}' },`;
|
|
405
465
|
}).join("\n");
|
|
406
466
|
parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, Record<string, string>>> = {
|
|
407
467
|
${labelEntries}
|
|
@@ -418,13 +478,15 @@ ${labelEntries}
|
|
|
418
478
|
`);
|
|
419
479
|
parts.push(` if (locale && labels[locale]) return labels[locale];
|
|
420
480
|
`);
|
|
421
|
-
parts.push(`
|
|
481
|
+
parts.push(` // Fallback: ja \u2192 en \u2192 first available
|
|
482
|
+
`);
|
|
483
|
+
parts.push(` return labels['ja'] ?? labels['en'] ?? Object.values(labels)[0] ?? value;
|
|
422
484
|
`);
|
|
423
485
|
parts.push(`}
|
|
424
486
|
|
|
425
487
|
`);
|
|
426
488
|
} else {
|
|
427
|
-
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${v.label}',`).join("\n");
|
|
489
|
+
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${escapeString(String(v.label))}',`).join("\n");
|
|
428
490
|
parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, string>> = {
|
|
429
491
|
${labelEntries}
|
|
430
492
|
};
|
|
@@ -480,6 +542,9 @@ ${extraEntries}
|
|
|
480
542
|
function lowerFirst(str) {
|
|
481
543
|
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
482
544
|
}
|
|
545
|
+
function escapeString(str) {
|
|
546
|
+
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
547
|
+
}
|
|
483
548
|
function enumToUnionType(enumDef) {
|
|
484
549
|
const type = enumDef.values.map((v) => `'${v.value}'`).join(" | ");
|
|
485
550
|
return {
|
|
@@ -1001,6 +1066,13 @@ function getZodSchemaForType(propDef, fieldName, customTypes) {
|
|
|
1001
1066
|
case "Json":
|
|
1002
1067
|
schema = "z.unknown()";
|
|
1003
1068
|
break;
|
|
1069
|
+
case "EnumRef":
|
|
1070
|
+
if (typeof def.enum === "string") {
|
|
1071
|
+
schema = `z.nativeEnum(${def.enum})`;
|
|
1072
|
+
} else {
|
|
1073
|
+
schema = "z.string()";
|
|
1074
|
+
}
|
|
1075
|
+
break;
|
|
1004
1076
|
case "Enum":
|
|
1005
1077
|
if (typeof def.enum === "string") {
|
|
1006
1078
|
schema = `${def.enum}Schema`;
|
|
@@ -1046,15 +1118,35 @@ function generateCompoundTypeSchemas(propName, propDef, customType, options) {
|
|
|
1046
1118
|
for (const field of customType.expand) {
|
|
1047
1119
|
const fieldName = `${toSnakeCase(propName)}_${toSnakeCase(field.suffix)}`;
|
|
1048
1120
|
const fieldOverride = propFields?.[field.suffix];
|
|
1049
|
-
const isNullable = fieldOverride?.nullable ?? propDef.nullable ?? false;
|
|
1050
|
-
const
|
|
1121
|
+
const isNullable = fieldOverride?.nullable ?? field.sql?.nullable ?? propDef.nullable ?? false;
|
|
1122
|
+
const pluginRules = field.rules;
|
|
1123
|
+
const overrideRules = fieldOverride?.rules;
|
|
1124
|
+
const length = fieldOverride?.length ?? overrideRules?.maxLength ?? pluginRules?.maxLength ?? field.sql?.length;
|
|
1125
|
+
const minLength = overrideRules?.minLength ?? pluginRules?.minLength;
|
|
1126
|
+
const pattern = overrideRules?.pattern ?? pluginRules?.pattern;
|
|
1127
|
+
const format = overrideRules?.format ?? pluginRules?.format;
|
|
1051
1128
|
let schema = "z.string()";
|
|
1129
|
+
if (format === "email") {
|
|
1130
|
+
schema = "z.string().email()";
|
|
1131
|
+
} else if (format === "url") {
|
|
1132
|
+
schema = "z.string().url()";
|
|
1133
|
+
} else if (format === "phone") {
|
|
1134
|
+
schema = "z.string()";
|
|
1135
|
+
} else if (format === "postal_code") {
|
|
1136
|
+
schema = `z.string().regex(/^\\d{3}-?\\d{4}$/)`;
|
|
1137
|
+
}
|
|
1052
1138
|
if (!isNullable) {
|
|
1053
|
-
|
|
1139
|
+
const min = minLength ?? 1;
|
|
1140
|
+
schema += `.min(${min})`;
|
|
1141
|
+
} else if (minLength) {
|
|
1142
|
+
schema += `.min(${minLength})`;
|
|
1054
1143
|
}
|
|
1055
1144
|
if (length) {
|
|
1056
1145
|
schema += `.max(${length})`;
|
|
1057
1146
|
}
|
|
1147
|
+
if (pattern && !format) {
|
|
1148
|
+
schema += `.regex(/${pattern}/)`;
|
|
1149
|
+
}
|
|
1058
1150
|
if (isNullable) {
|
|
1059
1151
|
schema += ".optional().nullable()";
|
|
1060
1152
|
}
|
|
@@ -1110,6 +1202,7 @@ function generateDisplayNames(schema, options) {
|
|
|
1110
1202
|
schema.name
|
|
1111
1203
|
);
|
|
1112
1204
|
const propertyDisplayNames = {};
|
|
1205
|
+
const propertyPlaceholders = {};
|
|
1113
1206
|
if (schema.properties) {
|
|
1114
1207
|
for (const [propName, propDef] of Object.entries(schema.properties)) {
|
|
1115
1208
|
const prop = propDef;
|
|
@@ -1117,19 +1210,47 @@ function generateDisplayNames(schema, options) {
|
|
|
1117
1210
|
if (customTypes) {
|
|
1118
1211
|
const customType = customTypes.get(propDef.type);
|
|
1119
1212
|
if (customType?.compound && customType.expand) {
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
propertyDisplayNames[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1213
|
+
if (prop.displayName) {
|
|
1214
|
+
propertyDisplayNames[fieldName] = getMultiLocaleDisplayName2(
|
|
1123
1215
|
prop.displayName,
|
|
1124
1216
|
locales,
|
|
1125
1217
|
fallbackLocale,
|
|
1126
1218
|
propName
|
|
1127
1219
|
);
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1220
|
+
}
|
|
1221
|
+
for (const field of customType.expand) {
|
|
1222
|
+
const expandedFieldName = `${fieldName}_${toSnakeCase(field.suffix)}`;
|
|
1223
|
+
const fieldOverride = prop.fields?.[field.suffix];
|
|
1224
|
+
const labelSource = fieldOverride?.displayName ?? field.label;
|
|
1225
|
+
if (labelSource) {
|
|
1226
|
+
propertyDisplayNames[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1227
|
+
labelSource,
|
|
1228
|
+
locales,
|
|
1229
|
+
fallbackLocale,
|
|
1230
|
+
field.suffix
|
|
1231
|
+
);
|
|
1232
|
+
} else {
|
|
1233
|
+
propertyDisplayNames[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1234
|
+
prop.displayName,
|
|
1235
|
+
locales,
|
|
1236
|
+
fallbackLocale,
|
|
1237
|
+
propName
|
|
1238
|
+
);
|
|
1239
|
+
for (const locale of locales) {
|
|
1240
|
+
propertyDisplayNames[expandedFieldName] = {
|
|
1241
|
+
...propertyDisplayNames[expandedFieldName],
|
|
1242
|
+
[locale]: `${propertyDisplayNames[expandedFieldName][locale]} (${field.suffix})`
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
const placeholderSource = fieldOverride?.placeholder ?? field.placeholder;
|
|
1247
|
+
if (placeholderSource) {
|
|
1248
|
+
propertyPlaceholders[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1249
|
+
placeholderSource,
|
|
1250
|
+
locales,
|
|
1251
|
+
fallbackLocale,
|
|
1252
|
+
""
|
|
1253
|
+
);
|
|
1133
1254
|
}
|
|
1134
1255
|
}
|
|
1135
1256
|
continue;
|
|
@@ -1141,9 +1262,17 @@ function generateDisplayNames(schema, options) {
|
|
|
1141
1262
|
fallbackLocale,
|
|
1142
1263
|
propName
|
|
1143
1264
|
);
|
|
1265
|
+
if (prop.placeholder) {
|
|
1266
|
+
propertyPlaceholders[fieldName] = getMultiLocaleDisplayName2(
|
|
1267
|
+
prop.placeholder,
|
|
1268
|
+
locales,
|
|
1269
|
+
fallbackLocale,
|
|
1270
|
+
""
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1144
1273
|
}
|
|
1145
1274
|
}
|
|
1146
|
-
return { displayName, propertyDisplayNames };
|
|
1275
|
+
return { displayName, propertyDisplayNames, propertyPlaceholders };
|
|
1147
1276
|
}
|
|
1148
1277
|
function getExcludedFields(schema, customTypes) {
|
|
1149
1278
|
const createExclude = /* @__PURE__ */ new Set();
|
|
@@ -1187,24 +1316,44 @@ function formatZodSchemasSection(schemaName, zodSchemas, displayNames, excludedF
|
|
|
1187
1316
|
const lowerName = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
|
|
1188
1317
|
parts.push(`// ============================================================================
|
|
1189
1318
|
`);
|
|
1190
|
-
parts.push(`//
|
|
1319
|
+
parts.push(`// I18n (Internationalization)
|
|
1191
1320
|
`);
|
|
1192
1321
|
parts.push(`// ============================================================================
|
|
1193
1322
|
|
|
1194
1323
|
`);
|
|
1195
|
-
parts.push(`/**
|
|
1324
|
+
parts.push(`/**
|
|
1196
1325
|
`);
|
|
1197
|
-
parts.push(`
|
|
1198
|
-
|
|
1326
|
+
parts.push(` * Unified i18n object for ${schemaName}
|
|
1199
1327
|
`);
|
|
1200
|
-
parts.push(
|
|
1328
|
+
parts.push(` * Contains model label and all field labels/placeholders
|
|
1329
|
+
`);
|
|
1330
|
+
parts.push(` */
|
|
1331
|
+
`);
|
|
1332
|
+
parts.push(`export const ${lowerName}I18n = {
|
|
1333
|
+
`);
|
|
1334
|
+
parts.push(` /** Model display name */
|
|
1201
1335
|
`);
|
|
1202
|
-
parts.push(`
|
|
1336
|
+
parts.push(` label: ${JSON.stringify(displayNames.displayName)},
|
|
1203
1337
|
`);
|
|
1204
|
-
|
|
1205
|
-
|
|
1338
|
+
parts.push(` /** Field labels and placeholders */
|
|
1339
|
+
`);
|
|
1340
|
+
parts.push(` fields: {
|
|
1341
|
+
`);
|
|
1342
|
+
for (const [propName, labelMap] of Object.entries(displayNames.propertyDisplayNames)) {
|
|
1343
|
+
const placeholderMap = displayNames.propertyPlaceholders[propName];
|
|
1344
|
+
parts.push(` ${propName}: {
|
|
1345
|
+
`);
|
|
1346
|
+
parts.push(` label: ${JSON.stringify(labelMap)},
|
|
1347
|
+
`);
|
|
1348
|
+
if (placeholderMap) {
|
|
1349
|
+
parts.push(` placeholder: ${JSON.stringify(placeholderMap)},
|
|
1350
|
+
`);
|
|
1351
|
+
}
|
|
1352
|
+
parts.push(` },
|
|
1206
1353
|
`);
|
|
1207
1354
|
}
|
|
1355
|
+
parts.push(` },
|
|
1356
|
+
`);
|
|
1208
1357
|
parts.push(`} as const;
|
|
1209
1358
|
|
|
1210
1359
|
`);
|
|
@@ -1261,35 +1410,50 @@ function formatZodSchemasSection(schemaName, zodSchemas, displayNames, excludedF
|
|
|
1261
1410
|
`);
|
|
1262
1411
|
parts.push(`// ============================================================================
|
|
1263
1412
|
`);
|
|
1264
|
-
parts.push(`// Helper Functions
|
|
1413
|
+
parts.push(`// I18n Helper Functions
|
|
1265
1414
|
`);
|
|
1266
1415
|
parts.push(`// ============================================================================
|
|
1267
1416
|
|
|
1268
1417
|
`);
|
|
1269
|
-
parts.push(`/** Get
|
|
1418
|
+
parts.push(`/** Get model label for a specific locale */
|
|
1270
1419
|
`);
|
|
1271
|
-
parts.push(`export function get${schemaName}
|
|
1420
|
+
parts.push(`export function get${schemaName}Label(locale: string): string {
|
|
1272
1421
|
`);
|
|
1273
|
-
parts.push(` return ${
|
|
1422
|
+
parts.push(` return ${lowerName}I18n.label[locale as keyof typeof ${lowerName}I18n.label] ?? ${lowerName}I18n.label['en'] ?? '${schemaName}';
|
|
1274
1423
|
`);
|
|
1275
1424
|
parts.push(`}
|
|
1276
1425
|
|
|
1277
1426
|
`);
|
|
1278
|
-
parts.push(`/** Get
|
|
1427
|
+
parts.push(`/** Get field label for a specific locale */
|
|
1279
1428
|
`);
|
|
1280
|
-
parts.push(`export function get${schemaName}
|
|
1429
|
+
parts.push(`export function get${schemaName}FieldLabel(field: string, locale: string): string {
|
|
1430
|
+
`);
|
|
1431
|
+
parts.push(` const fieldI18n = ${lowerName}I18n.fields[field as keyof typeof ${lowerName}I18n.fields];
|
|
1432
|
+
`);
|
|
1433
|
+
parts.push(` if (!fieldI18n) return field;
|
|
1281
1434
|
`);
|
|
1282
|
-
parts.push(`
|
|
1435
|
+
parts.push(` return fieldI18n.label[locale as keyof typeof fieldI18n.label] ?? fieldI18n.label['en'] ?? field;
|
|
1283
1436
|
`);
|
|
1284
|
-
parts.push(`
|
|
1437
|
+
parts.push(`}
|
|
1438
|
+
|
|
1439
|
+
`);
|
|
1440
|
+
parts.push(`/** Get field placeholder for a specific locale */
|
|
1441
|
+
`);
|
|
1442
|
+
parts.push(`export function get${schemaName}FieldPlaceholder(field: string, locale: string): string {
|
|
1443
|
+
`);
|
|
1444
|
+
parts.push(` const fieldI18n = ${lowerName}I18n.fields[field as keyof typeof ${lowerName}I18n.fields];
|
|
1445
|
+
`);
|
|
1446
|
+
parts.push(` if (!fieldI18n || !('placeholder' in fieldI18n)) return '';
|
|
1447
|
+
`);
|
|
1448
|
+
parts.push(` const placeholder = fieldI18n.placeholder as Record<string, string>;
|
|
1285
1449
|
`);
|
|
1286
|
-
parts.push(` return
|
|
1450
|
+
parts.push(` return placeholder[locale] ?? placeholder['en'] ?? '';
|
|
1287
1451
|
`);
|
|
1288
1452
|
parts.push(`}
|
|
1289
1453
|
`);
|
|
1290
1454
|
return parts.join("");
|
|
1291
1455
|
}
|
|
1292
|
-
function formatZodModelFile(schemaName) {
|
|
1456
|
+
function formatZodModelFile(schemaName, _hasPlaceholders = false) {
|
|
1293
1457
|
const lowerName = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
|
|
1294
1458
|
return `/**
|
|
1295
1459
|
* ${schemaName} Model
|
|
@@ -1305,10 +1469,10 @@ import {
|
|
|
1305
1469
|
base${schemaName}Schemas,
|
|
1306
1470
|
base${schemaName}CreateSchema,
|
|
1307
1471
|
base${schemaName}UpdateSchema,
|
|
1308
|
-
${
|
|
1309
|
-
${schemaName}
|
|
1310
|
-
get${schemaName}
|
|
1311
|
-
get${schemaName}
|
|
1472
|
+
${lowerName}I18n,
|
|
1473
|
+
get${schemaName}Label,
|
|
1474
|
+
get${schemaName}FieldLabel,
|
|
1475
|
+
get${schemaName}FieldPlaceholder,
|
|
1312
1476
|
} from './base/${schemaName}.js';
|
|
1313
1477
|
|
|
1314
1478
|
// ============================================================================
|
|
@@ -1334,12 +1498,12 @@ export const ${lowerName}UpdateSchema = base${schemaName}UpdateSchema;
|
|
|
1334
1498
|
export type ${schemaName}Create = z.infer<typeof ${lowerName}CreateSchema>;
|
|
1335
1499
|
export type ${schemaName}Update = z.infer<typeof ${lowerName}UpdateSchema>;
|
|
1336
1500
|
|
|
1337
|
-
// Re-export
|
|
1501
|
+
// Re-export i18n and helpers
|
|
1338
1502
|
export {
|
|
1339
|
-
${
|
|
1340
|
-
${schemaName}
|
|
1341
|
-
get${schemaName}
|
|
1342
|
-
get${schemaName}
|
|
1503
|
+
${lowerName}I18n,
|
|
1504
|
+
get${schemaName}Label,
|
|
1505
|
+
get${schemaName}FieldLabel,
|
|
1506
|
+
get${schemaName}FieldPlaceholder,
|
|
1343
1507
|
};
|
|
1344
1508
|
|
|
1345
1509
|
// Re-export base type for internal use
|
|
@@ -1455,13 +1619,24 @@ function generateBaseInterfaceFile(schemaName, schemas, options) {
|
|
|
1455
1619
|
parts.push(`import type { ${commonImports.join(", ")} } from '../common.js';
|
|
1456
1620
|
`);
|
|
1457
1621
|
}
|
|
1622
|
+
if (iface.enumDependencies && iface.enumDependencies.length > 0) {
|
|
1623
|
+
const enumPrefix = options.enumImportPrefix ? `../${options.enumImportPrefix}` : "../enum";
|
|
1624
|
+
const pluginEnumNames = new Set(
|
|
1625
|
+
options.pluginEnums ? Array.from(options.pluginEnums.keys()) : []
|
|
1626
|
+
);
|
|
1627
|
+
for (const enumName of iface.enumDependencies) {
|
|
1628
|
+
const enumPath = pluginEnumNames.has(enumName) ? `${enumPrefix}/plugin/${enumName}.js` : `${enumPrefix}/${enumName}.js`;
|
|
1629
|
+
parts.push(`import { ${enumName} } from '${enumPath}';
|
|
1630
|
+
`);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1458
1633
|
if (iface.dependencies && iface.dependencies.length > 0) {
|
|
1459
1634
|
for (const dep of iface.dependencies) {
|
|
1460
1635
|
parts.push(`import type { ${dep} } from './${dep}.js';
|
|
1461
1636
|
`);
|
|
1462
1637
|
}
|
|
1463
1638
|
parts.push("\n");
|
|
1464
|
-
} else if (commonImports.length > 0 || options.generateZodSchemas) {
|
|
1639
|
+
} else if (commonImports.length > 0 || options.generateZodSchemas || iface.enumDependencies && iface.enumDependencies.length > 0) {
|
|
1465
1640
|
parts.push("\n");
|
|
1466
1641
|
}
|
|
1467
1642
|
parts.push(formatInterface(iface));
|
|
@@ -1482,15 +1657,17 @@ function generateBaseInterfaceFile(schemaName, schemas, options) {
|
|
|
1482
1657
|
overwrite: true
|
|
1483
1658
|
};
|
|
1484
1659
|
}
|
|
1485
|
-
function generateEnumFile(enumDef) {
|
|
1660
|
+
function generateEnumFile(enumDef, isPluginEnum = false) {
|
|
1486
1661
|
const parts = [generateBaseHeader()];
|
|
1487
1662
|
parts.push(formatEnum(enumDef));
|
|
1488
1663
|
parts.push("\n");
|
|
1664
|
+
const filePath = isPluginEnum ? `plugin/${enumDef.name}.ts` : `${enumDef.name}.ts`;
|
|
1489
1665
|
return {
|
|
1490
|
-
filePath
|
|
1666
|
+
filePath,
|
|
1491
1667
|
content: parts.join(""),
|
|
1492
1668
|
types: [enumDef.name],
|
|
1493
|
-
overwrite: true
|
|
1669
|
+
overwrite: true,
|
|
1670
|
+
category: "enum"
|
|
1494
1671
|
};
|
|
1495
1672
|
}
|
|
1496
1673
|
function generateTypeAliasFile(alias) {
|
|
@@ -1498,10 +1675,11 @@ function generateTypeAliasFile(alias) {
|
|
|
1498
1675
|
parts.push(formatTypeAlias(alias));
|
|
1499
1676
|
parts.push("\n");
|
|
1500
1677
|
return {
|
|
1501
|
-
filePath:
|
|
1678
|
+
filePath: `${alias.name}.ts`,
|
|
1502
1679
|
content: parts.join(""),
|
|
1503
1680
|
types: [alias.name],
|
|
1504
|
-
overwrite: true
|
|
1681
|
+
overwrite: true,
|
|
1682
|
+
category: "enum"
|
|
1505
1683
|
};
|
|
1506
1684
|
}
|
|
1507
1685
|
function generateModelFile(schemaName, options) {
|
|
@@ -1542,6 +1720,88 @@ function generateModelFile(schemaName, options) {
|
|
|
1542
1720
|
// Never overwrite user models
|
|
1543
1721
|
};
|
|
1544
1722
|
}
|
|
1723
|
+
var DEFAULT_VALIDATION_MESSAGES = {
|
|
1724
|
+
required: {
|
|
1725
|
+
en: "${displayName} is required",
|
|
1726
|
+
ja: "${displayName}\u306F\u5FC5\u9808\u3067\u3059",
|
|
1727
|
+
vi: "${displayName} l\xE0 b\u1EAFt bu\u1ED9c",
|
|
1728
|
+
ko: "${displayName}\uC740(\uB294) \uD544\uC218\uC785\uB2C8\uB2E4",
|
|
1729
|
+
"zh-CN": "${displayName}\u662F\u5FC5\u586B\u9879",
|
|
1730
|
+
"zh-TW": "${displayName}\u70BA\u5FC5\u586B\u6B04\u4F4D",
|
|
1731
|
+
th: "${displayName} \u0E08\u0E33\u0E40\u0E1B\u0E47\u0E19\u0E15\u0E49\u0E2D\u0E07\u0E01\u0E23\u0E2D\u0E01",
|
|
1732
|
+
es: "${displayName} es obligatorio"
|
|
1733
|
+
},
|
|
1734
|
+
minLength: {
|
|
1735
|
+
en: "${displayName} must be at least ${min} characters",
|
|
1736
|
+
ja: "${displayName}\u306F${min}\u6587\u5B57\u4EE5\u4E0A\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1737
|
+
vi: "${displayName} ph\u1EA3i c\xF3 \xEDt nh\u1EA5t ${min} k\xFD t\u1EF1",
|
|
1738
|
+
ko: "${displayName}\uC740(\uB294) ${min}\uC790 \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
|
|
1739
|
+
"zh-CN": "${displayName}\u81F3\u5C11\u9700\u8981${min}\u4E2A\u5B57\u7B26",
|
|
1740
|
+
"zh-TW": "${displayName}\u81F3\u5C11\u9700\u8981${min}\u500B\u5B57\u5143",
|
|
1741
|
+
th: "${displayName} \u0E15\u0E49\u0E2D\u0E07\u0E21\u0E35\u0E2D\u0E22\u0E48\u0E32\u0E07\u0E19\u0E49\u0E2D\u0E22 ${min} \u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23",
|
|
1742
|
+
es: "${displayName} debe tener al menos ${min} caracteres"
|
|
1743
|
+
},
|
|
1744
|
+
maxLength: {
|
|
1745
|
+
en: "${displayName} must be at most ${max} characters",
|
|
1746
|
+
ja: "${displayName}\u306F${max}\u6587\u5B57\u4EE5\u5185\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1747
|
+
vi: "${displayName} kh\xF4ng \u0111\u01B0\u1EE3c qu\xE1 ${max} k\xFD t\u1EF1",
|
|
1748
|
+
ko: "${displayName}\uC740(\uB294) ${max}\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
|
|
1749
|
+
"zh-CN": "${displayName}\u6700\u591A${max}\u4E2A\u5B57\u7B26",
|
|
1750
|
+
"zh-TW": "${displayName}\u6700\u591A${max}\u500B\u5B57\u5143",
|
|
1751
|
+
th: "${displayName} \u0E15\u0E49\u0E2D\u0E07\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 ${max} \u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23",
|
|
1752
|
+
es: "${displayName} debe tener como m\xE1ximo ${max} caracteres"
|
|
1753
|
+
},
|
|
1754
|
+
min: {
|
|
1755
|
+
en: "${displayName} must be at least ${min}",
|
|
1756
|
+
ja: "${displayName}\u306F${min}\u4EE5\u4E0A\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1757
|
+
vi: "${displayName} ph\u1EA3i l\u1EDBn h\u01A1n ho\u1EB7c b\u1EB1ng ${min}",
|
|
1758
|
+
ko: "${displayName}\uC740(\uB294) ${min} \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
|
|
1759
|
+
"zh-CN": "${displayName}\u5FC5\u987B\u5927\u4E8E\u7B49\u4E8E${min}",
|
|
1760
|
+
"zh-TW": "${displayName}\u5FC5\u9808\u5927\u65BC\u7B49\u65BC${min}",
|
|
1761
|
+
th: "${displayName} \u0E15\u0E49\u0E2D\u0E07\u0E21\u0E32\u0E01\u0E01\u0E27\u0E48\u0E32\u0E2B\u0E23\u0E37\u0E2D\u0E40\u0E17\u0E48\u0E32\u0E01\u0E31\u0E1A ${min}",
|
|
1762
|
+
es: "${displayName} debe ser al menos ${min}"
|
|
1763
|
+
},
|
|
1764
|
+
max: {
|
|
1765
|
+
en: "${displayName} must be at most ${max}",
|
|
1766
|
+
ja: "${displayName}\u306F${max}\u4EE5\u4E0B\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1767
|
+
vi: "${displayName} ph\u1EA3i nh\u1ECF h\u01A1n ho\u1EB7c b\u1EB1ng ${max}",
|
|
1768
|
+
ko: "${displayName}\uC740(\uB294) ${max} \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
|
|
1769
|
+
"zh-CN": "${displayName}\u5FC5\u987B\u5C0F\u4E8E\u7B49\u4E8E${max}",
|
|
1770
|
+
"zh-TW": "${displayName}\u5FC5\u9808\u5C0F\u65BC\u7B49\u65BC${max}",
|
|
1771
|
+
th: "${displayName} \u0E15\u0E49\u0E2D\u0E07\u0E19\u0E49\u0E2D\u0E22\u0E01\u0E27\u0E48\u0E32\u0E2B\u0E23\u0E37\u0E2D\u0E40\u0E17\u0E48\u0E32\u0E01\u0E31\u0E1A ${max}",
|
|
1772
|
+
es: "${displayName} debe ser como m\xE1ximo ${max}"
|
|
1773
|
+
},
|
|
1774
|
+
email: {
|
|
1775
|
+
en: "Please enter a valid email address",
|
|
1776
|
+
ja: "\u6709\u52B9\u306A\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1777
|
+
vi: "Vui l\xF2ng nh\u1EADp \u0111\u1ECBa ch\u1EC9 email h\u1EE3p l\u1EC7",
|
|
1778
|
+
ko: "\uC720\uD6A8\uD55C \uC774\uBA54\uC77C \uC8FC\uC18C\uB97C \uC785\uB825\uD558\uC138\uC694",
|
|
1779
|
+
"zh-CN": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7535\u5B50\u90AE\u4EF6\u5730\u5740",
|
|
1780
|
+
"zh-TW": "\u8ACB\u8F38\u5165\u6709\u6548\u7684\u96FB\u5B50\u90F5\u4EF6\u5730\u5740",
|
|
1781
|
+
th: "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E01\u0E23\u0E2D\u0E01\u0E2D\u0E35\u0E40\u0E21\u0E25\u0E17\u0E35\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07",
|
|
1782
|
+
es: "Por favor, introduce una direcci\xF3n de correo electr\xF3nico v\xE1lida"
|
|
1783
|
+
},
|
|
1784
|
+
url: {
|
|
1785
|
+
en: "Please enter a valid URL",
|
|
1786
|
+
ja: "\u6709\u52B9\u306AURL\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1787
|
+
vi: "Vui l\xF2ng nh\u1EADp URL h\u1EE3p l\u1EC7",
|
|
1788
|
+
ko: "\uC720\uD6A8\uD55C URL\uC744 \uC785\uB825\uD558\uC138\uC694",
|
|
1789
|
+
"zh-CN": "\u8BF7\u8F93\u5165\u6709\u6548\u7684URL",
|
|
1790
|
+
"zh-TW": "\u8ACB\u8F38\u5165\u6709\u6548\u7684\u7DB2\u5740",
|
|
1791
|
+
th: "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E01\u0E23\u0E2D\u0E01 URL \u0E17\u0E35\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07",
|
|
1792
|
+
es: "Por favor, introduce una URL v\xE1lida"
|
|
1793
|
+
},
|
|
1794
|
+
pattern: {
|
|
1795
|
+
en: "${displayName} format is invalid",
|
|
1796
|
+
ja: "${displayName}\u306E\u5F62\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093",
|
|
1797
|
+
vi: "${displayName} kh\xF4ng \u0111\xFAng \u0111\u1ECBnh d\u1EA1ng",
|
|
1798
|
+
ko: "${displayName} \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
|
|
1799
|
+
"zh-CN": "${displayName}\u683C\u5F0F\u4E0D\u6B63\u786E",
|
|
1800
|
+
"zh-TW": "${displayName}\u683C\u5F0F\u4E0D\u6B63\u78BA",
|
|
1801
|
+
th: "\u0E23\u0E39\u0E1B\u0E41\u0E1A\u0E1A${displayName}\u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07",
|
|
1802
|
+
es: "El formato de ${displayName} no es v\xE1lido"
|
|
1803
|
+
}
|
|
1804
|
+
};
|
|
1545
1805
|
function generateCommonFile(options) {
|
|
1546
1806
|
const locales = options.localeConfig?.locales ?? ["ja", "en"];
|
|
1547
1807
|
const localeUnion = locales.map((l) => `'${l}'`).join(" | ");
|
|
@@ -1589,15 +1849,142 @@ export type DateString = string;
|
|
|
1589
1849
|
overwrite: true
|
|
1590
1850
|
};
|
|
1591
1851
|
}
|
|
1592
|
-
function
|
|
1852
|
+
function generateI18nFile(options) {
|
|
1853
|
+
const locales = options.localeConfig?.locales ?? ["ja", "en"];
|
|
1854
|
+
const defaultLocale = options.localeConfig?.defaultLocale ?? "ja";
|
|
1855
|
+
const fallbackLocale = options.localeConfig?.fallbackLocale ?? "en";
|
|
1856
|
+
const userMessages = options.localeConfig?.messages ?? {};
|
|
1857
|
+
const mergedMessages = {};
|
|
1858
|
+
for (const [key, defaultMsgs] of Object.entries(DEFAULT_VALIDATION_MESSAGES)) {
|
|
1859
|
+
mergedMessages[key] = {};
|
|
1860
|
+
for (const locale of locales) {
|
|
1861
|
+
if (defaultMsgs[locale]) {
|
|
1862
|
+
mergedMessages[key][locale] = defaultMsgs[locale];
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
for (const [key, userMsgs] of Object.entries(userMessages)) {
|
|
1867
|
+
if (userMsgs) {
|
|
1868
|
+
if (!mergedMessages[key]) {
|
|
1869
|
+
mergedMessages[key] = {};
|
|
1870
|
+
}
|
|
1871
|
+
for (const [locale, msg] of Object.entries(userMsgs)) {
|
|
1872
|
+
mergedMessages[key][locale] = msg;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
const messagesJson = JSON.stringify(mergedMessages, null, 2);
|
|
1877
|
+
const content = `${generateBaseHeader()}
|
|
1878
|
+
import type { LocaleMap } from './common.js';
|
|
1879
|
+
|
|
1880
|
+
/**
|
|
1881
|
+
* Default locale for this project.
|
|
1882
|
+
*/
|
|
1883
|
+
export const defaultLocale = '${defaultLocale}' as const;
|
|
1884
|
+
|
|
1885
|
+
/**
|
|
1886
|
+
* Fallback locale when requested locale is not found.
|
|
1887
|
+
*/
|
|
1888
|
+
export const fallbackLocale = '${fallbackLocale}' as const;
|
|
1889
|
+
|
|
1890
|
+
/**
|
|
1891
|
+
* Supported locales in this project.
|
|
1892
|
+
*/
|
|
1893
|
+
export const supportedLocales = ${JSON.stringify(locales)} as const;
|
|
1894
|
+
|
|
1895
|
+
/**
|
|
1896
|
+
* Validation messages for all supported locales.
|
|
1897
|
+
* Use getMessage(key, locale, params) to get formatted message.
|
|
1898
|
+
*/
|
|
1899
|
+
export const validationMessages = ${messagesJson} as const;
|
|
1900
|
+
|
|
1901
|
+
/**
|
|
1902
|
+
* Get validation message for a specific key and locale.
|
|
1903
|
+
* Supports template placeholders: \${displayName}, \${min}, \${max}, etc.
|
|
1904
|
+
*
|
|
1905
|
+
* @param key - Message key (e.g., 'required', 'minLength')
|
|
1906
|
+
* @param locale - Locale code (e.g., 'ja', 'en')
|
|
1907
|
+
* @param params - Template parameters to replace
|
|
1908
|
+
* @returns Formatted message string
|
|
1909
|
+
*
|
|
1910
|
+
* @example
|
|
1911
|
+
* getMessage('required', 'ja', { displayName: '\u6C0F\u540D' })
|
|
1912
|
+
* // => '\u6C0F\u540D\u306F\u5FC5\u9808\u3067\u3059'
|
|
1913
|
+
*/
|
|
1914
|
+
export function getMessage(
|
|
1915
|
+
key: string,
|
|
1916
|
+
locale: string,
|
|
1917
|
+
params: Record<string, string | number> = {}
|
|
1918
|
+
): string {
|
|
1919
|
+
const messages = validationMessages[key as keyof typeof validationMessages];
|
|
1920
|
+
if (!messages) return key;
|
|
1921
|
+
|
|
1922
|
+
let message = (messages as LocaleMap)[locale]
|
|
1923
|
+
?? (messages as LocaleMap)[fallbackLocale]
|
|
1924
|
+
?? (messages as LocaleMap)[defaultLocale]
|
|
1925
|
+
?? key;
|
|
1926
|
+
|
|
1927
|
+
// Replace template placeholders
|
|
1928
|
+
for (const [param, value] of Object.entries(params)) {
|
|
1929
|
+
message = message.replace(new RegExp(\`\\\\$\\{\${param}\\}\`, 'g'), String(value));
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
return message;
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
/**
|
|
1936
|
+
* Get all validation messages for a specific locale.
|
|
1937
|
+
*
|
|
1938
|
+
* @param locale - Locale code
|
|
1939
|
+
* @returns Object with all messages for the locale
|
|
1940
|
+
*/
|
|
1941
|
+
export function getMessages(locale: string): Record<string, string> {
|
|
1942
|
+
const result: Record<string, string> = {};
|
|
1943
|
+
for (const [key, messages] of Object.entries(validationMessages)) {
|
|
1944
|
+
result[key] = (messages as LocaleMap)[locale]
|
|
1945
|
+
?? (messages as LocaleMap)[fallbackLocale]
|
|
1946
|
+
?? (messages as LocaleMap)[defaultLocale]
|
|
1947
|
+
?? key;
|
|
1948
|
+
}
|
|
1949
|
+
return result;
|
|
1950
|
+
}
|
|
1951
|
+
`;
|
|
1952
|
+
return {
|
|
1953
|
+
filePath: "i18n.ts",
|
|
1954
|
+
content,
|
|
1955
|
+
types: ["validationMessages", "getMessage", "getMessages"],
|
|
1956
|
+
overwrite: true
|
|
1957
|
+
};
|
|
1958
|
+
}
|
|
1959
|
+
function generateIndexFile(schemas, enums, pluginEnums, typeAliases, options) {
|
|
1593
1960
|
const parts = [generateBaseHeader()];
|
|
1594
1961
|
parts.push(`// Common Types
|
|
1595
1962
|
`);
|
|
1596
1963
|
parts.push(`export type { LocaleMap, Locale, ValidationRule, DateTimeString, DateString } from './common.js';
|
|
1597
1964
|
|
|
1598
1965
|
`);
|
|
1599
|
-
|
|
1600
|
-
|
|
1966
|
+
parts.push(`// i18n (Internationalization)
|
|
1967
|
+
`);
|
|
1968
|
+
parts.push(`export {
|
|
1969
|
+
`);
|
|
1970
|
+
parts.push(` defaultLocale,
|
|
1971
|
+
`);
|
|
1972
|
+
parts.push(` fallbackLocale,
|
|
1973
|
+
`);
|
|
1974
|
+
parts.push(` supportedLocales,
|
|
1975
|
+
`);
|
|
1976
|
+
parts.push(` validationMessages,
|
|
1977
|
+
`);
|
|
1978
|
+
parts.push(` getMessage,
|
|
1979
|
+
`);
|
|
1980
|
+
parts.push(` getMessages,
|
|
1981
|
+
`);
|
|
1982
|
+
parts.push(`} from './i18n.js';
|
|
1983
|
+
|
|
1984
|
+
`);
|
|
1985
|
+
const enumPrefix = options.enumImportPrefix ?? "./enum";
|
|
1986
|
+
if (enums.length > 0) {
|
|
1987
|
+
parts.push(`// Schema Enums
|
|
1601
1988
|
`);
|
|
1602
1989
|
for (const enumDef of enums) {
|
|
1603
1990
|
parts.push(`export {
|
|
@@ -1612,9 +1999,35 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1612
1999
|
`);
|
|
1613
2000
|
parts.push(` get${enumDef.name}Extra,
|
|
1614
2001
|
`);
|
|
1615
|
-
parts.push(`} from '
|
|
2002
|
+
parts.push(`} from '${enumPrefix}/${enumDef.name}.js';
|
|
2003
|
+
`);
|
|
2004
|
+
}
|
|
2005
|
+
parts.push("\n");
|
|
2006
|
+
}
|
|
2007
|
+
if (pluginEnums.length > 0) {
|
|
2008
|
+
parts.push(`// Plugin Enums
|
|
2009
|
+
`);
|
|
2010
|
+
for (const enumDef of pluginEnums) {
|
|
2011
|
+
parts.push(`export {
|
|
2012
|
+
`);
|
|
2013
|
+
parts.push(` ${enumDef.name},
|
|
2014
|
+
`);
|
|
2015
|
+
parts.push(` ${enumDef.name}Values,
|
|
2016
|
+
`);
|
|
2017
|
+
parts.push(` is${enumDef.name},
|
|
2018
|
+
`);
|
|
2019
|
+
parts.push(` get${enumDef.name}Label,
|
|
2020
|
+
`);
|
|
2021
|
+
parts.push(` get${enumDef.name}Extra,
|
|
2022
|
+
`);
|
|
2023
|
+
parts.push(`} from '${enumPrefix}/plugin/${enumDef.name}.js';
|
|
1616
2024
|
`);
|
|
1617
2025
|
}
|
|
2026
|
+
parts.push("\n");
|
|
2027
|
+
}
|
|
2028
|
+
if (typeAliases.length > 0) {
|
|
2029
|
+
parts.push(`// Inline Enums (Type Aliases)
|
|
2030
|
+
`);
|
|
1618
2031
|
for (const alias of typeAliases) {
|
|
1619
2032
|
parts.push(`export {
|
|
1620
2033
|
`);
|
|
@@ -1628,13 +2041,13 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1628
2041
|
`);
|
|
1629
2042
|
parts.push(` get${alias.name}Extra,
|
|
1630
2043
|
`);
|
|
1631
|
-
parts.push(`} from '
|
|
2044
|
+
parts.push(`} from '${enumPrefix}/${alias.name}.js';
|
|
1632
2045
|
`);
|
|
1633
2046
|
}
|
|
1634
2047
|
parts.push("\n");
|
|
1635
2048
|
}
|
|
1636
2049
|
if (options.generateZodSchemas) {
|
|
1637
|
-
parts.push(`// Models (with Zod schemas and Create/Update types)
|
|
2050
|
+
parts.push(`// Models (with Zod schemas, i18n, and Create/Update types)
|
|
1638
2051
|
`);
|
|
1639
2052
|
for (const schema of Object.values(schemas)) {
|
|
1640
2053
|
if (schema.kind === "enum") continue;
|
|
@@ -1650,13 +2063,13 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1650
2063
|
`);
|
|
1651
2064
|
parts.push(` ${lowerName}UpdateSchema,
|
|
1652
2065
|
`);
|
|
1653
|
-
parts.push(` ${
|
|
2066
|
+
parts.push(` ${lowerName}I18n,
|
|
1654
2067
|
`);
|
|
1655
|
-
parts.push(` ${schema.name}
|
|
2068
|
+
parts.push(` get${schema.name}Label,
|
|
1656
2069
|
`);
|
|
1657
|
-
parts.push(` get${schema.name}
|
|
2070
|
+
parts.push(` get${schema.name}FieldLabel,
|
|
1658
2071
|
`);
|
|
1659
|
-
parts.push(` get${schema.name}
|
|
2072
|
+
parts.push(` get${schema.name}FieldPlaceholder,
|
|
1660
2073
|
`);
|
|
1661
2074
|
parts.push(`} from './${schema.name}.js';
|
|
1662
2075
|
`);
|
|
@@ -1702,9 +2115,47 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1702
2115
|
function generateTypeScript(schemas, options = {}) {
|
|
1703
2116
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
1704
2117
|
const files = [];
|
|
2118
|
+
const schemasByName = /* @__PURE__ */ new Map();
|
|
2119
|
+
for (const schema of Object.values(schemas)) {
|
|
2120
|
+
const paths = schemasByName.get(schema.name) ?? [];
|
|
2121
|
+
paths.push(schema.relativePath ?? schema.filePath);
|
|
2122
|
+
schemasByName.set(schema.name, paths);
|
|
2123
|
+
}
|
|
2124
|
+
const duplicateSchemas = Array.from(schemasByName.entries()).filter(([, paths]) => paths.length > 1);
|
|
2125
|
+
if (duplicateSchemas.length > 0) {
|
|
2126
|
+
const errors = duplicateSchemas.map(
|
|
2127
|
+
([name, paths]) => ` - "${name}" defined in: ${paths.join(", ")}`
|
|
2128
|
+
).join("\n");
|
|
2129
|
+
throw new Error(
|
|
2130
|
+
`Duplicate schema/enum names detected. Names must be globally unique:
|
|
2131
|
+
${errors}
|
|
2132
|
+
Hint: Rename to unique names like "Blog${duplicateSchemas[0][0]}" or "Shop${duplicateSchemas[0][0]}"`
|
|
2133
|
+
);
|
|
2134
|
+
}
|
|
2135
|
+
if (opts.pluginEnums && opts.pluginEnums.size > 0) {
|
|
2136
|
+
const conflicts = [];
|
|
2137
|
+
for (const schema of Object.values(schemas)) {
|
|
2138
|
+
if (schema.kind === "enum" && opts.pluginEnums.has(schema.name)) {
|
|
2139
|
+
conflicts.push(`"${schema.name}" (schema: ${schema.relativePath ?? schema.filePath}, plugin enum)`);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
if (conflicts.length > 0) {
|
|
2143
|
+
throw new Error(
|
|
2144
|
+
`Schema enum conflicts with plugin enum:
|
|
2145
|
+
- ${conflicts.join("\n - ")}
|
|
2146
|
+
Hint: Rename your schema enum to avoid conflict with plugin-provided enums`
|
|
2147
|
+
);
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
1705
2150
|
const enums = generateEnums(schemas, opts);
|
|
1706
2151
|
for (const enumDef of enums) {
|
|
1707
|
-
files.push(generateEnumFile(enumDef));
|
|
2152
|
+
files.push(generateEnumFile(enumDef, false));
|
|
2153
|
+
}
|
|
2154
|
+
if (opts.pluginEnums && opts.pluginEnums.size > 0) {
|
|
2155
|
+
const pluginEnums = generatePluginEnums(opts.pluginEnums, opts);
|
|
2156
|
+
for (const enumDef of pluginEnums) {
|
|
2157
|
+
files.push(generateEnumFile(enumDef, true));
|
|
2158
|
+
}
|
|
1708
2159
|
}
|
|
1709
2160
|
const typeAliases = extractInlineEnums(schemas, opts);
|
|
1710
2161
|
for (const alias of typeAliases) {
|
|
@@ -1725,7 +2176,9 @@ function generateTypeScript(schemas, options = {}) {
|
|
|
1725
2176
|
files.push(...rulesFiles);
|
|
1726
2177
|
}
|
|
1727
2178
|
files.push(generateCommonFile(opts));
|
|
1728
|
-
files.push(
|
|
2179
|
+
files.push(generateI18nFile(opts));
|
|
2180
|
+
const pluginEnumsList = opts.pluginEnums ? generatePluginEnums(opts.pluginEnums, opts) : [];
|
|
2181
|
+
files.push(generateIndexFile(schemas, enums, pluginEnumsList, typeAliases, opts));
|
|
1729
2182
|
return files;
|
|
1730
2183
|
}
|
|
1731
2184
|
|
|
@@ -1742,6 +2195,8 @@ export {
|
|
|
1742
2195
|
toEnumName,
|
|
1743
2196
|
schemaToEnum,
|
|
1744
2197
|
generateEnums,
|
|
2198
|
+
pluginEnumToTSEnum,
|
|
2199
|
+
generatePluginEnums,
|
|
1745
2200
|
formatEnum,
|
|
1746
2201
|
enumToUnionType,
|
|
1747
2202
|
formatTypeAlias,
|
|
@@ -1754,4 +2209,4 @@ export {
|
|
|
1754
2209
|
generateRulesFiles,
|
|
1755
2210
|
generateTypeScript
|
|
1756
2211
|
};
|
|
1757
|
-
//# sourceMappingURL=chunk-
|
|
2212
|
+
//# sourceMappingURL=chunk-6I4O23X6.js.map
|