UNPKG

prisma-zod-generator

Version:

Prisma 2+ generator to emit Zod schemas from your Prisma schema

221 lines (220 loc) 7.5 kB
/** * Result Schema Generator * Generates Zod schemas for Prisma operation return values to enable validation of API responses and operation results */ import { DMMF } from '@prisma/generator-helper'; import { GeneratorConfig } from '../config/parser'; /** * Prisma operation types that return results */ export declare enum OperationType { FIND_UNIQUE = "findUnique", FIND_FIRST = "findFirst", FIND_MANY = "findMany", CREATE = "create", CREATE_MANY = "createMany", UPDATE = "update", UPDATE_MANY = "updateMany", UPSERT = "upsert", DELETE = "delete", DELETE_MANY = "deleteMany", AGGREGATE = "aggregate", GROUP_BY = "groupBy", COUNT = "count" } /** * Result schema generation options */ export interface ResultSchemaOptions { modelName: string; operationType: OperationType; includeRelations?: string[]; excludeFields?: string[]; paginationSupport?: boolean; nullableResult?: boolean; customValidations?: Record<string, string>; } /** * Pagination schema configuration */ export interface PaginationConfig { includeCursor?: boolean; includeCount?: boolean; includePageInfo?: boolean; customFields?: Record<string, string>; } /** * Aggregate operation configuration */ export interface AggregateConfig { includeCount?: boolean; includeSum?: string[]; includeAvg?: string[]; includeMin?: string[]; includeMax?: string[]; customAggregates?: Record<string, string>; } /** * Reference to a pure model schema that a result schema depends on. * `exportName` is the exported identifier (e.g. `TagSchema`) and `fileBase` * is the model file name without its `.ts` extension (e.g. `Tag.schema`). */ export interface ResultModelSchemaRef { exportName: string; fileBase: string; } /** * Generated result schema information */ export interface GeneratedResultSchema { operationType: OperationType; schemaName: string; zodSchema: string; typeDefinition: string; imports: Set<string>; exports: Set<string>; dependencies: string[]; /** * Pure model schemas (by Prisma model name) referenced by relation fields in * this result schema. The transformer turns these into `../models/*` imports. * Separate from `dependencies` (which routes through `../objects`). */ modelDependencies: string[]; documentation: string; examples?: string[]; } /** * Result schema generation context */ export interface ResultGenerationContext { model: DMMF.Model; options: ResultSchemaOptions; baseModelSchema?: string; relatedModels: Map<string, DMMF.Model>; fieldTypeMap: Map<string, string>; } /** * Result Schema Generator * Main class for generating Zod schemas for Prisma operation results */ export declare class ResultSchemaGenerator { private generatedSchemas; private baseModelSchemas; private config; /** * Pure model schemas that are known to be emitted and safe to reference from * result schemas, keyed by Prisma model name. Populated by the transformer via * {@link setAvailablePureModels}. When a relation's target model is present * here, the relation field references its `<Model>Schema`; otherwise it falls * back to `z.unknown()`. Empty in single-file mode (references cannot resolve * across the inlined bundle) so relations degrade to the safe fallback. */ private availablePureModels; private isJsonSchemaModeEnabled; /** * Zod expression for a Decimal field in a result schema, honoring decimalMode. * * Result schemas validate what Prisma *returns*, and in the default 'decimal' * mode that is a Prisma.Decimal instance — so a plain z.number() would reject * real query results. The 'decimal' expression is deliberately import-free * (structural check on the decimal.js shape) so result files stay * dependency-free and keep working in single-file bundles; it also matches * Decimal instances coming from a different runtime copy of the class. * * It remains a union with number and numeric string so that callers already * parsing serialized results (which previously validated against z.number()) * keep working — the change only adds the Decimal shape that used to be * rejected. */ private decimalResultExpression; private getJsonSchemaOptions; constructor(config?: GeneratorConfig); /** * Register the set of pure model schemas that are emitted and safe to * reference from generated result schemas. Called by the transformer, which * owns knowledge of model enablement, the pure-model emission predicate and * the pure-model naming resolver. Passing an empty map (the single-file case) * makes every relation field fall back to `z.unknown()`. */ setAvailablePureModels(models: Map<string, ResultModelSchemaRef>): void; /** * Generate result schema for a specific operation */ generateResultSchema(model: DMMF.Model, options: ResultSchemaOptions): GeneratedResultSchema; /** * Generate schemas for all operations of a model */ generateAllResultSchemas(model: DMMF.Model, operationTypes?: OperationType[]): GeneratedResultSchema[]; /** * Build generation context */ private buildGenerationContext; /** * Generate single result schema (for operations returning one model or null) */ private generateSingleResultSchema; /** * Generate array result schema (for findMany operations) */ private generateArrayResultSchema; /** * Generate batch operation result schema */ private generateBatchResultSchema; /** * Generate aggregate result schema */ private generateAggregateResultSchema; /** * Generate groupBy result schema */ private generateGroupByResultSchema; /** * Generate count result schema */ private generateCountResultSchema; /** * Helper methods */ private generateSchemaName; private operationTypeToSuffix; private isNullableOperation; private buildBaseResultSchema; /** * Build the Zod expression for a relation (object) field in a record-shaped * result schema. References the related model's pure schema when it is emitted * and safe to import; otherwise falls back to `z.unknown()`. Always optional * because relations are only present when the query `include`s them. * * Self-relations (target model === current model) use the fallback so the * result file never has to import a schema for a cyclic/self reference, * mirroring the existing guard in {@link extractDependencies}. */ private buildRelationFieldSchema; private buildRelationSchema; private buildAggregateFields; private buildGroupByFields; private generatePaginationSchema; private mapPrismaTypeToZod; private getBaseModelSchema; private extractDependencies; private generateDocumentation; private generateExamples; private generateCacheKey; /** * Public utility methods */ /** * Clear generated schema cache */ clearCache(): void; /** * Get all generated schemas */ getAllGeneratedSchemas(): GeneratedResultSchema[]; /** * Register base model schema */ registerBaseModelSchema(modelName: string, schema: string): void; } export default ResultSchemaGenerator;