Skip to content

Commit e78b91e

Browse files
committed
Add event sourcing types and deciders for cart management functionality
1 parent a85bdd7 commit e78b91e

7 files changed

Lines changed: 120 additions & 2 deletions

File tree

src/libs/types.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export type HasParamWithDiscriminant<
2+
Params extends Array<any>,
3+
DiscriminantKey extends keyof any,
4+
Value extends string
5+
> = Params extends [infer First, ...infer Rest] ? First extends { [K in DiscriminantKey]: Value } ? true
6+
: HasParamWithDiscriminant<Rest, DiscriminantKey, Value>
7+
: false
8+
9+
export type SelectFunctionByDiscriminantValueInParams<
10+
FuncUnion extends (...args: Array<any>) => any,
11+
DiscriminantKey extends keyof any,
12+
Value extends string
13+
> = FuncUnion extends (...args: infer Params) => any
14+
? HasParamWithDiscriminant<Params, DiscriminantKey, Value> extends true ? FuncUnion
15+
: never
16+
: never
17+
18+
export type HasNoNever<T> = { [K in keyof T]: T[K] extends never ? K : never }[keyof T] extends never ? true : false
19+
20+
export type AssertMapShape<
21+
MapType,
22+
KeyUnion extends keyof any,
23+
ValueType
24+
> = MapType extends Record<KeyUnion, ValueType> ? HasNoNever<MapType> extends true ? true
25+
: ["Error: MapType contains 'never' values"]
26+
: ["Error: MapType shape is invalid"]

src/orderManagement/deciders.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type {
2+
AddBillingDetailsCommand,
3+
AddItemToCartCommand,
4+
ExternalCommand,
5+
RemoveItemFromCartCommand
6+
} from "./externalCommands"
7+
import type { BillingDetailsAddedEvent, ItemAddedEvent, ItemRemovedEvent } from "./internalEvents"
8+
import type { NewCartState, OpenCartState } from "./states"
9+
import type { IDecide } from "../functionalEventSourcing/types"
10+
import type { AssertMapShape, SelectFunctionByDiscriminantValueInParams } from "../libs/types"
11+
12+
export type AddItemToCartDecider = IDecide<
13+
AddItemToCartCommand,
14+
NewCartState | OpenCartState,
15+
ItemAddedEvent
16+
>
17+
18+
export type RemoveItemFromCartDecider = IDecide<
19+
RemoveItemFromCartCommand,
20+
OpenCartState,
21+
ItemRemovedEvent
22+
>
23+
24+
export type AddBillingDetailsDecider = IDecide<
25+
AddBillingDetailsCommand,
26+
OpenCartState,
27+
BillingDetailsAddedEvent
28+
>
29+
30+
export type Decider =
31+
| AddItemToCartDecider
32+
| RemoveItemFromCartDecider
33+
34+
export type DeciderMap = {
35+
[K in ExternalCommand["_tag"]]: SelectFunctionByDiscriminantValueInParams<Decider, "_tag", K>
36+
}
37+
const _assertDeciderMapShape: AssertMapShape<DeciderMap, ExternalCommand["_tag"], Decider> = true

src/orderManagement/evolvers.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { BillingDetailsAddedEvent, ItemAddedEvent } from "./internalEvents"
2+
import type { NewCartState, OpenCartState } from "./states"
3+
import type { IEvolve } from "../functionalEventSourcing/types"
4+
5+
export type openCartEvolve = IEvolve<
6+
NewCartState | OpenCartState,
7+
ItemAddedEvent,
8+
OpenCartState
9+
>
10+
11+
export type openCartWithBillingDetailsEvolve = IEvolve<
12+
OpenCartState,
13+
BillingDetailsAddedEvent,
14+
OpenCartState
15+
>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { ICommand } from "../functionalEventSourcing/types"
2+
3+
export interface AddItemToCartCommand extends ICommand {
4+
_tag: "AddItemToCartCommand"
5+
}
6+
7+
export interface RemoveItemFromCartCommand extends ICommand {
8+
_tag: "RemoveItemFromCartCommand"
9+
}
10+
11+
export interface AddBillingDetailsCommand extends ICommand {
12+
_tag: "AddBillingDetailsCommand"
13+
}
14+
15+
export type ExternalCommand =
16+
| AddItemToCartCommand
17+
| RemoveItemFromCartCommand
18+
| AddBillingDetailsCommand
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { IEvent } from "../functionalEventSourcing/types"
2+
3+
export interface ItemAddedEvent extends IEvent {
4+
_tag: "ItemAddedEvent"
5+
}
6+
7+
export interface ItemRemovedEvent extends IEvent {
8+
_tag: "ItemRemovedEvent"
9+
}
10+
11+
export interface BillingDetailsAddedEvent extends IEvent {
12+
_tag: "BillingDetailsAddedEvent"
13+
}

src/orderManagement/states.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { IState } from "../functionalEventSourcing/types"
2+
3+
export interface NewCartState extends IState {
4+
_tag: "NewCartState"
5+
}
6+
7+
export interface OpenCartState extends IState {
8+
_tag: "OpenCartState"
9+
}

tsconfig.base.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"skipLibCheck": true,
1212
"emitDecoratorMetadata": true,
1313
"experimentalDecorators": true,
14-
"moduleResolution": "NodeNext",
14+
"moduleResolution": "bundler",
1515
"lib": ["ES2022", "DOM", "DOM.Iterable"],
1616
"types": [],
1717
"isolatedModules": true,
@@ -35,6 +35,6 @@
3535
"module": "NodeNext",
3636
"incremental": true,
3737
"removeComments": false,
38-
"plugins": [{ "name": "@effect/language-service" }]
38+
"plugins": [{ "name": "@effect/language-service" }],
3939
}
4040
}

0 commit comments

Comments
 (0)