npm package: @impactor/nest-crud
Description: Automatically generate APIs and crud operators for NestJs apps
Author: Sherif Eldeeb
Latest version: 3.0.0
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

Quickly generate all API endpoints and Crud operations of a controller without a single line of code.

## Installation

```shell
npm install @impactor/nest-crud
```

## Usage

just decorate your controller with `@Crud()` ... that's all.

```ts
import { Crud } from "@impactor/nest-crud";

@Controller("users")
@Crud({ model: User }) //<--- provide the DTO, so validations can works.
export class UsersController {
  constructor(private readonly service: UsersService) {}

  // you don't need to add any method here, all routes are generated automatically.
  // but if you need to add additional route or modify the generated routes, you're welcome.
}
```

This decorator automatically generates all endpoints for this entity.
It also generates swagger metadata, so you document all your operations automatically.
It also support advanced queries, so you can filter and sort your data efficiently.
you don't need the DTOs that are generated by NestJS, you can safely delete them.

## generated endpoints:

- `GET /:id`: retrieves a single record by its primary key.
- `GET /`: retrieves all or some of the records. filtration and sorting are supported here. it also supports all [TypeORM find query options](https://typeorm.io/docs/working-with-entity-manager/find-options)
- `POST /`: inserts a new record.
- `PATCH /:id`: update a record by its primary key.
- `PATCH /`: update multiple records that match the specified conditions.
- `PUT /:id`: replace a record by its primary key.
- `PUT /`: replace multiple records that match the specified conditions.
- `DELETE /:id`: perform a hard or soft delete on a record by its primary key.
- `DELETE /`: perform a hard or soft delete on multiple records.
- `DELETE /clear`: clear all records from the repository.
- Relation endpoints for each relation defined in your DTO, for instance `GET /users/:id/roles`: retrieves all roles associated with a user.

## Controller methods.

The following methods are automatically attached to the controller class.
You don't need to add them manually.

- `getOne(id: string, query?: Object, req?: Request){}`
- `getMany(query?: Object, req?: Request){}`
- `post(body: DTO, query?: Object, req?: Request){}`
- `patchOne(id: string, body: PartialDeep<DTO>, query?: Object, req?: Request){}`
- `patchMany(body: PartialDeep<DTO>, query?: Object, req?: Request){}`
- `PutOne(id: string, body: DTO, query?: Object, req?: Request){}`
- `putMany(body:DTO, query?: Object, req?: Request){}`
- `deleteOne(id: string, query?: Object, req?: Request){}`
- `deleteMany(query?: Object, req?: Request){}`

The generated methods follow the following pattern guide:

- The method name is a combination between the http method and `One` (for single record) or `Many` (for multiple records), except `post()`
- all methods accept `query` and `req` as last params.
- all single methods (i.e. those which ends with `One`) accept `id` as a first param.

each methods calls the corresponds method in the injected service.
you can add these methods manually, or just extend `CrudTypeOrmService`.

## add or override routes

You can add additional routes by providing the option `routes[]` in `@Crud()` decorator,
or by declaring a new route in your controller.

```ts
import { Crud } from "@impactor/nest-crud";

@Controller("users")
@Crud({
  model: User,
  routes: [
    /* define new routes here*/
  ],
})
export class UsersController {
  constructor(private readonly service: UsersService) {}

  // or simply add your methods as usual
  @Get("/hello")
  sayHello() {
    return "Hello World!";
  }
}
```

The magic also added to your additional routes the same way as the generated ones.
for instance, Swagger metadata, query filter options, and other validations and decorators are applied to your additional routes.
You can control each route options by decorate it using `@CrudRoute()` which accepts almost the same options that `@Crud()` accepts.

for example, you can tell your route to limit the number of results returned by the route to 50 max.
also, to add filter options and enable fiteration and sorting features, set `many: true`.
This also adjusts Swagger to expect the response to be as array or results, instead of a single object result, improving your documentations for your endpoints.

```ts
@Get('/hello')
@CrudRoute({many: true, query: { maxLimit: 50 }})
  sayHello(){
    return 'Hello World!';
  }
```

You can disable additional features to any route by simply add `disabled: true`.

To modify a route behavior, just declare a route with the same method name.

```ts
@Get(':id')
@CrudRoute({/* override the default route behavior here*/})
  getOne(@Param("id") id: string, @Query() query?: Object, @Req() req?: Request){
    return 'custom response'
  }
```

or

```ts
@Controller("users")
@Crud({ model: User, routes: [{ methodName: "deleteMany", disabled: true }] }) //<-- disable `DELETE /`
export class UsersController {}
```

## Options

You can customize the behavior of `@Crud()` using options, all options are inherited by default to all routes.
but each route can override and use its own custom behavior.

- `model`: the entity or DTO.
- `routes`: a list of route configurations.
- `servicename`: the injected service name, default: "service"
- `responseModels`: the response model for each corresponding response code, by default it is the same as `model`.
- `primaryKey`: the primary key name, default: "id"
- `maxLimit`: the maximum allowed records to be returned by the request, use this option to protect your large repos from fetching too much data size.
- `decorators`: the decorators to be applied to the routes.
- `interceptors`: the interceptors to be added to the routes.
- `query`: the default query object to be merged with each route query.

## Service

As said before, each controller method ends up calling the corresponding method of the injected service, which has the same name.

instead of declaring all these methods manually, you can just extend `CrudTypeOrmService`.

### Example:

```ts
import { CrudTypeOrmService } from "@impactor/nest-crud";

@Injectable()
export class UsersService extends CrudTypeOrmService<User> {
  constructor(@InjectRepository(User) protected repo: Repository<User>) {
    super(repo);
  }

  // you don't need to perform CRUD operations manually.
  // all CRUDs are automatically generated.
}
```

## Full example

1- define our entity or DTO

```ts
import { Entity, PrimaryGeneratedColumn } from "typeorm";
import { ApiHideProperty, ApiProperty } from "@nestjs/swagger";

@Entity()
export class User {
  @PrimaryGeneratedColumn("uuid")
  @ApiHideProperty()
  id: string;

  @Column({ nullable: false, type: "varchar", length: 100 })
  @IsString()
  @MaxLength(100)
  @ApiProperty()
  name: string;

  @Column({ unique: true, nullable: false, type: "varchar", length: 250 })
  @IsEmail()
  @ApiProperty({ example: "user.email@gmail.com" })
  email: string;
}
```

2- define our service

```ts
import { CrudTypeOrmService } from "@impactor/nest-crud";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { User } from "./entities/user.entity";

@Injectable()
export class UsersService extends CrudTypeOrmService<User> {
  constructor(@InjectRepository(User) protected repo: Repository<User>) {
    super(repo);
  }
}
```

3- finally define our controller

```ts
import { Crud } from "@impactor/nest-crud";

@Controller("users")
@Crud({ model: User })
export class UsersController {
  constructor(private readonly service: UsersService) {}

  // add additional routes
  @Get("random")
  getRandomUser() {
    return this.getMany({ limit: 1 }).then((res) => res[0]);
  }

  // disallowing deleting multiple records
  @CrudRoute({ disabled: true })
  deleteMany() {}

  // modify a route behavior, such as `GET /:id`
  async post(@Param("id") id: string) {
    let res = await this.service.getOne(id);
    res.name = `Mr. ${res.name}`;
    return res;
  }
}
```

Start your app and navigate to "localhost:<port>" to see the generated endpoints in Swagger UI.
Now you can make requests like `GET /users/1` and `POST /users` without even declaring any of them yourself.

## Contact me

have a question? feel free to contact me anytime.

### follow me:

[LinkedIn](https://linkedin.com/in/dibo) | [Telegram](https://t.me/its_dibo)