Trying to call by Enum (NestJS) - node.js

I'm coding on NestJS and I'm trying to call my database info by enumeration.
Example: I want all of motherboard (motherboard is an enum). I'm having many options for this.
I would like your opinion and for you, what is the best option?
This is my Entity :
#Entity('component')
export class Component {
static idComponent(idComponent: any): Component[] | PromiseLike<Component[]> {
throw new Error('Method not implemented.');
}
#PrimaryGeneratedColumn()
idComponent: number;
#Column()
name: string;
#Column()
brand: string;
#Column()
availability: string;
#Column()
price: string;
#Column('enum', { enum: ComponentType })
type: ComponentType;
service_type: ComponentType;
#Column('datetime', { default: () => 'CURRENT_TIMESTAMP' })
date: string;
#ApiProperty({ enum: () => Configurateur })
#OneToMany(() => Configurateur, configurateur => configurateur.component)
ComponentType: Configurateur[];
}
My Controller :
#ApiTags('component')
#Controller('component')
export class ComponentController {
constructor(private componentService: ComponentService) { }
#Get('all')
async findAll(#Res() res) {
const lists = await this.componentService.findAll();
return res.status(HttpStatus.OK).json(lists);
}
#Get('id')
async findById(#Res() res, #Query('id') id: string) {
const lists = await this.componentService.findById(id);
if (!lists) throw new NotFoundException('Id does not exist!');
return res.status(HttpStatus.OK).json(lists);
}
#Get('type')
async findByType(#Res() res, #Query('type') ComponentType: string) {
const listsType = await this.componentService.findByType(ComponentType);
if (!listsType) throw new NotFoundException('Id does not exist!');
return res.status(HttpStatus.OK).json(listsType);
}
}
And my Service :
#Injectable()
export class ComponentService {
constructor(
#InjectRepository(Component)
private readonly componentRepository: Repository<Component>,
) { }
async findAll(): Promise<Component[]> {
return await this.componentRepository.find();
}
async findById(id): Promise<Component[]> {
const customer = await this.componentRepository.findByIds(id);
return customer;
}
async findByType(ComponentType): Promise<any> {
const customerType = await this.componentRepository.find(ComponentType);
return customerType;
}
// Have Error and is a test
getType(ByType): Promise<any> {
let Type = String(ByType);
return new Promise(resolve => {
const type = this.componentRepository.find(type => type.Type === Type);
if (!type) {
throw new HttpException('Course does not exist', 404)
}
resolve(Type)
});
}
}
Edit : CompentType is my Enums file.
Thank you for your time.

Related

ERROR [ExceptionsHandler] Cannot query across many-to-many for property permissions

