@robinmalfait/event-source 0.0.9 → 0.0.10

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.d.mts CHANGED
@@ -13,10 +13,10 @@ type ApplyConcreteEvents<Events extends EventType> = Events extends EventType<in
13
13
  eventName: T;
14
14
  }>) => void;
15
15
  } : never;
16
- type Lazy<T> = (...args: any[]) => T;
17
- type ApplyLazyEvents<Events extends Lazy<EventType>> = ApplyConcreteEvents<ReturnType<Events>>;
18
- type MaybeLazy<T> = T | Lazy<T>;
19
- type ApplyEvents<Events extends MaybeLazy<EventType> = any> = Events extends Lazy<EventType> ? ApplyLazyEvents<Events> : Events extends EventType ? ApplyConcreteEvents<Events> : never;
16
+ type Lazy$1<T> = (...args: any[]) => T;
17
+ type ApplyLazyEvents<Events extends Lazy$1<EventType>> = ApplyConcreteEvents<ReturnType<Events>>;
18
+ type MaybeLazy$1<T> = T | Lazy$1<T>;
19
+ type ApplyEvents<Events extends MaybeLazy$1<EventType> = any> = Events extends Lazy$1<EventType> ? ApplyLazyEvents<Events> : Events extends EventType ? ApplyConcreteEvents<Events> : never;
20
20
  declare abstract class Aggregate {
21
21
  #private;
22
22
  abstract apply: ApplyEvents;
@@ -43,6 +43,18 @@ declare function abort<T>(message: string, attributes?: T): void;
43
43
 
44
44
  declare function objectToYaml<T extends Object>(object: T): string;
45
45
 
46
+ interface Job {
47
+ handle: () => void;
48
+ resolve: (value: unknown) => unknown;
49
+ reject: (value: unknown) => unknown;
50
+ }
51
+ declare class Queue {
52
+ constructor();
53
+ get length(): number;
54
+ start(): Promise<void>;
55
+ push(handle: Job['handle']): Promise<unknown>;
56
+ }
57
+
46
58
  type MaybePromise<T> = T | Promise<T>;
47
59
  interface EventStore {
48
60
  persist(events: EventType[]): MaybePromise<void>;
@@ -52,10 +64,23 @@ interface EventStore {
52
64
  interface EventHandler {
53
65
  (event: EventType, es: EventSource): MaybePromise<unknown>;
54
66
  }
55
- interface Projector {
56
- name: string;
57
- init: (es: EventSource) => MaybePromise<void>;
58
- update: (event: EventType) => MaybePromise<unknown>;
67
+ type ApplyConcreteProjectorEvents<Events extends EventType> = Events extends EventType<infer EventName, any> ? {
68
+ [T in EventName]: (event: Extract<Events, {
69
+ eventName: T;
70
+ }>) => Promise<void>;
71
+ } : never;
72
+ type Lazy<T> = (...args: any[]) => T;
73
+ type ApplyLazyProjectorEvents<Events extends Lazy<EventType>> = ApplyConcreteProjectorEvents<ReturnType<Events>>;
74
+ type MaybeLazy<T> = T | Lazy<T>;
75
+ type ApplyProjectorEvents<Events extends MaybeLazy<EventType> = any> = Events extends Lazy<EventType> ? ApplyLazyProjectorEvents<Events> : Events extends EventType ? ApplyConcreteProjectorEvents<Events> : never;
76
+ declare abstract class Projector<T extends ApplyProjectorEvents<any> = any> {
77
+ abstract name: string;
78
+ abstract apply: T;
79
+ initializer(): void | Promise<void>;
80
+ q: Queue;
81
+ init(es: EventSource): Promise<void>;
82
+ applyEvent(event: EventType): Promise<void>;
83
+ project(event: EventType): void | Promise<void>;
59
84
  }
60
85
  interface CommandHandler {
61
86
  (command: CommandType, es: EventSource): MaybePromise<void>;
@@ -87,11 +112,8 @@ declare class EventSourceBuilder {
87
112
  addEventHandler(eventHandler: EventHandler): this;
88
113
  }
89
114
 
90
- type EventMapper$1 = Record<string, (event: EventType, es: EventSource) => void>;
91
- declare function createEventMapper(mapper: EventMapper$1): (event: EventType, es: EventSource) => void;
92
-
93
- type EventMapper<Ctx> = Record<string, (event: EventType, ctx?: Ctx) => void>;
94
- declare function createProjector<Ctx>(name: string, mapper: EventMapper<Ctx>, initializer?: (ctx: Ctx) => Promise<void> | void, createContext?: () => Ctx): Projector;
115
+ type EventMapper = Record<string, (event: EventType, es: EventSource) => void>;
116
+ declare function createEventMapper(mapper: EventMapper): (event: EventType, es: EventSource) => void;
95
117
 
96
118
  declare function createTestEventStore(commandHandlers: Record<string, CommandHandler>, projectors?: Projector[]): {
97
119
  ___: any;
@@ -100,4 +122,4 @@ declare function createTestEventStore(commandHandlers: Record<string, CommandHan
100
122
  then(expectation: EventType[] | Error): Promise<void>;
101
123
  };
102
124
 
103
- export { Aggregate, type ApplyEvents, Command, type CommandHandler, type CommandType, Event, type EventHandler, EventSource, type EventStore, type EventType, type PayloadOf, type Projector, type TypeOf, abort, createEventMapper, createProjector, createTestEventStore, objectToYaml };
125
+ export { Aggregate, type ApplyEvents, Command, type CommandHandler, type CommandType, Event, type EventHandler, EventSource, type EventStore, type EventType, type PayloadOf, Projector, type TypeOf, abort, createEventMapper, createTestEventStore, objectToYaml };
package/dist/index.d.ts CHANGED
@@ -13,10 +13,10 @@ type ApplyConcreteEvents<Events extends EventType> = Events extends EventType<in
13
13
  eventName: T;
14
14
  }>) => void;
15
15
  } : never;
16
- type Lazy<T> = (...args: any[]) => T;
17
- type ApplyLazyEvents<Events extends Lazy<EventType>> = ApplyConcreteEvents<ReturnType<Events>>;
18
- type MaybeLazy<T> = T | Lazy<T>;
19
- type ApplyEvents<Events extends MaybeLazy<EventType> = any> = Events extends Lazy<EventType> ? ApplyLazyEvents<Events> : Events extends EventType ? ApplyConcreteEvents<Events> : never;
16
+ type Lazy$1<T> = (...args: any[]) => T;
17
+ type ApplyLazyEvents<Events extends Lazy$1<EventType>> = ApplyConcreteEvents<ReturnType<Events>>;
18
+ type MaybeLazy$1<T> = T | Lazy$1<T>;
19
+ type ApplyEvents<Events extends MaybeLazy$1<EventType> = any> = Events extends Lazy$1<EventType> ? ApplyLazyEvents<Events> : Events extends EventType ? ApplyConcreteEvents<Events> : never;
20
20
  declare abstract class Aggregate {
21
21
  #private;
22
22
  abstract apply: ApplyEvents;
@@ -43,6 +43,18 @@ declare function abort<T>(message: string, attributes?: T): void;
43
43
 
44
44
  declare function objectToYaml<T extends Object>(object: T): string;
45
45
 
46
+ interface Job {
47
+ handle: () => void;
48
+ resolve: (value: unknown) => unknown;
49
+ reject: (value: unknown) => unknown;
50
+ }
51
+ declare class Queue {
52
+ constructor();
53
+ get length(): number;
54
+ start(): Promise<void>;
55
+ push(handle: Job['handle']): Promise<unknown>;
56
+ }
57
+
46
58
  type MaybePromise<T> = T | Promise<T>;
47
59
  interface EventStore {
48
60
  persist(events: EventType[]): MaybePromise<void>;
@@ -52,10 +64,23 @@ interface EventStore {
52
64
  interface EventHandler {
53
65
  (event: EventType, es: EventSource): MaybePromise<unknown>;
54
66
  }
55
- interface Projector {
56
- name: string;
57
- init: (es: EventSource) => MaybePromise<void>;
58
- update: (event: EventType) => MaybePromise<unknown>;
67
+ type ApplyConcreteProjectorEvents<Events extends EventType> = Events extends EventType<infer EventName, any> ? {
68
+ [T in EventName]: (event: Extract<Events, {
69
+ eventName: T;
70
+ }>) => Promise<void>;
71
+ } : never;
72
+ type Lazy<T> = (...args: any[]) => T;
73
+ type ApplyLazyProjectorEvents<Events extends Lazy<EventType>> = ApplyConcreteProjectorEvents<ReturnType<Events>>;
74
+ type MaybeLazy<T> = T | Lazy<T>;
75
+ type ApplyProjectorEvents<Events extends MaybeLazy<EventType> = any> = Events extends Lazy<EventType> ? ApplyLazyProjectorEvents<Events> : Events extends EventType ? ApplyConcreteProjectorEvents<Events> : never;
76
+ declare abstract class Projector<T extends ApplyProjectorEvents<any> = any> {
77
+ abstract name: string;
78
+ abstract apply: T;
79
+ initializer(): void | Promise<void>;
80
+ q: Queue;
81
+ init(es: EventSource): Promise<void>;
82
+ applyEvent(event: EventType): Promise<void>;
83
+ project(event: EventType): void | Promise<void>;
59
84
  }
60
85
  interface CommandHandler {
61
86
  (command: CommandType, es: EventSource): MaybePromise<void>;
@@ -87,11 +112,8 @@ declare class EventSourceBuilder {
87
112
  addEventHandler(eventHandler: EventHandler): this;
88
113
  }
89
114
 
90
- type EventMapper$1 = Record<string, (event: EventType, es: EventSource) => void>;
91
- declare function createEventMapper(mapper: EventMapper$1): (event: EventType, es: EventSource) => void;
92
-
93
- type EventMapper<Ctx> = Record<string, (event: EventType, ctx?: Ctx) => void>;
94
- declare function createProjector<Ctx>(name: string, mapper: EventMapper<Ctx>, initializer?: (ctx: Ctx) => Promise<void> | void, createContext?: () => Ctx): Projector;
115
+ type EventMapper = Record<string, (event: EventType, es: EventSource) => void>;
116
+ declare function createEventMapper(mapper: EventMapper): (event: EventType, es: EventSource) => void;
95
117
 
96
118
  declare function createTestEventStore(commandHandlers: Record<string, CommandHandler>, projectors?: Projector[]): {
97
119
  ___: any;
@@ -100,4 +122,4 @@ declare function createTestEventStore(commandHandlers: Record<string, CommandHan
100
122
  then(expectation: EventType[] | Error): Promise<void>;
101
123
  };
102
124
 
103
- export { Aggregate, type ApplyEvents, Command, type CommandHandler, type CommandType, Event, type EventHandler, EventSource, type EventStore, type EventType, type PayloadOf, type Projector, type TypeOf, abort, createEventMapper, createProjector, createTestEventStore, objectToYaml };
125
+ export { Aggregate, type ApplyEvents, Command, type CommandHandler, type CommandType, Event, type EventHandler, EventSource, type EventStore, type EventType, type PayloadOf, Projector, type TypeOf, abort, createEventMapper, createTestEventStore, objectToYaml };
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- "use strict";var L=Object.create;var y=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty;var F=(r,e)=>{for(var t in e)y(r,t,{get:e[t],enumerable:!0})},N=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Q(e))!q.call(r,o)&&o!==t&&y(r,o,{get:()=>e[o],enumerable:!(n=z(e,o))||n.enumerable});return r};var V=(r,e,t)=>(t=r!=null?L(R(r)):{},N(e||!r||!r.__esModule?y(t,"default",{value:r,enumerable:!0}):t,r)),Y=r=>N(y({},"__esModule",{value:!0}),r);var K={};F(K,{Aggregate:()=>j,Command:()=>U,Event:()=>W,EventSource:()=>u,abort:()=>c,createEventMapper:()=>I,createProjector:()=>$,createTestEventStore:()=>G,objectToYaml:()=>f});module.exports=Y(K);function P(r,e){let t=Object.assign(new Error(r),e);return t.stack,Error.captureStackTrace&&Error.captureStackTrace(t,P),t}function c(r,e){let t=P(r,e);throw Error.captureStackTrace&&Error.captureStackTrace(t,c),t}function w(r){Object.freeze(r);for(let e of Object.getOwnPropertyNames(r))r.hasOwnProperty(e)&&r[e]!==null&&(typeof r[e]=="object"||typeof r[e]=="function")&&!Object.isFrozen(r[e])&&w(r[e]);return r}var J={NODE_ENV:process.env.NODE_ENV},j=class{#e=0;#t=[];replayEvents(e=[]){for(let t of e)this.applyAnEvent(t);return this}applyAnEvent(e){J.NODE_ENV==="test"&&w(e);let t=this.apply[e.eventName];t==null&&(e.eventName.match(/^[$A-Z_][0-9A-Z_$]*$/i)?c(`Aggregate "${this.constructor.name}" has no method:
1
+ "use strict";var O=Object.create;var T=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var Q=Object.getPrototypeOf,R=Object.prototype.hasOwnProperty;var F=(r,e)=>{for(var t in e)T(r,t,{get:e[t],enumerable:!0})},z=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of q(e))!R.call(r,o)&&o!==t&&T(r,o,{get:()=>e[o],enumerable:!(n=_(e,o))||n.enumerable});return r};var V=(r,e,t)=>(t=r!=null?O(Q(r)):{},z(e||!r||!r.__esModule?T(t,"default",{value:r,enumerable:!0}):t,r)),Y=r=>z(T({},"__esModule",{value:!0}),r);var G={};F(G,{Aggregate:()=>A,Command:()=>U,Event:()=>W,EventSource:()=>v,Projector:()=>E,abort:()=>i,createEventMapper:()=>M,createTestEventStore:()=>B,objectToYaml:()=>h});module.exports=Y(G);function w(r,e){let t=Object.assign(new Error(r),e);return t.stack,Error.captureStackTrace&&Error.captureStackTrace(t,w),t}function i(r,e){let t=w(r,e);throw Error.captureStackTrace&&Error.captureStackTrace(t,i),t}function j(r){Object.freeze(r);for(let e of Object.getOwnPropertyNames(r))r.hasOwnProperty(e)&&r[e]!==null&&(typeof r[e]=="object"||typeof r[e]=="function")&&!Object.isFrozen(r[e])&&j(r[e]);return r}var J={NODE_ENV:process.env.NODE_ENV},A=class{#e=0;#t=[];replayEvents(e=[]){for(let t of e)this.applyAnEvent(t);return this}applyAnEvent(e){J.NODE_ENV==="test"&&j(e);let t=this.apply[e.eventName];t==null&&(e.eventName.match(/^[$A-Z_][0-9A-Z_$]*$/i)?i(`Aggregate "${this.constructor.name}" has no method:
2
2
 
3
3
  apply = {
4
4
  ${e.eventName}(event) {
5
5
  // Code goes here...
6
6
  }
7
7
  // ...
8
- }`):c(`Aggregate "${this.constructor.name}" has no method:
8
+ }`):i(`Aggregate "${this.constructor.name}" has no method:
9
9
 
10
10
  apply = {
11
11
  ['${e.eventName}'](event) {
@@ -15,16 +15,16 @@ apply = {
15
15
  }`));try{t(e)}catch(n){n instanceof Error&&console.error(`An error occurred inside your "%s" function:
16
16
  `,e.eventName,n.stack?.split(`
17
17
  `).map(o=>` ${o}`).join(`
18
- `))}finally{this.#e++}return this}recordThat(e){let t={...e,version:this.#e};return this.applyAnEvent(t),this.#t.push(t),this}releaseEvents(){return this.#t.splice(0)}};function U(r,e=null){return{type:r,payload:e}}var M=require("crypto");function W(r,e,t=null){return{aggregateId:e,eventId:(0,M.randomUUID)(),eventName:r,payload:t,recordedAt:new Date,version:-1}}var k=V(require("yamlify-object")),Z={indent:" ",colors:{date:d,error:d,symbol:d,string:d,number:d,boolean:d,null:d,undefined:d}};function d(r){return r}function f(r){return r instanceof Error?f({...r}):(0,k.default)(r,Z).split(`
18
+ `))}finally{this.#e++}return this}recordThat(e){let t={...e,version:this.#e};return this.applyAnEvent(t),this.#t.push(t),this}releaseEvents(){return this.#t.splice(0)}};function U(r,e=null){return{type:r,payload:e}}var L=require("crypto");function W(r,e,t=null){return{aggregateId:e,eventId:(0,L.randomUUID)(),eventName:r,payload:t,recordedAt:new Date,version:-1}}var I=V(require("yamlify-object")),Z={indent:" ",colors:{date:c,error:c,symbol:c,string:c,number:c,boolean:c,null:c,undefined:c}};function c(r){return r}function h(r){return r instanceof Error?h({...r}):(0,I.default)(r,Z).split(`
19
19
  `).slice(1).join(`
20
- `)}var u=class r{constructor(e,t,n,o){this.store=e;this.commandHandlers=t;this.projectors=n;this.eventHandlers=o}static builder(e){return new S(e)}static new(e,t,n,o){return new r(e,t,n,o)}async resetProjections(){await Promise.all(this.projectors.map(e=>e.init(this)))}async dispatch(e){return this.commandHandlers.has(e.type)||c(`There is no command handler for the "${e.type}" command`),await this.commandHandlers.get(e.type)(e,this),e}async loadEvents(){return this.store.loadEvents()}async load(e,t){let n=await this.store.load(t);return n.length<=0&&c(`Aggregate(${e.constructor.name}) with ID(${t}) does not exist.`,{aggregate:e.constructor.name,aggregateId:t}),e.replayEvents(n)}async persist(e){let t=e.releaseEvents();await this.store.persist(t);for(let n of t)await Promise.all(this.projectors.map(async o=>{try{await o.update(n)}catch(s){throw s instanceof Error&&console.error(`An error occurred in one of your projections: ${o.name}, given an event`,s.stack?.split(`
21
- `).map(i=>` ${i}`).join(`
20
+ `)}var f=new WeakMap;function g(r,e){if(f.has(r)){let t=f.get(r);for(let n in e)t[n]=e[n]}else f.set(r,e)}function x(r){return f.get(r)}var b=class{constructor(){g(this,{jobs:[],state:0})}get length(){return x(this).jobs.length}async start(){let{state:e,jobs:t}=x(this);if(!(e===1||t.length<=0)){for(g(this,{state:1});t.length>0;){let n=t.shift();await Promise.resolve().then(n.handle).then(n.resolve,n.reject)}g(this,{state:0})}}push(e){return new Promise((t,n)=>{let{jobs:o}=x(this);o.push({handle:e,resolve:t,reject:n}),setImmediate(()=>this.start())})}};var E=class{initializer(){}q=new b;async init(e){await this.q.push(()=>this.initializer());let t=await e.loadEvents();await Promise.all(t.map(n=>this.applyEvent(n)))}async applyEvent(e){await this.q.push(()=>this.apply?.[e.eventName]?.(e)),await this.q.push(()=>this.project(e))}project(e){}},v=class r{constructor(e,t,n,o){this.store=e;this.commandHandlers=t;this.projectors=n;this.eventHandlers=o}static builder(e){return new S(e)}static new(e,t,n,o){return new r(e,t,n,o)}async resetProjections(){await Promise.all(this.projectors.map(e=>e.init(this)))}async dispatch(e){return this.commandHandlers.has(e.type)||i(`There is no command handler for the "${e.type}" command`),await this.commandHandlers.get(e.type)(e,this),e}async loadEvents(){return this.store.loadEvents()}async load(e,t){let n=await this.store.load(t);return n.length<=0&&i(`Aggregate(${e.constructor.name}) with ID(${t}) does not exist.`,{aggregate:e.constructor.name,aggregateId:t}),e.replayEvents(n)}async persist(e){let t=e.releaseEvents();await this.store.persist(t);for(let n of t)await Promise.all(this.projectors.map(async o=>{try{await o.applyEvent(n)}catch(s){throw s instanceof Error&&console.error(`An error occurred in one of your projections: ${o.name}, given an event`,s.stack?.split(`
21
+ `).map(d=>` ${d}`).join(`
22
22
  `)),s}})),await Promise.all(this.eventHandlers.map(async o=>{try{await o(n,this)}catch(s){throw s instanceof Error&&console.error(`An error occurred in one of your event handlers: ${o.name}, given an event`,s.stack?.split(`
23
- `).map(i=>` ${i}`).join(`
24
- `)),s}}))}async loadPersist(e,t,n){return await this.load(e,t),await n(e),this.persist(e)}},S=class{constructor(e){this.store=e}commandHandlers=new Map;projectors=[];eventHandlers=[];build(){return u.new(this.store,this.commandHandlers,this.projectors,this.eventHandlers)}addCommandHandler(e,t){return this.commandHandlers.has(e)&&c(`A command handler for the "${e}" command already exists`),this.commandHandlers.set(e,t),this}addProjector(e){return this.projectors.push(e),this}addEventHandler(e){return this.eventHandlers.push(e),this}};function I(r){return(e,t)=>r[e.eventName]?.(e,t)}var h=new WeakMap;function T(r,e){if(h.has(r)){let t=h.get(r);for(let n in e)t[n]=e[n]}else h.set(r,e)}function g(r){return h.get(r)}var x=class{constructor(){T(this,{jobs:[],state:0})}get length(){return g(this).jobs.length}async start(){let{state:e,jobs:t}=g(this);if(!(e===1||t.length<=0)){for(T(this,{state:1});t.length>0;){let n=t.shift();await Promise.resolve().then(n.handle).then(n.resolve,n.reject)}T(this,{state:0})}}push(e){return new Promise((t,n)=>{let{jobs:o}=g(this);o.push({handle:e,resolve:t,reject:n}),setImmediate(()=>this.start())})}};function B(){}function $(r,e,t=B,n){let o=new x,s=n?.()??{};return{name:r,async init(i){await o.push(()=>t(s));let a=await i.loadEvents();await Promise.all(a.map(p=>this.update(p)))},update(i){return o.push(()=>e[i.eventName]?.(i,s))}}}var H=Symbol("__placeholder__"),v={usedTestEventStoreInTest:!1,calledThenHandler:!1};process.env.NODE_ENV==="test"&&(beforeEach(()=>{v.usedTestEventStoreInTest=!1,v.calledThenHandler=!1}),afterEach(()=>{v.usedTestEventStoreInTest&&!v.calledThenHandler&&c("It seems like you used `createTestEventStore()`\nwithout using the `await then([expected, events, go, here, ...])`")}));function D(r,e){try{return r()}catch(t){throw Error.captureStackTrace&&t instanceof Error&&Error.captureStackTrace(t,e),t}}var C=class{constructor(e=[],t=[]){this.db=e;this.producedEvents=t}name="test-recording-projector";init(){this.db.splice(0)}update(e){this.producedEvents.push(e)}};function G(r,e=[]){v.usedTestEventStoreInTest=!0;let t=new C,n=u.builder({load(a){return t.db.filter(p=>p.aggregateId===a)},loadEvents(){return t.db},persist(a){t.db.push(...a)}});for(let a of e)n.addProjector(a);n.addProjector(t);for(let[a,p]of Object.entries(r))n.addCommandHandler(a,p);let o=n.build(),s,i={___:H,async given(a=[]){t.db.push(...a)},async when(a){try{return await o.dispatch(typeof a=="function"?a():a)}catch(p){return p instanceof Error&&(s=p),p}},async then(a){if(v.calledThenHandler=!0,a instanceof Error){let b=a;D(()=>expect(s).toEqual(b),i.then);return}let p=a;if(s)throw Object.keys(s).length>0&&(s.message=["With properties:",`
25
- ${f(s)}
23
+ `).map(d=>` ${d}`).join(`
24
+ `)),s}}))}async loadPersist(e,t,n){return await this.load(e,t),await n(e),this.persist(e)}},S=class{constructor(e){this.store=e}commandHandlers=new Map;projectors=[];eventHandlers=[];build(){return v.new(this.store,this.commandHandlers,this.projectors,this.eventHandlers)}addCommandHandler(e,t){return this.commandHandlers.has(e)&&i(`A command handler for the "${e}" command already exists`),this.commandHandlers.set(e,t),this}addProjector(e){return this.projectors.push(e),this}addEventHandler(e){return this.eventHandlers.push(e),this}};function M(r){return(e,t)=>r[e.eventName]?.(e,t)}var H=Symbol("__placeholder__"),y={usedTestEventStoreInTest:!1,calledThenHandler:!1};process.env.NODE_ENV==="test"&&(beforeEach(()=>{y.usedTestEventStoreInTest=!1,y.calledThenHandler=!1}),afterEach(()=>{y.usedTestEventStoreInTest&&!y.calledThenHandler&&i("It seems like you used `createTestEventStore()`\nwithout using the `await then([expected, events, go, here, ...])`")}));function k(r,e){try{return r()}catch(t){throw Error.captureStackTrace&&t instanceof Error&&Error.captureStackTrace(t,e),t}}var N=class extends E{constructor(t=[],n=[]){super();this.db=t;this.producedEvents=n}apply={};name="test-recording-projector";initializer(){this.db.splice(0)}project(t){this.producedEvents.push(t)}};function B(r,e=[]){y.usedTestEventStoreInTest=!0;let t=new N,n=v.builder({load(a){return t.db.filter(p=>p.aggregateId===a)},loadEvents(){return t.db},persist(a){t.db.push(...a)}});for(let a of e)n.addProjector(a);n.addProjector(t);for(let[a,p]of Object.entries(r))n.addCommandHandler(a,p);let o=n.build(),s,d={___:H,async given(a=[]){t.db.push(...a)},async when(a){try{return await o.dispatch(typeof a=="function"?a():a)}catch(p){return p instanceof Error&&(s=p),p}},async then(a){if(y.calledThenHandler=!0,a instanceof Error){let P=a;k(()=>expect(s).toEqual(P),d.then);return}let p=a;if(s)throw Object.keys(s).length>0&&(s.message=["With properties:",`
25
+ ${h(s)}
26
26
 
27
27
  ---
28
28
 
29
29
  `].join(`
30
- `)),s;D(()=>{expect(p).toHaveLength(t.producedEvents.length);for(let[b,l]of p.entries()){let{aggregateId:O,eventName:_,payload:m}=t.producedEvents[b];if(l.aggregateId===H)throw new Error("Expected an `aggregateId`, but got `___` instead.");expect(l.aggregateId).toEqual(O),expect(l.eventName).toEqual(_),(l.payload===null||l.payload===void 0)&&expect(l.payload).toEqual(m);for(let E in l.payload){let A=l.payload[E];A===H?(expect(m).toHaveProperty(E),expect(m[E]).toBeDefined()):expect(m[E]).toEqual(A)}}},i.then)}};return i}0&&(module.exports={Aggregate,Command,Event,EventSource,abort,createEventMapper,createProjector,createTestEventStore,objectToYaml});
30
+ `)),s;k(()=>{expect(p).toHaveLength(t.producedEvents.length);for(let[P,l]of p.entries()){let{aggregateId:$,eventName:D,payload:m}=t.producedEvents[P];if(l.aggregateId===H)throw new Error("Expected an `aggregateId`, but got `___` instead.");expect(l.aggregateId).toEqual($),expect(l.eventName).toEqual(D),(l.payload===null||l.payload===void 0)&&expect(l.payload).toEqual(m);for(let u in l.payload){let C=l.payload[u];C===H?(expect(m).toHaveProperty(u),expect(m[u]).toBeDefined()):expect(m[u]).toEqual(C)}}},d.then)}};return d}0&&(module.exports={Aggregate,Command,Event,EventSource,Projector,abort,createEventMapper,createTestEventStore,objectToYaml});
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
- function x(r,e){let t=Object.assign(new Error(r),e);return t.stack,Error.captureStackTrace&&Error.captureStackTrace(t,x),t}function c(r,e){let t=x(r,e);throw Error.captureStackTrace&&Error.captureStackTrace(t,c),t}function b(r){Object.freeze(r);for(let e of Object.getOwnPropertyNames(r))r.hasOwnProperty(e)&&r[e]!==null&&(typeof r[e]=="object"||typeof r[e]=="function")&&!Object.isFrozen(r[e])&&b(r[e]);return r}var k={NODE_ENV:process.env.NODE_ENV},C=class{#e=0;#t=[];replayEvents(e=[]){for(let t of e)this.applyAnEvent(t);return this}applyAnEvent(e){k.NODE_ENV==="test"&&b(e);let t=this.apply[e.eventName];t==null&&(e.eventName.match(/^[$A-Z_][0-9A-Z_$]*$/i)?c(`Aggregate "${this.constructor.name}" has no method:
1
+ function b(r,e){let t=Object.assign(new Error(r),e);return t.stack,Error.captureStackTrace&&Error.captureStackTrace(t,b),t}function p(r,e){let t=b(r,e);throw Error.captureStackTrace&&Error.captureStackTrace(t,p),t}function P(r){Object.freeze(r);for(let e of Object.getOwnPropertyNames(r))r.hasOwnProperty(e)&&r[e]!==null&&(typeof r[e]=="object"||typeof r[e]=="function")&&!Object.isFrozen(r[e])&&P(r[e]);return r}var I={NODE_ENV:process.env.NODE_ENV},N=class{#e=0;#t=[];replayEvents(e=[]){for(let t of e)this.applyAnEvent(t);return this}applyAnEvent(e){I.NODE_ENV==="test"&&P(e);let t=this.apply[e.eventName];t==null&&(e.eventName.match(/^[$A-Z_][0-9A-Z_$]*$/i)?p(`Aggregate "${this.constructor.name}" has no method:
2
2
 
3
3
  apply = {
4
4
  ${e.eventName}(event) {
5
5
  // Code goes here...
6
6
  }
7
7
  // ...
8
- }`):c(`Aggregate "${this.constructor.name}" has no method:
8
+ }`):p(`Aggregate "${this.constructor.name}" has no method:
9
9
 
10
10
  apply = {
11
11
  ['${e.eventName}'](event) {
@@ -15,16 +15,16 @@ apply = {
15
15
  }`));try{t(e)}catch(n){n instanceof Error&&console.error(`An error occurred inside your "%s" function:
16
16
  `,e.eventName,n.stack?.split(`
17
17
  `).map(a=>` ${a}`).join(`
18
- `))}finally{this.#e++}return this}recordThat(e){let t={...e,version:this.#e};return this.applyAnEvent(t),this.#t.push(t),this}releaseEvents(){return this.#t.splice(0)}};function J(r,e=null){return{type:r,payload:e}}import{randomUUID as I}from"crypto";function Z(r,e,t=null){return{aggregateId:e,eventId:I(),eventName:r,payload:t,recordedAt:new Date,version:-1}}import $ from"yamlify-object";var D={indent:" ",colors:{date:d,error:d,symbol:d,string:d,number:d,boolean:d,null:d,undefined:d}};function d(r){return r}function P(r){return r instanceof Error?P({...r}):$(r,D).split(`
18
+ `))}finally{this.#e++}return this}recordThat(e){let t={...e,version:this.#e};return this.applyAnEvent(t),this.#t.push(t),this}releaseEvents(){return this.#t.splice(0)}};function Y(r,e=null){return{type:r,payload:e}}import{randomUUID as M}from"crypto";function W(r,e,t=null){return{aggregateId:e,eventId:M(),eventName:r,payload:t,recordedAt:new Date,version:-1}}import k from"yamlify-object";var $={indent:" ",colors:{date:c,error:c,symbol:c,string:c,number:c,boolean:c,null:c,undefined:c}};function c(r){return r}function w(r){return r instanceof Error?w({...r}):k(r,$).split(`
19
19
  `).slice(1).join(`
20
- `)}var v=class r{constructor(e,t,n,a){this.store=e;this.commandHandlers=t;this.projectors=n;this.eventHandlers=a}static builder(e){return new w(e)}static new(e,t,n,a){return new r(e,t,n,a)}async resetProjections(){await Promise.all(this.projectors.map(e=>e.init(this)))}async dispatch(e){return this.commandHandlers.has(e.type)||c(`There is no command handler for the "${e.type}" command`),await this.commandHandlers.get(e.type)(e,this),e}async loadEvents(){return this.store.loadEvents()}async load(e,t){let n=await this.store.load(t);return n.length<=0&&c(`Aggregate(${e.constructor.name}) with ID(${t}) does not exist.`,{aggregate:e.constructor.name,aggregateId:t}),e.replayEvents(n)}async persist(e){let t=e.releaseEvents();await this.store.persist(t);for(let n of t)await Promise.all(this.projectors.map(async a=>{try{await a.update(n)}catch(s){throw s instanceof Error&&console.error(`An error occurred in one of your projections: ${a.name}, given an event`,s.stack?.split(`
21
- `).map(i=>` ${i}`).join(`
20
+ `)}var u=new WeakMap;function T(r,e){if(u.has(r)){let t=u.get(r);for(let n in e)t[n]=e[n]}else u.set(r,e)}function h(r){return u.get(r)}var f=class{constructor(){T(this,{jobs:[],state:0})}get length(){return h(this).jobs.length}async start(){let{state:e,jobs:t}=h(this);if(!(e===1||t.length<=0)){for(T(this,{state:1});t.length>0;){let n=t.shift();await Promise.resolve().then(n.handle).then(n.resolve,n.reject)}T(this,{state:0})}}push(e){return new Promise((t,n)=>{let{jobs:a}=h(this);a.push({handle:e,resolve:t,reject:n}),setImmediate(()=>this.start())})}};var g=class{initializer(){}q=new f;async init(e){await this.q.push(()=>this.initializer());let t=await e.loadEvents();await Promise.all(t.map(n=>this.applyEvent(n)))}async applyEvent(e){await this.q.push(()=>this.apply?.[e.eventName]?.(e)),await this.q.push(()=>this.project(e))}project(e){}},y=class r{constructor(e,t,n,a){this.store=e;this.commandHandlers=t;this.projectors=n;this.eventHandlers=a}static builder(e){return new j(e)}static new(e,t,n,a){return new r(e,t,n,a)}async resetProjections(){await Promise.all(this.projectors.map(e=>e.init(this)))}async dispatch(e){return this.commandHandlers.has(e.type)||p(`There is no command handler for the "${e.type}" command`),await this.commandHandlers.get(e.type)(e,this),e}async loadEvents(){return this.store.loadEvents()}async load(e,t){let n=await this.store.load(t);return n.length<=0&&p(`Aggregate(${e.constructor.name}) with ID(${t}) does not exist.`,{aggregate:e.constructor.name,aggregateId:t}),e.replayEvents(n)}async persist(e){let t=e.releaseEvents();await this.store.persist(t);for(let n of t)await Promise.all(this.projectors.map(async a=>{try{await a.applyEvent(n)}catch(s){throw s instanceof Error&&console.error(`An error occurred in one of your projections: ${a.name}, given an event`,s.stack?.split(`
21
+ `).map(d=>` ${d}`).join(`
22
22
  `)),s}})),await Promise.all(this.eventHandlers.map(async a=>{try{await a(n,this)}catch(s){throw s instanceof Error&&console.error(`An error occurred in one of your event handlers: ${a.name}, given an event`,s.stack?.split(`
23
- `).map(i=>` ${i}`).join(`
24
- `)),s}}))}async loadPersist(e,t,n){return await this.load(e,t),await n(e),this.persist(e)}},w=class{constructor(e){this.store=e}commandHandlers=new Map;projectors=[];eventHandlers=[];build(){return v.new(this.store,this.commandHandlers,this.projectors,this.eventHandlers)}addCommandHandler(e,t){return this.commandHandlers.has(e)&&c(`A command handler for the "${e}" command already exists`),this.commandHandlers.set(e,t),this}addProjector(e){return this.projectors.push(e),this}addEventHandler(e){return this.eventHandlers.push(e),this}};function O(r){return(e,t)=>r[e.eventName]?.(e,t)}var y=new WeakMap;function f(r,e){if(y.has(r)){let t=y.get(r);for(let n in e)t[n]=e[n]}else y.set(r,e)}function h(r){return y.get(r)}var T=class{constructor(){f(this,{jobs:[],state:0})}get length(){return h(this).jobs.length}async start(){let{state:e,jobs:t}=h(this);if(!(e===1||t.length<=0)){for(f(this,{state:1});t.length>0;){let n=t.shift();await Promise.resolve().then(n.handle).then(n.resolve,n.reject)}f(this,{state:0})}}push(e){return new Promise((t,n)=>{let{jobs:a}=h(this);a.push({handle:e,resolve:t,reject:n}),setImmediate(()=>this.start())})}};function _(){}function L(r,e,t=_,n){let a=new T,s=n?.()??{};return{name:r,async init(i){await a.push(()=>t(s));let o=await i.loadEvents();await Promise.all(o.map(p=>this.update(p)))},update(i){return a.push(()=>e[i.eventName]?.(i,s))}}}var j=Symbol("__placeholder__"),u={usedTestEventStoreInTest:!1,calledThenHandler:!1};process.env.NODE_ENV==="test"&&(beforeEach(()=>{u.usedTestEventStoreInTest=!1,u.calledThenHandler=!1}),afterEach(()=>{u.usedTestEventStoreInTest&&!u.calledThenHandler&&c("It seems like you used `createTestEventStore()`\nwithout using the `await then([expected, events, go, here, ...])`")}));function A(r,e){try{return r()}catch(t){throw Error.captureStackTrace&&t instanceof Error&&Error.captureStackTrace(t,e),t}}var S=class{constructor(e=[],t=[]){this.db=e;this.producedEvents=t}name="test-recording-projector";init(){this.db.splice(0)}update(e){this.producedEvents.push(e)}};function ue(r,e=[]){u.usedTestEventStoreInTest=!0;let t=new S,n=v.builder({load(o){return t.db.filter(p=>p.aggregateId===o)},loadEvents(){return t.db},persist(o){t.db.push(...o)}});for(let o of e)n.addProjector(o);n.addProjector(t);for(let[o,p]of Object.entries(r))n.addCommandHandler(o,p);let a=n.build(),s,i={___:j,async given(o=[]){t.db.push(...o)},async when(o){try{return await a.dispatch(typeof o=="function"?o():o)}catch(p){return p instanceof Error&&(s=p),p}},async then(o){if(u.calledThenHandler=!0,o instanceof Error){let g=o;A(()=>expect(s).toEqual(g),i.then);return}let p=o;if(s)throw Object.keys(s).length>0&&(s.message=["With properties:",`
25
- ${P(s)}
23
+ `).map(d=>` ${d}`).join(`
24
+ `)),s}}))}async loadPersist(e,t,n){return await this.load(e,t),await n(e),this.persist(e)}},j=class{constructor(e){this.store=e}commandHandlers=new Map;projectors=[];eventHandlers=[];build(){return y.new(this.store,this.commandHandlers,this.projectors,this.eventHandlers)}addCommandHandler(e,t){return this.commandHandlers.has(e)&&p(`A command handler for the "${e}" command already exists`),this.commandHandlers.set(e,t),this}addProjector(e){return this.projectors.push(e),this}addEventHandler(e){return this.eventHandlers.push(e),this}};function D(r){return(e,t)=>r[e.eventName]?.(e,t)}var A=Symbol("__placeholder__"),v={usedTestEventStoreInTest:!1,calledThenHandler:!1};process.env.NODE_ENV==="test"&&(beforeEach(()=>{v.usedTestEventStoreInTest=!1,v.calledThenHandler=!1}),afterEach(()=>{v.usedTestEventStoreInTest&&!v.calledThenHandler&&p("It seems like you used `createTestEventStore()`\nwithout using the `await then([expected, events, go, here, ...])`")}));function C(r,e){try{return r()}catch(t){throw Error.captureStackTrace&&t instanceof Error&&Error.captureStackTrace(t,e),t}}var S=class extends g{constructor(t=[],n=[]){super();this.db=t;this.producedEvents=n}apply={};name="test-recording-projector";initializer(){this.db.splice(0)}project(t){this.producedEvents.push(t)}};function le(r,e=[]){v.usedTestEventStoreInTest=!0;let t=new S,n=y.builder({load(o){return t.db.filter(i=>i.aggregateId===o)},loadEvents(){return t.db},persist(o){t.db.push(...o)}});for(let o of e)n.addProjector(o);n.addProjector(t);for(let[o,i]of Object.entries(r))n.addCommandHandler(o,i);let a=n.build(),s,d={___:A,async given(o=[]){t.db.push(...o)},async when(o){try{return await a.dispatch(typeof o=="function"?o():o)}catch(i){return i instanceof Error&&(s=i),i}},async then(o){if(v.calledThenHandler=!0,o instanceof Error){let x=o;C(()=>expect(s).toEqual(x),d.then);return}let i=o;if(s)throw Object.keys(s).length>0&&(s.message=["With properties:",`
25
+ ${w(s)}
26
26
 
27
27
  ---
28
28
 
29
29
  `].join(`
30
- `)),s;A(()=>{expect(p).toHaveLength(t.producedEvents.length);for(let[g,l]of p.entries()){let{aggregateId:N,eventName:M,payload:m}=t.producedEvents[g];if(l.aggregateId===j)throw new Error("Expected an `aggregateId`, but got `___` instead.");expect(l.aggregateId).toEqual(N),expect(l.eventName).toEqual(M),(l.payload===null||l.payload===void 0)&&expect(l.payload).toEqual(m);for(let E in l.payload){let H=l.payload[E];H===j?(expect(m).toHaveProperty(E),expect(m[E]).toBeDefined()):expect(m[E]).toEqual(H)}}},i.then)}};return i}export{C as Aggregate,J as Command,Z as Event,v as EventSource,c as abort,O as createEventMapper,L as createProjector,ue as createTestEventStore,P as objectToYaml};
30
+ `)),s;C(()=>{expect(i).toHaveLength(t.producedEvents.length);for(let[x,l]of i.entries()){let{aggregateId:z,eventName:L,payload:E}=t.producedEvents[x];if(l.aggregateId===A)throw new Error("Expected an `aggregateId`, but got `___` instead.");expect(l.aggregateId).toEqual(z),expect(l.eventName).toEqual(L),(l.payload===null||l.payload===void 0)&&expect(l.payload).toEqual(E);for(let m in l.payload){let H=l.payload[m];H===A?(expect(E).toHaveProperty(m),expect(E[m]).toBeDefined()):expect(E[m]).toEqual(H)}}},d.then)}};return d}export{N as Aggregate,Y as Command,W as Event,y as EventSource,g as Projector,p as abort,D as createEventMapper,le as createTestEventStore,w as objectToYaml};
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.9",
2
+ "version": "0.0.10",
3
3
  "name": "@robinmalfait/event-source",
4
4
  "publishConfig": {
5
5
  "access": "public"