-
Notifications
You must be signed in to change notification settings - Fork 6
/
Hotel.projector.ts
47 lines (43 loc) · 1.31 KB
/
Hotel.projector.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
import { client, Projector } from "@rotorsoft/eventually";
import { z } from "zod";
import * as models from "./Room.models";
import * as schemas from "./Room.schemas";
import { addDays } from "./utils";
export const RoomStateSchema = z.object({
id: z.string(),
number: z.number(),
type: z.nativeEnum(schemas.RoomType),
price: z.number(),
reserved: z.record(z.string())
});
export type RoomState = z.infer<typeof RoomStateSchema>;
export const Hotel = (): Projector<RoomState, models.RoomEvents> => ({
description: "Hotel read model",
schemas: {
state: RoomStateSchema,
events: {
RoomOpened: schemas.Room,
RoomBooked: schemas.BookRoom
}
},
on: {
RoomOpened: ({ data }) => {
const id = `Room-${data.number}`;
const { number, type, price } = data;
return Promise.resolve([{ id, number, type, price, reserved: {} }]);
},
RoomBooked: async ({ data }, map) => {
const id = `Room-${data.number}`;
const reserved =
map.records.get(id)?.reserved ??
(await client().read(Hotel, id)).at(0)?.state.reserved ??
{};
let day = data.checkin;
while (day <= data.checkout) {
reserved[day.toISOString().substring(0, 10)] = data.id;
day = addDays(day, 1);
}
return [{ where: { id }, reserved }];
}
}
});