I have a project that I have made the project with nestjs and now I have a problem in method's update and the relation is Many-To-Many when I call Put Api nest gives me below error Note: I have 2 entity Role and Permission that they have many-to-many relation together.
I have a update method in role-service that I commented on it that works well but I have made a abstract class and role-service extended it but the method update doesn't work and give me bellow error
request api => url/api/role/id Body => {name:"admin",permissions:[{"id":1},{"id":2}]}
ERROR [ExceptionsHandler] Cannot query across many-to-many for property permissions
-Role Entity
import { Permission } from 'src/permission/model/permission.entity';
import {
Column,
Entity,
JoinTable,
ManyToMany,
PrimaryGeneratedColumn,
} from 'typeorm';
#Entity('roles')
export class Role {
#PrimaryGeneratedColumn()
id: number;
#Column()
name: string;
#ManyToMany((_Type) => Permission, { cascade: true })
#JoinTable({
name: 'role_permissions',
joinColumn: { name: 'role_id', referencedColumnName: 'id' },
inverseJoinColumn: { name: 'permission_id', referencedColumnName: 'id' },
})
permissions: Permission[];
}
Permission Entity
#Entity('permissions')
export class Permission {
#PrimaryGeneratedColumn()
id: number;
#Column()
name: string;
}
Role Controller
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Put,
UseGuards,
} from '#nestjs/common';
import { AuthGuard } from 'src/auth/auth.guard';
import { RoleCreateDto } from './models/role-create.dto';
import { RoleUpdateDto } from './models/role-update.dto';
import { Role } from './models/role.entity';
import { RoleService } from './role.service';
#UseGuards(AuthGuard)
#Controller('roles')
export class RoleController {
constructor(private roleService: RoleService) {}
#Put(':id')
async update(#Param('id') id: number, #Body() body: RoleUpdateDto) {
await this.roleService.update(id,body);
return await this.roleService.findOne({ id });
}
}
Role service
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { AbstractService } from 'src/common/abstract.service';
import { Repository } from 'typeorm';
import { RoleCreateDto } from './models/role-create.dto';
import { Role } from './models/role.entity';
#Injectable()
export class RoleService extends AbstractService {
constructor(
#InjectRepository(Role) private readonly roleRepository: Repository<Role>,
) {
super(roleRepository)
}
async findOne(condition): Promise<Role> {
return await this.roleRepository.findOne({ where: condition , relations:["permissions"]});
}
// async update(id: number, data:any): Promise<any> {
// console.log(id);
// const role = await this.findOne({id});
// console.log(role);
// role.name = data.name;
// role.permissions= data.permissions;
// const r = await this.roleRepository.preload(role)
// console.log("role",r);
// return await this.roleRepository.save(r);
// }
// async delete(id: number): Promise<any> {
// return await this.roleRepository.delete(id);
// }
}
abstract service
import { Injectable } from '#nestjs/common';
import { Repository } from 'typeorm';
import { PaginatedResult } from './pagibated-result.interface';
#Injectable()
export abstract class AbstractService {
protected constructor(protected readonly repository: Repository<any>) {}
async all(): Promise<any[]> {
return await this.repository.find();
}
async paginate(page = 1): Promise<PaginatedResult> {
const take = 1;
const [data, total] = await this.repository.findAndCount({
take,
skip: (page - 1) * take,
});
return {
data: data,
meta: {
total,
page,
last_page: Math.ceil(total / take),
},
};
}
async create(data): Promise<any> {
return await this.repository.save(data);
}
async findOne(condition): Promise<any> {
return await this.repository.findOne({ where: condition });
}
async update(id: number, data): Promise<any> {
return await this.repository.update({id},data);
}
async delete(id: number): Promise<any> {
return await this.repository.delete(id);
}
}

How should I create a PrismaAdapter

I would like to create a PrismaAdapter,the model should be a string or the PrismaModel (i dont know how to type it) but I am struggling and I don't know if it is even possible. Here is my failed attempt.
thx for your help
import { PrismaClient } from '#prisma/client'
//type PrismaModel = keyof PrismaClient<PrismaClientOptions>
//type PrismaModel = keyof Prisma.userDelegate<GlobalReject>
//type PrismaUserModel = Prisma.userDelegate<GlobalReject>;
class PrismaAdapter {
private prisma: PrismaClient
private user: PrismaUserModel
constructor() {
this.prisma = new PrismaClient()
this.user = this.prisma.user
}
async findOne(model: PrismaModel, where: object): Promise<any> {
return await this.prisma[model].findOne({ where })
}
async findMany(model: string): Promise<any[]> {
return await this.prisma[model].findMany()
}
async create(model: PrismaModel, data: object): Promise<any> {
return await this.prisma[model].create({ data })
}
async update(model: string, where: object, data: object): Promise<any> {
return await this.prisma[model].update({ where, data })
}
async delete(model: string, where: object): Promise<any> {
return await this.prisma[model].delete({ where })
}
}
export default PrismaAdapter
I am expecting to use it in a Database service class.
import PrismaAdapter from "./PrismaAdapter";
class DatabaseAdapter {
private database: PrismaAdapter;
private model: PrismaModel;
constructor({database, model}: {database: PrismaAdapter, model: PrismaModel}) {
this.database = database;
}
async findOne(model :PrismaModel,id: number): Promise<any> {
return this.database.findOne(model,where: {id})
}
async findMany(model: string): Promise<any[]> {
return await this.database.findMany(model)
}
}
export default DatabaseAdapter
And use this database Adapter in for exemple a UserRepository.

NESTJS - Cannot read property of repository in some cases

