atomservices 0.15.0 → 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 +11 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +11 -5
- 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{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,
|
|
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/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 {
|
|
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
|
@@ -78,7 +78,7 @@ interface IReducer<State> {
|
|
|
78
78
|
(state: State, event: IEvent): State;
|
|
79
79
|
}
|
|
80
80
|
//#endregion
|
|
81
|
-
//#region src/IService.d.ts
|
|
81
|
+
//#region src/core/IService.d.ts
|
|
82
82
|
interface IService {
|
|
83
83
|
/**
|
|
84
84
|
* Processes a user intent (Command) through the system lifecycle.
|
|
@@ -94,6 +94,14 @@ interface IService {
|
|
|
94
94
|
dispatch: (command: ICommand, afterHandler?: (error?: Error) => void) => Promise<void>;
|
|
95
95
|
}
|
|
96
96
|
//#endregion
|
|
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
|
|
97
105
|
//#region src/defineCommand.d.ts
|
|
98
106
|
declare const defineCommand: <C extends ICommand, E extends IEvent>(definitions: {
|
|
99
107
|
name: string;
|
|
@@ -124,9 +132,7 @@ declare const defineCommand: <C extends ICommand, E extends IEvent>(definitions:
|
|
|
124
132
|
//#region src/createService.d.ts
|
|
125
133
|
declare const createService: (definition: {
|
|
126
134
|
EventStore: IEventStore;
|
|
127
|
-
|
|
128
|
-
Projections: IProjection[];
|
|
129
|
-
Reactions: IReaction[];
|
|
135
|
+
ServiceContainers: IServiceContainer[];
|
|
130
136
|
onReactionError?: (context: IReactionError) => void;
|
|
131
137
|
}) => IService;
|
|
132
138
|
//#endregion
|
|
@@ -134,5 +140,5 @@ declare const createService: (definition: {
|
|
|
134
140
|
declare const remap: <T>(...objs: Record<string, T>[]) => T[];
|
|
135
141
|
declare const generateID: () => string;
|
|
136
142
|
//#endregion
|
|
137
|
-
export { type ICommand, type ICommandHandler, type IEvent, type IEventStore, type IProjection, type IReaction, type IReactionError, type IReducer, type IService, createService, defineCommand, generateID, remap };
|
|
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 };
|
|
138
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/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/IService.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;;;
|
|
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
|
@@ -78,7 +78,7 @@ interface IReducer<State> {
|
|
|
78
78
|
(state: State, event: IEvent): State;
|
|
79
79
|
}
|
|
80
80
|
//#endregion
|
|
81
|
-
//#region src/IService.d.ts
|
|
81
|
+
//#region src/core/IService.d.ts
|
|
82
82
|
interface IService {
|
|
83
83
|
/**
|
|
84
84
|
* Processes a user intent (Command) through the system lifecycle.
|
|
@@ -94,6 +94,14 @@ interface IService {
|
|
|
94
94
|
dispatch: (command: ICommand, afterHandler?: (error?: Error) => void) => Promise<void>;
|
|
95
95
|
}
|
|
96
96
|
//#endregion
|
|
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
|
|
97
105
|
//#region src/defineCommand.d.ts
|
|
98
106
|
declare const defineCommand: <C extends ICommand, E extends IEvent>(definitions: {
|
|
99
107
|
name: string;
|
|
@@ -124,9 +132,7 @@ declare const defineCommand: <C extends ICommand, E extends IEvent>(definitions:
|
|
|
124
132
|
//#region src/createService.d.ts
|
|
125
133
|
declare const createService: (definition: {
|
|
126
134
|
EventStore: IEventStore;
|
|
127
|
-
|
|
128
|
-
Projections: IProjection[];
|
|
129
|
-
Reactions: IReaction[];
|
|
135
|
+
ServiceContainers: IServiceContainer[];
|
|
130
136
|
onReactionError?: (context: IReactionError) => void;
|
|
131
137
|
}) => IService;
|
|
132
138
|
//#endregion
|
|
@@ -134,5 +140,5 @@ declare const createService: (definition: {
|
|
|
134
140
|
declare const remap: <T>(...objs: Record<string, T>[]) => T[];
|
|
135
141
|
declare const generateID: () => string;
|
|
136
142
|
//#endregion
|
|
137
|
-
export { type ICommand, type ICommandHandler, type IEvent, type IEventStore, type IProjection, type IReaction, type IReactionError, type IReducer, type IService, createService, defineCommand, generateID, remap };
|
|
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 };
|
|
138
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/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/IService.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;;;
|
|
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{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,
|
|
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/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 {
|
|
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"}
|