1.2.3 • Published 3 years ago

generate-crud v1.2.3

Weekly downloads
-
License
MIT
Repository
-
Last release
3 years ago

Generate crud Nestjs

This package provides a CRUD service for database MySQL build with TypeORM

Installation

npm i generate-crud

1. REST API with swagger

Usage

Assume you have some TypeORM enitity:

@Entity()
export class ProductEntity{
  @PrimaryGeneratedColumn()
  id: number;
  @Column()
  name: string;
  @Column()
  price: number;

}

Note: id is required

Then you need to create a service:

import { CrudTypeormService } from 'generate-crud';
@Injectable()
export class ProductService extends CrudTypeormService<ProductEntity> {
  constructor(
    @InjectRepository(ProductEntity)
    private productRepository: Repository<ProductEntity>,
  ) {
    super(productRepository);
  }
}

DTO is used for creating or updating entity, we will need it in controller

import { CrudTypeormController } from 'generate-crud';
@Controller('product')
export class ProductController extends CrudTypeormController(ProductEntity, InputProductDto) {
  constructor(private readonly productService: ProductService) {
    super(productService);
  }
}

After that you need to provide your service in a controller:

import { CrudTypeormController } from 'generate-crud';
@Controller('product')
export class ProductController extends CrudTypeormController(ProductEntity, InputProductDto) {
  constructor(private readonly productService: ProductService) {
    super(productService);
  }
}

Finally in main.js

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const config = new DocumentBuilder()
    .setTitle('Test api')
    .setVersion('1.0')
    .addTag('testapi')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);
  await app.listen(3000);
}
bootstrap();

2. Authentication with swagger and JWT

First you have some entity with other information: (username and password are included in Auth)

import { Auth } from 'generate-crud';
import { Entity, Column } from 'typeorm';

@Entity()
export class UserEntity extends Auth {
  @Column()
  firstName: string;
  @Column()
  lastName: string;
}

Then you need to create a auth Service:

import { AuthService } from 'generate-crud';
@Injectable()
export class UserService extends AuthService<UserEntity> {
  constructor(
    @InjectRepository(UserEntity)
    private userRepository: Repository<UserEntity>,
  ) {
    super(userRepository);
  }
}

InputUserDto for creating an account for user, there is no need to add username and password, only other information like firstName, lastName ...

import { Credential } from 'generate-crud';
import { ApiProperty } from '@nestjs/swagger';
export class InputUserDto extends Credential {
  @ApiProperty()
  firstName: string;
  @ApiProperty()
  lastName: string;
}

And create UserController extends from AuthController

import { Controller } from '@nestjs/common';
import { UserService } from './user.service';
import { AuthController } from 'generate-crud';
import { UserEntity } from './user.entity';
import { InputUserDto } from './create-user.dto';
@Controller('user')
export class UserController extends AuthController(UserEntity, InputUserDto) {
  constructor(private readonly userService: UserService) {
    super(userService);
  }
}

Add JwtStrategy in providers of app.module.ts file

import { JwtStrategy } from 'generate-crud';
@Module({
  ...
  providers: [JwtStrategy],
  ...
})

And in main.ts, edit config

const config = new DocumentBuilder()
    .setTitle('Test api')
    .setVersion('1.0')
    .addTag('testapi')
    .addBearerAuth(
      {
        type: 'http',
        scheme: 'bearer',
        bearerFormat: 'JWT',
        name: 'JWT',
        description: 'Enter JWT token',
        in: 'header',
      },
      'JWT-auth',
    )
    .build();

3. Authorization with swagger and JWT

First, let's create a Role enum representing roles in the system:

export enum Role {
  User = 'user',
  Admin = 'admin',
}

Your User class must look as follows:

@Entity()
export class UserEntity extends Auth {
  @Column()
  firstName: string;
  @Column()
  lastName: string;
  @Column({ type: 'enum', enum: Role, default: Role.User })
  roles: Role;
}

And now we set authorization for users, for examples:

export const Permisson = {
  create: [Role.User], // only 'user' role can create Product
  findAll: [Role.Admin, Role.User], // both 'admin' and 'user' role can findAll product
  findOne: [Role.User], // only 'user' role can findOne a Product
  delete: ['all'], // every user can delete Product
  patch: [], // every user can update Product
}

And pass Permission as a parameter of Product Controller

@Controller('product')
export class ProductController extends CrudTypeormController(
  ProductEntity,
  InputProductDto,
  Permisson
) {
  constructor(private readonly productService: ProductService) {
    super(productService);
  }
}

4. Using GraphQL

Usage

Assume you have some GraphQL schema :

@ObjectType('Product')
export class Product {
  @Field((type) => ID)
  id: number;
  @Field()
  name: string;
  @Field()
  price: number;
}

(Note: id is required)

After that you need to provide your service in a resolver:

@Resolver((type) => Product)
export class ProductResolver extends CrudTypeormResolver(Product) {
  constructor(private productService: ProductService) {
    super(productService);
  }
}

5. Authentication with GraphQL

Usage

Assume you have some GraphQL schema :

@ObjectType('User')
export class User {
  @Field((type) => ID)
  id: number;
  @Field()
  username: string;
  @Field()
  password: string;
  @Field()
  firstName: string;
  @Field()
  lastName: string;
}

(Note: id is required)

InputUserDto for creating an account for user

import { Field, InputType } from '@nestjs/graphql';
@InputType()
export class UserInputDto {
  @Field()
  username: string;
  @Field()
  password: string;
  @Field()
  firstName: string;
  @Field()
  lastName: string;
}

Then we need to create a service

import { AuthResolver, AuthTokenService } from 'generate-crud';
@Resolver((type) => User)
export class UserResolver extends AuthResolver(User) {
  constructor(
    private userService: UserService,
    private tokenService: AuthTokenService,
  ) {
    super(userService);
  }
}

After that we need to init AuthModule in UserModule

import { UserResolver } from './user.resolver';
import { AuthModule } from 'generate-crud';

@Module({
  imports: [TypeOrmModule.forFeature([UserEntity]),AuthModule],
  providers: [UserService, UserResolver],
  exports: [TypeOrmModule],
})

Finally in AppModule, add Auth and AuthToken to entity list

import { JwtStrategy, Auth, AuthToken } from 'generate-crud';
@Module({
  imports: [
    TypeOrmModule.forRoot({
      ...
      entities: [
        ...,
        Auth,
        AuthToken,
      ],
    }),
  ],
  controllers: [],
  providers: [JwtStrategy],
})

6. Authorization with GraphQL

Pass Permission as a parameter of Product Controller, and provide a AuthTokenService

import { AuthTokenService, CrudTypeormResolver } from 'generate-crud';
@Resolver((type) => Product)
export class ProductResolver extends CrudTypeormResolver(Product, Permisson) {
  constructor(
    private productService: ProductService,
    private tokenService: AuthTokenService,
  ) {
    super(productService);
  }
}

Then remember to import AuthModule in ProductModule

import { AuthModule } from 'generate-crud';
@Module({
  imports: [TypeOrmModule.forFeature([ProductEntity]), AuthModule],
  controllers: [ProductController],
  providers: [ProductService, ProductResolver],
})
export class ProductModule {}

License

MIT