forked from Sairyss/domain-driven-hexagon
-
Notifications
You must be signed in to change notification settings - Fork 3
/
user.repository.ts
68 lines (59 loc) · 2.16 KB
/
user.repository.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import { InjectPool } from 'nestjs-slonik';
import { DatabasePool, sql } from 'slonik';
import { UserRepositoryPort } from './user.repository.port';
import { z } from 'zod';
import { UserMapper } from '../user.mapper';
import { UserRoles } from '../domain/user.types';
import { UserEntity } from '../domain/user.entity';
import { SqlRepositoryBase } from '@src/libs/db/sql-repository.base';
import { Injectable, Logger } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
/**
* Runtime validation of user object for extra safety (in case database schema changes).
* https://github.com/gajus/slonik#runtime-validation
* If you prefer to avoid performance penalty of validation, use interfaces instead.
*/
export const userSchema = z.object({
id: z.string().uuid(),
createdAt: z.preprocess((val: any) => new Date(val), z.date()),
updatedAt: z.preprocess((val: any) => new Date(val), z.date()),
email: z.string().email(),
country: z.string().min(1).max(255),
postalCode: z.string().min(1).max(20),
street: z.string().min(1).max(255),
role: z.nativeEnum(UserRoles),
});
export type UserModel = z.TypeOf<typeof userSchema>;
/**
* Repository is used for retrieving/saving domain entities
* */
@Injectable()
export class UserRepository
extends SqlRepositoryBase<UserEntity, UserModel>
implements UserRepositoryPort
{
protected tableName = 'users';
protected schema = userSchema;
constructor(
@InjectPool()
pool: DatabasePool,
mapper: UserMapper,
eventEmitter: EventEmitter2,
) {
super(pool, mapper, eventEmitter, new Logger(UserRepository.name));
}
async updateAddress(user: UserEntity): Promise<void> {
const address = user.getPropsCopy().address;
const statement = sql.type(userSchema)`
UPDATE "users" SET
street = ${address.street}, country = ${address.country}, "postalCode" = ${address.postalCode}
WHERE id = ${user.id}`;
await this.writeQuery(statement, user);
}
async findOneByEmail(email: string): Promise<UserEntity> {
const user = await this.pool.one(
sql.type(userSchema)`SELECT * FROM "users" WHERE email = ${email}`,
);
return this.mapper.toDomain(user);
}
}