Skip to main content
The CrudOptions interface defines all available configuration options for the @Crud() decorator.

Interface definition

interface CrudOptions {
  model: ModelOptions;
  dto?: DtoOptions;
  serialize?: SerializeOptions;
  query?: QueryOptions;
  routes?: RoutesOptions;
  params?: ParamsOptions;
  validation?: ValidationPipeOptions | false;
  routesFactory?: typeof CrudRoutesFactory;
}

Model options

model
ModelOptions
required
Defines the entity model for this controller.
model.type
any
required
The entity class that this controller manages.
model: {
  type: User,
}

DTO options

dto
DtoOptions
Custom Data Transfer Objects for request validation.
dto.create
any
DTO class for create operations (POST).
dto.update
any
DTO class for update operations (PATCH).
dto.replace
any
DTO class for replace operations (PUT).

Example

import { CreateUserDto, UpdateUserDto, ReplaceUserDto } from './dto';

@Crud({
  model: { type: User },
  dto: {
    create: CreateUserDto,
    update: UpdateUserDto,
    replace: ReplaceUserDto,
  },
})
When DTOs are not specified, the entity class is used with validation groups CRUD-CREATE and CRUD-UPDATE.

Serialize options

serialize
SerializeOptions
Response transformation configuration for each route type.
serialize.getMany
Type<any> | false
Response DTO for the get many route.
serialize.get
Type<any> | false
Response DTO for the get one route.
serialize.create
Type<any> | false
Response DTO for the create one route.
serialize.createMany
Type<any> | false
Response DTO for the create many route.
serialize.update
Type<any> | false
Response DTO for the update route.
serialize.replace
Type<any> | false
Response DTO for the replace route.
serialize.delete
Type<any> | false
Response DTO for the delete route.
serialize.recover
Type<any> | false
Response DTO for the recover route.

Example

import { GetCompanyResponseDto } from './responses';

@Crud({
  model: { type: Company },
  serialize: {
    get: GetCompanyResponseDto,
    getMany: GetCompanyResponseDto,
  },
})
GetCompanyResponseDto
import { Exclude } from 'class-transformer';

export class GetCompanyResponseDto {
  id: number;
  name: string;
  domain: string;
  description: string;
  
  @Exclude()
  createdAt: Date;
  
  @Exclude()
  updatedAt: Date;
}

Query options

query
QueryOptions
Configuration for query behavior, filtering, pagination, and joins.

Allow and exclude fields

query.allow
string[]
Whitelist of fields that can be used in queries (filter, sort, select).
query.exclude
string[]
Blacklist of fields that cannot be used in queries.
query.persist
string[]
Fields that are always returned in responses, even if not requested.

Filtering

query.filter
QueryFilterOption
Server-side filters that are always applied to queries.
query: {
  filter: {
    isActive: true,
  },
}

Sorting

query.sort
QuerySort[]
Default sort order for queries.
query: {
  sort: [
    { field: 'createdAt', order: 'DESC' },
  ],
}

Pagination

query.limit
number
Default number of entities to return per page.
query.maxLimit
number
Maximum number of entities that can be requested per page.
query.alwaysPaginate
boolean
When true, all responses are paginated. When false, only paginate when limit is specified.

Soft delete

query.softDelete
boolean
Enable soft delete support. Deleted entities are filtered out by default.
query: {
  softDelete: true,
}

Caching

query.cache
number | false
Cache duration in milliseconds, or false to disable caching.

Join options

query.join
JoinOptions
Configuration for entity relations.
interface JoinOptions {
  [relationName: string]: JoinOption;
}

interface JoinOption {
  alias?: string;         // Query alias for this relation
  allow?: string[];       // Allowed fields in queries
  eager?: boolean;        // Always load this relation
  exclude?: string[];     // Excluded fields
  persist?: string[];     // Always return these fields
  select?: false;         // Prevent selecting this relation
  required?: boolean;     // Use INNER JOIN instead of LEFT JOIN
}

Join example

@Crud({
  model: { type: User },
  query: {
    join: {
      company: {
        exclude: ['description'],
      },
      'company.projects': {
        alias: 'pr',
        exclude: ['description'],
      },
      profile: {
        eager: true,
        exclude: ['updatedAt'],
      },
    },
  },
})
  • Nested joins: Use dot notation like 'company.projects' to join through relations
  • Eager loading: Set eager: true to always include the relation
  • Field filtering: Use allow and exclude to control which relation fields can be queried
  • Custom aliases: Provide an alias for use in query parameters
  • Required joins: Set required: true for INNER JOIN behavior

Params options

params
ParamsOptions
Configuration for URL path parameters.
interface ParamsOptions {
  [paramName: string]: ParamOption;
}

interface ParamOption {
  field?: string;           // Entity field name
  type?: 'number' | 'string' | 'uuid';  // Parameter type
  primary?: boolean;        // Is this the primary key?
  disabled?: boolean;       // Disable this parameter
}

Example: Nested routes

@Crud({
  model: { type: User },
  params: {
    companyId: {
      field: 'companyId',
      type: 'number',
    },
    id: {
      field: 'id',
      type: 'number',
      primary: true,
    },
  },
})
@Controller('/companies/:companyId/users')
export class UsersController {
  constructor(public service: UsersService) {}
}
This creates routes like:
  • GET /companies/1/users
  • GET /companies/1/users/5
  • POST /companies/1/users

Example: UUID primary key

@Crud({
  model: { type: Device },
  params: {
    deviceKey: {
      field: 'deviceKey',
      type: 'uuid',
      primary: true,
    },
  },
})
@Controller('/devices')
export class DevicesController {}

Example: Disabled parameter

@Crud({
  model: { type: User },
  routes: {
    only: ['getOneBase', 'updateOneBase'],
  },
  params: {
    id: {
      primary: true,
      disabled: true,  // User ID comes from auth context
    },
  },
})
@Controller('me')
export class MeController {}

Validation options

validation
ValidationPipeOptions | false
NestJS ValidationPipe configuration, or false to disable validation.
@Crud({
  model: { type: User },
  validation: {
    whitelist: true,
    forbidNonWhitelisted: true,
    transform: true,
  },
})
Set to false to disable automatic validation:
@Crud({
  model: { type: User },
  validation: false,
})
See Validation for more details.

Routes factory

routesFactory
typeof CrudRoutesFactory
Custom routes factory class for advanced customization.
This is an advanced option for creating custom route generation logic. Most users should not need to modify this.

Complete example

import { Controller } from '@nestjs/common';
import { Crud } from '@nestjsx/crud';
import { User } from './user.entity';
import { UsersService } from './users.service';
import { CreateUserDto, UpdateUserDto } from './dto';
import { GetUserResponseDto } from './responses';

@Crud({
  model: {
    type: User,
  },
  dto: {
    create: CreateUserDto,
    update: UpdateUserDto,
  },
  serialize: {
    get: GetUserResponseDto,
    getMany: GetUserResponseDto,
  },
  query: {
    limit: 25,
    maxLimit: 100,
    alwaysPaginate: true,
    softDelete: true,
    sort: [
      { field: 'createdAt', order: 'DESC' },
    ],
    join: {
      company: {
        eager: true,
        exclude: ['description'],
      },
      profile: {
        eager: true,
      },
    },
  },
  params: {
    id: {
      field: 'id',
      type: 'number',
      primary: true,
    },
  },
  validation: {
    whitelist: true,
    forbidNonWhitelisted: true,
    transform: true,
  },
})
@Controller('users')
export class UsersController {
  constructor(public service: UsersService) {}
}