diff --git a/package-lock.json b/package-lock.json index ca6697d..03f1656 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,9 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@event-driven-io/emmett-esdb": "0.10.0", - "@event-driven-io/emmett-expressjs": "0.10.0", - "@event-driven-io/emmett-testcontainers": "0.10.0" + "@event-driven-io/emmett-esdb": "0.11.0", + "@event-driven-io/emmett-expressjs": "0.11.0", + "@event-driven-io/emmett-testcontainers": "0.11.0" }, "devDependencies": { "@types/node": "20.11.30", @@ -490,9 +490,9 @@ } }, "node_modules/@event-driven-io/emmett": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@event-driven-io/emmett/-/emmett-0.10.0.tgz", - "integrity": "sha512-QcLNm34COaWUn+Taawg6cq6mOoeU9L19cGbebwBrEoVpcxmEtYv2nubgQ8ui48ypa3C7IEu77BIGcd3Z6mXP0A==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@event-driven-io/emmett/-/emmett-0.11.0.tgz", + "integrity": "sha512-/jtSkDUBe9SUFokJ7LuCcEbdgIYutigi7n58WxjBHxRFlXB/dzvmSUr6mEo8ODRssCAXU8XYEH2zOmVo2fC+EQ==", "peerDependencies": { "@types/async-retry": "^1.4.8", "@types/uuid": "^9.0.8", @@ -502,20 +502,20 @@ } }, "node_modules/@event-driven-io/emmett-esdb": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@event-driven-io/emmett-esdb/-/emmett-esdb-0.10.0.tgz", - "integrity": "sha512-/0JTi1OyeWhcReoN5I+DxvJ0iLMMl8jnpr0DqABho9o6lmWhzEz2a2A1tTENu6AxjYBkirsIGjpYuDK89sjY2Q==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@event-driven-io/emmett-esdb/-/emmett-esdb-0.11.0.tgz", + "integrity": "sha512-Q10j/paDLc1LC05dFhWqgRuvmKbXAEvZ3O/vK+ySrAQgTa0cWVHQfuZi0wdGBhShpAKZmBsAKlDHt2V3onjSUw==", "peerDependencies": { - "@event-driven-io/emmett": "0.10.0", + "@event-driven-io/emmett": "0.11.0", "@eventstore/db-client": "^6.1.0" } }, "node_modules/@event-driven-io/emmett-expressjs": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@event-driven-io/emmett-expressjs/-/emmett-expressjs-0.10.0.tgz", - "integrity": "sha512-cedwMNBTKjW6YpOrtfV0ozsLD1cLodnE6dlRMXsA6hZKZ0V33oCfalOzMKLH/9pcosypfpgap5QgWjy+F1lxHg==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@event-driven-io/emmett-expressjs/-/emmett-expressjs-0.11.0.tgz", + "integrity": "sha512-+lw5dNgU11Q8hiHHbE+dM1WtJEiiIYRDnGSCM0+l0InyyDncK/+kdiofw4gUkKM04w3oLJDWHabDOX1SliRoxw==", "peerDependencies": { - "@event-driven-io/emmett": "0.10.0", + "@event-driven-io/emmett": "0.11.0", "@types/express": "4.17.21", "@types/supertest": "6.0.2", "express": "4.19.2", @@ -525,11 +525,11 @@ } }, "node_modules/@event-driven-io/emmett-testcontainers": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@event-driven-io/emmett-testcontainers/-/emmett-testcontainers-0.10.0.tgz", - "integrity": "sha512-PnH896jrfKvhGIx6YPB93IO8Cd8X56bCec5S8+2stRB2DesLx3yHPh+V5p7NSGwZ3fMJP3XfoZg6rZMZn6JaKg==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@event-driven-io/emmett-testcontainers/-/emmett-testcontainers-0.11.0.tgz", + "integrity": "sha512-HHoCgILTcujOv9KwVJBDUr545KUSLoaNWHB4I5jWGzYzvum7eu/CUmqP6xuff8iGz5O/cXvn7LoE069dIY2uZQ==", "dependencies": { - "@event-driven-io/emmett": "0.10.0", + "@event-driven-io/emmett": "0.11.0", "testcontainers": "^10.7.2" } }, diff --git a/package.json b/package.json index 382f946..d6d9f6f 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,9 @@ }, "homepage": "https://github.com/oskardudycz/EventSourcing.NodeJS#readme", "dependencies": { - "@event-driven-io/emmett-esdb": "0.10.0", - "@event-driven-io/emmett-expressjs": "0.10.0", - "@event-driven-io/emmett-testcontainers": "0.10.0" + "@event-driven-io/emmett-esdb": "0.11.0", + "@event-driven-io/emmett-expressjs": "0.11.0", + "@event-driven-io/emmett-testcontainers": "0.11.0" }, "devDependencies": { "@types/node": "20.11.30", diff --git a/src/guestStayAccounts/api/api.e2e.spec.ts b/src/guestStayAccounts/api/api.e2e.spec.ts index d3a5251..a3e5953 100644 --- a/src/guestStayAccounts/api/api.e2e.spec.ts +++ b/src/guestStayAccounts/api/api.e2e.spec.ts @@ -220,6 +220,6 @@ describe('guestStayAccount E2E', () => { void it(`doesn't checkout`, () => given(...checkedOutAccount) .when(checkOut) - .then([expectError(403, { detail: `NotOpened` })])); + .then([expectError(403, { detail: `NotCheckedIn` })])); }); }); diff --git a/src/guestStayAccounts/api/api.int.spec.ts b/src/guestStayAccounts/api/api.int.spec.ts index b6472c7..724fad6 100644 --- a/src/guestStayAccounts/api/api.int.spec.ts +++ b/src/guestStayAccounts/api/api.int.spec.ts @@ -2,6 +2,7 @@ import { formatDateToUtcYYYYMMDD, getInMemoryEventStore, type EventStore, + type TestEventStream, } from '@event-driven-io/emmett'; import { ApiSpecification, @@ -12,7 +13,6 @@ import { getApplication, type TestRequest, } from '@event-driven-io/emmett-expressjs'; -import type { TestEventStream } from '@event-driven-io/emmett-expressjs/dist/testing/utils'; import { randomUUID } from 'node:crypto'; import { beforeEach, describe, it } from 'node:test'; import { @@ -426,14 +426,14 @@ void describe('Guest stay account', () => { given(checkedOutAccount) .when(checkOut) .then([ - expectError(403, { detail: `NotOpened` }), + expectError(403, { detail: `NotCheckedIn` }), expectNewEvents(guestStayAccountId, [ { type: 'GuestCheckoutFailed', data: { guestStayAccountId, groupCheckoutId: undefined, - reason: 'NotOpened', + reason: 'NotCheckedIn', failedAt: now, }, }, diff --git a/src/guestStayAccounts/api/api.ts b/src/guestStayAccounts/api/api.ts index 864eb7f..94b9759 100644 --- a/src/guestStayAccounts/api/api.ts +++ b/src/guestStayAccounts/api/api.ts @@ -55,7 +55,7 @@ type CheckOutRequest = Request< unknown >; -type GetShoppingCartRequest = Request< +type GetGuestStayAccountDetailsRequest = Request< Partial<{ guestId: string; roomId: string; checkInDate: string }>, unknown, unknown @@ -153,7 +153,7 @@ export const guestStayAccountsApi = }), ); - // CheckOut Shopping Cart + // CheckOut Guest router.delete( '/guests/:guestId/stays/:roomId/periods/:checkInDate', on(async (request: CheckOutRequest) => { @@ -179,10 +179,10 @@ export const guestStayAccountsApi = }), ); - // Get Shopping Cart + // Get Guest Stay Account Details router.get( '/guests/:guestId/stays/:roomId/periods/:checkInDate', - on(async (request: GetShoppingCartRequest) => { + on(async (request: GetGuestStayAccountDetailsRequest) => { const guestStayAccountId = parseGuestStayAccountId(request.params); const result = await getGuestStayDetails( @@ -192,7 +192,7 @@ export const guestStayAccountsApi = if (result === null) return NotFound(); - if (result.state.status !== 'Opened') return NotFound(); + if (result.state.status !== 'CheckedIn') return NotFound(); return OK({ body: result.state, diff --git a/src/guestStayAccounts/businessLogic.ts b/src/guestStayAccounts/businessLogic.ts index 0c20a8d..07073ad 100644 --- a/src/guestStayAccounts/businessLogic.ts +++ b/src/guestStayAccounts/businessLogic.ts @@ -2,12 +2,12 @@ import { IllegalStateError, type Command } from '@event-driven-io/emmett'; import { toGuestStayAccountId, type ChargeRecorded, + type CheckedIn, type GuestCheckedIn, type GuestCheckedOut, type GuestCheckoutFailed, type GuestStayAccount, type GuestStayAccountEvent, - type Opened, type PaymentRecorded, } from './guestStayAccount'; @@ -74,7 +74,7 @@ export const recordCharge = ( { data: { guestStayAccountId, chargeId, amount }, metadata }: RecordCharge, state: GuestStayAccount, ): ChargeRecorded => { - assertIsOpened(state); + assertIsCheckedIn(state); return { type: 'ChargeRecorded', @@ -91,7 +91,7 @@ export const recordPayment = ( { data: { guestStayAccountId, paymentId, amount }, metadata }: RecordPayment, state: GuestStayAccount, ): PaymentRecorded => { - assertIsOpened(state); + assertIsCheckedIn(state); return { type: 'PaymentRecorded', @@ -110,13 +110,13 @@ export const checkOut = ( ): GuestCheckedOut | GuestCheckoutFailed => { const now = metadata?.now ?? new Date(); - if (state.status !== 'Opened') + if (state.status !== 'CheckedIn') return { type: 'GuestCheckoutFailed', data: { guestStayAccountId, groupCheckoutId, - reason: 'NotOpened', + reason: 'NotCheckedIn', failedAt: now, }, }; @@ -165,8 +165,8 @@ export const decide = ( } }; -const assertDoesNotExist = (state: GuestStayAccount): state is Opened => { - if (state.status === 'Opened') +const assertDoesNotExist = (state: GuestStayAccount): state is CheckedIn => { + if (state.status === 'CheckedIn') throw new IllegalStateError(`Guest is already checked-in!`); if (state.status === 'CheckedOut') @@ -175,7 +175,7 @@ const assertDoesNotExist = (state: GuestStayAccount): state is Opened => { return true; }; -const assertIsOpened = (state: GuestStayAccount): state is Opened => { +const assertIsCheckedIn = (state: GuestStayAccount): state is CheckedIn => { if (state.status === 'NotExisting') throw new IllegalStateError(`Guest account doesn't exist!`); diff --git a/src/guestStayAccounts/businessLogic.unit.spec.ts b/src/guestStayAccounts/businessLogic.unit.spec.ts index 5f03a05..d445e92 100644 --- a/src/guestStayAccounts/businessLogic.unit.spec.ts +++ b/src/guestStayAccounts/businessLogic.unit.spec.ts @@ -101,7 +101,7 @@ void describe('Guest Stay Account', () => { data: { guestStayAccountId, groupCheckoutId: undefined, - reason: 'NotOpened', + reason: 'NotCheckedIn', failedAt: now, }, }, @@ -491,7 +491,7 @@ void describe('Guest Stay Account', () => { data: { guestStayAccountId, groupCheckoutId: undefined, - reason: 'NotOpened', + reason: 'NotCheckedIn', failedAt: now, }, }, diff --git a/src/guestStayAccounts/guestStayAccount.ts b/src/guestStayAccounts/guestStayAccount.ts index e523967..8534639 100644 --- a/src/guestStayAccounts/guestStayAccount.ts +++ b/src/guestStayAccounts/guestStayAccount.ts @@ -47,7 +47,7 @@ export type GuestCheckoutFailed = Event< 'GuestCheckoutFailed', { guestStayAccountId: string; - reason: 'NotOpened' | 'BalanceNotSettled'; + reason: 'NotCheckedIn' | 'BalanceNotSettled'; failedAt: Date; groupCheckoutId?: string; } @@ -66,11 +66,11 @@ export type GuestStayAccountEvent = export type NotExisting = { status: 'NotExisting' }; -export type Opened = { status: 'Opened'; balance: number }; +export type CheckedIn = { status: 'CheckedIn'; balance: number }; export type CheckedOut = { status: 'CheckedOut' }; -export type GuestStayAccount = NotExisting | Opened | CheckedOut; +export type GuestStayAccount = NotExisting | CheckedIn | CheckedOut; export const initialState = (): GuestStayAccount => ({ status: 'NotExisting', @@ -93,11 +93,11 @@ export const evolve = ( switch (type) { case 'GuestCheckedIn': { return state.status === 'NotExisting' - ? { status: 'Opened', balance: 0 } + ? { status: 'CheckedIn', balance: 0 } : state; } case 'ChargeRecorded': { - return state.status === 'Opened' + return state.status === 'CheckedIn' ? { ...state, balance: state.balance - event.amount, @@ -105,7 +105,7 @@ export const evolve = ( : state; } case 'PaymentRecorded': { - return state.status === 'Opened' + return state.status === 'CheckedIn' ? { ...state, balance: state.balance + event.amount, @@ -113,7 +113,7 @@ export const evolve = ( : state; } case 'GuestCheckedOut': { - return state.status === 'Opened' ? { status: 'CheckedOut' } : state; + return state.status === 'CheckedIn' ? { status: 'CheckedOut' } : state; } case 'GuestCheckoutFailed': { return state; diff --git a/src/guestStayAccounts/guestStayDetails.ts b/src/guestStayAccounts/guestStayDetails.ts index 0898ded..50a8842 100644 --- a/src/guestStayAccounts/guestStayDetails.ts +++ b/src/guestStayAccounts/guestStayDetails.ts @@ -3,11 +3,11 @@ import type { GuestStayAccountEvent } from './guestStayAccount'; export type NotExisting = { status: 'NotExisting' }; -export type Opened = { +export type CheckedIn = { id: string; guestId: string; roomId: string; - status: 'Opened' | 'CheckedOut'; + status: 'CheckedIn' | 'CheckedOut'; balance: number; transactionsCount: number; transactions: { id: string; amount: number }[]; @@ -15,7 +15,7 @@ export type Opened = { checkedOutAt?: Date; }; -export type GuestStayDetails = NotExisting | Opened; +export type GuestStayDetails = NotExisting | CheckedIn; export const initialState = (): GuestStayDetails => ({ status: 'NotExisting', @@ -32,7 +32,7 @@ export const evolve = ( id: event.guestStayAccountId, guestId: event.guestId, roomId: event.roomId, - status: 'Opened', + status: 'CheckedIn', balance: 0, transactionsCount: 0, transactions: [], @@ -41,7 +41,7 @@ export const evolve = ( : state; } case 'ChargeRecorded': { - return state.status === 'Opened' + return state.status === 'CheckedIn' ? { ...state, balance: state.balance - event.amount, @@ -54,7 +54,7 @@ export const evolve = ( : state; } case 'PaymentRecorded': { - return state.status === 'Opened' + return state.status === 'CheckedIn' ? { ...state, balance: state.balance + event.amount, @@ -67,7 +67,7 @@ export const evolve = ( : state; } case 'GuestCheckedOut': { - return state.status === 'Opened' + return state.status === 'CheckedIn' ? { ...state, status: 'CheckedOut', diff --git a/src/index.ts b/src/index.ts index 84f087c..ad2a7af 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ const eventStore = getEventStoreDBEventStore(eventStoreDBClient); const doesGuestStayExist = (_guestId: string, _roomId: string, _day: Date) => Promise.resolve(true); -const shoppingCarts = guestStayAccountsApi( +const guestStayAccounts = guestStayAccountsApi( eventStore, doesGuestStayExist, (prefix) => `${prefix}-${randomUUID()}`, @@ -21,7 +21,7 @@ const shoppingCarts = guestStayAccountsApi( ); const application: Application = getApplication({ - apis: [shoppingCarts], + apis: [guestStayAccounts], }); startAPI(application);