@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
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,12 +17,22 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
23
33
|
DEFAULT_VALIDATION_TEMPLATES: () => DEFAULT_VALIDATION_TEMPLATES,
|
|
34
|
+
STUB_FILES: () => STUB_FILES,
|
|
35
|
+
copyStubs: () => copyStubs,
|
|
24
36
|
enumToUnionType: () => enumToUnionType,
|
|
25
37
|
extractInlineEnums: () => extractInlineEnums,
|
|
26
38
|
formatEnum: () => formatEnum,
|
|
@@ -28,18 +40,23 @@ __export(index_exports, {
|
|
|
28
40
|
formatProperty: () => formatProperty,
|
|
29
41
|
formatTypeAlias: () => formatTypeAlias,
|
|
30
42
|
formatValidationMessage: () => formatValidationMessage,
|
|
43
|
+
generateAIGuides: () => generateAIGuides,
|
|
31
44
|
generateEnums: () => generateEnums,
|
|
32
45
|
generateInterfaces: () => generateInterfaces,
|
|
33
46
|
generateModelRules: () => generateModelRules,
|
|
47
|
+
generatePluginEnums: () => generatePluginEnums,
|
|
34
48
|
generateRulesFiles: () => generateRulesFiles,
|
|
35
49
|
generateTypeScript: () => generateTypeScript,
|
|
36
50
|
generateTypeScriptFiles: () => generateTypeScript,
|
|
37
51
|
getPropertyType: () => getPropertyType,
|
|
52
|
+
getStubPaths: () => getStubPaths,
|
|
38
53
|
getValidationMessages: () => getValidationMessages,
|
|
39
54
|
mergeValidationTemplates: () => mergeValidationTemplates,
|
|
55
|
+
pluginEnumToTSEnum: () => pluginEnumToTSEnum,
|
|
40
56
|
propertyToTSProperty: () => propertyToTSProperty,
|
|
41
57
|
schemaToEnum: () => schemaToEnum,
|
|
42
58
|
schemaToInterface: () => schemaToInterface,
|
|
59
|
+
shouldGenerateAIGuides: () => shouldGenerateAIGuides,
|
|
43
60
|
toEnumMemberName: () => toEnumMemberName,
|
|
44
61
|
toEnumName: () => toEnumName,
|
|
45
62
|
toInterfaceName: () => toInterfaceName,
|
|
@@ -130,6 +147,10 @@ function getPropertyType(property, _allSchemas) {
|
|
|
130
147
|
return "unknown";
|
|
131
148
|
}
|
|
132
149
|
}
|
|
150
|
+
if (property.type === "EnumRef") {
|
|
151
|
+
const enumRefProp = property;
|
|
152
|
+
return enumRefProp.enum;
|
|
153
|
+
}
|
|
133
154
|
if (property.type === "Enum") {
|
|
134
155
|
const enumProp = property;
|
|
135
156
|
if (typeof enumProp.enum === "string") {
|
|
@@ -158,7 +179,7 @@ function propertyToTSProperties(propertyName, property, allSchemas, options = {}
|
|
|
158
179
|
for (const field of customType.expand) {
|
|
159
180
|
const fieldName = `${propertyName}_${toSnakeCase(field.suffix)}`;
|
|
160
181
|
const fieldOverride = baseProp.fields?.[field.suffix];
|
|
161
|
-
const isNullable = fieldOverride?.nullable ?? baseProp.nullable ?? false;
|
|
182
|
+
const isNullable = fieldOverride?.nullable ?? field.sql?.nullable ?? baseProp.nullable ?? false;
|
|
162
183
|
const tsType = field.typescript?.type ?? "string";
|
|
163
184
|
expandedProps.push({
|
|
164
185
|
name: fieldName,
|
|
@@ -303,12 +324,24 @@ function schemaToInterface(schema, allSchemas, options = {}) {
|
|
|
303
324
|
}
|
|
304
325
|
}
|
|
305
326
|
}
|
|
327
|
+
const enumDependencySet = /* @__PURE__ */ new Set();
|
|
328
|
+
if (schema.properties) {
|
|
329
|
+
for (const property of Object.values(schema.properties)) {
|
|
330
|
+
if (property.type === "EnumRef") {
|
|
331
|
+
const enumRefProp = property;
|
|
332
|
+
if (enumRefProp.enum) {
|
|
333
|
+
enumDependencySet.add(enumRefProp.enum);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
306
338
|
const schemaDisplayName = resolveDisplayName(schema.displayName, options);
|
|
307
339
|
return {
|
|
308
340
|
name: toInterfaceName(schema.name),
|
|
309
341
|
properties,
|
|
310
342
|
comment: schemaDisplayName ?? schema.name,
|
|
311
|
-
dependencies: dependencySet.size > 0 ? Array.from(dependencySet).sort() : void 0
|
|
343
|
+
dependencies: dependencySet.size > 0 ? Array.from(dependencySet).sort() : void 0,
|
|
344
|
+
enumDependencies: enumDependencySet.size > 0 ? Array.from(enumDependencySet).sort() : void 0
|
|
312
345
|
};
|
|
313
346
|
}
|
|
314
347
|
function formatProperty(property) {
|
|
@@ -355,7 +388,11 @@ function resolveDisplayName2(value, options = {}) {
|
|
|
355
388
|
});
|
|
356
389
|
}
|
|
357
390
|
function toEnumMemberName(value) {
|
|
358
|
-
|
|
391
|
+
let result = value.split(/[-_\s]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
392
|
+
if (/^\d/.test(result)) {
|
|
393
|
+
result = "_" + result;
|
|
394
|
+
}
|
|
395
|
+
return result;
|
|
359
396
|
}
|
|
360
397
|
function toEnumName(schemaName) {
|
|
361
398
|
return schemaName;
|
|
@@ -409,6 +446,46 @@ function generateEnums(schemas, options = {}) {
|
|
|
409
446
|
}
|
|
410
447
|
return enums;
|
|
411
448
|
}
|
|
449
|
+
function pluginEnumToTSEnum(enumDef, options = {}) {
|
|
450
|
+
const values = enumDef.values.map((v) => {
|
|
451
|
+
let label;
|
|
452
|
+
if (v.label !== void 0) {
|
|
453
|
+
if (typeof v.label === "string") {
|
|
454
|
+
label = v.label;
|
|
455
|
+
} else if (options.multiLocale) {
|
|
456
|
+
label = v.label;
|
|
457
|
+
} else {
|
|
458
|
+
label = resolveDisplayName2(v.label, options);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
name: toEnumMemberName(v.value),
|
|
463
|
+
value: v.value,
|
|
464
|
+
label,
|
|
465
|
+
extra: v.extra
|
|
466
|
+
};
|
|
467
|
+
});
|
|
468
|
+
let comment;
|
|
469
|
+
if (enumDef.displayName !== void 0) {
|
|
470
|
+
if (typeof enumDef.displayName === "string") {
|
|
471
|
+
comment = enumDef.displayName;
|
|
472
|
+
} else {
|
|
473
|
+
comment = resolveDisplayName2(enumDef.displayName, options);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
name: enumDef.name,
|
|
478
|
+
values,
|
|
479
|
+
comment: comment ?? enumDef.name
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
function generatePluginEnums(pluginEnums, options = {}) {
|
|
483
|
+
const enums = [];
|
|
484
|
+
for (const enumDef of pluginEnums.values()) {
|
|
485
|
+
enums.push(pluginEnumToTSEnum(enumDef, options));
|
|
486
|
+
}
|
|
487
|
+
return enums;
|
|
488
|
+
}
|
|
412
489
|
function isMultiLocaleLabel(label) {
|
|
413
490
|
return label !== void 0 && typeof label === "object";
|
|
414
491
|
}
|
|
@@ -429,7 +506,7 @@ ${enumValues}
|
|
|
429
506
|
`);
|
|
430
507
|
parts.push(`/** All ${name} values */
|
|
431
508
|
`);
|
|
432
|
-
parts.push(`export const ${name}Values = Object.values(${name});
|
|
509
|
+
parts.push(`export const ${name}Values = Object.values(${name}) as ${name}[];
|
|
433
510
|
|
|
434
511
|
`);
|
|
435
512
|
parts.push(`/** Type guard for ${name} */
|
|
@@ -447,10 +524,10 @@ ${enumValues}
|
|
|
447
524
|
if (hasMultiLocale) {
|
|
448
525
|
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => {
|
|
449
526
|
if (isMultiLocaleLabel(v.label)) {
|
|
450
|
-
const locales = Object.entries(v.label).map(([locale, text]) =>
|
|
527
|
+
const locales = Object.entries(v.label).map(([locale, text]) => `'${locale}': '${escapeString(text)}'`).join(", ");
|
|
451
528
|
return ` [${name}.${v.name}]: { ${locales} },`;
|
|
452
529
|
}
|
|
453
|
-
return ` [${name}.${v.name}]: { default: '${v.label}' },`;
|
|
530
|
+
return ` [${name}.${v.name}]: { default: '${escapeString(String(v.label))}' },`;
|
|
454
531
|
}).join("\n");
|
|
455
532
|
parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, Record<string, string>>> = {
|
|
456
533
|
${labelEntries}
|
|
@@ -467,13 +544,15 @@ ${labelEntries}
|
|
|
467
544
|
`);
|
|
468
545
|
parts.push(` if (locale && labels[locale]) return labels[locale];
|
|
469
546
|
`);
|
|
470
|
-
parts.push(`
|
|
547
|
+
parts.push(` // Fallback: ja \u2192 en \u2192 first available
|
|
548
|
+
`);
|
|
549
|
+
parts.push(` return labels['ja'] ?? labels['en'] ?? Object.values(labels)[0] ?? value;
|
|
471
550
|
`);
|
|
472
551
|
parts.push(`}
|
|
473
552
|
|
|
474
553
|
`);
|
|
475
554
|
} else {
|
|
476
|
-
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${v.label}',`).join("\n");
|
|
555
|
+
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${escapeString(String(v.label))}',`).join("\n");
|
|
477
556
|
parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, string>> = {
|
|
478
557
|
${labelEntries}
|
|
479
558
|
};
|
|
@@ -529,6 +608,9 @@ ${extraEntries}
|
|
|
529
608
|
function lowerFirst(str) {
|
|
530
609
|
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
531
610
|
}
|
|
611
|
+
function escapeString(str) {
|
|
612
|
+
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
613
|
+
}
|
|
532
614
|
function enumToUnionType(enumDef) {
|
|
533
615
|
const type = enumDef.values.map((v) => `'${v.value}'`).join(" | ");
|
|
534
616
|
return {
|
|
@@ -1050,6 +1132,13 @@ function getZodSchemaForType(propDef, fieldName, customTypes) {
|
|
|
1050
1132
|
case "Json":
|
|
1051
1133
|
schema = "z.unknown()";
|
|
1052
1134
|
break;
|
|
1135
|
+
case "EnumRef":
|
|
1136
|
+
if (typeof def.enum === "string") {
|
|
1137
|
+
schema = `z.nativeEnum(${def.enum})`;
|
|
1138
|
+
} else {
|
|
1139
|
+
schema = "z.string()";
|
|
1140
|
+
}
|
|
1141
|
+
break;
|
|
1053
1142
|
case "Enum":
|
|
1054
1143
|
if (typeof def.enum === "string") {
|
|
1055
1144
|
schema = `${def.enum}Schema`;
|
|
@@ -1095,15 +1184,35 @@ function generateCompoundTypeSchemas(propName, propDef, customType, options) {
|
|
|
1095
1184
|
for (const field of customType.expand) {
|
|
1096
1185
|
const fieldName = `${toSnakeCase(propName)}_${toSnakeCase(field.suffix)}`;
|
|
1097
1186
|
const fieldOverride = propFields?.[field.suffix];
|
|
1098
|
-
const isNullable = fieldOverride?.nullable ?? propDef.nullable ?? false;
|
|
1099
|
-
const
|
|
1187
|
+
const isNullable = fieldOverride?.nullable ?? field.sql?.nullable ?? propDef.nullable ?? false;
|
|
1188
|
+
const pluginRules = field.rules;
|
|
1189
|
+
const overrideRules = fieldOverride?.rules;
|
|
1190
|
+
const length = fieldOverride?.length ?? overrideRules?.maxLength ?? pluginRules?.maxLength ?? field.sql?.length;
|
|
1191
|
+
const minLength = overrideRules?.minLength ?? pluginRules?.minLength;
|
|
1192
|
+
const pattern = overrideRules?.pattern ?? pluginRules?.pattern;
|
|
1193
|
+
const format = overrideRules?.format ?? pluginRules?.format;
|
|
1100
1194
|
let schema = "z.string()";
|
|
1195
|
+
if (format === "email") {
|
|
1196
|
+
schema = "z.string().email()";
|
|
1197
|
+
} else if (format === "url") {
|
|
1198
|
+
schema = "z.string().url()";
|
|
1199
|
+
} else if (format === "phone") {
|
|
1200
|
+
schema = "z.string()";
|
|
1201
|
+
} else if (format === "postal_code") {
|
|
1202
|
+
schema = `z.string().regex(/^\\d{3}-?\\d{4}$/)`;
|
|
1203
|
+
}
|
|
1101
1204
|
if (!isNullable) {
|
|
1102
|
-
|
|
1205
|
+
const min = minLength ?? 1;
|
|
1206
|
+
schema += `.min(${min})`;
|
|
1207
|
+
} else if (minLength) {
|
|
1208
|
+
schema += `.min(${minLength})`;
|
|
1103
1209
|
}
|
|
1104
1210
|
if (length) {
|
|
1105
1211
|
schema += `.max(${length})`;
|
|
1106
1212
|
}
|
|
1213
|
+
if (pattern && !format) {
|
|
1214
|
+
schema += `.regex(/${pattern}/)`;
|
|
1215
|
+
}
|
|
1107
1216
|
if (isNullable) {
|
|
1108
1217
|
schema += ".optional().nullable()";
|
|
1109
1218
|
}
|
|
@@ -1159,6 +1268,7 @@ function generateDisplayNames(schema, options) {
|
|
|
1159
1268
|
schema.name
|
|
1160
1269
|
);
|
|
1161
1270
|
const propertyDisplayNames = {};
|
|
1271
|
+
const propertyPlaceholders = {};
|
|
1162
1272
|
if (schema.properties) {
|
|
1163
1273
|
for (const [propName, propDef] of Object.entries(schema.properties)) {
|
|
1164
1274
|
const prop = propDef;
|
|
@@ -1166,19 +1276,47 @@ function generateDisplayNames(schema, options) {
|
|
|
1166
1276
|
if (customTypes) {
|
|
1167
1277
|
const customType = customTypes.get(propDef.type);
|
|
1168
1278
|
if (customType?.compound && customType.expand) {
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
propertyDisplayNames[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1279
|
+
if (prop.displayName) {
|
|
1280
|
+
propertyDisplayNames[fieldName] = getMultiLocaleDisplayName2(
|
|
1172
1281
|
prop.displayName,
|
|
1173
1282
|
locales,
|
|
1174
1283
|
fallbackLocale,
|
|
1175
1284
|
propName
|
|
1176
1285
|
);
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1286
|
+
}
|
|
1287
|
+
for (const field of customType.expand) {
|
|
1288
|
+
const expandedFieldName = `${fieldName}_${toSnakeCase(field.suffix)}`;
|
|
1289
|
+
const fieldOverride = prop.fields?.[field.suffix];
|
|
1290
|
+
const labelSource = fieldOverride?.displayName ?? field.label;
|
|
1291
|
+
if (labelSource) {
|
|
1292
|
+
propertyDisplayNames[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1293
|
+
labelSource,
|
|
1294
|
+
locales,
|
|
1295
|
+
fallbackLocale,
|
|
1296
|
+
field.suffix
|
|
1297
|
+
);
|
|
1298
|
+
} else {
|
|
1299
|
+
propertyDisplayNames[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1300
|
+
prop.displayName,
|
|
1301
|
+
locales,
|
|
1302
|
+
fallbackLocale,
|
|
1303
|
+
propName
|
|
1304
|
+
);
|
|
1305
|
+
for (const locale of locales) {
|
|
1306
|
+
propertyDisplayNames[expandedFieldName] = {
|
|
1307
|
+
...propertyDisplayNames[expandedFieldName],
|
|
1308
|
+
[locale]: `${propertyDisplayNames[expandedFieldName][locale]} (${field.suffix})`
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
const placeholderSource = fieldOverride?.placeholder ?? field.placeholder;
|
|
1313
|
+
if (placeholderSource) {
|
|
1314
|
+
propertyPlaceholders[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1315
|
+
placeholderSource,
|
|
1316
|
+
locales,
|
|
1317
|
+
fallbackLocale,
|
|
1318
|
+
""
|
|
1319
|
+
);
|
|
1182
1320
|
}
|
|
1183
1321
|
}
|
|
1184
1322
|
continue;
|
|
@@ -1190,9 +1328,17 @@ function generateDisplayNames(schema, options) {
|
|
|
1190
1328
|
fallbackLocale,
|
|
1191
1329
|
propName
|
|
1192
1330
|
);
|
|
1331
|
+
if (prop.placeholder) {
|
|
1332
|
+
propertyPlaceholders[fieldName] = getMultiLocaleDisplayName2(
|
|
1333
|
+
prop.placeholder,
|
|
1334
|
+
locales,
|
|
1335
|
+
fallbackLocale,
|
|
1336
|
+
""
|
|
1337
|
+
);
|
|
1338
|
+
}
|
|
1193
1339
|
}
|
|
1194
1340
|
}
|
|
1195
|
-
return { displayName, propertyDisplayNames };
|
|
1341
|
+
return { displayName, propertyDisplayNames, propertyPlaceholders };
|
|
1196
1342
|
}
|
|
1197
1343
|
function getExcludedFields(schema, customTypes) {
|
|
1198
1344
|
const createExclude = /* @__PURE__ */ new Set();
|
|
@@ -1236,24 +1382,44 @@ function formatZodSchemasSection(schemaName, zodSchemas, displayNames, excludedF
|
|
|
1236
1382
|
const lowerName = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
|
|
1237
1383
|
parts.push(`// ============================================================================
|
|
1238
1384
|
`);
|
|
1239
|
-
parts.push(`//
|
|
1385
|
+
parts.push(`// I18n (Internationalization)
|
|
1240
1386
|
`);
|
|
1241
1387
|
parts.push(`// ============================================================================
|
|
1242
1388
|
|
|
1243
1389
|
`);
|
|
1244
|
-
parts.push(`/**
|
|
1390
|
+
parts.push(`/**
|
|
1245
1391
|
`);
|
|
1246
|
-
parts.push(`
|
|
1247
|
-
|
|
1392
|
+
parts.push(` * Unified i18n object for ${schemaName}
|
|
1248
1393
|
`);
|
|
1249
|
-
parts.push(
|
|
1394
|
+
parts.push(` * Contains model label and all field labels/placeholders
|
|
1395
|
+
`);
|
|
1396
|
+
parts.push(` */
|
|
1397
|
+
`);
|
|
1398
|
+
parts.push(`export const ${lowerName}I18n = {
|
|
1399
|
+
`);
|
|
1400
|
+
parts.push(` /** Model display name */
|
|
1401
|
+
`);
|
|
1402
|
+
parts.push(` label: ${JSON.stringify(displayNames.displayName)},
|
|
1403
|
+
`);
|
|
1404
|
+
parts.push(` /** Field labels and placeholders */
|
|
1250
1405
|
`);
|
|
1251
|
-
parts.push(`
|
|
1406
|
+
parts.push(` fields: {
|
|
1252
1407
|
`);
|
|
1253
|
-
for (const [propName,
|
|
1254
|
-
|
|
1408
|
+
for (const [propName, labelMap] of Object.entries(displayNames.propertyDisplayNames)) {
|
|
1409
|
+
const placeholderMap = displayNames.propertyPlaceholders[propName];
|
|
1410
|
+
parts.push(` ${propName}: {
|
|
1411
|
+
`);
|
|
1412
|
+
parts.push(` label: ${JSON.stringify(labelMap)},
|
|
1413
|
+
`);
|
|
1414
|
+
if (placeholderMap) {
|
|
1415
|
+
parts.push(` placeholder: ${JSON.stringify(placeholderMap)},
|
|
1416
|
+
`);
|
|
1417
|
+
}
|
|
1418
|
+
parts.push(` },
|
|
1255
1419
|
`);
|
|
1256
1420
|
}
|
|
1421
|
+
parts.push(` },
|
|
1422
|
+
`);
|
|
1257
1423
|
parts.push(`} as const;
|
|
1258
1424
|
|
|
1259
1425
|
`);
|
|
@@ -1310,35 +1476,50 @@ function formatZodSchemasSection(schemaName, zodSchemas, displayNames, excludedF
|
|
|
1310
1476
|
`);
|
|
1311
1477
|
parts.push(`// ============================================================================
|
|
1312
1478
|
`);
|
|
1313
|
-
parts.push(`// Helper Functions
|
|
1479
|
+
parts.push(`// I18n Helper Functions
|
|
1314
1480
|
`);
|
|
1315
1481
|
parts.push(`// ============================================================================
|
|
1316
1482
|
|
|
1317
1483
|
`);
|
|
1318
|
-
parts.push(`/** Get
|
|
1484
|
+
parts.push(`/** Get model label for a specific locale */
|
|
1319
1485
|
`);
|
|
1320
|
-
parts.push(`export function get${schemaName}
|
|
1486
|
+
parts.push(`export function get${schemaName}Label(locale: string): string {
|
|
1321
1487
|
`);
|
|
1322
|
-
parts.push(` return ${
|
|
1488
|
+
parts.push(` return ${lowerName}I18n.label[locale as keyof typeof ${lowerName}I18n.label] ?? ${lowerName}I18n.label['en'] ?? '${schemaName}';
|
|
1323
1489
|
`);
|
|
1324
1490
|
parts.push(`}
|
|
1325
1491
|
|
|
1326
1492
|
`);
|
|
1327
|
-
parts.push(`/** Get
|
|
1493
|
+
parts.push(`/** Get field label for a specific locale */
|
|
1328
1494
|
`);
|
|
1329
|
-
parts.push(`export function get${schemaName}
|
|
1495
|
+
parts.push(`export function get${schemaName}FieldLabel(field: string, locale: string): string {
|
|
1330
1496
|
`);
|
|
1331
|
-
parts.push(` const
|
|
1497
|
+
parts.push(` const fieldI18n = ${lowerName}I18n.fields[field as keyof typeof ${lowerName}I18n.fields];
|
|
1332
1498
|
`);
|
|
1333
|
-
parts.push(` if (!
|
|
1499
|
+
parts.push(` if (!fieldI18n) return field;
|
|
1334
1500
|
`);
|
|
1335
|
-
parts.push(` return
|
|
1501
|
+
parts.push(` return fieldI18n.label[locale as keyof typeof fieldI18n.label] ?? fieldI18n.label['en'] ?? field;
|
|
1502
|
+
`);
|
|
1503
|
+
parts.push(`}
|
|
1504
|
+
|
|
1505
|
+
`);
|
|
1506
|
+
parts.push(`/** Get field placeholder for a specific locale */
|
|
1507
|
+
`);
|
|
1508
|
+
parts.push(`export function get${schemaName}FieldPlaceholder(field: string, locale: string): string {
|
|
1509
|
+
`);
|
|
1510
|
+
parts.push(` const fieldI18n = ${lowerName}I18n.fields[field as keyof typeof ${lowerName}I18n.fields];
|
|
1511
|
+
`);
|
|
1512
|
+
parts.push(` if (!fieldI18n || !('placeholder' in fieldI18n)) return '';
|
|
1513
|
+
`);
|
|
1514
|
+
parts.push(` const placeholder = fieldI18n.placeholder as Record<string, string>;
|
|
1515
|
+
`);
|
|
1516
|
+
parts.push(` return placeholder[locale] ?? placeholder['en'] ?? '';
|
|
1336
1517
|
`);
|
|
1337
1518
|
parts.push(`}
|
|
1338
1519
|
`);
|
|
1339
1520
|
return parts.join("");
|
|
1340
1521
|
}
|
|
1341
|
-
function formatZodModelFile(schemaName) {
|
|
1522
|
+
function formatZodModelFile(schemaName, _hasPlaceholders = false) {
|
|
1342
1523
|
const lowerName = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
|
|
1343
1524
|
return `/**
|
|
1344
1525
|
* ${schemaName} Model
|
|
@@ -1354,10 +1535,10 @@ import {
|
|
|
1354
1535
|
base${schemaName}Schemas,
|
|
1355
1536
|
base${schemaName}CreateSchema,
|
|
1356
1537
|
base${schemaName}UpdateSchema,
|
|
1357
|
-
${
|
|
1358
|
-
${schemaName}
|
|
1359
|
-
get${schemaName}
|
|
1360
|
-
get${schemaName}
|
|
1538
|
+
${lowerName}I18n,
|
|
1539
|
+
get${schemaName}Label,
|
|
1540
|
+
get${schemaName}FieldLabel,
|
|
1541
|
+
get${schemaName}FieldPlaceholder,
|
|
1361
1542
|
} from './base/${schemaName}.js';
|
|
1362
1543
|
|
|
1363
1544
|
// ============================================================================
|
|
@@ -1383,12 +1564,12 @@ export const ${lowerName}UpdateSchema = base${schemaName}UpdateSchema;
|
|
|
1383
1564
|
export type ${schemaName}Create = z.infer<typeof ${lowerName}CreateSchema>;
|
|
1384
1565
|
export type ${schemaName}Update = z.infer<typeof ${lowerName}UpdateSchema>;
|
|
1385
1566
|
|
|
1386
|
-
// Re-export
|
|
1567
|
+
// Re-export i18n and helpers
|
|
1387
1568
|
export {
|
|
1388
|
-
${
|
|
1389
|
-
${schemaName}
|
|
1390
|
-
get${schemaName}
|
|
1391
|
-
get${schemaName}
|
|
1569
|
+
${lowerName}I18n,
|
|
1570
|
+
get${schemaName}Label,
|
|
1571
|
+
get${schemaName}FieldLabel,
|
|
1572
|
+
get${schemaName}FieldPlaceholder,
|
|
1392
1573
|
};
|
|
1393
1574
|
|
|
1394
1575
|
// Re-export base type for internal use
|
|
@@ -1504,13 +1685,24 @@ function generateBaseInterfaceFile(schemaName, schemas, options) {
|
|
|
1504
1685
|
parts.push(`import type { ${commonImports.join(", ")} } from '../common.js';
|
|
1505
1686
|
`);
|
|
1506
1687
|
}
|
|
1688
|
+
if (iface.enumDependencies && iface.enumDependencies.length > 0) {
|
|
1689
|
+
const enumPrefix = options.enumImportPrefix ? `../${options.enumImportPrefix}` : "../enum";
|
|
1690
|
+
const pluginEnumNames = new Set(
|
|
1691
|
+
options.pluginEnums ? Array.from(options.pluginEnums.keys()) : []
|
|
1692
|
+
);
|
|
1693
|
+
for (const enumName of iface.enumDependencies) {
|
|
1694
|
+
const enumPath = pluginEnumNames.has(enumName) ? `${enumPrefix}/plugin/${enumName}.js` : `${enumPrefix}/${enumName}.js`;
|
|
1695
|
+
parts.push(`import { ${enumName} } from '${enumPath}';
|
|
1696
|
+
`);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1507
1699
|
if (iface.dependencies && iface.dependencies.length > 0) {
|
|
1508
1700
|
for (const dep of iface.dependencies) {
|
|
1509
1701
|
parts.push(`import type { ${dep} } from './${dep}.js';
|
|
1510
1702
|
`);
|
|
1511
1703
|
}
|
|
1512
1704
|
parts.push("\n");
|
|
1513
|
-
} else if (commonImports.length > 0 || options.generateZodSchemas) {
|
|
1705
|
+
} else if (commonImports.length > 0 || options.generateZodSchemas || iface.enumDependencies && iface.enumDependencies.length > 0) {
|
|
1514
1706
|
parts.push("\n");
|
|
1515
1707
|
}
|
|
1516
1708
|
parts.push(formatInterface(iface));
|
|
@@ -1531,15 +1723,17 @@ function generateBaseInterfaceFile(schemaName, schemas, options) {
|
|
|
1531
1723
|
overwrite: true
|
|
1532
1724
|
};
|
|
1533
1725
|
}
|
|
1534
|
-
function generateEnumFile(enumDef) {
|
|
1726
|
+
function generateEnumFile(enumDef, isPluginEnum = false) {
|
|
1535
1727
|
const parts = [generateBaseHeader()];
|
|
1536
1728
|
parts.push(formatEnum(enumDef));
|
|
1537
1729
|
parts.push("\n");
|
|
1730
|
+
const filePath = isPluginEnum ? `plugin/${enumDef.name}.ts` : `${enumDef.name}.ts`;
|
|
1538
1731
|
return {
|
|
1539
|
-
filePath
|
|
1732
|
+
filePath,
|
|
1540
1733
|
content: parts.join(""),
|
|
1541
1734
|
types: [enumDef.name],
|
|
1542
|
-
overwrite: true
|
|
1735
|
+
overwrite: true,
|
|
1736
|
+
category: "enum"
|
|
1543
1737
|
};
|
|
1544
1738
|
}
|
|
1545
1739
|
function generateTypeAliasFile(alias) {
|
|
@@ -1547,10 +1741,11 @@ function generateTypeAliasFile(alias) {
|
|
|
1547
1741
|
parts.push(formatTypeAlias(alias));
|
|
1548
1742
|
parts.push("\n");
|
|
1549
1743
|
return {
|
|
1550
|
-
filePath:
|
|
1744
|
+
filePath: `${alias.name}.ts`,
|
|
1551
1745
|
content: parts.join(""),
|
|
1552
1746
|
types: [alias.name],
|
|
1553
|
-
overwrite: true
|
|
1747
|
+
overwrite: true,
|
|
1748
|
+
category: "enum"
|
|
1554
1749
|
};
|
|
1555
1750
|
}
|
|
1556
1751
|
function generateModelFile(schemaName, options) {
|
|
@@ -1591,6 +1786,88 @@ function generateModelFile(schemaName, options) {
|
|
|
1591
1786
|
// Never overwrite user models
|
|
1592
1787
|
};
|
|
1593
1788
|
}
|
|
1789
|
+
var DEFAULT_VALIDATION_MESSAGES = {
|
|
1790
|
+
required: {
|
|
1791
|
+
en: "${displayName} is required",
|
|
1792
|
+
ja: "${displayName}\u306F\u5FC5\u9808\u3067\u3059",
|
|
1793
|
+
vi: "${displayName} l\xE0 b\u1EAFt bu\u1ED9c",
|
|
1794
|
+
ko: "${displayName}\uC740(\uB294) \uD544\uC218\uC785\uB2C8\uB2E4",
|
|
1795
|
+
"zh-CN": "${displayName}\u662F\u5FC5\u586B\u9879",
|
|
1796
|
+
"zh-TW": "${displayName}\u70BA\u5FC5\u586B\u6B04\u4F4D",
|
|
1797
|
+
th: "${displayName} \u0E08\u0E33\u0E40\u0E1B\u0E47\u0E19\u0E15\u0E49\u0E2D\u0E07\u0E01\u0E23\u0E2D\u0E01",
|
|
1798
|
+
es: "${displayName} es obligatorio"
|
|
1799
|
+
},
|
|
1800
|
+
minLength: {
|
|
1801
|
+
en: "${displayName} must be at least ${min} characters",
|
|
1802
|
+
ja: "${displayName}\u306F${min}\u6587\u5B57\u4EE5\u4E0A\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1803
|
+
vi: "${displayName} ph\u1EA3i c\xF3 \xEDt nh\u1EA5t ${min} k\xFD t\u1EF1",
|
|
1804
|
+
ko: "${displayName}\uC740(\uB294) ${min}\uC790 \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
|
|
1805
|
+
"zh-CN": "${displayName}\u81F3\u5C11\u9700\u8981${min}\u4E2A\u5B57\u7B26",
|
|
1806
|
+
"zh-TW": "${displayName}\u81F3\u5C11\u9700\u8981${min}\u500B\u5B57\u5143",
|
|
1807
|
+
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",
|
|
1808
|
+
es: "${displayName} debe tener al menos ${min} caracteres"
|
|
1809
|
+
},
|
|
1810
|
+
maxLength: {
|
|
1811
|
+
en: "${displayName} must be at most ${max} characters",
|
|
1812
|
+
ja: "${displayName}\u306F${max}\u6587\u5B57\u4EE5\u5185\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1813
|
+
vi: "${displayName} kh\xF4ng \u0111\u01B0\u1EE3c qu\xE1 ${max} k\xFD t\u1EF1",
|
|
1814
|
+
ko: "${displayName}\uC740(\uB294) ${max}\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
|
|
1815
|
+
"zh-CN": "${displayName}\u6700\u591A${max}\u4E2A\u5B57\u7B26",
|
|
1816
|
+
"zh-TW": "${displayName}\u6700\u591A${max}\u500B\u5B57\u5143",
|
|
1817
|
+
th: "${displayName} \u0E15\u0E49\u0E2D\u0E07\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 ${max} \u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23",
|
|
1818
|
+
es: "${displayName} debe tener como m\xE1ximo ${max} caracteres"
|
|
1819
|
+
},
|
|
1820
|
+
min: {
|
|
1821
|
+
en: "${displayName} must be at least ${min}",
|
|
1822
|
+
ja: "${displayName}\u306F${min}\u4EE5\u4E0A\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1823
|
+
vi: "${displayName} ph\u1EA3i l\u1EDBn h\u01A1n ho\u1EB7c b\u1EB1ng ${min}",
|
|
1824
|
+
ko: "${displayName}\uC740(\uB294) ${min} \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4",
|
|
1825
|
+
"zh-CN": "${displayName}\u5FC5\u987B\u5927\u4E8E\u7B49\u4E8E${min}",
|
|
1826
|
+
"zh-TW": "${displayName}\u5FC5\u9808\u5927\u65BC\u7B49\u65BC${min}",
|
|
1827
|
+
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}",
|
|
1828
|
+
es: "${displayName} debe ser al menos ${min}"
|
|
1829
|
+
},
|
|
1830
|
+
max: {
|
|
1831
|
+
en: "${displayName} must be at most ${max}",
|
|
1832
|
+
ja: "${displayName}\u306F${max}\u4EE5\u4E0B\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1833
|
+
vi: "${displayName} ph\u1EA3i nh\u1ECF h\u01A1n ho\u1EB7c b\u1EB1ng ${max}",
|
|
1834
|
+
ko: "${displayName}\uC740(\uB294) ${max} \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4",
|
|
1835
|
+
"zh-CN": "${displayName}\u5FC5\u987B\u5C0F\u4E8E\u7B49\u4E8E${max}",
|
|
1836
|
+
"zh-TW": "${displayName}\u5FC5\u9808\u5C0F\u65BC\u7B49\u65BC${max}",
|
|
1837
|
+
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}",
|
|
1838
|
+
es: "${displayName} debe ser como m\xE1ximo ${max}"
|
|
1839
|
+
},
|
|
1840
|
+
email: {
|
|
1841
|
+
en: "Please enter a valid email address",
|
|
1842
|
+
ja: "\u6709\u52B9\u306A\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1843
|
+
vi: "Vui l\xF2ng nh\u1EADp \u0111\u1ECBa ch\u1EC9 email h\u1EE3p l\u1EC7",
|
|
1844
|
+
ko: "\uC720\uD6A8\uD55C \uC774\uBA54\uC77C \uC8FC\uC18C\uB97C \uC785\uB825\uD558\uC138\uC694",
|
|
1845
|
+
"zh-CN": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7535\u5B50\u90AE\u4EF6\u5730\u5740",
|
|
1846
|
+
"zh-TW": "\u8ACB\u8F38\u5165\u6709\u6548\u7684\u96FB\u5B50\u90F5\u4EF6\u5730\u5740",
|
|
1847
|
+
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",
|
|
1848
|
+
es: "Por favor, introduce una direcci\xF3n de correo electr\xF3nico v\xE1lida"
|
|
1849
|
+
},
|
|
1850
|
+
url: {
|
|
1851
|
+
en: "Please enter a valid URL",
|
|
1852
|
+
ja: "\u6709\u52B9\u306AURL\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
1853
|
+
vi: "Vui l\xF2ng nh\u1EADp URL h\u1EE3p l\u1EC7",
|
|
1854
|
+
ko: "\uC720\uD6A8\uD55C URL\uC744 \uC785\uB825\uD558\uC138\uC694",
|
|
1855
|
+
"zh-CN": "\u8BF7\u8F93\u5165\u6709\u6548\u7684URL",
|
|
1856
|
+
"zh-TW": "\u8ACB\u8F38\u5165\u6709\u6548\u7684\u7DB2\u5740",
|
|
1857
|
+
th: "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E01\u0E23\u0E2D\u0E01 URL \u0E17\u0E35\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07",
|
|
1858
|
+
es: "Por favor, introduce una URL v\xE1lida"
|
|
1859
|
+
},
|
|
1860
|
+
pattern: {
|
|
1861
|
+
en: "${displayName} format is invalid",
|
|
1862
|
+
ja: "${displayName}\u306E\u5F62\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093",
|
|
1863
|
+
vi: "${displayName} kh\xF4ng \u0111\xFAng \u0111\u1ECBnh d\u1EA1ng",
|
|
1864
|
+
ko: "${displayName} \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
|
|
1865
|
+
"zh-CN": "${displayName}\u683C\u5F0F\u4E0D\u6B63\u786E",
|
|
1866
|
+
"zh-TW": "${displayName}\u683C\u5F0F\u4E0D\u6B63\u78BA",
|
|
1867
|
+
th: "\u0E23\u0E39\u0E1B\u0E41\u0E1A\u0E1A${displayName}\u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07",
|
|
1868
|
+
es: "El formato de ${displayName} no es v\xE1lido"
|
|
1869
|
+
}
|
|
1870
|
+
};
|
|
1594
1871
|
function generateCommonFile(options) {
|
|
1595
1872
|
const locales = options.localeConfig?.locales ?? ["ja", "en"];
|
|
1596
1873
|
const localeUnion = locales.map((l) => `'${l}'`).join(" | ");
|
|
@@ -1638,15 +1915,142 @@ export type DateString = string;
|
|
|
1638
1915
|
overwrite: true
|
|
1639
1916
|
};
|
|
1640
1917
|
}
|
|
1641
|
-
function
|
|
1918
|
+
function generateI18nFile(options) {
|
|
1919
|
+
const locales = options.localeConfig?.locales ?? ["ja", "en"];
|
|
1920
|
+
const defaultLocale = options.localeConfig?.defaultLocale ?? "ja";
|
|
1921
|
+
const fallbackLocale = options.localeConfig?.fallbackLocale ?? "en";
|
|
1922
|
+
const userMessages = options.localeConfig?.messages ?? {};
|
|
1923
|
+
const mergedMessages = {};
|
|
1924
|
+
for (const [key, defaultMsgs] of Object.entries(DEFAULT_VALIDATION_MESSAGES)) {
|
|
1925
|
+
mergedMessages[key] = {};
|
|
1926
|
+
for (const locale of locales) {
|
|
1927
|
+
if (defaultMsgs[locale]) {
|
|
1928
|
+
mergedMessages[key][locale] = defaultMsgs[locale];
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
for (const [key, userMsgs] of Object.entries(userMessages)) {
|
|
1933
|
+
if (userMsgs) {
|
|
1934
|
+
if (!mergedMessages[key]) {
|
|
1935
|
+
mergedMessages[key] = {};
|
|
1936
|
+
}
|
|
1937
|
+
for (const [locale, msg] of Object.entries(userMsgs)) {
|
|
1938
|
+
mergedMessages[key][locale] = msg;
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
const messagesJson = JSON.stringify(mergedMessages, null, 2);
|
|
1943
|
+
const content = `${generateBaseHeader()}
|
|
1944
|
+
import type { LocaleMap } from './common.js';
|
|
1945
|
+
|
|
1946
|
+
/**
|
|
1947
|
+
* Default locale for this project.
|
|
1948
|
+
*/
|
|
1949
|
+
export const defaultLocale = '${defaultLocale}' as const;
|
|
1950
|
+
|
|
1951
|
+
/**
|
|
1952
|
+
* Fallback locale when requested locale is not found.
|
|
1953
|
+
*/
|
|
1954
|
+
export const fallbackLocale = '${fallbackLocale}' as const;
|
|
1955
|
+
|
|
1956
|
+
/**
|
|
1957
|
+
* Supported locales in this project.
|
|
1958
|
+
*/
|
|
1959
|
+
export const supportedLocales = ${JSON.stringify(locales)} as const;
|
|
1960
|
+
|
|
1961
|
+
/**
|
|
1962
|
+
* Validation messages for all supported locales.
|
|
1963
|
+
* Use getMessage(key, locale, params) to get formatted message.
|
|
1964
|
+
*/
|
|
1965
|
+
export const validationMessages = ${messagesJson} as const;
|
|
1966
|
+
|
|
1967
|
+
/**
|
|
1968
|
+
* Get validation message for a specific key and locale.
|
|
1969
|
+
* Supports template placeholders: \${displayName}, \${min}, \${max}, etc.
|
|
1970
|
+
*
|
|
1971
|
+
* @param key - Message key (e.g., 'required', 'minLength')
|
|
1972
|
+
* @param locale - Locale code (e.g., 'ja', 'en')
|
|
1973
|
+
* @param params - Template parameters to replace
|
|
1974
|
+
* @returns Formatted message string
|
|
1975
|
+
*
|
|
1976
|
+
* @example
|
|
1977
|
+
* getMessage('required', 'ja', { displayName: '\u6C0F\u540D' })
|
|
1978
|
+
* // => '\u6C0F\u540D\u306F\u5FC5\u9808\u3067\u3059'
|
|
1979
|
+
*/
|
|
1980
|
+
export function getMessage(
|
|
1981
|
+
key: string,
|
|
1982
|
+
locale: string,
|
|
1983
|
+
params: Record<string, string | number> = {}
|
|
1984
|
+
): string {
|
|
1985
|
+
const messages = validationMessages[key as keyof typeof validationMessages];
|
|
1986
|
+
if (!messages) return key;
|
|
1987
|
+
|
|
1988
|
+
let message = (messages as LocaleMap)[locale]
|
|
1989
|
+
?? (messages as LocaleMap)[fallbackLocale]
|
|
1990
|
+
?? (messages as LocaleMap)[defaultLocale]
|
|
1991
|
+
?? key;
|
|
1992
|
+
|
|
1993
|
+
// Replace template placeholders
|
|
1994
|
+
for (const [param, value] of Object.entries(params)) {
|
|
1995
|
+
message = message.replace(new RegExp(\`\\\\$\\{\${param}\\}\`, 'g'), String(value));
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
return message;
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
/**
|
|
2002
|
+
* Get all validation messages for a specific locale.
|
|
2003
|
+
*
|
|
2004
|
+
* @param locale - Locale code
|
|
2005
|
+
* @returns Object with all messages for the locale
|
|
2006
|
+
*/
|
|
2007
|
+
export function getMessages(locale: string): Record<string, string> {
|
|
2008
|
+
const result: Record<string, string> = {};
|
|
2009
|
+
for (const [key, messages] of Object.entries(validationMessages)) {
|
|
2010
|
+
result[key] = (messages as LocaleMap)[locale]
|
|
2011
|
+
?? (messages as LocaleMap)[fallbackLocale]
|
|
2012
|
+
?? (messages as LocaleMap)[defaultLocale]
|
|
2013
|
+
?? key;
|
|
2014
|
+
}
|
|
2015
|
+
return result;
|
|
2016
|
+
}
|
|
2017
|
+
`;
|
|
2018
|
+
return {
|
|
2019
|
+
filePath: "i18n.ts",
|
|
2020
|
+
content,
|
|
2021
|
+
types: ["validationMessages", "getMessage", "getMessages"],
|
|
2022
|
+
overwrite: true
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
function generateIndexFile(schemas, enums, pluginEnums, typeAliases, options) {
|
|
1642
2026
|
const parts = [generateBaseHeader()];
|
|
1643
2027
|
parts.push(`// Common Types
|
|
1644
2028
|
`);
|
|
1645
2029
|
parts.push(`export type { LocaleMap, Locale, ValidationRule, DateTimeString, DateString } from './common.js';
|
|
1646
2030
|
|
|
1647
2031
|
`);
|
|
1648
|
-
|
|
1649
|
-
|
|
2032
|
+
parts.push(`// i18n (Internationalization)
|
|
2033
|
+
`);
|
|
2034
|
+
parts.push(`export {
|
|
2035
|
+
`);
|
|
2036
|
+
parts.push(` defaultLocale,
|
|
2037
|
+
`);
|
|
2038
|
+
parts.push(` fallbackLocale,
|
|
2039
|
+
`);
|
|
2040
|
+
parts.push(` supportedLocales,
|
|
2041
|
+
`);
|
|
2042
|
+
parts.push(` validationMessages,
|
|
2043
|
+
`);
|
|
2044
|
+
parts.push(` getMessage,
|
|
2045
|
+
`);
|
|
2046
|
+
parts.push(` getMessages,
|
|
2047
|
+
`);
|
|
2048
|
+
parts.push(`} from './i18n.js';
|
|
2049
|
+
|
|
2050
|
+
`);
|
|
2051
|
+
const enumPrefix = options.enumImportPrefix ?? "./enum";
|
|
2052
|
+
if (enums.length > 0) {
|
|
2053
|
+
parts.push(`// Schema Enums
|
|
1650
2054
|
`);
|
|
1651
2055
|
for (const enumDef of enums) {
|
|
1652
2056
|
parts.push(`export {
|
|
@@ -1661,9 +2065,35 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1661
2065
|
`);
|
|
1662
2066
|
parts.push(` get${enumDef.name}Extra,
|
|
1663
2067
|
`);
|
|
1664
|
-
parts.push(`} from '
|
|
2068
|
+
parts.push(`} from '${enumPrefix}/${enumDef.name}.js';
|
|
1665
2069
|
`);
|
|
1666
2070
|
}
|
|
2071
|
+
parts.push("\n");
|
|
2072
|
+
}
|
|
2073
|
+
if (pluginEnums.length > 0) {
|
|
2074
|
+
parts.push(`// Plugin Enums
|
|
2075
|
+
`);
|
|
2076
|
+
for (const enumDef of pluginEnums) {
|
|
2077
|
+
parts.push(`export {
|
|
2078
|
+
`);
|
|
2079
|
+
parts.push(` ${enumDef.name},
|
|
2080
|
+
`);
|
|
2081
|
+
parts.push(` ${enumDef.name}Values,
|
|
2082
|
+
`);
|
|
2083
|
+
parts.push(` is${enumDef.name},
|
|
2084
|
+
`);
|
|
2085
|
+
parts.push(` get${enumDef.name}Label,
|
|
2086
|
+
`);
|
|
2087
|
+
parts.push(` get${enumDef.name}Extra,
|
|
2088
|
+
`);
|
|
2089
|
+
parts.push(`} from '${enumPrefix}/plugin/${enumDef.name}.js';
|
|
2090
|
+
`);
|
|
2091
|
+
}
|
|
2092
|
+
parts.push("\n");
|
|
2093
|
+
}
|
|
2094
|
+
if (typeAliases.length > 0) {
|
|
2095
|
+
parts.push(`// Inline Enums (Type Aliases)
|
|
2096
|
+
`);
|
|
1667
2097
|
for (const alias of typeAliases) {
|
|
1668
2098
|
parts.push(`export {
|
|
1669
2099
|
`);
|
|
@@ -1677,13 +2107,13 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1677
2107
|
`);
|
|
1678
2108
|
parts.push(` get${alias.name}Extra,
|
|
1679
2109
|
`);
|
|
1680
|
-
parts.push(`} from '
|
|
2110
|
+
parts.push(`} from '${enumPrefix}/${alias.name}.js';
|
|
1681
2111
|
`);
|
|
1682
2112
|
}
|
|
1683
2113
|
parts.push("\n");
|
|
1684
2114
|
}
|
|
1685
2115
|
if (options.generateZodSchemas) {
|
|
1686
|
-
parts.push(`// Models (with Zod schemas and Create/Update types)
|
|
2116
|
+
parts.push(`// Models (with Zod schemas, i18n, and Create/Update types)
|
|
1687
2117
|
`);
|
|
1688
2118
|
for (const schema of Object.values(schemas)) {
|
|
1689
2119
|
if (schema.kind === "enum") continue;
|
|
@@ -1699,13 +2129,13 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1699
2129
|
`);
|
|
1700
2130
|
parts.push(` ${lowerName}UpdateSchema,
|
|
1701
2131
|
`);
|
|
1702
|
-
parts.push(` ${
|
|
2132
|
+
parts.push(` ${lowerName}I18n,
|
|
1703
2133
|
`);
|
|
1704
|
-
parts.push(` ${schema.name}
|
|
2134
|
+
parts.push(` get${schema.name}Label,
|
|
1705
2135
|
`);
|
|
1706
|
-
parts.push(` get${schema.name}
|
|
2136
|
+
parts.push(` get${schema.name}FieldLabel,
|
|
1707
2137
|
`);
|
|
1708
|
-
parts.push(` get${schema.name}
|
|
2138
|
+
parts.push(` get${schema.name}FieldPlaceholder,
|
|
1709
2139
|
`);
|
|
1710
2140
|
parts.push(`} from './${schema.name}.js';
|
|
1711
2141
|
`);
|
|
@@ -1751,9 +2181,47 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1751
2181
|
function generateTypeScript(schemas, options = {}) {
|
|
1752
2182
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
1753
2183
|
const files = [];
|
|
2184
|
+
const schemasByName = /* @__PURE__ */ new Map();
|
|
2185
|
+
for (const schema of Object.values(schemas)) {
|
|
2186
|
+
const paths = schemasByName.get(schema.name) ?? [];
|
|
2187
|
+
paths.push(schema.relativePath ?? schema.filePath);
|
|
2188
|
+
schemasByName.set(schema.name, paths);
|
|
2189
|
+
}
|
|
2190
|
+
const duplicateSchemas = Array.from(schemasByName.entries()).filter(([, paths]) => paths.length > 1);
|
|
2191
|
+
if (duplicateSchemas.length > 0) {
|
|
2192
|
+
const errors = duplicateSchemas.map(
|
|
2193
|
+
([name, paths]) => ` - "${name}" defined in: ${paths.join(", ")}`
|
|
2194
|
+
).join("\n");
|
|
2195
|
+
throw new Error(
|
|
2196
|
+
`Duplicate schema/enum names detected. Names must be globally unique:
|
|
2197
|
+
${errors}
|
|
2198
|
+
Hint: Rename to unique names like "Blog${duplicateSchemas[0][0]}" or "Shop${duplicateSchemas[0][0]}"`
|
|
2199
|
+
);
|
|
2200
|
+
}
|
|
2201
|
+
if (opts.pluginEnums && opts.pluginEnums.size > 0) {
|
|
2202
|
+
const conflicts = [];
|
|
2203
|
+
for (const schema of Object.values(schemas)) {
|
|
2204
|
+
if (schema.kind === "enum" && opts.pluginEnums.has(schema.name)) {
|
|
2205
|
+
conflicts.push(`"${schema.name}" (schema: ${schema.relativePath ?? schema.filePath}, plugin enum)`);
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
if (conflicts.length > 0) {
|
|
2209
|
+
throw new Error(
|
|
2210
|
+
`Schema enum conflicts with plugin enum:
|
|
2211
|
+
- ${conflicts.join("\n - ")}
|
|
2212
|
+
Hint: Rename your schema enum to avoid conflict with plugin-provided enums`
|
|
2213
|
+
);
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
1754
2216
|
const enums = generateEnums(schemas, opts);
|
|
1755
2217
|
for (const enumDef of enums) {
|
|
1756
|
-
files.push(generateEnumFile(enumDef));
|
|
2218
|
+
files.push(generateEnumFile(enumDef, false));
|
|
2219
|
+
}
|
|
2220
|
+
if (opts.pluginEnums && opts.pluginEnums.size > 0) {
|
|
2221
|
+
const pluginEnums = generatePluginEnums(opts.pluginEnums, opts);
|
|
2222
|
+
for (const enumDef of pluginEnums) {
|
|
2223
|
+
files.push(generateEnumFile(enumDef, true));
|
|
2224
|
+
}
|
|
1757
2225
|
}
|
|
1758
2226
|
const typeAliases = extractInlineEnums(schemas, opts);
|
|
1759
2227
|
for (const alias of typeAliases) {
|
|
@@ -1774,12 +2242,235 @@ function generateTypeScript(schemas, options = {}) {
|
|
|
1774
2242
|
files.push(...rulesFiles);
|
|
1775
2243
|
}
|
|
1776
2244
|
files.push(generateCommonFile(opts));
|
|
1777
|
-
files.push(
|
|
2245
|
+
files.push(generateI18nFile(opts));
|
|
2246
|
+
const pluginEnumsList = opts.pluginEnums ? generatePluginEnums(opts.pluginEnums, opts) : [];
|
|
2247
|
+
files.push(generateIndexFile(schemas, enums, pluginEnumsList, typeAliases, opts));
|
|
1778
2248
|
return files;
|
|
1779
2249
|
}
|
|
2250
|
+
|
|
2251
|
+
// src/stubs.ts
|
|
2252
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
2253
|
+
var import_path = __toESM(require("path"), 1);
|
|
2254
|
+
var import_url = require("url");
|
|
2255
|
+
var import_meta = {};
|
|
2256
|
+
var __filename = (0, import_url.fileURLToPath)(import_meta.url);
|
|
2257
|
+
var __dirname = import_path.default.dirname(__filename);
|
|
2258
|
+
var STUB_FILES = [
|
|
2259
|
+
// Components
|
|
2260
|
+
{
|
|
2261
|
+
stub: "JapaneseNameField.tsx.stub",
|
|
2262
|
+
output: "components/JapaneseNameField.tsx",
|
|
2263
|
+
indexExport: ""
|
|
2264
|
+
// Handled by components-index.ts.stub
|
|
2265
|
+
},
|
|
2266
|
+
{
|
|
2267
|
+
stub: "JapaneseAddressField.tsx.stub",
|
|
2268
|
+
output: "components/JapaneseAddressField.tsx",
|
|
2269
|
+
indexExport: ""
|
|
2270
|
+
// Handled by components-index.ts.stub
|
|
2271
|
+
},
|
|
2272
|
+
{
|
|
2273
|
+
stub: "JapaneseBankField.tsx.stub",
|
|
2274
|
+
output: "components/JapaneseBankField.tsx",
|
|
2275
|
+
indexExport: ""
|
|
2276
|
+
// Handled by components-index.ts.stub
|
|
2277
|
+
},
|
|
2278
|
+
{
|
|
2279
|
+
stub: "components-index.ts.stub",
|
|
2280
|
+
output: "components/index.ts",
|
|
2281
|
+
indexExport: ""
|
|
2282
|
+
// This IS the index
|
|
2283
|
+
},
|
|
2284
|
+
// Hooks
|
|
2285
|
+
{
|
|
2286
|
+
stub: "use-form-mutation.ts.stub",
|
|
2287
|
+
output: "hooks/use-form-mutation.ts",
|
|
2288
|
+
indexExport: `export { useFormMutation } from './use-form-mutation';
|
|
2289
|
+
`
|
|
2290
|
+
},
|
|
2291
|
+
// Lib
|
|
2292
|
+
{
|
|
2293
|
+
stub: "zod-i18n.ts.stub",
|
|
2294
|
+
output: "lib/zod-i18n.ts",
|
|
2295
|
+
indexExport: `export { setZodLocale, getZodLocale, getZodMessage } from './zod-i18n';
|
|
2296
|
+
`
|
|
2297
|
+
},
|
|
2298
|
+
{
|
|
2299
|
+
stub: "form-validation.ts.stub",
|
|
2300
|
+
output: "lib/form-validation.ts",
|
|
2301
|
+
indexExport: `export { zodRule, requiredRule } from './form-validation';
|
|
2302
|
+
export * from './rules';
|
|
2303
|
+
`
|
|
2304
|
+
},
|
|
2305
|
+
// Rules
|
|
2306
|
+
{
|
|
2307
|
+
stub: "rules/kana.ts.stub",
|
|
2308
|
+
output: "lib/rules/kana.ts",
|
|
2309
|
+
indexExport: ""
|
|
2310
|
+
// Will be handled by rules/index.ts
|
|
2311
|
+
},
|
|
2312
|
+
{
|
|
2313
|
+
stub: "rules/index.ts.stub",
|
|
2314
|
+
output: "lib/rules/index.ts",
|
|
2315
|
+
indexExport: ""
|
|
2316
|
+
// Already exported via form-validation
|
|
2317
|
+
}
|
|
2318
|
+
];
|
|
2319
|
+
function copyStubs(options) {
|
|
2320
|
+
const { targetDir, skipIfExists = true } = options;
|
|
2321
|
+
const stubsDir = import_path.default.join(__dirname, "..", "stubs");
|
|
2322
|
+
const result = { copied: [], skipped: [] };
|
|
2323
|
+
const directories = /* @__PURE__ */ new Map();
|
|
2324
|
+
for (const { stub, output, indexExport } of STUB_FILES) {
|
|
2325
|
+
const stubPath = import_path.default.join(stubsDir, stub);
|
|
2326
|
+
const outputPath = import_path.default.join(targetDir, output);
|
|
2327
|
+
const outputDir = import_path.default.dirname(outputPath);
|
|
2328
|
+
const dirName = import_path.default.dirname(output).split("/")[0];
|
|
2329
|
+
if (!directories.has(dirName)) {
|
|
2330
|
+
directories.set(dirName, "");
|
|
2331
|
+
}
|
|
2332
|
+
directories.set(dirName, directories.get(dirName) + indexExport);
|
|
2333
|
+
if (!import_fs.default.existsSync(outputDir)) {
|
|
2334
|
+
import_fs.default.mkdirSync(outputDir, { recursive: true });
|
|
2335
|
+
}
|
|
2336
|
+
if (skipIfExists && import_fs.default.existsSync(outputPath)) {
|
|
2337
|
+
result.skipped.push(output);
|
|
2338
|
+
continue;
|
|
2339
|
+
}
|
|
2340
|
+
if (import_fs.default.existsSync(stubPath)) {
|
|
2341
|
+
const content = import_fs.default.readFileSync(stubPath, "utf-8");
|
|
2342
|
+
import_fs.default.writeFileSync(outputPath, content);
|
|
2343
|
+
result.copied.push(output);
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
for (const [dirName, exports2] of directories) {
|
|
2347
|
+
const indexPath = import_path.default.join(targetDir, dirName, "index.ts");
|
|
2348
|
+
if (skipIfExists && import_fs.default.existsSync(indexPath)) {
|
|
2349
|
+
continue;
|
|
2350
|
+
}
|
|
2351
|
+
import_fs.default.writeFileSync(indexPath, exports2);
|
|
2352
|
+
result.copied.push(`${dirName}/index.ts`);
|
|
2353
|
+
}
|
|
2354
|
+
return result;
|
|
2355
|
+
}
|
|
2356
|
+
function getStubPaths() {
|
|
2357
|
+
return STUB_FILES.map((s) => s.output);
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
// src/ai-guides/generator.ts
|
|
2361
|
+
var import_node_fs = require("fs");
|
|
2362
|
+
var import_node_path = require("path");
|
|
2363
|
+
var import_node_url = require("url");
|
|
2364
|
+
var import_meta2 = {};
|
|
2365
|
+
var __filename2 = (0, import_node_url.fileURLToPath)(import_meta2.url);
|
|
2366
|
+
var __dirname2 = (0, import_node_path.dirname)(__filename2);
|
|
2367
|
+
function getStubsDir() {
|
|
2368
|
+
const devPath = (0, import_node_path.resolve)(__dirname2, "../../stubs/ai-guides");
|
|
2369
|
+
if ((0, import_node_fs.existsSync)(devPath)) {
|
|
2370
|
+
return devPath;
|
|
2371
|
+
}
|
|
2372
|
+
const distPath = (0, import_node_path.resolve)(__dirname2, "../stubs/ai-guides");
|
|
2373
|
+
if ((0, import_node_fs.existsSync)(distPath)) {
|
|
2374
|
+
return distPath;
|
|
2375
|
+
}
|
|
2376
|
+
throw new Error("AI guides stubs not found");
|
|
2377
|
+
}
|
|
2378
|
+
function extractTypescriptBasePath(typescriptPath) {
|
|
2379
|
+
if (!typescriptPath) return "src";
|
|
2380
|
+
const normalized = typescriptPath.replace(/\\/g, "/");
|
|
2381
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
2382
|
+
if (parts.length > 1) {
|
|
2383
|
+
return parts.slice(0, -1).join("/");
|
|
2384
|
+
}
|
|
2385
|
+
return "src";
|
|
2386
|
+
}
|
|
2387
|
+
function replacePlaceholders(content, basePath) {
|
|
2388
|
+
return content.replace(/\{\{TYPESCRIPT_BASE\}\}/g, basePath);
|
|
2389
|
+
}
|
|
2390
|
+
function copyStubs2(srcDir, destDir, transform) {
|
|
2391
|
+
const writtenFiles = [];
|
|
2392
|
+
if (!(0, import_node_fs.existsSync)(srcDir)) {
|
|
2393
|
+
return writtenFiles;
|
|
2394
|
+
}
|
|
2395
|
+
if (!(0, import_node_fs.existsSync)(destDir)) {
|
|
2396
|
+
(0, import_node_fs.mkdirSync)(destDir, { recursive: true });
|
|
2397
|
+
}
|
|
2398
|
+
const entries = (0, import_node_fs.readdirSync)(srcDir, { withFileTypes: true });
|
|
2399
|
+
for (const entry of entries) {
|
|
2400
|
+
const srcPath = (0, import_node_path.join)(srcDir, entry.name);
|
|
2401
|
+
if (entry.isDirectory()) {
|
|
2402
|
+
const subDestDir = (0, import_node_path.join)(destDir, entry.name);
|
|
2403
|
+
const subFiles = copyStubs2(srcPath, subDestDir, transform);
|
|
2404
|
+
writtenFiles.push(...subFiles);
|
|
2405
|
+
} else if (entry.isFile() && entry.name.endsWith(".stub")) {
|
|
2406
|
+
const destName = entry.name.slice(0, -5);
|
|
2407
|
+
const destPath = (0, import_node_path.join)(destDir, destName);
|
|
2408
|
+
let content = (0, import_node_fs.readFileSync)(srcPath, "utf-8");
|
|
2409
|
+
if (transform) {
|
|
2410
|
+
content = transform(content);
|
|
2411
|
+
}
|
|
2412
|
+
(0, import_node_fs.writeFileSync)(destPath, content);
|
|
2413
|
+
writtenFiles.push(destPath);
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
return writtenFiles;
|
|
2417
|
+
}
|
|
2418
|
+
function generateAIGuides(rootDir, options = {}) {
|
|
2419
|
+
const stubsDir = getStubsDir();
|
|
2420
|
+
const basePath = options.typescriptBasePath || extractTypescriptBasePath(options.typescriptPath);
|
|
2421
|
+
const result = {
|
|
2422
|
+
claudeGuides: 0,
|
|
2423
|
+
claudeChecklists: 0,
|
|
2424
|
+
cursorRules: 0,
|
|
2425
|
+
files: []
|
|
2426
|
+
};
|
|
2427
|
+
const claudeSrcDir = (0, import_node_path.join)(stubsDir, "react");
|
|
2428
|
+
const claudeDestDir = (0, import_node_path.resolve)(rootDir, ".claude/omnify/guides/react");
|
|
2429
|
+
if ((0, import_node_fs.existsSync)(claudeSrcDir)) {
|
|
2430
|
+
const files = copyStubs2(claudeSrcDir, claudeDestDir);
|
|
2431
|
+
result.claudeGuides = files.length;
|
|
2432
|
+
result.files.push(...files);
|
|
2433
|
+
}
|
|
2434
|
+
const claudeChecklistsSrcDir = (0, import_node_path.join)(stubsDir, "checklists");
|
|
2435
|
+
const claudeChecklistsDestDir = (0, import_node_path.resolve)(rootDir, ".claude/omnify/checklists");
|
|
2436
|
+
if ((0, import_node_fs.existsSync)(claudeChecklistsSrcDir)) {
|
|
2437
|
+
const files = copyStubs2(claudeChecklistsSrcDir, claudeChecklistsDestDir);
|
|
2438
|
+
result.claudeChecklists = files.length;
|
|
2439
|
+
result.files.push(...files);
|
|
2440
|
+
}
|
|
2441
|
+
const cursorSrcDir = (0, import_node_path.join)(stubsDir, "cursor");
|
|
2442
|
+
const cursorDestDir = (0, import_node_path.resolve)(rootDir, ".cursor/rules/omnify");
|
|
2443
|
+
if ((0, import_node_fs.existsSync)(cursorSrcDir)) {
|
|
2444
|
+
const files = copyStubs2(
|
|
2445
|
+
cursorSrcDir,
|
|
2446
|
+
cursorDestDir,
|
|
2447
|
+
(content) => replacePlaceholders(content, basePath)
|
|
2448
|
+
);
|
|
2449
|
+
result.cursorRules = files.length;
|
|
2450
|
+
result.files.push(...files);
|
|
2451
|
+
}
|
|
2452
|
+
return result;
|
|
2453
|
+
}
|
|
2454
|
+
function shouldGenerateAIGuides(rootDir) {
|
|
2455
|
+
const claudeDir = (0, import_node_path.resolve)(rootDir, ".claude/omnify/guides/react");
|
|
2456
|
+
const cursorDir = (0, import_node_path.resolve)(rootDir, ".cursor/rules/omnify");
|
|
2457
|
+
if (!(0, import_node_fs.existsSync)(claudeDir) || !(0, import_node_fs.existsSync)(cursorDir)) {
|
|
2458
|
+
return true;
|
|
2459
|
+
}
|
|
2460
|
+
try {
|
|
2461
|
+
const claudeFiles = (0, import_node_fs.readdirSync)(claudeDir);
|
|
2462
|
+
const cursorFiles = (0, import_node_fs.readdirSync)(cursorDir);
|
|
2463
|
+
const hasReactRules = cursorFiles.some((f) => f.startsWith("react"));
|
|
2464
|
+
return claudeFiles.length === 0 || !hasReactRules;
|
|
2465
|
+
} catch {
|
|
2466
|
+
return true;
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
1780
2469
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1781
2470
|
0 && (module.exports = {
|
|
1782
2471
|
DEFAULT_VALIDATION_TEMPLATES,
|
|
2472
|
+
STUB_FILES,
|
|
2473
|
+
copyStubs,
|
|
1783
2474
|
enumToUnionType,
|
|
1784
2475
|
extractInlineEnums,
|
|
1785
2476
|
formatEnum,
|
|
@@ -1787,18 +2478,23 @@ function generateTypeScript(schemas, options = {}) {
|
|
|
1787
2478
|
formatProperty,
|
|
1788
2479
|
formatTypeAlias,
|
|
1789
2480
|
formatValidationMessage,
|
|
2481
|
+
generateAIGuides,
|
|
1790
2482
|
generateEnums,
|
|
1791
2483
|
generateInterfaces,
|
|
1792
2484
|
generateModelRules,
|
|
2485
|
+
generatePluginEnums,
|
|
1793
2486
|
generateRulesFiles,
|
|
1794
2487
|
generateTypeScript,
|
|
1795
2488
|
generateTypeScriptFiles,
|
|
1796
2489
|
getPropertyType,
|
|
2490
|
+
getStubPaths,
|
|
1797
2491
|
getValidationMessages,
|
|
1798
2492
|
mergeValidationTemplates,
|
|
2493
|
+
pluginEnumToTSEnum,
|
|
1799
2494
|
propertyToTSProperty,
|
|
1800
2495
|
schemaToEnum,
|
|
1801
2496
|
schemaToInterface,
|
|
2497
|
+
shouldGenerateAIGuides,
|
|
1802
2498
|
toEnumMemberName,
|
|
1803
2499
|
toEnumName,
|
|
1804
2500
|
toInterfaceName,
|