A set of opinionated NestJS extensions and modules
@nestjsx/crud
has been designed for creating CRUD controllers and services for RESTful applications built with NestJs. It can be used with TypeORM repositories for now, but Mongoose functionality available in the future.
npm i @nestjsx/crud typeorm @nestjs/typeorm --save
Assume you have some typorm enitity:
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class Hero {
@PrimaryGeneratedColumn() id: number;
@Column() name: string;
}
Next, let's create a service for it:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { RepositoryService } from '@nestjsx/crud/typeorm';
import { Hero } from './hero.entity';
@Injectable()
export class HeroesService extends RepositoryService<Hero> {
constructor(@InjectRepository(Hero) repo) {
super(repo);
}
}
Just like that!
Next, let create a CRUD controller that expose some RESTful endpoints for us:
import { Controller } from '@nestjs/common';
import { Crud, CrudController } from '@nestjsx/crud';
import { Hero } from './hero.entity';
import { HeroesService } from './heroes.service';
@Crud(Hero)
@Controller('heroes')
export class HeroesController implements CrudController<HeroesService, Hero> {
constructor(service: HeroesService) {
super(service);
}
}
And that's it, no more inheritance and tight coupling. Let's see what happens here:
@Crud(Hero)
We pass our Hero
entity as a dto
for validation purpose (you can pass any other Dto class that fits you needs). So, if you use class-validator and class-transformer packages and ValidationPipe (or maybe your own implementation of it), in that case you can use validation decorators inside your entity class. Pretty handy, right?
If you don't use those, the implementation of request data validation is your own prerogative.
implements CrudController<HeroesService, Hero>
If you are not planning to override generated endpoints and you're pretty much sure that your service extends RepositoryService
, in that case you can remove interface here.
After that, all you have to do is to hook up everything in your module. By doing this simple steps your application will expose these endpoints:
GET /heroes
- get list of heroesGET /heroes/:id
- get one hero by idPOST /heroes
- create new heroPOST /heroes/bulk
- create many heroesPATCH /heroes/:id
- update existing heroDELETE /heroes/:id
- delete one hero
GET
endpoints that are generated by CRUD controller support some useful query parameters (all of them are optional):
fields
- get selected fields in GET resultfilter
(alias:filter[]
) - filter GET result byAND
type of conditionor
(alias:or[]
) - filter GET result byOR
type of conditionsort
(alias:sort[]
) - sort GET result by somefield
inASC | DESC
orderjoin
(alias:join[]
) - receive joined relational entities in GET result (with all or selected fields)limit
(aliasper_page
) - receiveN
amount of entitiesoffset
(aliasskip
) - offsetN
amount of entitiespage
- receive a portion oflimit
(per_page
) entities (alternative tooffset
)cache
- reset cache (if was enabled) and receive entities from the DB
Selects fields that should be returned in the reponse body.
Syntax:
?fields=field1,field2,...
Example:
?fields=email,name
Adds fields request condition (multiple conditions) to you request.
Syntax:
?filter=field||condition||value
Examples:
?filter=name||eq||batman
?filter=isVillain||eq||false&filter=city||eq||Arkham (multiple filters are treated as a combination of
AND
type of conditions)
?filter=shots||in||12,26 (some conditions accept multiple values separated by commas)
?filter=power||isnull (some conditions don't accept value)
Alias: filter[]
(condition - operator
):
eq
(=
, equal)ne
(!=
, not equal)gt
(>
, greater than)lt
(<
, lower that)gte
(>=
, greater than or equal)lte
(<=
, lower than or equal)starts
(LIKE val%
, starts with)ends
(LIKE %val
, ends with)cont
(LIKE %val%
, contains)excl
(NOT LIKE %val%
, not contains)in
(IN
, in range, accepts multiple values)notin
(NOT IN
, not in range, accepts multiple values)isnull
(IS NULL
, is NULL, doesn't accept value)notnull
(IS NOT NULL
, not NULL, doesn't accept value)between
(BETWEEN
, between, accepts two values)
Adds OR
conditions to the request
Syntax:
?or=field||condition||value