prisma-entity-gen 0.1.2 → 0.1.3
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/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +5 -2
- package/dist/cli/index.cjs +0 -711
- package/dist/cli/index.cjs.map +0 -1
- package/dist/cli/index.d.cts +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
4
|
var fs = require('fs');
|
|
@@ -5,7 +6,6 @@ var path = require('path');
|
|
|
5
6
|
var zod = require('zod');
|
|
6
7
|
var prismaAst = require('@mrleebo/prisma-ast');
|
|
7
8
|
|
|
8
|
-
// src/config/loader.ts
|
|
9
9
|
var ConfigSchema = zod.z.object({
|
|
10
10
|
/**
|
|
11
11
|
* Caminho para o schema.prisma
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
3
|
import { resolve, dirname } from 'path';
|
|
3
4
|
import { z, ZodError } from 'zod';
|
|
4
5
|
import { getSchema } from '@mrleebo/prisma-ast';
|
|
5
6
|
|
|
6
|
-
// src/config/loader.ts
|
|
7
7
|
var ConfigSchema = z.object({
|
|
8
8
|
/**
|
|
9
9
|
* Caminho para o schema.prisma
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-entity-gen",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "AST-based entity generator for Prisma schemas — type, interface or class output",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "",
|
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
"typecheck": "tsc --noEmit",
|
|
40
40
|
"prepublishOnly": "npm run build && npm run typecheck"
|
|
41
41
|
},
|
|
42
|
+
"overrides": {
|
|
43
|
+
"lodash": "^4.18.0"
|
|
44
|
+
},
|
|
42
45
|
"dependencies": {
|
|
43
46
|
"@mrleebo/prisma-ast": "^0.12.0",
|
|
44
47
|
"commander": "^12.1.0",
|
|
@@ -63,4 +66,4 @@
|
|
|
63
66
|
"generator",
|
|
64
67
|
"ast"
|
|
65
68
|
]
|
|
66
|
-
}
|
|
69
|
+
}
|
package/dist/cli/index.cjs
DELETED
|
@@ -1,711 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
var commander = require('commander');
|
|
5
|
-
var fs = require('fs');
|
|
6
|
-
var path = require('path');
|
|
7
|
-
var zod = require('zod');
|
|
8
|
-
var prismaAst = require('@mrleebo/prisma-ast');
|
|
9
|
-
|
|
10
|
-
var ConfigSchema = zod.z.object({
|
|
11
|
-
/**
|
|
12
|
-
* Caminho para o schema.prisma
|
|
13
|
-
* @default "prisma/schema.prisma"
|
|
14
|
-
*/
|
|
15
|
-
schemaPath: zod.z.string().default("prisma/schema.prisma"),
|
|
16
|
-
/**
|
|
17
|
-
* Diretório de saída das entities geradas
|
|
18
|
-
* @default "src/entities"
|
|
19
|
-
*/
|
|
20
|
-
outputDir: zod.z.string().default("src/entities"),
|
|
21
|
-
/**
|
|
22
|
-
* Modo de geração:
|
|
23
|
-
* - "type" → type aliases e interfaces puras (melhor performance TS)
|
|
24
|
-
* - "class" → classes com decorators (NestJS / class-validator)
|
|
25
|
-
* - "both" → gera os dois em subpastas /types e /classes
|
|
26
|
-
*/
|
|
27
|
-
mode: zod.z.enum(["type", "class", "both"]).default("type"),
|
|
28
|
-
/**
|
|
29
|
-
* Quando mode="class", inclui decorators do class-validator
|
|
30
|
-
* @default false
|
|
31
|
-
*/
|
|
32
|
-
classValidator: zod.z.boolean().default(false),
|
|
33
|
-
/**
|
|
34
|
-
* Quando mode="class", inclui decorators do class-transformer
|
|
35
|
-
* @default false
|
|
36
|
-
*/
|
|
37
|
-
classTransformer: zod.z.boolean().default(false),
|
|
38
|
-
/**
|
|
39
|
-
* Gera barrel index.ts na raiz do outputDir
|
|
40
|
-
* @default true
|
|
41
|
-
*/
|
|
42
|
-
barrel: zod.z.boolean().default(true),
|
|
43
|
-
/**
|
|
44
|
-
* Modelos a ignorar na geração
|
|
45
|
-
* @default []
|
|
46
|
-
*/
|
|
47
|
-
exclude: zod.z.array(zod.z.string()).default([]),
|
|
48
|
-
/**
|
|
49
|
-
* Apenas esses modelos serão gerados (vazio = todos)
|
|
50
|
-
* @default []
|
|
51
|
-
*/
|
|
52
|
-
include: zod.z.array(zod.z.string()).default([]),
|
|
53
|
-
/**
|
|
54
|
-
* Formato de saída dos enums:
|
|
55
|
-
* - "enum" → export enum Role { ADMIN = "ADMIN" }
|
|
56
|
-
* - "union" → export type Role = "ADMIN" | "USER"
|
|
57
|
-
* Use "union" para evitar conflitos com enums do @prisma/client
|
|
58
|
-
* @default "enum"
|
|
59
|
-
*/
|
|
60
|
-
enumOutput: zod.z.enum(["enum", "union"]).default("enum"),
|
|
61
|
-
/**
|
|
62
|
-
* Define se campos de relação são opcionais ou obrigatórios na entity gerada:
|
|
63
|
-
* - "optional" → relações sempre com ? (compatível com queries sem include)
|
|
64
|
-
* - "required" → relações sem ? (requer include em toda query que retornar o tipo)
|
|
65
|
-
* @default "optional"
|
|
66
|
-
*/
|
|
67
|
-
relations: zod.z.enum(["optional", "required"]).default("optional"),
|
|
68
|
-
/**
|
|
69
|
-
* Sufixo dos arquivos gerados
|
|
70
|
-
* @default "entity"
|
|
71
|
-
* Resulta em: user.entity.ts
|
|
72
|
-
*/
|
|
73
|
-
suffix: zod.z.string().default("entity"),
|
|
74
|
-
/**
|
|
75
|
-
* Simula a geração sem escrever arquivos
|
|
76
|
-
* @default false
|
|
77
|
-
*/
|
|
78
|
-
dryRun: zod.z.boolean().default(false),
|
|
79
|
-
/**
|
|
80
|
-
* Nível de log: "silent" | "info" | "verbose"
|
|
81
|
-
* @default "info"
|
|
82
|
-
*/
|
|
83
|
-
logLevel: zod.z.enum(["silent", "info", "verbose"]).default("info")
|
|
84
|
-
});
|
|
85
|
-
ConfigSchema.parse({});
|
|
86
|
-
|
|
87
|
-
// src/config/loader.ts
|
|
88
|
-
var RC_FILES = [
|
|
89
|
-
".entitygenrc.json",
|
|
90
|
-
"entitygen.config.json",
|
|
91
|
-
".entitygenrc"
|
|
92
|
-
];
|
|
93
|
-
var ConfigError = class extends Error {
|
|
94
|
-
constructor(message, cause) {
|
|
95
|
-
super(message, { cause });
|
|
96
|
-
this.name = "ConfigError";
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
function loadConfig(cwd = process.cwd()) {
|
|
100
|
-
const rcFile = RC_FILES.map((f) => path.resolve(cwd, f)).find(fs.existsSync);
|
|
101
|
-
if (!rcFile) {
|
|
102
|
-
return ConfigSchema.parse({});
|
|
103
|
-
}
|
|
104
|
-
let raw;
|
|
105
|
-
try {
|
|
106
|
-
raw = JSON.parse(fs.readFileSync(rcFile, "utf-8"));
|
|
107
|
-
} catch (err) {
|
|
108
|
-
throw new ConfigError(`Falha ao ler ${rcFile}: arquivo JSON inv\xE1lido`, err);
|
|
109
|
-
}
|
|
110
|
-
try {
|
|
111
|
-
return ConfigSchema.parse(raw);
|
|
112
|
-
} catch (err) {
|
|
113
|
-
if (err instanceof zod.ZodError) {
|
|
114
|
-
const messages = err.errors.map((e) => ` \u2022 ${e.path.join(".")} \u2014 ${e.message}`).join("\n");
|
|
115
|
-
throw new ConfigError(
|
|
116
|
-
`Config inv\xE1lido em ${rcFile}:
|
|
117
|
-
${messages}`,
|
|
118
|
-
err
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
throw err;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// src/parser/types.ts
|
|
126
|
-
var PRISMA_TO_TS = {
|
|
127
|
-
String: "string",
|
|
128
|
-
Boolean: "boolean",
|
|
129
|
-
Int: "number",
|
|
130
|
-
BigInt: "bigint",
|
|
131
|
-
Float: "number",
|
|
132
|
-
Decimal: "string",
|
|
133
|
-
// Decimal não tem tipo nativo TS — string é mais seguro que number
|
|
134
|
-
DateTime: "Date",
|
|
135
|
-
Json: "Record<string, unknown>",
|
|
136
|
-
Bytes: "Buffer"
|
|
137
|
-
};
|
|
138
|
-
var SCALARS = new Set(Object.keys(PRISMA_TO_TS));
|
|
139
|
-
function isScalar(type) {
|
|
140
|
-
return SCALARS.has(type);
|
|
141
|
-
}
|
|
142
|
-
function resolveTsType(prismaType, knownEnums) {
|
|
143
|
-
if (isScalar(prismaType)) return PRISMA_TO_TS[prismaType];
|
|
144
|
-
if (knownEnums.has(prismaType)) return prismaType;
|
|
145
|
-
return prismaType;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// src/parser/relations.ts
|
|
149
|
-
function detectCircularRefs(graph) {
|
|
150
|
-
const color = /* @__PURE__ */ new Map();
|
|
151
|
-
const circular = /* @__PURE__ */ new Map();
|
|
152
|
-
for (const node of graph.keys()) {
|
|
153
|
-
color.set(node, "white");
|
|
154
|
-
circular.set(node, /* @__PURE__ */ new Set());
|
|
155
|
-
}
|
|
156
|
-
function addCircular(a, b) {
|
|
157
|
-
circular.get(a)?.add(b);
|
|
158
|
-
circular.get(b)?.add(a);
|
|
159
|
-
}
|
|
160
|
-
function dfs(node, ancestors) {
|
|
161
|
-
color.set(node, "gray");
|
|
162
|
-
for (const neighbor of graph.get(node) ?? []) {
|
|
163
|
-
if (!color.has(neighbor)) continue;
|
|
164
|
-
if (color.get(neighbor) === "gray") {
|
|
165
|
-
addCircular(node, neighbor);
|
|
166
|
-
for (const anc of ancestors) {
|
|
167
|
-
if (color.get(anc) === "gray") {
|
|
168
|
-
addCircular(anc, neighbor);
|
|
169
|
-
addCircular(node, anc);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
} else if (color.get(neighbor) === "white") {
|
|
173
|
-
dfs(neighbor, [...ancestors, node]);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
color.set(node, "black");
|
|
177
|
-
}
|
|
178
|
-
for (const node of graph.keys()) {
|
|
179
|
-
if (color.get(node) === "white") {
|
|
180
|
-
dfs(node, []);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return circular;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// src/parser/index.ts
|
|
187
|
-
function hasAttribute(field, name) {
|
|
188
|
-
return field.attributes?.some((a) => a.name === name) ?? false;
|
|
189
|
-
}
|
|
190
|
-
function hasDefault(field) {
|
|
191
|
-
return hasAttribute(field, "default") || hasAttribute(field, "updatedAt");
|
|
192
|
-
}
|
|
193
|
-
function parseEnum(node) {
|
|
194
|
-
const values = node.enumerators.filter((e) => e.type === "enumerator").map((e) => e.name);
|
|
195
|
-
return { name: node.name, values, documentation: node.comment };
|
|
196
|
-
}
|
|
197
|
-
function parseField(field, knownModels, knownEnums) {
|
|
198
|
-
return {
|
|
199
|
-
name: field.name,
|
|
200
|
-
prismaType: field.fieldType,
|
|
201
|
-
tsType: resolveTsType(field.fieldType, knownEnums),
|
|
202
|
-
isOptional: field.optional,
|
|
203
|
-
isArray: field.array,
|
|
204
|
-
isRelation: knownModels.has(field.fieldType),
|
|
205
|
-
isCircular: false,
|
|
206
|
-
hasDefault: hasDefault(field),
|
|
207
|
-
isId: hasAttribute(field, "id"),
|
|
208
|
-
isUnique: hasAttribute(field, "unique"),
|
|
209
|
-
isUpdatedAt: hasAttribute(field, "updatedAt"),
|
|
210
|
-
decorators: []
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
function parseModel(node, knownModels, knownEnums) {
|
|
214
|
-
const fields = node.properties.filter((p) => p.type === "field").map((f) => parseField(f, knownModels, knownEnums));
|
|
215
|
-
const relations = [...new Set(
|
|
216
|
-
fields.filter((f) => f.isRelation).map((f) => f.prismaType)
|
|
217
|
-
)];
|
|
218
|
-
return {
|
|
219
|
-
name: node.name,
|
|
220
|
-
fields,
|
|
221
|
-
relations,
|
|
222
|
-
circularRefs: [],
|
|
223
|
-
documentation: node.comment
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
var ParseError = class extends Error {
|
|
227
|
-
constructor(message, cause) {
|
|
228
|
-
super(message, { cause });
|
|
229
|
-
this.name = "ParseError";
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
function parseSchema(schemaPath) {
|
|
233
|
-
let raw;
|
|
234
|
-
try {
|
|
235
|
-
raw = fs.readFileSync(schemaPath, "utf-8");
|
|
236
|
-
} catch (err) {
|
|
237
|
-
throw new ParseError(`N\xE3o foi poss\xEDvel ler o schema em "${schemaPath}"`, err);
|
|
238
|
-
}
|
|
239
|
-
return parseSchemaString(raw);
|
|
240
|
-
}
|
|
241
|
-
function parseSchemaString(schemaContent) {
|
|
242
|
-
let ast;
|
|
243
|
-
try {
|
|
244
|
-
ast = prismaAst.getSchema(schemaContent);
|
|
245
|
-
} catch (err) {
|
|
246
|
-
throw new ParseError("Falha ao fazer parse do schema Prisma", err);
|
|
247
|
-
}
|
|
248
|
-
const rawNodes = ast.list;
|
|
249
|
-
const knownModels = new Set(
|
|
250
|
-
rawNodes.filter((n) => n.type === "model").map((n) => n.name)
|
|
251
|
-
);
|
|
252
|
-
const knownEnums = new Set(
|
|
253
|
-
rawNodes.filter((n) => n.type === "enum").map((n) => n.name)
|
|
254
|
-
);
|
|
255
|
-
const enums = rawNodes.filter((n) => n.type === "enum").map((n) => parseEnum(n));
|
|
256
|
-
const models = rawNodes.filter((n) => n.type === "model").map((n) => parseModel(n, knownModels, knownEnums));
|
|
257
|
-
const graph = new Map(models.map((m) => [m.name, m.relations]));
|
|
258
|
-
const circularMap = detectCircularRefs(graph);
|
|
259
|
-
for (const model of models) {
|
|
260
|
-
const circulars = circularMap.get(model.name) ?? /* @__PURE__ */ new Set();
|
|
261
|
-
model.circularRefs = [...circulars];
|
|
262
|
-
for (const field of model.fields) {
|
|
263
|
-
if (field.isRelation && circulars.has(field.prismaType)) {
|
|
264
|
-
field.isCircular = true;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
return { models, enums };
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// src/emitters/base.ts
|
|
272
|
-
function fileHeader() {
|
|
273
|
-
return [
|
|
274
|
-
"/**",
|
|
275
|
-
" * ARQUIVO GERADO AUTOMATICAMENTE \u2014 N\xC3O EDITE MANUALMENTE.",
|
|
276
|
-
" * Gerado por prisma-entity-gen. Rode o gerador para atualizar.",
|
|
277
|
-
" */",
|
|
278
|
-
""
|
|
279
|
-
].join("\n");
|
|
280
|
-
}
|
|
281
|
-
function formatFieldType(tsType, isArray, isOptional, isCircular) {
|
|
282
|
-
const base = isArray ? `${tsType}[]` : tsType;
|
|
283
|
-
const nullable = isOptional ? ` | null` : "";
|
|
284
|
-
return `${base}${nullable}`;
|
|
285
|
-
}
|
|
286
|
-
function formatJsDoc(doc) {
|
|
287
|
-
if (!doc) return "";
|
|
288
|
-
const lines = doc.split("\n").map((l) => ` * ${l.trim()}`).join("\n");
|
|
289
|
-
return `/**
|
|
290
|
-
${lines}
|
|
291
|
-
*/
|
|
292
|
-
`;
|
|
293
|
-
}
|
|
294
|
-
var BaseEmitter = class {
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
// src/emitters/type.emitter.ts
|
|
298
|
-
function toKebab(name) {
|
|
299
|
-
return name.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
300
|
-
}
|
|
301
|
-
var TypeEmitter = class extends BaseEmitter {
|
|
302
|
-
constructor(options = {}) {
|
|
303
|
-
super();
|
|
304
|
-
this.options = options;
|
|
305
|
-
}
|
|
306
|
-
options;
|
|
307
|
-
emit(model, enums) {
|
|
308
|
-
const enumNames = new Set(enums.map((e) => e.name));
|
|
309
|
-
const lines = [fileHeader()];
|
|
310
|
-
const relationImports = this.collectRelationImports(model, enumNames);
|
|
311
|
-
if (relationImports.length > 0) {
|
|
312
|
-
for (const imp of relationImports) lines.push(imp);
|
|
313
|
-
lines.push("");
|
|
314
|
-
}
|
|
315
|
-
const enumImports = this.collectEnumImports(model, enumNames);
|
|
316
|
-
if (enumImports.length > 0) {
|
|
317
|
-
for (const imp of enumImports) lines.push(imp);
|
|
318
|
-
lines.push("");
|
|
319
|
-
}
|
|
320
|
-
if (model.documentation) lines.push(formatJsDoc(model.documentation));
|
|
321
|
-
lines.push(`export interface ${model.name}Entity {`);
|
|
322
|
-
for (const field of model.fields) {
|
|
323
|
-
lines.push(` ${this.formatField(field)}`);
|
|
324
|
-
}
|
|
325
|
-
lines.push("}");
|
|
326
|
-
lines.push("");
|
|
327
|
-
return lines.join("\n");
|
|
328
|
-
}
|
|
329
|
-
formatField(field) {
|
|
330
|
-
const relationsOptional = this.options.relations !== "required";
|
|
331
|
-
const optional = field.isRelation && relationsOptional || field.isOptional ? "?" : "";
|
|
332
|
-
const tsType = field.isRelation ? `${field.prismaType}Entity` : field.tsType;
|
|
333
|
-
const type = formatFieldType(tsType, field.isArray, field.isOptional, field.isCircular);
|
|
334
|
-
return `${field.name}${optional}: ${type};`;
|
|
335
|
-
}
|
|
336
|
-
collectRelationImports(model, enumNames) {
|
|
337
|
-
const seen = /* @__PURE__ */ new Set();
|
|
338
|
-
const imports = [];
|
|
339
|
-
for (const field of model.fields) {
|
|
340
|
-
if (field.isRelation && !enumNames.has(field.prismaType) && !seen.has(field.prismaType) && field.prismaType !== model.name) {
|
|
341
|
-
seen.add(field.prismaType);
|
|
342
|
-
imports.push(
|
|
343
|
-
`import type { ${field.prismaType}Entity } from "./${toKebab(field.prismaType)}.entity.js";`
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return imports;
|
|
348
|
-
}
|
|
349
|
-
collectEnumImports(model, enumNames) {
|
|
350
|
-
const seen = /* @__PURE__ */ new Set();
|
|
351
|
-
const imports = [];
|
|
352
|
-
for (const field of model.fields) {
|
|
353
|
-
if (enumNames.has(field.prismaType) && !seen.has(field.prismaType)) {
|
|
354
|
-
seen.add(field.prismaType);
|
|
355
|
-
imports.push(
|
|
356
|
-
`import { ${field.prismaType} } from "./${toKebab(field.prismaType)}.enum.js";`
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
return imports;
|
|
361
|
-
}
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
// src/emitters/class.emitter.ts
|
|
365
|
-
var ClassEmitter = class extends BaseEmitter {
|
|
366
|
-
constructor(options = {}) {
|
|
367
|
-
super();
|
|
368
|
-
this.options = options;
|
|
369
|
-
}
|
|
370
|
-
options;
|
|
371
|
-
emit(model, enums) {
|
|
372
|
-
const enumNames = new Set(enums.map((e) => e.name));
|
|
373
|
-
const lines = [fileHeader()];
|
|
374
|
-
const cvImports = this.collectCvImports(model, enumNames);
|
|
375
|
-
if (this.options.classValidator && cvImports.length > 0) {
|
|
376
|
-
lines.push(`import { ${cvImports.join(", ")} } from "class-validator";`);
|
|
377
|
-
}
|
|
378
|
-
if (this.options.classTransformer) {
|
|
379
|
-
lines.push(`import { Type } from "class-transformer";`);
|
|
380
|
-
}
|
|
381
|
-
if (this.options.classValidator && cvImports.length > 0 || this.options.classTransformer) {
|
|
382
|
-
lines.push("");
|
|
383
|
-
}
|
|
384
|
-
const relationImports = this.collectRelationImports(model, enumNames);
|
|
385
|
-
if (relationImports.length > 0) {
|
|
386
|
-
for (const imp of relationImports) lines.push(imp);
|
|
387
|
-
lines.push("");
|
|
388
|
-
}
|
|
389
|
-
const enumImports = this.collectEnumImports(model, enumNames);
|
|
390
|
-
if (enumImports.length > 0) {
|
|
391
|
-
for (const imp of enumImports) lines.push(imp);
|
|
392
|
-
lines.push("");
|
|
393
|
-
}
|
|
394
|
-
if (model.documentation) lines.push(formatJsDoc(model.documentation));
|
|
395
|
-
lines.push(`export class ${model.name}Entity {`);
|
|
396
|
-
for (const field of model.fields) {
|
|
397
|
-
const fieldLines = this.formatField(field, enumNames);
|
|
398
|
-
for (const l of fieldLines) lines.push(` ${l}`);
|
|
399
|
-
}
|
|
400
|
-
lines.push("}");
|
|
401
|
-
lines.push("");
|
|
402
|
-
return lines.join("\n");
|
|
403
|
-
}
|
|
404
|
-
formatField(field, enumNames) {
|
|
405
|
-
const lines = [];
|
|
406
|
-
if (this.options.classValidator) {
|
|
407
|
-
const decorators = this.getCvDecorators(field, enumNames);
|
|
408
|
-
for (const d of decorators) lines.push(d);
|
|
409
|
-
}
|
|
410
|
-
if (this.options.classTransformer && field.isRelation && !field.isCircular) {
|
|
411
|
-
lines.push(`@Type(() => ${field.tsType}Entity)`);
|
|
412
|
-
}
|
|
413
|
-
const optional = field.isOptional || field.hasDefault ? "?" : "!";
|
|
414
|
-
const type = formatFieldType(
|
|
415
|
-
field.isRelation && !field.isCircular ? `${field.tsType}Entity` : field.tsType,
|
|
416
|
-
field.isArray,
|
|
417
|
-
field.isOptional,
|
|
418
|
-
field.isCircular
|
|
419
|
-
);
|
|
420
|
-
const comment = field.isCircular ? " // circular ref \u2014 usar Ref" : "";
|
|
421
|
-
lines.push(`${field.name}${optional}: ${type};${comment}`);
|
|
422
|
-
lines.push("");
|
|
423
|
-
return lines;
|
|
424
|
-
}
|
|
425
|
-
getCvDecorators(field, enumNames) {
|
|
426
|
-
const decorators = [];
|
|
427
|
-
if (field.isOptional || field.hasDefault) {
|
|
428
|
-
decorators.push("@IsOptional()");
|
|
429
|
-
}
|
|
430
|
-
if (field.isArray) {
|
|
431
|
-
decorators.push("@IsArray()");
|
|
432
|
-
}
|
|
433
|
-
if (field.isRelation || enumNames.has(field.prismaType)) {
|
|
434
|
-
return decorators;
|
|
435
|
-
}
|
|
436
|
-
switch (field.prismaType) {
|
|
437
|
-
case "String":
|
|
438
|
-
decorators.push("@IsString()");
|
|
439
|
-
break;
|
|
440
|
-
case "Boolean":
|
|
441
|
-
decorators.push("@IsBoolean()");
|
|
442
|
-
break;
|
|
443
|
-
case "Int":
|
|
444
|
-
case "Float":
|
|
445
|
-
case "Decimal":
|
|
446
|
-
decorators.push("@IsNumber()");
|
|
447
|
-
break;
|
|
448
|
-
case "BigInt":
|
|
449
|
-
decorators.push("@IsInt()");
|
|
450
|
-
break;
|
|
451
|
-
case "DateTime":
|
|
452
|
-
decorators.push("@IsDate()");
|
|
453
|
-
break;
|
|
454
|
-
}
|
|
455
|
-
return decorators;
|
|
456
|
-
}
|
|
457
|
-
collectCvImports(model, enumNames) {
|
|
458
|
-
const imports = /* @__PURE__ */ new Set();
|
|
459
|
-
for (const field of model.fields) {
|
|
460
|
-
if (field.isOptional || field.hasDefault) imports.add("IsOptional");
|
|
461
|
-
if (field.isArray) imports.add("IsArray");
|
|
462
|
-
if (field.isRelation || enumNames.has(field.prismaType)) continue;
|
|
463
|
-
switch (field.prismaType) {
|
|
464
|
-
case "String":
|
|
465
|
-
imports.add("IsString");
|
|
466
|
-
break;
|
|
467
|
-
case "Boolean":
|
|
468
|
-
imports.add("IsBoolean");
|
|
469
|
-
break;
|
|
470
|
-
case "Int":
|
|
471
|
-
case "Float":
|
|
472
|
-
case "Decimal":
|
|
473
|
-
imports.add("IsNumber");
|
|
474
|
-
break;
|
|
475
|
-
case "BigInt":
|
|
476
|
-
imports.add("IsInt");
|
|
477
|
-
break;
|
|
478
|
-
case "DateTime":
|
|
479
|
-
imports.add("IsDate");
|
|
480
|
-
break;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
return [...imports].sort();
|
|
484
|
-
}
|
|
485
|
-
collectRelationImports(model, enumNames) {
|
|
486
|
-
const seen = /* @__PURE__ */ new Set();
|
|
487
|
-
const imports = [];
|
|
488
|
-
for (const field of model.fields) {
|
|
489
|
-
if (field.isRelation && !field.isCircular && !enumNames.has(field.prismaType) && !seen.has(field.prismaType)) {
|
|
490
|
-
seen.add(field.prismaType);
|
|
491
|
-
const fileName = field.prismaType.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
492
|
-
imports.push(
|
|
493
|
-
`import { ${field.prismaType}Entity } from "./${fileName}.entity.js";`
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
return imports;
|
|
498
|
-
}
|
|
499
|
-
collectEnumImports(model, enumNames) {
|
|
500
|
-
const seen = /* @__PURE__ */ new Set();
|
|
501
|
-
const imports = [];
|
|
502
|
-
for (const field of model.fields) {
|
|
503
|
-
if (enumNames.has(field.prismaType) && !seen.has(field.prismaType)) {
|
|
504
|
-
seen.add(field.prismaType);
|
|
505
|
-
const fileName = field.prismaType.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
506
|
-
imports.push(
|
|
507
|
-
`import { ${field.prismaType} } from "./${fileName}.enum.js";`
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
return imports;
|
|
512
|
-
}
|
|
513
|
-
};
|
|
514
|
-
var FileWriter = class {
|
|
515
|
-
constructor(outputDir, dryRun, logger) {
|
|
516
|
-
this.outputDir = outputDir;
|
|
517
|
-
this.dryRun = dryRun;
|
|
518
|
-
this.logger = logger;
|
|
519
|
-
}
|
|
520
|
-
outputDir;
|
|
521
|
-
dryRun;
|
|
522
|
-
logger;
|
|
523
|
-
writeAll(files) {
|
|
524
|
-
const result = { written: [], skipped: [] };
|
|
525
|
-
if (!this.dryRun) {
|
|
526
|
-
fs.mkdirSync(path.resolve(this.outputDir), { recursive: true });
|
|
527
|
-
}
|
|
528
|
-
for (const file of files) {
|
|
529
|
-
const absPath = path.resolve(this.outputDir, file.relativePath);
|
|
530
|
-
if (this.dryRun) {
|
|
531
|
-
this.logger.info(`[dry-run] ${file.relativePath}`);
|
|
532
|
-
result.skipped.push(absPath);
|
|
533
|
-
continue;
|
|
534
|
-
}
|
|
535
|
-
fs.mkdirSync(path.dirname(absPath), { recursive: true });
|
|
536
|
-
fs.writeFileSync(absPath, file.content, "utf-8");
|
|
537
|
-
this.logger.success(file.relativePath);
|
|
538
|
-
result.written.push(absPath);
|
|
539
|
-
}
|
|
540
|
-
return result;
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
// src/writer/barrel.ts
|
|
545
|
-
function generateBarrel(files) {
|
|
546
|
-
const exports$1 = files.filter((f) => !f.relativePath.endsWith("index.ts")).map((f) => {
|
|
547
|
-
const path = f.relativePath.replace(/\.ts$/, ".js");
|
|
548
|
-
return `export * from "./${path}";`;
|
|
549
|
-
}).sort();
|
|
550
|
-
return [fileHeader(), ...exports$1, ""].join("\n");
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// src/logger.ts
|
|
554
|
-
var LEVELS = {
|
|
555
|
-
silent: 0,
|
|
556
|
-
info: 1,
|
|
557
|
-
verbose: 2
|
|
558
|
-
};
|
|
559
|
-
var Logger = class {
|
|
560
|
-
level;
|
|
561
|
-
constructor(logLevel = "info") {
|
|
562
|
-
this.level = LEVELS[logLevel];
|
|
563
|
-
}
|
|
564
|
-
info(msg) {
|
|
565
|
-
if (this.level >= LEVELS.info) {
|
|
566
|
-
console.log(` ${msg}`);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
verbose(msg) {
|
|
570
|
-
if (this.level >= LEVELS.verbose) {
|
|
571
|
-
console.log(` [verbose] ${msg}`);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
success(msg) {
|
|
575
|
-
if (this.level >= LEVELS.info) {
|
|
576
|
-
console.log(` \u2713 ${msg}`);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
warn(msg) {
|
|
580
|
-
if (this.level >= LEVELS.info) {
|
|
581
|
-
console.warn(` \u26A0 ${msg}`);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
error(msg) {
|
|
585
|
-
console.error(` \u2717 ${msg}`);
|
|
586
|
-
}
|
|
587
|
-
};
|
|
588
|
-
|
|
589
|
-
// src/generator.ts
|
|
590
|
-
function toKebabCase(name) {
|
|
591
|
-
return name.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
592
|
-
}
|
|
593
|
-
function shouldInclude(name, config) {
|
|
594
|
-
if (config.include.length > 0 && !config.include.includes(name)) return false;
|
|
595
|
-
if (config.exclude.includes(name)) return false;
|
|
596
|
-
return true;
|
|
597
|
-
}
|
|
598
|
-
function buildFiles(models, enums, config) {
|
|
599
|
-
const files = [];
|
|
600
|
-
const useType = config.mode === "type" || config.mode === "both";
|
|
601
|
-
const useClass = config.mode === "class" || config.mode === "both";
|
|
602
|
-
const typeEmitter = useType ? new TypeEmitter({ relations: config.relations }) : null;
|
|
603
|
-
const classEmitter = useClass ? new ClassEmitter({
|
|
604
|
-
classValidator: config.classValidator,
|
|
605
|
-
classTransformer: config.classTransformer
|
|
606
|
-
}) : null;
|
|
607
|
-
const typeDir = config.mode === "both" ? "types/" : "";
|
|
608
|
-
const classDir = config.mode === "both" ? "classes/" : "";
|
|
609
|
-
for (const model of models) {
|
|
610
|
-
if (!shouldInclude(model.name, config)) continue;
|
|
611
|
-
const fileName = `${toKebabCase(model.name)}.${config.suffix}.ts`;
|
|
612
|
-
if (typeEmitter) {
|
|
613
|
-
files.push({
|
|
614
|
-
relativePath: `${typeDir}${fileName}`,
|
|
615
|
-
content: typeEmitter.emit(model, enums),
|
|
616
|
-
sourceName: model.name
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
if (classEmitter) {
|
|
620
|
-
files.push({
|
|
621
|
-
relativePath: `${classDir}${fileName}`,
|
|
622
|
-
content: classEmitter.emit(model, enums),
|
|
623
|
-
sourceName: model.name
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
for (const enumDef of enums) {
|
|
628
|
-
if (!shouldInclude(enumDef.name, config)) continue;
|
|
629
|
-
const fileName = `${toKebabCase(enumDef.name)}.enum.ts`;
|
|
630
|
-
const content = buildEnumFile(enumDef, config.enumOutput);
|
|
631
|
-
if (typeDir) files.push({ relativePath: `${typeDir}${fileName}`, content, sourceName: enumDef.name });
|
|
632
|
-
else files.push({ relativePath: fileName, content, sourceName: enumDef.name });
|
|
633
|
-
if (classDir) files.push({ relativePath: `${classDir}${fileName}`, content, sourceName: enumDef.name });
|
|
634
|
-
}
|
|
635
|
-
return files;
|
|
636
|
-
}
|
|
637
|
-
function buildEnumFile(enumDef, enumOutput) {
|
|
638
|
-
const header = [
|
|
639
|
-
"/**",
|
|
640
|
-
" * ARQUIVO GERADO AUTOMATICAMENTE \u2014 N\xC3O EDITE MANUALMENTE.",
|
|
641
|
-
" * Gerado por prisma-entity-gen. Rode o gerador para atualizar.",
|
|
642
|
-
" */",
|
|
643
|
-
""
|
|
644
|
-
];
|
|
645
|
-
if (enumOutput === "union") {
|
|
646
|
-
const union = enumDef.values.map((v) => `"${v}"`).join(" | ");
|
|
647
|
-
return [...header, `export type ${enumDef.name} = ${union};`, ""].join("\n");
|
|
648
|
-
}
|
|
649
|
-
return [
|
|
650
|
-
...header,
|
|
651
|
-
`export enum ${enumDef.name} {`,
|
|
652
|
-
...enumDef.values.map((v) => ` ${v} = "${v}",`),
|
|
653
|
-
"}",
|
|
654
|
-
""
|
|
655
|
-
].join("\n");
|
|
656
|
-
}
|
|
657
|
-
async function generate(config) {
|
|
658
|
-
const logger = new Logger(config.logLevel);
|
|
659
|
-
logger.verbose(`Lendo schema: ${config.schemaPath}`);
|
|
660
|
-
const { models, enums } = parseSchema(config.schemaPath);
|
|
661
|
-
logger.info(`${models.length} models encontrados`);
|
|
662
|
-
logger.info(`${enums.length} enums encontrados`);
|
|
663
|
-
const files = buildFiles(models, enums, config);
|
|
664
|
-
logger.verbose(`${files.length} arquivos a gerar`);
|
|
665
|
-
if (config.barrel) {
|
|
666
|
-
files.push({
|
|
667
|
-
relativePath: "index.ts",
|
|
668
|
-
content: generateBarrel(files),
|
|
669
|
-
sourceName: "barrel"
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
const writer = new FileWriter(config.outputDir, config.dryRun, logger);
|
|
673
|
-
const result = writer.writeAll(files);
|
|
674
|
-
if (config.dryRun) {
|
|
675
|
-
logger.info(`${result.skipped.length} arquivos seriam gerados`);
|
|
676
|
-
} else {
|
|
677
|
-
logger.success(`${result.written.length} arquivos gerados em ${config.outputDir}`);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
// src/cli/index.ts
|
|
682
|
-
var program = new commander.Command();
|
|
683
|
-
program.name("prisma-entity-gen").description("Gera entities TypeScript a partir do schema.prisma via AST").version("0.1.0");
|
|
684
|
-
program.command("generate", { isDefault: true }).description("Gera as entities do schema.prisma").option("-s, --schema <path>", "Caminho para o schema.prisma").option("-o, --output <dir>", "Diret\xF3rio de sa\xEDda").option("-m, --mode <mode>", "Modo: type | class | both").option("--relations <mode>", "Rela\xE7\xF5es nas entities: optional | required").option("--enum-output <format>", "Formato dos enums: enum | union").option("--dry-run", "Simula sem escrever arquivos").option("--log-level <level>", "silent | info | verbose").action(async (opts) => {
|
|
685
|
-
let config;
|
|
686
|
-
try {
|
|
687
|
-
config = loadConfig();
|
|
688
|
-
} catch (err) {
|
|
689
|
-
if (err instanceof ConfigError) {
|
|
690
|
-
console.error(err.message);
|
|
691
|
-
process.exit(1);
|
|
692
|
-
}
|
|
693
|
-
throw err;
|
|
694
|
-
}
|
|
695
|
-
if (opts.schema) config = { ...config, schemaPath: opts.schema };
|
|
696
|
-
if (opts.output) config = { ...config, outputDir: opts.output };
|
|
697
|
-
if (opts.mode) config = { ...config, mode: opts.mode };
|
|
698
|
-
if (opts.relations) config = { ...config, relations: opts.relations };
|
|
699
|
-
if (opts.enumOutput) config = { ...config, enumOutput: opts.enumOutput };
|
|
700
|
-
if (opts.dryRun) config = { ...config, dryRun: true };
|
|
701
|
-
if (opts.logLevel) config = { ...config, logLevel: opts.logLevel };
|
|
702
|
-
try {
|
|
703
|
-
await generate(config);
|
|
704
|
-
} catch (err) {
|
|
705
|
-
console.error(err.message);
|
|
706
|
-
process.exit(1);
|
|
707
|
-
}
|
|
708
|
-
});
|
|
709
|
-
program.parse();
|
|
710
|
-
//# sourceMappingURL=index.cjs.map
|
|
711
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/cli/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/schema.ts","../../src/config/loader.ts","../../src/parser/types.ts","../../src/parser/relations.ts","../../src/parser/index.ts","../../src/emitters/base.ts","../../src/emitters/type.emitter.ts","../../src/emitters/class.emitter.ts","../../src/writer/file.ts","../../src/writer/barrel.ts","../../src/logger.ts","../../src/generator.ts","../../src/cli/index.ts"],"names":["z","resolve","existsSync","readFileSync","ZodError","getSchema","mkdirSync","dirname","writeFileSync","exports","Command"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from \"zod\";\n\nexport const ConfigSchema = z.object({\n /**\n * Caminho para o schema.prisma\n * @default \"prisma/schema.prisma\"\n */\n schemaPath: z.string().default(\"prisma/schema.prisma\"),\n\n /**\n * Diretório de saída das entities geradas\n * @default \"src/entities\"\n */\n outputDir: z.string().default(\"src/entities\"),\n\n /**\n * Modo de geração:\n * - \"type\" → type aliases e interfaces puras (melhor performance TS)\n * - \"class\" → classes com decorators (NestJS / class-validator)\n * - \"both\" → gera os dois em subpastas /types e /classes\n */\n mode: z.enum([\"type\", \"class\", \"both\"]).default(\"type\"),\n\n /**\n * Quando mode=\"class\", inclui decorators do class-validator\n * @default false\n */\n classValidator: z.boolean().default(false),\n\n /**\n * Quando mode=\"class\", inclui decorators do class-transformer\n * @default false\n */\n classTransformer: z.boolean().default(false),\n\n /**\n * Gera barrel index.ts na raiz do outputDir\n * @default true\n */\n barrel: z.boolean().default(true),\n\n /**\n * Modelos a ignorar na geração\n * @default []\n */\n exclude: z.array(z.string()).default([]),\n\n /**\n * Apenas esses modelos serão gerados (vazio = todos)\n * @default []\n */\n include: z.array(z.string()).default([]),\n\n /**\n * Formato de saída dos enums:\n * - \"enum\" → export enum Role { ADMIN = \"ADMIN\" }\n * - \"union\" → export type Role = \"ADMIN\" | \"USER\"\n * Use \"union\" para evitar conflitos com enums do @prisma/client\n * @default \"enum\"\n */\n enumOutput: z.enum([\"enum\", \"union\"]).default(\"enum\"),\n\n /**\n * Define se campos de relação são opcionais ou obrigatórios na entity gerada:\n * - \"optional\" → relações sempre com ? (compatível com queries sem include)\n * - \"required\" → relações sem ? (requer include em toda query que retornar o tipo)\n * @default \"optional\"\n */\n relations: z.enum([\"optional\", \"required\"]).default(\"optional\"),\n\n /**\n * Sufixo dos arquivos gerados\n * @default \"entity\"\n * Resulta em: user.entity.ts\n */\n suffix: z.string().default(\"entity\"),\n\n /**\n * Simula a geração sem escrever arquivos\n * @default false\n */\n dryRun: z.boolean().default(false),\n\n /**\n * Nível de log: \"silent\" | \"info\" | \"verbose\"\n * @default \"info\"\n */\n logLevel: z.enum([\"silent\", \"info\", \"verbose\"]).default(\"info\"),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport const DEFAULT_CONFIG: Config = ConfigSchema.parse({});\n","import { existsSync, readFileSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { ZodError } from \"zod\";\nimport { ConfigSchema, type Config } from \"./schema.js\";\n\nconst RC_FILES = [\n \".entitygenrc.json\",\n \"entitygen.config.json\",\n \".entitygenrc\",\n] as const;\n\nexport class ConfigError extends Error {\n constructor(\n message: string,\n cause?: unknown,\n ) {\n super(message, { cause });\n this.name = \"ConfigError\";\n }\n}\n\n/**\n * Carrega e valida o config do projeto.\n * Procura por RC files na ordem definida em RC_FILES.\n * Merge com defaults do zod schema.\n */\nexport function loadConfig(cwd: string = process.cwd()): Config {\n const rcFile = RC_FILES.map((f) => resolve(cwd, f)).find(existsSync);\n\n if (!rcFile) {\n return ConfigSchema.parse({});\n }\n\n let raw: unknown;\n\n try {\n raw = JSON.parse(readFileSync(rcFile, \"utf-8\"));\n } catch (err) {\n throw new ConfigError(`Falha ao ler ${rcFile}: arquivo JSON inválido`, err);\n }\n\n try {\n return ConfigSchema.parse(raw);\n } catch (err) {\n if (err instanceof ZodError) {\n const messages = err.errors\n .map((e) => ` • ${e.path.join(\".\")} — ${e.message}`)\n .join(\"\\n\");\n throw new ConfigError(\n `Config inválido em ${rcFile}:\\n${messages}`,\n err,\n );\n }\n throw err;\n }\n}\n","import type { PrismaScalar } from \"../types.js\";\n\n/**\n * Mapeamento canônico de scalars Prisma → TypeScript.\n * Enums e models relacionados são resolvidos dinamicamente pelo parser.\n */\nexport const PRISMA_TO_TS: Record<PrismaScalar, string> = {\n String: \"string\",\n Boolean: \"boolean\",\n Int: \"number\",\n BigInt: \"bigint\",\n Float: \"number\",\n Decimal: \"string\", // Decimal não tem tipo nativo TS — string é mais seguro que number\n DateTime: \"Date\",\n Json: \"Record<string, unknown>\",\n Bytes: \"Buffer\",\n};\n\nconst SCALARS = new Set(Object.keys(PRISMA_TO_TS));\n\nexport function isScalar(type: string): type is PrismaScalar {\n return SCALARS.has(type);\n}\n\nexport function resolveTsType(\n prismaType: string,\n knownEnums: Set<string>,\n): string {\n if (isScalar(prismaType)) return PRISMA_TO_TS[prismaType];\n if (knownEnums.has(prismaType)) return prismaType; // enum — mantém o nome\n return prismaType; // relation — mantém o nome do model\n}\n","/**\n * Detecta ciclos no grafo de relações entre models.\n *\n * Usa DFS com coloração de nós (white/gray/black) para identificar\n * back-edges — a técnica clássica para detecção de ciclos em grafos dirigidos.\n *\n * Retorna um Map onde cada model aponta para o conjunto de models\n * com os quais forma um ciclo.\n *\n * Exemplo:\n * User → Post → User → { User: Set(['Post']), Post: Set(['User']) }\n */\nexport function detectCircularRefs(\n graph: Map<string, string[]>,\n): Map<string, Set<string>> {\n type Color = \"white\" | \"gray\" | \"black\";\n\n const color = new Map<string, Color>();\n const circular = new Map<string, Set<string>>();\n\n for (const node of graph.keys()) {\n color.set(node, \"white\");\n circular.set(node, new Set());\n }\n\n function addCircular(a: string, b: string): void {\n circular.get(a)?.add(b);\n circular.get(b)?.add(a);\n }\n\n function dfs(node: string, ancestors: string[]): void {\n color.set(node, \"gray\");\n\n for (const neighbor of graph.get(node) ?? []) {\n if (!color.has(neighbor)) continue; // neighbor não é model (é scalar/enum)\n\n if (color.get(neighbor) === \"gray\") {\n // Back-edge encontrado — ciclo detectado\n addCircular(node, neighbor);\n\n // Propaga para todos os ancestrais no caminho atual\n for (const anc of ancestors) {\n if (color.get(anc) === \"gray\") {\n addCircular(anc, neighbor);\n addCircular(node, anc);\n }\n }\n } else if (color.get(neighbor) === \"white\") {\n dfs(neighbor, [...ancestors, node]);\n }\n }\n\n color.set(node, \"black\");\n }\n\n for (const node of graph.keys()) {\n if (color.get(node) === \"white\") {\n dfs(node, []);\n }\n }\n\n return circular;\n}\n","import { readFileSync } from \"fs\";\nimport { getSchema } from \"@mrleebo/prisma-ast\";\nimport type {\n ParsedSchema,\n ModelDefinition,\n EnumDefinition,\n FieldDefinition,\n} from \"../types.js\";\nimport { resolveTsType } from \"./types.js\";\nimport { detectCircularRefs } from \"./relations.js\";\n\n// ─── tipos internos do @mrleebo/prisma-ast ────────────────────────────────────\n\ninterface AstField {\n type: \"field\";\n name: string;\n fieldType: string;\n array: boolean;\n optional: boolean;\n attributes?: AstAttribute[];\n comment?: string;\n}\n\ninterface AstAttribute {\n type: \"attribute\";\n name: string;\n kind: \"field\" | \"model\";\n args?: Array<{ type: string; value: unknown }>;\n}\n\ninterface AstModel {\n type: \"model\";\n name: string;\n properties: Array<AstField | { type: string }>;\n comment?: string;\n}\n\ninterface AstEnumerator {\n type: \"enumerator\";\n name: string;\n}\n\ninterface AstEnum {\n type: \"enum\";\n name: string;\n enumerators: Array<AstEnumerator | { type: string }>;\n comment?: string;\n}\n\n// ─── helpers ──────────────────────────────────────────────────────────────────\n\nfunction hasAttribute(field: AstField, name: string): boolean {\n return field.attributes?.some((a) => a.name === name) ?? false;\n}\n\nfunction hasDefault(field: AstField): boolean {\n return hasAttribute(field, \"default\") || hasAttribute(field, \"updatedAt\");\n}\n\n// ─── parsers internos ─────────────────────────────────────────────────────────\n\nfunction parseEnum(node: AstEnum): EnumDefinition {\n const values = node.enumerators\n .filter((e): e is AstEnumerator => e.type === \"enumerator\")\n .map((e) => e.name);\n return { name: node.name, values, documentation: node.comment };\n}\n\nfunction parseField(\n field: AstField,\n knownModels: Set<string>,\n knownEnums: Set<string>,\n): FieldDefinition {\n return {\n name: field.name,\n prismaType: field.fieldType,\n tsType: resolveTsType(field.fieldType, knownEnums),\n isOptional: field.optional,\n isArray: field.array,\n isRelation: knownModels.has(field.fieldType),\n isCircular: false,\n hasDefault: hasDefault(field),\n isId: hasAttribute(field, \"id\"),\n isUnique: hasAttribute(field, \"unique\"),\n isUpdatedAt: hasAttribute(field, \"updatedAt\"),\n decorators: [],\n };\n}\n\nfunction parseModel(\n node: AstModel,\n knownModels: Set<string>,\n knownEnums: Set<string>,\n): ModelDefinition {\n const fields = node.properties\n .filter((p): p is AstField => p.type === \"field\")\n .map((f) => parseField(f, knownModels, knownEnums));\n\n const relations = [...new Set(\n fields.filter((f) => f.isRelation).map((f) => f.prismaType),\n )];\n\n return {\n name: node.name,\n fields,\n relations,\n circularRefs: [],\n documentation: node.comment,\n };\n}\n\n// ─── entry points ─────────────────────────────────────────────────────────────\n\nexport class ParseError extends Error {\n constructor(message: string, cause?: unknown) {\n super(message, { cause });\n this.name = \"ParseError\";\n }\n}\n\nexport function parseSchema(schemaPath: string): ParsedSchema {\n let raw: string;\n try {\n raw = readFileSync(schemaPath, \"utf-8\");\n } catch (err) {\n throw new ParseError(`Não foi possível ler o schema em \"${schemaPath}\"`, err);\n }\n return parseSchemaString(raw);\n}\n\nexport function parseSchemaString(schemaContent: string): ParsedSchema {\n let ast: ReturnType<typeof getSchema>;\n try {\n ast = getSchema(schemaContent);\n } catch (err) {\n throw new ParseError(\"Falha ao fazer parse do schema Prisma\", err);\n }\n\n const rawNodes = ast.list as Array<{ type: string }>;\n\n const knownModels = new Set(\n rawNodes.filter((n) => n.type === \"model\").map((n) => (n as AstModel).name),\n );\n const knownEnums = new Set(\n rawNodes.filter((n) => n.type === \"enum\").map((n) => (n as AstEnum).name),\n );\n\n const enums = rawNodes\n .filter((n) => n.type === \"enum\")\n .map((n) => parseEnum(n as AstEnum));\n\n const models = rawNodes\n .filter((n) => n.type === \"model\")\n .map((n) => parseModel(n as AstModel, knownModels, knownEnums));\n\n // Detecta e marca referências circulares\n const graph = new Map(models.map((m) => [m.name, m.relations]));\n const circularMap = detectCircularRefs(graph);\n\n for (const model of models) {\n const circulars = circularMap.get(model.name) ?? new Set<string>();\n model.circularRefs = [...circulars];\n for (const field of model.fields) {\n if (field.isRelation && circulars.has(field.prismaType)) {\n field.isCircular = true;\n }\n }\n }\n\n return { models, enums };\n}\n","import type { IEmitter, ModelDefinition, EnumDefinition } from \"../types.js\";\n\nexport type { IEmitter };\n\n/**\n * Converte PascalCase para kebab-case\n * UserProfile → user-profile\n */\nexport function toKebab(name: string): string {\n return name\n .replace(/([a-z])([A-Z])/g, \"$1-$2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1-$2\")\n .toLowerCase();\n}\n\n/**\n * Gera o cabeçalho padrão de cada arquivo entity.\n * Inclui aviso de \"não editar manualmente\" e timestamp.\n */\nexport function fileHeader(): string {\n return [\n \"/**\",\n \" * ARQUIVO GERADO AUTOMATICAMENTE — NÃO EDITE MANUALMENTE.\",\n \" * Gerado por prisma-entity-gen. Rode o gerador para atualizar.\",\n \" */\",\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * Formata um campo TS com a tipagem correta, incluindo array e opcional.\n * Ex: posts: Post[] | name?: string\n */\nexport function formatFieldType(\n tsType: string,\n isArray: boolean,\n isOptional: boolean,\n isCircular: boolean,\n): string {\n // Referências circulares usam lazy type via interface para não travar o TS\n const base = isArray ? `${tsType}[]` : tsType;\n const nullable = isOptional ? ` | null` : \"\";\n return `${base}${nullable}`;\n}\n\n/**\n * Gera o bloco de documentação JSDoc a partir de um comentário Prisma.\n */\nexport function formatJsDoc(doc?: string): string {\n if (!doc) return \"\";\n const lines = doc\n .split(\"\\n\")\n .map((l) => ` * ${l.trim()}`)\n .join(\"\\n\");\n return `/**\\n${lines}\\n */\\n`;\n}\n\nexport abstract class BaseEmitter implements IEmitter {\n abstract emit(model: ModelDefinition, enums: EnumDefinition[]): string;\n}\n","import type { ModelDefinition, EnumDefinition, FieldDefinition } from \"../types.js\";\nimport {\n BaseEmitter,\n fileHeader,\n formatFieldType,\n formatJsDoc,\n} from \"./base.js\";\n\nfunction toKebab(name: string): string {\n return name\n .replace(/([a-z])([A-Z])/g, \"$1-$2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1-$2\")\n .toLowerCase();\n}\n\nexport interface TypeEmitterOptions {\n relations?: \"optional\" | \"required\";\n}\n\nexport class TypeEmitter extends BaseEmitter {\n constructor(private readonly options: TypeEmitterOptions = {}) {\n super();\n }\n\n emit(model: ModelDefinition, enums: EnumDefinition[]): string {\n const enumNames = new Set(enums.map((e) => e.name));\n const lines: string[] = [fileHeader()];\n\n // Imports de relações\n const relationImports = this.collectRelationImports(model, enumNames);\n if (relationImports.length > 0) {\n for (const imp of relationImports) lines.push(imp);\n lines.push(\"\");\n }\n\n // Imports de enums\n const enumImports = this.collectEnumImports(model, enumNames);\n if (enumImports.length > 0) {\n for (const imp of enumImports) lines.push(imp);\n lines.push(\"\");\n }\n\n // Interface principal — todos os campos, fiel ao schema\n // O BaseRepository compõe Omit/Partial sobre essa interface\n if (model.documentation) lines.push(formatJsDoc(model.documentation));\n lines.push(`export interface ${model.name}Entity {`);\n for (const field of model.fields) {\n lines.push(` ${this.formatField(field)}`);\n }\n lines.push(\"}\");\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n }\n\n private formatField(field: FieldDefinition): string {\n // isOptional (campo nullable no schema) — opcional com | null\n // hasDefault — obrigatório na entity (sempre vem do banco preenchido)\n // relações — opcional ou obrigatório conforme config (default: optional)\n const relationsOptional = this.options.relations !== \"required\";\n const optional = (field.isRelation && relationsOptional) || field.isOptional ? \"?\" : \"\";\n\n // Relações usam XxxEntity — interfaces são lazy no TS, suporta ciclos\n const tsType = field.isRelation\n ? `${field.prismaType}Entity`\n : field.tsType;\n\n const type = formatFieldType(tsType, field.isArray, field.isOptional, field.isCircular);\n return `${field.name}${optional}: ${type};`;\n }\n\n private collectRelationImports(\n model: ModelDefinition,\n enumNames: Set<string>,\n ): string[] {\n const seen = new Set<string>();\n const imports: string[] = [];\n\n for (const field of model.fields) {\n if (\n field.isRelation &&\n !enumNames.has(field.prismaType) &&\n !seen.has(field.prismaType) &&\n field.prismaType !== model.name // ignora self-relation\n ) {\n seen.add(field.prismaType);\n imports.push(\n `import type { ${field.prismaType}Entity } from \"./${toKebab(field.prismaType)}.entity.js\";`,\n );\n }\n }\n\n return imports;\n }\n\n private collectEnumImports(\n model: ModelDefinition,\n enumNames: Set<string>,\n ): string[] {\n const seen = new Set<string>();\n const imports: string[] = [];\n\n for (const field of model.fields) {\n if (enumNames.has(field.prismaType) && !seen.has(field.prismaType)) {\n seen.add(field.prismaType);\n imports.push(\n `import { ${field.prismaType} } from \"./${toKebab(field.prismaType)}.enum.js\";`,\n );\n }\n }\n\n return imports;\n }\n}\n","import type { ModelDefinition, EnumDefinition, FieldDefinition } from \"../types.js\";\nimport {\n BaseEmitter,\n fileHeader,\n formatFieldType,\n formatJsDoc,\n} from \"./base.js\";\n\nexport interface ClassEmitterOptions {\n classValidator?: boolean;\n classTransformer?: boolean;\n}\n\nexport class ClassEmitter extends BaseEmitter {\n constructor(private readonly options: ClassEmitterOptions = {}) {\n super();\n }\n\n emit(model: ModelDefinition, enums: EnumDefinition[]): string {\n const enumNames = new Set(enums.map((e) => e.name));\n const lines: string[] = [fileHeader()];\n\n // Imports de decorators\n const cvImports = this.collectCvImports(model, enumNames);\n if (this.options.classValidator && cvImports.length > 0) {\n lines.push(`import { ${cvImports.join(\", \")} } from \"class-validator\";`);\n }\n if (this.options.classTransformer) {\n lines.push(`import { Type } from \"class-transformer\";`);\n }\n if (\n (this.options.classValidator && cvImports.length > 0) ||\n this.options.classTransformer\n ) {\n lines.push(\"\");\n }\n\n // Imports de relações\n const relationImports = this.collectRelationImports(model, enumNames);\n if (relationImports.length > 0) {\n for (const imp of relationImports) lines.push(imp);\n lines.push(\"\");\n }\n\n // Enum imports\n const enumImports = this.collectEnumImports(model, enumNames);\n if (enumImports.length > 0) {\n for (const imp of enumImports) lines.push(imp);\n lines.push(\"\");\n }\n\n // Classe principal\n if (model.documentation) lines.push(formatJsDoc(model.documentation));\n lines.push(`export class ${model.name}Entity {`);\n\n for (const field of model.fields) {\n const fieldLines = this.formatField(field, enumNames);\n for (const l of fieldLines) lines.push(` ${l}`);\n }\n\n lines.push(\"}\");\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n }\n\n private formatField(\n field: FieldDefinition,\n enumNames: Set<string>,\n ): string[] {\n const lines: string[] = [];\n\n if (this.options.classValidator) {\n const decorators = this.getCvDecorators(field, enumNames);\n for (const d of decorators) lines.push(d);\n }\n\n if (this.options.classTransformer && field.isRelation && !field.isCircular) {\n lines.push(`@Type(() => ${field.tsType}Entity)`);\n }\n\n const optional = field.isOptional || field.hasDefault ? \"?\" : \"!\";\n const type = formatFieldType(\n field.isRelation && !field.isCircular\n ? `${field.tsType}Entity`\n : field.tsType,\n field.isArray,\n field.isOptional,\n field.isCircular,\n );\n const comment = field.isCircular ? \" // circular ref — usar Ref\" : \"\";\n lines.push(`${field.name}${optional}: ${type};${comment}`);\n lines.push(\"\");\n\n return lines;\n }\n\n private getCvDecorators(\n field: FieldDefinition,\n enumNames: Set<string>,\n ): string[] {\n const decorators: string[] = [];\n\n if (field.isOptional || field.hasDefault) {\n decorators.push(\"@IsOptional()\");\n }\n\n if (field.isArray) {\n decorators.push(\"@IsArray()\");\n }\n\n if (field.isRelation || enumNames.has(field.prismaType)) {\n return decorators; // relações e enums não têm decorators de tipo primitivo\n }\n\n switch (field.prismaType) {\n case \"String\":\n decorators.push(\"@IsString()\");\n break;\n case \"Boolean\":\n decorators.push(\"@IsBoolean()\");\n break;\n case \"Int\":\n case \"Float\":\n case \"Decimal\":\n decorators.push(\"@IsNumber()\");\n break;\n case \"BigInt\":\n decorators.push(\"@IsInt()\");\n break;\n case \"DateTime\":\n decorators.push(\"@IsDate()\");\n break;\n }\n\n return decorators;\n }\n\n private collectCvImports(\n model: ModelDefinition,\n enumNames: Set<string>,\n ): string[] {\n const imports = new Set<string>();\n\n for (const field of model.fields) {\n if (field.isOptional || field.hasDefault) imports.add(\"IsOptional\");\n if (field.isArray) imports.add(\"IsArray\");\n if (field.isRelation || enumNames.has(field.prismaType)) continue;\n\n switch (field.prismaType) {\n case \"String\": imports.add(\"IsString\"); break;\n case \"Boolean\": imports.add(\"IsBoolean\"); break;\n case \"Int\":\n case \"Float\":\n case \"Decimal\": imports.add(\"IsNumber\"); break;\n case \"BigInt\": imports.add(\"IsInt\"); break;\n case \"DateTime\": imports.add(\"IsDate\"); break;\n }\n }\n\n return [...imports].sort();\n }\n\n private collectRelationImports(\n model: ModelDefinition,\n enumNames: Set<string>,\n ): string[] {\n const seen = new Set<string>();\n const imports: string[] = [];\n\n for (const field of model.fields) {\n if (\n field.isRelation &&\n !field.isCircular &&\n !enumNames.has(field.prismaType) &&\n !seen.has(field.prismaType)\n ) {\n seen.add(field.prismaType);\n const fileName = field.prismaType\n .replace(/([a-z])([A-Z])/g, \"$1-$2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1-$2\")\n .toLowerCase();\n imports.push(\n `import { ${field.prismaType}Entity } from \"./${fileName}.entity.js\";`,\n );\n }\n }\n\n return imports;\n }\n\n private collectEnumImports(\n model: ModelDefinition,\n enumNames: Set<string>,\n ): string[] {\n const seen = new Set<string>();\n const imports: string[] = [];\n\n for (const field of model.fields) {\n if (enumNames.has(field.prismaType) && !seen.has(field.prismaType)) {\n seen.add(field.prismaType);\n const fileName = field.prismaType\n .replace(/([a-z])([A-Z])/g, \"$1-$2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1-$2\")\n .toLowerCase();\n imports.push(\n `import { ${field.prismaType} } from \"./${fileName}.enum.js\";`,\n );\n }\n }\n\n return imports;\n }\n}\n","import { mkdirSync, writeFileSync, existsSync } from \"fs\";\nimport { resolve, dirname } from \"path\";\nimport type { GeneratedFile } from \"../types.js\";\nimport type { Logger } from \"../logger.js\";\n\nexport interface WriteResult {\n written: string[];\n skipped: string[];\n}\n\nexport class FileWriter {\n constructor(\n private readonly outputDir: string,\n private readonly dryRun: boolean,\n private readonly logger: Logger,\n ) {}\n\n writeAll(files: GeneratedFile[]): WriteResult {\n const result: WriteResult = { written: [], skipped: [] };\n\n if (!this.dryRun) {\n mkdirSync(resolve(this.outputDir), { recursive: true });\n }\n\n for (const file of files) {\n const absPath = resolve(this.outputDir, file.relativePath);\n\n if (this.dryRun) {\n this.logger.info(`[dry-run] ${file.relativePath}`);\n result.skipped.push(absPath);\n continue;\n }\n\n mkdirSync(dirname(absPath), { recursive: true });\n writeFileSync(absPath, file.content, \"utf-8\");\n this.logger.success(file.relativePath);\n result.written.push(absPath);\n }\n\n return result;\n }\n}\n","import type { GeneratedFile } from \"../types.js\";\nimport { fileHeader } from \"../emitters/base.js\";\n\n/**\n * Gera o arquivo index.ts (barrel) que re-exporta todas as entities.\n * Facilita imports no projeto: import { UserEntity } from '@/entities'\n */\nexport function generateBarrel(files: GeneratedFile[]): string {\n const exports = files\n .filter((f) => !f.relativePath.endsWith(\"index.ts\"))\n .map((f) => {\n // Remove extensão .ts para o import path\n const path = f.relativePath.replace(/\\.ts$/, \".js\");\n return `export * from \"./${path}\";`;\n })\n .sort();\n\n return [fileHeader(), ...exports, \"\"].join(\"\\n\");\n}\n","import type { Config } from \"./config/schema.js\";\n\ntype LogLevel = Config[\"logLevel\"];\n\nconst LEVELS: Record<LogLevel, number> = {\n silent: 0,\n info: 1,\n verbose: 2,\n};\n\nexport class Logger {\n private readonly level: number;\n\n constructor(logLevel: LogLevel = \"info\") {\n this.level = LEVELS[logLevel];\n }\n\n info(msg: string): void {\n if (this.level >= LEVELS.info) {\n console.log(` ${msg}`);\n }\n }\n\n verbose(msg: string): void {\n if (this.level >= LEVELS.verbose) {\n console.log(` [verbose] ${msg}`);\n }\n }\n\n success(msg: string): void {\n if (this.level >= LEVELS.info) {\n console.log(` ✓ ${msg}`);\n }\n }\n\n warn(msg: string): void {\n if (this.level >= LEVELS.info) {\n console.warn(` ⚠ ${msg}`);\n }\n }\n\n error(msg: string): void {\n console.error(` ✗ ${msg}`);\n }\n}\n","import type { Config } from \"./config/schema.js\";\nimport type { GeneratedFile, ModelDefinition, EnumDefinition } from \"./types.js\";\nimport { parseSchema } from \"./parser/index.js\";\nimport { TypeEmitter } from \"./emitters/type.emitter.js\";\nimport { ClassEmitter } from \"./emitters/class.emitter.js\";\nimport { FileWriter } from \"./writer/file.js\";\nimport { generateBarrel } from \"./writer/barrel.js\";\nimport { Logger } from \"./logger.js\";\n\nfunction toKebabCase(name: string): string {\n return name\n .replace(/([a-z])([A-Z])/g, \"$1-$2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1-$2\")\n .toLowerCase();\n}\n\nfunction shouldInclude(name: string, config: Config): boolean {\n if (config.include.length > 0 && !config.include.includes(name)) return false;\n if (config.exclude.includes(name)) return false;\n return true;\n}\n\nfunction buildFiles(\n models: ModelDefinition[],\n enums: EnumDefinition[],\n config: Config,\n): GeneratedFile[] {\n const files: GeneratedFile[] = [];\n\n const useType = config.mode === \"type\" || config.mode === \"both\";\n const useClass = config.mode === \"class\" || config.mode === \"both\";\n\n const typeEmitter = useType ? new TypeEmitter({ relations: config.relations }) : null;\n const classEmitter = useClass\n ? new ClassEmitter({\n classValidator: config.classValidator,\n classTransformer: config.classTransformer,\n })\n : null;\n\n const typeDir = config.mode === \"both\" ? \"types/\" : \"\";\n const classDir = config.mode === \"both\" ? \"classes/\" : \"\";\n\n for (const model of models) {\n if (!shouldInclude(model.name, config)) continue;\n\n const fileName = `${toKebabCase(model.name)}.${config.suffix}.ts`;\n\n if (typeEmitter) {\n files.push({\n relativePath: `${typeDir}${fileName}`,\n content: typeEmitter.emit(model, enums),\n sourceName: model.name,\n });\n }\n\n if (classEmitter) {\n files.push({\n relativePath: `${classDir}${fileName}`,\n content: classEmitter.emit(model, enums),\n sourceName: model.name,\n });\n }\n }\n\n // Enums — gerados como arquivos separados\n for (const enumDef of enums) {\n if (!shouldInclude(enumDef.name, config)) continue;\n\n const fileName = `${toKebabCase(enumDef.name)}.enum.ts`;\n const content = buildEnumFile(enumDef, config.enumOutput);\n\n if (typeDir) files.push({ relativePath: `${typeDir}${fileName}`, content, sourceName: enumDef.name });\n else files.push({ relativePath: fileName, content, sourceName: enumDef.name });\n\n if (classDir) files.push({ relativePath: `${classDir}${fileName}`, content, sourceName: enumDef.name });\n }\n\n return files;\n}\n\nfunction buildEnumFile(enumDef: EnumDefinition, enumOutput: \"enum\" | \"union\"): string {\n const header = [\n \"/**\",\n \" * ARQUIVO GERADO AUTOMATICAMENTE — NÃO EDITE MANUALMENTE.\",\n \" * Gerado por prisma-entity-gen. Rode o gerador para atualizar.\",\n \" */\",\n \"\",\n ];\n\n if (enumOutput === \"union\") {\n const union = enumDef.values.map((v) => `\"${v}\"`).join(\" | \");\n return [...header, `export type ${enumDef.name} = ${union};`, \"\"].join(\"\\n\");\n }\n\n return [\n ...header,\n `export enum ${enumDef.name} {`,\n ...enumDef.values.map((v) => ` ${v} = \"${v}\",`),\n \"}\",\n \"\",\n ].join(\"\\n\");\n}\n\nexport async function generate(config: Config): Promise<void> {\n const logger = new Logger(config.logLevel);\n\n logger.verbose(`Lendo schema: ${config.schemaPath}`);\n const { models, enums } = parseSchema(config.schemaPath);\n\n logger.info(`${models.length} models encontrados`);\n logger.info(`${enums.length} enums encontrados`);\n\n const files = buildFiles(models, enums, config);\n logger.verbose(`${files.length} arquivos a gerar`);\n\n if (config.barrel) {\n files.push({\n relativePath: \"index.ts\",\n content: generateBarrel(files),\n sourceName: \"barrel\",\n });\n }\n\n const writer = new FileWriter(config.outputDir, config.dryRun, logger);\n const result = writer.writeAll(files);\n\n if (config.dryRun) {\n logger.info(`${result.skipped.length} arquivos seriam gerados`);\n } else {\n logger.success(`${result.written.length} arquivos gerados em ${config.outputDir}`);\n }\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { loadConfig, ConfigError } from \"../config/loader.js\";\nimport { generate } from \"../generator.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"prisma-entity-gen\")\n .description(\"Gera entities TypeScript a partir do schema.prisma via AST\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"generate\", { isDefault: true })\n .description(\"Gera as entities do schema.prisma\")\n .option(\"-s, --schema <path>\", \"Caminho para o schema.prisma\")\n .option(\"-o, --output <dir>\", \"Diretório de saída\")\n .option(\"-m, --mode <mode>\", \"Modo: type | class | both\")\n .option(\"--relations <mode>\", \"Relações nas entities: optional | required\")\n .option(\"--enum-output <format>\", \"Formato dos enums: enum | union\")\n .option(\"--dry-run\", \"Simula sem escrever arquivos\")\n .option(\"--log-level <level>\", \"silent | info | verbose\")\n .action(async (opts) => {\n let config;\n\n try {\n config = loadConfig();\n } catch (err) {\n if (err instanceof ConfigError) {\n console.error(err.message);\n process.exit(1);\n }\n throw err;\n }\n\n if (opts.schema) config = { ...config, schemaPath: opts.schema };\n if (opts.output) config = { ...config, outputDir: opts.output };\n if (opts.mode) config = { ...config, mode: opts.mode };\n if (opts.relations) config = { ...config, relations: opts.relations };\n if (opts.enumOutput) config = { ...config, enumOutput: opts.enumOutput };\n if (opts.dryRun) config = { ...config, dryRun: true };\n if (opts.logLevel) config = { ...config, logLevel: opts.logLevel };\n\n try {\n await generate(config);\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
|
package/dist/cli/index.d.cts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|