async updateOne(
customerId: string,
name: string,
legalStatus: LegalStatus,
legalRegistrationDate: Date,
address: string,
city: City,
businessPhone: string,
businessEmail: string,
businessWebsite: string,
businessType: BusinessType,
activityStartingDate: Date,
fullTimeEmployees: number,
partTimeEmployees: number,
yearlyTurnover: number,
otherInfo: string
) {
const customer = await this.customersRepository.findOne(customerId);
if (!customer) {
throw new HttpException('Failed to find the Customer with given id', HttpStatus.NOT_FOUND);
}
if (name) {
const { id } = customer;
const { name } = customer;
const customers = await this.customersRepository.find({
where: {
id: Not(id),
name,
},
});
if (customers.length > 0) {
throw new HttpException(
'The Customer with the given name already exists',
HttpStatus.BAD_REQUEST
);
}
}
const payload = {
name,
legalStatus,
legalRegistrationDate,
address,
city,
businessPhone,
businessEmail,
businessWebsite,
businessType,
activityStartingDate,
fullTimeEmployees,
partTimeEmployees,
yearlyTurnover,
otherInfo,
};
console.log(payload);
// const updatedCustomer = Object.assign(customer, payload);
const updatedCustomer = this.customersRepository.update(customer.id, payload);
if (!updatedCustomer) {
throw new HttpException('Failed to update the Customer', HttpStatus.INTERNAL_SERVER_ERROR);
}
const savedCustomer = this.customersRepository.save(customer);
if (!savedCustomer) {
throw new HttpException('Failed to save the Customer', HttpStatus.INTERNAL_SERVER_ERROR);
}
return savedCustomer;
}
I am using nest.js, typescript, typeorm, postgress sql. I want to update specific fields of entity, and i want fields that i have not entered not to update. Is there any method i could use to update entity partially and not whole. I know a method Partial< EntityName > but it doesn't work with object as fields. I want a solution to this problem if someone can find it.
There are some solutions. Unfortunately, what you're describing is more of a domain of OOP IMO. So let's divide this problem into subproblems:
export interface IUser {
id: number,
username: string,
firstName: string
}
export class User implements IUser {
id: number;
username: string;
firstName: string;
// this is how I prefer doing constructors then:
constructor(iUser: IUser) {
this.id = iUser.id;
this.username = iUser.username;
this.firstName = iUser.firstName;
// here you can do additional validation using for example class-validator with annotations
}
}
So far so good. How do we ensure no one passes some malicious fields then? I really hate this about TS. What's the point of strongly typed language if I can still do:
(user as any).password="now your password is gone"
So what I do in that case is enforcing the type strictly in the part of the code I have full control over:
//...some service
updateUser(user: User) {
user = user instanceof User ? user : new User(user)
//... the rest of the code
}
it's a single line some JS developers would consider completely redundant, but I come from Java world, and I can't stand that a type is really a loose type in TS. You can look here for more on interfaces and how unreliable they can be.
Using this approach you can implement a function doing something like this:
export abstract class Updatable<T> {
updatePartial(input: Partial<T>): Partial<Omit<T, "id">> {
const updateObj = Object.keys(this).reduce(
(prev, curr) =>
input[curr] !== undefined ? { ...prev, [curr]: input[curr] } : prev,
{},
);
// just in case
delete (updateObj as any).id;
return updateObj;
}
}
which basically goes through the fields of an entity and compares them with given input. You should ensure names of the input match the entities'.
Then simply create a UserEntity and make it extend Updatable.
This solution is probably far from ideal, but if you want to perform safe PATCH operations, this is as far as I got it. If you find a better solution, please let me know, I'd love to make it better :)