I'm getting: TypeError: Cannot read property 'list' of undefined (my custom repository BeneficiosRepository)
The problem is for the same instance of this service (BeneficiosService), the create and update function works, but pageAll, findOne and delete do not.
I can't understand the reason
I did a test forcing the create function to call the pageAll and it worked.
My Module:
#Module({
imports: [TypeOrmModule.forFeature([Beneficio,]), forwardRef(() => UsersModule)],
controllers: [BeneficiosController],
providers: [BeneficiosService, BeneficiosRepository, IsUniqueNomeConstraint],
exports: [BeneficiosService, BeneficiosRepository],
})
export class BeneficiosModule { }
My Service:
#Injectable({ scope: Scope.REQUEST })
export class BeneficiosService {
constructor(
#Inject(REQUEST)
private readonly request: Request,
private beneficiosRepository: BeneficiosRepository,
#Inject(forwardRef(() => UsersService))
private readonly usersService: UsersService,
) {
}
#UseInterceptors(ClassSerializerInterceptor)
async pageAll(pageOptionsDto: PageOptionsDto, filterDto: FilterBeneficioDto) {
const [beneficios, total] = await this.beneficiosRepository.list(pageOptionsDto, filterDto);
const pageMetaDto = new PageMetaDto({ itemCount: total, pageOptionsDto });
return new PageDto(beneficios, pageMetaDto);
}
#UseInterceptors(ClassSerializerInterceptor)
async create(dto: CreateBeneficioDto) {
const validatedDto = this.validationDesconto(dto);
const user_id = getUserIdService(this.request);
const user = await this.usersService.findOne(user_id);
const beneficio = this.beneficiosRepository.create(validatedDto);
beneficio.user_registrou = user;
const createdBeneficio = await this.beneficiosRepository.save(beneficio);
return plainToClass(Beneficio, createdBeneficio);
}
#UseInterceptors(ClassSerializerInterceptor)
async findOne(id: string) {
const beneficioExists = await this.checkIfBeneficioExists(id);
return instanceToPlain(beneficioExists, { groups: ['find'] }) as Beneficio;
}
#UseInterceptors(ClassSerializerInterceptor)
async update(id: string, dto: UpdateBeneficioDto) {
const validatedDto = this.validationDesconto(dto);
await this.checkIfBeneficioExists(id);
const updatedBeneficio = await this.beneficiosRepository.save(validatedDto);
return plainToClass(Beneficio, updatedBeneficio);
}
#UseInterceptors(ClassSerializerInterceptor)
async remove(id: string) {
await this.checkIfBeneficioExists(id);
await this.beneficiosRepository.softDelete({ id });
}
async findByIds(ids: string[]) {
return await this.beneficiosRepository.findBy({ id: In(ids) });
}
private async checkIfBeneficioExists(id: string): Promise<Beneficio> {
const beneficioExists = await this.beneficiosRepository.findById(id);
if (!beneficioExists) {
throw new AppError(`Benefício ${id} não encontrado!`, 404);
}
return beneficioExists;
}
private validationDesconto(beneficio: Beneficio | UpdateBeneficioDto | CreateBeneficioDto): Beneficio | UpdateBeneficioDto | CreateBeneficioDto {
const { is_descontado, tipo_desconto, valor_desconto } = beneficio;
if (!is_descontado) {
delete beneficio.tipo_desconto;
delete beneficio.valor_desconto;
return beneficio;
}
if (tipo_desconto && valor_desconto && valor_desconto.valueOf()) {
return beneficio;
}
throw new AppError(`Se o benefício é descontado, os campos "tipo_desconto" e "valor_desconto" devem obrigatóriamente serem preenchidos!`);
}
}
My Controller:
#ApiBearerAuth()
#ApiTags('beneficios')
#Controller('beneficios')
export class BeneficiosController {
constructor(private readonly beneficiosService: BeneficiosService) { }
#Post()
#ApiOperation({ summary: 'Cria um novo benefício' })
#ApiResponse({ status: 200, isArray: false, type: Beneficio })
#ApiResponse({ status: 403, description: 'Proibido.' })
async create(#Body() dto: CreateBeneficioDto) {
return await this.beneficiosService.create(dto);
}
#Get()
#ApiOperation({ summary: 'Lista todos os benefícios ativos' })
#ApiResponse({ status: 200, isArray: true, type: Beneficio })
#ApiResponse({ status: 403, description: 'Proibido.' })
async pageAll(#Query() dto: PageOptionsDto, #Query() filter: FilterBeneficioDto) {
return await this.beneficiosService.pageAll(dto, filter);
}
#Get(':id')
#ApiOperation({ summary: 'Recupera um benefício com base no ID passado' })
#ApiResponse({ status: 200, isArray: false, type: Beneficio })
#ApiResponse({ status: 403, description: 'Proibido.' })
findOne(#Param('id') id: string) {
return this.beneficiosService.findOne(id);
}
#Put(':id')
#ApiOperation({ summary: 'Atualiza um benefício' })
#ApiResponse({ status: 200, isArray: false, type: Beneficio })
#ApiResponse({ status: 403, description: 'Proibido.' })
update(#Param('id',) id: string, #Body() dto: UpdateBeneficioDto) {
return this.beneficiosService.update(id, dto);
}
#Delete(':id')
#ApiOperation({ summary: 'Deleta um benefício' })
#ApiResponse({ status: 204, })
#ApiResponse({ status: 403, description: 'Proibido.' })
remove(#Param('id') id: string) {
return this.beneficiosService.remove(id);
}
}
My Repo:
#Injectable()
export class BeneficiosRepository extends Repository<Beneficio> implements IBeneficiosRepository {
constructor(private dataSource: DataSource) {
super(Beneficio, dataSource.createEntityManager());
}
async findById(id: string): Promise<Beneficio> {
const beneficio = await this
.createQueryBuilder("beneficio")
.leftJoinAndSelect("beneficio.user_registrou", "users")
.where("beneficio.id = :id", { id })
.getOne();
return beneficio;
}
async findByNome(nome: string): Promise<Beneficio> {
const beneficio = await this
.createQueryBuilder("beneficio")
.leftJoinAndSelect("beneficio.user_registrou", "users")
.where("beneficio.nome ILIKE :nome", { nome })
.getOne();
return beneficio;
}
async list({ skip, take, order }: PageOptionsDto,
{ tipo_desconto, is_descontado, descricao, nome }: FilterBeneficioDto): Promise<[Beneficio[], number]> {
const query = this
.createQueryBuilder("beneficio")
.orderBy("beneficio.created_at", order)
.skip(skip)
.take(take)
.where("1=1");
if (nome) {
query.andWhere("beneficio.nome ILIKE :nome", { nome: '%${nome}%'});
}
if (descricao) {
query.andWhere("beneficio.descricao ILIKE :descricao", { descricao: '%${descricao}%' });
}
if (is_descontado && is_descontado === 'true' || is_descontado === 'false') {
query.andWhere("beneficio.is_descontado = :is_descontado", { is_descontado });
}
if (tipo_desconto) {
query.andWhere("beneficio.tipo_desconto = :tipo_desconto", { tipo_desconto });
}
const beneficios = await query.getManyAndCount();
return beneficios;
}
}
Resource http://localhost:3000/beneficios - Method POST = Work
Print success
Resource http://localhost:3000/beneficios - Method GET = Repository is undefined
Print error
Testing via Insomnia
Work:
#UseInterceptors(ClassSerializerInterceptor)
async create(dto: CreateBeneficioDto) {
return await this.pageAll({skip: 0}, {});
}
Undefined Error:
#UseInterceptors(ClassSerializerInterceptor)
async pageAll(pageOptionsDto: PageOptionsDto, filterDto: FilterBeneficioDto) {
const [beneficios, total] = await this.beneficiosRepository.list(pageOptionsDto, filterDto);
const pageMetaDto = new PageMetaDto({ itemCount: total, pageOptionsDto });
return new PageDto(beneficios, pageMetaDto);
}

