atomservices 0.14.2 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -35
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +76 -35
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`uuidv7`);const t=t=>{let{
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`uuidv7`);const t=t=>{let{name:n,aggregateType:r}=t,i=({aggregateID:t,payloads:i,_version:a,_createdBy:o,_metadata:s})=>({_id:(0,e.uuidv7)(),name:n,aggregateID:t??(0,e.uuidv7)(),aggregateType:r,payloads:i,_version:a,_createdAt:new Date,_createdBy:o,_metadata:s??{}});return{transform:e=>({action:i,handler:{name:n,aggregateType:r,transform:e}})}},n=e=>{let t={};return e.forEach(e=>{let{aggregateType:n,name:r}=e;t[n]||(t[n]={}),t[n][r]||(t[n][r]=[]),t[n][r].push(e)}),{resolve:(e,n)=>t[e]?.[n]||[]}},r=e=>{let t={};return e.forEach(e=>{if(t[e.aggregateType]||(t[e.aggregateType]={}),t[e.aggregateType][e.name])throw Error(`Duplicate command handler for ${e.aggregateType} and ${e.name}`);t[e.aggregateType][e.name]=e}),{transform:e=>{let n=t[e.aggregateType]?.[e.name];if(!n)throw Error(`No command handler found for ${e.aggregateType} and ${e.name}`);return n.transform(e)}}},i=e=>{let{EventStore:t,ServiceContainers:i,onReactionError:a}=e,o=i.flatMap(e=>e.CommandHandlers),s=i.flatMap(e=>e.Projections),c=i.flatMap(e=>e.Reactions),l=n(s),u=n(c),d=r(o);return{async dispatch(e,n){try{let r=d.transform(e);await t.append(r);let i=l.resolve(r.aggregateType,r.name);await Promise.all(i.map(e=>e.project(r))),u.resolve(r.aggregateType,r.name).forEach(e=>{e.on(r).catch(t=>{let n=t instanceof Error?t:Error(String(t));a&&a({reactionName:e.name,eventName:r.name,eventID:r._id,error:n})})}),n?.()}catch(e){let t=e instanceof Error?e:Error(String(e));throw n?.(t),t}}}},a=(...e)=>e.flatMap(e=>Object.values(e)),o=()=>(0,e.uuidv7)();exports.createService=i,exports.defineCommand=t,exports.generateID=o,exports.remap=a;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/defineCommand.ts","../src/common/composeMapper.ts","../src/common/composeCommandHandlers.ts","../src/createService.ts","../src/util.ts"],"sourcesContent":["import { uuidv7 } from \"uuidv7\";\r\nimport { ICommand } from \"./core/ICommand\";\r\nimport { IEvent } from \"./core/IEvent\";\r\n\r\nexport const defineCommand = <C extends ICommand, E extends IEvent>(definitions: {\r\n name: string;\r\n aggregateType: string;\r\n}) => {\r\n const { name, aggregateType } = definitions;\r\n\r\n const action = ({\r\n aggregateID,\r\n payloads,\r\n _version,\r\n _createdBy,\r\n _metadata,\r\n }: {\r\n aggregateID?: string;\r\n payloads: C[\"payloads\"];\r\n _version: C[\"_version\"];\r\n _createdBy: C[\"_createdBy\"];\r\n _metadata?: C[\"_metadata\"];\r\n }): C => ({\r\n _id: uuidv7(),\r\n name,\r\n aggregateID: aggregateID ?? uuidv7(),\r\n aggregateType,\r\n payloads,\r\n _version,\r\n _createdAt: new Date(),\r\n _createdBy,\r\n _metadata: _metadata ?? ({} as C[\"_metadata\"]),\r\n } as unknown as C);\r\n\r\n return {\r\n transform: (fn: (command: C) => E) => ({\r\n action,\r\n handler: {\r\n name,\r\n aggregateType,\r\n transform: fn,\r\n },\r\n })\r\n };\r\n};\r\n","// src/common/composeMapper.ts\r\n\r\n// A generic utility to compose Mappers for Projections and Reactions based on aggregateType and name\r\nexport const composeMapper = <T extends { aggregateType: string; name: string; }>(components: T[]): {\r\n resolve: (aggregateType: string, name: string) => T[];\r\n} => {\r\n const Registry = {} as Record<string, Record<string, T[]>>;\r\n\r\n components.forEach((component) => {\r\n const { aggregateType, name } = component;\r\n if (!Registry[aggregateType]) {\r\n Registry[aggregateType] = {};\r\n }\r\n\r\n if (!Registry[aggregateType][name]) {\r\n Registry[aggregateType][name] = [];\r\n }\r\n\r\n Registry[aggregateType][name].push(component);\r\n });\r\n\r\n return {\r\n // Resolve returns an array of components matching the aggregateType and name, or an empty array if none found\r\n resolve: (aggregateType: string, name: string): T[] =>\r\n Registry[aggregateType]?.[name] || [],\r\n };\r\n};\r\n","// src/common/composeCommandHandlers.ts\r\n\r\nimport { ICommand } from \"../core/ICommand\";\r\nimport { ICommandHandler } from \"../core/ICommandHandler\";\r\n\r\nexport const composeCommandHandlers = (handlers: ICommandHandler[]) => {\r\n const Registry = {} as Record<string, Record<string, ICommandHandler>>;\r\n\r\n handlers.forEach(handler => {\r\n if (!Registry[handler.aggregateType]) {\r\n Registry[handler.aggregateType] = {};\r\n }\r\n\r\n if (Registry[handler.aggregateType][handler.name]) {\r\n throw new Error(`Duplicate command handler for ${handler.aggregateType} and ${handler.name}`);\r\n }\r\n\r\n Registry[handler.aggregateType][handler.name] = handler;\r\n });\r\n\r\n return {\r\n transform: (command: ICommand) => {\r\n const handler = Registry[command.aggregateType]?.[command.name];\r\n\r\n if (!handler) {\r\n throw new Error(`No command handler found for ${command.aggregateType} and ${command.name}`);\r\n }\r\n\r\n return handler.transform(command);\r\n },\r\n };\r\n};\r\n","// src/createService.ts\r\n\r\nimport { composeMapper } from \"./common/composeMapper\";\r\nimport { composeCommandHandlers } from \"./common/composeCommandHandlers\";\r\nimport { IEventStore } from \"./core/IEventStore\";\r\nimport { IProjection } from \"./core/IProjection\";\r\nimport { IReaction } from \"./core/IReaction\";\r\nimport { IReactionError } from \"./core/IReactionError\";\r\nimport { IService } from \"./core/IService\";\r\nimport { IServiceContainer } from \"./core/IServiceContainer\";\r\n\r\nexport const createService = (definition: {\r\n EventStore: IEventStore;\r\n ServiceContainers: IServiceContainer[];\r\n onReactionError?: (context: IReactionError) => void;\r\n}): IService => {\r\n const { EventStore, ServiceContainers, onReactionError } = definition;\r\n\r\n // Flatten command handlers, projections, and reactions from each container\r\n const CommandHandlers = ServiceContainers.flatMap((c) => c.CommandHandlers);\r\n const Projections = ServiceContainers.flatMap((c) => c.Projections);\r\n const Reactions = ServiceContainers.flatMap((c) => c.Reactions);\r\n\r\n // Initialize Mappers\r\n const _ProjectionMapper = composeMapper<IProjection>(Projections);\r\n const _ReactionMapper = composeMapper<IReaction>(Reactions);\r\n const _CommandHandler = composeCommandHandlers(CommandHandlers);\r\n\r\n return {\r\n async dispatch(command, afterHandler): Promise<void> {\r\n try {\r\n const event = _CommandHandler.transform(command);\r\n await EventStore.append(event);\r\n\r\n const projections = _ProjectionMapper.resolve(event.aggregateType, event.name);\r\n await Promise.all(projections.map((p) => p.project(event)));\r\n\r\n const reactions = _ReactionMapper.resolve(event.aggregateType, event.name);\r\n reactions.forEach((r) => {\r\n r.on(event).catch((error) => {\r\n const wrappedError = error instanceof Error ? error : new Error(String(error));\r\n if (onReactionError) {\r\n onReactionError({\r\n reactionName: r.name,\r\n eventName: event.name,\r\n eventID: event._id,\r\n error: wrappedError,\r\n });\r\n }\r\n });\r\n });\r\n\r\n // Resolve successful dispatch immediately after state is sync'd\r\n afterHandler?.();\r\n } catch (error) {\r\n const wrappedError = error instanceof Error ? error : new Error(String(error));\r\n afterHandler?.(wrappedError);\r\n throw wrappedError;\r\n }\r\n },\r\n };\r\n};\r\n","import { uuidv7 } from \"uuidv7\";\r\n\r\nexport const remap = <T>(...objs: Record<string, T>[]): T[] =>\r\n objs.flatMap(obj => Object.values(obj));\r\n\r\nexport const generateID = (): string => uuidv7();\r\n"],"mappings":"2FAIA,MAAa,EAAuD,GAG9D,CACJ,GAAM,CAAE,OAAM,iBAAkB,EAE1B,GAAU,CACd,cACA,WACA,WACA,aACA,gBAOQ,CACR,KAAA,EAAA,EAAA,SAAa,CACb,OACA,YAAa,IAAA,EAAA,EAAA,SAAuB,CACpC,gBACA,WACA,WACA,WAAY,IAAI,KAChB,aACA,UAAW,GAAc,EAAE,CAC5B,EAED,MAAO,CACL,UAAY,IAA2B,CACrC,SACA,QAAS,CACP,OACA,gBACA,UAAW,EACZ,CACF,EACF,ECxCU,EAAqE,GAE7E,CACH,IAAM,EAAW,EAAE,CAenB,OAbA,EAAW,QAAS,GAAc,CAChC,GAAM,CAAE,gBAAe,QAAS,EAC3B,EAAS,KACZ,EAAS,GAAiB,EAAE,EAGzB,EAAS,GAAe,KAC3B,EAAS,GAAe,GAAQ,EAAE,EAGpC,EAAS,GAAe,GAAM,KAAK,EAAU,EAC7C,CAEK,CAEL,SAAU,EAAuB,IAC/B,EAAS,KAAiB,IAAS,EAAE,CACxC,ECpBU,EAA0B,GAAgC,CACrE,IAAM,EAAW,EAAE,CAcnB,OAZA,EAAS,QAAQ,GAAW,CAK1B,GAJK,EAAS,EAAQ,iBACpB,EAAS,EAAQ,eAAiB,EAAE,EAGlC,EAAS,EAAQ,eAAe,EAAQ,MAC1C,MAAU,MAAM,iCAAiC,EAAQ,cAAc,OAAO,EAAQ,OAAO,CAG/F,EAAS,EAAQ,eAAe,EAAQ,MAAQ,GAChD,CAEK,CACL,UAAY,GAAsB,CAChC,IAAM,EAAU,EAAS,EAAQ,iBAAiB,EAAQ,MAE1D,GAAI,CAAC,EACH,MAAU,MAAM,gCAAgC,EAAQ,cAAc,OAAO,EAAQ,OAAO,CAG9F,OAAO,EAAQ,UAAU,EAAQ,EAEpC,ECnBU,EAAiB,GAId,CACd,GAAM,CAAE,aAAY,oBAAmB,mBAAoB,EAGrD,EAAkB,EAAkB,QAAS,GAAM,EAAE,gBAAgB,CACrE,EAAc,EAAkB,QAAS,GAAM,EAAE,YAAY,CAC7D,EAAY,EAAkB,QAAS,GAAM,EAAE,UAAU,CAGzD,EAAoB,EAA2B,EAAY,CAC3D,EAAkB,EAAyB,EAAU,CACrD,EAAkB,EAAuB,EAAgB,CAE/D,MAAO,CACL,MAAM,SAAS,EAAS,EAA6B,CACnD,GAAI,CACF,IAAM,EAAQ,EAAgB,UAAU,EAAQ,CAChD,MAAM,EAAW,OAAO,EAAM,CAE9B,IAAM,EAAc,EAAkB,QAAQ,EAAM,cAAe,EAAM,KAAK,CAC9E,MAAM,QAAQ,IAAI,EAAY,IAAK,GAAM,EAAE,QAAQ,EAAM,CAAC,CAAC,CAEzC,EAAgB,QAAQ,EAAM,cAAe,EAAM,KAC5D,CAAC,QAAS,GAAM,CACvB,EAAE,GAAG,EAAM,CAAC,MAAO,GAAU,CAC3B,IAAM,EAAe,aAAiB,MAAQ,EAAY,MAAM,OAAO,EAAM,CAAC,CAC1E,GACF,EAAgB,CACd,aAAc,EAAE,KAChB,UAAW,EAAM,KACjB,QAAS,EAAM,IACf,MAAO,EACR,CAAC,EAEJ,EACF,CAGF,KAAgB,OACT,EAAO,CACd,IAAM,EAAe,aAAiB,MAAQ,EAAY,MAAM,OAAO,EAAM,CAAC,CAE9E,MADA,IAAe,EAAa,CACtB,IAGX,EC1DU,GAAY,GAAG,IAC1B,EAAK,QAAQ,GAAO,OAAO,OAAO,EAAI,CAAC,CAE5B,OAAA,EAAA,EAAA,SAAmC"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/core/IEvent.d.ts
|
|
2
|
-
interface IEvent<Payloads =
|
|
2
|
+
interface IEvent<Payloads extends Record<string, unknown> = {}, Metadata extends Record<string, unknown> = {}> {
|
|
3
3
|
_id: string;
|
|
4
4
|
name: string;
|
|
5
5
|
aggregateID: string;
|
|
@@ -11,6 +11,26 @@ interface IEvent<Payloads = any, Metadata extends Record<string, unknown> = {}>
|
|
|
11
11
|
_metadata: Metadata;
|
|
12
12
|
}
|
|
13
13
|
//#endregion
|
|
14
|
+
//#region src/core/ICommand.d.ts
|
|
15
|
+
interface ICommand<E extends IEvent = IEvent, Payloads = E["payloads"], Metadata = E["_metadata"]> {
|
|
16
|
+
_id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
aggregateID: string;
|
|
19
|
+
aggregateType: string;
|
|
20
|
+
payloads: Payloads;
|
|
21
|
+
_version: number;
|
|
22
|
+
_createdAt: Date;
|
|
23
|
+
_createdBy: string;
|
|
24
|
+
_metadata: Metadata;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/core/ICommandHandler.d.ts
|
|
28
|
+
interface ICommandHandler<Command extends ICommand = ICommand, Event extends IEvent = IEvent> {
|
|
29
|
+
name: string;
|
|
30
|
+
aggregateType: string;
|
|
31
|
+
transform: (command: Command) => Event;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
14
34
|
//#region src/core/IEventStore.d.ts
|
|
15
35
|
interface IEventStore {
|
|
16
36
|
append: (event: IEvent) => Promise<void>;
|
|
@@ -22,10 +42,10 @@ interface IEventStore {
|
|
|
22
42
|
* Responsibility: Update the Read Model.
|
|
23
43
|
* Must be idempotent and focused solely on state representation.
|
|
24
44
|
*/
|
|
25
|
-
interface IProjection<
|
|
26
|
-
type: string;
|
|
45
|
+
interface IProjection<Event extends IEvent = IEvent> {
|
|
27
46
|
name: string;
|
|
28
|
-
|
|
47
|
+
aggregateType: string;
|
|
48
|
+
project: (event: Event) => Promise<void>;
|
|
29
49
|
}
|
|
30
50
|
//#endregion
|
|
31
51
|
//#region src/core/IReaction.d.ts
|
|
@@ -34,10 +54,10 @@ interface IProjection<E extends IEvent = IEvent> {
|
|
|
34
54
|
* Reactions are asynchronous, non-blocking listeners to events.
|
|
35
55
|
* They do NOT update state directly; they trigger external actions or new events.
|
|
36
56
|
*/
|
|
37
|
-
interface IReaction<
|
|
38
|
-
type: string;
|
|
57
|
+
interface IReaction<Event extends IEvent = IEvent> {
|
|
39
58
|
name: string;
|
|
40
|
-
|
|
59
|
+
aggregateType: string;
|
|
60
|
+
on: (event: Event) => Promise<void>;
|
|
41
61
|
}
|
|
42
62
|
//#endregion
|
|
43
63
|
//#region src/core/IReactionError.d.ts
|
|
@@ -54,44 +74,65 @@ interface IReactionError {
|
|
|
54
74
|
* Must calculate the new state immediately without side effects.
|
|
55
75
|
* Used for high-performance Aggregate Rehydration.
|
|
56
76
|
*/
|
|
57
|
-
interface IReducer<
|
|
58
|
-
(state:
|
|
77
|
+
interface IReducer<State> {
|
|
78
|
+
(state: State, event: IEvent): State;
|
|
59
79
|
}
|
|
60
80
|
//#endregion
|
|
61
|
-
//#region src/IService.d.ts
|
|
81
|
+
//#region src/core/IService.d.ts
|
|
62
82
|
interface IService {
|
|
63
83
|
/**
|
|
64
|
-
*
|
|
65
|
-
* *
|
|
66
|
-
*
|
|
67
|
-
*
|
|
84
|
+
* Processes a user intent (Command) through the system lifecycle.
|
|
85
|
+
* * Lifecycle:
|
|
86
|
+
* 1. Resolve: Find the 1-to-1 Command Handler for the given command name and type.
|
|
87
|
+
* 2. Transform: Convert the Command into an Event using a pure handler function.
|
|
88
|
+
* 3. Persist: Append the resulting Event to the Event Store.
|
|
89
|
+
* 4. Project: Update the State Store (Read Models) via Projections.
|
|
90
|
+
* 5. React: Trigger side-effects (e.g., emails, external APIs) via Reactions.
|
|
91
|
+
* * @param command - The ICommand object representing the intent.
|
|
92
|
+
* @param afterHandler - Optional callback executed after the state is synchronized.
|
|
68
93
|
*/
|
|
69
|
-
dispatch: (
|
|
94
|
+
dispatch: (command: ICommand, afterHandler?: (error?: Error) => void) => Promise<void>;
|
|
70
95
|
}
|
|
71
96
|
//#endregion
|
|
72
|
-
//#region src/
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
97
|
+
//#region src/core/IServiceContainer.d.ts
|
|
98
|
+
interface IServiceContainer {
|
|
99
|
+
aggregateType: string;
|
|
100
|
+
CommandHandlers: ICommandHandler[];
|
|
101
|
+
Projections: IProjection[];
|
|
102
|
+
Reactions: IReaction[];
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/defineCommand.d.ts
|
|
106
|
+
declare const defineCommand: <C extends ICommand, E extends IEvent>(definitions: {
|
|
107
|
+
name: string;
|
|
108
|
+
aggregateType: string;
|
|
109
|
+
}) => {
|
|
110
|
+
transform: (fn: (command: C) => E) => {
|
|
111
|
+
action: ({
|
|
112
|
+
aggregateID,
|
|
113
|
+
payloads,
|
|
114
|
+
_version,
|
|
115
|
+
_createdBy,
|
|
116
|
+
_metadata
|
|
117
|
+
}: {
|
|
118
|
+
aggregateID?: string;
|
|
119
|
+
payloads: C["payloads"];
|
|
120
|
+
_version: C["_version"];
|
|
121
|
+
_createdBy: C["_createdBy"];
|
|
122
|
+
_metadata?: C["_metadata"];
|
|
123
|
+
}) => C;
|
|
124
|
+
handler: {
|
|
125
|
+
name: string;
|
|
126
|
+
aggregateType: string;
|
|
127
|
+
transform: (command: C) => E;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
};
|
|
89
131
|
//#endregion
|
|
90
132
|
//#region src/createService.d.ts
|
|
91
133
|
declare const createService: (definition: {
|
|
92
134
|
EventStore: IEventStore;
|
|
93
|
-
|
|
94
|
-
Reactions: IReaction[];
|
|
135
|
+
ServiceContainers: IServiceContainer[];
|
|
95
136
|
onReactionError?: (context: IReactionError) => void;
|
|
96
137
|
}) => IService;
|
|
97
138
|
//#endregion
|
|
@@ -99,5 +140,5 @@ declare const createService: (definition: {
|
|
|
99
140
|
declare const remap: <T>(...objs: Record<string, T>[]) => T[];
|
|
100
141
|
declare const generateID: () => string;
|
|
101
142
|
//#endregion
|
|
102
|
-
export { type IEvent, type IEventStore, type IProjection, type IReaction, type IReactionError, type IReducer, type IService,
|
|
143
|
+
export { type ICommand, type ICommandHandler, type IEvent, type IEventStore, type IProjection, type IReaction, type IReactionError, type IReducer, type IService, type IServiceContainer, createService, defineCommand, generateID, remap };
|
|
103
144
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/core/IEvent.ts","../src/core/IEventStore.ts","../src/core/IProjection.ts","../src/core/IReaction.ts","../src/core/IReactionError.ts","../src/core/IReducer.ts","../src/IService.ts","../src/
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/core/IEvent.ts","../src/core/ICommand.ts","../src/core/ICommandHandler.ts","../src/core/IEventStore.ts","../src/core/IProjection.ts","../src/core/IReaction.ts","../src/core/IReactionError.ts","../src/core/IReducer.ts","../src/core/IService.ts","../src/core/IServiceContainer.ts","../src/defineCommand.ts","../src/createService.ts","../src/util.ts"],"mappings":";UAEiB,MAAA,kBAAwB,MAAA,yCAA+C,MAAA;EACtF,GAAA;EACA,IAAA;EACA,WAAA;EACA,aAAA;EACA,QAAA,EAAU,QAAA;EACV,QAAA;EACA,UAAA,EAAY,IAAA;EACZ,UAAA;EACA,SAAA,EAAW,QAAA;AAAA;;;UCPI,QAAA,WAAmB,MAAA,GAAS,MAAA,aAAmB,CAAA,yBAA0B,CAAA;EACxF,GAAA;EACA,IAAA;EACA,WAAA;EACA,aAAA;EACA,QAAA,EAAU,QAAA;EACV,QAAA;EACA,UAAA,EAAY,IAAA;EACZ,UAAA;EACA,SAAA,EAAW,QAAA;AAAA;;;UCVI,eAAA,iBAAgC,QAAA,GAAW,QAAA,gBAAwB,MAAA,GAAS,MAAA;EAC3F,IAAA;EACA,aAAA;EACA,SAAA,GAAY,OAAA,EAAS,OAAA,KAAY,KAAA;AAAA;;;UCFlB,WAAA;EACf,MAAA,GAAS,KAAA,EAAO,MAAA,KAAW,OAAA;AAAA;;;AHH7B;;;;;AAAA,UIOiB,WAAA,eAA0B,MAAA,GAAS,MAAA;EAClD,IAAA;EACA,aAAA;EACA,OAAA,GAAU,KAAA,EAAO,KAAA,KAAU,OAAA;AAAA;;;AJV7B;;;;;AAAA,UKKiB,SAAA,eAAwB,MAAA,GAAS,MAAA;EAChD,IAAA;EACA,aAAA;EACA,EAAA,GAAK,KAAA,EAAO,KAAA,KAAU,OAAA;AAAA;;;UCVP,cAAA;EACf,YAAA;EACA,SAAA;EACA,OAAA;EACA,KAAA,EAAO,KAAA;AAAA;;;ANFT;;;;;AAAA,UOOiB,QAAA;EAAA,CACd,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,MAAA,GAAS,KAAA;AAAA;;;UCNhB,QAAA;ERFM;;;;;;;;;;;EQcrB,QAAA,GAAW,OAAA,EAAS,QAAA,EAAU,YAAA,IAAgB,KAAA,GAAQ,KAAA,cAAmB,OAAA;AAAA;;;UCZ1D,iBAAA;EACf,aAAA;EACA,eAAA,EAAiB,eAAA;EACjB,WAAA,EAAa,WAAA;EACb,SAAA,EAAW,SAAA;AAAA;;;cCJA,aAAA,aAA2B,QAAA,YAAoB,MAAA,EAAQ,WAAA;EAClE,IAAA;EACA,aAAA;AAAA;mBA6BmB,OAAA,EAAS,CAAA,KAAM,CAAA;;;;;;;;MAlBhC,WAAA;MACA,QAAA,EAAU,CAAA;MACV,QAAA,EAAU,CAAA;MACV,UAAA,EAAY,CAAA;MACZ,SAAA,GAAY,CAAA;IAAA,MACV,CAAA;;;;2BAawB,CAAA,KAAM,CAAA;IAAA;EAAA;AAAA;;;cCxBvB,aAAA,GAAiB,UAAA;EAC5B,UAAA,EAAY,WAAA;EACZ,iBAAA,EAAmB,iBAAA;EACnB,eAAA,IAAmB,OAAA,EAAS,cAAA;AAAA,MAC1B,QAAA;;;cCbS,KAAA,SAAe,IAAA,EAAM,MAAA,SAAe,CAAA,QAAO,CAAA;AAAA,cAG3C,UAAA"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/core/IEvent.d.ts
|
|
2
|
-
interface IEvent<Payloads =
|
|
2
|
+
interface IEvent<Payloads extends Record<string, unknown> = {}, Metadata extends Record<string, unknown> = {}> {
|
|
3
3
|
_id: string;
|
|
4
4
|
name: string;
|
|
5
5
|
aggregateID: string;
|
|
@@ -11,6 +11,26 @@ interface IEvent<Payloads = any, Metadata extends Record<string, unknown> = {}>
|
|
|
11
11
|
_metadata: Metadata;
|
|
12
12
|
}
|
|
13
13
|
//#endregion
|
|
14
|
+
//#region src/core/ICommand.d.ts
|
|
15
|
+
interface ICommand<E extends IEvent = IEvent, Payloads = E["payloads"], Metadata = E["_metadata"]> {
|
|
16
|
+
_id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
aggregateID: string;
|
|
19
|
+
aggregateType: string;
|
|
20
|
+
payloads: Payloads;
|
|
21
|
+
_version: number;
|
|
22
|
+
_createdAt: Date;
|
|
23
|
+
_createdBy: string;
|
|
24
|
+
_metadata: Metadata;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/core/ICommandHandler.d.ts
|
|
28
|
+
interface ICommandHandler<Command extends ICommand = ICommand, Event extends IEvent = IEvent> {
|
|
29
|
+
name: string;
|
|
30
|
+
aggregateType: string;
|
|
31
|
+
transform: (command: Command) => Event;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
14
34
|
//#region src/core/IEventStore.d.ts
|
|
15
35
|
interface IEventStore {
|
|
16
36
|
append: (event: IEvent) => Promise<void>;
|
|
@@ -22,10 +42,10 @@ interface IEventStore {
|
|
|
22
42
|
* Responsibility: Update the Read Model.
|
|
23
43
|
* Must be idempotent and focused solely on state representation.
|
|
24
44
|
*/
|
|
25
|
-
interface IProjection<
|
|
26
|
-
type: string;
|
|
45
|
+
interface IProjection<Event extends IEvent = IEvent> {
|
|
27
46
|
name: string;
|
|
28
|
-
|
|
47
|
+
aggregateType: string;
|
|
48
|
+
project: (event: Event) => Promise<void>;
|
|
29
49
|
}
|
|
30
50
|
//#endregion
|
|
31
51
|
//#region src/core/IReaction.d.ts
|
|
@@ -34,10 +54,10 @@ interface IProjection<E extends IEvent = IEvent> {
|
|
|
34
54
|
* Reactions are asynchronous, non-blocking listeners to events.
|
|
35
55
|
* They do NOT update state directly; they trigger external actions or new events.
|
|
36
56
|
*/
|
|
37
|
-
interface IReaction<
|
|
38
|
-
type: string;
|
|
57
|
+
interface IReaction<Event extends IEvent = IEvent> {
|
|
39
58
|
name: string;
|
|
40
|
-
|
|
59
|
+
aggregateType: string;
|
|
60
|
+
on: (event: Event) => Promise<void>;
|
|
41
61
|
}
|
|
42
62
|
//#endregion
|
|
43
63
|
//#region src/core/IReactionError.d.ts
|
|
@@ -54,44 +74,65 @@ interface IReactionError {
|
|
|
54
74
|
* Must calculate the new state immediately without side effects.
|
|
55
75
|
* Used for high-performance Aggregate Rehydration.
|
|
56
76
|
*/
|
|
57
|
-
interface IReducer<
|
|
58
|
-
(state:
|
|
77
|
+
interface IReducer<State> {
|
|
78
|
+
(state: State, event: IEvent): State;
|
|
59
79
|
}
|
|
60
80
|
//#endregion
|
|
61
|
-
//#region src/IService.d.ts
|
|
81
|
+
//#region src/core/IService.d.ts
|
|
62
82
|
interface IService {
|
|
63
83
|
/**
|
|
64
|
-
*
|
|
65
|
-
* *
|
|
66
|
-
*
|
|
67
|
-
*
|
|
84
|
+
* Processes a user intent (Command) through the system lifecycle.
|
|
85
|
+
* * Lifecycle:
|
|
86
|
+
* 1. Resolve: Find the 1-to-1 Command Handler for the given command name and type.
|
|
87
|
+
* 2. Transform: Convert the Command into an Event using a pure handler function.
|
|
88
|
+
* 3. Persist: Append the resulting Event to the Event Store.
|
|
89
|
+
* 4. Project: Update the State Store (Read Models) via Projections.
|
|
90
|
+
* 5. React: Trigger side-effects (e.g., emails, external APIs) via Reactions.
|
|
91
|
+
* * @param command - The ICommand object representing the intent.
|
|
92
|
+
* @param afterHandler - Optional callback executed after the state is synchronized.
|
|
68
93
|
*/
|
|
69
|
-
dispatch: (
|
|
94
|
+
dispatch: (command: ICommand, afterHandler?: (error?: Error) => void) => Promise<void>;
|
|
70
95
|
}
|
|
71
96
|
//#endregion
|
|
72
|
-
//#region src/
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
97
|
+
//#region src/core/IServiceContainer.d.ts
|
|
98
|
+
interface IServiceContainer {
|
|
99
|
+
aggregateType: string;
|
|
100
|
+
CommandHandlers: ICommandHandler[];
|
|
101
|
+
Projections: IProjection[];
|
|
102
|
+
Reactions: IReaction[];
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/defineCommand.d.ts
|
|
106
|
+
declare const defineCommand: <C extends ICommand, E extends IEvent>(definitions: {
|
|
107
|
+
name: string;
|
|
108
|
+
aggregateType: string;
|
|
109
|
+
}) => {
|
|
110
|
+
transform: (fn: (command: C) => E) => {
|
|
111
|
+
action: ({
|
|
112
|
+
aggregateID,
|
|
113
|
+
payloads,
|
|
114
|
+
_version,
|
|
115
|
+
_createdBy,
|
|
116
|
+
_metadata
|
|
117
|
+
}: {
|
|
118
|
+
aggregateID?: string;
|
|
119
|
+
payloads: C["payloads"];
|
|
120
|
+
_version: C["_version"];
|
|
121
|
+
_createdBy: C["_createdBy"];
|
|
122
|
+
_metadata?: C["_metadata"];
|
|
123
|
+
}) => C;
|
|
124
|
+
handler: {
|
|
125
|
+
name: string;
|
|
126
|
+
aggregateType: string;
|
|
127
|
+
transform: (command: C) => E;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
};
|
|
89
131
|
//#endregion
|
|
90
132
|
//#region src/createService.d.ts
|
|
91
133
|
declare const createService: (definition: {
|
|
92
134
|
EventStore: IEventStore;
|
|
93
|
-
|
|
94
|
-
Reactions: IReaction[];
|
|
135
|
+
ServiceContainers: IServiceContainer[];
|
|
95
136
|
onReactionError?: (context: IReactionError) => void;
|
|
96
137
|
}) => IService;
|
|
97
138
|
//#endregion
|
|
@@ -99,5 +140,5 @@ declare const createService: (definition: {
|
|
|
99
140
|
declare const remap: <T>(...objs: Record<string, T>[]) => T[];
|
|
100
141
|
declare const generateID: () => string;
|
|
101
142
|
//#endregion
|
|
102
|
-
export { type IEvent, type IEventStore, type IProjection, type IReaction, type IReactionError, type IReducer, type IService,
|
|
143
|
+
export { type ICommand, type ICommandHandler, type IEvent, type IEventStore, type IProjection, type IReaction, type IReactionError, type IReducer, type IService, type IServiceContainer, createService, defineCommand, generateID, remap };
|
|
103
144
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/IEvent.ts","../src/core/IEventStore.ts","../src/core/IProjection.ts","../src/core/IReaction.ts","../src/core/IReactionError.ts","../src/core/IReducer.ts","../src/IService.ts","../src/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/IEvent.ts","../src/core/ICommand.ts","../src/core/ICommandHandler.ts","../src/core/IEventStore.ts","../src/core/IProjection.ts","../src/core/IReaction.ts","../src/core/IReactionError.ts","../src/core/IReducer.ts","../src/core/IService.ts","../src/core/IServiceContainer.ts","../src/defineCommand.ts","../src/createService.ts","../src/util.ts"],"mappings":";UAEiB,MAAA,kBAAwB,MAAA,yCAA+C,MAAA;EACtF,GAAA;EACA,IAAA;EACA,WAAA;EACA,aAAA;EACA,QAAA,EAAU,QAAA;EACV,QAAA;EACA,UAAA,EAAY,IAAA;EACZ,UAAA;EACA,SAAA,EAAW,QAAA;AAAA;;;UCPI,QAAA,WAAmB,MAAA,GAAS,MAAA,aAAmB,CAAA,yBAA0B,CAAA;EACxF,GAAA;EACA,IAAA;EACA,WAAA;EACA,aAAA;EACA,QAAA,EAAU,QAAA;EACV,QAAA;EACA,UAAA,EAAY,IAAA;EACZ,UAAA;EACA,SAAA,EAAW,QAAA;AAAA;;;UCVI,eAAA,iBAAgC,QAAA,GAAW,QAAA,gBAAwB,MAAA,GAAS,MAAA;EAC3F,IAAA;EACA,aAAA;EACA,SAAA,GAAY,OAAA,EAAS,OAAA,KAAY,KAAA;AAAA;;;UCFlB,WAAA;EACf,MAAA,GAAS,KAAA,EAAO,MAAA,KAAW,OAAA;AAAA;;;AHH7B;;;;;AAAA,UIOiB,WAAA,eAA0B,MAAA,GAAS,MAAA;EAClD,IAAA;EACA,aAAA;EACA,OAAA,GAAU,KAAA,EAAO,KAAA,KAAU,OAAA;AAAA;;;AJV7B;;;;;AAAA,UKKiB,SAAA,eAAwB,MAAA,GAAS,MAAA;EAChD,IAAA;EACA,aAAA;EACA,EAAA,GAAK,KAAA,EAAO,KAAA,KAAU,OAAA;AAAA;;;UCVP,cAAA;EACf,YAAA;EACA,SAAA;EACA,OAAA;EACA,KAAA,EAAO,KAAA;AAAA;;;ANFT;;;;;AAAA,UOOiB,QAAA;EAAA,CACd,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,MAAA,GAAS,KAAA;AAAA;;;UCNhB,QAAA;ERFM;;;;;;;;;;;EQcrB,QAAA,GAAW,OAAA,EAAS,QAAA,EAAU,YAAA,IAAgB,KAAA,GAAQ,KAAA,cAAmB,OAAA;AAAA;;;UCZ1D,iBAAA;EACf,aAAA;EACA,eAAA,EAAiB,eAAA;EACjB,WAAA,EAAa,WAAA;EACb,SAAA,EAAW,SAAA;AAAA;;;cCJA,aAAA,aAA2B,QAAA,YAAoB,MAAA,EAAQ,WAAA;EAClE,IAAA;EACA,aAAA;AAAA;mBA6BmB,OAAA,EAAS,CAAA,KAAM,CAAA;;;;;;;;MAlBhC,WAAA;MACA,QAAA,EAAU,CAAA;MACV,QAAA,EAAU,CAAA;MACV,UAAA,EAAY,CAAA;MACZ,SAAA,GAAY,CAAA;IAAA,MACV,CAAA;;;;2BAawB,CAAA,KAAM,CAAA;IAAA;EAAA;AAAA;;;cCxBvB,aAAA,GAAiB,UAAA;EAC5B,UAAA,EAAY,WAAA;EACZ,iBAAA,EAAmB,iBAAA;EACnB,eAAA,IAAmB,OAAA,EAAS,cAAA;AAAA,MAC1B,QAAA;;;cCbS,KAAA,SAAe,IAAA,EAAM,MAAA,SAAe,CAAA,QAAO,CAAA;AAAA,cAG3C,UAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{uuidv7 as e}from"uuidv7";const t=t=>{let{
|
|
1
|
+
import{uuidv7 as e}from"uuidv7";const t=t=>{let{name:n,aggregateType:r}=t,i=({aggregateID:t,payloads:i,_version:a,_createdBy:o,_metadata:s})=>({_id:e(),name:n,aggregateID:t??e(),aggregateType:r,payloads:i,_version:a,_createdAt:new Date,_createdBy:o,_metadata:s??{}});return{transform:e=>({action:i,handler:{name:n,aggregateType:r,transform:e}})}},n=e=>{let t={};return e.forEach(e=>{let{aggregateType:n,name:r}=e;t[n]||(t[n]={}),t[n][r]||(t[n][r]=[]),t[n][r].push(e)}),{resolve:(e,n)=>t[e]?.[n]||[]}},r=e=>{let t={};return e.forEach(e=>{if(t[e.aggregateType]||(t[e.aggregateType]={}),t[e.aggregateType][e.name])throw Error(`Duplicate command handler for ${e.aggregateType} and ${e.name}`);t[e.aggregateType][e.name]=e}),{transform:e=>{let n=t[e.aggregateType]?.[e.name];if(!n)throw Error(`No command handler found for ${e.aggregateType} and ${e.name}`);return n.transform(e)}}},i=e=>{let{EventStore:t,ServiceContainers:i,onReactionError:a}=e,o=i.flatMap(e=>e.CommandHandlers),s=i.flatMap(e=>e.Projections),c=i.flatMap(e=>e.Reactions),l=n(s),u=n(c),d=r(o);return{async dispatch(e,n){try{let r=d.transform(e);await t.append(r);let i=l.resolve(r.aggregateType,r.name);await Promise.all(i.map(e=>e.project(r))),u.resolve(r.aggregateType,r.name).forEach(e=>{e.on(r).catch(t=>{let n=t instanceof Error?t:Error(String(t));a&&a({reactionName:e.name,eventName:r.name,eventID:r._id,error:n})})}),n?.()}catch(e){let t=e instanceof Error?e:Error(String(e));throw n?.(t),t}}}},a=(...e)=>e.flatMap(e=>Object.values(e)),o=()=>e();export{i as createService,t as defineCommand,o as generateID,a as remap};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/defineCommand.ts","../src/common/composeMapper.ts","../src/common/composeCommandHandlers.ts","../src/createService.ts","../src/util.ts"],"sourcesContent":["import { uuidv7 } from \"uuidv7\";\r\nimport { ICommand } from \"./core/ICommand\";\r\nimport { IEvent } from \"./core/IEvent\";\r\n\r\nexport const defineCommand = <C extends ICommand, E extends IEvent>(definitions: {\r\n name: string;\r\n aggregateType: string;\r\n}) => {\r\n const { name, aggregateType } = definitions;\r\n\r\n const action = ({\r\n aggregateID,\r\n payloads,\r\n _version,\r\n _createdBy,\r\n _metadata,\r\n }: {\r\n aggregateID?: string;\r\n payloads: C[\"payloads\"];\r\n _version: C[\"_version\"];\r\n _createdBy: C[\"_createdBy\"];\r\n _metadata?: C[\"_metadata\"];\r\n }): C => ({\r\n _id: uuidv7(),\r\n name,\r\n aggregateID: aggregateID ?? uuidv7(),\r\n aggregateType,\r\n payloads,\r\n _version,\r\n _createdAt: new Date(),\r\n _createdBy,\r\n _metadata: _metadata ?? ({} as C[\"_metadata\"]),\r\n } as unknown as C);\r\n\r\n return {\r\n transform: (fn: (command: C) => E) => ({\r\n action,\r\n handler: {\r\n name,\r\n aggregateType,\r\n transform: fn,\r\n },\r\n })\r\n };\r\n};\r\n","// src/common/composeMapper.ts\r\n\r\n// A generic utility to compose Mappers for Projections and Reactions based on aggregateType and name\r\nexport const composeMapper = <T extends { aggregateType: string; name: string; }>(components: T[]): {\r\n resolve: (aggregateType: string, name: string) => T[];\r\n} => {\r\n const Registry = {} as Record<string, Record<string, T[]>>;\r\n\r\n components.forEach((component) => {\r\n const { aggregateType, name } = component;\r\n if (!Registry[aggregateType]) {\r\n Registry[aggregateType] = {};\r\n }\r\n\r\n if (!Registry[aggregateType][name]) {\r\n Registry[aggregateType][name] = [];\r\n }\r\n\r\n Registry[aggregateType][name].push(component);\r\n });\r\n\r\n return {\r\n // Resolve returns an array of components matching the aggregateType and name, or an empty array if none found\r\n resolve: (aggregateType: string, name: string): T[] =>\r\n Registry[aggregateType]?.[name] || [],\r\n };\r\n};\r\n","// src/common/composeCommandHandlers.ts\r\n\r\nimport { ICommand } from \"../core/ICommand\";\r\nimport { ICommandHandler } from \"../core/ICommandHandler\";\r\n\r\nexport const composeCommandHandlers = (handlers: ICommandHandler[]) => {\r\n const Registry = {} as Record<string, Record<string, ICommandHandler>>;\r\n\r\n handlers.forEach(handler => {\r\n if (!Registry[handler.aggregateType]) {\r\n Registry[handler.aggregateType] = {};\r\n }\r\n\r\n if (Registry[handler.aggregateType][handler.name]) {\r\n throw new Error(`Duplicate command handler for ${handler.aggregateType} and ${handler.name}`);\r\n }\r\n\r\n Registry[handler.aggregateType][handler.name] = handler;\r\n });\r\n\r\n return {\r\n transform: (command: ICommand) => {\r\n const handler = Registry[command.aggregateType]?.[command.name];\r\n\r\n if (!handler) {\r\n throw new Error(`No command handler found for ${command.aggregateType} and ${command.name}`);\r\n }\r\n\r\n return handler.transform(command);\r\n },\r\n };\r\n};\r\n","// src/createService.ts\r\n\r\nimport { composeMapper } from \"./common/composeMapper\";\r\nimport { composeCommandHandlers } from \"./common/composeCommandHandlers\";\r\nimport { IEventStore } from \"./core/IEventStore\";\r\nimport { IProjection } from \"./core/IProjection\";\r\nimport { IReaction } from \"./core/IReaction\";\r\nimport { IReactionError } from \"./core/IReactionError\";\r\nimport { IService } from \"./core/IService\";\r\nimport { IServiceContainer } from \"./core/IServiceContainer\";\r\n\r\nexport const createService = (definition: {\r\n EventStore: IEventStore;\r\n ServiceContainers: IServiceContainer[];\r\n onReactionError?: (context: IReactionError) => void;\r\n}): IService => {\r\n const { EventStore, ServiceContainers, onReactionError } = definition;\r\n\r\n // Flatten command handlers, projections, and reactions from each container\r\n const CommandHandlers = ServiceContainers.flatMap((c) => c.CommandHandlers);\r\n const Projections = ServiceContainers.flatMap((c) => c.Projections);\r\n const Reactions = ServiceContainers.flatMap((c) => c.Reactions);\r\n\r\n // Initialize Mappers\r\n const _ProjectionMapper = composeMapper<IProjection>(Projections);\r\n const _ReactionMapper = composeMapper<IReaction>(Reactions);\r\n const _CommandHandler = composeCommandHandlers(CommandHandlers);\r\n\r\n return {\r\n async dispatch(command, afterHandler): Promise<void> {\r\n try {\r\n const event = _CommandHandler.transform(command);\r\n await EventStore.append(event);\r\n\r\n const projections = _ProjectionMapper.resolve(event.aggregateType, event.name);\r\n await Promise.all(projections.map((p) => p.project(event)));\r\n\r\n const reactions = _ReactionMapper.resolve(event.aggregateType, event.name);\r\n reactions.forEach((r) => {\r\n r.on(event).catch((error) => {\r\n const wrappedError = error instanceof Error ? error : new Error(String(error));\r\n if (onReactionError) {\r\n onReactionError({\r\n reactionName: r.name,\r\n eventName: event.name,\r\n eventID: event._id,\r\n error: wrappedError,\r\n });\r\n }\r\n });\r\n });\r\n\r\n // Resolve successful dispatch immediately after state is sync'd\r\n afterHandler?.();\r\n } catch (error) {\r\n const wrappedError = error instanceof Error ? error : new Error(String(error));\r\n afterHandler?.(wrappedError);\r\n throw wrappedError;\r\n }\r\n },\r\n };\r\n};\r\n","import { uuidv7 } from \"uuidv7\";\r\n\r\nexport const remap = <T>(...objs: Record<string, T>[]): T[] =>\r\n objs.flatMap(obj => Object.values(obj));\r\n\r\nexport const generateID = (): string => uuidv7();\r\n"],"mappings":"gCAIA,MAAa,EAAuD,GAG9D,CACJ,GAAM,CAAE,OAAM,iBAAkB,EAE1B,GAAU,CACd,cACA,WACA,WACA,aACA,gBAOQ,CACR,IAAK,GAAQ,CACb,OACA,YAAa,GAAe,GAAQ,CACpC,gBACA,WACA,WACA,WAAY,IAAI,KAChB,aACA,UAAW,GAAc,EAAE,CAC5B,EAED,MAAO,CACL,UAAY,IAA2B,CACrC,SACA,QAAS,CACP,OACA,gBACA,UAAW,EACZ,CACF,EACF,ECxCU,EAAqE,GAE7E,CACH,IAAM,EAAW,EAAE,CAenB,OAbA,EAAW,QAAS,GAAc,CAChC,GAAM,CAAE,gBAAe,QAAS,EAC3B,EAAS,KACZ,EAAS,GAAiB,EAAE,EAGzB,EAAS,GAAe,KAC3B,EAAS,GAAe,GAAQ,EAAE,EAGpC,EAAS,GAAe,GAAM,KAAK,EAAU,EAC7C,CAEK,CAEL,SAAU,EAAuB,IAC/B,EAAS,KAAiB,IAAS,EAAE,CACxC,ECpBU,EAA0B,GAAgC,CACrE,IAAM,EAAW,EAAE,CAcnB,OAZA,EAAS,QAAQ,GAAW,CAK1B,GAJK,EAAS,EAAQ,iBACpB,EAAS,EAAQ,eAAiB,EAAE,EAGlC,EAAS,EAAQ,eAAe,EAAQ,MAC1C,MAAU,MAAM,iCAAiC,EAAQ,cAAc,OAAO,EAAQ,OAAO,CAG/F,EAAS,EAAQ,eAAe,EAAQ,MAAQ,GAChD,CAEK,CACL,UAAY,GAAsB,CAChC,IAAM,EAAU,EAAS,EAAQ,iBAAiB,EAAQ,MAE1D,GAAI,CAAC,EACH,MAAU,MAAM,gCAAgC,EAAQ,cAAc,OAAO,EAAQ,OAAO,CAG9F,OAAO,EAAQ,UAAU,EAAQ,EAEpC,ECnBU,EAAiB,GAId,CACd,GAAM,CAAE,aAAY,oBAAmB,mBAAoB,EAGrD,EAAkB,EAAkB,QAAS,GAAM,EAAE,gBAAgB,CACrE,EAAc,EAAkB,QAAS,GAAM,EAAE,YAAY,CAC7D,EAAY,EAAkB,QAAS,GAAM,EAAE,UAAU,CAGzD,EAAoB,EAA2B,EAAY,CAC3D,EAAkB,EAAyB,EAAU,CACrD,EAAkB,EAAuB,EAAgB,CAE/D,MAAO,CACL,MAAM,SAAS,EAAS,EAA6B,CACnD,GAAI,CACF,IAAM,EAAQ,EAAgB,UAAU,EAAQ,CAChD,MAAM,EAAW,OAAO,EAAM,CAE9B,IAAM,EAAc,EAAkB,QAAQ,EAAM,cAAe,EAAM,KAAK,CAC9E,MAAM,QAAQ,IAAI,EAAY,IAAK,GAAM,EAAE,QAAQ,EAAM,CAAC,CAAC,CAEzC,EAAgB,QAAQ,EAAM,cAAe,EAAM,KAC5D,CAAC,QAAS,GAAM,CACvB,EAAE,GAAG,EAAM,CAAC,MAAO,GAAU,CAC3B,IAAM,EAAe,aAAiB,MAAQ,EAAY,MAAM,OAAO,EAAM,CAAC,CAC1E,GACF,EAAgB,CACd,aAAc,EAAE,KAChB,UAAW,EAAM,KACjB,QAAS,EAAM,IACf,MAAO,EACR,CAAC,EAEJ,EACF,CAGF,KAAgB,OACT,EAAO,CACd,IAAM,EAAe,aAAiB,MAAQ,EAAY,MAAM,OAAO,EAAM,CAAC,CAE9E,MADA,IAAe,EAAa,CACtB,IAGX,EC1DU,GAAY,GAAG,IAC1B,EAAK,QAAQ,GAAO,OAAO,OAAO,EAAI,CAAC,CAE5B,MAA2B,GAAQ"}
|