hekireki 0.7.0 → 0.7.2
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/README.md +282 -14
- package/dist/generator/ajv/index.d.ts +6 -0
- package/dist/generator/ajv/index.js +87 -0
- package/dist/generator/arktype/index.js +17 -3
- package/dist/generator/dbml/index.js +43 -33
- package/dist/generator/drizzle/index.js +15 -24
- package/dist/generator/ecto/index.js +34 -9
- package/dist/generator/effect/index.js +17 -3
- package/dist/generator/gorm/index.d.ts +6 -0
- package/dist/generator/gorm/index.js +370 -0
- package/dist/generator/mermaid-er/index.js +6 -12
- package/dist/generator/sea-orm/index.d.ts +6 -0
- package/dist/generator/sea-orm/index.js +444 -0
- package/dist/generator/sqlalchemy/index.d.ts +6 -0
- package/dist/generator/sqlalchemy/index.js +458 -0
- package/dist/generator/typebox/index.d.ts +6 -0
- package/dist/generator/typebox/index.js +93 -0
- package/dist/generator/valibot/index.js +15 -5
- package/dist/generator/zod/index.js +15 -5
- package/dist/{prisma-Cc0YxSiO.js → prisma-ChsFqlYX.js} +6 -6
- package/dist/utils-COHZyQue.js +116 -0
- package/package.json +18 -7
- package/dist/utils-DeZn2r_T.js +0 -287
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { d as mkdir, f as writeFile, n as getString, o as makeSnakeCase } from "../../utils-COHZyQue.js";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import pkg from "@prisma/generator-helper";
|
|
5
|
+
|
|
6
|
+
//#region src/helper/sea-orm.ts
|
|
7
|
+
const PRISMA_TO_RUST = {
|
|
8
|
+
String: "String",
|
|
9
|
+
Int: "i32",
|
|
10
|
+
BigInt: "i64",
|
|
11
|
+
Float: "f64",
|
|
12
|
+
Decimal: "Decimal",
|
|
13
|
+
Boolean: "bool",
|
|
14
|
+
DateTime: "DateTimeUtc",
|
|
15
|
+
Json: "Json",
|
|
16
|
+
Bytes: "Vec<u8>"
|
|
17
|
+
};
|
|
18
|
+
function prismaTypeToRustType(type, isRequired) {
|
|
19
|
+
const base = PRISMA_TO_RUST[type] ?? "String";
|
|
20
|
+
if (!isRequired) return `Option<${base}>`;
|
|
21
|
+
return base;
|
|
22
|
+
}
|
|
23
|
+
function resolveSeaOrmColumnType(field) {
|
|
24
|
+
if (!field.nativeType) return null;
|
|
25
|
+
const [nativeName, nativeArgs] = field.nativeType;
|
|
26
|
+
const args = nativeArgs ?? [];
|
|
27
|
+
switch (nativeName) {
|
|
28
|
+
case "VarChar":
|
|
29
|
+
case "Char": return args.length > 0 ? `String(StringLen::N(${args[0]}))` : null;
|
|
30
|
+
case "Text":
|
|
31
|
+
case "MediumText":
|
|
32
|
+
case "LongText":
|
|
33
|
+
case "TinyText": return "Text";
|
|
34
|
+
case "SmallInt":
|
|
35
|
+
case "TinyInt": return "SmallInteger";
|
|
36
|
+
case "MediumInt": return "Integer";
|
|
37
|
+
case "DoublePrecision":
|
|
38
|
+
case "Double":
|
|
39
|
+
case "Real": return "Double";
|
|
40
|
+
case "Decimal":
|
|
41
|
+
case "Money": return args.length >= 2 ? `Decimal(Some((${args[0]}, ${args[1]})))` : "Decimal(None)";
|
|
42
|
+
case "Uuid": return "Uuid";
|
|
43
|
+
case "Timestamp":
|
|
44
|
+
case "Timestamptz": return "TimestampWithTimeZone";
|
|
45
|
+
case "Date": return "Date";
|
|
46
|
+
case "Time":
|
|
47
|
+
case "Timetz": return "Time";
|
|
48
|
+
case "JsonB": return "JsonBinary";
|
|
49
|
+
default: return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function isFunctionDefault(def) {
|
|
53
|
+
return def !== null && typeof def === "object" && "name" in def;
|
|
54
|
+
}
|
|
55
|
+
function isAutoincrement(field) {
|
|
56
|
+
return isFunctionDefault(field.default) && field.default.name === "autoincrement";
|
|
57
|
+
}
|
|
58
|
+
function formatRustDefault(def) {
|
|
59
|
+
if (def === void 0 || def === null) return null;
|
|
60
|
+
if (typeof def === "boolean") return def ? "true" : "false";
|
|
61
|
+
if (typeof def === "number") return String(def);
|
|
62
|
+
if (typeof def === "string") return `"${def}"`;
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
function buildSeaOrmAttributes(field, isPk, isCompositePk) {
|
|
66
|
+
const attrs = [];
|
|
67
|
+
if (isPk) {
|
|
68
|
+
const parts = ["primary_key"];
|
|
69
|
+
if (!isAutoincrement(field)) parts.push("auto_increment = false");
|
|
70
|
+
attrs.push(`#[sea_orm(${parts.join(", ")})]`);
|
|
71
|
+
}
|
|
72
|
+
if (field.isUnique) attrs.push("#[sea_orm(unique)]");
|
|
73
|
+
const columnParts = [];
|
|
74
|
+
const columnName = field.dbName ?? makeSnakeCase(field.name);
|
|
75
|
+
if (columnName !== makeSnakeCase(field.name)) columnParts.push(`column_name = "${columnName}"`);
|
|
76
|
+
const colType = resolveSeaOrmColumnType(field);
|
|
77
|
+
if (colType) columnParts.push(`column_type = "${colType}"`);
|
|
78
|
+
if (!isPk || isCompositePk) {
|
|
79
|
+
if (!(field.type === "DateTime" && isFunctionDefault(field.default) && field.default.name === "now" || field.isUpdatedAt)) {
|
|
80
|
+
const defaultVal = formatRustDefault(field.default);
|
|
81
|
+
if (defaultVal !== null) columnParts.push(`default_value = ${defaultVal}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (columnParts.length > 0) attrs.push(`#[sea_orm(${columnParts.join(", ")})]`);
|
|
85
|
+
return attrs;
|
|
86
|
+
}
|
|
87
|
+
function getAssociations(model, allModels) {
|
|
88
|
+
const belongsTo = [];
|
|
89
|
+
const hasMany = [];
|
|
90
|
+
const hasOne = [];
|
|
91
|
+
const manyToMany = [];
|
|
92
|
+
for (const field of model.fields) {
|
|
93
|
+
if (field.kind !== "object") continue;
|
|
94
|
+
if (field.relationFromFields && field.relationFromFields.length > 0) belongsTo.push({
|
|
95
|
+
name: field.name,
|
|
96
|
+
targetModel: field.type,
|
|
97
|
+
foreignKey: field.relationFromFields[0],
|
|
98
|
+
references: field.relationToFields?.[0] ?? "id"
|
|
99
|
+
});
|
|
100
|
+
else if (field.isList) {
|
|
101
|
+
const targetModel = allModels.find((m) => m.name === field.type);
|
|
102
|
+
if (!targetModel) continue;
|
|
103
|
+
if (targetModel.fields.find((f) => f.relationName === field.relationName && f.kind === "object")?.isList) manyToMany.push({
|
|
104
|
+
name: field.name,
|
|
105
|
+
targetModel: field.type,
|
|
106
|
+
relationName: field.relationName ?? `${model.name}To${field.type}`
|
|
107
|
+
});
|
|
108
|
+
else {
|
|
109
|
+
const fkField = targetModel.fields.find((f) => f.relationName === field.relationName && f.relationFromFields && f.relationFromFields.length > 0);
|
|
110
|
+
const foreignKey = fkField?.relationFromFields?.[0];
|
|
111
|
+
if (!foreignKey) continue;
|
|
112
|
+
const references = fkField?.relationToFields?.[0] ?? "id";
|
|
113
|
+
hasMany.push({
|
|
114
|
+
name: field.name,
|
|
115
|
+
targetModel: field.type,
|
|
116
|
+
foreignKey,
|
|
117
|
+
references,
|
|
118
|
+
isList: true
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
const targetModel = allModels.find((m) => m.name === field.type);
|
|
123
|
+
if (!targetModel) continue;
|
|
124
|
+
const fkField = targetModel.fields.find((f) => f.relationName === field.relationName && f.relationFromFields && f.relationFromFields.length > 0);
|
|
125
|
+
const foreignKey = fkField?.relationFromFields?.[0];
|
|
126
|
+
if (!foreignKey) continue;
|
|
127
|
+
const references = fkField?.relationToFields?.[0] ?? "id";
|
|
128
|
+
hasOne.push({
|
|
129
|
+
name: field.name,
|
|
130
|
+
targetModel: field.type,
|
|
131
|
+
foreignKey,
|
|
132
|
+
references,
|
|
133
|
+
isList: false
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
belongsTo,
|
|
139
|
+
hasMany,
|
|
140
|
+
hasOne,
|
|
141
|
+
manyToMany
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function toSnakeCase(name) {
|
|
145
|
+
return makeSnakeCase(name);
|
|
146
|
+
}
|
|
147
|
+
function toPascalCase(name) {
|
|
148
|
+
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
149
|
+
}
|
|
150
|
+
function toModuleName(modelName) {
|
|
151
|
+
return toSnakeCase(modelName);
|
|
152
|
+
}
|
|
153
|
+
const NON_EQ_PRISMA_TYPES = new Set(["Float"]);
|
|
154
|
+
function canDeriveEq(fields) {
|
|
155
|
+
return fields.filter((f) => f.kind !== "object").every((f) => !NON_EQ_PRISMA_TYPES.has(f.type));
|
|
156
|
+
}
|
|
157
|
+
function buildSerdeAttributes(opts) {
|
|
158
|
+
const parts = [];
|
|
159
|
+
if (opts.renameAll) parts.push(`rename_all = "${opts.renameAll}"`);
|
|
160
|
+
if (parts.length === 0) return [];
|
|
161
|
+
return [`#[serde(${parts.join(", ")})]`];
|
|
162
|
+
}
|
|
163
|
+
function generateEnum(e, serde = {}) {
|
|
164
|
+
const variants = e.values.map((v) => {
|
|
165
|
+
const pascalName = v.name.charAt(0).toUpperCase() + v.name.slice(1).toLowerCase();
|
|
166
|
+
return ` #[sea_orm(string_value = "${v.name}")]\n ${pascalName},`;
|
|
167
|
+
});
|
|
168
|
+
return [
|
|
169
|
+
"#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]",
|
|
170
|
+
...buildSerdeAttributes(serde),
|
|
171
|
+
"#[sea_orm(rs_type = \"String\", db_type = \"String(StringLen::None)\")]",
|
|
172
|
+
`pub enum ${e.name} {`,
|
|
173
|
+
...variants,
|
|
174
|
+
"}"
|
|
175
|
+
].join("\n");
|
|
176
|
+
}
|
|
177
|
+
function generateRelationEnum(_model, associations) {
|
|
178
|
+
if (!(associations.belongsTo.length > 0 || associations.hasMany.length > 0 || associations.hasOne.length > 0)) return ["#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]", "pub enum Relation {}"].join("\n");
|
|
179
|
+
const variants = [];
|
|
180
|
+
for (const assoc of associations.belongsTo) {
|
|
181
|
+
const variantName = toPascalCase(assoc.name);
|
|
182
|
+
const targetModule = toModuleName(assoc.targetModel);
|
|
183
|
+
const fromCol = toPascalCase(assoc.foreignKey);
|
|
184
|
+
const toCol = toPascalCase(assoc.references);
|
|
185
|
+
variants.push(` #[sea_orm(\n belongs_to = "super::${targetModule}::Entity",\n from = "Column::${fromCol}",\n to = "super::${targetModule}::Column::${toCol}"\n )]\n ${variantName},`);
|
|
186
|
+
}
|
|
187
|
+
for (const assoc of associations.hasMany) {
|
|
188
|
+
const variantName = toPascalCase(assoc.name);
|
|
189
|
+
const targetModule = toModuleName(assoc.targetModel);
|
|
190
|
+
variants.push(` #[sea_orm(has_many = "super::${targetModule}::Entity")]\n ${variantName},`);
|
|
191
|
+
}
|
|
192
|
+
for (const assoc of associations.hasOne) {
|
|
193
|
+
const variantName = toPascalCase(assoc.name);
|
|
194
|
+
const targetModule = toModuleName(assoc.targetModel);
|
|
195
|
+
variants.push(` #[sea_orm(has_one = "super::${targetModule}::Entity")]\n ${variantName},`);
|
|
196
|
+
}
|
|
197
|
+
return [
|
|
198
|
+
"#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]",
|
|
199
|
+
"pub enum Relation {",
|
|
200
|
+
...variants,
|
|
201
|
+
"}"
|
|
202
|
+
].join("\n");
|
|
203
|
+
}
|
|
204
|
+
function generateRelatedImpls(model, associations) {
|
|
205
|
+
const impls = [];
|
|
206
|
+
const m2mTargets = new Set(associations.manyToMany.map((a) => a.targetModel));
|
|
207
|
+
for (const assoc of associations.belongsTo) {
|
|
208
|
+
if (m2mTargets.has(assoc.targetModel)) continue;
|
|
209
|
+
const targetModule = toModuleName(assoc.targetModel);
|
|
210
|
+
impls.push([
|
|
211
|
+
`impl Related<super::${targetModule}::Entity> for Entity {`,
|
|
212
|
+
" fn to() -> RelationDef {",
|
|
213
|
+
` Relation::${toPascalCase(assoc.name)}.def()`,
|
|
214
|
+
" }",
|
|
215
|
+
"}"
|
|
216
|
+
].join("\n"));
|
|
217
|
+
}
|
|
218
|
+
for (const assoc of associations.hasMany) {
|
|
219
|
+
if (m2mTargets.has(assoc.targetModel)) continue;
|
|
220
|
+
const targetModule = toModuleName(assoc.targetModel);
|
|
221
|
+
impls.push([
|
|
222
|
+
`impl Related<super::${targetModule}::Entity> for Entity {`,
|
|
223
|
+
" fn to() -> RelationDef {",
|
|
224
|
+
` Relation::${toPascalCase(assoc.name)}.def()`,
|
|
225
|
+
" }",
|
|
226
|
+
"}"
|
|
227
|
+
].join("\n"));
|
|
228
|
+
}
|
|
229
|
+
for (const assoc of associations.hasOne) {
|
|
230
|
+
if (m2mTargets.has(assoc.targetModel)) continue;
|
|
231
|
+
const targetModule = toModuleName(assoc.targetModel);
|
|
232
|
+
impls.push([
|
|
233
|
+
`impl Related<super::${targetModule}::Entity> for Entity {`,
|
|
234
|
+
" fn to() -> RelationDef {",
|
|
235
|
+
` Relation::${toPascalCase(assoc.name)}.def()`,
|
|
236
|
+
" }",
|
|
237
|
+
"}"
|
|
238
|
+
].join("\n"));
|
|
239
|
+
}
|
|
240
|
+
for (const assoc of associations.manyToMany) {
|
|
241
|
+
const targetModule = toModuleName(assoc.targetModel);
|
|
242
|
+
const [leftName, rightName] = model.name < assoc.targetModel ? [model.name, assoc.targetModel] : [assoc.targetModel, model.name];
|
|
243
|
+
const junctionModule = toSnakeCase(`${leftName}To${rightName}`);
|
|
244
|
+
const junctionRelToTarget = toPascalCase(assoc.targetModel);
|
|
245
|
+
const junctionRelToSelf = toPascalCase(model.name);
|
|
246
|
+
impls.push([
|
|
247
|
+
`impl Related<super::${targetModule}::Entity> for Entity {`,
|
|
248
|
+
" fn to() -> RelationDef {",
|
|
249
|
+
` super::${junctionModule}::Relation::${junctionRelToTarget}.def()`,
|
|
250
|
+
" }",
|
|
251
|
+
" fn via() -> Option<RelationDef> {",
|
|
252
|
+
` Some(super::${junctionModule}::Relation::${junctionRelToSelf}.def().rev())`,
|
|
253
|
+
" }",
|
|
254
|
+
"}"
|
|
255
|
+
].join("\n"));
|
|
256
|
+
}
|
|
257
|
+
return impls;
|
|
258
|
+
}
|
|
259
|
+
function generateEntityFile(model, allModels, enums, serde = {}) {
|
|
260
|
+
const idField = model.fields.find((f) => f.isId);
|
|
261
|
+
const compositePkFieldNames = new Set(model.primaryKey?.fields ?? []);
|
|
262
|
+
const isCompositePk = !idField && compositePkFieldNames.size > 0;
|
|
263
|
+
if (!(idField || isCompositePk)) return "";
|
|
264
|
+
const tableName = model.dbName ?? toSnakeCase(model.name);
|
|
265
|
+
const associations = getAssociations(model, allModels);
|
|
266
|
+
const enumNames = new Set(enums.map((e) => e.name));
|
|
267
|
+
const scalarFields = model.fields.filter((f) => f.kind !== "object");
|
|
268
|
+
const fieldLines = [];
|
|
269
|
+
for (const field of scalarFields) {
|
|
270
|
+
const attrs = buildSeaOrmAttributes(field, field.isId || compositePkFieldNames.has(field.name), isCompositePk);
|
|
271
|
+
let rustType;
|
|
272
|
+
if (enumNames.has(field.type)) rustType = field.isRequired ? field.type : `Option<${field.type}>`;
|
|
273
|
+
else rustType = prismaTypeToRustType(field.type, field.isRequired);
|
|
274
|
+
const fieldName = toSnakeCase(field.name);
|
|
275
|
+
for (const attr of attrs) fieldLines.push(` ${attr}`);
|
|
276
|
+
fieldLines.push(` pub ${fieldName}: ${rustType},`);
|
|
277
|
+
}
|
|
278
|
+
const relationEnum = generateRelationEnum(model, associations);
|
|
279
|
+
const relatedImpls = generateRelatedImpls(model, associations);
|
|
280
|
+
const useLines = ["use sea_orm::entity::prelude::*;", "use serde::{Deserialize, Serialize};"];
|
|
281
|
+
const deriveModel = canDeriveEq(scalarFields) ? "#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]" : "#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]";
|
|
282
|
+
const serdeAttrs = buildSerdeAttributes(serde);
|
|
283
|
+
return [
|
|
284
|
+
...useLines,
|
|
285
|
+
"",
|
|
286
|
+
deriveModel,
|
|
287
|
+
...serdeAttrs,
|
|
288
|
+
`#[sea_orm(table_name = "${tableName}")]`,
|
|
289
|
+
"pub struct Model {",
|
|
290
|
+
...fieldLines,
|
|
291
|
+
"}",
|
|
292
|
+
"",
|
|
293
|
+
relationEnum,
|
|
294
|
+
"",
|
|
295
|
+
...relatedImpls.map((impl) => `${impl}\n`),
|
|
296
|
+
"impl ActiveModelBehavior for ActiveModel {}"
|
|
297
|
+
].join("\n");
|
|
298
|
+
}
|
|
299
|
+
function generateM2MEntity(leftModel, rightModel, _allModels, serde = {}) {
|
|
300
|
+
const [sortedLeft, sortedRight] = leftModel < rightModel ? [leftModel, rightModel] : [rightModel, leftModel];
|
|
301
|
+
const tableName = `_${sortedLeft}To${sortedRight}`;
|
|
302
|
+
const leftModule = toModuleName(sortedLeft);
|
|
303
|
+
const rightModule = toModuleName(sortedRight);
|
|
304
|
+
const leftFk = `${toSnakeCase(sortedLeft)}_id`;
|
|
305
|
+
const rightFk = `${toSnakeCase(sortedRight)}_id`;
|
|
306
|
+
const leftCol = toPascalCase(`${toSnakeCase(sortedLeft)}Id`);
|
|
307
|
+
const rightCol = toPascalCase(`${toSnakeCase(sortedRight)}Id`);
|
|
308
|
+
const useLines = ["use sea_orm::entity::prelude::*;", "use serde::{Deserialize, Serialize};"];
|
|
309
|
+
const deriveModel = "#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]";
|
|
310
|
+
const serdeAttrs = buildSerdeAttributes(serde);
|
|
311
|
+
return [
|
|
312
|
+
...useLines,
|
|
313
|
+
"",
|
|
314
|
+
deriveModel,
|
|
315
|
+
...serdeAttrs,
|
|
316
|
+
`#[sea_orm(table_name = "${tableName}")]`,
|
|
317
|
+
"pub struct Model {",
|
|
318
|
+
" #[sea_orm(primary_key, auto_increment = false)]",
|
|
319
|
+
` pub ${leftFk}: String,`,
|
|
320
|
+
" #[sea_orm(primary_key, auto_increment = false)]",
|
|
321
|
+
` pub ${rightFk}: String,`,
|
|
322
|
+
"}",
|
|
323
|
+
"",
|
|
324
|
+
"#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]",
|
|
325
|
+
"pub enum Relation {",
|
|
326
|
+
" #[sea_orm(",
|
|
327
|
+
` belongs_to = "super::${leftModule}::Entity",`,
|
|
328
|
+
` from = "Column::${leftCol}",`,
|
|
329
|
+
` to = "super::${leftModule}::Column::Id"`,
|
|
330
|
+
" )]",
|
|
331
|
+
` ${sortedLeft},`,
|
|
332
|
+
" #[sea_orm(",
|
|
333
|
+
` belongs_to = "super::${rightModule}::Entity",`,
|
|
334
|
+
` from = "Column::${rightCol}",`,
|
|
335
|
+
` to = "super::${rightModule}::Column::Id"`,
|
|
336
|
+
" )]",
|
|
337
|
+
` ${sortedRight},`,
|
|
338
|
+
"}",
|
|
339
|
+
"",
|
|
340
|
+
"impl ActiveModelBehavior for ActiveModel {}"
|
|
341
|
+
].join("\n");
|
|
342
|
+
}
|
|
343
|
+
function generateModRs(moduleNames) {
|
|
344
|
+
return `${moduleNames.map((m) => `pub mod ${m};`).join("\n")}\n`;
|
|
345
|
+
}
|
|
346
|
+
function generatePreludeRs(models) {
|
|
347
|
+
return `${models.map((m) => {
|
|
348
|
+
return `pub use super::${toModuleName(m.name)}::Entity as ${m.name};`;
|
|
349
|
+
}).join("\n")}\n`;
|
|
350
|
+
}
|
|
351
|
+
async function writeSeaOrmFiles(models, outDir, enums, serde = {}) {
|
|
352
|
+
const mkdirResult = await mkdir(outDir);
|
|
353
|
+
if (!mkdirResult.ok) return mkdirResult;
|
|
354
|
+
const moduleNames = [];
|
|
355
|
+
const m2mJunctions = /* @__PURE__ */ new Set();
|
|
356
|
+
const m2mPairs = [];
|
|
357
|
+
for (const model of models) {
|
|
358
|
+
const associations = getAssociations(model, models);
|
|
359
|
+
for (const assoc of associations.manyToMany) {
|
|
360
|
+
const [left, right] = model.name < assoc.targetModel ? [model.name, assoc.targetModel] : [assoc.targetModel, model.name];
|
|
361
|
+
const key = `${left}_${right}`;
|
|
362
|
+
if (!m2mJunctions.has(key)) {
|
|
363
|
+
m2mJunctions.add(key);
|
|
364
|
+
m2mPairs.push({
|
|
365
|
+
left,
|
|
366
|
+
right
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
for (const e of enums) {
|
|
372
|
+
const moduleName = toSnakeCase(e.name);
|
|
373
|
+
const code = [
|
|
374
|
+
...["use sea_orm::entity::prelude::*;", "use serde::{Deserialize, Serialize};"],
|
|
375
|
+
"",
|
|
376
|
+
generateEnum(e, serde),
|
|
377
|
+
""
|
|
378
|
+
].join("\n");
|
|
379
|
+
const filePath = join(outDir, `${moduleName}.rs`);
|
|
380
|
+
const writeResult = await writeFile(filePath, code);
|
|
381
|
+
if (!writeResult.ok) return writeResult;
|
|
382
|
+
moduleNames.push(moduleName);
|
|
383
|
+
console.log(`wrote ${filePath}`);
|
|
384
|
+
}
|
|
385
|
+
for (const model of models) {
|
|
386
|
+
const code = generateEntityFile(model, models, enums, serde);
|
|
387
|
+
if (!code.trim()) continue;
|
|
388
|
+
const moduleName = toModuleName(model.name);
|
|
389
|
+
const filePath = join(outDir, `${moduleName}.rs`);
|
|
390
|
+
const writeResult = await writeFile(filePath, code);
|
|
391
|
+
if (!writeResult.ok) return writeResult;
|
|
392
|
+
moduleNames.push(moduleName);
|
|
393
|
+
console.log(`wrote ${filePath}`);
|
|
394
|
+
}
|
|
395
|
+
for (const pair of m2mPairs) {
|
|
396
|
+
const moduleName = toSnakeCase(`${pair.left}To${pair.right}`);
|
|
397
|
+
const code = generateM2MEntity(pair.left, pair.right, models, serde);
|
|
398
|
+
const filePath = join(outDir, `${moduleName}.rs`);
|
|
399
|
+
const writeResult = await writeFile(filePath, code);
|
|
400
|
+
if (!writeResult.ok) return writeResult;
|
|
401
|
+
moduleNames.push(moduleName);
|
|
402
|
+
console.log(`wrote ${filePath}`);
|
|
403
|
+
}
|
|
404
|
+
const preludeCode = generatePreludeRs(models);
|
|
405
|
+
const preludePath = join(outDir, "prelude.rs");
|
|
406
|
+
const preludeResult = await writeFile(preludePath, preludeCode);
|
|
407
|
+
if (!preludeResult.ok) return preludeResult;
|
|
408
|
+
moduleNames.push("prelude");
|
|
409
|
+
console.log(`wrote ${preludePath}`);
|
|
410
|
+
moduleNames.sort();
|
|
411
|
+
const modCode = generateModRs(moduleNames);
|
|
412
|
+
const modPath = join(outDir, "mod.rs");
|
|
413
|
+
const modResult = await writeFile(modPath, modCode);
|
|
414
|
+
if (!modResult.ok) return modResult;
|
|
415
|
+
console.log(`wrote ${modPath}`);
|
|
416
|
+
return {
|
|
417
|
+
ok: true,
|
|
418
|
+
value: void 0
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
//#endregion
|
|
423
|
+
//#region src/generator/sea-orm/index.ts
|
|
424
|
+
const { generatorHandler } = pkg;
|
|
425
|
+
async function main(options) {
|
|
426
|
+
if (!(options.generator.isCustomOutput && options.generator.output?.value)) throw new Error("output is required for Hekireki-SeaORM. Please specify output in your generator config.");
|
|
427
|
+
const output = options.generator.output.value;
|
|
428
|
+
const serde = { renameAll: getString(options.generator.config?.renameAll) };
|
|
429
|
+
const enums = options.dmmf.datamodel.enums;
|
|
430
|
+
const result = await writeSeaOrmFiles(options.dmmf.datamodel.models, output, enums, serde);
|
|
431
|
+
if (!result.ok) throw new Error(`Failed to write SeaORM entities: ${result.error}`);
|
|
432
|
+
}
|
|
433
|
+
generatorHandler({
|
|
434
|
+
onManifest() {
|
|
435
|
+
return {
|
|
436
|
+
defaultOutput: ".",
|
|
437
|
+
prettyName: "Hekireki-SeaORM"
|
|
438
|
+
};
|
|
439
|
+
},
|
|
440
|
+
onGenerate: main
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
//#endregion
|
|
444
|
+
export { main };
|