@famgia/omnify-typescript 0.0.64 → 0.0.66
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-53QQ3AMT.js → chunk-4L77AHAC.js} +544 -23
- package/dist/chunk-4L77AHAC.js.map +1 -0
- package/dist/index.cjs +543 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +1 -1
- package/dist/plugin.cjs +561 -27
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +13 -7
- package/dist/plugin.d.ts +13 -7
- package/dist/plugin.js +19 -6
- package/dist/plugin.js.map +1 -1
- package/package.json +10 -2
- package/dist/chunk-53QQ3AMT.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -951,11 +951,460 @@ function generateRulesFiles(schemas, options = {}) {
|
|
|
951
951
|
return files;
|
|
952
952
|
}
|
|
953
953
|
|
|
954
|
+
// src/zod-generator.ts
|
|
955
|
+
function getMultiLocaleDisplayName2(value, locales, fallbackLocale, defaultValue) {
|
|
956
|
+
if (!value) {
|
|
957
|
+
const result2 = {};
|
|
958
|
+
for (const locale of locales) {
|
|
959
|
+
result2[locale] = defaultValue;
|
|
960
|
+
}
|
|
961
|
+
return result2;
|
|
962
|
+
}
|
|
963
|
+
if (typeof value === "string") {
|
|
964
|
+
const result2 = {};
|
|
965
|
+
for (const locale of locales) {
|
|
966
|
+
result2[locale] = value;
|
|
967
|
+
}
|
|
968
|
+
return result2;
|
|
969
|
+
}
|
|
970
|
+
const result = {};
|
|
971
|
+
for (const locale of locales) {
|
|
972
|
+
result[locale] = value[locale] ?? value[fallbackLocale] ?? value["en"] ?? defaultValue;
|
|
973
|
+
}
|
|
974
|
+
return result;
|
|
975
|
+
}
|
|
976
|
+
function getZodSchemaForType(propDef, fieldName, customTypes) {
|
|
977
|
+
const def = propDef;
|
|
978
|
+
const isNullable = def.nullable ?? false;
|
|
979
|
+
let schema = "";
|
|
980
|
+
if (customTypes) {
|
|
981
|
+
const customType = customTypes.get(propDef.type);
|
|
982
|
+
if (customType && !customType.compound) {
|
|
983
|
+
const sqlType = customType.sql?.sqlType || "VARCHAR";
|
|
984
|
+
schema = "z.string()";
|
|
985
|
+
if (customType.sql?.length) {
|
|
986
|
+
schema += `.max(${customType.sql.length})`;
|
|
987
|
+
}
|
|
988
|
+
if (isNullable) {
|
|
989
|
+
schema += ".optional().nullable()";
|
|
990
|
+
}
|
|
991
|
+
return schema;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
switch (propDef.type) {
|
|
995
|
+
case "String":
|
|
996
|
+
case "Text":
|
|
997
|
+
case "MediumText":
|
|
998
|
+
case "LongText":
|
|
999
|
+
case "Password":
|
|
1000
|
+
schema = "z.string()";
|
|
1001
|
+
if (!isNullable) {
|
|
1002
|
+
schema += ".min(1)";
|
|
1003
|
+
}
|
|
1004
|
+
if (def.maxLength || def.length) {
|
|
1005
|
+
schema += `.max(${def.maxLength ?? def.length})`;
|
|
1006
|
+
}
|
|
1007
|
+
if (def.minLength && def.minLength > 1) {
|
|
1008
|
+
schema = schema.replace(".min(1)", `.min(${def.minLength})`);
|
|
1009
|
+
}
|
|
1010
|
+
break;
|
|
1011
|
+
case "Email":
|
|
1012
|
+
schema = "z.string().email()";
|
|
1013
|
+
if (def.maxLength || def.length) {
|
|
1014
|
+
schema += `.max(${def.maxLength ?? def.length ?? 255})`;
|
|
1015
|
+
}
|
|
1016
|
+
break;
|
|
1017
|
+
case "TinyInt":
|
|
1018
|
+
case "Int":
|
|
1019
|
+
case "BigInt":
|
|
1020
|
+
schema = "z.number().int()";
|
|
1021
|
+
if (def.min !== void 0) {
|
|
1022
|
+
schema += `.gte(${def.min})`;
|
|
1023
|
+
}
|
|
1024
|
+
if (def.max !== void 0) {
|
|
1025
|
+
schema += `.lte(${def.max})`;
|
|
1026
|
+
}
|
|
1027
|
+
break;
|
|
1028
|
+
case "Float":
|
|
1029
|
+
schema = "z.number()";
|
|
1030
|
+
if (def.min !== void 0) {
|
|
1031
|
+
schema += `.gte(${def.min})`;
|
|
1032
|
+
}
|
|
1033
|
+
if (def.max !== void 0) {
|
|
1034
|
+
schema += `.lte(${def.max})`;
|
|
1035
|
+
}
|
|
1036
|
+
break;
|
|
1037
|
+
case "Boolean":
|
|
1038
|
+
schema = "z.boolean()";
|
|
1039
|
+
break;
|
|
1040
|
+
case "Date":
|
|
1041
|
+
schema = "z.string().date()";
|
|
1042
|
+
break;
|
|
1043
|
+
case "DateTime":
|
|
1044
|
+
case "Timestamp":
|
|
1045
|
+
schema = "z.string().datetime({ offset: true })";
|
|
1046
|
+
break;
|
|
1047
|
+
case "Time":
|
|
1048
|
+
schema = "z.string().time()";
|
|
1049
|
+
break;
|
|
1050
|
+
case "Json":
|
|
1051
|
+
schema = "z.unknown()";
|
|
1052
|
+
break;
|
|
1053
|
+
case "Enum":
|
|
1054
|
+
if (typeof def.enum === "string") {
|
|
1055
|
+
schema = `${def.enum}Schema`;
|
|
1056
|
+
} else if (Array.isArray(def.enum)) {
|
|
1057
|
+
const values = def.enum.map((v) => `'${v}'`).join(", ");
|
|
1058
|
+
schema = `z.enum([${values}])`;
|
|
1059
|
+
} else {
|
|
1060
|
+
schema = "z.string()";
|
|
1061
|
+
}
|
|
1062
|
+
break;
|
|
1063
|
+
case "Select":
|
|
1064
|
+
if (def.options && def.options.length > 0) {
|
|
1065
|
+
const values = def.options.map((v) => `'${v}'`).join(", ");
|
|
1066
|
+
schema = `z.enum([${values}])`;
|
|
1067
|
+
} else {
|
|
1068
|
+
schema = "z.string()";
|
|
1069
|
+
}
|
|
1070
|
+
break;
|
|
1071
|
+
case "Lookup":
|
|
1072
|
+
schema = "z.number().int().positive()";
|
|
1073
|
+
break;
|
|
1074
|
+
case "Association":
|
|
1075
|
+
return "";
|
|
1076
|
+
case "File":
|
|
1077
|
+
return "";
|
|
1078
|
+
default:
|
|
1079
|
+
schema = "z.string()";
|
|
1080
|
+
}
|
|
1081
|
+
if (isNullable && schema) {
|
|
1082
|
+
schema += ".optional().nullable()";
|
|
1083
|
+
}
|
|
1084
|
+
if (def.pattern && schema) {
|
|
1085
|
+
schema += `.regex(/${def.pattern}/)`;
|
|
1086
|
+
}
|
|
1087
|
+
return schema;
|
|
1088
|
+
}
|
|
1089
|
+
function generateCompoundTypeSchemas(propName, propDef, customType, options) {
|
|
1090
|
+
const schemas = [];
|
|
1091
|
+
const propFields = propDef.fields;
|
|
1092
|
+
const locales = options.localeConfig?.locales ?? ["en"];
|
|
1093
|
+
const fallbackLocale = options.localeConfig?.fallbackLocale ?? "en";
|
|
1094
|
+
if (!customType.expand) return schemas;
|
|
1095
|
+
for (const field of customType.expand) {
|
|
1096
|
+
const fieldName = `${toSnakeCase(propName)}_${toSnakeCase(field.suffix)}`;
|
|
1097
|
+
const fieldOverride = propFields?.[field.suffix];
|
|
1098
|
+
const isNullable = fieldOverride?.nullable ?? propDef.nullable ?? false;
|
|
1099
|
+
const length = fieldOverride?.length ?? field.sql?.length;
|
|
1100
|
+
let schema = "z.string()";
|
|
1101
|
+
if (!isNullable) {
|
|
1102
|
+
schema += ".min(1)";
|
|
1103
|
+
}
|
|
1104
|
+
if (length) {
|
|
1105
|
+
schema += `.max(${length})`;
|
|
1106
|
+
}
|
|
1107
|
+
if (isNullable) {
|
|
1108
|
+
schema += ".optional().nullable()";
|
|
1109
|
+
}
|
|
1110
|
+
const propDisplayName = getMultiLocaleDisplayName2(
|
|
1111
|
+
propDef.displayName,
|
|
1112
|
+
locales,
|
|
1113
|
+
fallbackLocale,
|
|
1114
|
+
propName
|
|
1115
|
+
);
|
|
1116
|
+
schemas.push({
|
|
1117
|
+
fieldName,
|
|
1118
|
+
schema,
|
|
1119
|
+
inCreate: true,
|
|
1120
|
+
inUpdate: true,
|
|
1121
|
+
comment: `${propDisplayName["en"] ?? propName} (${field.suffix})`
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
return schemas;
|
|
1125
|
+
}
|
|
1126
|
+
function generateZodSchemas(schema, options) {
|
|
1127
|
+
const schemas = [];
|
|
1128
|
+
const customTypes = options.customTypes;
|
|
1129
|
+
if (!schema.properties) return schemas;
|
|
1130
|
+
for (const [propName, propDef] of Object.entries(schema.properties)) {
|
|
1131
|
+
if (customTypes) {
|
|
1132
|
+
const customType = customTypes.get(propDef.type);
|
|
1133
|
+
if (customType?.compound) {
|
|
1134
|
+
schemas.push(...generateCompoundTypeSchemas(propName, propDef, customType, options));
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
const zodSchema = getZodSchemaForType(propDef, propName, customTypes);
|
|
1139
|
+
if (!zodSchema) continue;
|
|
1140
|
+
const fieldName = toSnakeCase(propName);
|
|
1141
|
+
schemas.push({
|
|
1142
|
+
fieldName,
|
|
1143
|
+
schema: zodSchema,
|
|
1144
|
+
inCreate: true,
|
|
1145
|
+
inUpdate: true,
|
|
1146
|
+
comment: void 0
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
return schemas;
|
|
1150
|
+
}
|
|
1151
|
+
function generateDisplayNames(schema, options) {
|
|
1152
|
+
const locales = options.localeConfig?.locales ?? ["en"];
|
|
1153
|
+
const fallbackLocale = options.localeConfig?.fallbackLocale ?? "en";
|
|
1154
|
+
const customTypes = options.customTypes;
|
|
1155
|
+
const displayName = getMultiLocaleDisplayName2(
|
|
1156
|
+
schema.displayName,
|
|
1157
|
+
locales,
|
|
1158
|
+
fallbackLocale,
|
|
1159
|
+
schema.name
|
|
1160
|
+
);
|
|
1161
|
+
const propertyDisplayNames = {};
|
|
1162
|
+
if (schema.properties) {
|
|
1163
|
+
for (const [propName, propDef] of Object.entries(schema.properties)) {
|
|
1164
|
+
const prop = propDef;
|
|
1165
|
+
const fieldName = toSnakeCase(propName);
|
|
1166
|
+
if (customTypes) {
|
|
1167
|
+
const customType = customTypes.get(propDef.type);
|
|
1168
|
+
if (customType?.compound && customType.expand) {
|
|
1169
|
+
for (const field of customType.expand) {
|
|
1170
|
+
const expandedFieldName = `${fieldName}_${toSnakeCase(field.suffix)}`;
|
|
1171
|
+
propertyDisplayNames[expandedFieldName] = getMultiLocaleDisplayName2(
|
|
1172
|
+
prop.displayName,
|
|
1173
|
+
locales,
|
|
1174
|
+
fallbackLocale,
|
|
1175
|
+
propName
|
|
1176
|
+
);
|
|
1177
|
+
for (const locale of locales) {
|
|
1178
|
+
propertyDisplayNames[expandedFieldName] = {
|
|
1179
|
+
...propertyDisplayNames[expandedFieldName],
|
|
1180
|
+
[locale]: `${propertyDisplayNames[expandedFieldName][locale]} (${field.suffix})`
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
propertyDisplayNames[fieldName] = getMultiLocaleDisplayName2(
|
|
1188
|
+
prop.displayName,
|
|
1189
|
+
locales,
|
|
1190
|
+
fallbackLocale,
|
|
1191
|
+
propName
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
return { displayName, propertyDisplayNames };
|
|
1196
|
+
}
|
|
1197
|
+
function getExcludedFields(schema, customTypes) {
|
|
1198
|
+
const createExclude = /* @__PURE__ */ new Set();
|
|
1199
|
+
const updateExclude = /* @__PURE__ */ new Set();
|
|
1200
|
+
if (schema.options?.id !== false) {
|
|
1201
|
+
createExclude.add("id");
|
|
1202
|
+
updateExclude.add("id");
|
|
1203
|
+
}
|
|
1204
|
+
if (schema.options?.timestamps !== false) {
|
|
1205
|
+
createExclude.add("created_at");
|
|
1206
|
+
createExclude.add("updated_at");
|
|
1207
|
+
updateExclude.add("created_at");
|
|
1208
|
+
updateExclude.add("updated_at");
|
|
1209
|
+
}
|
|
1210
|
+
if (schema.options?.softDelete) {
|
|
1211
|
+
createExclude.add("deleted_at");
|
|
1212
|
+
updateExclude.add("deleted_at");
|
|
1213
|
+
}
|
|
1214
|
+
if (schema.properties) {
|
|
1215
|
+
if (schema.properties["emailVerifiedAt"] || schema.properties["email_verified_at"]) {
|
|
1216
|
+
createExclude.add("email_verified_at");
|
|
1217
|
+
updateExclude.add("email_verified_at");
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
if (schema.properties && customTypes) {
|
|
1221
|
+
for (const [propName, propDef] of Object.entries(schema.properties)) {
|
|
1222
|
+
const customType = customTypes.get(propDef.type);
|
|
1223
|
+
if (customType?.accessors) {
|
|
1224
|
+
for (const accessor of customType.accessors) {
|
|
1225
|
+
const fieldName = `${toSnakeCase(propName)}_${toSnakeCase(accessor.name)}`;
|
|
1226
|
+
createExclude.add(fieldName);
|
|
1227
|
+
updateExclude.add(fieldName);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return { create: createExclude, update: updateExclude };
|
|
1233
|
+
}
|
|
1234
|
+
function formatZodSchemasSection(schemaName, zodSchemas, displayNames, excludedFields) {
|
|
1235
|
+
const parts = [];
|
|
1236
|
+
const lowerName = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
|
|
1237
|
+
parts.push(`// ============================================================================
|
|
1238
|
+
`);
|
|
1239
|
+
parts.push(`// Display Names
|
|
1240
|
+
`);
|
|
1241
|
+
parts.push(`// ============================================================================
|
|
1242
|
+
|
|
1243
|
+
`);
|
|
1244
|
+
parts.push(`/** Display name for ${schemaName} */
|
|
1245
|
+
`);
|
|
1246
|
+
parts.push(`export const ${schemaName}DisplayName = ${JSON.stringify(displayNames.displayName, null, 2)} as const;
|
|
1247
|
+
|
|
1248
|
+
`);
|
|
1249
|
+
parts.push(`/** Property display names for ${schemaName} */
|
|
1250
|
+
`);
|
|
1251
|
+
parts.push(`export const ${schemaName}PropertyDisplayNames = {
|
|
1252
|
+
`);
|
|
1253
|
+
for (const [propName, localeMap] of Object.entries(displayNames.propertyDisplayNames)) {
|
|
1254
|
+
parts.push(` ${propName}: ${JSON.stringify(localeMap)},
|
|
1255
|
+
`);
|
|
1256
|
+
}
|
|
1257
|
+
parts.push(`} as const;
|
|
1258
|
+
|
|
1259
|
+
`);
|
|
1260
|
+
parts.push(`// ============================================================================
|
|
1261
|
+
`);
|
|
1262
|
+
parts.push(`// Zod Schemas
|
|
1263
|
+
`);
|
|
1264
|
+
parts.push(`// ============================================================================
|
|
1265
|
+
|
|
1266
|
+
`);
|
|
1267
|
+
parts.push(`/** Field schemas for ${schemaName} */
|
|
1268
|
+
`);
|
|
1269
|
+
parts.push(`export const base${schemaName}Schemas = {
|
|
1270
|
+
`);
|
|
1271
|
+
for (const prop of zodSchemas) {
|
|
1272
|
+
if (prop.comment) {
|
|
1273
|
+
parts.push(` /** ${prop.comment} */
|
|
1274
|
+
`);
|
|
1275
|
+
}
|
|
1276
|
+
parts.push(` ${prop.fieldName}: ${prop.schema},
|
|
1277
|
+
`);
|
|
1278
|
+
}
|
|
1279
|
+
parts.push(`} as const;
|
|
1280
|
+
|
|
1281
|
+
`);
|
|
1282
|
+
const createFields = zodSchemas.filter((p) => p.inCreate && !excludedFields.create.has(p.fieldName));
|
|
1283
|
+
parts.push(`/** Create schema for ${schemaName} (POST requests) */
|
|
1284
|
+
`);
|
|
1285
|
+
parts.push(`export const base${schemaName}CreateSchema = z.object({
|
|
1286
|
+
`);
|
|
1287
|
+
for (const prop of createFields) {
|
|
1288
|
+
parts.push(` ${prop.fieldName}: base${schemaName}Schemas.${prop.fieldName},
|
|
1289
|
+
`);
|
|
1290
|
+
}
|
|
1291
|
+
parts.push(`});
|
|
1292
|
+
|
|
1293
|
+
`);
|
|
1294
|
+
parts.push(`/** Update schema for ${schemaName} (PUT/PATCH requests) */
|
|
1295
|
+
`);
|
|
1296
|
+
parts.push(`export const base${schemaName}UpdateSchema = base${schemaName}CreateSchema.partial();
|
|
1297
|
+
|
|
1298
|
+
`);
|
|
1299
|
+
parts.push(`// ============================================================================
|
|
1300
|
+
`);
|
|
1301
|
+
parts.push(`// Inferred Types
|
|
1302
|
+
`);
|
|
1303
|
+
parts.push(`// ============================================================================
|
|
1304
|
+
|
|
1305
|
+
`);
|
|
1306
|
+
parts.push(`export type Base${schemaName}Create = z.infer<typeof base${schemaName}CreateSchema>;
|
|
1307
|
+
`);
|
|
1308
|
+
parts.push(`export type Base${schemaName}Update = z.infer<typeof base${schemaName}UpdateSchema>;
|
|
1309
|
+
|
|
1310
|
+
`);
|
|
1311
|
+
parts.push(`// ============================================================================
|
|
1312
|
+
`);
|
|
1313
|
+
parts.push(`// Helper Functions
|
|
1314
|
+
`);
|
|
1315
|
+
parts.push(`// ============================================================================
|
|
1316
|
+
|
|
1317
|
+
`);
|
|
1318
|
+
parts.push(`/** Get display name for a specific locale */
|
|
1319
|
+
`);
|
|
1320
|
+
parts.push(`export function get${schemaName}DisplayName(locale: string): string {
|
|
1321
|
+
`);
|
|
1322
|
+
parts.push(` return ${schemaName}DisplayName[locale as keyof typeof ${schemaName}DisplayName] ?? ${schemaName}DisplayName['en'] ?? '${schemaName}';
|
|
1323
|
+
`);
|
|
1324
|
+
parts.push(`}
|
|
1325
|
+
|
|
1326
|
+
`);
|
|
1327
|
+
parts.push(`/** Get property display name for a specific locale */
|
|
1328
|
+
`);
|
|
1329
|
+
parts.push(`export function get${schemaName}PropertyDisplayName(property: string, locale: string): string {
|
|
1330
|
+
`);
|
|
1331
|
+
parts.push(` const names = ${schemaName}PropertyDisplayNames[property as keyof typeof ${schemaName}PropertyDisplayNames];
|
|
1332
|
+
`);
|
|
1333
|
+
parts.push(` if (!names) return property;
|
|
1334
|
+
`);
|
|
1335
|
+
parts.push(` return names[locale as keyof typeof names] ?? names['en'] ?? property;
|
|
1336
|
+
`);
|
|
1337
|
+
parts.push(`}
|
|
1338
|
+
`);
|
|
1339
|
+
return parts.join("");
|
|
1340
|
+
}
|
|
1341
|
+
function formatZodModelFile(schemaName) {
|
|
1342
|
+
const lowerName = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
|
|
1343
|
+
return `/**
|
|
1344
|
+
* ${schemaName} Model
|
|
1345
|
+
*
|
|
1346
|
+
* This file extends the auto-generated base interface.
|
|
1347
|
+
* You can add custom methods, computed properties, or override types/schemas here.
|
|
1348
|
+
* This file will NOT be overwritten by the generator.
|
|
1349
|
+
*/
|
|
1350
|
+
|
|
1351
|
+
import { z } from 'zod';
|
|
1352
|
+
import type { ${schemaName} as ${schemaName}Base } from './base/${schemaName}.js';
|
|
1353
|
+
import {
|
|
1354
|
+
base${schemaName}Schemas,
|
|
1355
|
+
base${schemaName}CreateSchema,
|
|
1356
|
+
base${schemaName}UpdateSchema,
|
|
1357
|
+
${schemaName}DisplayName,
|
|
1358
|
+
${schemaName}PropertyDisplayNames,
|
|
1359
|
+
get${schemaName}DisplayName,
|
|
1360
|
+
get${schemaName}PropertyDisplayName,
|
|
1361
|
+
} from './base/${schemaName}.js';
|
|
1362
|
+
|
|
1363
|
+
// ============================================================================
|
|
1364
|
+
// Types (extend or re-export)
|
|
1365
|
+
// ============================================================================
|
|
1366
|
+
|
|
1367
|
+
export interface ${schemaName} extends ${schemaName}Base {
|
|
1368
|
+
// Add custom properties here
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
// ============================================================================
|
|
1372
|
+
// Schemas (extend or re-export)
|
|
1373
|
+
// ============================================================================
|
|
1374
|
+
|
|
1375
|
+
export const ${lowerName}Schemas = { ...base${schemaName}Schemas };
|
|
1376
|
+
export const ${lowerName}CreateSchema = base${schemaName}CreateSchema;
|
|
1377
|
+
export const ${lowerName}UpdateSchema = base${schemaName}UpdateSchema;
|
|
1378
|
+
|
|
1379
|
+
// ============================================================================
|
|
1380
|
+
// Types
|
|
1381
|
+
// ============================================================================
|
|
1382
|
+
|
|
1383
|
+
export type ${schemaName}Create = z.infer<typeof ${lowerName}CreateSchema>;
|
|
1384
|
+
export type ${schemaName}Update = z.infer<typeof ${lowerName}UpdateSchema>;
|
|
1385
|
+
|
|
1386
|
+
// Re-export display names and helpers
|
|
1387
|
+
export {
|
|
1388
|
+
${schemaName}DisplayName,
|
|
1389
|
+
${schemaName}PropertyDisplayNames,
|
|
1390
|
+
get${schemaName}DisplayName,
|
|
1391
|
+
get${schemaName}PropertyDisplayName,
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
// Re-export base type for internal use
|
|
1395
|
+
export type { ${schemaName}Base };
|
|
1396
|
+
`;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
954
1399
|
// src/generator.ts
|
|
955
1400
|
var DEFAULT_OPTIONS = {
|
|
956
1401
|
readonly: false,
|
|
957
1402
|
// Changed: interfaces should be mutable for forms/mutations
|
|
958
|
-
strictNullChecks: true
|
|
1403
|
+
strictNullChecks: true,
|
|
1404
|
+
generateZodSchemas: true,
|
|
1405
|
+
// Generate Zod schemas by default
|
|
1406
|
+
generateRules: false
|
|
1407
|
+
// Legacy Ant Design rules (deprecated, ignored when generateZodSchemas=true)
|
|
959
1408
|
};
|
|
960
1409
|
function generateBaseHeader() {
|
|
961
1410
|
return `/**
|
|
@@ -976,7 +1425,21 @@ function generateModelHeader(schemaName) {
|
|
|
976
1425
|
|
|
977
1426
|
`;
|
|
978
1427
|
}
|
|
979
|
-
function
|
|
1428
|
+
function getComputedFields(schema, customTypes) {
|
|
1429
|
+
const computedFields = [];
|
|
1430
|
+
if (!schema.properties) return computedFields;
|
|
1431
|
+
for (const [propName, propDef] of Object.entries(schema.properties)) {
|
|
1432
|
+
const snakeName = toSnakeCase(propName);
|
|
1433
|
+
const customType = customTypes?.get(propDef.type);
|
|
1434
|
+
if (customType?.accessors) {
|
|
1435
|
+
for (const accessor of customType.accessors) {
|
|
1436
|
+
computedFields.push(`${snakeName}_${toSnakeCase(accessor.name)}`);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
return computedFields;
|
|
1441
|
+
}
|
|
1442
|
+
function generateUtilityTypes(schemaName, schema, customTypes) {
|
|
980
1443
|
const parts = [];
|
|
981
1444
|
const excludeFields = [];
|
|
982
1445
|
if (schema.options?.id !== false) {
|
|
@@ -988,6 +1451,13 @@ function generateUtilityTypes(schemaName, schema) {
|
|
|
988
1451
|
if (schema.options?.softDelete) {
|
|
989
1452
|
excludeFields.push("'deleted_at'");
|
|
990
1453
|
}
|
|
1454
|
+
if (schema.properties?.["emailVerifiedAt"] || schema.properties?.["email_verified_at"]) {
|
|
1455
|
+
excludeFields.push("'email_verified_at'");
|
|
1456
|
+
}
|
|
1457
|
+
const computedFields = getComputedFields(schema, customTypes);
|
|
1458
|
+
for (const field of computedFields) {
|
|
1459
|
+
excludeFields.push(`'${field}'`);
|
|
1460
|
+
}
|
|
991
1461
|
const omitType = excludeFields.length > 0 ? `Omit<${schemaName}, ${excludeFields.join(" | ")}>` : schemaName;
|
|
992
1462
|
parts.push(`
|
|
993
1463
|
/** For creating new ${schemaName} (POST requests) */`);
|
|
@@ -1022,6 +1492,10 @@ function generateBaseInterfaceFile(schemaName, schemas, options) {
|
|
|
1022
1492
|
throw new Error(`Interface not found for schema: ${schemaName}`);
|
|
1023
1493
|
}
|
|
1024
1494
|
const parts = [generateBaseHeader()];
|
|
1495
|
+
if (options.generateZodSchemas) {
|
|
1496
|
+
parts.push(`import { z } from 'zod';
|
|
1497
|
+
`);
|
|
1498
|
+
}
|
|
1025
1499
|
const dateImports = needsDateTimeImports(iface);
|
|
1026
1500
|
const commonImports = [];
|
|
1027
1501
|
if (dateImports.dateTime) commonImports.push("DateTimeString");
|
|
@@ -1036,12 +1510,20 @@ function generateBaseInterfaceFile(schemaName, schemas, options) {
|
|
|
1036
1510
|
`);
|
|
1037
1511
|
}
|
|
1038
1512
|
parts.push("\n");
|
|
1039
|
-
} else if (commonImports.length > 0) {
|
|
1513
|
+
} else if (commonImports.length > 0 || options.generateZodSchemas) {
|
|
1040
1514
|
parts.push("\n");
|
|
1041
1515
|
}
|
|
1042
1516
|
parts.push(formatInterface(iface));
|
|
1043
1517
|
parts.push("\n");
|
|
1044
|
-
|
|
1518
|
+
if (options.generateZodSchemas) {
|
|
1519
|
+
const zodSchemas = generateZodSchemas(schema, options);
|
|
1520
|
+
const displayNames = generateDisplayNames(schema, options);
|
|
1521
|
+
const excludedFields = getExcludedFields(schema, options.customTypes);
|
|
1522
|
+
parts.push("\n");
|
|
1523
|
+
parts.push(formatZodSchemasSection(schemaName, zodSchemas, displayNames, excludedFields));
|
|
1524
|
+
} else {
|
|
1525
|
+
parts.push(generateUtilityTypes(schemaName, schema, options.customTypes));
|
|
1526
|
+
}
|
|
1045
1527
|
return {
|
|
1046
1528
|
filePath: `base/${schemaName}.ts`,
|
|
1047
1529
|
content: parts.join(""),
|
|
@@ -1071,7 +1553,16 @@ function generateTypeAliasFile(alias) {
|
|
|
1071
1553
|
overwrite: true
|
|
1072
1554
|
};
|
|
1073
1555
|
}
|
|
1074
|
-
function generateModelFile(schemaName) {
|
|
1556
|
+
function generateModelFile(schemaName, options) {
|
|
1557
|
+
if (options.generateZodSchemas) {
|
|
1558
|
+
return {
|
|
1559
|
+
filePath: `${schemaName}.ts`,
|
|
1560
|
+
content: formatZodModelFile(schemaName),
|
|
1561
|
+
types: [schemaName],
|
|
1562
|
+
overwrite: false
|
|
1563
|
+
// Never overwrite user models
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1075
1566
|
const parts = [generateModelHeader(schemaName)];
|
|
1076
1567
|
parts.push(`import type { ${schemaName} as ${schemaName}Base } from './base/${schemaName}.js';
|
|
1077
1568
|
|
|
@@ -1191,33 +1682,63 @@ function generateIndexFile(schemas, enums, typeAliases, options) {
|
|
|
1191
1682
|
}
|
|
1192
1683
|
parts.push("\n");
|
|
1193
1684
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
for (const schema of Object.values(schemas)) {
|
|
1197
|
-
if (schema.kind === "enum") continue;
|
|
1198
|
-
if (schema.options?.hidden === true) continue;
|
|
1199
|
-
parts.push(`export type { ${schema.name} } from './${schema.name}.js';
|
|
1200
|
-
`);
|
|
1201
|
-
parts.push(`export type { ${schema.name}Create, ${schema.name}Update } from './base/${schema.name}.js';
|
|
1202
|
-
`);
|
|
1203
|
-
}
|
|
1204
|
-
if (options.generateRules) {
|
|
1205
|
-
parts.push(`
|
|
1206
|
-
// Validation Rules
|
|
1685
|
+
if (options.generateZodSchemas) {
|
|
1686
|
+
parts.push(`// Models (with Zod schemas and Create/Update types)
|
|
1207
1687
|
`);
|
|
1208
1688
|
for (const schema of Object.values(schemas)) {
|
|
1209
1689
|
if (schema.kind === "enum") continue;
|
|
1210
1690
|
if (schema.options?.hidden === true) continue;
|
|
1691
|
+
const lowerName = schema.name.charAt(0).toLowerCase() + schema.name.slice(1);
|
|
1692
|
+
parts.push(`export type { ${schema.name}, ${schema.name}Create, ${schema.name}Update } from './${schema.name}.js';
|
|
1693
|
+
`);
|
|
1211
1694
|
parts.push(`export {
|
|
1212
1695
|
`);
|
|
1213
|
-
parts.push(`
|
|
1696
|
+
parts.push(` ${lowerName}Schemas,
|
|
1697
|
+
`);
|
|
1698
|
+
parts.push(` ${lowerName}CreateSchema,
|
|
1699
|
+
`);
|
|
1700
|
+
parts.push(` ${lowerName}UpdateSchema,
|
|
1701
|
+
`);
|
|
1702
|
+
parts.push(` ${schema.name}DisplayName,
|
|
1703
|
+
`);
|
|
1704
|
+
parts.push(` ${schema.name}PropertyDisplayNames,
|
|
1214
1705
|
`);
|
|
1215
1706
|
parts.push(` get${schema.name}DisplayName,
|
|
1216
1707
|
`);
|
|
1217
1708
|
parts.push(` get${schema.name}PropertyDisplayName,
|
|
1218
1709
|
`);
|
|
1219
|
-
parts.push(`} from '
|
|
1710
|
+
parts.push(`} from './${schema.name}.js';
|
|
1711
|
+
`);
|
|
1712
|
+
}
|
|
1713
|
+
} else {
|
|
1714
|
+
parts.push(`// Models (with Create/Update utility types)
|
|
1715
|
+
`);
|
|
1716
|
+
for (const schema of Object.values(schemas)) {
|
|
1717
|
+
if (schema.kind === "enum") continue;
|
|
1718
|
+
if (schema.options?.hidden === true) continue;
|
|
1719
|
+
parts.push(`export type { ${schema.name} } from './${schema.name}.js';
|
|
1720
|
+
`);
|
|
1721
|
+
parts.push(`export type { ${schema.name}Create, ${schema.name}Update } from './base/${schema.name}.js';
|
|
1722
|
+
`);
|
|
1723
|
+
}
|
|
1724
|
+
if (options.generateRules) {
|
|
1725
|
+
parts.push(`
|
|
1726
|
+
// Validation Rules
|
|
1220
1727
|
`);
|
|
1728
|
+
for (const schema of Object.values(schemas)) {
|
|
1729
|
+
if (schema.kind === "enum") continue;
|
|
1730
|
+
if (schema.options?.hidden === true) continue;
|
|
1731
|
+
parts.push(`export {
|
|
1732
|
+
`);
|
|
1733
|
+
parts.push(` get${schema.name}Rules,
|
|
1734
|
+
`);
|
|
1735
|
+
parts.push(` get${schema.name}DisplayName,
|
|
1736
|
+
`);
|
|
1737
|
+
parts.push(` get${schema.name}PropertyDisplayName,
|
|
1738
|
+
`);
|
|
1739
|
+
parts.push(`} from './rules/${schema.name}.rules.js';
|
|
1740
|
+
`);
|
|
1741
|
+
}
|
|
1221
1742
|
}
|
|
1222
1743
|
}
|
|
1223
1744
|
return {
|
|
@@ -1246,9 +1767,9 @@ function generateTypeScript(schemas, options = {}) {
|
|
|
1246
1767
|
for (const schema of Object.values(schemas)) {
|
|
1247
1768
|
if (schema.kind === "enum") continue;
|
|
1248
1769
|
if (schema.options?.hidden === true) continue;
|
|
1249
|
-
files.push(generateModelFile(schema.name));
|
|
1770
|
+
files.push(generateModelFile(schema.name, opts));
|
|
1250
1771
|
}
|
|
1251
|
-
if (opts.generateRules) {
|
|
1772
|
+
if (!opts.generateZodSchemas && opts.generateRules) {
|
|
1252
1773
|
const rulesFiles = generateRulesFiles(schemas, opts);
|
|
1253
1774
|
files.push(...rulesFiles);
|
|
1254
1775
|
}
|