prisma-generator-nestjs-graphql-crud

2.5.5 • Public • Published

prisma-generator-nestjs-graphql-crud

This prisma generator will create all the @nestjs/graphql classes you'll need for basic CRUD operations; based on your prisma schema. It includes dataloader to prevent the infamous n+1 problem in graphql.

npm i prisma-generator-nestjs-graphql-crud

Getting Started

  1. Inside your prisma schema add the following:
generator nestJsGraphQlCrud {
  provider = "prisma-generator-nestjs-graphql-crud"
}

Options:

Feature Description Default Example
excludes prisma model names to exclude from generator excludes = ["Ignore"]
includeMutations include mutation resolvers includeMutations = "true"
output cwd relative path for the output node_modules/@generated/graphql output = "./example/src"
  1. Configure your Graphql Service In NestJs

The generated code relies on the context object for graphql to contain a reference to the prisma client. See the use of useFactory in the GraphQLModule below.

PrismaModule and PrismaService are generated; if you want your own custom implementation, use this doc as a guide.

* generated code is compatible with @nestjs/mercurius, @nestjs/apollo and @graphql-yoga/nestjs

import {
  DataLoaderService,
  PrismaModule,
  prismaProviders,
  PrismaService
} from '@generated/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';

@Module({
  imports: [
    GraphQLModule.forRootAsync<ApolloDriverConfig>({
      driver: ApolloDriver,
      inject: [DataLoaderService, PrismaService],
      useFactory: (loaders: DataLoaderService, prisma: PrismaService) => ({
        autoSchemaFile: 'schema.gql',
        context: (req: FastifyRequest, res: FastifyReply) => {
          return {
            loaders: loaders.create(),
            prisma,
            req,
            res
          };
        },
        graphiql: true
      })
    }),
    PrismaModule.forRoot({
      isGlobal: true
    })
  ],
  providers: [...prismaProviders]
})
export class AppModule {
}

Prisma Features

Feature Available Notes
create
createMany
delete
deleteMany
findUnique by primary key or composite keys
findMany pagination included (skip/take only for now)
filters gt,gte,lt,lte,notIn,in,not, etc. (DateTime, Int, String supported)
orderBy
update
updateMany

The following are the various filters and generated resolvers. Note the table name is Upper-CamelCased; e.g. user_session would become UserSession.


Resolvers

All the following are based on the example project found here.


create

Create a new entity. Here's an example:

mutation {
    createTodo(title: "Next Todo", userId: 1) {
        id
        title
        userId
    }
}

This would return the following:

{
  "data": {
    "createTodo": {
      "id": 6,
      "title": "Next Todo",
      "userId": 1
    }
  }
}

createMany

Create multiple new entities. Here's an example:

mutation {
    createManyTodo([{"title": "Another Todo", "userId": 1}, {"title": "Final Todo", "userId": 2}]) {
        id
        title
        userId
    }
}

This would return the following:

{
  "data": {
    "createManyTodo": [
      {
        "id": 7,
        "title": "Another Todo",
        "userId": 1
      },
      {
        "id": 8,
        "title": "Final Todo",
        "userId": 2
      }
    ]
  }
}

delete

Delete an entity. Here's an example:

mutation {
    deleteTodo(id: 1) {
        id
        title
        userId
    }
}

This would return the following:

{
  "data": {
    "deleteTodo": {
      "id": 1,
      "title": "First Todo",
      "userId": 1
    }
  }
}

deleteMany

Delete multiple entities. Here's an example:

mutation {
    deleteManyTodo(userId: 1) {
        id
        title
        userId
    }
}

This returns the list of deleted todos:

{
  "data": {
    "deleteManyTodo": [
      {
        "id": 1,
        "title": "First Todo",
        "userId": 1
      },
      {
        "id": 2,
        "title": "Second Todo",
        "userId": 1
      }
    ]
  }
}

findFirst

Find first should be used when you want to query and find a single row without using any of the unique keys for filters; this means that any filters you use for a findMany can be used here. Here's an example:

query {
    findFirstTodo(title: "That Todo") {
        id
        title
        userId
    }
}

This would return the following:

{
  "data": {
    "findFirstTodo": {
      "id": 1,
      "title": "That Todo",
      "userId": 1
    }
  }
}

findMany

Find many is used to return either filtered or unfiltered rows from a table, and can optionally provide skip (offset) and take (limit) as parameters to control pagination. Here's an example:

query {
    findManyTodo(skip: 0, take: 5) {
        id
        title
        userId
    }
}

This would return the following:

{
  "data": {
    "findManyTodo": [
      {
        "id": 1,
        "title": "Todo 1",
        "userId": 1
      },
      {
        "id": 2,
        "title": "Todo 2",
        "userId": 1
      },
      {
        "id": 3,
        "title": "Todo 3",
        "userId": 1
      },
      {
        "id": 4,
        "title": "Todo 4",
        "userId": 2
      },
      {
        "id": 5,
        "title": "Todo 5",
        "userId": 2
      }
    ]
  }
}

findUnique

Find unique should be used when you want to query against a primary key or composite key. Here's an example:

query {
    findUniqueTodo(id: 1) {
        id
        title
        userId
    }
}

This would return the following:

{
  "data": {
    "findUniqueTodo": {
      "id": 1,
      "title": "Todo 1",
      "userId": 1
    }
  }
}

update

Updates a single entity. Here's an example:

mutation {
    updateTodo(data: {"title": "First Todo", "userId": 2}, where: {"id": 1}) {
        id
        title
        userId
    }
}

This would return the following:

{
  "data": {
    "updateTodo": {
      "id": 1,
      "title": "First Todo",
      "userId": 2
    }
  }
}

updateMany

Updates a single entity. Here's an example:

mutation {
    updateManyTodo(data: {"userId": 2}, where: {"userId": 1}) {
        id
        title
        userId
    }
}

This would return the following:

{
  "data": {
    "updateManyTodo": [
      {
        "id": 1,
        "title": "First Todo",
        "userId": 2
      },
      {
        "id": 2,
        "title": "Second Todo",
        "userId": 2
      }
    ]
  }
}

Filters

The following filters are available are:


DateFilter

Type Supported
findFirst
findMany
findUnique

Options

Type Description Example
gt where the column value is greater than the given {value} gt: "2022-01-10"
gte where the column value is greater than or equal to the given {value} gte:"2022-01-10"
lt where the column value is less than the given {value} lt: "2022-01-10"
lte where the column value is less than or equal to the given {value} lte:"2022-01-10"
not where the column value is not equal to the given {value} not: "2022-01-10"

Example:

query {
    findManyTodo(createdAt: { gt: "2022-01-10", lt: "2023-01-10" }) {
        id
        title
    }
}

NumberFilter

Type Supported
findFirst
findMany
findUnique

Options

Type Description Example
gt where the column value is greater than the given {value} gt: 1
gte where the column value is greater than or equal to the given {value} gte: 1
lt where the column value is less than the given {value} lt: 1
lte where the column value is less than or equal to the given {value} lte: 1
not where the column value is not equal to the given {value} not: 1

Example:

query {
    findManyTodo(userId: { gt: 1, lt: 2 }) {
        id
        title
        userId
    }
}

OrderBy

Type Supported
findFirst
findMany
findUnique

Example:

query {
    findManyTodo(skip: 0, take: 5, orderBy: {title: "desc"}) {
        id
        title
    }
}

StringFilter

Type Supported
findFirst
findMany
findUnique

Options

Type Description Example
contains where the column contains the given {value} contains: "Robert"
endsWith where the column value ends with the {value} endsWith: "ert"
in where the column contains a value matching the array of {values}s in: ["Robert", "Rob"]
not where the column value does not not equal the {value} not: "Matt"
notIn where the column does not contain a value matching the array of {values}s notIn: ["robb", "Robb"]
startsWith where the column value starts with the {value} startsWith: "Rob"

*all are case-insensitive

Example:

query {
    findManyTodo(title: { contains: "First" }) {
        id
        title
    }
}

Skip (offset)

Type Supported
findFirst
findMany
findUnique

Example:

query {
    findManyTodo(skip: 0) {
        id
        title
    }
}

Take (limit)

Type Supported
findFirst
findMany
findUnique

Example:

query {
    findManyTodo(take: 10) {
        id
        title
    }
}

Graphql Features

Feature Available Notes
FieldResolvers both up and down relationships supported
Mutations
Query
Resolvers

Example

See a generated example here; note, when the output is in a node_modules directory, it will automatically transpile cjs and mjs versions.


Road Map

  • authentication guard integration
  • cursor-based pagination
  • expand gt, gte, lt, lte, notIn, in, not "where" filtering to types other than DateTime, Int, and String

TODO

  • fix orderBy ArgTypes casting to Prisma.{Model}FindManyArgs['orderBy']
  • fix data ArgTypes casting to Prisma.{Model}CreateArgs['data']
  • fix where ArgTypes casting to Prisma.{Model}FindManyArgs['where']

Package Sidebar

Install

npm i prisma-generator-nestjs-graphql-crud

Weekly Downloads

32

Version

2.5.5

License

MIT

Unpacked Size

262 kB

Total Files

45

Last publish

Collaborators

  • dayne.mentier