How to access the value of a constant outside a function?

I am using Node with websocket and I have this function:
const validatedCep = async () => {
const data = await axios
.get(`https://viacep.com.br/ws/${message}/json/`)
.then((res) => {
return res.data;
})
.catch((err) => {
return err.response;
});
console.log(1, data);
return data;
};
if (this.props.dataType === "CEP") {
validatedCep();
}
How can I get the value returned in response and access that value outside the validatedCep function?
I need this value to be able to check if it will return the value of the answer or an error, so that I can proceed with the logic of the function.
Full function:
import { MessageSender } from "./message-sender";
import { WappMessage } from "./wapp-message";
import axios from "axios";
export type FormProps = {
error?: string;
text: string;
dataType: string;
typingDuration: number;
};
export class WappFormMessage extends WappMessage<FormProps> {
constructor(
readonly props: FormProps,
private next: WappMessage<any> | undefined,
protected messageSender: MessageSender<FormProps>
) {
super(props, "response", true, messageSender);
}
getNext(message: string): WappMessage<any> | undefined {
const regexs = [
{ type: "email", regex: "^[a-z0-9]+#[a-z0-9]+\\.[a-z]+\\.?([a-z]+)?$" },
{ type: "CPF", regex: "^\\d{3}\\.?\\d{3}\\.?\\d{3}\\-?\\d{2}$" },
{ type: "CNPJ", regex: "^d{2}.?d{3}.?d{3}/?d{4}-?d{2}$" },
{
type: "cellPhone",
regex: "(^\\(?\\d{2}\\)?\\s?)(\\d{4,5}\\-?\\d{4}$)",
},
{ type: "phone", regex: "(^\\(?\\d{2}\\)?\\s?)(\\d{4}\\-?\\d{4}$)" },
{ type: "birthDate", regex: "(^\\d{2})\\/(\\d{2})\\/(\\d{4}$)" },
];
const dataTypes = [
"email",
"birthDate",
"CPF",
"CNPJ",
"cellPhone",
"phone",
];
const validateData = (element: string) => {
if (this.props.dataType === element) {
const getRegex = regexs.find((regexs) => regexs.type === element);
const regexCreate = new RegExp(getRegex!.regex, "i");
const validate = regexCreate.test(message);
return validate;
}
return true;
};
const isValid = dataTypes.find(validateData);
if (!isValid) {
return new WappFormMessage(
{
error: "Invalid data!",
...this.props,
},
this.next,
this.messageSender
);
}
const validatedCep = async () => {
const data = await axios
.get(`https://viacep.com.br/ws/${message}/json/`)
.then((res) => {
return res.data;
})
.catch((err) => {
return err.response;
});
console.log(1, data);
return data;
};
if (this.props.dataType === "CEP") {
validatedCep();
}
return this.next;
}
async send(remoteJid: string): Promise<void> {
await this.messageSender.send(
remoteJid,
this.props,
this.props.typingDuration
);
}
}

