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.
@@ -1,19 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as fmt } from "../../format-CzXgkLDe.js";
3
- import { N as mkdir, P as writeFile, b as makeSnakeCase } from "../../utils-DeZn2r_T.js";
3
+ import { d as mkdir, f as writeFile, o as makeSnakeCase } from "../../utils-COHZyQue.js";
4
4
  import path from "node:path";
5
5
  import pkg from "@prisma/generator-helper";
6
6
 
7
7
  //#region src/helper/drizzle.ts
8
- function resolveProvider(provider) {
9
- switch (provider) {
10
- case "postgresql":
11
- case "cockroachdb": return "postgresql";
12
- case "mysql": return "mysql";
13
- case "sqlite": return "sqlite";
14
- default: throw new Error(`Unsupported provider: ${provider}`);
15
- }
16
- }
17
8
  const PG_SCALAR_MAP = {
18
9
  String: "text()",
19
10
  Int: "integer()",
@@ -140,13 +131,6 @@ function toCamelCase(name) {
140
131
  function isFieldDefault(v) {
141
132
  return typeof v === "object" && v !== null && "name" in v;
142
133
  }
143
- function insertColName(expr, colName) {
144
- const parenIdx = expr.indexOf("(");
145
- if (parenIdx === -1) return expr;
146
- const fnName = expr.slice(0, parenIdx);
147
- const rest = expr.slice(parenIdx + 1);
148
- return rest === ")" ? `${fnName}('${colName}')` : `${fnName}('${colName}', ${rest}`;
149
- }
150
134
  function resolveScalarType(field, provider) {
151
135
  if (field.nativeType && provider !== "sqlite") {
152
136
  const [nativeName, nativeArgs] = field.nativeType;
@@ -179,7 +163,11 @@ function makeColumnExpr(field, provider, imports, enums) {
179
163
  const baseExpr = resolveScalarType(field, provider);
180
164
  const fnName = baseExpr.match(/^(\w+)/)?.[1];
181
165
  if (fnName) imports.addCore(fnName);
182
- return insertColName(baseExpr, colName);
166
+ const parenIdx = baseExpr.indexOf("(");
167
+ if (parenIdx === -1) return baseExpr;
168
+ const baseFnName = baseExpr.slice(0, parenIdx);
169
+ const rest = baseExpr.slice(parenIdx + 1);
170
+ return rest === ")" ? `${baseFnName}('${colName}')` : `${baseFnName}('${colName}', ${rest}`;
183
171
  }
184
172
  function makeDefaultChain(dflt, fieldType, provider, imports) {
185
173
  if (dflt === void 0 || dflt === null) return "";
@@ -228,9 +216,6 @@ function makeColumn(field, model, provider, imports, enums) {
228
216
  ].join("");
229
217
  return `${field.name}: ${colExpr}${chain}`;
230
218
  }
231
- function makeEnums() {
232
- return [];
233
- }
234
219
  function makeCompositeConstraints(model, imports, indexes) {
235
220
  const pkLine = model.primaryKey ? (() => {
236
221
  imports.addCore("primaryKey");
@@ -291,9 +276,16 @@ function makeRelations(models, imports) {
291
276
  });
292
277
  }
293
278
  function drizzleSchema(datamodel, provider, indexes) {
294
- const db = resolveProvider(provider);
279
+ const db = (() => {
280
+ switch (provider) {
281
+ case "postgresql":
282
+ case "cockroachdb": return "postgresql";
283
+ case "mysql": return "mysql";
284
+ case "sqlite": return "sqlite";
285
+ default: throw new Error(`Unsupported provider: ${provider}`);
286
+ }
287
+ })();
295
288
  const imports = new ImportTracker(db);
296
- const enumLines = makeEnums();
297
289
  const tableLines = datamodel.models.map((model) => makeTable(model, db, imports, datamodel.enums, indexes));
298
290
  const relationsLines = makeRelations(datamodel.models, imports);
299
291
  const tableLinesWithGap = tableLines.flatMap((line, i) => i < tableLines.length - 1 ? [line, ""] : [line]);
@@ -301,7 +293,6 @@ function drizzleSchema(datamodel, provider, indexes) {
301
293
  return [
302
294
  imports.generate(),
303
295
  "",
304
- ...enumLines.length > 0 ? [...enumLines, ""] : [],
305
296
  ...tableLinesWithGap,
306
297
  ...relationsLinesWithGap.length > 0 ? ["", ...relationsLinesWithGap] : []
307
298
  ].join("\n");
@@ -1,9 +1,36 @@
1
1
  #!/usr/bin/env node
2
- import { N as mkdir, P as writeFile, b as makeSnakeCase, k as prismaTypeToEctoType, n as ectoTypeToTypespec } from "../../utils-DeZn2r_T.js";
2
+ import { d as mkdir, f as writeFile, o as makeSnakeCase } from "../../utils-COHZyQue.js";
3
3
  import { join } from "node:path";
4
4
  import pkg from "@prisma/generator-helper";
5
5
 
6
6
  //#region src/helper/ecto.ts
7
+ function prismaTypeToEctoType(type) {
8
+ if (type === "Int") return "integer";
9
+ if (type === "BigInt") return "integer";
10
+ if (type === "Float") return "float";
11
+ if (type === "Decimal") return "decimal";
12
+ if (type === "String") return "string";
13
+ if (type === "Boolean") return "boolean";
14
+ if (type === "DateTime") return "utc_datetime";
15
+ if (type === "Json") return "map";
16
+ if (type === "Bytes") return "binary";
17
+ return "string";
18
+ }
19
+ function ectoTypeToTypespec(type) {
20
+ switch (type) {
21
+ case "string": return "String.t()";
22
+ case "integer": return "integer()";
23
+ case "float": return "float()";
24
+ case "boolean": return "boolean()";
25
+ case "binary_id": return "Ecto.UUID.t()";
26
+ case "naive_datetime": return "NaiveDateTime.t()";
27
+ case "utc_datetime": return "DateTime.t()";
28
+ case "decimal": return "Decimal.t()";
29
+ case "map": return "map()";
30
+ case "binary": return "binary()";
31
+ default: return "term()";
32
+ }
33
+ }
7
34
  function getPrimaryKeyConfig(field) {
8
35
  const def = field.default;
9
36
  const isFunctionDefault = def && typeof def === "object" && "name" in def;
@@ -26,13 +53,6 @@ function getPrimaryKeyConfig(field) {
26
53
  useBinaryForeignKey: false
27
54
  };
28
55
  }
29
- function getFieldDefaultOption(field) {
30
- const def = field.default;
31
- if (def === void 0 || def === null) return null;
32
- if (typeof def === "string") return `default: "${def}"`;
33
- if (typeof def === "number" || typeof def === "boolean") return `default: ${def}`;
34
- return null;
35
- }
36
56
  function makeTimestampsLine(fields) {
37
57
  const insertedAliases = [
38
58
  "inserted_at",
@@ -183,7 +203,12 @@ function ectoSchemas(models, app, allModels, enums) {
183
203
  }
184
204
  const type = prismaTypeToEctoType(f.type);
185
205
  const ectoType = f.isList ? `{:array, :${type}}` : `:${type}`;
186
- const defaultOpt = getFieldDefaultOption(f);
206
+ const defaultOpt = ((def) => {
207
+ if (def === void 0 || def === null) return null;
208
+ if (typeof def === "string") return `default: "${def}"`;
209
+ if (typeof def === "number" || typeof def === "boolean") return `default: ${def}`;
210
+ return null;
211
+ })(f.default);
187
212
  return ` field(:${snakeName}, ${ectoType}${primary}${defaultOpt ? `, ${defaultOpt}` : ""}${sourceOpt})`;
188
213
  });
189
214
  const fkFieldLines = [];
@@ -1,11 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as fmt } from "../../format-CzXgkLDe.js";
3
- import { N as mkdir, O as parseDocumentWithoutAnnotations, P as writeFile, a as getBool, g as makeEffectSchema, h as makeEffectProperties, j as schemaFromFields, m as makeEffectInfer, p as makeEffectEnumExpression, w as makeValidationExtractor } from "../../utils-DeZn2r_T.js";
4
- import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-Cc0YxSiO.js";
3
+ import { c as parseDocumentWithoutAnnotations, d as mkdir, f as writeFile, l as schemaFromFields, s as makeValidationExtractor, t as getBool } from "../../utils-COHZyQue.js";
4
+ import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-ChsFqlYX.js";
5
5
  import path from "node:path";
6
6
  import pkg from "@prisma/generator-helper";
7
7
 
8
8
  //#region src/helper/effect.ts
9
+ function makeEffectInfer(modelName) {
10
+ return `export type ${modelName} = Schema.Schema.Type<typeof ${modelName}Schema>`;
11
+ }
12
+ function makeEffectSchema(modelName, fields) {
13
+ return `export const ${modelName}Schema = Schema.Struct({\n${fields}\n})`;
14
+ }
15
+ function makeEffectProperties(fields, comment) {
16
+ return fields.map((field) => {
17
+ return `${comment && field.comment.length > 0 ? `${field.comment.map((c) => ` /** ${c} */`).join("\n")}\n` : ""} ${field.fieldName}: ${field.validation ?? "Schema.Unknown"},`;
18
+ }).join("\n");
19
+ }
20
+ function makeEffectEnumExpression(values) {
21
+ return `Schema.Literal(${values.map((v) => `'${v}'`).join(", ")})`;
22
+ }
9
23
  const PRISMA_TO_EFFECT = {
10
24
  String: "Schema.String",
11
25
  Int: "Schema.Number",
@@ -53,7 +67,7 @@ async function main(options) {
53
67
  dir: output,
54
68
  file: path.join(output, "index.ts")
55
69
  };
56
- const enableRelation = options.generator.config?.relation === "true" || Array.isArray(options.generator.config?.relation) && options.generator.config?.relation[0] === "true";
70
+ const enableRelation = getBool(options.generator.config?.relation);
57
71
  const fmtResult = await fmt([effect(options.dmmf.datamodel.models, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), options.dmmf.datamodel.enums), enableRelation ? makeRelationsOnly(options.dmmf, getBool(options.generator.config?.type), makeEffectRelations) : ""].filter(Boolean).join("\n\n"));
58
72
  if (!fmtResult.ok) throw new Error(`Format error: ${fmtResult.error}`);
59
73
  const mkdirResult = await mkdir(resolved.dir);
@@ -0,0 +1,6 @@
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/gorm/index.d.ts
4
+ declare function main(options: GeneratorOptions): Promise<void>;
5
+ //#endregion
6
+ export { main };
@@ -0,0 +1,370 @@
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 path, { dirname } from "node:path";
4
+ import pkg from "@prisma/generator-helper";
5
+
6
+ //#region src/helper/gorm.ts
7
+ const PRISMA_TO_GO = {
8
+ String: "string",
9
+ Int: "int",
10
+ BigInt: "int64",
11
+ Float: "float64",
12
+ Decimal: "float64",
13
+ Boolean: "bool",
14
+ DateTime: "time.Time",
15
+ Json: "datatypes.JSON",
16
+ Bytes: "[]byte"
17
+ };
18
+ function prismaTypeToGoType(type, isRequired) {
19
+ const base = PRISMA_TO_GO[type] ?? "string";
20
+ if (!isRequired && base !== "[]byte" && base !== "datatypes.JSON") return `*${base}`;
21
+ return base;
22
+ }
23
+ function resolveNativeType(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 ? `varchar(${args[0]})` : null;
30
+ case "Text":
31
+ case "MediumText":
32
+ case "LongText":
33
+ case "TinyText": return "text";
34
+ case "SmallInt":
35
+ case "TinyInt": return "smallint";
36
+ case "MediumInt": return "mediumint";
37
+ case "DoublePrecision":
38
+ case "Double":
39
+ case "Real": return "double precision";
40
+ case "Decimal":
41
+ case "Money": return args.length >= 2 ? `decimal(${args[0]},${args[1]})` : "decimal";
42
+ case "Uuid": return "char(36)";
43
+ case "Timestamp":
44
+ case "Timestamptz": return "timestamp";
45
+ case "Date": return "date";
46
+ case "Time":
47
+ case "Timetz": return "time";
48
+ case "JsonB": return "jsonb";
49
+ case "Xml": return "xml";
50
+ default: return null;
51
+ }
52
+ }
53
+ function getAssociations(model, allModels) {
54
+ const belongsTo = [];
55
+ const hasMany = [];
56
+ const hasOne = [];
57
+ const manyToMany = [];
58
+ for (const field of model.fields) {
59
+ if (field.kind !== "object") continue;
60
+ if (field.relationFromFields && field.relationFromFields.length > 0) belongsTo.push({
61
+ name: field.name,
62
+ targetModel: field.type,
63
+ foreignKey: field.relationFromFields[0],
64
+ references: field.relationToFields?.[0] ?? "id"
65
+ });
66
+ else if (field.isList) {
67
+ const targetModel = allModels.find((m) => m.name === field.type);
68
+ if (!targetModel) continue;
69
+ if (targetModel.fields.find((f) => f.relationName === field.relationName && f.kind === "object")?.isList) manyToMany.push({
70
+ name: field.name,
71
+ targetModel: field.type,
72
+ relationName: field.relationName ?? `${model.name}To${field.type}`
73
+ });
74
+ else {
75
+ const fkField = targetModel.fields.find((f) => f.relationName === field.relationName && f.relationFromFields && f.relationFromFields.length > 0);
76
+ const foreignKey = fkField?.relationFromFields?.[0];
77
+ if (!foreignKey) continue;
78
+ const references = fkField?.relationToFields?.[0] ?? "id";
79
+ hasMany.push({
80
+ name: field.name,
81
+ targetModel: field.type,
82
+ foreignKey,
83
+ references,
84
+ isList: true
85
+ });
86
+ }
87
+ } else {
88
+ const targetModel = allModels.find((m) => m.name === field.type);
89
+ if (!targetModel) continue;
90
+ const fkField = targetModel.fields.find((f) => f.relationName === field.relationName && f.relationFromFields && f.relationFromFields.length > 0);
91
+ const foreignKey = fkField?.relationFromFields?.[0];
92
+ if (!foreignKey) continue;
93
+ const references = fkField?.relationToFields?.[0] ?? "id";
94
+ hasOne.push({
95
+ name: field.name,
96
+ targetModel: field.type,
97
+ foreignKey,
98
+ references,
99
+ isList: false
100
+ });
101
+ }
102
+ }
103
+ return {
104
+ belongsTo,
105
+ hasMany,
106
+ hasOne,
107
+ manyToMany
108
+ };
109
+ }
110
+ function isFunctionDefault(def) {
111
+ return def !== null && typeof def === "object" && "name" in def;
112
+ }
113
+ function isAutoincrement(field) {
114
+ return isFunctionDefault(field.default) && field.default.name === "autoincrement";
115
+ }
116
+ function formatGoDefault(def) {
117
+ if (def === void 0 || def === null) return null;
118
+ if (typeof def === "boolean") return def ? "true" : "false";
119
+ if (typeof def === "number") return String(def);
120
+ if (typeof def === "string") return def;
121
+ return null;
122
+ }
123
+ function buildGormTags(field, isPk, isCompositePk, compositeIndexTags) {
124
+ const columnName = field.dbName ?? makeSnakeCase(field.name);
125
+ const parts = [`column:${columnName}`];
126
+ if (isPk) {
127
+ parts.push("primaryKey");
128
+ if (isAutoincrement(field)) parts.push("autoIncrement");
129
+ if (isFunctionDefault(field.default) && field.default.name === "uuid") parts.push("type:char(36)");
130
+ }
131
+ if (field.isUnique) parts.push("uniqueIndex");
132
+ for (const tag of compositeIndexTags) parts.push(tag);
133
+ const nativeType = resolveNativeType(field);
134
+ if (nativeType && !isPk) parts.push(`type:${nativeType}`);
135
+ else if (nativeType && isPk && !isFunctionDefault(field.default)) parts.push(`type:${nativeType}`);
136
+ else if (nativeType && isPk && isFunctionDefault(field.default) && field.default.name !== "uuid") parts.push(`type:${nativeType}`);
137
+ if (!isPk || isCompositePk) if (field.type === "DateTime" && isFunctionDefault(field.default) && field.default.name === "now") parts.push("autoCreateTime");
138
+ else if (field.isUpdatedAt) {} else {
139
+ const defaultVal = formatGoDefault(field.default);
140
+ if (defaultVal !== null) parts.push(`default:${defaultVal}`);
141
+ }
142
+ else if (isPk && !isCompositePk) {
143
+ if (field.type === "DateTime" && isFunctionDefault(field.default) && field.default.name === "now") parts.push("autoCreateTime");
144
+ }
145
+ if (field.isUpdatedAt) parts.push("autoUpdateTime");
146
+ if (field.isRequired && !isPk) parts.push("not null");
147
+ return `\`gorm:"${parts.join(";")}" json:"${columnName}"\``;
148
+ }
149
+ function collectCompositeIndexTags(model, indexes) {
150
+ const tagMap = /* @__PURE__ */ new Map();
151
+ const addTag = (fieldName, tag) => {
152
+ const existing = tagMap.get(fieldName) ?? [];
153
+ existing.push(tag);
154
+ tagMap.set(fieldName, existing);
155
+ };
156
+ for (const fields of model.uniqueFields) {
157
+ if (fields.length <= 1) continue;
158
+ const idxName = `idx_${fields.map((f) => {
159
+ return model.fields.find((mf) => mf.name === f)?.dbName ?? makeSnakeCase(f);
160
+ }).join("_")}_unique`;
161
+ for (const f of fields) addTag(f, `uniqueIndex:${idxName}`);
162
+ }
163
+ for (const idx of indexes) {
164
+ if (idx.model !== model.name) continue;
165
+ if (idx.type !== "normal" && idx.type !== "fulltext") continue;
166
+ const idxName = idx.dbName ?? idx.name ?? `idx_${idx.fields.map((f) => makeSnakeCase(f.name)).join("_")}`;
167
+ for (const f of idx.fields) addTag(f.name, `index:${idxName}`);
168
+ }
169
+ return tagMap;
170
+ }
171
+ const GO_INITIALISMS = new Set([
172
+ "acl",
173
+ "api",
174
+ "ascii",
175
+ "cpu",
176
+ "css",
177
+ "dns",
178
+ "eof",
179
+ "guid",
180
+ "html",
181
+ "http",
182
+ "https",
183
+ "id",
184
+ "ip",
185
+ "json",
186
+ "lhs",
187
+ "qps",
188
+ "ram",
189
+ "rhs",
190
+ "rpc",
191
+ "sla",
192
+ "smtp",
193
+ "sql",
194
+ "ssh",
195
+ "tcp",
196
+ "tls",
197
+ "ttl",
198
+ "udp",
199
+ "ui",
200
+ "uid",
201
+ "uri",
202
+ "url",
203
+ "utf8",
204
+ "uuid",
205
+ "vm",
206
+ "xml",
207
+ "xmpp",
208
+ "xsrf",
209
+ "xss"
210
+ ]);
211
+ /**
212
+ * Split a camelCase/PascalCase name into words, applying Go initialism rules.
213
+ * e.g. "userId" -> ["User", "ID"], "avatarUrl" -> ["Avatar", "URL"],
214
+ * "ipAddress" -> ["IP", "Address"], "createdAt" -> ["Created", "At"]
215
+ */
216
+ function splitGoWords(name) {
217
+ const parts = name.replace(/([a-z0-9])([A-Z])/g, "$1\0$2").split("\0");
218
+ const result = [];
219
+ let i = 0;
220
+ while (i < parts.length) {
221
+ const lower = parts[i].toLowerCase();
222
+ if (GO_INITIALISMS.has(lower)) {
223
+ result.push(lower.toUpperCase());
224
+ i++;
225
+ continue;
226
+ }
227
+ result.push(parts[i].charAt(0).toUpperCase() + parts[i].slice(1));
228
+ i++;
229
+ }
230
+ return result;
231
+ }
232
+ function goFieldName(name) {
233
+ return splitGoWords(name).join("");
234
+ }
235
+ function generateStructField(field, isPk, isCompositePk, compositeIndexTags, _enumNames) {
236
+ const fieldName = goFieldName(field.name);
237
+ let goType;
238
+ if (field.kind === "enum") goType = field.isRequired ? "string" : "*string";
239
+ else goType = prismaTypeToGoType(field.type, field.isRequired);
240
+ const tag = buildGormTags(field, isPk, isCompositePk, compositeIndexTags);
241
+ const tagStr = tag ? ` ${tag}` : "";
242
+ return `\t${fieldName} ${goType}${tagStr}`;
243
+ }
244
+ function needsReferencesTag(references) {
245
+ return references !== "id";
246
+ }
247
+ function buildRelationTag(parts) {
248
+ return `\`gorm:"${parts.join(";")}"\``;
249
+ }
250
+ function generateRelationFields(model, associations) {
251
+ const lines = [];
252
+ for (const assoc of associations.belongsTo) {
253
+ const fieldName = goFieldName(assoc.name);
254
+ const fkFieldName = goFieldName(assoc.foreignKey);
255
+ const refsFieldName = goFieldName(assoc.references);
256
+ const isAmbiguous = fieldName !== assoc.targetModel || associations.belongsTo.filter((a) => a.targetModel === assoc.targetModel).length > 1;
257
+ const tagParts = [];
258
+ if (isAmbiguous) tagParts.push(`foreignKey:${fkFieldName}`);
259
+ if (needsReferencesTag(assoc.references)) tagParts.push(`references:${refsFieldName}`);
260
+ if (tagParts.length > 0) lines.push(`\t${fieldName} ${assoc.targetModel} ${buildRelationTag(tagParts)}`);
261
+ else lines.push(`\t${fieldName} ${assoc.targetModel}`);
262
+ }
263
+ for (const assoc of associations.hasMany) {
264
+ const tagParts = [`foreignKey:${goFieldName(assoc.foreignKey)}`];
265
+ if (needsReferencesTag(assoc.references)) tagParts.push(`references:${goFieldName(assoc.references)}`);
266
+ lines.push(`\t${goFieldName(assoc.name)} []${assoc.targetModel} ${buildRelationTag(tagParts)}`);
267
+ }
268
+ for (const assoc of associations.hasOne) {
269
+ const tagParts = [`foreignKey:${goFieldName(assoc.foreignKey)}`];
270
+ if (needsReferencesTag(assoc.references)) tagParts.push(`references:${goFieldName(assoc.references)}`);
271
+ lines.push(`\t${goFieldName(assoc.name)} ${assoc.targetModel} ${buildRelationTag(tagParts)}`);
272
+ }
273
+ for (const assoc of associations.manyToMany) {
274
+ const [leftName, rightName] = model.name < assoc.targetModel ? [model.name, assoc.targetModel] : [assoc.targetModel, model.name];
275
+ const joinTable = `_${leftName}To${rightName}`;
276
+ lines.push(`\t${goFieldName(assoc.name)} []${assoc.targetModel} \`gorm:"many2many:${joinTable};"\``);
277
+ }
278
+ return lines;
279
+ }
280
+ function generateModelStruct(model, allModels, enums, indexes) {
281
+ const idField = model.fields.find((f) => f.isId);
282
+ const compositePkFieldNames = new Set(model.primaryKey?.fields ?? []);
283
+ const isCompositePk = !idField && compositePkFieldNames.size > 0;
284
+ if (!(idField || isCompositePk)) return null;
285
+ const associations = getAssociations(model, allModels);
286
+ const enumNames = new Set((enums ?? []).map((e) => e.name));
287
+ const compositeTagMap = collectCompositeIndexTags(model, indexes);
288
+ const tableName = model.dbName ?? makeSnakeCase(model.name);
289
+ const fieldLines = model.fields.filter((f) => f.kind !== "object").map((field) => {
290
+ return generateStructField(field, field.isId || compositePkFieldNames.has(field.name), isCompositePk, compositeTagMap.get(field.name) ?? [], enumNames);
291
+ });
292
+ const relationLines = generateRelationFields(model, associations);
293
+ const lines = [
294
+ `type ${model.name} struct {`,
295
+ ...fieldLines,
296
+ ...relationLines.length > 0 ? relationLines : [],
297
+ "}"
298
+ ];
299
+ if (tableName !== makeSnakeCase(model.name)) {
300
+ lines.push("");
301
+ lines.push(`func (${model.name}) TableName() string {`);
302
+ lines.push(`\treturn "${tableName}"`);
303
+ lines.push("}");
304
+ }
305
+ return lines.join("\n");
306
+ }
307
+ function collectImports(models) {
308
+ const imports = [];
309
+ const needsTime = models.some((m) => m.fields.some((f) => f.kind !== "object" && f.type === "DateTime"));
310
+ const needsDatatypes = models.some((m) => m.fields.some((f) => f.kind !== "object" && f.type === "Json"));
311
+ if (needsTime) imports.push("\"time\"");
312
+ if (needsDatatypes) imports.push("\"gorm.io/datatypes\"");
313
+ return imports;
314
+ }
315
+ function generateGormModels(models, enums, indexes, packageName = "model") {
316
+ const idx = indexes ?? [];
317
+ const modelBodies = models.map((model) => generateModelStruct(model, models, enums, idx)).filter((body) => body !== null);
318
+ const imports = collectImports(models);
319
+ const lines = [`package ${packageName}`];
320
+ if (imports.length > 0) {
321
+ lines.push("");
322
+ if (imports.length === 1) lines.push(`import ${imports[0]}`);
323
+ else {
324
+ lines.push("import (");
325
+ for (const imp of imports) lines.push(`\t${imp}`);
326
+ lines.push(")");
327
+ }
328
+ }
329
+ lines.push("");
330
+ lines.push(modelBodies.join("\n\n"));
331
+ lines.push("");
332
+ return lines.join("\n");
333
+ }
334
+ async function writeGormFile(models, outPath, enums, indexes, packageName = "model") {
335
+ const mkdirResult = await mkdir(dirname(outPath));
336
+ if (!mkdirResult.ok) return mkdirResult;
337
+ const writeResult = await writeFile(outPath, generateGormModels(models, enums, indexes, packageName));
338
+ if (!writeResult.ok) return writeResult;
339
+ console.log(`wrote ${outPath}`);
340
+ return {
341
+ ok: true,
342
+ value: void 0
343
+ };
344
+ }
345
+
346
+ //#endregion
347
+ //#region src/generator/gorm/index.ts
348
+ const { generatorHandler } = pkg;
349
+ async function main(options) {
350
+ if (!(options.generator.isCustomOutput && options.generator.output?.value)) throw new Error("output is required for Hekireki-GORM. Please specify output in your generator config.");
351
+ const output = options.generator.output.value;
352
+ const resolved = path.extname(output) ? output : path.join(output, "models.go");
353
+ const packageName = getString(options.generator.config.package, "model");
354
+ const enums = options.dmmf.datamodel.enums;
355
+ const indexes = options.dmmf.datamodel.indexes;
356
+ const result = await writeGormFile(options.dmmf.datamodel.models, resolved, enums, indexes, packageName);
357
+ if (!result.ok) throw new Error(`Failed to write GORM models: ${result.error}`);
358
+ }
359
+ generatorHandler({
360
+ onManifest() {
361
+ return {
362
+ defaultOutput: ".",
363
+ prettyName: "Hekireki-GORM"
364
+ };
365
+ },
366
+ onGenerate: main
367
+ });
368
+
369
+ //#endregion
370
+ export { main };
@@ -1,32 +1,26 @@
1
1
  #!/usr/bin/env node
2
- import { A as removeDuplicateRelations, N as mkdir, P as writeFile } from "../../utils-DeZn2r_T.js";
2
+ import { d as mkdir, f as writeFile, u as stripAnnotations } from "../../utils-COHZyQue.js";
3
3
  import path from "node:path";
4
4
  import pkg from "@prisma/generator-helper";
5
5
 
6
6
  //#region src/helper/mermaid-er.ts
7
- const ZOD_ANNOTATION = "@z.";
8
- const VALIBOT_ANNOTATION = "@v.";
9
- const RELATION_ANNOTATION = "@relation";
7
+ function removeDuplicateRelations(relations) {
8
+ return [...new Set(relations)];
9
+ }
10
10
  const RELATIONSHIPS = {
11
11
  "zero-one": "|o",
12
12
  one: "||",
13
13
  "zero-many": "}o",
14
14
  many: "}|"
15
15
  };
16
- function toMermaidType(prismaType) {
17
- return prismaType.toLowerCase();
18
- }
19
16
  function modelFields(model) {
20
17
  const fkFields = new Set(model.fields.filter((f) => f.relationFromFields && f.relationFromFields.length > 0).flatMap((f) => f.relationFromFields ?? []));
21
18
  return model.fields.map((field) => {
22
19
  if (field.relationName) return null;
23
- const commentPart = field.documentation ? field.documentation.split("\n").filter((line) => {
24
- const trimmed = line.trim();
25
- return !(trimmed.startsWith(ZOD_ANNOTATION) || trimmed.startsWith(VALIBOT_ANNOTATION) || trimmed.startsWith("@a.") || trimmed.startsWith("@e.") || trimmed.includes(RELATION_ANNOTATION) || trimmed === "@z" || trimmed === "@v" || trimmed === "@a" || trimmed === "@e");
26
- }).join("\n").trim() : "";
20
+ const commentPart = stripAnnotations(field.documentation) ?? "";
27
21
  const keyMarker = field.isId ? "PK" : fkFields.has(field.name) ? "FK" : "";
28
22
  const keyPart = keyMarker ? ` ${keyMarker}` : "";
29
- return ` ${toMermaidType(field.type)} ${field.name}${keyPart}${commentPart ? ` "${commentPart}"` : ""}`;
23
+ return ` ${field.type.toLowerCase()} ${field.name}${keyPart}${commentPart ? ` "${commentPart}"` : ""}`;
30
24
  }).filter((field) => field !== null);
31
25
  }
32
26
  function modelInfo(model) {
@@ -0,0 +1,6 @@
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/sea-orm/index.d.ts
4
+ declare function main(options: GeneratorOptions): Promise<void>;
5
+ //#endregion
6
+ export { main };