• Stars
    star
    274
  • Rank 150,274 (Top 3 %)
  • Language
    TypeScript
  • License
    Apache License 2.0
  • Created over 3 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Generates NestJS DTO classes from Prisma Schema

Project Status: Looking for new maintainers!

This project is looking for maintainers.

We are not using this package anymore ourselves, so we can no longer validate/review/test any incoming PRs anymore and ensure correct functionality.

If you are an experienced open source contributor and are interested in taking over maintenance, please open a GitHub issue and let's discuss how to proceed.

Prisma Generator NestJS DTO

Release License

  1. What is it?
  2. Usage
  3. Annotations
  4. Example
  5. Principles
  6. License

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.

Usage?

npm install --save-dev @vegardit/prisma-generator-nestjs-dto
generator nestjsDto {
  provider                        = "prisma-generator-nestjs-dto"
  output                          = "../src/generated/nestjs-dto"
  outputToNestJsResourceStructure = "false"
  exportRelationModifierClasses   = "true"
  reExport                        = "false"
  createDtoPrefix                 = "Create"
  updateDtoPrefix                 = "Update"
  dtoSuffix                       = "Dto"
  entityPrefix                    = ""
  entitySuffix                    = ""
  fileNamingStyle                 = "camel"
}

Parameters

All parameters are optional.

  • [output]: (default: "../src/generated/nestjs-dto") - output path relative to your schema.prisma file
  • [outputToNestJsResourceStructure]: (default: "false") - writes dtos and entities to subfolders aligned with NestJS CRUD generator. Resource module name is derived from lower-cased model name in schema.prisma
  • [exportRelationModifierClasses]: (default: "true") - Should extra classes generated for relationship field operations on DTOs be exported?
  • [reExport]: (default: false) - Should an index.ts be created for every folder?
  • [createDtoPrefix]: (default: "Create") - phrase to prefix every CreateDTO class with
  • [updateDtoPrefix]: (default: "Update") - phrase to prefix every UpdateDTO class with
  • [dtoSuffix]: (default: "Dto") - phrase to suffix every CreateDTO and UpdateDTO class with
  • [entityPrefix]: (default: "") - phrase to prefix every Entity class with
  • [entitySuffix]: (default: "") - phrase to suffix every Entity class with
  • [fileNamingStyle]: (default: "camel") - how to name generated files. Valid choices are "camel", "pascal", "kebab" and "snake".

Annotations

Annotations provide additional information to help this generator understand your intentions. They are applied as tripple slash comments to a field node in your Prisma Schema. You can apply multiple annotations to the same field.

model Post {
  /// @DtoCreateOptional
  /// @DtoUpdateHidden
  createdAt   DateTime @default(now())
}
  • @DtoReadOnly - omits field in CreateDTO and UpdateDTO
  • @DtoEntityHidden - omits field in Entity
  • @DtoCreateOptional - adds field optionally to CreateDTO - useful for fields that would otherwise be omitted (e.g. @id, @updatedAt)
  • @DtoUpdateOptional- adds field optionally to UpdateDTO - useful for fields that would otherwise be omitted (e.g. @id, @updatedAt)
  • @DtoRelationRequired - marks relation required in Entity although it's optional in PrismaSchema - useful when you don't want (SQL) ON DELETE CASCADE behavior - but your logical data schema sees this relation as required (Note: becomes obsolete once referentialActions are released and stable)
  • @DtoRelationCanCreateOnCreate - adds create option on a relation field in the generated CreateDTO - useful when you want to allow to create related model instances
  • @DtoRelationCanConnectOnCreate - adds connect option on a relation field in the generated CreateDTO - useful when you want/need to connect to an existing related instance
  • @DtoRelationCanCreateOnUpdate - adds create option on a relation field in the generated UpdateDTO - useful when you want to allow to create related model instances
  • @DtoRelationCanConnectOnUpdate - adds connect option on a relation field in the generated UpdateDTO - useful when you want/need to connect to an existing related instance

Example

Prisma Schema
generator nestjsDto {
provider = "prisma-generator-nestjs-dto"
output = "../src"
outputToNestJsResourceStructure = "true"
}

model Question {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
/// @DtoReadOnly
createdAt DateTime @default(now())
/// @DtoRelationRequired
createdBy User? @relation("CreatedQuestions", fields: [createdById], references: [id])
createdById String? @db.Uuid
updatedAt DateTime @updatedAt
/// @DtoRelationRequired
updatedBy User? @relation("UpdatedQuestions", fields: [updatedById], references: [id])
updatedById String? @db.Uuid

  /// @DtoRelationRequired
  /// @DtoRelationCanConnectOnCreate
  category   Category? @relation(fields: [categoryId], references: [id])
  categoryId String?   @db.Uuid

  /// @DtoCreateOptional
  /// @DtoRelationCanCreateOnCreate
  /// @DtoRelationCanConnectOnCreate
  /// @DtoRelationCanCreateOnUpdate
  /// @DtoRelationCanConnectOnUpdate
  tags Tag[]

  title     String
  content   String
  responses Response[]

}
Generated results
// src/question/dto/connect-question.dto.ts
export class ConnectQuestionDto {
  id: string;
}
// src/question/dto/create-question.dto.ts
import { ApiExtraModels } from '@nestjs/swagger';
import { ConnectCategoryDto } from '../../category/dto/connect-category.dto';
import { CreateTagDto } from '../../tag/dto/create-tag.dto';
import { ConnectTagDto } from '../../tag/dto/connect-tag.dto';

