UNPKG

prisma-zod-generator

Version:

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

790 lines 32.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ValidationErrorType = exports.MINIMAL_OPERATIONS = exports.DEFAULT_CONFIG = exports.SCHEMA_VARIANTS = exports.GENERATION_MODES = exports.PRISMA_OPERATIONS = exports.SuffixSchema = exports.OutputPathSchema = exports.ModelNameSchema = exports.FieldNameSchema = exports.ConfigurationSchema = void 0; exports.isValidFieldName = isValidFieldName; exports.isValidModelName = isValidModelName; exports.isValidOperation = isValidOperation; exports.isValidMode = isValidMode; exports.isValidVariant = isValidVariant; exports.isValidSuffix = isValidSuffix; exports.getSchemaSection = getSchemaSection; exports.createPartialSchema = createPartialSchema; /** * Comprehensive JSON Schema for Prisma Zod Generator configuration * * This schema defines strict validation rules for all configuration options * including data types, constraints, and allowed values. */ exports.ConfigurationSchema = { $schema: 'http://json-schema.org/draft-07/schema#', title: 'Prisma Zod Generator Configuration', description: 'Configuration schema for the Prisma Zod Generator', type: 'object', additionalProperties: false, properties: { $schema: { type: 'string', default: 'http://json-schema.org/draft-07/schema#', // Placeholder most likely would be https://omar-dulaimi.github.io/prisma-zod-generator/docs/schema.json description: 'JSON Schema for the Prisma Zod Generator configuration', }, mode: { type: 'string', enum: ['full', 'minimal', 'custom'], default: 'full', description: 'Generation mode: full (all schemas), minimal (basic CRUD only), or custom', }, output: { type: 'string', minLength: 1, pattern: '^[^<>:"|?*\\x00-\\x1f]+$', description: 'Output directory path for generated schemas', }, useMultipleFiles: { type: 'boolean', default: true, description: 'When true (default), generate multiple files; when false, generate a single bundled file', }, singleFileName: { type: 'string', minLength: 1, default: 'schemas.ts', description: 'Name of the single bundled file when useMultipleFiles is false', }, placeSingleFileAtRoot: { type: 'boolean', default: true, description: 'When bundling to a single file, place it at the output root instead of a schemas/ subdirectory', }, placeArrayVariantsAtRoot: { type: 'boolean', default: true, description: 'When using array-based variants, place them at schemas root; if false, under variants/', }, formatGeneratedSchemas: { type: 'boolean', default: false, description: 'Whether to run a formatter on generated schemas', }, pureModels: { type: 'boolean', default: false, description: 'Whether to generate pure model schemas', }, pureModelsLean: { type: 'boolean', default: true, description: 'Emit lean pure model schemas (no verbose JSDoc/statistics/comments)', }, pureModelsIncludeRelations: { type: 'boolean', default: false, description: 'When pureModels is true, include relation fields. Default false (omit relation fields for slimmer models)', }, pureModelsExcludeCircularRelations: { type: 'boolean', default: false, description: 'When pureModelsIncludeRelations is true, exclude relation fields that would create circular references. Keeps foreign key fields but omits relation object fields to avoid TypeScript circular dependency errors.', }, naming: { type: 'object', additionalProperties: false, description: 'Optional naming customization settings (experimental)', properties: { preset: { type: 'string', enum: ['default', 'zod-prisma', 'zod-prisma-types', 'legacy-model-suffix'], description: 'Predefined naming preset to apply', }, pureModel: { type: 'object', additionalProperties: false, description: 'Overrides for pure model file and symbol naming', properties: { filePattern: { type: 'string', minLength: 3, maxLength: 80, description: 'Pattern for pure model file names. Tokens: {Model}, {model}, {camel}, {kebab}. Must end with .ts', pattern: '.*\\.ts$', }, schemaSuffix: { type: 'string', minLength: 0, maxLength: 30, pattern: '^[A-Z][A-Za-z0-9_]*$|^$', description: 'Suffix appended to schema variable (e.g. Schema). Empty string allowed.', }, typeSuffix: { type: 'string', minLength: 0, maxLength: 30, pattern: '^[A-Z][A-Za-z0-9_]*$|^$', description: 'Suffix appended to inferred type export (e.g. Type). Empty string allowed.', }, exportNamePattern: { type: 'string', minLength: 0, maxLength: 80, description: 'Pattern for schema export variable. Tokens: {Model} {model} plus optional suffix tokens {SchemaSuffix}. Defaults derived from schemaSuffix.', }, legacyAliases: { type: 'boolean', default: false, description: 'Emit deprecated alias exports (e.g. UserModel) for compatibility when preset supplies them.', }, }, }, schema: { type: 'object', additionalProperties: false, description: 'Overrides for CRUD operation schema file and symbol naming', properties: { filePattern: { type: 'string', minLength: 3, maxLength: 80, description: 'Pattern for schema file names. Tokens: {Model}, {model}, {camel}, {kebab}. Must end with .ts', pattern: '.*\\.ts$', }, exportNamePattern: { type: 'string', minLength: 0, maxLength: 80, description: 'Pattern for schema export variable. Tokens: {Model}, {model}, {Operation}.', }, }, }, input: { type: 'object', additionalProperties: false, description: 'Overrides for input object file and symbol naming', properties: { filePattern: { type: 'string', minLength: 3, maxLength: 80, description: 'Pattern for input file names. Tokens: {Model}, {model}, {camel}, {kebab}, {InputType}. Must end with .ts', pattern: '.*\\.ts$', }, exportNamePattern: { type: 'string', minLength: 0, maxLength: 80, description: 'Pattern for input export variable. Tokens: {Model}, {model}, {InputType}.', }, }, }, enum: { type: 'object', additionalProperties: false, description: 'Overrides for enum file and symbol naming', properties: { filePattern: { type: 'string', minLength: 3, maxLength: 80, description: 'Pattern for enum file names. Tokens: {Enum}, {enum}, {camel}, {kebab}. Must end with .ts', pattern: '.*\\.ts$', }, exportNamePattern: { type: 'string', minLength: 0, maxLength: 80, description: 'Pattern for enum export variable. Tokens: {Enum}, {enum}.', }, }, }, }, }, dateTimeStrategy: { type: 'string', enum: ['date', 'coerce', 'isoString'], default: 'date', description: 'How DateTime fields are represented: date (z.date()), coerce (z.coerce.date()), isoString (ISO string validated & transformed)', }, dateTimeSplitStrategy: { type: 'boolean', default: true, description: 'When true and dateTimeStrategy is unset, use coerce for input schemas and date for pure/result schemas (split strategy)', }, jsonSchemaCompatible: { type: 'boolean', default: false, description: 'Generate schemas compatible with z.toJSONSchema() for API documentation. When enabled, overrides dateTimeStrategy and removes transforms. Trade-off: No runtime type conversion.', }, jsonSchemaOptions: { type: 'object', properties: { dateTimeFormat: { type: 'string', enum: ['isoString', 'isoDate'], default: 'isoString', description: 'Format for DateTime fields in JSON Schema compatible mode', }, bigIntFormat: { type: 'string', enum: ['string', 'number'], default: 'string', description: 'Format for BigInt fields in JSON Schema compatible mode', }, bytesFormat: { type: 'string', enum: ['base64String', 'hexString'], default: 'base64String', description: 'Format for Bytes fields in JSON Schema compatible mode', }, conversionOptions: { type: 'object', additionalProperties: false, properties: { unrepresentable: { type: 'string', enum: ['throw', 'any'], default: 'any' }, cycles: { type: 'string', enum: ['ref', 'throw'], default: 'throw' }, reused: { type: 'string', enum: ['inline', 'ref'], default: 'inline' }, }, description: 'Options forwarded to z.toJSONSchema()', }, }, additionalProperties: false, description: 'Options for JSON Schema compatibility mode', }, addSelectType: { type: 'boolean', default: false, description: 'Legacy option: also generate Select type', }, addIncludeType: { type: 'boolean', default: false, description: 'Legacy option: also generate Include type', }, strictCreateInputs: { type: 'boolean', default: true, description: 'When true, Create-like inputs bypass exclusions and strictly match Prisma types', }, preserveRequiredScalarsOnCreate: { type: 'boolean', default: true, description: 'When strictCreateInputs is false, keep required non-auto scalars in Create-like inputs even if excluded', }, inferCreateArgsFromSchemas: { type: 'boolean', default: false, description: 'When true, Args for create operations infer types from generated schemas instead of Prisma.*', }, globalExclusions: { type: 'object', additionalProperties: false, description: 'Global field exclusions applied to all models', properties: { input: { type: 'array', items: { type: 'string', minLength: 1, pattern: '^[a-zA-Z_][a-zA-Z0-9_]*$', }, uniqueItems: true, description: 'Fields to exclude from input schemas globally', }, result: { type: 'array', items: { type: 'string', minLength: 1, pattern: '^[a-zA-Z_][a-zA-Z0-9_]*$', }, uniqueItems: true, description: 'Fields to exclude from result schemas globally', }, pure: { type: 'array', items: { type: 'string', minLength: 1, pattern: '^[a-zA-Z_][a-zA-Z0-9_]*$', }, uniqueItems: true, description: 'Fields to exclude from pure model schemas globally', }, operations: { type: 'array', items: { type: 'string', enum: [ 'findMany', 'findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow', 'create', 'createMany', 'createManyAndReturn', 'update', 'updateMany', 'updateManyAndReturn', 'upsert', 'delete', 'deleteMany', 'aggregate', 'groupBy', 'count', ], }, uniqueItems: true, minItems: 1, description: 'Operations to exclude globally from all models', }, }, }, variants: { type: 'object', additionalProperties: false, description: 'Configuration for different schema variants', properties: { pure: { $ref: '#/definitions/variantConfig', description: 'Pure model schema variant configuration', }, input: { $ref: '#/definitions/variantConfig', description: 'Input schema variant configuration', }, result: { $ref: '#/definitions/variantConfig', description: 'Result schema variant configuration', }, }, }, models: { type: 'object', additionalProperties: false, description: 'Per-model configuration options', patternProperties: { '^[A-Z][a-zA-Z0-9_]*$': { $ref: '#/definitions/modelConfig', description: 'Model-specific configuration (model names must be PascalCase)', }, }, }, zodImportTarget: { type: 'string', enum: ['auto', 'v3', 'v4'], default: 'auto', description: "How to import Zod in generated code: 'auto' uses import * as z from 'zod'; 'v3' uses import { z } from 'zod'; 'v4' uses import * as z from 'zod/v4'", }, validateWhereUniqueAtLeastOne: { type: 'boolean', default: false, description: 'Opt-in: add a minimal Zod superRefine to WhereUniqueInput schemas requiring at least one top-level unique selector to be present. Disabled by default.', }, strictMode: { type: 'object', additionalProperties: false, description: 'Global strict mode configuration for generated Zod schemas', properties: { enabled: { type: 'boolean', default: true, description: 'Global default for strict mode on all schemas (backward compatibility)', }, operations: { type: 'boolean', default: true, description: 'Apply strict mode to operation schemas (findMany, create, etc.)', }, objects: { type: 'boolean', default: true, description: 'Apply strict mode to object schemas (WhereInput, CreateInput, etc.)', }, variants: { type: 'boolean', default: true, description: 'Apply strict mode to variant schemas (pure, input, result)', }, enums: { type: 'boolean', default: true, description: 'Apply strict mode to enum schemas', }, }, }, }, definitions: { variantConfig: { type: 'object', additionalProperties: false, description: 'Configuration for a specific schema variant', properties: { enabled: { type: 'boolean', default: true, description: 'Whether this variant should be generated', }, suffix: { type: 'string', minLength: 1, maxLength: 20, pattern: '^\\.[a-zA-Z][a-zA-Z0-9_]*$', description: 'File suffix for this variant (must start with a dot, e.g., ".model")', }, excludeFields: { type: 'array', items: { type: 'string', minLength: 1, pattern: '^[a-zA-Z_][a-zA-Z0-9_]*$', }, uniqueItems: true, description: 'Fields to exclude from this variant', }, partial: { type: 'boolean', default: false, description: 'Apply .partial() to the generated schema, making all fields optional', }, strictMode: { type: ['boolean', 'null'], description: 'Override strict mode for this variant (null uses global/parent setting)', }, }, }, modelConfig: { type: 'object', additionalProperties: false, description: 'Configuration for a specific Prisma model', properties: { enabled: { type: 'boolean', default: true, description: 'Whether schemas should be generated for this model', }, operations: { type: 'array', items: { type: 'string', enum: [ 'findMany', 'findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow', 'create', 'createMany', 'createManyAndReturn', 'update', 'updateMany', 'updateManyAndReturn', 'upsert', 'delete', 'deleteMany', 'aggregate', 'groupBy', 'count', ], }, uniqueItems: true, minItems: 1, description: 'Which operations to generate schemas for', }, strictMode: { type: 'object', additionalProperties: false, description: 'Strict mode configuration for this model', properties: { enabled: { type: ['boolean', 'null'], description: 'Override global strict mode for this model (null uses global setting)', }, operations: { oneOf: [ { type: 'boolean' }, { type: 'array', items: { type: 'string', enum: [ 'findMany', 'findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow', 'create', 'createMany', 'createManyAndReturn', 'update', 'updateMany', 'updateManyAndReturn', 'upsert', 'delete', 'deleteMany', 'aggregate', 'groupBy', 'count', ], }, uniqueItems: true, }, { type: 'null' }, ], description: 'Control strict mode for specific operations (boolean for all, array for specific, null for global)', }, exclude: { type: 'array', items: { type: 'string', enum: [ 'findMany', 'findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow', 'create', 'createMany', 'createManyAndReturn', 'update', 'updateMany', 'updateManyAndReturn', 'upsert', 'delete', 'deleteMany', 'aggregate', 'groupBy', 'count', ], }, uniqueItems: true, description: 'Operations to exclude from strict mode', }, objects: { type: ['boolean', 'null'], description: 'Override strict mode for object schemas of this model (null uses global setting)', }, variants: { type: 'object', additionalProperties: false, description: 'Per-variant strict mode overrides for this model', properties: { pure: { type: ['boolean', 'null'], description: 'Override strict mode for pure variant of this model', }, input: { type: ['boolean', 'null'], description: 'Override strict mode for input variant of this model', }, result: { type: ['boolean', 'null'], description: 'Override strict mode for result variant of this model', }, }, }, }, }, variants: { type: 'object', additionalProperties: false, description: 'Variant-specific configuration for this model', properties: { pure: { $ref: '#/definitions/variantConfig', description: 'Pure model variant configuration for this model', }, input: { $ref: '#/definitions/variantConfig', description: 'Input variant configuration for this model', }, result: { $ref: '#/definitions/variantConfig', description: 'Result variant configuration for this model', }, }, }, }, }, }, }; /** * Schema for validating individual field names */ exports.FieldNameSchema = { type: 'string', minLength: 1, maxLength: 64, pattern: '^[a-zA-Z_][a-zA-Z0-9_]*$', description: 'Valid field name (alphanumeric with underscores, cannot start with number)', }; /** * Schema for validating model names (PascalCase) */ exports.ModelNameSchema = { type: 'string', minLength: 1, maxLength: 64, pattern: '^[A-Z][a-zA-Z0-9_]*$', description: 'Valid model name (PascalCase, alphanumeric with underscores)', }; /** * Schema for validating output directory paths */ exports.OutputPathSchema = { type: 'string', minLength: 1, maxLength: 260, // Windows MAX_PATH limitation pattern: '^[^<>:"|?*\\x00-\\x1f]+$', description: 'Valid output directory path (no invalid filename characters)', }; /** * Schema for validating file suffixes */ exports.SuffixSchema = { type: 'string', minLength: 2, // At least ".x" maxLength: 20, pattern: '^\\.[a-zA-Z][a-zA-Z0-9_]*$', description: 'Valid file suffix (must start with dot, followed by valid identifier)', }; /** * Available Prisma operations that can be configured */ exports.PRISMA_OPERATIONS = [ 'findMany', 'findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow', 'create', 'createMany', 'createManyAndReturn', 'update', 'updateMany', 'updateManyAndReturn', 'upsert', 'delete', 'deleteMany', 'aggregate', 'groupBy', 'count', ]; /** * Available generation modes */ exports.GENERATION_MODES = ['full', 'minimal', 'custom']; /** * Available schema variants */ exports.SCHEMA_VARIANTS = ['pure', 'input', 'result']; /** * Default configuration values */ exports.DEFAULT_CONFIG = { mode: 'full', output: './generated', globalExclusions: {}, variants: { pure: { enabled: true, suffix: '.model', }, input: { enabled: true, suffix: '.input', }, result: { enabled: true, suffix: '.result', }, }, models: {}, }; /** * Minimal mode operation set */ exports.MINIMAL_OPERATIONS = [ 'findMany', 'findUnique', 'findFirst', 'create', 'update', 'delete', ]; /** * Configuration validation error types */ var ValidationErrorType; (function (ValidationErrorType) { ValidationErrorType["INVALID_JSON_SCHEMA"] = "INVALID_JSON_SCHEMA"; ValidationErrorType["INVALID_FIELD_NAME"] = "INVALID_FIELD_NAME"; ValidationErrorType["INVALID_MODEL_NAME"] = "INVALID_MODEL_NAME"; ValidationErrorType["INVALID_OPERATION"] = "INVALID_OPERATION"; ValidationErrorType["INVALID_MODE"] = "INVALID_MODE"; ValidationErrorType["INVALID_VARIANT"] = "INVALID_VARIANT"; ValidationErrorType["DUPLICATE_VALUES"] = "DUPLICATE_VALUES"; ValidationErrorType["MISSING_REQUIRED"] = "MISSING_REQUIRED"; })(ValidationErrorType || (exports.ValidationErrorType = ValidationErrorType = {})); /** * Utility function to validate field names */ function isValidFieldName(fieldName) { return (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(fieldName) && fieldName.length > 0 && fieldName.length <= 64); } /** * Utility function to validate model names (PascalCase) */ function isValidModelName(modelName) { return /^[A-Z][a-zA-Z0-9_]*$/.test(modelName) && modelName.length > 0 && modelName.length <= 64; } /** * Utility function to validate Prisma operations */ function isValidOperation(operation) { return exports.PRISMA_OPERATIONS.includes(operation); } /** * Utility function to validate generation modes */ function isValidMode(mode) { return exports.GENERATION_MODES.includes(mode); } /** * Utility function to validate schema variants */ function isValidVariant(variant) { return exports.SCHEMA_VARIANTS.includes(variant); } /** * Utility function to validate file suffixes */ function isValidSuffix(suffix) { return /^\.[a-zA-Z][a-zA-Z0-9_]*$/.test(suffix) && suffix.length >= 2 && suffix.length <= 20; } /** * Get schema reference for a specific configuration section */ function getSchemaSection(section) { var _a; return (_a = exports.ConfigurationSchema.definitions) === null || _a === void 0 ? void 0 : _a[section]; } /** * Create a custom schema for validating specific parts of the configuration */ function createPartialSchema(properties) { const baseSchema = { ...exports.ConfigurationSchema }; const filteredProperties = {}; properties.forEach((prop) => { var _a; if ((_a = baseSchema.properties) === null || _a === void 0 ? void 0 : _a[prop]) { const propSchema = baseSchema.properties[prop]; if (typeof propSchema === 'object') { filteredProperties[prop] = propSchema; } } }); return { ...baseSchema, properties: filteredProperties, required: properties.filter((prop) => { var _a; return (_a = baseSchema.required) === null || _a === void 0 ? void 0 : _a.includes(prop); }), }; } //# sourceMappingURL=schema.js.map