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 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,CommandHandlers:i,Projections:a,Reactions:o,onReactionError:s}=e,c=n(a),l=n(o),u=r(i);return{async dispatch(e,n){try{let r=u.transform(e);await t.append(r);let i=c.resolve(r.aggregateType,r.name);await Promise.all(i.map(e=>e.project(r))),l.resolve(r.aggregateType,r.name).forEach(e=>{e.on(r).catch(t=>{let n=t instanceof Error?t:Error(String(t));s&&s({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;
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
@@ -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 { ICommandHandler } from \"./core/ICommandHandler\";\r\nimport { IProjection } from \"./core/IProjection\";\r\nimport { IReaction } from \"./core/IReaction\";\r\nimport { IReactionError } from \"./core/IReactionError\";\r\nimport { IService } from \"./IService\";\r\n\r\nexport const createService = (definition: {\r\n EventStore: IEventStore;\r\n CommandHandlers: ICommandHandler[];\r\n Projections: IProjection[];\r\n Reactions: IReaction[];\r\n onReactionError?: (context: IReactionError) => void;\r\n}): IService => {\r\n const { EventStore, CommandHandlers, Projections, Reactions, onReactionError } = definition;\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,GAMd,CACd,GAAM,CAAE,aAAY,kBAAiB,cAAa,YAAW,mBAAoB,EAG3E,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,ECvDU,GAAY,GAAG,IAC1B,EAAK,QAAQ,GAAO,OAAO,OAAO,EAAI,CAAC,CAE5B,OAAA,EAAA,EAAA,SAAmC"}
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
- CommandHandlers: ICommandHandler[];
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
@@ -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;;;cCZ9D,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,eAAA,EAAiB,eAAA;EACjB,WAAA,EAAa,WAAA;EACb,SAAA,EAAW,SAAA;EACX,eAAA,IAAmB,OAAA,EAAS,cAAA;AAAA,MAC1B,QAAA;;;cCfS,KAAA,SAAe,IAAA,EAAM,MAAA,SAAe,CAAA,QAAO,CAAA;AAAA,cAG3C,UAAA"}
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
- CommandHandlers: ICommandHandler[];
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
@@ -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;;;cCZ9D,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,eAAA,EAAiB,eAAA;EACjB,WAAA,EAAa,WAAA;EACb,SAAA,EAAW,SAAA;EACX,eAAA,IAAmB,OAAA,EAAS,cAAA;AAAA,MAC1B,QAAA;;;cCfS,KAAA,SAAe,IAAA,EAAM,MAAA,SAAe,CAAA,QAAO,CAAA;AAAA,cAG3C,UAAA"}
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,CommandHandlers:i,Projections:a,Reactions:o,onReactionError:s}=e,c=n(a),l=n(o),u=r(i);return{async dispatch(e,n){try{let r=u.transform(e);await t.append(r);let i=c.resolve(r.aggregateType,r.name);await Promise.all(i.map(e=>e.project(r))),l.resolve(r.aggregateType,r.name).forEach(e=>{e.on(r).catch(t=>{let n=t instanceof Error?t:Error(String(t));s&&s({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};
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
@@ -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 { ICommandHandler } from \"./core/ICommandHandler\";\r\nimport { IProjection } from \"./core/IProjection\";\r\nimport { IReaction } from \"./core/IReaction\";\r\nimport { IReactionError } from \"./core/IReactionError\";\r\nimport { IService } from \"./IService\";\r\n\r\nexport const createService = (definition: {\r\n EventStore: IEventStore;\r\n CommandHandlers: ICommandHandler[];\r\n Projections: IProjection[];\r\n Reactions: IReaction[];\r\n onReactionError?: (context: IReactionError) => void;\r\n}): IService => {\r\n const { EventStore, CommandHandlers, Projections, Reactions, onReactionError } = definition;\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,GAMd,CACd,GAAM,CAAE,aAAY,kBAAiB,cAAa,YAAW,mBAAoB,EAG3E,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,ECvDU,GAAY,GAAG,IAC1B,EAAK,QAAQ,GAAO,OAAO,OAAO,EAAI,CAAC,CAE5B,MAA2B,GAAQ"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atomservices",
3
- "version": "0.15.0",
3
+ "version": "0.15.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",