prisma-zod-generator
Version:
Prisma 2+ generator to emit Zod schemas from your Prisma schema
221 lines (220 loc) • 7.5 kB
TypeScript
/**
* 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;