Warning: we are using typeorm 0.3 and postgres for this tutorial
This tutorial continues where we left in
And let’s fill in the rest of generated boilerplate by nest-cli.
The Read of CRUD
Find queries are pretty straightforward:
// users.resolver.ts
@Query(() => [User], { name: 'users' })
async findAll(): Promise<User[]> {
return this.usersService.findAll();
}
@Query(() => User, { name: 'user' })
async findOne(
@Args('uuid', { type: () => String }) uuid: string,
): Promise<User> {
return this.usersService.findOne(uuid);
}
// users.service.ts
async findAll() {
return this.userRepo.find();
}
async findOne(uuid: string) {
return this.userRepo.findOneBy({ uuid });
}
The Update of CRUD
Define update DTO first, note that it can leverage PartialType
of the create DTO. For detailed tutorial of PartialType
and OmitType
check official doc at https://docs.nestjs.com/openapi/mapped-types
// update-user.input.ts
@InputType()
export default class UpdateUserInput extends PartialType(CreateUserInput) {
@Field(() => String)
uuid: string;
}
For update mutation, for a minimal version we can just return the count of affected rows:
// users.resolver.ts
@Mutation(() => Int)
async updateUser(
@Args('updateUserInput') updateUserInput: UpdateUserInput,
): Promise<number> {
return this.usersService.update(updateUserInput.uuid, updateUserInput);
}
// users.service.ts
async update(uuid: string, updateUserInput: UpdateUserInput) {
return (await this.userRepo.update({ uuid }, updateUserInput)).affected;
}
Alternatively, we may want to return the updated User from the update mutation, the code may not look elegant but it works:
// users.service.ts
import * as _ from 'lodash';
async update(uuid: string, updateUserInput: UpdateUserInput) {
const result = await this.userRepo
.createQueryBuilder()
.update(User)
.set(updateUserInput)
.where({ uuid })
.returning('*')
.execute();
return result.raw[0]
? _.mapKeys(result.raw[0], (_v: any, k: any) => _.camelCase(k))
: null;
}
Since we are using snake case naming strategy for postgres to keep it consistent with postgres standard we need to map the object names back to camel case.
Here returning('*')
enforces the user entity to be returned.
The Delete of CRUD
Similarly if we just want to return affected Rows count:
// users.resolver.ts
@Mutation(() => Int)
async removeUser(@Args('uuid', { type: () => String }) uuid: string) {
return this.usersService.remove(uuid);
}
// users.service.ts
async remove(uuid: string) {
return (await this.userRepo.delete(uuid)).affected;
}
To return the deleted users entities + affected rows count together we will have another in-depth tutorial on that in the future.