NestJS Logo

CRUD generator (TypeScript only)

Over the lifespan of a project, building new features often means adding new resources to the application. Each new resource typically requires the same set of repetitive operations.

Introduction#

Consider a real-world scenario in which you need to expose CRUD endpoints for two entities, User and Product. Following best practices, you would have to perform several operations for each entity:

  • Generate a module (nest g mo) to keep code organized and establish clear boundaries (grouping related components)
  • Generate a controller (nest g co) to define CRUD routes (or queries/mutations for GraphQL applications)
  • Generate a service (nest g s) to implement and isolate business logic
  • Generate an entity class/interface to represent the resource data shape
  • Generate Data Transfer Objects (or inputs for GraphQL applications) to define how the data will be sent over the network

To speed up this repetitive process, the Nest CLI provides a generator (schematic) that generates all of this boilerplate code automatically.

Note The schematic supports generating HTTP controllers, Microservice controllers, GraphQL resolvers (both code first and schema first), and WebSocket Gateways.

Generating a new resource#

To create a new resource, run the following command in the root directory of your project:


$ nest g resource

The nest g resource command generates not only the NestJS building blocks (module, service, and controller classes), but also an entity class, DTO classes, and the test (.spec) files.

Here's the generated controller file (for a REST API):


@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
    return this.usersService.update(+id, updateUserDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.usersService.remove(+id);
  }
}

The command also creates placeholders for all the CRUD endpoints: routes for REST APIs, queries and mutations for GraphQL, and message handlers for both microservices and WebSocket gateways.

Note Generated service classes are not tied to any specific ORM (or data source), which makes the generator generic enough to meet the needs of any project. By default, all methods contain placeholders that you can populate with the data sources specific to your project.

Likewise, to generate resolvers for a GraphQL application, select GraphQL (code first) (or GraphQL (schema first)) as your transport layer.

In this case, Nest generates a resolver class instead of a REST API controller:


$ nest g resource users

> ? What transport layer do you use? GraphQL (code first)
> ? Would you like to generate CRUD entry points? Yes
> CREATE src/users/users.module.ts (224 bytes)
> CREATE src/users/users.resolver.spec.ts (525 bytes)
> CREATE src/users/users.resolver.ts (1109 bytes)
> CREATE src/users/users.service.spec.ts (453 bytes)
> CREATE src/users/users.service.ts (625 bytes)
> CREATE src/users/dto/create-user.input.ts (195 bytes)
> CREATE src/users/dto/update-user.input.ts (281 bytes)
> CREATE src/users/entities/user.entity.ts (187 bytes)
> UPDATE src/app.module.ts (312 bytes)
Hint To skip generating test files, pass the --no-spec flag, as follows: nest g resource users --no-spec.

As shown below, the command not only creates all the boilerplate mutations and queries, but also wires everything together, using the UsersService, the User entity, and the DTOs.


import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql';
import { UsersService } from './users.service.js';
import { User } from './entities/user.entity.js';
import { CreateUserInput } from './dto/create-user.input.js';
import { UpdateUserInput } from './dto/update-user.input.js';

@Resolver(() => User)
export class UsersResolver {
  constructor(private readonly usersService: UsersService) {}

  @Mutation(() => User)
  createUser(@Args('createUserInput') createUserInput: CreateUserInput) {
    return this.usersService.create(createUserInput);
  }

  @Query(() => [User], { name: 'users' })
  findAll() {
    return this.usersService.findAll();
  }

  @Query(() => User, { name: 'user' })
  findOne(@Args('id', { type: () => Int }) id: number) {
    return this.usersService.findOne(id);
  }

  @Mutation(() => User)
  updateUser(@Args('updateUserInput') updateUserInput: UpdateUserInput) {
    return this.usersService.update(updateUserInput.id, updateUserInput);
  }

  @Mutation(() => User)
  removeUser(@Args('id', { type: () => Int }) id: number) {
    return this.usersService.remove(id);
  }
}
Edit on GitHub

Support us

Nest is an MIT-licensed open source project. It can grow thanks to the support of these awesome people. If you'd like to join them, please read more here.

Principal Sponsors

SerpApi LogoTrilon LogoMojam Logo

Sponsors / Partners

Become a sponsor