-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
find-users.query-handler.ts
65 lines (57 loc) · 1.88 KB
/
find-users.query-handler.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
import { IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { Ok, Result } from 'oxide.ts';
import { PaginatedParams, PaginatedQueryBase } from '@libs/ddd/query.base';
import { Paginated } from '@src/libs/ddd';
import { InjectPool } from 'nestjs-slonik';
import { DatabasePool, sql } from 'slonik';
import { UserModel, userSchema } from '../../database/user.repository';
export class FindUsersQuery extends PaginatedQueryBase {
readonly country?: string;
readonly postalCode?: string;
readonly street?: string;
constructor(props: PaginatedParams<FindUsersQuery>) {
super(props);
this.country = props.country;
this.postalCode = props.postalCode;
this.street = props.street;
}
}
@QueryHandler(FindUsersQuery)
export class FindUsersQueryHandler implements IQueryHandler {
constructor(
@InjectPool()
private readonly pool: DatabasePool,
) {}
/**
* In read model we don't need to execute
* any business logic, so we can bypass
* domain and repository layers completely
* and execute query directly
*/
async execute(
query: FindUsersQuery,
): Promise<Result<Paginated<UserModel>, Error>> {
/**
* Constructing a query with Slonik.
* More info: https://contra.com/p/AqZWWoUB-writing-composable-sql-using-java-script
*/
const statement = sql.type(userSchema)`
SELECT *
FROM users
WHERE
${query.country ? sql`country = ${query.country}` : true} AND
${query.street ? sql`street = ${query.street}` : true} AND
${query.postalCode ? sql`"postalCode" = ${query.postalCode}` : true}
LIMIT ${query.limit}
OFFSET ${query.offset}`;
const records = await this.pool.query(statement);
return Ok(
new Paginated({
data: records.rows,
count: records.rowCount,
limit: query.limit,
page: query.page,
}),
);
}
}