Skip to main content

Overview

The TypeOrmCrudService is a powerful service class that extends the abstract CrudService and provides complete CRUD functionality for TypeORM entities. It handles complex querying, filtering, sorting, pagination, and relation management out of the box.

Basic Usage

The simplest way to use TypeOrmCrudService is to extend it in your service class:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';
import { User } from './user.entity';

@Injectable()
export class UsersService extends TypeOrmCrudService<User> {
  constructor(@InjectRepository(User) repo) {
    super(repo);
  }
}
The TypeOrmCrudService automatically inherits all CRUD methods and doesn’t require any additional configuration for basic operations.

Constructor

repo
Repository<T>
required
The TypeORM repository instance for your entity. This is typically injected using @InjectRepository(Entity).

Properties

Protected Properties

dbName
DataSourceOptions['type']
The database type (e.g., ‘postgres’, ‘mysql’, ‘mariadb’). Automatically detected from the repository connection.
entityColumns
string[]
An array of all column names in the entity. Populated during initialization.
entityPrimaryColumns
string[]
An array of primary key column names. Used for entity identification.
entityHasDeleteColumn
boolean
Indicates whether the entity has a soft delete column. Enables soft delete functionality.
entityColumnsHash
ObjectLiteral
A hash map of entity columns for quick lookup and SQL injection prevention.
entityRelationsHash
Map<string, IAllowedRelation>
A cache of entity relations metadata for efficient join operations.

Public Methods

getMany

Retrieves multiple entities based on the request parameters.
public async getMany(req: CrudRequest): Promise<GetManyDefaultResponse<T> | T[]>
req
CrudRequest
required
The CRUD request object containing parsed query parameters and options.
return
GetManyDefaultResponse<T> | T[]
Returns either a paginated response with metadata or a plain array of entities.
Example:
const result = await usersService.getMany(req);
// With pagination:
// { data: [...], count: 10, total: 100, page: 1, pageCount: 10 }
// Without pagination:
// [...]

getOne

Retrieves a single entity based on the request parameters.
public async getOne(req: CrudRequest): Promise<T>
req
CrudRequest
required
The CRUD request object with search criteria.
return
T
Returns the found entity or throws a NotFoundException.
Example:
const user = await usersService.getOne(req);

createOne

Creates a single entity.
public async createOne(req: CrudRequest, dto: T | Partial<T>): Promise<T>
req
CrudRequest
required
The CRUD request object with options.
dto
T | Partial<T>
required
The data transfer object containing the entity data to create.
return
T
Returns the created entity, either as a shallow object or fully populated based on the returnShallow option.
Example:
const newUser = await usersService.createOne(req, {
  email: 'user@example.com',
  name: 'John Doe'
});

createMany

Creates multiple entities in bulk.
public async createMany(req: CrudRequest, dto: CreateManyDto<T | Partial<T>>): Promise<T[]>
req
CrudRequest
required
The CRUD request object.
dto
CreateManyDto<T | Partial<T>>
required
An object with a bulk property containing an array of entities to create.
return
T[]
Returns an array of created entities.
Example:
const users = await usersService.createMany(req, {
  bulk: [
    { email: 'user1@example.com', name: 'User 1' },
    { email: 'user2@example.com', name: 'User 2' }
  ]
});
Bulk creates are processed in chunks of 50 entities for optimal performance.

updateOne

Updates a single entity.
public async updateOne(req: CrudRequest, dto: T | Partial<T>): Promise<T>
req
CrudRequest
required
The CRUD request object with entity identification.
dto
T | Partial<T>
required
Partial entity data to update.
return
T
Returns the updated entity.
Example:
const updatedUser = await usersService.updateOne(req, {
  name: 'Jane Doe'
});
By default, path parameters cannot be overridden. Set allowParamsOverride: true in route options to change this behavior.

replaceOne

Replaces an entire entity (PUT operation).
public async replaceOne(req: CrudRequest, dto: T | Partial<T>): Promise<T>
req
CrudRequest
required
The CRUD request object.
dto
T | Partial<T>
required
Complete entity data to replace.
return
T
Returns the replaced entity.
Example:
const replacedUser = await usersService.replaceOne(req, {
  email: 'user@example.com',
  name: 'John Smith',
  age: 30
});

