Quick start

Install

pnpm add -D prisma-generator-nestjs class-validator class-transformer

Add Prisma schema generator

generator nestjsDto {
  provider = "prisma-generator-nestjs"
  output   = "../src/lib/model"
}

What is it?

Generates ConnectDTO, CreateDTO, UpdateDTO, and Entity classes for models in your Prisma Schema. This is useful if you want to leverage OpenAPI in your NestJS application - but also helps with GraphQL resources as well). NestJS Swagger requires input parameters in controllers to be described through classes because it leverages TypeScript's emitted metadata and Reflection to generate models/components for the OpenAPI spec. It does the same for response models/components on your controller methods.

These classes can also be used with the built-in ValidationPipe and Serialization.

Prisma Schema Decorators

Prisma schema decorators allow you to create dto and entities. You can use them with /// comments or by configuring them directly in the Prisma schema file. This guide focuses on class-validator decorators and additional Prisma decorators that can be used for generating DTOs and entities.

Class-validator Decorators

Class-validator decorators are also available for use in Prisma schemas. For a comprehensive list of class-validator decorators, refer to the official class-validator documentation.

Additional Prisma Decorators

  • @Ignore: Ignores the decorated property in all generated DTOs and can be used on both models and fields.

  • @NoAdd: Ignores the decorated property in the generated create DTO.

  • @NoSet: Ignores the decorated property in the generated update DTO.

  • @OptAdd: Makes the decorated property optional in the generated create DTO.

  • @OptSet: Makes the decorated property optional in the generated update DTO.

  • @NoEntity: Excludes the decorated field from the generated entity.

  • @RReq: Makes the decorated relation required in the all generated DTO.

  • @RAddOnAdd: Makes the additional class for create when create

  • @RLnOnAdd: Makes the additional class for connect when create

  • @RAddOnSet: Makes the additional class for create when update

  • @RLnOnSet: Makes the additional class for connect when update

  • Add @RAddOn and @RLnOn for connect or create

All additional Prisma decorators can be used on fields, and the @Ignore decorator can be used on both models and fields.

Configuring Decorators

Decorators can be configured using the configuration file or Prisma schema config or by adding them directly in the schema.

Using /// Comments

model User {
  id    Int    @id @default(autoincrement())
  /// @NoSet @IsEmail()
  email String
}

/// @Ignore
model Ignored {
  id Int @id @default(autoincrement())
}

Prisma options defaults:

generator nestjsDto {
  // Prisma global
  provider = "prisma-generator-nestjs"
  output   = "../src/model"

  // File config path
  fileConfig = "nest-dto.js"

  // Dto Prefix 
  connectDtoPrefix = "Connect"
  createDtoPrefix  = "Create"
  updateDtoPrefix  = "Update"
  // Suffix
  dtoSuffix        = "Dto"
  entityPrefix     = ""
  entitySuffix     = ""

  // Style file naming
  fileNamingStyle = "kebab"
  // Transform Prisma.Decimal to number
  decimalAsNumber = "false"
  // Import path for prisma
  importPath      = "@prisma/client"

  // Class validator auto generator
  // @IsOptional() when not is required field
  cvIsOptional   = "true"
  // @IsDateString() DataTime types
  cvIsDateString = "true"

  // Use prettier to format your file
  prettier = "true"
  // Only "openapi" mode
  mode     = "openapi"

  // deprecated: remove in favor of one structure
  outputToNestJsResourceStructure = "true"
  exportRelationModifierClasses   = "true"
}

Config file

In the configuration file, you can define a list of customization rules for your models and their fields. Each rule consists of an optional regular expression to target specific Prisma model names, and a list of field customizations. Each field customization includes a regular expression to match desired field names within the targeted model, and decorators to be applied to the matched field.

The priority order for applying decorators is determined by the order in which they appear in the list. The first match found or the one defined in the Prisma schema will be used.

By leveraging this configuration structure, you can create a more flexible and powerful configuration for your models and fields, applying decorators as needed for custom functionality and validation.

const { defConfig } = require('prisma-generator-nestjs');

module.exports = defConfig({
  // Priority by first schema and order, take the first
  regulars: [
    {
      models: /^User$/,
      fields: [{ regex: /password$/, decorators: '@Length(16)' }],
    },
    {
      fields: [
        { regex: /password$/, decorators: '@Length(8)' },
        { regex: /mail$/, decorators: '@IsEmail() @Length(200)' },
      ],
    },
  ],
});

