Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/generator/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zod-prisma-types",
"version": "3.2.4",
"version": "3.2.5-20250710+heartade",
"description": "Generates zod schemas from Prisma models with advanced validation",
"author": "Chris Hörmann",
"license": "MIT",
Expand Down
13 changes: 5 additions & 8 deletions packages/generator/src/classes/extendedDMMF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ExtendedDMMFDatamodel } from './extendedDMMFDatamodel';
import { ExtendedDMMFMappings } from './extendedDMMFMappings';
import { ExtendedDMMFSchema } from './extendedDMMFSchema';
import type { GeneratorConfig } from '../schemas';
import { writeImportStatementOptions } from './fileWriter';

/////////////////////////////////////////////////
// CLASS
Expand All @@ -14,8 +15,8 @@ export class ExtendedDMMF implements DMMF.Document {
readonly datamodel: ExtendedDMMFDatamodel;
readonly schema: ExtendedDMMFSchema;
readonly mappings: DMMF.Mappings;
readonly imports: Set<string>;
readonly customImports: Set<string>;
readonly imports: writeImportStatementOptions[];
readonly customImports: writeImportStatementOptions[];

constructor(dmmf: DMMF.Document, config: GeneratorConfig) {
this.generatorConfig = this._setGeneratorConfig(config);
Expand All @@ -39,15 +40,11 @@ export class ExtendedDMMF implements DMMF.Document {
}

private _getImports() {
return new Set(
this.datamodel.models.map((model) => [...model.imports]).flat(),
);
return this.datamodel.models.map((model) => [...model.imports]).flat();
}

private _getModelImports() {
return new Set(
this.datamodel.models.map((model) => [...model.modelImports]).flat(),
);
return this.datamodel.models.map((model) => [...model.modelImports]).flat();
}

private _getExtendedMappings(dmmf: DMMF.Document) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import { GeneratorConfig } from '../../schemas';
import { transformImportStringToList } from '../../utils/transformImportStringToList';
import { validateImportStatement } from '../../utils/validateImportStatements';
import { ExtendedDMMFFieldZodType } from './12_extendedDMMFFieldZodType';
import { transformImportListToOptions } from '../../utils/transformImportListToOptions';
import { writeImportStatementOptions } from '../fileWriter';

/////////////////////////////////////////////////
// CLASS
/////////////////////////////////////////////////

export class ExtendedDMMFFieldImportMatch extends ExtendedDMMFFieldZodType {
protected _importStatements?: string;
readonly imports: Set<string>;
readonly imports: writeImportStatementOptions[];

constructor(
field: DMMF.Field,
Expand All @@ -33,7 +35,8 @@ export class ExtendedDMMFFieldImportMatch extends ExtendedDMMFFieldZodType {
}

private _getImports() {
if (!this._importStatements) return new Set([]);
return new Set(transformImportStringToList(this._importStatements));
if (!this._importStatements) return [];
const importList = transformImportStringToList(this._importStatements);
return transformImportListToOptions(importList);
}
}
3 changes: 2 additions & 1 deletion packages/generator/src/classes/extendedDMMFField/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { OmitFieldMode } from './11_extendedDMMFFieldOmitField';
import { GeneratorConfig } from '../../schemas';
import { FormattedNames } from '../formattedNames';
import { ExtendedDMMFFieldImportMatch } from './13_extendedDMMFFieldImportMatch';
import { writeImportStatementOptions } from '../fileWriter';

export interface ExtendedDMMFField extends DMMF.Field, FormattedNames {
/**
Expand Down Expand Up @@ -118,7 +119,7 @@ export interface ExtendedDMMFField extends DMMF.Field, FormattedNames {
* Contains the imprt string that should be used for a field's refine function or similar.
* @description `import { myFunction } from "../../../../utils/myFunction";`
*/
readonly imports: Set<string>;
readonly imports: writeImportStatementOptions[];
}

/**
Expand Down
54 changes: 38 additions & 16 deletions packages/generator/src/classes/extendedDMMFInputType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
PRISMA_FUNCTION_TYPES_WITH_VALIDATORS_WHERE_UNIQUE,
} from '../constants/regex';
import { GeneratorConfig } from '../schemas';
import { writeImportStatementOptions } from './fileWriter';

const SPLIT_NAME_REGEX =
/Unchecked|Create|Update|CreateMany|CreateManyAndReturn|UpdateMany|UpdateManyAndReturn|Upsert|Where|WhereUnique|OrderBy|ScalarWhere|Aggregate|GroupBy/g;
Expand All @@ -36,7 +37,7 @@ export class ExtendedDMMFInputType
readonly isBytesField: boolean;
readonly isDecimalField: boolean;
readonly omitFields: string[] = [];
readonly imports: Set<string>;
readonly imports: writeImportStatementOptions[];
/** @deprecated */
readonly isWhereUniqueInput?: boolean;
readonly extendedWhereUniqueFields?: ExtendedDMMFSchemaArg[][];
Expand Down Expand Up @@ -189,40 +190,61 @@ export class ExtendedDMMFInputType
decimalJSInstalled,
} = this.generatorConfig;

const prismaImports = [];
const fieldImports: writeImportStatementOptions[] = [];
const prismaImports: writeImportStatementOptions[] = [];

// If the field is a decimal field, we need to import the
// Decimal class in order to use `z.instanceof`
if (this.isDecimalField) {
if (isPrismaClientGenerator) {
prismaImports.push(
`import { Decimal as PrismaDecimal } from '${prismaLibraryPath}';`,
);
// If isPrismaClientGenerator, import Prisma.Decimal as PrismaDecimal
// We also need to import { type Prisma } below
prismaImports.push({
name: 'Decimal',
as: 'PrismaDecimal',
path: prismaLibraryPath,
});
} else {
prismaImports.push(`import { Prisma } from '${prismaClientPath}';`);
// If not isPrismaClientGenerator, import whole Prisma client
prismaImports.push({
name: 'Prisma',
path: prismaClientPath,
});
}
if (decimalJSInstalled) {
// If decimal.js is installed, import Decimal from decimal.js
fieldImports.push({
name: 'Decimal',
path: 'decimal.js',
isDefault: true,
});
}
}

if (!this.isDecimalField || isPrismaClientGenerator) {
prismaImports.push(`import type { Prisma } from '${prismaClientPath}';`);
prismaImports.push({
name: 'Prisma',
path: prismaClientPath,
isTypeOnly: true,
});
}

const decimalJSImport =
decimalJSInstalled && this.isDecimalField
? `import Decimal from 'decimal.js';`
: '';
const zodImport = "import { z } from 'zod';";
const zodImport: writeImportStatementOptions = {
name: 'z',
path: 'zod',
};

const fieldImports = [
fieldImports.push(
...prismaImports,
decimalJSImport,
zodImport,
...this.fields.map((field) => field.getImports(this.name)).flat(),
];
);

if (this._fieldIsPrismaFunctionType() && this.linkedModel?.fieldImports) {
fieldImports.push(...this.linkedModel.fieldImports);
}

return new Set(fieldImports);
return fieldImports;
}

private _getExtendedWhereUniqueFieldCombinations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ import { GeneratorConfig } from '../../schemas';
import { ExtendedDMMFModelValidatorPattern } from './04_extendedDMMFModelValidatorPattern';
import { transformImportStringToList } from '../../utils/transformImportStringToList';
import { validateImportStatement } from '../../utils/validateImportStatements';
import { writeImportStatementOptions } from '../fileWriter';
import { transformImportListToOptions } from '../../utils/transformImportListToOptions';

/////////////////////////////////////////////////
// CLASS
/////////////////////////////////////////////////

export class ExtendedDMMFModelImportStatement extends ExtendedDMMFModelValidatorPattern {
protected _importStatements?: string[];
protected _automaticImports?: string[];
readonly modelImports: Set<string>;
readonly fieldImports: Set<string>;
readonly imports: Set<string>;
protected _automaticImports?: writeImportStatementOptions[];
readonly modelImports: writeImportStatementOptions[];
readonly fieldImports: writeImportStatementOptions[];
readonly imports: writeImportStatementOptions[];

constructor(generatorConfig: GeneratorConfig, model: DMMF.Model) {
super(generatorConfig, model);
Expand Down Expand Up @@ -45,7 +47,7 @@ export class ExtendedDMMFModelImportStatement extends ExtendedDMMFModelValidator
* @returns array of import statements that are automatically added to the model's imports.
*/
private _getAutomaticImports() {
const statements: string[] = [];
const statements: writeImportStatementOptions[] = [];

const {
inputTypePath,
Expand All @@ -55,66 +57,73 @@ export class ExtendedDMMFModelImportStatement extends ExtendedDMMFModelValidator
} = this.generatorConfig;

if (this.fields.some((field) => field.isJsonType)) {
statements.push(
`import { JsonValueSchema } from '../${inputTypePath}/JsonValueSchema'`,
);
statements.push({
name: 'JsonValueSchema',
path: `../${inputTypePath}/JsonValueSchema`,
});
}

if (this.hasDecimalFields) {
if (isPrismaClientGenerator) {
statements.push(
`import { Decimal as PrismaDecimal } from '${prismaLibraryPath}';`,
);
statements.push({
name: 'Decimal',
as: 'PrismaDecimal',
path: prismaLibraryPath,
});
} else {
statements.push(`import { Prisma } from '${prismaClientPath}'`);
statements.push({
name: 'Prisma',
path: prismaClientPath,
});
}
}

this.enumFields.forEach((field) => {
statements.push(
`import { ${field.type}Schema } from '../${inputTypePath}/${field.type}Schema'`,
);
statements.push({
name: `${field.type}Schema`,
path: `../${inputTypePath}/${field.type}Schema`,
});
});

return statements;
}

private _getModelImports() {
if (!this._importStatements) return new Set<string>();
if (!this._importStatements) return [];

const importList = this._importStatements
.map((importStatement) => {
return transformImportStringToList(importStatement);
})
.flat();

return new Set(importList);
return transformImportListToOptions(importList);
}

private _getImports() {
const imports = new Set<string>();
const imports: writeImportStatementOptions[] = [];

if (this._automaticImports) {
this._automaticImports.forEach((statement) => imports.add(statement));
this._automaticImports.forEach((statement) => imports.push(statement));
}

if (this.modelImports) {
this.modelImports.forEach((statement) => imports.add(statement));
this.modelImports.forEach((statement) => imports.push(statement));
}

if (this.fieldImports) {
this.fieldImports.forEach((statement) => imports.add(statement));
this.fieldImports.forEach((statement) => imports.push(statement));
}

return imports;
}

private _getFieldImports() {
const imports = new Set<string>();
const imports: writeImportStatementOptions[] = [];

this.fields.forEach((field) => {
if (field.imports) {
field.imports.forEach((statement) => imports.add(statement));
field.imports.forEach((statement) => imports.push(statement));
}
});

Expand Down
7 changes: 4 additions & 3 deletions packages/generator/src/classes/extendedDMMFModel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FormattedNames } from '../formattedNames';
import { ExtendedDMMFModelFormatingHelpers } from './08_extendedDMMFModelFormatingHelpers';
import { ExtendedDMMFField } from '../extendedDMMFField';
import { GeneratorConfig } from '../../schemas/generatorConfigSchema';
import { writeImportStatementOptions } from '../fileWriter';

/////////////////////////////////////////////////
// TYPES INTERFACE
Expand Down Expand Up @@ -113,19 +114,19 @@ export interface ExtendedDMMFModel extends DMMF.Model, FormattedNames {
* Set of import statements that are used in the model and need to be added to the generated file.
* Contains model, field and automatic imports like `import { InputJsonValue } from "../inputTypes/InputJsonValue";` for json fields.
*/
readonly imports: Set<string>;
readonly imports: writeImportStatementOptions[];

/**
* Set of import statements that are used in the model and need to be added to the generated file.
* Contains only the model imports from the model's documentation.
*/
readonly modelImports: Set<string>;
readonly modelImports: writeImportStatementOptions[];

/**
* Set of import statements that are used in the model and need to be added to the generated file.
* Contains only the field level imports from the model's documentation.
*/
readonly fieldImports: Set<string>;
readonly fieldImports: writeImportStatementOptions[];

/**
* Documentation string provided via rich comments without the `@zod` directives.
Expand Down
Loading