zodipus 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,696 @@
1
+ 'use strict';
2
+
3
+ var generatorHelper = require('@prisma/generator-helper');
4
+ var fs = require('fs');
5
+ var path = require('path');
6
+
7
+ // src/index.ts
8
+ function parseConfig(options) {
9
+ const config = options.generator.config;
10
+ const getConfigValue = (key, defaultValue) => {
11
+ const value = config[key];
12
+ if (Array.isArray(value)) return value[0] ?? defaultValue;
13
+ return value ?? defaultValue;
14
+ };
15
+ return {
16
+ dateFormat: getConfigValue("dateFormat", "coerce"),
17
+ passthroughEnabled: getConfigValue("passthroughEnabled", "false") === "true",
18
+ relationDepth: Number.parseInt(getConfigValue("relationDepth", "5")),
19
+ debug: getConfigValue("debug", "false") === "true",
20
+ zodImport: getConfigValue("zodImport", "zod"),
21
+ dryRun: process.env.ZODIPUS_DRY_RUN === "true"
22
+ };
23
+ }
24
+ async function generate(options) {
25
+ if (process.env.ZODIPUS_CMD === "inspect") {
26
+ await inspectSchema(options.dmmf);
27
+ return;
28
+ }
29
+ const outputDir = options.generator.output?.value;
30
+ if (!outputDir) {
31
+ throw new Error("No output directory specified");
32
+ }
33
+ const config = parseConfig(options);
34
+ const log = (...args) => {
35
+ if (config.debug) {
36
+ console.log(...args);
37
+ }
38
+ };
39
+ const resolvedOutputDir = path.resolve(path.dirname(options.schemaPath), outputDir);
40
+ log("\u{1F527} Zodipus generator");
41
+ log(`\u{1F4C1} Output directory: ${resolvedOutputDir}`);
42
+ log(
43
+ `\u2699\uFE0F Config: dateFormat=${config.dateFormat}, passthroughEnabled=${config.passthroughEnabled}, relationDepth=${config.relationDepth}`
44
+ );
45
+ log("\u{1F4E6} Generating clean Zod model schemas...");
46
+ await generateCleanModelSchemas(options, resolvedOutputDir, log, config);
47
+ log("\u{1F517} Extracting relations from DMMF...");
48
+ log(` Total models in schema: ${options.dmmf.datamodel.models.length}`);
49
+ const relations = extractRelationsFromDMMF(options.dmmf, config.relationDepth);
50
+ log(` Found ${Object.keys(relations).length} models with relations`);
51
+ const relationsCode = formatRelationsAsTypeScript(relations, config.relationDepth);
52
+ const relationsPath = path.resolve(resolvedOutputDir, "generated-relations.ts");
53
+ if (!config.dryRun) {
54
+ fs.mkdirSync(path.dirname(relationsPath), { recursive: true });
55
+ fs.writeFileSync(relationsPath, relationsCode, "utf-8");
56
+ } else {
57
+ log(` [DRY RUN] Would write to ${relationsPath}`);
58
+ }
59
+ log(` \u2705 Relations written to ${relationsPath}`);
60
+ log("\u{1F4DD} Generating index file...");
61
+ const indexCode = generateIndexFile(options.dmmf);
62
+ const indexPath = path.resolve(resolvedOutputDir, "generated-index.ts");
63
+ if (!config.dryRun) {
64
+ fs.writeFileSync(indexPath, indexCode, "utf-8");
65
+ } else {
66
+ log(` [DRY RUN] Would write to ${indexPath}`);
67
+ }
68
+ log("\u2705 Query Engine generation complete!");
69
+ }
70
+ async function generateCleanModelSchemas(options, outputDir, log, config) {
71
+ const models = options.dmmf.datamodel.models;
72
+ const enums = options.dmmf.datamodel.enums;
73
+ const enumNames = new Set(enums.map((e) => e.name));
74
+ log(` Found ${models.length} models and ${enums.length} enums`);
75
+ const customSchemas = /* @__PURE__ */ new Set();
76
+ for (const model of models) {
77
+ const scalarFields = model.fields.filter((field) => field.kind !== "object");
78
+ for (const field of scalarFields) {
79
+ const customSchema = extractCustomSchema(field.documentation);
80
+ if (customSchema) {
81
+ customSchemas.add(customSchema);
82
+ }
83
+ }
84
+ }
85
+ const enumSchemas = [];
86
+ for (const enumDef of enums) {
87
+ const enumCode = generateEnumSchema(enumDef, config);
88
+ enumSchemas.push(enumCode);
89
+ }
90
+ const usedEnums = /* @__PURE__ */ new Set();
91
+ for (const model of models) {
92
+ const scalarFields = model.fields.filter((field) => field.kind !== "object");
93
+ for (const field of scalarFields) {
94
+ if (enumNames.has(field.type)) {
95
+ usedEnums.add(field.type);
96
+ }
97
+ }
98
+ }
99
+ const modelSchemas = [];
100
+ for (const model of models) {
101
+ const modelCode = generateModelSchema(model, enums, config);
102
+ modelSchemas.push(modelCode);
103
+ }
104
+ const enumsCode = `import { z } from '${config.zodImport}';
105
+
106
+ ${enumSchemas.map((s) => s.replace(/import \{ z \} from '[^']+';\n\n/g, "")).join("\n\n")}`;
107
+ const enumsPath = path.resolve(outputDir, "enums.ts");
108
+ if (!config.dryRun) {
109
+ fs.writeFileSync(enumsPath, enumsCode, "utf-8");
110
+ } else {
111
+ log(` [DRY RUN] Would write to ${enumsPath}`);
112
+ }
113
+ const enumImportList = Array.from(usedEnums).sort().map((name) => `${name}Schema`).join(", ");
114
+ const customSchemaImportList = Array.from(customSchemas).sort().join(", ");
115
+ const modelImports = [`import { z } from '${config.zodImport}';`];
116
+ if (usedEnums.size > 0) {
117
+ modelImports.push(`import { ${enumImportList} } from './enums';`);
118
+ }
119
+ if (customSchemas.size > 0) {
120
+ modelImports.push(`import { ${customSchemaImportList} } from './custom-schemas';`);
121
+ }
122
+ const modelsCodeWithoutImports = modelSchemas.map(
123
+ (s) => s.replace(/import \{ z \} from '[^']+';\n/g, "").replace(/import \{ [^}]+ \} from '\.\/enums';\n/g, "").replace(/import \{ [^}]+ \} from '\.\/custom-schemas';\n/g, "").trim()
124
+ ).join("\n\n");
125
+ const modelsCode = `${modelImports.join("\n")}
126
+
127
+ ${modelsCodeWithoutImports}`;
128
+ const modelsPath = path.resolve(outputDir, "models.ts");
129
+ if (!config.dryRun) {
130
+ fs.writeFileSync(modelsPath, modelsCode, "utf-8");
131
+ } else {
132
+ log(` [DRY RUN] Would write to ${modelsPath}`);
133
+ }
134
+ if (customSchemas.size > 0) {
135
+ generateCustomSchemasTemplate(outputDir, customSchemas, log, config);
136
+ }
137
+ log(` \u2705 Generated ${enums.length} enums and ${models.length} model schemas`);
138
+ if (customSchemas.size > 0) {
139
+ log(` \u{1F4DD} Found ${customSchemas.size} custom schema references - update custom-schemas.ts`);
140
+ }
141
+ }
142
+ function generateCustomSchemasTemplate(outputDir, customSchemas, log, config) {
143
+ const customSchemasPath = path.resolve(outputDir, "custom-schemas.ts");
144
+ if (fs.existsSync(customSchemasPath)) {
145
+ log(" \u26A0\uFE0F custom-schemas.ts already exists, skipping template generation");
146
+ return;
147
+ }
148
+ const schemaTemplates = Array.from(customSchemas).map((schemaName) => {
149
+ return `/**
150
+ * ${schemaName} schema
151
+ */
152
+ export const ${schemaName} = z.any(); // Replace with your schema`;
153
+ }).join("\n\n");
154
+ const template = `import { z } from '${config.zodImport}';
155
+
156
+ /**
157
+ * Custom Zod schemas for JSON fields
158
+ *
159
+ * This file contains custom schemas referenced via @zodSchema annotations
160
+ * in your Prisma schema. Update these with your actual schema definitions.
161
+ */
162
+
163
+ ${schemaTemplates}
164
+ `;
165
+ if (!config.dryRun) {
166
+ fs.writeFileSync(customSchemasPath, template, "utf-8");
167
+ log(` \u2728 Created custom-schemas.ts template at ${customSchemasPath}`);
168
+ } else {
169
+ log(` [DRY RUN] Would create template at ${customSchemasPath}`);
170
+ }
171
+ }
172
+ async function inspectSchema(dmmf) {
173
+ const flags = process.env.ZODIPUS_INSPECT_FLAGS || "";
174
+ const showModels = flags.includes("models");
175
+ const showEnums = flags.includes("enums");
176
+ const showRelations = flags.includes("relations");
177
+ const showAll = !showModels && !showEnums && !showRelations;
178
+ const asJson = process.env.ZODIPUS_INSPECT_JSON === "true";
179
+ if (asJson) {
180
+ const output = {};
181
+ if (showAll || showModels) {
182
+ output.models = dmmf.datamodel.models.map((m) => ({
183
+ name: m.name,
184
+ fields: m.fields.map((f) => ({
185
+ name: f.name,
186
+ type: f.type,
187
+ isRequired: f.isRequired,
188
+ isList: f.isList,
189
+ isId: f.isId,
190
+ isUnique: f.isUnique
191
+ }))
192
+ }));
193
+ }
194
+ if (showAll || showEnums) {
195
+ output.enums = dmmf.datamodel.enums.map((e) => ({
196
+ name: e.name,
197
+ values: e.values.map((v) => v.name)
198
+ }));
199
+ }
200
+ console.log(JSON.stringify(output, null, 2));
201
+ return;
202
+ }
203
+ if (showAll || showModels) {
204
+ console.log("\u{1F4E6} Models:");
205
+ console.log("\u2500".repeat(50));
206
+ for (const model of dmmf.datamodel.models) {
207
+ const fieldCount = model.fields.length;
208
+ const scalarCount = model.fields.filter((f) => f.kind !== "object").length;
209
+ const relationCount = fieldCount - scalarCount;
210
+ console.log(` ${model.name} (${scalarCount} fields, ${relationCount} relations)`);
211
+ for (const field of model.fields) {
212
+ const markers = [];
213
+ if (field.isId) markers.push("@id");
214
+ if (field.isUnique) markers.push("@unique");
215
+ if (!field.isRequired) markers.push("optional");
216
+ if (field.isList) markers.push("[]");
217
+ const markerStr = markers.length > 0 ? ` [${markers.join(", ")}]` : "";
218
+ const typeStr = field.kind === "object" ? `\u2192 ${field.type}` : field.type;
219
+ console.log(` \u2022 ${field.name}: ${typeStr}${markerStr}`);
220
+ }
221
+ console.log();
222
+ }
223
+ }
224
+ if (showAll || showEnums) {
225
+ console.log("\n\u{1F3F7}\uFE0F Enums:");
226
+ console.log("\u2500".repeat(50));
227
+ for (const enumDef of dmmf.datamodel.enums) {
228
+ const values = enumDef.values.map((v) => v.name).join(", ");
229
+ console.log(` ${enumDef.name}: ${values}`);
230
+ }
231
+ console.log();
232
+ }
233
+ if (showAll || showRelations) {
234
+ console.log("\n\u{1F517} Relations:");
235
+ console.log("\u2500".repeat(50));
236
+ for (const model of dmmf.datamodel.models) {
237
+ const relations = model.fields.filter((f) => f.kind === "object");
238
+ if (relations.length > 0) {
239
+ console.log(` ${model.name}:`);
240
+ for (const rel of relations) {
241
+ const arrow = rel.isList ? "\u2500\u252C\u25B6" : "\u2500\u2500\u25B6";
242
+ console.log(` ${arrow} ${rel.type} (via ${rel.name})`);
243
+ }
244
+ }
245
+ }
246
+ console.log();
247
+ }
248
+ console.log("\u2705 Inspection complete\n");
249
+ }
250
+ function generateEnumSchema(enumDef, config) {
251
+ const values = enumDef.values.map((v) => ` '${v.name}'`).join(",\n");
252
+ const jsDocLines = ["/**"];
253
+ jsDocLines.push(` * ${enumDef.name} enum schema`);
254
+ if (enumDef.documentation) {
255
+ jsDocLines.push(` * @description ${enumDef.documentation}`);
256
+ }
257
+ jsDocLines.push(` * @values ${enumDef.values.map((v) => v.name).join(", ")}`);
258
+ jsDocLines.push(" */");
259
+ const jsDoc = jsDocLines.join("\n");
260
+ return `import { z } from '${config.zodImport}';
261
+
262
+ ${jsDoc}
263
+ export const ${enumDef.name}Schema = z.enum([
264
+ ${values}
265
+ ]);
266
+
267
+ export type ${enumDef.name} = z.infer<typeof ${enumDef.name}Schema>;`;
268
+ }
269
+ function generateModelSchema(model, enums, config) {
270
+ const enumNames = new Set(enums.map((e) => e.name));
271
+ const scalarFields = model.fields.filter((field) => field.kind !== "object");
272
+ const imports = [`import { z } from '${config.zodImport}';`];
273
+ const enumImports = /* @__PURE__ */ new Set();
274
+ const customSchemaImports = /* @__PURE__ */ new Set();
275
+ const fieldDefinitions = [];
276
+ for (const field of scalarFields) {
277
+ const customSchema = extractCustomSchema(field.documentation);
278
+ let zodType;
279
+ if (customSchema) {
280
+ zodType = customSchema;
281
+ customSchemaImports.add(customSchema);
282
+ } else {
283
+ zodType = mapPrismaTypeToZod(field, enumNames, config);
284
+ if (enumNames.has(field.type)) {
285
+ enumImports.add(field.type);
286
+ }
287
+ }
288
+ const optional = field.isRequired ? "" : ".optional()";
289
+ const nullable = field.isRequired ? "" : ".nullable()";
290
+ const array = field.isList ? ".array()" : "";
291
+ let fieldDef = ` ${field.name}: ${zodType}${array}${optional}${nullable}`;
292
+ const fieldDocLines = [];
293
+ if (field.documentation) {
294
+ const cleanDoc = field.documentation.replace(/@zodSchema\s+\w+/g, "").trim();
295
+ if (cleanDoc) {
296
+ fieldDocLines.push(cleanDoc);
297
+ }
298
+ }
299
+ const constraints = [];
300
+ if (field.isId) constraints.push("@id");
301
+ if (field.isUnique) constraints.push("@unique");
302
+ if (field.hasDefaultValue) {
303
+ const defaultVal = formatDefaultValue(field.default);
304
+ constraints.push(`@default(${defaultVal})`);
305
+ }
306
+ if (field.isUpdatedAt) constraints.push("@updatedAt");
307
+ if (!field.isRequired) constraints.push("optional");
308
+ if (constraints.length > 0) {
309
+ fieldDocLines.push(`Prisma: ${constraints.join(", ")}`);
310
+ }
311
+ if (fieldDocLines.length > 0) {
312
+ fieldDef = ` /** ${fieldDocLines.join(" | ")} */
313
+ ${fieldDef}`;
314
+ }
315
+ fieldDefinitions.push(fieldDef);
316
+ }
317
+ if (enumImports.size > 0) {
318
+ const enumImportList = Array.from(enumImports).map((name) => `${name}Schema`).sort().join(", ");
319
+ imports.push(`import { ${enumImportList} } from './enums';`);
320
+ }
321
+ if (customSchemaImports.size > 0) {
322
+ const customImportList = Array.from(customSchemaImports).sort().join(", ");
323
+ imports.push(`import { ${customImportList} } from './custom-schemas';`);
324
+ }
325
+ const schemaModifier = config.passthroughEnabled ? ".passthrough()" : "";
326
+ return `${imports.join("\n")}
327
+
328
+ /**
329
+ * ${model.name} model (clean schema without relations)
330
+ */
331
+ export const ${model.name}Schema = z.object({
332
+ ${fieldDefinitions.join(",\n")}
333
+ })${schemaModifier};
334
+
335
+ export type ${model.name} = z.infer<typeof ${model.name}Schema>;`;
336
+ }
337
+ function extractCustomSchema(documentation) {
338
+ if (!documentation) return null;
339
+ const match = documentation.match(/@zodSchema\s+(\w+)/);
340
+ return match ? match[1] : null;
341
+ }
342
+ function formatDefaultValue(value) {
343
+ if (typeof value === "object" && value !== null && "name" in value && "args" in value) {
344
+ const { name, args } = value;
345
+ if (name.includes("(")) return name;
346
+ if (Array.isArray(args) && args.length > 0) {
347
+ return `${name}(${args.join(", ")})`;
348
+ }
349
+ return `${name}()`;
350
+ }
351
+ if (typeof value === "object" && value !== null) {
352
+ return JSON.stringify(value);
353
+ }
354
+ return String(value);
355
+ }
356
+ function mapPrismaTypeToZod(field, enumNames, config) {
357
+ if (enumNames.has(field.type)) {
358
+ return `${field.type}Schema`;
359
+ }
360
+ switch (field.type) {
361
+ case "String":
362
+ return "z.string()";
363
+ case "Int":
364
+ return "z.number().int()";
365
+ case "BigInt":
366
+ return "z.bigint()";
367
+ case "Float":
368
+ return "z.number()";
369
+ case "Decimal":
370
+ return 'z.union([z.number(), z.string(), z.custom<{ toString(): string }>((val) => typeof val === "object" && val !== null && "toString" in val)]).transform(String)';
371
+ case "Boolean":
372
+ return "z.boolean()";
373
+ case "DateTime":
374
+ return config.dateFormat === "string" ? "z.string().datetime()" : "z.coerce.date()";
375
+ case "Json":
376
+ return "z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())])";
377
+ case "Bytes":
378
+ return "z.instanceof(Buffer)";
379
+ default:
380
+ return "z.unknown()";
381
+ }
382
+ }
383
+ function extractRelationsFromDMMF(dmmf, maxDepth) {
384
+ const relations = {};
385
+ const modelMap = new Map(dmmf.datamodel.models.map((m) => [m.name, m]));
386
+ function extractForModel(modelName, depth, visited) {
387
+ if (depth > maxDepth || visited.has(modelName)) {
388
+ return {};
389
+ }
390
+ const model = modelMap.get(modelName);
391
+ if (!model) return {};
392
+ const newVisited = new Set(visited);
393
+ newVisited.add(modelName);
394
+ const result = {};
395
+ for (const field of model.fields) {
396
+ if (field.kind === "object") {
397
+ const nestedRelations = extractForModel(field.type, depth + 1, newVisited);
398
+ result[field.name] = {
399
+ type: toCamelCase(field.type),
400
+ isArray: field.isList,
401
+ ...Object.keys(nestedRelations).length > 0 && {
402
+ relations: nestedRelations
403
+ }
404
+ };
405
+ }
406
+ }
407
+ return result;
408
+ }
409
+ for (const model of dmmf.datamodel.models) {
410
+ const modelRelations = extractForModel(model.name, 0, /* @__PURE__ */ new Set());
411
+ if (Object.keys(modelRelations).length > 0) {
412
+ relations[toCamelCase(model.name)] = modelRelations;
413
+ }
414
+ }
415
+ return relations;
416
+ }
417
+ function formatRelationsAsTypeScript(relations, maxDepth) {
418
+ const formatValue = (value, indent) => {
419
+ const spaces = " ".repeat(indent);
420
+ if (typeof value === "string") {
421
+ return `"${value}" as const`;
422
+ }
423
+ if (typeof value === "boolean") {
424
+ return String(value);
425
+ }
426
+ if (typeof value === "object" && value !== null) {
427
+ const entries2 = Object.entries(value);
428
+ if (entries2.length === 0) return "{}";
429
+ const formattedEntries = entries2.map(([key, val]) => {
430
+ const formattedVal = formatValue(val, indent + 1);
431
+ return `${spaces} ${key}: ${formattedVal},`;
432
+ });
433
+ return `{
434
+ ${formattedEntries.join("\n")}
435
+ ${spaces}}`;
436
+ }
437
+ return String(value);
438
+ };
439
+ const lines = [];
440
+ lines.push("/**");
441
+ lines.push(" * Auto-generated relation metadata from Prisma schema");
442
+ lines.push(` * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}`);
443
+ lines.push(` * Max nesting depth: ${maxDepth}`);
444
+ lines.push(" *");
445
+ lines.push(" * Generated by zodipus");
446
+ lines.push(" * To regenerate: prisma generate");
447
+ lines.push(" */");
448
+ lines.push("");
449
+ lines.push("const modelRelations = {");
450
+ const entries = Object.entries(relations);
451
+ for (let i = 0; i < entries.length; i++) {
452
+ const [modelName, modelRelations] = entries[i];
453
+ const formattedRelations = formatValue(modelRelations, 1);
454
+ const comma = i < entries.length - 1 ? "," : "";
455
+ lines.push(` ${modelName}: ${formattedRelations}${comma}`);
456
+ }
457
+ lines.push("} as const;");
458
+ lines.push("");
459
+ lines.push("export default modelRelations;");
460
+ lines.push("");
461
+ return lines.join("\n");
462
+ }
463
+ function generateIndexFile(dmmf) {
464
+ const modelNames = dmmf.datamodel.models.map((m) => m.name);
465
+ const enumNames = dmmf.datamodel.enums.map((e) => e.name);
466
+ const modelTypeExports = modelNames.map((name) => ` ${name},`).join("\n");
467
+ const enumTypeExports = enumNames.map((name) => ` ${name},`).join("\n");
468
+ return `/**
469
+ * Generated export from zodipus
470
+ *
471
+ * This file exports:
472
+ * - Clean Zod model schemas (without relations)
473
+ * - Enum schemas
474
+ * - Relation metadata
475
+ */
476
+
477
+ // Export enum schemas
478
+ export * from './enums';
479
+
480
+ // Export model schemas
481
+ export * as models from './models';
482
+
483
+ // Export relation metadata
484
+ export { default as modelRelations } from './generated-relations';
485
+
486
+ // Re-export types for convenience
487
+ export type {
488
+ ${modelTypeExports}
489
+ } from './models';
490
+
491
+ export type {
492
+ ${enumTypeExports}
493
+ } from './enums';
494
+ `;
495
+ }
496
+ function toCamelCase(str) {
497
+ return str.charAt(0).toLowerCase() + str.slice(1);
498
+ }
499
+
500
+ // src/errors.ts
501
+ var ZodipusError = class extends Error {
502
+ constructor(message) {
503
+ super(message);
504
+ this.name = "ZodipusError";
505
+ if (Error.captureStackTrace) {
506
+ Error.captureStackTrace(this, this.constructor);
507
+ }
508
+ }
509
+ };
510
+ var ZodipusValidationError = class extends ZodipusError {
511
+ context;
512
+ constructor(message, context) {
513
+ const contextInfo = [
514
+ `Model: ${context.model}`,
515
+ context.field ? `Field: ${context.field}` : null,
516
+ context.expected ? `Expected: ${context.expected}` : null,
517
+ context.received ? `Received: ${context.received}` : null,
518
+ context.path?.length ? `Path: ${context.path.join(".")}` : null
519
+ ].filter(Boolean).join(", ");
520
+ super(`${message} (${contextInfo})`);
521
+ this.name = "ZodipusValidationError";
522
+ this.context = context;
523
+ }
524
+ };
525
+ var ZodipusGeneratorError = class extends ZodipusError {
526
+ schemaPath;
527
+ modelName;
528
+ constructor(message, options) {
529
+ const contextParts = [
530
+ options?.schemaPath ? `Schema: ${options.schemaPath}` : null,
531
+ options?.modelName ? `Model: ${options.modelName}` : null
532
+ ].filter(Boolean);
533
+ const fullMessage = contextParts.length ? `${message} (${contextParts.join(", ")})` : message;
534
+ super(fullMessage);
535
+ this.name = "ZodipusGeneratorError";
536
+ this.schemaPath = options?.schemaPath;
537
+ this.modelName = options?.modelName;
538
+ }
539
+ };
540
+
541
+ // src/queryEngine.ts
542
+ function createRegistry(config) {
543
+ return {
544
+ createQuery: (model) => {
545
+ return (query) => {
546
+ const createParser = (isArray) => {
547
+ return (data) => {
548
+ const parseRelations = (item) => {
549
+ if (typeof item !== "object" || item === null) {
550
+ throw new ZodipusValidationError(`Invalid data for model "${String(model)}"`, {
551
+ model: String(model),
552
+ expected: "object",
553
+ received: item === null ? "null" : typeof item
554
+ });
555
+ }
556
+ let result;
557
+ if (hasSelect) {
558
+ result = item;
559
+ } else {
560
+ const modelSchema = config.models[model];
561
+ if (!modelSchema) {
562
+ throw new ZodipusValidationError("Model schema not found", {
563
+ model: String(model)
564
+ });
565
+ }
566
+ const parsed = modelSchema.parse(item);
567
+ result = parsed;
568
+ }
569
+ for (const [key, value] of Object.entries(query)) {
570
+ if (key === "select") continue;
571
+ if (typeof item === "object" && item !== null && key in item) {
572
+ const modelRelations = config.relations[model];
573
+ if (!modelRelations) continue;
574
+ const relationType = modelRelations[key]?.type;
575
+ if (!relationType) continue;
576
+ const relationHasSelectOrInclude = typeof value === "object" && value !== null && ("select" in value || "include" in value);
577
+ if (Array.isArray(item[key])) {
578
+ result[key] = item[key].map(
579
+ (rel) => {
580
+ if (relationHasSelectOrInclude) {
581
+ return rel;
582
+ }
583
+ const relationSchema = config.models[relationType];
584
+ if (!relationSchema) {
585
+ throw new ZodipusValidationError("Model schema not found for relation", {
586
+ model: relationType,
587
+ field: key,
588
+ path: [String(model), key]
589
+ });
590
+ }
591
+ return relationSchema.parse(rel);
592
+ }
593
+ );
594
+ } else {
595
+ const relData = item[key];
596
+ if (relData === null) {
597
+ result[key] = null;
598
+ } else if (relationHasSelectOrInclude) {
599
+ result[key] = relData;
600
+ } else {
601
+ const relationSchema = config.models[relationType];
602
+ if (!relationSchema) {
603
+ throw new ZodipusValidationError("Model schema not found for relation", {
604
+ model: relationType,
605
+ field: key,
606
+ path: [String(model), key]
607
+ });
608
+ }
609
+ result[key] = relationSchema.parse(relData);
610
+ }
611
+ }
612
+ }
613
+ }
614
+ return result;
615
+ };
616
+ if (isArray) {
617
+ const arrayData = data;
618
+ return arrayData.map(parseRelations);
619
+ }
620
+ return parseRelations(data);
621
+ };
622
+ };
623
+ const relationEntries = Object.fromEntries(
624
+ Object.entries(query).filter(([key]) => key !== "select")
625
+ );
626
+ const hasSelect = "select" in query && query.select;
627
+ const hasRelations = Object.keys(relationEntries).length > 0;
628
+ let selectQuery;
629
+ let includeQuery;
630
+ if (hasSelect && hasRelations) {
631
+ selectQuery = {
632
+ ...query.select ?? {},
633
+ ...relationEntries
634
+ };
635
+ includeQuery = {};
636
+ } else if (hasSelect && !hasRelations) {
637
+ selectQuery = query.select ?? {};
638
+ includeQuery = {};
639
+ } else if (!hasSelect && hasRelations) {
640
+ selectQuery = {};
641
+ includeQuery = relationEntries;
642
+ } else {
643
+ selectQuery = {};
644
+ includeQuery = {};
645
+ }
646
+ return {
647
+ query: hasSelect ? { select: selectQuery } : { include: includeQuery },
648
+ parse: createParser(false),
649
+ safeParse: ((data) => {
650
+ try {
651
+ return { success: true, data: createParser(false)(data) };
652
+ } catch (error) {
653
+ return {
654
+ success: false,
655
+ error: error instanceof Error ? error : new Error(String(error))
656
+ };
657
+ }
658
+ }),
659
+ array: () => ({
660
+ parse: createParser(true),
661
+ safeParse: ((data) => {
662
+ try {
663
+ return { success: true, data: createParser(true)(data) };
664
+ } catch (error) {
665
+ return {
666
+ success: false,
667
+ error: error instanceof Error ? error : new Error(String(error))
668
+ };
669
+ }
670
+ })
671
+ })
672
+ };
673
+ };
674
+ }
675
+ };
676
+ }
677
+
678
+ // src/index.ts
679
+ generatorHelper.generatorHandler({
680
+ onManifest() {
681
+ return {
682
+ prettyName: "Zodipus - Prisma Zod Schema Generator",
683
+ defaultOutput: "../generated"
684
+ };
685
+ },
686
+ async onGenerate(options) {
687
+ await generate(options);
688
+ }
689
+ });
690
+
691
+ exports.ZodipusError = ZodipusError;
692
+ exports.ZodipusGeneratorError = ZodipusGeneratorError;
693
+ exports.ZodipusValidationError = ZodipusValidationError;
694
+ exports.createRegistry = createRegistry;
695
+ //# sourceMappingURL=index.cjs.map
696
+ //# sourceMappingURL=index.cjs.map