deleteOne

Deletes a single entity.
public async deleteOne(req: CrudRequest): Promise<void | T>
req
CrudRequest
required
The CRUD request object with entity identification.
return
void | T
Returns the deleted entity if returnDeleted is true, otherwise returns void.
Example:
await usersService.deleteOne(req);
Supports both hard delete and soft delete. When soft delete is enabled, the entity is marked as deleted but not removed from the database.

recoverOne

Recovers a soft-deleted entity.
public async recoverOne(req: CrudRequest): Promise<T>
req
CrudRequest
required
The CRUD request object identifying the soft-deleted entity.
return
T
Returns the recovered entity.
Example:
const recoveredUser = await usersService.recoverOne(req);

createBuilder

Creates a TypeORM QueryBuilder with all request parameters applied.
public async createBuilder(
  parsed: ParsedRequestParams,
  options: CrudRequestOptions,
  many = true,
  withDeleted = false
): Promise<SelectQueryBuilder<T>>
parsed
ParsedRequestParams
required
Parsed request parameters including filters, joins, sort, and pagination.
options
CrudRequestOptions
required
CRUD request options from the controller configuration.
many
boolean
default:"true"
Whether to apply pagination and sorting (for getMany) or not (for getOne).
withDeleted
boolean
default:"false"
Whether to include soft-deleted entities in the query.
return
SelectQueryBuilder<T>
A fully configured TypeORM SelectQueryBuilder instance.
Example:
const builder = await this.createBuilder(req.parsed, req.options);
const users = await builder.getMany();

Advanced Features

SQL Injection Protection

The service includes built-in SQL injection protection using regular expressions:
protected sqlInjectionRegEx: RegExp[] = [
  /(%27)|(\')|(--)|(%)|(#)/gi,
  /((%3D)|(=))[^\n]*((%27)|(\')|(--)|(%)|(;))/gi,
  /w*((%27)|(\')|(\')|(%4F))((%72)|r|(%52))/gi,
  /((%27)|(\')|(\')|(\'))union/gi,
];
Field names and values are automatically checked for SQL injection patterns. Invalid queries throw BadRequestException.

Query Operators

The service supports a comprehensive set of query operators: Basic Operators:
  • $eq - Equal to
  • $ne - Not equal to
  • $gt - Greater than
  • $lt - Less than
  • $gte - Greater than or equal to
  • $lte - Less than or equal to
String Operators:
  • $cont - Contains
  • $excl - Excludes
  • $starts - Starts with
  • $ends - Ends with
Case-Insensitive Operators:
  • $eqL - Equal (case-insensitive)
  • $neL - Not equal (case-insensitive)
  • $contL - Contains (case-insensitive)
  • $startsL - Starts with (case-insensitive)
  • $endsL - Ends with (case-insensitive)
  • $exclL - Excludes (case-insensitive)
Array Operators:
  • $in - In array
  • $notin - Not in array
  • $inL - In array (case-insensitive)
  • $notinL - Not in array (case-insensitive)
Null Operators:
  • $isnull - Is null
  • $notnull - Is not null
Range Operators:
  • $between - Between two values

Database-Specific Optimizations

The service automatically detects the database type and applies appropriate optimizations:
const likeOperator = this.dbName === 'postgres' ? 'ILIKE' : 'LIKE';
For MySQL and MariaDB, backticks are used for identifiers, while PostgreSQL uses double quotes.

Repository Access

Direct access to TypeORM repository methods:
public get findOne(): Repository<T>['findOne']
public get find(): Repository<T>['find']
public get count(): Repository<T>['count']
Example:
// Access the underlying repository
const count = await usersService.count({ where: { isActive: true } });
const user = await usersService.findOne({ where: { email: 'user@example.com' } });

Error Handling

The service provides consistent error handling:
  • NotFoundException: Thrown when an entity is not found
  • BadRequestException: Thrown for invalid data or SQL injection attempts
Example:
try {
  const user = await usersService.getOne(req);
} catch (error) {
  if (error instanceof NotFoundException) {
    // Handle not found
  }
}

See Also