typeorm convert EntitySchema to Entity

I'm using typescript and typeorm. I have this Entity:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
#Entity()
export class Sample {
#PrimaryGeneratedColumn()
id: number;
#Column({ length: 50 })
name: string;
#Column('text', { nullable: true })
description: string;
}
I query a single result like this:
const connection = await this.getConnection();
const sampleRepo = await connection.getRepository(Sample);
const sample = await sampleRepo.createQueryBuilder('sample')
.where('sample.id = :id', { id: id })
.getOne();
Now, I need to do some stuff with the result columns, but the sample object is of type EntitySchema. So, in typescript, I can't do sample.id because the error:
Property 'id' does not exist on type 'EntitySchema<any>'
Is there anyway to convert the EntitySchema into an actual Sample object?
As it turns out, this is due to a bad implementation. I moved the creation of the repository to a separate class:
export default class Database {
private connectionManager: ConnectionManager
constructor() {
this.connectionManager = getConnectionManager();
}
public getRepository<T extends EntitySchema>(type: ObjectType<T> | EntitySchema<T> | string): Promise<Repository<T>> {
const connection = await this.getConnection();
return connection.getRepository(type);
}
public async getConnection(connectionName = 'default'): Promise<Connection> {
let connection: Connection;
if (this.connectionManager.has(connectionName)) {
connection = this.connectionManager.get(connectionName);
if (!connection.isConnected) {
connection = await connection.connect();
}
}
else {
const connectionOptions: ConnectionOptions = Object
.assign({ name: connection }, connectionProperties);
connection = await createConnection(connectionOptions);
}
return connection;
}
}
It looks like connection.getRepository doesn't return a promise. As well, the T generic shouldn't be extending EntitySchema. To make the function work as intended, I had to write it like this:
public getRepository<T>(type: ObjectType<T> | EntitySchema<T> | string): Promise<Repository<T>> {
return new Promise((resolve, reject) => {
this.getConnection().then(conn => {
resolve(conn.getRepository(type));
}).catch(reject);
});
}

Resources