@vibeorm/generator 1.0.0
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 +58 -0
- package/package.json +42 -0
- package/src/generate.ts +65 -0
- package/src/generators/generate-args.ts +322 -0
- package/src/generators/generate-client.ts +186 -0
- package/src/generators/generate-delegates.ts +213 -0
- package/src/generators/generate-enums.ts +28 -0
- package/src/generators/generate-inputs.ts +626 -0
- package/src/generators/generate-models.ts +103 -0
- package/src/generators/generate-result.ts +163 -0
- package/src/generators/generate-schemas.ts +474 -0
- package/src/index.ts +2 -0
- package/src/utils.ts +51 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Model,
|
|
3
|
+
Schema,
|
|
4
|
+
ScalarField,
|
|
5
|
+
EnumField,
|
|
6
|
+
RelationField,
|
|
7
|
+
PrismaScalarType,
|
|
8
|
+
} from "@vibeorm/parser";
|
|
9
|
+
import { fileHeader } from "../utils.ts";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generates Zod v4 schemas for model validation:
|
|
13
|
+
* - Model schemas (validating query results / output)
|
|
14
|
+
* - CreateInput schemas (validating mutation input)
|
|
15
|
+
* - UpdateInput schemas (with atomic number operations)
|
|
16
|
+
*/
|
|
17
|
+
export function generateSchemas(params: { schema: Schema }): string {
|
|
18
|
+
const { schema } = params;
|
|
19
|
+
const parts: string[] = [fileHeader()];
|
|
20
|
+
|
|
21
|
+
// Import zod
|
|
22
|
+
parts.push(`import { z } from "zod/v4";\n`);
|
|
23
|
+
|
|
24
|
+
// Generate shared atomic operation schemas first (referenced by update schemas)
|
|
25
|
+
parts.push(generateAtomicOperationSchemas());
|
|
26
|
+
|
|
27
|
+
// Generate shared where filter schemas (referenced by WhereInput schemas)
|
|
28
|
+
parts.push(generateWhereFilterSchemas());
|
|
29
|
+
|
|
30
|
+
// Generate enum schemas (they're referenced by model schemas)
|
|
31
|
+
for (const enumDef of schema.enums) {
|
|
32
|
+
const values = enumDef.values.map((v) => `"${v.name}"`).join(", ");
|
|
33
|
+
parts.push(`export const ${enumDef.name}Schema = z.enum([${values}]);\n`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Generate model schemas
|
|
37
|
+
for (const model of schema.models) {
|
|
38
|
+
parts.push(generateModelSchema({ model, schema }));
|
|
39
|
+
parts.push(generateCreateInputSchema({ model, schema }));
|
|
40
|
+
parts.push(generateUpdateInputSchema({ model, schema }));
|
|
41
|
+
parts.push(generateWhereInputSchema({ model, schema }));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return parts.join("\n");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ─── Model Schema ────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
function generateModelSchema(params: { model: Model; schema: Schema }): string {
|
|
50
|
+
const { model } = params;
|
|
51
|
+
const fields: string[] = [];
|
|
52
|
+
|
|
53
|
+
for (const field of model.fields) {
|
|
54
|
+
if (field.kind === "scalar") {
|
|
55
|
+
const zodType = scalarToZod({ field });
|
|
56
|
+
fields.push(` ${field.name}: ${zodType},`);
|
|
57
|
+
} else if (field.kind === "enum") {
|
|
58
|
+
let zodType = `${field.enumName}Schema`;
|
|
59
|
+
if (field.isList) {
|
|
60
|
+
zodType = `z.array(${zodType})`;
|
|
61
|
+
} else if (!field.isRequired) {
|
|
62
|
+
zodType = `${zodType}.nullable()`;
|
|
63
|
+
}
|
|
64
|
+
fields.push(` ${field.name}: ${zodType},`);
|
|
65
|
+
}
|
|
66
|
+
// Relations are excluded from model schemas (they're separate queries)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return `export const ${model.name}Schema = z.object({
|
|
70
|
+
${fields.join("\n")}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export type ${model.name}Validated = z.infer<typeof ${model.name}Schema>;
|
|
74
|
+
`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ─── CreateInput Schema ──────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
function generateCreateInputSchema(params: {
|
|
80
|
+
model: Model;
|
|
81
|
+
schema: Schema;
|
|
82
|
+
}): string {
|
|
83
|
+
const { model } = params;
|
|
84
|
+
const fields: string[] = [];
|
|
85
|
+
|
|
86
|
+
for (const field of model.fields) {
|
|
87
|
+
if (field.kind === "scalar") {
|
|
88
|
+
const isAutoGenerated =
|
|
89
|
+
field.default &&
|
|
90
|
+
(field.default.kind === "autoincrement" ||
|
|
91
|
+
field.default.kind === "now" ||
|
|
92
|
+
field.default.kind === "uuid" ||
|
|
93
|
+
field.default.kind === "cuid" ||
|
|
94
|
+
field.default.kind === "nanoid" ||
|
|
95
|
+
field.default.kind === "ulid");
|
|
96
|
+
const isOptional =
|
|
97
|
+
!field.isRequired ||
|
|
98
|
+
field.default !== undefined ||
|
|
99
|
+
isAutoGenerated ||
|
|
100
|
+
field.isUpdatedAt;
|
|
101
|
+
|
|
102
|
+
let zodType = scalarToZodBase({ prismaType: field.prismaType });
|
|
103
|
+
if (field.isList) {
|
|
104
|
+
zodType = `z.array(${zodType})`;
|
|
105
|
+
} else if (!field.isRequired) {
|
|
106
|
+
zodType = `${zodType}.nullable()`;
|
|
107
|
+
}
|
|
108
|
+
if (isOptional) {
|
|
109
|
+
zodType = `${zodType}.optional()`;
|
|
110
|
+
}
|
|
111
|
+
fields.push(` ${field.name}: ${zodType},`);
|
|
112
|
+
} else if (field.kind === "enum") {
|
|
113
|
+
const isOptional = !field.isRequired || field.default !== undefined;
|
|
114
|
+
let zodType = `${field.enumName}Schema`;
|
|
115
|
+
if (field.isList) {
|
|
116
|
+
zodType = `z.array(${zodType})`;
|
|
117
|
+
} else if (!field.isRequired) {
|
|
118
|
+
zodType = `${zodType}.nullable()`;
|
|
119
|
+
}
|
|
120
|
+
if (isOptional) {
|
|
121
|
+
zodType = `${zodType}.optional()`;
|
|
122
|
+
}
|
|
123
|
+
fields.push(` ${field.name}: ${zodType},`);
|
|
124
|
+
}
|
|
125
|
+
// Relations are excluded — nested creates are complex and handled separately
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return `export const ${model.name}CreateInputSchema = z.object({
|
|
129
|
+
${fields.join("\n")}
|
|
130
|
+
});
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ─── UpdateInput Schema ──────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
function generateUpdateInputSchema(params: {
|
|
137
|
+
model: Model;
|
|
138
|
+
schema: Schema;
|
|
139
|
+
}): string {
|
|
140
|
+
const { model } = params;
|
|
141
|
+
const fields: string[] = [];
|
|
142
|
+
|
|
143
|
+
for (const field of model.fields) {
|
|
144
|
+
if (field.kind === "scalar") {
|
|
145
|
+
if (field.isList) {
|
|
146
|
+
// Array field — support set/push operations
|
|
147
|
+
const baseZod = scalarToZodBase({ prismaType: field.prismaType });
|
|
148
|
+
const listSchema = `z.union([z.array(${baseZod}), z.object({ set: z.array(${baseZod}).optional(), push: z.union([${baseZod}, z.array(${baseZod})]).optional() })])`;
|
|
149
|
+
fields.push(` ${field.name}: ${listSchema}.optional(),`);
|
|
150
|
+
} else {
|
|
151
|
+
let zodType = scalarToZodBase({ prismaType: field.prismaType });
|
|
152
|
+
if (!field.isRequired) {
|
|
153
|
+
zodType = `${zodType}.nullable()`;
|
|
154
|
+
}
|
|
155
|
+
// For numeric fields, also accept atomic operations
|
|
156
|
+
const atomicSchema = numericAtomicSchema({ prismaType: field.prismaType });
|
|
157
|
+
if (atomicSchema) {
|
|
158
|
+
zodType = `z.union([${zodType}, ${atomicSchema}])`;
|
|
159
|
+
}
|
|
160
|
+
fields.push(` ${field.name}: ${zodType}.optional(),`);
|
|
161
|
+
}
|
|
162
|
+
} else if (field.kind === "enum") {
|
|
163
|
+
let zodType = `${field.enumName}Schema`;
|
|
164
|
+
if (field.isList) {
|
|
165
|
+
zodType = `z.array(${zodType})`;
|
|
166
|
+
} else if (!field.isRequired) {
|
|
167
|
+
zodType = `${zodType}.nullable()`;
|
|
168
|
+
}
|
|
169
|
+
fields.push(` ${field.name}: ${zodType}.optional(),`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return `export const ${model.name}UpdateInputSchema = z.object({
|
|
174
|
+
${fields.join("\n")}
|
|
175
|
+
});
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ─── Atomic Operation Schemas ────────────────────────────────────
|
|
180
|
+
|
|
181
|
+
function generateAtomicOperationSchemas(): string {
|
|
182
|
+
return `
|
|
183
|
+
// ─── Atomic Operation Schemas ────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
export const IntFieldUpdateOperationsSchema = z.object({
|
|
186
|
+
set: z.number().int().optional(),
|
|
187
|
+
increment: z.number().int().optional(),
|
|
188
|
+
decrement: z.number().int().optional(),
|
|
189
|
+
multiply: z.number().int().optional(),
|
|
190
|
+
divide: z.number().int().optional(),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
export const FloatFieldUpdateOperationsSchema = z.object({
|
|
194
|
+
set: z.number().optional(),
|
|
195
|
+
increment: z.number().optional(),
|
|
196
|
+
decrement: z.number().optional(),
|
|
197
|
+
multiply: z.number().optional(),
|
|
198
|
+
divide: z.number().optional(),
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
export const BigIntFieldUpdateOperationsSchema = z.object({
|
|
202
|
+
set: z.bigint().optional(),
|
|
203
|
+
increment: z.bigint().optional(),
|
|
204
|
+
decrement: z.bigint().optional(),
|
|
205
|
+
multiply: z.bigint().optional(),
|
|
206
|
+
divide: z.bigint().optional(),
|
|
207
|
+
});
|
|
208
|
+
`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ─── Helpers ─────────────────────────────────────────────────────
|
|
212
|
+
|
|
213
|
+
function scalarToZod(params: { field: ScalarField }): string {
|
|
214
|
+
let base = scalarToZodBase({ prismaType: params.field.prismaType });
|
|
215
|
+
if (params.field.isList) {
|
|
216
|
+
return `z.array(${base})`;
|
|
217
|
+
}
|
|
218
|
+
if (!params.field.isRequired) {
|
|
219
|
+
return `${base}.nullable()`;
|
|
220
|
+
}
|
|
221
|
+
return base;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function scalarToZodBase(params: { prismaType: PrismaScalarType }): string {
|
|
225
|
+
switch (params.prismaType) {
|
|
226
|
+
case "String":
|
|
227
|
+
return "z.string()";
|
|
228
|
+
case "Boolean":
|
|
229
|
+
return "z.boolean()";
|
|
230
|
+
case "Int":
|
|
231
|
+
return "z.number().int()";
|
|
232
|
+
case "Float":
|
|
233
|
+
case "Decimal":
|
|
234
|
+
return "z.number()";
|
|
235
|
+
case "BigInt":
|
|
236
|
+
return "z.bigint()";
|
|
237
|
+
case "DateTime":
|
|
238
|
+
return "z.union([z.date(), z.string()])";
|
|
239
|
+
case "Json":
|
|
240
|
+
return "z.unknown()";
|
|
241
|
+
case "Bytes":
|
|
242
|
+
return "z.instanceof(Buffer)";
|
|
243
|
+
default:
|
|
244
|
+
return "z.unknown()";
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function numericAtomicSchema(params: { prismaType: PrismaScalarType }): string | null {
|
|
249
|
+
switch (params.prismaType) {
|
|
250
|
+
case "Int":
|
|
251
|
+
return "IntFieldUpdateOperationsSchema";
|
|
252
|
+
case "Float":
|
|
253
|
+
case "Decimal":
|
|
254
|
+
return "FloatFieldUpdateOperationsSchema";
|
|
255
|
+
case "BigInt":
|
|
256
|
+
return "BigIntFieldUpdateOperationsSchema";
|
|
257
|
+
default:
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ─── Where Filter Schemas ───────────────────────────────────────
|
|
263
|
+
|
|
264
|
+
function generateWhereFilterSchemas(): string {
|
|
265
|
+
return `
|
|
266
|
+
// ─── Where Filter Schemas ───────────────────────────────────────
|
|
267
|
+
|
|
268
|
+
export const StringFilterSchema = z.object({
|
|
269
|
+
equals: z.string().optional(),
|
|
270
|
+
not: z.union([z.string(), z.lazy(() => StringFilterSchema)]).optional(),
|
|
271
|
+
in: z.array(z.string()).optional(),
|
|
272
|
+
notIn: z.array(z.string()).optional(),
|
|
273
|
+
lt: z.string().optional(),
|
|
274
|
+
lte: z.string().optional(),
|
|
275
|
+
gt: z.string().optional(),
|
|
276
|
+
gte: z.string().optional(),
|
|
277
|
+
contains: z.string().optional(),
|
|
278
|
+
startsWith: z.string().optional(),
|
|
279
|
+
endsWith: z.string().optional(),
|
|
280
|
+
mode: z.enum(["default", "insensitive"]).optional(),
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
export const NullableStringFilterSchema = z.object({
|
|
284
|
+
equals: z.string().nullable().optional(),
|
|
285
|
+
not: z.union([z.string().nullable(), z.lazy(() => NullableStringFilterSchema)]).optional(),
|
|
286
|
+
in: z.array(z.string().nullable()).optional(),
|
|
287
|
+
notIn: z.array(z.string().nullable()).optional(),
|
|
288
|
+
lt: z.string().optional(),
|
|
289
|
+
lte: z.string().optional(),
|
|
290
|
+
gt: z.string().optional(),
|
|
291
|
+
gte: z.string().optional(),
|
|
292
|
+
contains: z.string().optional(),
|
|
293
|
+
startsWith: z.string().optional(),
|
|
294
|
+
endsWith: z.string().optional(),
|
|
295
|
+
mode: z.enum(["default", "insensitive"]).optional(),
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
export const NumberFilterSchema = z.object({
|
|
299
|
+
equals: z.number().optional(),
|
|
300
|
+
not: z.union([z.number(), z.lazy(() => NumberFilterSchema)]).optional(),
|
|
301
|
+
in: z.array(z.number()).optional(),
|
|
302
|
+
notIn: z.array(z.number()).optional(),
|
|
303
|
+
lt: z.number().optional(),
|
|
304
|
+
lte: z.number().optional(),
|
|
305
|
+
gt: z.number().optional(),
|
|
306
|
+
gte: z.number().optional(),
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
export const NullableNumberFilterSchema = z.object({
|
|
310
|
+
equals: z.number().nullable().optional(),
|
|
311
|
+
not: z.union([z.number().nullable(), z.lazy(() => NullableNumberFilterSchema)]).optional(),
|
|
312
|
+
in: z.array(z.number().nullable()).optional(),
|
|
313
|
+
notIn: z.array(z.number().nullable()).optional(),
|
|
314
|
+
lt: z.number().optional(),
|
|
315
|
+
lte: z.number().optional(),
|
|
316
|
+
gt: z.number().optional(),
|
|
317
|
+
gte: z.number().optional(),
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
export const BigIntFilterSchema = z.object({
|
|
321
|
+
equals: z.bigint().optional(),
|
|
322
|
+
not: z.union([z.bigint(), z.lazy(() => BigIntFilterSchema)]).optional(),
|
|
323
|
+
in: z.array(z.bigint()).optional(),
|
|
324
|
+
notIn: z.array(z.bigint()).optional(),
|
|
325
|
+
lt: z.bigint().optional(),
|
|
326
|
+
lte: z.bigint().optional(),
|
|
327
|
+
gt: z.bigint().optional(),
|
|
328
|
+
gte: z.bigint().optional(),
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
export const NullableBigIntFilterSchema = z.object({
|
|
332
|
+
equals: z.bigint().nullable().optional(),
|
|
333
|
+
not: z.union([z.bigint().nullable(), z.lazy(() => NullableBigIntFilterSchema)]).optional(),
|
|
334
|
+
in: z.array(z.bigint().nullable()).optional(),
|
|
335
|
+
notIn: z.array(z.bigint().nullable()).optional(),
|
|
336
|
+
lt: z.bigint().optional(),
|
|
337
|
+
lte: z.bigint().optional(),
|
|
338
|
+
gt: z.bigint().optional(),
|
|
339
|
+
gte: z.bigint().optional(),
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
export const BooleanFilterSchema = z.object({
|
|
343
|
+
equals: z.boolean().optional(),
|
|
344
|
+
not: z.union([z.boolean(), z.lazy(() => BooleanFilterSchema)]).optional(),
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
export const NullableBooleanFilterSchema = z.object({
|
|
348
|
+
equals: z.boolean().nullable().optional(),
|
|
349
|
+
not: z.union([z.boolean().nullable(), z.lazy(() => NullableBooleanFilterSchema)]).optional(),
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
export const DateTimeFilterSchema = z.object({
|
|
353
|
+
equals: z.union([z.date(), z.string()]).optional(),
|
|
354
|
+
not: z.union([z.date(), z.string(), z.lazy(() => DateTimeFilterSchema)]).optional(),
|
|
355
|
+
in: z.array(z.union([z.date(), z.string()])).optional(),
|
|
356
|
+
notIn: z.array(z.union([z.date(), z.string()])).optional(),
|
|
357
|
+
lt: z.union([z.date(), z.string()]).optional(),
|
|
358
|
+
lte: z.union([z.date(), z.string()]).optional(),
|
|
359
|
+
gt: z.union([z.date(), z.string()]).optional(),
|
|
360
|
+
gte: z.union([z.date(), z.string()]).optional(),
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
export const NullableDateTimeFilterSchema = z.object({
|
|
364
|
+
equals: z.union([z.date(), z.string()]).nullable().optional(),
|
|
365
|
+
not: z.union([z.date(), z.string(), z.lazy(() => NullableDateTimeFilterSchema)]).nullable().optional(),
|
|
366
|
+
in: z.array(z.union([z.date(), z.string()]).nullable()).optional(),
|
|
367
|
+
notIn: z.array(z.union([z.date(), z.string()]).nullable()).optional(),
|
|
368
|
+
lt: z.union([z.date(), z.string()]).optional(),
|
|
369
|
+
lte: z.union([z.date(), z.string()]).optional(),
|
|
370
|
+
gt: z.union([z.date(), z.string()]).optional(),
|
|
371
|
+
gte: z.union([z.date(), z.string()]).optional(),
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
export const EnumFilterSchema = z.object({
|
|
375
|
+
equals: z.string().optional(),
|
|
376
|
+
not: z.union([z.string(), z.lazy(() => EnumFilterSchema)]).optional(),
|
|
377
|
+
in: z.array(z.string()).optional(),
|
|
378
|
+
notIn: z.array(z.string()).optional(),
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
export const NullableEnumFilterSchema = z.object({
|
|
382
|
+
equals: z.string().nullable().optional(),
|
|
383
|
+
not: z.union([z.string().nullable(), z.lazy(() => NullableEnumFilterSchema)]).optional(),
|
|
384
|
+
in: z.array(z.string().nullable()).optional(),
|
|
385
|
+
notIn: z.array(z.string().nullable()).optional(),
|
|
386
|
+
});
|
|
387
|
+
`;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// ─── WhereInput Schema ──────────────────────────────────────────
|
|
391
|
+
|
|
392
|
+
function generateWhereInputSchema(params: {
|
|
393
|
+
model: Model;
|
|
394
|
+
schema: Schema;
|
|
395
|
+
}): string {
|
|
396
|
+
const { model } = params;
|
|
397
|
+
const fields: string[] = [];
|
|
398
|
+
|
|
399
|
+
for (const field of model.fields) {
|
|
400
|
+
if (field.kind === "scalar") {
|
|
401
|
+
if (field.isList) {
|
|
402
|
+
// Skip list/array fields — array filtering is complex and not included
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
const baseZod = scalarToZodBase({ prismaType: field.prismaType });
|
|
406
|
+
const filterName = scalarFilterSchemaName({
|
|
407
|
+
prismaType: field.prismaType,
|
|
408
|
+
isRequired: field.isRequired,
|
|
409
|
+
});
|
|
410
|
+
if (!field.isRequired) {
|
|
411
|
+
fields.push(
|
|
412
|
+
` ${field.name}: z.union([${baseZod}.nullable(), ${filterName}]).optional(),`
|
|
413
|
+
);
|
|
414
|
+
} else {
|
|
415
|
+
fields.push(
|
|
416
|
+
` ${field.name}: z.union([${baseZod}, ${filterName}]).optional(),`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
} else if (field.kind === "enum") {
|
|
420
|
+
if (field.isList) {
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
const enumSchemaRef = `${field.enumName}Schema`;
|
|
424
|
+
const filterName = field.isRequired
|
|
425
|
+
? "EnumFilterSchema"
|
|
426
|
+
: "NullableEnumFilterSchema";
|
|
427
|
+
if (!field.isRequired) {
|
|
428
|
+
fields.push(
|
|
429
|
+
` ${field.name}: z.union([${enumSchemaRef}.nullable(), ${filterName}]).optional(),`
|
|
430
|
+
);
|
|
431
|
+
} else {
|
|
432
|
+
fields.push(
|
|
433
|
+
` ${field.name}: z.union([${enumSchemaRef}, ${filterName}]).optional(),`
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// Relations are excluded from WhereInput schemas
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const schemaName = `${model.name}WhereInputSchema`;
|
|
441
|
+
|
|
442
|
+
return `export const ${schemaName}: z.ZodType<any> = z.lazy(() => z.object({
|
|
443
|
+
AND: z.union([${schemaName}, z.array(${schemaName})]).optional(),
|
|
444
|
+
OR: z.array(${schemaName}).optional(),
|
|
445
|
+
NOT: z.union([${schemaName}, z.array(${schemaName})]).optional(),
|
|
446
|
+
${fields.join("\n")}
|
|
447
|
+
}).partial());
|
|
448
|
+
`;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function scalarFilterSchemaName(params: {
|
|
452
|
+
prismaType: PrismaScalarType;
|
|
453
|
+
isRequired: boolean;
|
|
454
|
+
}): string {
|
|
455
|
+
const nullable = !params.isRequired;
|
|
456
|
+
switch (params.prismaType) {
|
|
457
|
+
case "String":
|
|
458
|
+
return nullable ? "NullableStringFilterSchema" : "StringFilterSchema";
|
|
459
|
+
case "Int":
|
|
460
|
+
case "Float":
|
|
461
|
+
case "Decimal":
|
|
462
|
+
return nullable ? "NullableNumberFilterSchema" : "NumberFilterSchema";
|
|
463
|
+
case "BigInt":
|
|
464
|
+
return nullable ? "NullableBigIntFilterSchema" : "BigIntFilterSchema";
|
|
465
|
+
case "Boolean":
|
|
466
|
+
return nullable ? "NullableBooleanFilterSchema" : "BooleanFilterSchema";
|
|
467
|
+
case "DateTime":
|
|
468
|
+
return nullable
|
|
469
|
+
? "NullableDateTimeFilterSchema"
|
|
470
|
+
: "DateTimeFilterSchema";
|
|
471
|
+
default:
|
|
472
|
+
return "z.unknown()";
|
|
473
|
+
}
|
|
474
|
+
}
|
package/src/index.ts
ADDED
package/src/utils.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code generation utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Convert PascalCase to camelCase */
|
|
6
|
+
export function toCamelCase(params: { str: string }): string {
|
|
7
|
+
const { str } = params;
|
|
8
|
+
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Convert to PascalCase (first letter uppercase) */
|
|
12
|
+
export function toPascalCase(params: { str: string }): string {
|
|
13
|
+
const { str } = params;
|
|
14
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Indent a block of text by n spaces */
|
|
18
|
+
export function indent(params: { text: string; spaces?: number }): string {
|
|
19
|
+
const { text, spaces = 2 } = params;
|
|
20
|
+
const pad = " ".repeat(spaces);
|
|
21
|
+
return text
|
|
22
|
+
.split("\n")
|
|
23
|
+
.map((line) => (line.trim() ? pad + line : line))
|
|
24
|
+
.join("\n");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Join lines with newline, filtering out empty/undefined */
|
|
28
|
+
export function lines(params: { items: (string | undefined | false)[] }): string {
|
|
29
|
+
return params.items.filter(Boolean).join("\n");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Create a TypeScript type alias */
|
|
33
|
+
export function typeAlias(params: {
|
|
34
|
+
name: string;
|
|
35
|
+
value: string;
|
|
36
|
+
exported?: boolean;
|
|
37
|
+
}): string {
|
|
38
|
+
const { name, value, exported = true } = params;
|
|
39
|
+
return `${exported ? "export " : ""}type ${name} = ${value};`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Wrap code in a block for file generation */
|
|
43
|
+
export function fileHeader(): string {
|
|
44
|
+
return [
|
|
45
|
+
"// ============================================",
|
|
46
|
+
"// THIS FILE IS AUTO-GENERATED BY VIBEORM",
|
|
47
|
+
"// DO NOT EDIT MANUALLY",
|
|
48
|
+
"// ============================================",
|
|
49
|
+
"",
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|