@vibeorm/generator 1.3.1 → 2.0.0-alpha.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 +43 -39
- package/dist/emit-dts.d.ts +24 -0
- package/dist/emit-dts.d.ts.map +1 -0
- package/dist/emit-js.d.ts +18 -0
- package/dist/emit-js.d.ts.map +1 -0
- package/dist/extension-bake.d.ts +42 -0
- package/dist/extension-bake.d.ts.map +1 -0
- package/dist/generate.d.ts +28 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1521 -0
- package/dist/index.js.map +16 -0
- package/dist/schema-view.d.ts +77 -0
- package/dist/schema-view.d.ts.map +1 -0
- package/dist/type-names.d.ts +30 -0
- package/dist/type-names.d.ts.map +1 -0
- package/dist/util.d.ts +39 -0
- package/dist/util.d.ts.map +1 -0
- package/package.json +29 -23
- package/src/generate.ts +0 -70
- package/src/generators/generate-args.ts +0 -322
- package/src/generators/generate-client.ts +0 -252
- package/src/generators/generate-delegates.ts +0 -590
- package/src/generators/generate-enums.ts +0 -28
- package/src/generators/generate-inputs.ts +0 -655
- package/src/generators/generate-models.ts +0 -130
- package/src/generators/generate-result.ts +0 -182
- package/src/generators/generate-schemas.ts +0 -474
- package/src/generators/generate-view-types.ts +0 -446
- package/src/index.ts +0 -2
- package/src/utils.ts +0 -51
|
@@ -1,590 +0,0 @@
|
|
|
1
|
-
import type { Model, Schema, ScalarField } from "@vibeorm/parser";
|
|
2
|
-
import { fileHeader, toCamelCase } from "../utils.ts";
|
|
3
|
-
|
|
4
|
-
const NUMERIC_PRISMA_TYPES = new Set(["Int", "Float", "Decimal", "BigInt"]);
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Generates delegate interfaces for each model.
|
|
8
|
-
* These are the user-facing APIs: db.user.findMany(), db.post.create(), etc.
|
|
9
|
-
*
|
|
10
|
-
* Each method uses a generic parameter to capture the exact literal type
|
|
11
|
-
* of the args object, enabling TypeScript to narrow the return type
|
|
12
|
-
* through the GetFindResult conditional type.
|
|
13
|
-
*/
|
|
14
|
-
export function generateDelegates(params: { schema: Schema }): string {
|
|
15
|
-
const { schema } = params;
|
|
16
|
-
const parts: string[] = [fileHeader()];
|
|
17
|
-
|
|
18
|
-
// Imports
|
|
19
|
-
const argsImports = schema.models
|
|
20
|
-
.flatMap((m) => [
|
|
21
|
-
`${m.name}FindManyArgs`,
|
|
22
|
-
`${m.name}FindFirstArgs`,
|
|
23
|
-
`${m.name}FindUniqueArgs`,
|
|
24
|
-
`${m.name}CreateArgs`,
|
|
25
|
-
`${m.name}CreateManyArgs`,
|
|
26
|
-
`${m.name}CreateManyAndReturnArgs`,
|
|
27
|
-
`${m.name}UpdateArgs`,
|
|
28
|
-
`${m.name}UpsertArgs`,
|
|
29
|
-
`${m.name}DeleteArgs`,
|
|
30
|
-
`${m.name}DeleteManyArgs`,
|
|
31
|
-
`${m.name}UpdateManyArgs`,
|
|
32
|
-
`${m.name}CountArgs`,
|
|
33
|
-
`${m.name}AggregateArgs`,
|
|
34
|
-
`${m.name}GroupByArgs`,
|
|
35
|
-
])
|
|
36
|
-
.join(", ");
|
|
37
|
-
parts.push(`import type { ${argsImports} } from "./args.ts";`);
|
|
38
|
-
|
|
39
|
-
const payloadImports = schema.models
|
|
40
|
-
.map((m) => `$${m.name}Payload`)
|
|
41
|
-
.join(", ");
|
|
42
|
-
|
|
43
|
-
// Include JsonValue if any model has Json scalar fields (used in aggregate/groupBy types)
|
|
44
|
-
const hasJsonField = schema.models.some((m) =>
|
|
45
|
-
m.fields.some((f) => f.kind === "scalar" && f.prismaType === "Json")
|
|
46
|
-
);
|
|
47
|
-
const extraImports = hasJsonField ? ", JsonValue" : "";
|
|
48
|
-
parts.push(`import type { ${payloadImports}${extraImports} } from "./models.ts";`);
|
|
49
|
-
|
|
50
|
-
parts.push(`import type { GetResult, Exact } from "./result.ts";`);
|
|
51
|
-
|
|
52
|
-
// Import enums if any models have enum fields
|
|
53
|
-
if (schema.enums.length > 0) {
|
|
54
|
-
const enumImports = schema.enums.map((e) => e.name).join(", ");
|
|
55
|
-
parts.push(`import type { ${enumImports} } from "./enums.ts";`);
|
|
56
|
-
}
|
|
57
|
-
parts.push("");
|
|
58
|
-
|
|
59
|
-
// Generate delegate for each model
|
|
60
|
-
for (const model of schema.models) {
|
|
61
|
-
parts.push(generateModelDelegate({ model }));
|
|
62
|
-
parts.push(generateAggregateResultType({ model }));
|
|
63
|
-
parts.push(generateGroupByResultType({ model }));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return parts.join("\n");
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function generateModelDelegate(params: { model: Model }): string {
|
|
70
|
-
const { model } = params;
|
|
71
|
-
const p = `$${model.name}Payload`;
|
|
72
|
-
const modelVar = toCamelCase({ str: model.name });
|
|
73
|
-
|
|
74
|
-
const findManyWhereBlock = buildFindManyWhereBlock({ model });
|
|
75
|
-
const uniqueWhereBlock = buildUniqueWhereBlock({ model });
|
|
76
|
-
const createDataBlock = buildObjectBlock({
|
|
77
|
-
key: "data",
|
|
78
|
-
lines: getExampleDataLines({ model }),
|
|
79
|
-
});
|
|
80
|
-
const updateDataBlock = buildObjectBlock({
|
|
81
|
-
key: "data",
|
|
82
|
-
lines: getExampleUpdateLines({ model }),
|
|
83
|
-
});
|
|
84
|
-
const createManyDataBlock = buildArrayOfObjectsBlock({
|
|
85
|
-
key: "data",
|
|
86
|
-
lines: getExampleDataLines({ model }),
|
|
87
|
-
});
|
|
88
|
-
const upsertCreateBlock = buildObjectBlock({
|
|
89
|
-
key: "create",
|
|
90
|
-
lines: getExampleDataLines({ model }),
|
|
91
|
-
});
|
|
92
|
-
const upsertUpdateBlock = buildObjectBlock({
|
|
93
|
-
key: "update",
|
|
94
|
-
lines: getExampleUpdateLines({ model }),
|
|
95
|
-
});
|
|
96
|
-
const includeBlock = buildIncludeBlock({ model });
|
|
97
|
-
const orderByField = getOrderByFieldName({ model });
|
|
98
|
-
|
|
99
|
-
return `/**
|
|
100
|
-
* Delegate API for the ${model.name} model.
|
|
101
|
-
* Access this via \`db.${modelVar}\`.
|
|
102
|
-
*/
|
|
103
|
-
export type ${model.name}Delegate = {
|
|
104
|
-
/**
|
|
105
|
-
* Find zero or more ${model.name} records.
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* const rows = await db.${modelVar}.findMany();
|
|
109
|
-
*
|
|
110
|
-
* @example
|
|
111
|
-
* const filteredRows = await db.${modelVar}.findMany({
|
|
112
|
-
${findManyWhereBlock}
|
|
113
|
-
* });
|
|
114
|
-
*
|
|
115
|
-
* @example
|
|
116
|
-
* const page = await db.${modelVar}.findMany({
|
|
117
|
-
${findManyWhereBlock}${includeBlock}
|
|
118
|
-
* orderBy: {
|
|
119
|
-
* ${orderByField}: "desc",
|
|
120
|
-
* },
|
|
121
|
-
* take: 20,
|
|
122
|
-
* skip: 0,
|
|
123
|
-
* });
|
|
124
|
-
*/
|
|
125
|
-
findMany<T extends ${model.name}FindManyArgs>(
|
|
126
|
-
args?: Exact<T, ${model.name}FindManyArgs>,
|
|
127
|
-
): Promise<GetResult<${p}, T, "findMany">>;
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Find the first ${model.name} record matching a filter.
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* const row = await db.${modelVar}.findFirst({
|
|
134
|
-
${findManyWhereBlock}
|
|
135
|
-
* orderBy: {
|
|
136
|
-
* ${orderByField}: "desc",
|
|
137
|
-
* },
|
|
138
|
-
* });
|
|
139
|
-
*/
|
|
140
|
-
findFirst<T extends ${model.name}FindFirstArgs>(
|
|
141
|
-
args?: Exact<T, ${model.name}FindFirstArgs>,
|
|
142
|
-
): Promise<GetResult<${p}, T, "findFirst">>;
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Find one ${model.name} record by a unique field.
|
|
146
|
-
*
|
|
147
|
-
* @example
|
|
148
|
-
* const row = await db.${modelVar}.findUnique({
|
|
149
|
-
${uniqueWhereBlock}
|
|
150
|
-
* });
|
|
151
|
-
*/
|
|
152
|
-
findUnique<T extends ${model.name}FindUniqueArgs>(
|
|
153
|
-
args: Exact<T, ${model.name}FindUniqueArgs>,
|
|
154
|
-
): Promise<GetResult<${p}, T, "findUnique">>;
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Find one ${model.name} record by a unique field, or throw if not found.
|
|
158
|
-
*
|
|
159
|
-
* @example
|
|
160
|
-
* const row = await db.${modelVar}.findUniqueOrThrow({
|
|
161
|
-
${uniqueWhereBlock}
|
|
162
|
-
* });
|
|
163
|
-
*/
|
|
164
|
-
findUniqueOrThrow<T extends ${model.name}FindUniqueArgs>(
|
|
165
|
-
args: Exact<T, ${model.name}FindUniqueArgs>,
|
|
166
|
-
): Promise<GetResult<${p}, T, "findUniqueOrThrow">>;
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Find the first ${model.name} record matching a filter, or throw if not found.
|
|
170
|
-
*/
|
|
171
|
-
findFirstOrThrow<T extends ${model.name}FindFirstArgs>(
|
|
172
|
-
args?: Exact<T, ${model.name}FindFirstArgs>,
|
|
173
|
-
): Promise<GetResult<${p}, T, "findFirstOrThrow">>;
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Create one ${model.name} record.
|
|
177
|
-
*
|
|
178
|
-
* @example
|
|
179
|
-
* const row = await db.${modelVar}.create({
|
|
180
|
-
${createDataBlock}
|
|
181
|
-
* });
|
|
182
|
-
*/
|
|
183
|
-
create<T extends ${model.name}CreateArgs>(
|
|
184
|
-
args: Exact<T, ${model.name}CreateArgs>,
|
|
185
|
-
): Promise<GetResult<${p}, T, "create">>;
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Create multiple ${model.name} records in one query.
|
|
189
|
-
*
|
|
190
|
-
* @example
|
|
191
|
-
* const result = await db.${modelVar}.createMany({
|
|
192
|
-
${createManyDataBlock}
|
|
193
|
-
* skipDuplicates: true,
|
|
194
|
-
* });
|
|
195
|
-
*/
|
|
196
|
-
createMany(
|
|
197
|
-
args: ${model.name}CreateManyArgs,
|
|
198
|
-
): Promise<{ count: number }>;
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Create multiple ${model.name} records and return selected fields.
|
|
202
|
-
*
|
|
203
|
-
* @example
|
|
204
|
-
* const rows = await db.${modelVar}.createManyAndReturn({
|
|
205
|
-
${createManyDataBlock}
|
|
206
|
-
* select: {
|
|
207
|
-
* // Choose fields to return
|
|
208
|
-
* },
|
|
209
|
-
* });
|
|
210
|
-
*/
|
|
211
|
-
createManyAndReturn<T extends ${model.name}CreateManyAndReturnArgs>(
|
|
212
|
-
args: Exact<T, ${model.name}CreateManyAndReturnArgs>,
|
|
213
|
-
): Promise<GetResult<${p}, T, "createManyAndReturn">>;
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Update one ${model.name} record.
|
|
217
|
-
*
|
|
218
|
-
* @example
|
|
219
|
-
* const row = await db.${modelVar}.update({
|
|
220
|
-
${uniqueWhereBlock}
|
|
221
|
-
${updateDataBlock}
|
|
222
|
-
* });
|
|
223
|
-
*/
|
|
224
|
-
update<T extends ${model.name}UpdateArgs>(
|
|
225
|
-
args: Exact<T, ${model.name}UpdateArgs>,
|
|
226
|
-
): Promise<GetResult<${p}, T, "update">>;
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Update one ${model.name} record if it exists, or create it otherwise.
|
|
230
|
-
*
|
|
231
|
-
* @example
|
|
232
|
-
* const row = await db.${modelVar}.upsert({
|
|
233
|
-
${uniqueWhereBlock}
|
|
234
|
-
${upsertCreateBlock}
|
|
235
|
-
${upsertUpdateBlock}
|
|
236
|
-
* });
|
|
237
|
-
*/
|
|
238
|
-
upsert<T extends ${model.name}UpsertArgs>(
|
|
239
|
-
args: Exact<T, ${model.name}UpsertArgs>,
|
|
240
|
-
): Promise<GetResult<${p}, T, "upsert">>;
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Delete one ${model.name} record by a unique field.
|
|
244
|
-
*
|
|
245
|
-
* @example
|
|
246
|
-
* const row = await db.${modelVar}.delete({
|
|
247
|
-
${uniqueWhereBlock}
|
|
248
|
-
* });
|
|
249
|
-
*/
|
|
250
|
-
delete<T extends ${model.name}DeleteArgs>(
|
|
251
|
-
args: Exact<T, ${model.name}DeleteArgs>,
|
|
252
|
-
): Promise<GetResult<${p}, T, "delete">>;
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Delete multiple ${model.name} records.
|
|
256
|
-
*
|
|
257
|
-
* @example
|
|
258
|
-
* const result = await db.${modelVar}.deleteMany({
|
|
259
|
-
${findManyWhereBlock}
|
|
260
|
-
* });
|
|
261
|
-
*/
|
|
262
|
-
deleteMany(
|
|
263
|
-
args?: ${model.name}DeleteManyArgs,
|
|
264
|
-
): Promise<{ count: number }>;
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Update multiple ${model.name} records.
|
|
268
|
-
*
|
|
269
|
-
* @example
|
|
270
|
-
* const result = await db.${modelVar}.updateMany({
|
|
271
|
-
${findManyWhereBlock}
|
|
272
|
-
${updateDataBlock}
|
|
273
|
-
* });
|
|
274
|
-
*/
|
|
275
|
-
updateMany(
|
|
276
|
-
args: ${model.name}UpdateManyArgs,
|
|
277
|
-
): Promise<{ count: number }>;
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Count ${model.name} records.
|
|
281
|
-
*
|
|
282
|
-
* @example
|
|
283
|
-
* const total = await db.${modelVar}.count({
|
|
284
|
-
${findManyWhereBlock}
|
|
285
|
-
* });
|
|
286
|
-
*/
|
|
287
|
-
count(
|
|
288
|
-
args?: ${model.name}CountArgs,
|
|
289
|
-
): Promise<number>;
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Run aggregate calculations on ${model.name} records.
|
|
293
|
-
*
|
|
294
|
-
* @example
|
|
295
|
-
* const stats = await db.${modelVar}.aggregate({
|
|
296
|
-
${findManyWhereBlock}
|
|
297
|
-
* _count: true,
|
|
298
|
-
* _avg: {
|
|
299
|
-
* // Choose numeric fields
|
|
300
|
-
* },
|
|
301
|
-
* });
|
|
302
|
-
*/
|
|
303
|
-
aggregate(
|
|
304
|
-
args: ${model.name}AggregateArgs,
|
|
305
|
-
): Promise<Aggregate${model.name}Result>;
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Group ${model.name} records by scalar fields.
|
|
309
|
-
*
|
|
310
|
-
* @example
|
|
311
|
-
* const grouped = await db.${modelVar}.groupBy({
|
|
312
|
-
* by: ["${orderByField}"],
|
|
313
|
-
${findManyWhereBlock}
|
|
314
|
-
* _count: true,
|
|
315
|
-
* });
|
|
316
|
-
*/
|
|
317
|
-
groupBy(
|
|
318
|
-
args: ${model.name}GroupByArgs,
|
|
319
|
-
): Promise<${model.name}GroupByResult[]>;
|
|
320
|
-
};
|
|
321
|
-
`;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
function buildObjectBlock(params: { key: string; lines: string[] }): string {
|
|
325
|
-
const { key, lines } = params;
|
|
326
|
-
const safeLines = lines.length > 0 ? lines : ["// Add model fields here"];
|
|
327
|
-
return ` * ${key}: {
|
|
328
|
-
${safeLines.map((line) => ` * ${line}`).join("\n")}
|
|
329
|
-
* },`;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
function buildArrayOfObjectsBlock(params: { key: string; lines: string[] }): string {
|
|
333
|
-
const { key, lines } = params;
|
|
334
|
-
const safeLines = lines.length > 0 ? lines : ["// Add model fields here"];
|
|
335
|
-
return ` * ${key}: [
|
|
336
|
-
* {
|
|
337
|
-
${safeLines.map((line) => ` * ${line}`).join("\n")}
|
|
338
|
-
* },
|
|
339
|
-
* ],`;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
function buildFindManyWhereBlock(params: { model: Model }): string {
|
|
343
|
-
return buildObjectBlock({
|
|
344
|
-
key: "where",
|
|
345
|
-
lines: getFindManyWhereLines({ model: params.model }),
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function buildUniqueWhereBlock(params: { model: Model }): string {
|
|
350
|
-
return buildObjectBlock({
|
|
351
|
-
key: "where",
|
|
352
|
-
lines: getUniqueWhereLines({ model: params.model }),
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function buildIncludeBlock(params: { model: Model }): string {
|
|
357
|
-
const relationField = params.model.fields.find((f) => f.kind === "relation");
|
|
358
|
-
if (!relationField) return "";
|
|
359
|
-
return `
|
|
360
|
-
* include: {
|
|
361
|
-
* ${relationField.name}: true,
|
|
362
|
-
* },`;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function getFindManyWhereLines(params: { model: Model }): string[] {
|
|
366
|
-
const field = getPreferredWhereField({ model: params.model });
|
|
367
|
-
if (!field) {
|
|
368
|
-
return ["// Add model-specific filters here"];
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
const fieldNameLower = field.name.toLowerCase();
|
|
372
|
-
if (field.prismaType === "String") {
|
|
373
|
-
if (fieldNameLower.includes("email")) {
|
|
374
|
-
return [`${field.name}: { endsWith: "@example.com" },`];
|
|
375
|
-
}
|
|
376
|
-
return [`${field.name}: { contains: "sample" },`];
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (field.prismaType === "DateTime") {
|
|
380
|
-
return [`${field.name}: { gte: new Date("2024-01-01T00:00:00.000Z") },`];
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (field.prismaType === "Boolean") {
|
|
384
|
-
return [`${field.name}: true,`];
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (field.prismaType === "BigInt") {
|
|
388
|
-
return [`${field.name}: { gte: 1n },`];
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (field.prismaType === "Decimal") {
|
|
392
|
-
return [`${field.name}: { gte: "1.00" },`];
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
if (field.prismaType === "Int" || field.prismaType === "Float") {
|
|
396
|
-
return [`${field.name}: { gte: 1 },`];
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
if (field.prismaType === "Json") {
|
|
400
|
-
return [`${field.name}: { equals: { key: "value" } },`];
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (field.prismaType === "Bytes") {
|
|
404
|
-
return [`${field.name}: { equals: new Uint8Array([1, 2, 3]) },`];
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
return [`${field.name}: { equals: ${getSampleValueForScalarField({ field })} },`];
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
function getUniqueWhereLines(params: { model: Model }): string[] {
|
|
411
|
-
const uniqueField = params.model.fields.find(
|
|
412
|
-
(f): f is ScalarField =>
|
|
413
|
-
f.kind === "scalar" && !f.isList && (f.isId || f.isUnique)
|
|
414
|
-
);
|
|
415
|
-
|
|
416
|
-
if (!uniqueField) {
|
|
417
|
-
return ["// Provide a unique field (for example id or email)"];
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
return [`${uniqueField.name}: ${getSampleValueForScalarField({ field: uniqueField })},`];
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
function getExampleDataLines(params: { model: Model }): string[] {
|
|
424
|
-
const candidates = params.model.fields.filter(
|
|
425
|
-
(f): f is ScalarField =>
|
|
426
|
-
f.kind === "scalar" &&
|
|
427
|
-
!f.isList &&
|
|
428
|
-
!f.isId &&
|
|
429
|
-
!f.isUpdatedAt &&
|
|
430
|
-
!f.default
|
|
431
|
-
);
|
|
432
|
-
|
|
433
|
-
const selected = candidates.length > 0
|
|
434
|
-
? candidates
|
|
435
|
-
: params.model.fields.filter(
|
|
436
|
-
(f): f is ScalarField =>
|
|
437
|
-
f.kind === "scalar" && !f.isList && !f.isId && !f.isUpdatedAt
|
|
438
|
-
);
|
|
439
|
-
|
|
440
|
-
if (selected.length === 0) {
|
|
441
|
-
return ["// Add model fields here"];
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
return selected.slice(0, 2).map((field) => {
|
|
445
|
-
return `${field.name}: ${getSampleValueForScalarField({ field })},`;
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
function getExampleUpdateLines(params: { model: Model }): string[] {
|
|
450
|
-
const selected = params.model.fields.filter(
|
|
451
|
-
(f): f is ScalarField =>
|
|
452
|
-
f.kind === "scalar" && !f.isList && !f.isId && !f.isUpdatedAt
|
|
453
|
-
);
|
|
454
|
-
|
|
455
|
-
if (selected.length === 0) {
|
|
456
|
-
return ["// Add fields to update"];
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
return selected.slice(0, 2).map((field) => {
|
|
460
|
-
return `${field.name}: ${getSampleValueForScalarField({ field })},`;
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
function getPreferredWhereField(params: { model: Model }): ScalarField | undefined {
|
|
465
|
-
const fields = params.model.fields.filter(
|
|
466
|
-
(f): f is ScalarField => f.kind === "scalar" && !f.isList
|
|
467
|
-
);
|
|
468
|
-
|
|
469
|
-
return fields.find((f) => !f.isId && f.prismaType === "String")
|
|
470
|
-
?? fields.find((f) => !f.isId && f.prismaType === "DateTime")
|
|
471
|
-
?? fields.find((f) => !f.isId && NUMERIC_PRISMA_TYPES.has(f.prismaType))
|
|
472
|
-
?? fields.find((f) => !f.isId && f.prismaType === "Boolean")
|
|
473
|
-
?? fields.find((f) => !f.isId)
|
|
474
|
-
?? fields[0];
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
function getOrderByFieldName(params: { model: Model }): string {
|
|
478
|
-
const scalarFields = params.model.fields.filter(
|
|
479
|
-
(f): f is ScalarField => f.kind === "scalar" && !f.isList
|
|
480
|
-
);
|
|
481
|
-
|
|
482
|
-
const preferred = scalarFields.find((f) => f.name === "createdAt")
|
|
483
|
-
?? scalarFields.find((f) => f.name === "updatedAt")
|
|
484
|
-
?? scalarFields.find((f) => f.isId)
|
|
485
|
-
?? scalarFields[0];
|
|
486
|
-
|
|
487
|
-
return preferred?.name ?? "id";
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
function getSampleValueForScalarField(params: { field: ScalarField }): string {
|
|
491
|
-
const { field } = params;
|
|
492
|
-
const fieldNameLower = field.name.toLowerCase();
|
|
493
|
-
|
|
494
|
-
if (field.prismaType === "String") {
|
|
495
|
-
if (fieldNameLower.includes("email")) return '"user@example.com"';
|
|
496
|
-
if (fieldNameLower.includes("name")) return '"Example"';
|
|
497
|
-
if (fieldNameLower.includes("title")) return '"Example title"';
|
|
498
|
-
return '"sample"';
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
if (field.prismaType === "Boolean") return "true";
|
|
502
|
-
if (field.prismaType === "Int" || field.prismaType === "Float") return "1";
|
|
503
|
-
if (field.prismaType === "Decimal") return '"1.00"';
|
|
504
|
-
if (field.prismaType === "BigInt") return "1n";
|
|
505
|
-
if (field.prismaType === "DateTime") return 'new Date("2024-01-01T00:00:00.000Z")';
|
|
506
|
-
if (field.prismaType === "Json") return '{ key: "value" }';
|
|
507
|
-
if (field.prismaType === "Bytes") return "new Uint8Array([1, 2, 3])";
|
|
508
|
-
|
|
509
|
-
return "undefined";
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
function generateAggregateResultType(params: { model: Model }): string {
|
|
513
|
-
const { model } = params;
|
|
514
|
-
|
|
515
|
-
const scalarFields = model.fields.filter(
|
|
516
|
-
(f): f is ScalarField => f.kind === "scalar"
|
|
517
|
-
);
|
|
518
|
-
const numericFields = scalarFields.filter(
|
|
519
|
-
(f) => NUMERIC_PRISMA_TYPES.has(f.prismaType)
|
|
520
|
-
);
|
|
521
|
-
|
|
522
|
-
const countFields = [
|
|
523
|
-
` _all: number;`,
|
|
524
|
-
...scalarFields.map((f) => ` ${f.name}: number;`),
|
|
525
|
-
];
|
|
526
|
-
|
|
527
|
-
const avgFields = numericFields.map((f) => ` ${f.name}: number | null;`);
|
|
528
|
-
const sumFields = numericFields.map((f) => ` ${f.name}: number | null;`);
|
|
529
|
-
const minFields = scalarFields.map((f) => {
|
|
530
|
-
const tsType = f.tsType;
|
|
531
|
-
return ` ${f.name}: ${tsType} | null;`;
|
|
532
|
-
});
|
|
533
|
-
const maxFields = scalarFields.map((f) => {
|
|
534
|
-
const tsType = f.tsType;
|
|
535
|
-
return ` ${f.name}: ${tsType} | null;`;
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
return `export type Aggregate${model.name}Result = {
|
|
539
|
-
_count: number | {
|
|
540
|
-
${countFields.join("\n")}
|
|
541
|
-
};
|
|
542
|
-
_avg: {
|
|
543
|
-
${avgFields.length > 0 ? avgFields.join("\n") : " [key: string]: never;"}
|
|
544
|
-
} | null;
|
|
545
|
-
_sum: {
|
|
546
|
-
${sumFields.length > 0 ? sumFields.join("\n") : " [key: string]: never;"}
|
|
547
|
-
} | null;
|
|
548
|
-
_min: {
|
|
549
|
-
${minFields.join("\n")}
|
|
550
|
-
} | null;
|
|
551
|
-
_max: {
|
|
552
|
-
${maxFields.join("\n")}
|
|
553
|
-
} | null;
|
|
554
|
-
};
|
|
555
|
-
`;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
function generateGroupByResultType(params: { model: Model }): string {
|
|
559
|
-
const { model } = params;
|
|
560
|
-
|
|
561
|
-
const scalarFields = model.fields.filter(
|
|
562
|
-
(f): f is ScalarField => f.kind === "scalar"
|
|
563
|
-
);
|
|
564
|
-
|
|
565
|
-
// GroupBy result is a partial of scalars + aggregate fields
|
|
566
|
-
const scalarEntries = scalarFields.map((f) => {
|
|
567
|
-
const tsType = f.tsType;
|
|
568
|
-
const nullable = f.isRequired ? "" : " | null";
|
|
569
|
-
return ` ${f.name}?: ${tsType}${nullable};`;
|
|
570
|
-
});
|
|
571
|
-
|
|
572
|
-
// Also include enum fields
|
|
573
|
-
const enumEntries = model.fields
|
|
574
|
-
.filter((f) => f.kind === "enum")
|
|
575
|
-
.map((f) => {
|
|
576
|
-
if (f.kind !== "enum") return "";
|
|
577
|
-
const nullable = f.isRequired ? "" : " | null";
|
|
578
|
-
return ` ${f.name}?: ${f.enumName}${nullable};`;
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
return `export type ${model.name}GroupByResult = {
|
|
582
|
-
${[...scalarEntries, ...enumEntries].join("\n")}
|
|
583
|
-
_count?: number | Record<string, number>;
|
|
584
|
-
_avg?: Record<string, number | null>;
|
|
585
|
-
_sum?: Record<string, number | null>;
|
|
586
|
-
_min?: Record<string, unknown>;
|
|
587
|
-
_max?: Record<string, unknown>;
|
|
588
|
-
};
|
|
589
|
-
`;
|
|
590
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { Enum } from "@vibeorm/parser";
|
|
2
|
-
import { fileHeader } from "../utils.ts";
|
|
3
|
-
|
|
4
|
-
export function generateEnums(params: { enums: Enum[] }): string {
|
|
5
|
-
const { enums } = params;
|
|
6
|
-
|
|
7
|
-
if (enums.length === 0) {
|
|
8
|
-
return fileHeader() + "\nexport {};\n";
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const parts: string[] = [fileHeader()];
|
|
12
|
-
|
|
13
|
-
for (const enumDef of enums) {
|
|
14
|
-
// Generate a const object (not a TS enum — objects are more flexible)
|
|
15
|
-
const values = enumDef.values
|
|
16
|
-
.map((v) => ` ${v.name}: "${v.name}" as const`)
|
|
17
|
-
.join(",\n");
|
|
18
|
-
|
|
19
|
-
parts.push(`export const ${enumDef.name} = {
|
|
20
|
-
${values},
|
|
21
|
-
} as const;
|
|
22
|
-
|
|
23
|
-
export type ${enumDef.name} = (typeof ${enumDef.name})[keyof typeof ${enumDef.name}];
|
|
24
|
-
`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return parts.join("\n");
|
|
28
|
-
}
|