Class-validator: How accept missing field? - nestjs

The validator throw error "brandId must be a number conforming to the specified constraints",
when I missing "not require" field in body.
My validator class:
export class CreateNotificationDto {
#IsNumber()
userId: number
#IsNumber()
brandId: number
#IsNumber()
companyId: number
#IsString()
#IsNotEmpty()
#MinLength(1)
#MaxLength(255)
title: string
#IsString()
#IsNotEmpty()
#MinLength(1)
#MaxLength(50)
type: string
#IsString()
#IsNotEmpty()
message: string
}
my controller:
#Post()
#UseGuards(AuthGuard)
#UseInterceptors(Interceptor)
async create(#Body() dto: CreateNotificationDto, #TransactionParam() transaction: Transaction): Promise<Notification> {
const room = `room-user-${dto.userId}`
const data = await this.notificationService.create(dto, transaction)
await this.notificationGateWay.sendNoti({
room,
message: data.message
})
return data
}

You can use #IsOptional() decorator. For optional fields.

Related

TypeORM Postgres NodeJs Saving Data ManyToMany

I have 4 Entities that I set up and I want to save a recipe.
#Entity('recipes')
export class Recipe extends BaseEntity {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({ type: String, unique: true })
recipe_name: string;
#Column({ type: String })
description: string;
#OneToMany(() => RecipeIngredientList, (r: RecipeIngredientList) => r.recipeId)
recipeLists: RecipeIngredientList[];
}
#Entity('measurements')
export class MeasurementUnits {
#PrimaryGeneratedColumn()
id: number;
#Column({ type: String })
unit: string;
#ManyToMany(() => RecipeIngredientList, (r) => r.unitID, { cascade: true })
recipeList: RecipeIngredientList[];
}
#Entity('ingredients')
export class Ingredient {
#PrimaryGeneratedColumn()
id: number;
#Column({ type: String })
ingredient_name: string;
#ManyToMany(() => RecipeList, (r: RecipeList) => r.ingredientID, { cascade: true })
recipeList: RecipeList[];
}
#Entity('RecipeIngredientList')
export class RecipeIngredientList{
#PrimaryGeneratedColumn()
id: number;
#Column({type:Number})
amount: number;
#ManyToOne(() => Recipe, (r) => r.recipeLists)
recipeID: Recipe;
#ManyToMany(() => Ingredient)
#JoinTable()
ingredientID: Ingredient[];
#ManyToMany(() => MeasurementUnits)
#JoinTable()
unitID: MeasurementUnits[];
}
//My Save Method() The getDatabaseConnention() is in a service I wrote to
// check/connect via the DataSource.manager
const create = async (recipe: Recipe): Promise<Recipe> => {
const recipeRepository = await (
await getDatabaseConnection()).getRepository(Recipe);
const newRecipe: Recipe = await recipeRepository.save(recipe)
.catch((e) => {
console.debug('failed to create recipe Record', e);
throw new Error(e);
});
return newRecipe;
};
The effect of this is its creating the 6 tables in Postgres as expected but its only saving to the main recipes table and not able to save any of the relations. Am I missing foreignKeys or constraints in my entity setup? Or is my save method not properly identifying the relationships?
Now I know the way I have the DB setup the RecipeIngredientList Table is going to be the work horse and has a potential to get bloated, but I think this is a decent setup for a recipe management (I removed a lot of metadata to not bloat the post).

typeorm) query builder, left join and delete

I want to receive id and user information from the controller as arguments and delete it with query builder. But I am getting QueryFailedError: Unknown column 'certificate.id' in 'where clause' error. What's the problem?
#Entity()
#Unique(['url'])
export class CertificateEntity {
#PrimaryGeneratedColumn()
id: number;
#Column()
#IsUrl()
url: string;
#Column()
valid_from: string;
#Column()
valid_to: string;
#ManyToOne((type) => AuthEntity, (user) => user.certificates, {
eager: false,
})
user: AuthEntity;
}
#Unique(['username'])
#Entity()
export class AuthEntity extends BaseEntity {
#PrimaryGeneratedColumn()
id: number;
#Column()
email: string;
#Column()
username: string;
#Column()
password: string;
#Column()
signupVerifyToken: string;
#OneToMany((type) => CertificateEntity, (certificates) => certificates.user, {
eager: true,
})
certificates: CertificateEntity[];
}
// service
async remove(id: number, user: AuthEntity): Promise<boolean> {
console.log(id, user.id);
// error this point !
await this.certificateRepo
.createQueryBuilder('certificate')
.leftJoin('certificate.user', 'user')
.where('certificate.id=:id', { id: id })
.andWhere('user.id=:id', { id: user.id })
.delete()
.execute();
return true;
}
I'm not familiar with the query builder. Why Do I Get QueryFailedError: Unknown column 'certificate.id' in 'where clause' Error?
If it's still relevant. I never saw the solution to delete with use leftJoin.
try to use default delete(), where "id" it's "certificate.id"
this.certificateRepo.delete({ user: { id }, id: "id" });
it's just a fast example, rewrite to suit your case.
Or use 2 steps (I suggest it's a bad sulution)
const result = await this.certificateRepo
.createQueryBuilder('certificate')
.leftJoin('certificate.user', 'user')
.where('certificate.id=:id', { id: id })
.andWhere('user.id=:id', { id: user.id })
.getMany(); // .getOne()
result.forEach((el) => this.repository.delete(el.id));
you need to remove the alias from the where, and the where expression needs to provide a unique parameter, otherwise the :id in andWhere will override the :id in where.
await this.certificateRepo
.createQueryBuilder('certificate')
.leftJoin('certificate.user', 'user')
.where('id=:id', { id: id })
.andWhere('user.id=:userId', { userId: user.id })
.delete()
.execute();

NestJs, TypeOrm) Delete request with 2 Params