export class CreateQuestionCategoryRelationInputDto {
  connect: ConnectCategoryDto;
}
export class CreateQuestionTagsRelationInputDto {
  create?: CreateTagDto[];
  connect?: ConnectTagDto[];
}

@ApiExtraModels(
  ConnectCategoryDto,
  CreateQuestionCategoryRelationInputDto,
  CreateTagDto,
  ConnectTagDto,
  CreateQuestionTagsRelationInputDto,
)
export class CreateQuestionDto {
  category: CreateQuestionCategoryRelationInputDto;
  tags?: CreateQuestionTagsRelationInputDto;
  title: string;
  content: string;
}
// src/question/dto/update-question.dto.ts
import { ApiExtraModels } from '@nestjs/swagger';
import { CreateTagDto } from '../../tag/dto/create-tag.dto';
import { ConnectTagDto } from '../../tag/dto/connect-tag.dto';

export class UpdateQuestionTagsRelationInputDto {
  create?: CreateTagDto[];
  connect?: ConnectTagDto[];
}

@ApiExtraModels(CreateTagDto, ConnectTagDto, UpdateQuestionTagsRelationInputDto)
export class UpdateQuestionDto {
  tags?: UpdateQuestionTagsRelationInputDto;
  title?: string;
  content?: string;
}
// src/question/entities/question.entity.ts
import { User } from '../../user/entities/user.entity';
import { Category } from '../../category/entities/category.entity';
import { Tag } from '../../tag/entities/tag.entity';
import { Response } from '../../response/entities/response.entity';

export class Question {
  id: string;
  createdAt: Date;
  createdBy?: User;
  createdById: string;
  updatedAt: Date;
  updatedBy?: User;
  updatedById: string;
  category?: Category;
  categoryId: string;
  tags?: Tag[];
  title: string;
  content: string;
  responses?: Response[];
}

Principles

Generally we read field properties from the DMMF.Field information provided by @prisma/generator-helper. Since a few scenarios don't become quite clear from that, we also check for additional annotations (or decorators) in a field's documentation (that is anything provided as a tripple slash comments for that field in your prisma.schema).

Initially, we wanted DTO classes to implement Prisma.<ModelName><(Create|Update)>Input but that turned out to conflict with required relation fields.

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 from 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 properties, 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

This kind of DTO represents the structure of input-data to expect from 'outside' (e.g. REST API consumer) when attempting to create a new instance of a Model. Typically the requirements for database schema differ from what we want to allow users to do. As an example (and this is the opinion represented in this generator), we don't think that relation scalar fields should be exposed to users for create, update, or delete activities (btw. TypeScript types generated in PrismaClient exclude these fields as well). If however, your schema defines a required relation, creating an entity of that Model would become quite difficult without the relation data. In some cases you can derive information regarding related instances from context (e.g. HTTP path on the rest endpoint /api/post/:postid/comment to create a Comment with relation to a Post). For all other cases, we have the

  • @DtoRelationCanCreateOnCreate
  • @DtoRelationCanConnectOnCreate
  • @DtoRelationCanCreateOnUpdate
  • @DtoRelationCanConnectOnUpdate

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 @DtoReadOnly (Note: this apparently includes relation scalar fields)
  • field represents a relation (field.kind === 'object') and is not annotated with @DtoRelationCanCreateOnCreate or @DtoRelationCanConnectOnCreate
  • field is a relation scalar
  • field is not annotated with @DtoCreateOptional 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 @DtoUpdateOptional
  • isReadOnly OR is annotated with @DtoReadOnly (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 @DtoRelationCanCreateOnUpdate or @DtoRelationCanConnectOnUpdate
  • field is a relation scalar
  • field is not annotated with @DtoUpdateOptional 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()))

Entity

When generating a Models Entity class, only fields annotated with @DtoEntityHidden are omitted. All other fields are only manipulated regarding their isRequired and isNullable flags.

By default, every scalar field in an entity is required meaning it doesn't get the TypeScript "optional member flag" ? next to it's name. Fields that are marked as optional in PrismaSchema are treated as nullable - meaning their TypeScript type is a union of field.type and null (e.g. string | null).