Extension

For each of the __extension.entity.ts files, it is important to note that these files are generated only once and will never be overwritten. This ensures that any customizations or modifications made to these files are preserved throughout the development process.

To extend the functionality of your models, you can make use of Mapped Types provided by NestJS. Mapped Types are utility functions that allow you to create new types based on existing ones, simplifying the process of creating and managing related types within your application.

The main Mapped Types provided by NestJS include:

  1. PartialType: Generates a new type by making all properties of the original type optional. This is particularly useful when handling partial updates or creating DTOs (Data Transfer Objects) for update operations.

  2. PickType: Generates a new type by selecting a subset of properties from the original type. This can be useful for creating DTOs that require only specific properties from a larger model.

  3. OmitType: Generates a new type by excluding a set of properties from the original type. This is helpful when creating DTOs that exclude certain properties from a model, such as sensitive information or internal fields.

  4. IntersectionType: Generates a new type by combining two existing types, allowing you to create composite DTOs that include properties from multiple sources.

By utilizing these Mapped Types, you can simplify the creation and management of related types in your application, improving the overall developer experience. For more information and examples, refer to the official NestJS Mapped Types documentation.

NestJS respects and integrates with the class-validator library, allowing you to leverage its powerful validation capabilities in your application. With class-validator, you can easily add validation rules to your DTOs (Data Transfer Objects) by using decorators on the properties of your classes.

When using Mapped Types provided by NestJS, such as PartialType, PickType, OmitType, and IntersectionType, the validation rules defined by class-validator will be preserved and applied to the resulting types.

For more information on how NestJS works with class-validator and examples of using validation decorators, refer to the official NestJS Validation documentation.

ConnectDTO

This kind of DTO represents the structure of input-data to expect from 'outside' (e.g. REST API consumer) when attempting to connect to a model through a relation field.

A Models ConnectDTO class is composed of a unique'd list of isId and isUnique scalar fields. If the ConnectDTO class has exactly one property, the property is marked as required. If there are more than one property, all properties are optional (since setting a single one of them is already sufficient for a unique query) - you must however specify at least one property.

ConnectDTOs are used for relation fields in CreateDTOs and UpdateDTOs.

CreateDTO

annotations that generate corresponding input properties on CreateDTO and UpdateDTO (optional or required - depending on the nature of the relation).

When generating a Models CreateDTO class, field that meet any of the following conditions are omitted (order matters):

  • isReadOnly OR is annotated with @NoSet (Note: this apparently includes relation scalar fields)
  • field represents a relation (field.kind === 'object') and is not annotated with @RAddOnAdd or @RLnOnAdd
  • field is a relation scalar
  • field is not annotated with @OptAdd AND
    • isId && hasDefaultValue (id fields are not supposed to be provided by the user)
    • isUpdatedAt (Prisma will inject value)
    • isRequired && hasDefaultValue (for schema-required fields that fallback to a default value when empty. Think: createdAt timestamps with @default(now()) (see now()))

UpdateDTO

When generating a Models UpdateDTO class, field that meet any of the following conditions are omitted (order matters):

  • field is annotated with @OptSet
  • isReadOnly OR is annotated with @NoSet (Note: this apparently includes relation scalar fields)
  • isId (id fields are not supposed to be updated by the user)
  • field represents a relation (field.kind === 'object') and is not annotated with @RAddOnSet or @RLnOnSet
  • field is a relation scalar
  • field is not annotated with @OptSet AND
    • isId (id fields are not supposed to be updated by the user)
    • isUpdatedAt (Prisma will inject value)
    • isRequired && hasDefaultValue (for schema-required fields that fallback to a default value when empty. Think: createdAt timestamps with @default(now()) (see now()))

Refactor roadmap and priority

  • Fix unused model fields (ids, uniques,..) when generate
  • Refactor generated classes with composition
  • Add extension.{entity,dto}.ts files for implement complex structures
  • Add per model index and default reexport
  • Refactor decimal.js to number and use hard cast from prisma client return type
  • Use @babel for parse comments like "COMMENT class {}" and extract decorator from ast
  • Add Documentation and clean README.md
  • Add support for class-validator by comment, by name, (in future by @db annotations)
  • Add config regulars: put decorators in fields by regex of its name and its parent
  • Simplify comment annotations and remove boilerplate
  • Clean Code and simplify structure
  • Prettify and complete documentation
  • ~100% coverage