I want to allow only the author of the post to remove the post from the db.
When requesting delete from controller, typeORM intended delte({id, user}) by sending post ID and user information together, but an error occurs.
//entity
#Entity()
export class Board extends BaseEntity {
#PrimaryGeneratedColumn()
id: number;
#Column()
title: string;
#Column()
description: string;
#Column()
status: BoardStatus;
#ManyToOne((type) => UserEntity, (user) => user.boards, { eager: false })
user: UserEntity;
}
// controller
#Delete(':id')
deleteBoard(
#Param('id', ParseIntPipe) id: number,
#GetUser() user: UserEntity,
): Promise<void> {
return this.boardService.deletBoard(id, user);
}
// service
async deletBoard(id: number, user: UserEntity): Promise<void> {
const result = await this.boardRepository.delete({ id, user });
/* Argument of type '{ id: number; user: UserEntity; }' is not assignable to parameter of type 'string | number | Date | ObjectID | string[] | number[] | Date[] | ObjectID[] | FindOptionsWhere<Board>'.
Types of property 'user' are incompatible. */
if (result.affected === 0)
throw new NotFoundException(`Can't find by ${id}`);
}
try createQueryBuilder():
await this.boardService.createQueryBuilder('board')
.leftJoin('board.user', 'user')
.where('board.id = :id', {id})
.andWhere('user.id = :id', {id: user.id})
.delete()
.execute();

How can i check if a user already exist in firebase using nest.js code?

I'm trying to check if the email of the registered user is already found in firebase or not, before creating a new user in the firebase.
Here is where I create a user:
async create(user: UserRegisterDto) {
let newUser = this.saveUserModel(user);
return await this.firebaseService
.createFirebaseUser(newUser.email, newUser.password)
.then(res => {
const firebaseUser = JSON.parse(res);
(newUser).id = firebaseUser.uid;
return this.saveUserRecord(newUser);
})
.catch(error => {
return error;
});
}
and this is the UserRegisterDto object:
export class UserRegisterDto {
#ApiProperty()
#IsString()
email: string;
#ApiProperty()
#IsString()
fullName: string;
#ApiProperty()
#IsString()
password: string;
}
If you want to check if a user already exists in Firebase Authentication for a specific email address, you can call the fetchSignInMethodsForEmail method. If the array it returns is empty, the email isn't used by any user yet.

Type 'string' has no properties in common with type 'FindOneOptions<User>'

I am trying to build a backend with express.js. I now have the following problem:
import { Request, Response } from "express";
import { getManager } from "typeorm";
import { User } from "../entity/user.entity";
export const GetUser = async (req: Request, res: Response) => {
const repository = getManager().getRepository(User);
const { password, ...user } = await repository.findOne(req.params.id);
res.send(user);
};
The following error always occurs:
(parameter) req: Request<ParamsDictionary, any, any, QueryString.ParsedQs, Record<string, any>>
Type 'string' has no properties in common with type 'FindOneOptions'.ts(2559)
router.ts
router.get("/api/users/:id", AuthMiddleware, GetUser);
user.entity.ts
import {
Column,
Entity,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
} from "typeorm";
import { Role } from "./role.entity";
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column()
first_name: string;
#Column()
last_name: string;
#Column({
unique: true,
})
email: string;
#Column()
password: string;
#ManyToOne(() => Role)
#JoinColumn({ name: "role_id" })
role: Role;
}
Can anyone help me with my problem?
The typeorm's findOne function is equivalent to Select * ... limit 1. This means that the findOne actually expects an object containing conditions to match and return the first element for which the condition is satisfied.
In your case, the code should be:
repository.findOne({where: {id: parseInt(req.params.id, 10)}})
or
repository.findOneBy({id: parseInt(req.params.id, 10)})
This will find the user whose id field will match match the req.params.id.
according to manual, use the { criteria: search }
so
findOneBy({id: req.params.id});

Resources