Relation and relation scalar fields are treated differently. If you don't specifically include a relation in your query, those fields will not exist in the response.

  • every relation field is always optional (isRequired = false)
  • relations are nullable except when
    • the relation field is a one-to-many or many-to-many (i.e. list) type (would return empty array if no related records found)
    • the relation was originally flagged as required (isRequired = true)
    • the relation field is annotated with @DtoRelationRequired (do this when you mark a relation as optional in PrismaSchema because you don't want (SQL) ON DELETE CASCADE behavior - but your logical data schema sees this relation as required)

License

All files are released under the Apache License 2.0.

More Repositories

1

cygwin-portable-installer

Windows batch file to perform unattended installations of a portable Cygwin environment.
Batchfile
189
star
2

docker-gitea-act-runner

Docker image based on debian:stable-slim to run Gitea's act_runner as a Docker container
Shell
162
star
3

haxe-concurrent

A haxelib for basic platform-agnostic concurrency support
Haxe
82
star
4

haxe-strings

A haxelib for consistent cross-platform UTF-8 string manipulation.
Haxe
76
star
5

docker-traefik-logrotate

Lightweight Docker image to be used in conjunction with a dockerized Traefik instance to rotate Traefik's access logs.
Shell
49
star
6

bash-funk

bash-funk is a collection of useful commands for Bash 3.2 or higher.
Shell
46
star
7

dart-hotreloader

Automatic hot code reloader for Dart projects.
Dart
46
star
8

haxe-files

A haxelib for cross-platform filesystem operations.
Haxe
46
star
9

docker-graalvm-maven

Docker image to build native Linux binaries from Java Maven projects using GraalVM native-image feature.
Shell
28
star
10

docker-softhsm2-pkcs11-proxy

Docker image to run a virtual HSM (Hardware Security Module) network service based on SoftHSM2 and pkcs11-proxy.
Dockerfile
26
star
11

fast-apt-mirror.sh

fast-apt-mirror.sh is a self-contained Bash script that helps you to easily and quickly determine and configure a fast APT repository mirror on Debian, Ubuntu and Pop!_OS systems.
Shell
24
star
12

copycat

Copycat is a cross-platform one-way file synchronization tool for local file systems similar to robocopy on Windows.
Java
23
star
13

haxe-doctest

A haxelib inspired by Python's doctest command that generates unit tests based on assertions specified within the source code.
Haxe
23
star
14

await.sh

Self-contained POSIX shell scripts to await the availability of resources and services. Can be used as a workaround for Docker Swarm's missing depends_on support.
Shell
20
star
15

haxe-reusable-workflows

Reusable workflows for GitHub Actions to build/test Haxe code.
Haxe
10
star
16

scoop-portable

Self-contained Windows batch file that installs/loads a portable scoop (https://scoop.sh) environment.
Batchfile
7
star
17

docker-osslsigncode

Docker image for signing Windows binaries with Microsoft Authenticode using osslsigncode
Dockerfile
7
star
18

docker-meshcentral

Opinionated docker image to run a MeshCentral server to manage/access remote machines from within a browser.
Shell
7
star
19

activemq-artemis-dynatrace-plugin

Custom Dynatrace JMX plug-in for ActiveMQ Artemis broker processes.
Shell
6
star
20

docker-openldap

Opinionated docker image based on debian:bookworm-slim to run an OpenLDAP 2.5 server.
Shell
5
star
21

no-npe

A carefully curated repository of Eclipse External null Annotations (EEA) for enhanced static null analysis
Java
5
star
22

vegardit-maven-parent

Opinionated best practices Maven parent project.
Shell
5
star
23

haxe-sshclient

A haxelib that provides a basic SSH client which uses a pre-installed OpenSSH, Putty, or Kitty client under the hood.
Haxe
3
star
24

gha-setup-yq

gha-setup-yq is a GitHub action to install the yq command line YAML parser.
3
star
25

docker-wordpress-ext

Docker image extending the official Wordpress docker image with support for LDAP auth, OPcache and reverse HTTPS proxies.
Shell
2
star
26

docker-shared

Scripts and resources to be reused by docker image repos
Shell
2
star
27

depcheck-maven-plugin

Maven plugin to check for used unused direct and used indirect (transitive) dependencies.
Java
2
star
28

node-har-extract

extract http archives (HAR 1.2) to filesystem
JavaScript
2
star
29

docker-jenkins-ext

Docker image based on the official Jenkins docker image with support for pre-installing plug-ins and pre-configuring the Jenkins instance during container start via YAML files using the configuration-as-code plugin.
Shell
2
star
30

gha-setup-jq

gha-setup-jq is a GitHub action to install the jq command-line JSON parser/processor.
2
star
31

docker-jenkins-swarm-agent

Docker image to be used with the Jenkins Docker Swarm Plugin
Shell
2
star
32

docker-openjdk-ext

This docker image extends the official OpenJDK docker images by pre-installing curl, git, less, and docker client.
Shell
1
star
33

haxe-clink-externs

A haxelib with Lua externs for the Clink API to develop custom command line completions for Clink using Haxe.
Haxe
1
star
34

docker-gitea-ext

Docker image based on the official Gitea docker image with additional support for rendering AsciiDoc files.
Shell
1
star