提问人:kassem moghraby 提问时间:11/6/2023 更新时间:11/6/2023 访问量:30
我需要为 Nestjs 和 typeorm 中的控制器和服务创建一个可重用的类
i need to create a reusable classes for the controllers and services in Nestjs & typeorm
问:
我为 BaseController 和 BaseService 创建了抽象类,并将动态权限传递给每个方法,我的问题是 DTo,我如何将动态 Dto 传递给每个方法?
你认为在构造函数级别传递它们好吗??
`
import { BaseEntity, DeepPartial } from "typeorm";
import { BaseService } from "./base.service";
import { Body, Delete, Get, Patch, Post } from "@nestjs/common";
import { ID } from "@/decorators/common.decorator";
import { ResourceTypes } from "@/types/permission.types";
import { PermissionAccess } from "@/decorators/roles.decorator";
import { ControllerInterface } from "./controller.interface";
export abstract class BaseController<T extends BaseEntity,DtoAdd,DtoEdit> implements ControllerInterface<BaseEntity>{
protected constructor(private readonly baseService: BaseService<T>,
private readonly resource: ResourceTypes) {
}
@PermissionAccess({ resource: this.resource, action: "all", possession: "any" })
@Get("all")
async findAllElements(): Promise<T[]> {
return this.baseService.findAll();
}
@PermissionAccess({ resource: this.resource, action: "read", possession: "any" })
@Get(":id")
async findElement(@ID() id: number): Promise<T> {
return this.baseService.findOneById(id);
}
@PermissionAccess({ resource: this.resource, action: "create", possession: "any" })
@Post()
async createElement(@Body() payload: DtoAdd): Promise<T> {
return await this.baseService.createOne(payload);
}
@PermissionAccess({ resource: this.resource, action: "edit", possession: "any" })
@Patch(":id")
async updateElementById(@ID() id: number,@Body() payload: DtoEdit): Promise<T> {
return this.baseService.updateOneById(id, payload);
}
@PermissionAccess({ resource: this.resource, action: "remove", possession: "any" })
@Delete(":id")
async deleteElement(@ID() id: number): Promise<void> {
await this.baseService.deleteOne(id);
}
}
对应于以下 intrepjected 的 BaseService:
import { BasicEntity } from "@/entities/basic.entity";
import { DeepPartial, Repository } from "typeorm";
import { HttpException, HttpStatus } from "@nestjs/common";
import { ListPaginatedService } from "./list-paginated.service";
import { BaseServiceInterface } from "./base-service.interface";
export abstract class BaseService<T extends BasicEntity> extends ListPaginatedService <T> implements BaseServiceInterface<T>{
protected constructor(private readonly repository: Repository<T>) {
super(repository);}
async findAll(): Promise<T[]> {
return this.repository.find();
}
async findOneById(id: number): Promise<T> {
return this.repository.findOneBy(id);
}
async createOne(_payload: DeepPartial<T>): Promise<T> {
const entity = this.repository.create(_payload);
return await this.repository.save(entity);
}
async updateOneById(id: number, _payload: DeepPartial<T>): Promise<T> {
const _elementObject:T = await this.getOneByField('id', _payload)
Object.assign(_elementObject,_payload)
// await this.repository.update(id, _elementObject); // Number of affected rows
// not used because i need to return the new state for obj to user
await this.repository.save(_elementObject)
}
async deleteOne(id: number): Promise<void> {
await this.repository.delete(id);
}
async getOneByField(_byField:keyof T,_payload:DeepPartial<T>):Promise<T>{
try {
const _existenceDb:T = await this.repository.findOneBy(
{[_byField]:_payload[_byField]}
)
if(!_existenceDb){
throw new HttpException('the element not found in database to make the changes !', HttpStatus.NOT_FOUND)
}
return _existenceDb
}catch (error){
throw new HttpException('internal error happened !,' + error.toString(), HttpStatus.INTERNAL_SERVER_ERROR)
}
}
async isValueNotInUse(_byField:keyof T,_payload:DeepPartial<T>):Promise<void>{
try {
const _existenceDb:T = await this.repository.findOneBy(
{[_byField]:_payload[_byField]}
)
if(_existenceDb){
throw new HttpException(`the${_payload} with value ${_payload[_byField]} already taken !`, HttpStatus.NOT_FOUND)
}
}catch (error){
throw new HttpException('internal error happened !,' + error.toString(), HttpStatus.INTERNAL_SERVER_ERROR)
}
}
abstract excludeResponseField(_element:T):DeepPartial<T>
buildResponse(_element:T){ // its better to replace it with interceptor
return {
data:_element,
success:true
}
}
}
使用的接口:
export interface BaseServiceInterface<T extends BasicEntity> {
findAll(): Promise<T[]>;
findOneById(id: number): Promise<T>;
createOne(_payload: DeepPartial<T>): Promise<T>;
updateOneById(id: number, _payload: DeepPartial<T>): Promise<T>;
deleteOne(id: number): Promise<void>;
}
export interface ControllerInterface<T>{
findAllElements(): Promise<T[]>
findElement(@ID() id: number): Promise<T>
createElement(data: DeepPartial<T>): Promise<T>
updateElementById(@ID() id: number, _payload: DeepPartial<T>): Promise<T>
deleteElement(@ID() id: number): Promise<void>
}
答: 暂无答案
评论