atomservices 0.12.0-alpha.2 → 0.12.0-alpha.4
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/README.md +103 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.mts → index.d.cts} +11 -12
- package/dist/index.d.ts +11 -12
- package/dist/index.js +1 -101
- package/dist/index.js.map +1 -1
- package/package.json +17 -13
- package/dist/index.mjs +0 -73
- package/dist/index.mjs.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# atomservices
|
|
2
|
+
|
|
3
|
+
A lightweight, strictly-typed Event Sourcing toolkit for Node.js and TypeScript. Designed for high-performance aggregate rehydration and flexible consistency models.
|
|
4
|
+
|
|
5
|
+
## Core Architecture
|
|
6
|
+
|
|
7
|
+
**atomservices** manages the lifecycle of a domain event through a structured pipeline that ensures data integrity and consistency.
|
|
8
|
+
|
|
9
|
+
1. **Event Definition**: Define strictly typed schemas for payloads and metadata using `IEvent`.
|
|
10
|
+
2. **Persistence**: Events are first appended to the **Event Store** (The Source of Truth).
|
|
11
|
+
3. **Notification**: Once stored, events are distributed via the **Event Bus** to registered **Handlers** for side effects.
|
|
12
|
+
|
|
13
|
+
## Consistency Models
|
|
14
|
+
|
|
15
|
+
The library's `dispatch` method is designed to support both Eventual and Strong consistency models depending on your business requirements.
|
|
16
|
+
|
|
17
|
+
### 1. Strong Consistency
|
|
18
|
+
|
|
19
|
+
If you need to ensure that all side effects (handlers) have completed successfully before proceeding, use the `notified` callback. This "upgrades" the asynchronous bus into a strongly consistent flow.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// Achieving Strong Consistency
|
|
23
|
+
await new Promise<void>((resolve, reject) => {
|
|
24
|
+
service.dispatch(myEvent, (err) => {
|
|
25
|
+
if (err) reject(err); // Fails if Store OR Handlers fail
|
|
26
|
+
else resolve(); // Success: Stored AND Handled
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Eventual Consistency
|
|
33
|
+
|
|
34
|
+
If you only care that the event is safely persisted and want handlers to run in the background, simply `await` the dispatch without a callback.
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// Achieving Eventual Consistency
|
|
38
|
+
await service.dispatch(myEvent);
|
|
39
|
+
// Resolves as soon as the Store appends the event.
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
### 1. Define an Event
|
|
48
|
+
|
|
49
|
+
Use `EventBuilder` to create a type-safe factory. It handles `_id` and `_createdAt` generation automatically.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { IEvent, EventBuilder } from 'atomservices';
|
|
53
|
+
|
|
54
|
+
interface UserCreated extends IEvent<{ email: string }> {}
|
|
55
|
+
|
|
56
|
+
const buildUserCreated = EventBuilder<UserCreated>({
|
|
57
|
+
EventName: "UserCreated",
|
|
58
|
+
AggregateType: "User"
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Initialize the Service
|
|
64
|
+
|
|
65
|
+
The `createService` function initializes your infrastructure lazily and wires up handlers to the bus.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { createService, InstantEventBus } from 'atomservices';
|
|
69
|
+
|
|
70
|
+
const service = createService({
|
|
71
|
+
EventStore: myEventStore, // Implements IEventStore
|
|
72
|
+
EventBus: new InstantEventBus(), // Local memory implementation
|
|
73
|
+
EventHandlers: [myHandler] // List of IEventHandler
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 3. Dispatch an Event
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
await service.dispatch(buildUserCreated({
|
|
82
|
+
_version: 1,
|
|
83
|
+
_createdBy: "admin-uuid",
|
|
84
|
+
payloads: { email: "user@example.com" }
|
|
85
|
+
}));
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## API Reference
|
|
92
|
+
|
|
93
|
+
* **`IEvent`**: The core data contract.
|
|
94
|
+
* **`EventBuilder`**: Factory pattern with automatic UUID and timestamp generation.
|
|
95
|
+
* **`createService`**: Orchestrates the persistence and publication flow.
|
|
96
|
+
* **`InstantEventBus`**: High-performance local memory event bus using `Promise.all` for handler execution.
|
|
97
|
+
* **`IReducer`**: Pure function type for aggregate state rehydration.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
ISC
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var p=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var f=Object.prototype.hasOwnProperty;var u=(r,e)=>{for(var t in e)p(r,t,{get:e[t],enumerable:!0})},h=(r,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of l(e))!f.call(r,n)&&n!==t&&p(r,n,{get:()=>e[n],enumerable:!(a=d(e,n))||a.enumerable});return r};var y=r=>h(p({},"__esModule",{value:!0}),r);var S={};u(S,{EventBuilder:()=>g,InstantEventBus:()=>m,createService:()=>c,generateUUID:()=>s});module.exports=y(S);var c=r=>{let{EventStore:e,EventHandlers:t,EventBus:a}=r,n,E=async()=>(await e.init(),t.forEach(o=>a.subscribe(o)),{async dispatch(o,i){await e.append(o),a.publish(o).then(()=>{i&&i()}).catch(v=>{let I=v instanceof Error?v:new Error(String(v));i&&i(I)})}});return{async dispatch(o,i){return n||(n=E()),(await n).dispatch(o,i)}}};var s=()=>globalThis.crypto?.randomUUID?.()||Math.random().toString(36).substring(2);var g=r=>{let{EventName:e,AggregateType:t,EventIdentifier:a=s,AggregateIdentifier:n=s}=r;return({aggregateID:E,_metadata:o,...i})=>({...i,_id:a(),name:e,aggregateType:t,aggregateID:E??n(),_metadata:o??{},_createdAt:new Date})};var m=class{handlers=new Map;async connect(){console.log("## Instant Event Bus (using local memory) Connected ##")}subscribe(e){let t=this.handlers.get(e.name)||[];t.push(e),this.handlers.set(e.name,t)}async publish(e){let t=this.handlers.get(e.name)||[];t.length>0&&await Promise.all(t.map(a=>a.handle(e)))}};0&&(module.exports={EventBuilder,InstantEventBus,createService,generateUUID});
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/createService.ts","../src/generateUUID.ts","../src/EventBuilder.ts","../src/InstantEventBus.ts"],"sourcesContent":["export type { IEvent } from \"./IEvent\";\r\nexport type { IEventBus } from \"./IEventBus\";\r\nexport type { IEventHandler } from \"./IEventHandler\";\r\nexport type { IEventService } from \"./IEventService\";\r\nexport type { IEventStore } from \"./IEventStore\";\r\nexport type { IReducer } from \"./IReducer\";\r\n\r\nexport { createService } from \"./createService\";\r\nexport { EventBuilder } from \"./EventBuilder\";\r\nexport { InstantEventBus } from \"./InstantEventBus\";\r\nexport { generateUUID } from \"./generateUUID\";\r\n","// src/createService.ts\r\n\r\nimport { IEvent } from \"./IEvent\";\r\nimport { IEventBus } from \"./IEventBus\";\r\nimport { IEventHandler } from \"./IEventHandler\";\r\nimport { IEventService } from \"./IEventService\";\r\nimport { IEventStore } from \"./IEventStore\";\r\n\r\nexport const createService = (definition: {\r\n EventStore: IEventStore;\r\n EventHandlers: IEventHandler[];\r\n EventBus: IEventBus;\r\n}): IEventService => {\r\n const { EventStore, EventHandlers, EventBus } = definition;\r\n\r\n let _initPromise: Promise<IEventService> | undefined = undefined;\r\n\r\n const init = async (): Promise<IEventService> => {\r\n await EventStore.init();\r\n\r\n EventHandlers.forEach((handler) => EventBus.subscribe(handler));\r\n\r\n return {\r\n async dispatch(event: IEvent, notified?: (error?: Error) => void): Promise<void> {\r\n await EventStore.append(event);\r\n\r\n EventBus.publish(event)\r\n .then(() => {\r\n if (notified) notified();\r\n })\r\n .catch((error) => {\r\n const wrappedError = error instanceof Error ? error : new Error(String(error));\r\n if (notified) notified(wrappedError);\r\n });\r\n },\r\n };\r\n };\r\n\r\n return {\r\n async dispatch(event: IEvent, notified?: (error?: Error) => void): Promise<void> {\r\n if (!_initPromise) {\r\n _initPromise = init();\r\n }\r\n\r\n const service = await _initPromise;\r\n\r\n return service.dispatch(event, notified);\r\n },\r\n };\r\n};\r\n","export const generateUUID = (): string => globalThis.crypto?.randomUUID?.() || Math.random().toString(36).substring(2);\r\n","// src/EventBuilder.ts\r\n\r\nimport { IEvent } from \"./IEvent\";\r\nimport { generateUUID } from \"./generateUUID\";\r\n\r\nexport const EventBuilder = <T extends IEvent>(definition: {\r\n EventName: string;\r\n AggregateType: string;\r\n AggregateIdentifier?: () => string;\r\n EventIdentifier?: () => string;\r\n}) => {\r\n const {\r\n EventName,\r\n AggregateType,\r\n EventIdentifier = generateUUID,\r\n AggregateIdentifier = generateUUID,\r\n } = definition;\r\n\r\n return ({\r\n aggregateID,\r\n _metadata,\r\n ...props\r\n }: Omit<T, \"_id\" | \"name\" | \"aggregateID\" | \"aggregateType\" | \"_createdAt\" | \"_metadata\"> & {\r\n aggregateID?: string;\r\n _metadata?: T[\"_metadata\"];\r\n }): T => ({\r\n ...props,\r\n _id: EventIdentifier(),\r\n name: EventName,\r\n aggregateType: AggregateType,\r\n aggregateID: aggregateID ?? AggregateIdentifier(),\r\n _metadata: _metadata ?? ({} as T[\"_metadata\"]),\r\n _createdAt: new Date(),\r\n } as T);\r\n}\r\n","// src/InstantEventBus.ts\r\n\r\nimport { IEventBus } from \"./IEventBus\";\r\nimport { IEventHandler } from \"./IEventHandler\";\r\nimport { IEvent } from \"./IEvent\";\r\n\r\nexport class InstantEventBus implements IEventBus {\r\n private handlers = new Map<string, IEventHandler[]>();\r\n\r\n async connect() {\r\n console.log(\"## Instant Event Bus (using local memory) Connected ##\");\r\n }\r\n\r\n subscribe(handler: IEventHandler) {\r\n const list = this.handlers.get(handler.name) || [];\r\n list.push(handler);\r\n this.handlers.set(handler.name, list);\r\n }\r\n\r\n async publish(event: IEvent) {\r\n const list = this.handlers.get(event.name) || [];\r\n\r\n if (list.length > 0) {\r\n await Promise.all(list.map(h => h.handle(event)));\r\n }\r\n }\r\n}\r\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,kBAAAE,EAAA,oBAAAC,EAAA,kBAAAC,EAAA,iBAAAC,IAAA,eAAAC,EAAAN,GCQO,IAAMO,EAAiBC,GAIT,CACnB,GAAM,CAAE,WAAAC,EAAY,cAAAC,EAAe,SAAAC,CAAS,EAAIH,EAE5CI,EAEEC,EAAO,UACX,MAAMJ,EAAW,KAAK,EAEtBC,EAAc,QAASI,GAAYH,EAAS,UAAUG,CAAO,CAAC,EAEvD,CACL,MAAM,SAASC,EAAeC,EAAmD,CAC/E,MAAMP,EAAW,OAAOM,CAAK,EAE7BJ,EAAS,QAAQI,CAAK,EACnB,KAAK,IAAM,CACNC,GAAUA,EAAS,CACzB,CAAC,EACA,MAAOC,GAAU,CAChB,IAAMC,EAAeD,aAAiB,MAAQA,EAAQ,IAAI,MAAM,OAAOA,CAAK,CAAC,EACzED,GAAUA,EAASE,CAAY,CACrC,CAAC,CACL,CACF,GAGF,MAAO,CACL,MAAM,SAASH,EAAeC,EAAmD,CAC/E,OAAKJ,IACHA,EAAeC,EAAK,IAGN,MAAMD,GAEP,SAASG,EAAOC,CAAQ,CACzC,CACF,CACF,ECjDO,IAAMG,EAAe,IAAc,WAAW,QAAQ,aAAa,GAAK,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,ECK9G,IAAMC,EAAkCC,GAKzC,CACJ,GAAM,CACJ,UAAAC,EACA,cAAAC,EACA,gBAAAC,EAAkBC,EAClB,oBAAAC,EAAsBD,CACxB,EAAIJ,EAEJ,MAAO,CAAC,CACN,YAAAM,EACA,UAAAC,EACA,GAAGC,CACL,KAGU,CACR,GAAGA,EACH,IAAKL,EAAgB,EACrB,KAAMF,EACN,cAAeC,EACf,YAAaI,GAAeD,EAAoB,EAChD,UAAWE,GAAc,CAAC,EAC1B,WAAY,IAAI,IAClB,EACF,EC5BO,IAAME,EAAN,KAA2C,CACxC,SAAW,IAAI,IAEvB,MAAM,SAAU,CACd,QAAQ,IAAI,wDAAwD,CACtE,CAEA,UAAUC,EAAwB,CAChC,IAAMC,EAAO,KAAK,SAAS,IAAID,EAAQ,IAAI,GAAK,CAAC,EACjDC,EAAK,KAAKD,CAAO,EACjB,KAAK,SAAS,IAAIA,EAAQ,KAAMC,CAAI,CACtC,CAEA,MAAM,QAAQC,EAAe,CAC3B,IAAMD,EAAO,KAAK,SAAS,IAAIC,EAAM,IAAI,GAAK,CAAC,EAE3CD,EAAK,OAAS,GAChB,MAAM,QAAQ,IAAIA,EAAK,IAAIE,GAAKA,EAAE,OAAOD,CAAK,CAAC,CAAC,CAEpD,CACF","names":["index_exports","__export","EventBuilder","InstantEventBus","createService","generateUUID","__toCommonJS","createService","definition","EventStore","EventHandlers","EventBus","_initPromise","init","handler","event","notified","error","wrappedError","generateUUID","EventBuilder","definition","EventName","AggregateType","EventIdentifier","generateUUID","AggregateIdentifier","aggregateID","_metadata","props","InstantEventBus","handler","list","event","h"]}
|
|
@@ -16,9 +16,9 @@ interface IEventHandler<E extends IEvent = IEvent> {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
interface IEventBus {
|
|
19
|
-
connect
|
|
20
|
-
publish
|
|
21
|
-
subscribe
|
|
19
|
+
connect(): Promise<void>;
|
|
20
|
+
publish(event: IEvent): Promise<void>;
|
|
21
|
+
subscribe(handler: IEventHandler): void;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface IEventService {
|
|
@@ -46,17 +46,14 @@ declare const createService: (definition: {
|
|
|
46
46
|
}) => IEventService;
|
|
47
47
|
|
|
48
48
|
declare const EventBuilder: <T extends IEvent>(definition: {
|
|
49
|
-
EventIdentifier: () => string;
|
|
50
49
|
EventName: string;
|
|
51
|
-
AggregateIdentifier: () => string;
|
|
52
50
|
AggregateType: string;
|
|
53
|
-
|
|
51
|
+
AggregateIdentifier?: () => string;
|
|
52
|
+
EventIdentifier?: () => string;
|
|
53
|
+
}) => ({ aggregateID, _metadata, ...props }: Omit<T, "_id" | "name" | "aggregateID" | "aggregateType" | "_createdAt" | "_metadata"> & {
|
|
54
54
|
aggregateID?: string;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
_createdBy: string;
|
|
58
|
-
_metadata: T["_metadata"];
|
|
59
|
-
} & Partial<Omit<T, "_id" | "name" | "aggregateID" | "aggregateType" | "payloads" | "_version" | "_createdAt" | "_createdBy" | "_metadata">>) => T;
|
|
55
|
+
_metadata?: T["_metadata"];
|
|
56
|
+
}) => T;
|
|
60
57
|
|
|
61
58
|
declare class InstantEventBus implements IEventBus {
|
|
62
59
|
private handlers;
|
|
@@ -65,4 +62,6 @@ declare class InstantEventBus implements IEventBus {
|
|
|
65
62
|
publish(event: IEvent): Promise<void>;
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
declare const generateUUID: () => string;
|
|
66
|
+
|
|
67
|
+
export { EventBuilder, type IEvent, type IEventBus, type IEventHandler, type IEventService, type IEventStore, type IReducer, InstantEventBus, createService, generateUUID };
|
package/dist/index.d.ts
CHANGED
|
@@ -16,9 +16,9 @@ interface IEventHandler<E extends IEvent = IEvent> {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
interface IEventBus {
|
|
19
|
-
connect
|
|
20
|
-
publish
|
|
21
|
-
subscribe
|
|
19
|
+
connect(): Promise<void>;
|
|
20
|
+
publish(event: IEvent): Promise<void>;
|
|
21
|
+
subscribe(handler: IEventHandler): void;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface IEventService {
|
|
@@ -46,17 +46,14 @@ declare const createService: (definition: {
|
|
|
46
46
|
}) => IEventService;
|
|
47
47
|
|
|
48
48
|
declare const EventBuilder: <T extends IEvent>(definition: {
|
|
49
|
-
EventIdentifier: () => string;
|
|
50
49
|
EventName: string;
|
|
51
|
-
AggregateIdentifier: () => string;
|
|
52
50
|
AggregateType: string;
|
|
53
|
-
|
|
51
|
+
AggregateIdentifier?: () => string;
|
|
52
|
+
EventIdentifier?: () => string;
|
|
53
|
+
}) => ({ aggregateID, _metadata, ...props }: Omit<T, "_id" | "name" | "aggregateID" | "aggregateType" | "_createdAt" | "_metadata"> & {
|
|
54
54
|
aggregateID?: string;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
_createdBy: string;
|
|
58
|
-
_metadata: T["_metadata"];
|
|
59
|
-
} & Partial<Omit<T, "_id" | "name" | "aggregateID" | "aggregateType" | "payloads" | "_version" | "_createdAt" | "_createdBy" | "_metadata">>) => T;
|
|
55
|
+
_metadata?: T["_metadata"];
|
|
56
|
+
}) => T;
|
|
60
57
|
|
|
61
58
|
declare class InstantEventBus implements IEventBus {
|
|
62
59
|
private handlers;
|
|
@@ -65,4 +62,6 @@ declare class InstantEventBus implements IEventBus {
|
|
|
65
62
|
publish(event: IEvent): Promise<void>;
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
declare const generateUUID: () => string;
|
|
66
|
+
|
|
67
|
+
export { EventBuilder, type IEvent, type IEventBus, type IEventHandler, type IEventService, type IEventStore, type IReducer, InstantEventBus, createService, generateUUID };
|
package/dist/index.js
CHANGED
|
@@ -1,102 +1,2 @@
|
|
|
1
|
-
"
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
EventBuilder: () => EventBuilder,
|
|
24
|
-
InstantEventBus: () => InstantEventBus,
|
|
25
|
-
createService: () => createService
|
|
26
|
-
});
|
|
27
|
-
module.exports = __toCommonJS(index_exports);
|
|
28
|
-
|
|
29
|
-
// src/createService.ts
|
|
30
|
-
var createService = (definition) => (({
|
|
31
|
-
EventStore,
|
|
32
|
-
EventHandlers,
|
|
33
|
-
EventBus
|
|
34
|
-
}) => {
|
|
35
|
-
let _SERVICE;
|
|
36
|
-
const resolveInstance = async () => {
|
|
37
|
-
if (!_SERVICE) {
|
|
38
|
-
await EventStore.init();
|
|
39
|
-
_SERVICE = (() => {
|
|
40
|
-
const EventBusInstance = EventBus;
|
|
41
|
-
EventHandlers.forEach((handler) => EventBusInstance.subscribe(handler));
|
|
42
|
-
return {
|
|
43
|
-
async dispatch(event, notified) {
|
|
44
|
-
await EventStore.append(event);
|
|
45
|
-
EventBusInstance.publish(event).then(() => {
|
|
46
|
-
if (notified) notified();
|
|
47
|
-
}).catch((error) => {
|
|
48
|
-
console.error("Error publishing event:", error);
|
|
49
|
-
if (notified) notified(error instanceof Error ? error : new Error(String(error)));
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
})();
|
|
54
|
-
return _SERVICE;
|
|
55
|
-
}
|
|
56
|
-
return _SERVICE;
|
|
57
|
-
};
|
|
58
|
-
return {
|
|
59
|
-
async dispatch(event) {
|
|
60
|
-
const service = await resolveInstance();
|
|
61
|
-
return service.dispatch(event);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
})(definition);
|
|
65
|
-
|
|
66
|
-
// src/EventBuilder.ts
|
|
67
|
-
var EventBuilder = (definition) => (props) => ({
|
|
68
|
-
...props,
|
|
69
|
-
_id: definition.EventIdentifier(),
|
|
70
|
-
name: definition.EventName,
|
|
71
|
-
aggregateID: props.aggregateID || definition.AggregateIdentifier(),
|
|
72
|
-
aggregateType: definition.AggregateType,
|
|
73
|
-
_createdAt: /* @__PURE__ */ new Date()
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// src/InstantEventBus.ts
|
|
77
|
-
var InstantEventBus = class {
|
|
78
|
-
constructor() {
|
|
79
|
-
this.handlers = /* @__PURE__ */ new Map();
|
|
80
|
-
}
|
|
81
|
-
async connect() {
|
|
82
|
-
console.log("## Instant Event Bus (using local memory) Connected ##");
|
|
83
|
-
}
|
|
84
|
-
subscribe(handler) {
|
|
85
|
-
const list = this.handlers.get(handler.name) || [];
|
|
86
|
-
list.push(handler);
|
|
87
|
-
this.handlers.set(handler.name, list);
|
|
88
|
-
}
|
|
89
|
-
async publish(event) {
|
|
90
|
-
const list = this.handlers.get(event.name) || [];
|
|
91
|
-
if (list.length > 0) {
|
|
92
|
-
await Promise.all(list.map((h) => h.handle(event)));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
97
|
-
0 && (module.exports = {
|
|
98
|
-
EventBuilder,
|
|
99
|
-
InstantEventBus,
|
|
100
|
-
createService
|
|
101
|
-
});
|
|
1
|
+
var c=i=>{let{EventStore:e,EventHandlers:t,EventBus:a}=i,o,m=async()=>(await e.init(),t.forEach(r=>a.subscribe(r)),{async dispatch(r,n){await e.append(r),a.publish(r).then(()=>{n&&n()}).catch(s=>{let p=s instanceof Error?s:new Error(String(s));n&&n(p)})}});return{async dispatch(r,n){return o||(o=m()),(await o).dispatch(r,n)}}};var v=()=>globalThis.crypto?.randomUUID?.()||Math.random().toString(36).substring(2);var g=i=>{let{EventName:e,AggregateType:t,EventIdentifier:a=v,AggregateIdentifier:o=v}=i;return({aggregateID:m,_metadata:r,...n})=>({...n,_id:a(),name:e,aggregateType:t,aggregateID:m??o(),_metadata:r??{},_createdAt:new Date})};var E=class{handlers=new Map;async connect(){console.log("## Instant Event Bus (using local memory) Connected ##")}subscribe(e){let t=this.handlers.get(e.name)||[];t.push(e),this.handlers.set(e.name,t)}async publish(e){let t=this.handlers.get(e.name)||[];t.length>0&&await Promise.all(t.map(a=>a.handle(e)))}};export{g as EventBuilder,E as InstantEventBus,c as createService,v as generateUUID};
|
|
102
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/
|
|
1
|
+
{"version":3,"sources":["../src/createService.ts","../src/generateUUID.ts","../src/EventBuilder.ts","../src/InstantEventBus.ts"],"sourcesContent":["// src/createService.ts\r\n\r\nimport { IEvent } from \"./IEvent\";\r\nimport { IEventBus } from \"./IEventBus\";\r\nimport { IEventHandler } from \"./IEventHandler\";\r\nimport { IEventService } from \"./IEventService\";\r\nimport { IEventStore } from \"./IEventStore\";\r\n\r\nexport const createService = (definition: {\r\n EventStore: IEventStore;\r\n EventHandlers: IEventHandler[];\r\n EventBus: IEventBus;\r\n}): IEventService => {\r\n const { EventStore, EventHandlers, EventBus } = definition;\r\n\r\n let _initPromise: Promise<IEventService> | undefined = undefined;\r\n\r\n const init = async (): Promise<IEventService> => {\r\n await EventStore.init();\r\n\r\n EventHandlers.forEach((handler) => EventBus.subscribe(handler));\r\n\r\n return {\r\n async dispatch(event: IEvent, notified?: (error?: Error) => void): Promise<void> {\r\n await EventStore.append(event);\r\n\r\n EventBus.publish(event)\r\n .then(() => {\r\n if (notified) notified();\r\n })\r\n .catch((error) => {\r\n const wrappedError = error instanceof Error ? error : new Error(String(error));\r\n if (notified) notified(wrappedError);\r\n });\r\n },\r\n };\r\n };\r\n\r\n return {\r\n async dispatch(event: IEvent, notified?: (error?: Error) => void): Promise<void> {\r\n if (!_initPromise) {\r\n _initPromise = init();\r\n }\r\n\r\n const service = await _initPromise;\r\n\r\n return service.dispatch(event, notified);\r\n },\r\n };\r\n};\r\n","export const generateUUID = (): string => globalThis.crypto?.randomUUID?.() || Math.random().toString(36).substring(2);\r\n","// src/EventBuilder.ts\r\n\r\nimport { IEvent } from \"./IEvent\";\r\nimport { generateUUID } from \"./generateUUID\";\r\n\r\nexport const EventBuilder = <T extends IEvent>(definition: {\r\n EventName: string;\r\n AggregateType: string;\r\n AggregateIdentifier?: () => string;\r\n EventIdentifier?: () => string;\r\n}) => {\r\n const {\r\n EventName,\r\n AggregateType,\r\n EventIdentifier = generateUUID,\r\n AggregateIdentifier = generateUUID,\r\n } = definition;\r\n\r\n return ({\r\n aggregateID,\r\n _metadata,\r\n ...props\r\n }: Omit<T, \"_id\" | \"name\" | \"aggregateID\" | \"aggregateType\" | \"_createdAt\" | \"_metadata\"> & {\r\n aggregateID?: string;\r\n _metadata?: T[\"_metadata\"];\r\n }): T => ({\r\n ...props,\r\n _id: EventIdentifier(),\r\n name: EventName,\r\n aggregateType: AggregateType,\r\n aggregateID: aggregateID ?? AggregateIdentifier(),\r\n _metadata: _metadata ?? ({} as T[\"_metadata\"]),\r\n _createdAt: new Date(),\r\n } as T);\r\n}\r\n","// src/InstantEventBus.ts\r\n\r\nimport { IEventBus } from \"./IEventBus\";\r\nimport { IEventHandler } from \"./IEventHandler\";\r\nimport { IEvent } from \"./IEvent\";\r\n\r\nexport class InstantEventBus implements IEventBus {\r\n private handlers = new Map<string, IEventHandler[]>();\r\n\r\n async connect() {\r\n console.log(\"## Instant Event Bus (using local memory) Connected ##\");\r\n }\r\n\r\n subscribe(handler: IEventHandler) {\r\n const list = this.handlers.get(handler.name) || [];\r\n list.push(handler);\r\n this.handlers.set(handler.name, list);\r\n }\r\n\r\n async publish(event: IEvent) {\r\n const list = this.handlers.get(event.name) || [];\r\n\r\n if (list.length > 0) {\r\n await Promise.all(list.map(h => h.handle(event)));\r\n }\r\n }\r\n}\r\n"],"mappings":"AAQO,IAAMA,EAAiBC,GAIT,CACnB,GAAM,CAAE,WAAAC,EAAY,cAAAC,EAAe,SAAAC,CAAS,EAAIH,EAE5CI,EAEEC,EAAO,UACX,MAAMJ,EAAW,KAAK,EAEtBC,EAAc,QAASI,GAAYH,EAAS,UAAUG,CAAO,CAAC,EAEvD,CACL,MAAM,SAASC,EAAeC,EAAmD,CAC/E,MAAMP,EAAW,OAAOM,CAAK,EAE7BJ,EAAS,QAAQI,CAAK,EACnB,KAAK,IAAM,CACNC,GAAUA,EAAS,CACzB,CAAC,EACA,MAAOC,GAAU,CAChB,IAAMC,EAAeD,aAAiB,MAAQA,EAAQ,IAAI,MAAM,OAAOA,CAAK,CAAC,EACzED,GAAUA,EAASE,CAAY,CACrC,CAAC,CACL,CACF,GAGF,MAAO,CACL,MAAM,SAASH,EAAeC,EAAmD,CAC/E,OAAKJ,IACHA,EAAeC,EAAK,IAGN,MAAMD,GAEP,SAASG,EAAOC,CAAQ,CACzC,CACF,CACF,ECjDO,IAAMG,EAAe,IAAc,WAAW,QAAQ,aAAa,GAAK,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,ECK9G,IAAMC,EAAkCC,GAKzC,CACJ,GAAM,CACJ,UAAAC,EACA,cAAAC,EACA,gBAAAC,EAAkBC,EAClB,oBAAAC,EAAsBD,CACxB,EAAIJ,EAEJ,MAAO,CAAC,CACN,YAAAM,EACA,UAAAC,EACA,GAAGC,CACL,KAGU,CACR,GAAGA,EACH,IAAKL,EAAgB,EACrB,KAAMF,EACN,cAAeC,EACf,YAAaI,GAAeD,EAAoB,EAChD,UAAWE,GAAc,CAAC,EAC1B,WAAY,IAAI,IAClB,EACF,EC5BO,IAAME,EAAN,KAA2C,CACxC,SAAW,IAAI,IAEvB,MAAM,SAAU,CACd,QAAQ,IAAI,wDAAwD,CACtE,CAEA,UAAUC,EAAwB,CAChC,IAAMC,EAAO,KAAK,SAAS,IAAID,EAAQ,IAAI,GAAK,CAAC,EACjDC,EAAK,KAAKD,CAAO,EACjB,KAAK,SAAS,IAAIA,EAAQ,KAAMC,CAAI,CACtC,CAEA,MAAM,QAAQC,EAAe,CAC3B,IAAMD,EAAO,KAAK,SAAS,IAAIC,EAAM,IAAI,GAAK,CAAC,EAE3CD,EAAK,OAAS,GAChB,MAAM,QAAQ,IAAIA,EAAK,IAAIE,GAAKA,EAAE,OAAOD,CAAK,CAAC,CAAC,CAEpD,CACF","names":["createService","definition","EventStore","EventHandlers","EventBus","_initPromise","init","handler","event","notified","error","wrappedError","generateUUID","EventBuilder","definition","EventName","AggregateType","EventIdentifier","generateUUID","AggregateIdentifier","aggregateID","_metadata","props","InstantEventBus","handler","list","event","h"]}
|
package/package.json
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atomservices",
|
|
3
|
-
"version": "0.12.0-alpha.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
"version": "0.12.0-alpha.4",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.mjs",
|
|
9
|
+
"require": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
9
12
|
"files": [
|
|
10
|
-
"dist"
|
|
11
|
-
"package.json",
|
|
12
|
-
"README.md"
|
|
13
|
+
"dist"
|
|
13
14
|
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"license": "ISC",
|
|
14
19
|
"author": "Architecode",
|
|
15
|
-
"type": "commonjs",
|
|
16
20
|
"scripts": {
|
|
17
21
|
"build": "tsup",
|
|
18
22
|
"dev": "tsup --watch",
|
|
19
23
|
"test": "vitest",
|
|
20
|
-
"prepublishOnly": "npm run build"
|
|
24
|
+
"prepublishOnly": "npm install && npm run build"
|
|
21
25
|
},
|
|
22
26
|
"devDependencies": {
|
|
23
|
-
"@types/node": "^25.0
|
|
27
|
+
"@types/node": "^25.5.0",
|
|
24
28
|
"tsup": "^8.5.1",
|
|
25
29
|
"typescript": "^5.9.3",
|
|
26
|
-
"vitest": "^4.0
|
|
30
|
+
"vitest": "^4.1.0"
|
|
27
31
|
}
|
|
28
32
|
}
|
package/dist/index.mjs
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// src/createService.ts
|
|
2
|
-
var createService = (definition) => (({
|
|
3
|
-
EventStore,
|
|
4
|
-
EventHandlers,
|
|
5
|
-
EventBus
|
|
6
|
-
}) => {
|
|
7
|
-
let _SERVICE;
|
|
8
|
-
const resolveInstance = async () => {
|
|
9
|
-
if (!_SERVICE) {
|
|
10
|
-
await EventStore.init();
|
|
11
|
-
_SERVICE = (() => {
|
|
12
|
-
const EventBusInstance = EventBus;
|
|
13
|
-
EventHandlers.forEach((handler) => EventBusInstance.subscribe(handler));
|
|
14
|
-
return {
|
|
15
|
-
async dispatch(event, notified) {
|
|
16
|
-
await EventStore.append(event);
|
|
17
|
-
EventBusInstance.publish(event).then(() => {
|
|
18
|
-
if (notified) notified();
|
|
19
|
-
}).catch((error) => {
|
|
20
|
-
console.error("Error publishing event:", error);
|
|
21
|
-
if (notified) notified(error instanceof Error ? error : new Error(String(error)));
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
})();
|
|
26
|
-
return _SERVICE;
|
|
27
|
-
}
|
|
28
|
-
return _SERVICE;
|
|
29
|
-
};
|
|
30
|
-
return {
|
|
31
|
-
async dispatch(event) {
|
|
32
|
-
const service = await resolveInstance();
|
|
33
|
-
return service.dispatch(event);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
})(definition);
|
|
37
|
-
|
|
38
|
-
// src/EventBuilder.ts
|
|
39
|
-
var EventBuilder = (definition) => (props) => ({
|
|
40
|
-
...props,
|
|
41
|
-
_id: definition.EventIdentifier(),
|
|
42
|
-
name: definition.EventName,
|
|
43
|
-
aggregateID: props.aggregateID || definition.AggregateIdentifier(),
|
|
44
|
-
aggregateType: definition.AggregateType,
|
|
45
|
-
_createdAt: /* @__PURE__ */ new Date()
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// src/InstantEventBus.ts
|
|
49
|
-
var InstantEventBus = class {
|
|
50
|
-
constructor() {
|
|
51
|
-
this.handlers = /* @__PURE__ */ new Map();
|
|
52
|
-
}
|
|
53
|
-
async connect() {
|
|
54
|
-
console.log("## Instant Event Bus (using local memory) Connected ##");
|
|
55
|
-
}
|
|
56
|
-
subscribe(handler) {
|
|
57
|
-
const list = this.handlers.get(handler.name) || [];
|
|
58
|
-
list.push(handler);
|
|
59
|
-
this.handlers.set(handler.name, list);
|
|
60
|
-
}
|
|
61
|
-
async publish(event) {
|
|
62
|
-
const list = this.handlers.get(event.name) || [];
|
|
63
|
-
if (list.length > 0) {
|
|
64
|
-
await Promise.all(list.map((h) => h.handle(event)));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
export {
|
|
69
|
-
EventBuilder,
|
|
70
|
-
InstantEventBus,
|
|
71
|
-
createService
|
|
72
|
-
};
|
|
73
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/createService.ts","../src/EventBuilder.ts","../src/InstantEventBus.ts"],"sourcesContent":["// src/createService.ts\r\n\r\nimport { IEvent } from \"./IEvent\";\r\nimport { IEventBus } from \"./IEventBus\";\r\nimport { IEventHandler } from \"./IEventHandler\";\r\nimport { IEventService } from \"./IEventService\";\r\nimport { IEventStore } from \"./IEventStore\";\r\n\r\nexport const createService = (definition: {\r\n EventStore: IEventStore;\r\n EventHandlers: IEventHandler[];\r\n EventBus: IEventBus;\r\n}): IEventService => (({\r\n EventStore,\r\n EventHandlers,\r\n EventBus,\r\n}: {\r\n EventStore: IEventStore;\r\n EventHandlers: IEventHandler[];\r\n EventBus: IEventBus;\r\n}) => {\r\n let _SERVICE: IEventService | undefined;\r\n\r\n const resolveInstance = async (): Promise<IEventService> => {\r\n if (!_SERVICE) {\r\n await EventStore.init();\r\n\r\n _SERVICE = ((): IEventService => {\r\n const EventBusInstance = EventBus;\r\n EventHandlers.forEach((handler: IEventHandler) => EventBusInstance.subscribe(handler));\r\n\r\n return {\r\n async dispatch(event: IEvent, notified?: (error?: Error) => void): Promise<void> {\r\n // Permanent Store (The Truth)\r\n await EventStore.append(event);\r\n\r\n // Publish to Event Bus (Subscribers)\r\n EventBusInstance.publish(event)\r\n .then(() => {\r\n if (notified) notified();\r\n })\r\n .catch((error) => {\r\n console.error(\"Error publishing event:\", error);\r\n if (notified) notified(error instanceof Error ? error : new Error(String(error)));\r\n });\r\n },\r\n };\r\n })();\r\n\r\n return _SERVICE;\r\n }\r\n\r\n return _SERVICE;\r\n };\r\n\r\n return {\r\n async dispatch(event: IEvent): Promise<void> {\r\n const service = await resolveInstance();\r\n\r\n return service.dispatch(event);\r\n },\r\n };\r\n})(definition);\r\n","// src/EventBuilder.ts\r\n\r\nimport { IEvent } from \"./IEvent\";\r\n\r\nexport const EventBuilder = <T extends IEvent>(definition: {\r\n EventIdentifier: () => string; // _id\r\n EventName: string; // name\r\n AggregateIdentifier: () => string; // aggregateID\r\n AggregateType: string; // aggregateType \r\n}) => (props: {\r\n aggregateID?: string;\r\n payloads: T[\"payloads\"];\r\n _version: number;\r\n _createdBy: string;\r\n _metadata: T[\"_metadata\"];\r\n} & Partial<Omit<T, \"_id\" | \"name\" | \"aggregateID\" | \"aggregateType\" | \"payloads\" | \"_version\" | \"_createdAt\" | \"_createdBy\" | \"_metadata\">>): T => ({\r\n ...props,\r\n _id: definition.EventIdentifier(),\r\n name: definition.EventName,\r\n aggregateID: props.aggregateID || definition.AggregateIdentifier(),\r\n aggregateType: definition.AggregateType,\r\n _createdAt: new Date(),\r\n} as T);\r\n","// src/InstantEventBus.ts\r\n\r\nimport { IEventBus } from \"./IEventBus\";\r\nimport { IEventHandler } from \"./IEventHandler\";\r\nimport { IEvent } from \"./IEvent\";\r\n\r\nexport class InstantEventBus implements IEventBus {\r\n private handlers = new Map<string, IEventHandler[]>();\r\n\r\n async connect() {\r\n console.log(\"## Instant Event Bus (using local memory) Connected ##\");\r\n }\r\n\r\n subscribe(handler: IEventHandler) {\r\n const list = this.handlers.get(handler.name) || [];\r\n list.push(handler);\r\n this.handlers.set(handler.name, list);\r\n }\r\n\r\n async publish(event: IEvent) {\r\n const list = this.handlers.get(event.name) || [];\r\n\r\n if (list.length > 0) {\r\n await Promise.all(list.map(h => h.handle(event)));\r\n }\r\n }\r\n}\r\n"],"mappings":";AAQO,IAAM,gBAAgB,CAAC,gBAIR,CAAC;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AACF,MAIM;AACJ,MAAI;AAEJ,QAAM,kBAAkB,YAAoC;AAC1D,QAAI,CAAC,UAAU;AACb,YAAM,WAAW,KAAK;AAEtB,kBAAY,MAAqB;AAC/B,cAAM,mBAAmB;AACzB,sBAAc,QAAQ,CAAC,YAA2B,iBAAiB,UAAU,OAAO,CAAC;AAErF,eAAO;AAAA,UACL,MAAM,SAAS,OAAe,UAAmD;AAE/E,kBAAM,WAAW,OAAO,KAAK;AAG7B,6BAAiB,QAAQ,KAAK,EAC3B,KAAK,MAAM;AACV,kBAAI,SAAU,UAAS;AAAA,YACzB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,sBAAQ,MAAM,2BAA2B,KAAK;AAC9C,kBAAI,SAAU,UAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,YAClF,CAAC;AAAA,UACL;AAAA,QACF;AAAA,MACF,GAAG;AAEH,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM,SAAS,OAA8B;AAC3C,YAAM,UAAU,MAAM,gBAAgB;AAEtC,aAAO,QAAQ,SAAS,KAAK;AAAA,IAC/B;AAAA,EACF;AACF,GAAG,UAAU;;;AC1DN,IAAM,eAAe,CAAmB,eAKzC,CAAC,WAM8I;AAAA,EACnJ,GAAG;AAAA,EACH,KAAK,WAAW,gBAAgB;AAAA,EAChC,MAAM,WAAW;AAAA,EACjB,aAAa,MAAM,eAAe,WAAW,oBAAoB;AAAA,EACjE,eAAe,WAAW;AAAA,EAC1B,YAAY,oBAAI,KAAK;AACvB;;;AChBO,IAAM,kBAAN,MAA2C;AAAA,EAA3C;AACL,SAAQ,WAAW,oBAAI,IAA6B;AAAA;AAAA,EAEpD,MAAM,UAAU;AACd,YAAQ,IAAI,wDAAwD;AAAA,EACtE;AAAA,EAEA,UAAU,SAAwB;AAChC,UAAM,OAAO,KAAK,SAAS,IAAI,QAAQ,IAAI,KAAK,CAAC;AACjD,SAAK,KAAK,OAAO;AACjB,SAAK,SAAS,IAAI,QAAQ,MAAM,IAAI;AAAA,EACtC;AAAA,EAEA,MAAM,QAAQ,OAAe;AAC3B,UAAM,OAAO,KAAK,SAAS,IAAI,MAAM,IAAI,KAAK,CAAC;AAE/C,QAAI,KAAK,SAAS,GAAG;AACnB,YAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,EAAE,OAAO,KAAK,CAAC,CAAC;AAAA,IAClD;AAAA,EACF;AACF;","names":[]}
|