@shirudo/ddd-kit 0.10.0 → 0.11.0
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 +32 -7
- package/dist/index.d.ts +539 -423
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var Q=Object.defineProperty;var o=(t,e)=>Q(t,"name",{value:e,configurable:true});function Y(t,e=0){return {state:t,version:e,pendingEvents:[]}}o(Y,"aggregate");function Z(t,e){return {...t,pendingEvents:[...t.pendingEvents,e]}}o(Z,"withEvent");function ee(t){return {...t,version:t.version+1}}o(ee,"bump");function F(t,e,r){return {type:t,payload:e,occurredAt:r?.occurredAt??new Date,version:r?.version??1,metadata:r?.metadata}}o(F,"createDomainEvent");function te(t,e,r,n){return F(t,e,{...n,metadata:r})}o(te,"createDomainEventWithMetadata");function re(t,e){return {...t.metadata??{},...e??{}}}o(re,"copyMetadata");function ne(...t){return Object.assign({},...t.filter(Boolean))}o(ne,"mergeMetadata");function oe(t,e){return t.id===e.id&&t.version===e.version}o(oe,"sameAggregate");var b=class{static{o(this,"AggregateBase");}id;version=0;_config;_autoVersionBump;get state(){return this._state}_state;constructor(e,r,n){this.id=e,this._state=r,this._config=n??{},this._autoVersionBump=this._config.autoVersionBump??false;}bumpVersion(){this.version=this.version+1;}setState(e,r){this._state=e,(r??this._autoVersionBump)&&this.bumpVersion();}createSnapshot(){return {state:{...this._state},version:this.version,snapshotAt:new Date}}restoreFromSnapshot(e){this._state=e.state,this.version=e.version;}};function E(t){return {ok:true,value:t}}o(E,"ok");function d(t){return {ok:false,error:t}}o(d,"err");var P=class extends b{static{o(this,"AggregateEventSourced");}_eventConfig;_eventAutoVersionBump;_pendingEvents=[];constructor(e,r,n){super(e,r,n),this._eventConfig=n??{},this._eventAutoVersionBump=this._eventConfig.autoVersionBump??true;}get pendingEvents(){return this._pendingEvents}clearPendingEvents(){this._pendingEvents.length=0;}validateEvent(e){return E(true)}apply(e,r=true){let n=this.validateEvent(e);if(!n.ok)return d(`Event validation failed for ${e.type}: ${n.error}`);let a=this.handlers[e.type];return a?(this._state=a(this._state,e),r&&(this._pendingEvents.push(e),this._eventAutoVersionBump&&(this.version=this.version+1)),E()):d(`Missing handler for event type: ${e.type}`)}applyUnsafe(e,r=true){let n=this.validateEvent(e);if(!n.ok)throw new Error(`Event validation failed for ${e.type}: ${n.error}`);let a=this.handlers[e.type];if(!a)throw new Error(`Missing handler for event type: ${e.type}`);this._state=a(this._state,e),r&&(this._pendingEvents.push(e),this._eventAutoVersionBump&&(this.version=this.version+1));}bumpVersion(){this.version=this.version+1;}loadFromHistory(e){for(let r of e){let n=this.apply(r,false);if(!n.ok)return n}return this.version=e.length,E()}hasPendingEvents(){return this._pendingEvents.length>0}getEventCount(){return this._pendingEvents.length}getLatestEvent(){return this._pendingEvents[this._pendingEvents.length-1]}restoreFromSnapshotWithEvents(e,r){this._state=e.state,this.version=e.version;for(let n of r){let a=this.apply(n,false);if(!a.ok)return a}return this.version=e.version+r.length,E()}};var I=class{static{o(this,"CommandBus");}handlers=new Map;register(e,r){this.handlers.set(e,r);}async execute(e){let r=this.handlers.get(e.type);return r?r(e):d(`No handler registered for command type: ${e.type}`)}};function je(t,e){return t.uow.transactional(async()=>{let{result:r,events:n}=await e();return await t.outbox.add(n),t.bus&&await t.bus.publish(n),r})}o(je,"withCommit");var j=class{static{o(this,"QueryBus");}handlers=new Map;register(e,r){this.handlers.set(e,r);}async execute(e){let r=this.handlers.get(e.type);if(!r)return d(`No handler registered for query type: ${e.type}`);try{let n=await r(e);return E(n)}catch(n){return d(n instanceof Error?n.message:String(n))}}async executeUnsafe(e){let r=this.handlers.get(e.type);if(!r)throw new Error(`No handler registered for query type: ${e.type}`);return r(e)}};function Qe(t,e){return t?E(true):d(e)}o(Qe,"guard");function Ke(t,e){return t.id===e.id}o(Ke,"sameEntity");function qe(t,e){return t.find(r=>r.id===e)}o(qe,"findEntityById");function Ne(t,e){return t.some(r=>r.id===e)}o(Ne,"hasEntityId");function We(t,e){return t.filter(r=>r.id!==e)}o(We,"removeEntityById");function $e(t,e,r){return t.map(n=>n.id===e?r(n):n)}o($e,"updateEntityById");function ze(t,e,r){return t.map(n=>n.id===e?r:n)}o(ze,"replaceEntityById");function Le(t){return t.map(e=>e.id)}o(Le,"entityIds");var V=class{static{o(this,"EventBusImpl");}handlers=new Map;subscribe(e,r){let n=e;this.handlers.has(n)||this.handlers.set(n,new Set);let a=this.handlers.get(n);return a.add(r),()=>{a.delete(r),a.size===0&&this.handlers.delete(n);}}async publish(e){for(let r of e){let n=this.handlers.get(r.type);n&&await Promise.all(Array.from(n).map(a=>a(r)));}}};function h(t,e){if(e.endsWith("Array]")||ArrayBuffer.isView(t)||e==="[object ArrayBuffer]"||e==="[object SharedArrayBuffer]")return true;let r=t.constructor;if(r&&typeof r=="function"){let a=r.name;if(a&&typeof globalThis<"u"&&a in globalThis&&globalThis[a]===r){let s=Object.getPrototypeOf(t);if(s!==Object.prototype&&s!==null)return true}}return new Set(["[object Date]","[object RegExp]","[object Map]","[object Set]","[object WeakMap]","[object WeakSet]","[object Promise]","[object Error]","[object Boolean]","[object Number]","[object String]"]).has(e)}o(h,"isBuiltInObject");var _=Object.prototype,k=_.toString,J=_.hasOwnProperty;function T(t,e){return v(t,e,new WeakMap)}o(T,"deepEqual");function v(t,e,r){if(t===e)return true;let n=typeof t,a=typeof e;if(n!=="object"||t===null||a!=="object"||e===null)return n==="number"&&a==="number"?Number.isNaN(t)&&Number.isNaN(e):false;let s=t,i=e,g=r.get(s);if(g!==void 0)return g===i;if(r.set(s,i),ArrayBuffer.isView(s)||ArrayBuffer.isView(i)){if(!ArrayBuffer.isView(s)||!ArrayBuffer.isView(i))return false;let c=k.call(s),p=k.call(i);if(c!==p)return false;if(c==="[object DataView]"){let m=s,O=i;if(m.byteLength!==O.byteLength)return false;let D=m.byteLength;for(let R=0;R<D;R++)if(m.getUint8(R)!==O.getUint8(R))return false;return true}let u=s,f=i,l=u.length;if(l!==f.length)return false;for(let m=0;m<l;m++)if(u[m]!==f[m])return false;return true}let y=k.call(s),x=k.call(i);if(y!==x)return false;switch(y){case "[object Array]":{let c=s,p=i,u=c.length;if(u!==p.length)return false;for(let f=0;f<u;f++)if(!v(c[f],p[f],r))return false;return true}case "[object Map]":{let c=s,p=i;if(c.size!==p.size)return false;for(let[u,f]of c){if(!p.has(u))return false;let l=p.get(u);if(!v(f,l,r))return false}return true}case "[object Set]":{let c=s,p=i;if(c.size!==p.size)return false;for(let u of c)if(!p.has(u))return false;return true}case "[object Date]":{let c=s.getTime(),p=i.getTime();return c===p}case "[object RegExp]":{let c=s,p=i;return c.source===p.source&&c.flags===p.flags}case "[object Boolean]":case "[object Number]":case "[object String]":return s.valueOf()===i.valueOf();default:{if(h(s,y)&&h(i,x))return s===i;let c=Object.keys(s),p=Object.keys(i),u=Object.getOwnPropertySymbols(s),f=Object.getOwnPropertySymbols(i);if(c.length!==p.length||u.length!==f.length)return false;for(let l of c)if(!J.call(i,l))return false;for(let l of u)if(!Object.getOwnPropertySymbols(i).includes(l))return false;for(let l of c)if(!v(s[l],i[l],r))return false;for(let l of u)if(!v(s[l],i[l],r))return false;return true}}}o(v,"deepEqualInner");function S(t,e){return A(t,e,[],new WeakMap)}o(S,"deepOmit");function A(t,e,r,n){if(t===null||typeof t!=="object")return t;let s=t,i=n.get(s);if(i!==void 0)return i;let g=Object.prototype.toString.call(s);if(g==="[object Array]"){let u=s,f=new Array(u.length);n.set(s,f);for(let l=0;l<u.length;l++)r.push(l),f[l]=A(u[l],e,r,n),r.pop();return f}if(h(s,g))return t;let y=Object.create(Object.getPrototypeOf(s));n.set(s,y);let x=Object.keys(s),c=Object.getOwnPropertySymbols(s),p=[...x,...c];for(let u of p)G(u,r,e)||(r.push(u),y[u]=A(s[u],e,r,n),r.pop());return y}o(A,"omitInternal");function G(t,e,r){return !!(r.ignoreKeys?.includes(t)||r.ignoreKeyPredicate?.(t,e))}o(G,"shouldIgnoreKey");function B(t,e,r){let n=S(t,r),a=S(e,r);return T(n,a)}o(B,"deepEqualExcept");function w(t,e=new WeakSet){if(t===null||typeof t!="object"||e.has(t))return t;e.add(t);let r=Object.getOwnPropertyNames(t);for(let n of r){let a=t[n];a&&(typeof a=="object"||Array.isArray(a))&&w(a,e);}return Object.freeze(t)}o(w,"deepFreeze");function U(t){return w({...t})}o(U,"vo");function dt(t,e){return T(t,e)}o(dt,"voEquals");function Et(t,e,r){return B(t,e,r)}o(Et,"voEqualsExcept");function mt(t,e,r){return e(t)?E(U(t)):d(r??`Validation failed for value object: ${JSON.stringify(t)}`)}o(mt,"voWithValidation");function yt(t,e,r){if(!e(t))throw new Error(r??`Validation failed for value object: ${JSON.stringify(t)}`);return U(t)}o(yt,"voWithValidationUnsafe");var C=class{static{o(this,"ValueObject");}props;constructor(e){this.props=w({...e});}equals(e){return e==null||e.props===void 0?false:T(this.props,e.props)}};export{b as AggregateBase,P as AggregateEventSourced,I as CommandBus,V as EventBusImpl,j as QueryBus,C as ValueObject,Y as aggregate,ee as bump,re as copyMetadata,F as createDomainEvent,te as createDomainEventWithMetadata,w as deepFreeze,Le as entityIds,qe as findEntityById,Qe as guard,Ne as hasEntityId,ne as mergeMetadata,We as removeEntityById,ze as replaceEntityById,oe as sameAggregate,Ke as sameEntity,$e as updateEntityById,U as vo,dt as voEquals,Et as voEqualsExcept,mt as voWithValidation,yt as voWithValidationUnsafe,je as withCommit,Z as withEvent};//# sourceMappingURL=index.js.map
|
|
1
|
+
var F=Object.defineProperty;var n=(t,e)=>F(t,"name",{value:e,configurable:true});function te(t,e=0){return {state:t,version:e,pendingEvents:[]}}n(te,"aggregate");function re(t,e){return {...t,pendingEvents:[...t.pendingEvents,e]}}n(re,"withEvent");function ne(t){return {...t,version:t.version+1}}n(ne,"bump");function M(t,e,r){return {type:t,payload:e,occurredAt:r?.occurredAt??new Date,version:r?.version??1,metadata:r?.metadata}}n(M,"createDomainEvent");function oe(t,e,r,o){return M(t,e,{...o,metadata:r})}n(oe,"createDomainEventWithMetadata");function se(t,e){return {...t.metadata??{},...e??{}}}n(se,"copyMetadata");function ae(...t){return Object.assign({},...t.filter(Boolean))}n(ae,"mergeMetadata");function ie(t,e){return t.id===e.id&&t.version===e.version}n(ie,"sameAggregate");var b=class{static{n(this,"AggregateRoot");}id;version=0;_config;_autoVersionBump;_domainEvents=[];get state(){return this._state}get domainEvents(){return this._domainEvents}clearDomainEvents(){this._domainEvents=[];}_state;constructor(e,r,o){if(e==null)throw new Error("Aggregate ID cannot be null or undefined");this.id=e,this._state=r,this._config=o??{},this._autoVersionBump=this._config.autoVersionBump??false,this.validateState(this._state);}validateState(e){}addDomainEvent(e){this._domainEvents.push(e);}bumpVersion(){this.version=this.version+1;}setState(e,r){this.validateState(e),this._state=e,(r??this._autoVersionBump)&&this.bumpVersion();}createSnapshot(){return {state:{...this._state},version:this.version,snapshotAt:new Date}}restoreFromSnapshot(e){this.validateState(e.state),this._state=e.state,this.version=e.version;}};function E(t){return {ok:true,value:t}}n(E,"ok");function f(t){return {ok:false,error:t}}n(f,"err");var O=class extends b{static{n(this,"AggregateEventSourced");}_eventConfig;_eventAutoVersionBump;constructor(e,r,o){super(e,r,o),this._eventConfig=o??{},this._eventAutoVersionBump=this._eventConfig.autoVersionBump??true;}get pendingEvents(){return this.domainEvents}clearPendingEvents(){this.clearDomainEvents();}validateEvent(e){return E(true)}apply(e,r=true){let o=this.validateEvent(e);if(!o.ok)return f(`Event validation failed for ${e.type}: ${o.error}`);let a=this.handlers[e.type];return a?(this._state=a(this._state,e),r&&(this.addDomainEvent(e),this._eventAutoVersionBump&&(this.version=this.version+1)),E()):f(`Missing handler for event type: ${e.type}`)}applyUnsafe(e,r=true){let o=this.validateEvent(e);if(!o.ok)throw new Error(`Event validation failed for ${e.type}: ${o.error}`);let a=this.handlers[e.type];if(!a)throw new Error(`Missing handler for event type: ${e.type}`);this._state=a(this._state,e),r&&(this.addDomainEvent(e),this._eventAutoVersionBump&&(this.version=this.version+1));}bumpVersion(){this.version=this.version+1;}loadFromHistory(e){for(let r of e){let o=this.apply(r,false);if(!o.ok)return o}return this.version=e.length,E()}hasPendingEvents(){return this.domainEvents.length>0}getEventCount(){return this.domainEvents.length}getLatestEvent(){let e=this.domainEvents;return e[e.length-1]}restoreFromSnapshotWithEvents(e,r){this._state=e.state,this.version=e.version;for(let o of r){let a=this.apply(o,false);if(!a.ok)return a}return this.version=e.version+r.length,E()}};var P=class{static{n(this,"CommandBus");}handlers=new Map;register(e,r){this.handlers.set(e,r);}async execute(e){let r=this.handlers.get(e.type);return r?r(e):f(`No handler registered for command type: ${e.type}`)}};function _e(t,e){return t.uow.transactional(async()=>{let{result:r,events:o}=await e();return await t.outbox.add(o),t.bus&&await t.bus.publish(o),r})}n(_e,"withCommit");var j=class{static{n(this,"QueryBus");}handlers=new Map;register(e,r){this.handlers.set(e,r);}async execute(e){let r=this.handlers.get(e.type);if(!r)return f(`No handler registered for query type: ${e.type}`);try{let o=await r(e);return E(o)}catch(o){return f(o instanceof Error?o.message:String(o))}}async executeUnsafe(e){let r=this.handlers.get(e.type);if(!r)throw new Error(`No handler registered for query type: ${e.type}`);return r(e)}};function qe(t,e){return t?E(true):f(e)}n(qe,"guard");function v(t,e){if(e.endsWith("Array]")||ArrayBuffer.isView(t)||e==="[object ArrayBuffer]"||e==="[object SharedArrayBuffer]")return true;let r=t.constructor;if(r&&typeof r=="function"){let a=r.name;if(a&&typeof globalThis<"u"&&a in globalThis&&globalThis[a]===r){let s=Object.getPrototypeOf(t);if(s!==Object.prototype&&s!==null)return true}}return new Set(["[object Date]","[object RegExp]","[object Map]","[object Set]","[object WeakMap]","[object WeakSet]","[object Promise]","[object Error]","[object Boolean]","[object Number]","[object String]"]).has(e)}n(v,"isBuiltInObject");var V=Object.prototype,w=V.toString,G=V.hasOwnProperty;function m(t,e){return h(t,e,new WeakMap)}n(m,"deepEqual");function h(t,e,r){if(t===e)return true;let o=typeof t,a=typeof e;if(o!=="object"||t===null||a!=="object"||e===null)return o==="number"&&a==="number"?Number.isNaN(t)&&Number.isNaN(e):false;let s=t,i=e,g=r.get(s);if(g!==void 0)return g===i;if(r.set(s,i),ArrayBuffer.isView(s)||ArrayBuffer.isView(i)){if(!ArrayBuffer.isView(s)||!ArrayBuffer.isView(i))return false;let c=w.call(s),l=w.call(i);if(c!==l)return false;if(c==="[object DataView]"){let y=s,S=i;if(y.byteLength!==S.byteLength)return false;let Q=y.byteLength;for(let R=0;R<Q;R++)if(y.getUint8(R)!==S.getUint8(R))return false;return true}let u=s,d=i,p=u.length;if(p!==d.length)return false;for(let y=0;y<p;y++)if(u[y]!==d[y])return false;return true}let T=w.call(s),x=w.call(i);if(T!==x)return false;switch(T){case "[object Array]":{let c=s,l=i,u=c.length;if(u!==l.length)return false;for(let d=0;d<u;d++)if(!h(c[d],l[d],r))return false;return true}case "[object Map]":{let c=s,l=i;if(c.size!==l.size)return false;for(let[u,d]of c){if(!l.has(u))return false;let p=l.get(u);if(!h(d,p,r))return false}return true}case "[object Set]":{let c=s,l=i;if(c.size!==l.size)return false;for(let u of c)if(!l.has(u))return false;return true}case "[object Date]":{let c=s.getTime(),l=i.getTime();return c===l}case "[object RegExp]":{let c=s,l=i;return c.source===l.source&&c.flags===l.flags}case "[object Boolean]":case "[object Number]":case "[object String]":return s.valueOf()===i.valueOf();default:{if(v(s,T)&&v(i,x))return s===i;let c=Object.keys(s),l=Object.keys(i),u=Object.getOwnPropertySymbols(s),d=Object.getOwnPropertySymbols(i);if(c.length!==l.length||u.length!==d.length)return false;for(let p of c)if(!G.call(i,p))return false;for(let p of u)if(!Object.getOwnPropertySymbols(i).includes(p))return false;for(let p of c)if(!h(s[p],i[p],r))return false;for(let p of u)if(!h(s[p],i[p],r))return false;return true}}}n(h,"deepEqualInner");var B=class{static{n(this,"Entity");}id;constructor(e){if(e==null)throw new Error("Entity ID cannot be null or undefined");this.id=e,this.validate();}validate(){}toJSON(){return {...this,id:this.id}}equals(e){return e==null?false:this===e?true:X(e)?Y(this,e):false}};function X(t){return typeof t=="object"&&t!==null&&"id"in t}n(X,"isEntity");function Y(t,e){return m(t.id,e.id)}n(Y,"sameEntity");function Ge(t,e){return t.find(r=>m(r.id,e))}n(Ge,"findEntityById");function Xe(t,e){return t.some(r=>m(r.id,e))}n(Xe,"hasEntityId");function Ye(t,e){return t.filter(r=>!m(r.id,e))}n(Ye,"removeEntityById");function Ze(t,e,r){return t.map(o=>m(o.id,e)?r(o):o)}n(Ze,"updateEntityById");function et(t,e,r){return t.map(o=>m(o.id,e)?r:o)}n(et,"replaceEntityById");function tt(t){return t.map(e=>e.id)}n(tt,"entityIds");var _=class{static{n(this,"EventBusImpl");}handlers=new Map;subscribe(e,r){let o=e;this.handlers.has(o)||this.handlers.set(o,new Set);let a=this.handlers.get(o);return a.add(r),()=>{a.delete(r),a.size===0&&this.handlers.delete(o);}}async publish(e){for(let r of e){let o=this.handlers.get(r.type);o&&await Promise.all(Array.from(o).map(a=>a(r)));}}};function A(t,e){return I(t,e,[],new WeakMap)}n(A,"deepOmit");function I(t,e,r,o){if(t===null||typeof t!=="object")return t;let s=t,i=o.get(s);if(i!==void 0)return i;let g=Object.prototype.toString.call(s);if(g==="[object Array]"){let u=s,d=new Array(u.length);o.set(s,d);for(let p=0;p<u.length;p++)r.push(p),d[p]=I(u[p],e,r,o),r.pop();return d}if(v(s,g))return t;let T=Object.create(Object.getPrototypeOf(s));o.set(s,T);let x=Object.keys(s),c=Object.getOwnPropertySymbols(s),l=[...x,...c];for(let u of l)Z(u,r,e)||(r.push(u),T[u]=I(s[u],e,r,o),r.pop());return T}n(I,"omitInternal");function Z(t,e,r){return !!(r.ignoreKeys?.includes(t)||r.ignoreKeyPredicate?.(t,e))}n(Z,"shouldIgnoreKey");function U(t,e,r){let o=A(t,r),a=A(e,r);return m(o,a)}n(U,"deepEqualExcept");function k(t,e=new WeakSet){if(t===null||typeof t!="object"||e.has(t))return t;e.add(t);let r=Object.getOwnPropertyNames(t);for(let o of r){let a=t[o];a&&(typeof a=="object"||Array.isArray(a))&&k(a,e);}return Object.freeze(t)}n(k,"deepFreeze");function D(t){return k({...t})}n(D,"vo");function yt(t,e){return m(t,e)}n(yt,"voEquals");function Tt(t,e,r){return U(t,e,r)}n(Tt,"voEqualsExcept");function gt(t,e,r){return e(t)?E(D(t)):f(r??`Validation failed for value object: ${JSON.stringify(t)}`)}n(gt,"voWithValidation");function vt(t,e,r){if(!e(t))throw new Error(r??`Validation failed for value object: ${JSON.stringify(t)}`);return D(t)}n(vt,"voWithValidationUnsafe");var C=class{static{n(this,"ValueObject");}props;constructor(e){this.validate(e),this.props=k({...e});}validate(e){}equals(e){return e==null||this.constructor!==e.constructor?false:m(this.props,e.props)}clone(e){let r=this.constructor;return new r({...this.props,...e||{}})}toJSON(){return this.props}};export{O as AggregateEventSourced,b as AggregateRoot,P as CommandBus,B as Entity,_ as EventBusImpl,j as QueryBus,C as ValueObject,te as aggregate,ne as bump,se as copyMetadata,M as createDomainEvent,oe as createDomainEventWithMetadata,k as deepFreeze,tt as entityIds,Ge as findEntityById,qe as guard,Xe as hasEntityId,ae as mergeMetadata,Ye as removeEntityById,et as replaceEntityById,ie as sameAggregate,Y as sameEntity,Ze as updateEntityById,D as vo,yt as voEquals,Tt as voEqualsExcept,gt as voWithValidation,vt as voWithValidationUnsafe,_e as withCommit,re as withEvent};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/aggregate/aggregate.ts","../src/aggregate/aggregate-base.ts","../src/core/result/result.ts","../src/aggregate/aggregate-event-sourced.ts","../src/app/command-bus.ts","../src/app/handler.ts","../src/app/query-bus.ts","../src/core/guard.ts","../src/entity/entity.ts","../src/events/event-bus.ts","../src/utils/array/is-built-in.ts","../src/utils/array/deep-equal.ts","../src/utils/array/deep-omit.ts","../src/utils/array/deep-equal-except.ts","../src/value-object/vo.ts","../src/value-object/value-object.ts"],"names":["aggregate","state","version","__name","withEvent","agg","evt","bump","createDomainEvent","type","payload","options","createDomainEventWithMetadata","metadata","copyMetadata","sourceEvent","additionalMetadata","mergeMetadata","metadataObjects","sameAggregate","a","b","AggregateBase","id","initialState","config","newState","bumpVersion","snapshot","ok","value","err","error","AggregateEventSourced","_event","event","isNew","validation","handler","history","result","eventsAfterSnapshot","CommandBus","commandType","command","withCommit","deps","fn","events","QueryBus","queryType","query","guard","cond","sameEntity","findEntityById","entities","entity","hasEntityId","removeEntityById","updateEntityById","updater","replaceEntityById","replacement","entityIds","EventBusImpl","eventType","handlersForType","isBuiltInObject","obj","tag","objConstructor","constructorName","proto","objProto","objToString","objHasOwn","deepEqual","deepEqualInner","visited","typeA","typeB","objA","objB","cached","tagA","tagB","viewA","viewB","len","i","arrA","arrB","mapA","mapB","key","valA","valB","setA","setB","timeA","timeB","regA","regB","stringKeysA","stringKeysB","symbolKeysA","symbolKeysB","deepOmit","omitInternal","path","arr","clone","stringKeys","symbolKeys","keys","shouldIgnoreKey","deepEqualExcept","prunedA","prunedB","deepFreeze","propNames","name","vo","voEquals","voEqualsExcept","voWithValidation","validate","errorMessage","voWithValidationUnsafe","ValueObject","props","other"],"mappings":"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","file":"index.js","sourcesContent":["import type { Id } from \"../core/id\";\n\nexport type Version = number & { readonly __v: true };\n\n/**\n * Metadata associated with a domain event for traceability and correlation.\n * Used in event-driven architectures to track event flow across services.\n */\nexport interface EventMetadata {\n\t/**\n\t * Correlation ID for tracing events across multiple services/components.\n\t * Typically used to group related events in a distributed system.\n\t */\n\tcorrelationId?: string;\n\n\t/**\n\t * Causation ID referencing the event or command that caused this event.\n\t * Used to build event chains and understand causality.\n\t */\n\tcausationId?: string;\n\n\t/**\n\t * User ID of the person or system that triggered the event.\n\t */\n\tuserId?: string;\n\n\t/**\n\t * Source service or component that produced the event.\n\t */\n\tsource?: string;\n\n\t/**\n\t * Additional custom metadata fields.\n\t * Allows extensibility for domain-specific metadata.\n\t */\n\t[key: string]: unknown;\n}\n\n/**\n * Domain Event represents something meaningful that happened in the domain.\n * Events are immutable and carry information about what occurred.\n *\n * @template T - The event type name (e.g., \"OrderCreated\")\n * @template P - The event payload type\n */\nexport interface DomainEvent<T extends string, P> {\n\t/**\n\t * The type of the event, used for routing and handling.\n\t */\n\ttype: T;\n\n\t/**\n\t * The event payload containing the domain data.\n\t */\n\tpayload: P;\n\n\t/**\n\t * Timestamp when the event occurred.\n\t */\n\toccurredAt: Date;\n\n\t/**\n\t * Event schema version for handling schema evolution.\n\t * Defaults to 1 if not specified. Higher versions indicate schema changes.\n\t */\n\tversion?: number;\n\n\t/**\n\t * Optional metadata for traceability, correlation, and auditing.\n\t * Includes correlationId, causationId, userId, source, and custom fields.\n\t */\n\tmetadata?: EventMetadata;\n}\n\n/**\n * Marker interface for Aggregate Roots.\n * \n * In Domain-Driven Design, an Aggregate Root is an Entity (the parent Entity of the aggregate).\n * It represents the aggregate externally and is the only object that external code\n * is allowed to hold references to. All access to child entities within the aggregate\n * must go through the Aggregate Root.\n * \n * An Aggregate consists of:\n * - One Aggregate Root (Entity with id + version)\n * - Optional child entities (Entities with id, but no own version)\n * - Optional value objects\n * \n * The Aggregate Root has identity (id) and version for optimistic concurrency control.\n * Child entities exist only within the aggregate boundary and are versioned through\n * the Aggregate Root.\n *\n * @template TId - The type of the aggregate root identifier\n *\n * @example\n * ```typescript\n * class Order extends AggregateBase<OrderState, OrderId> implements AggregateRoot<OrderId> {\n * // Order is an Aggregate Root (an Entity)\n * // OrderState contains child entities (e.g., OrderItem) and value objects\n * }\n * ```\n */\nexport interface AggregateRoot<TId extends Id<string>> {\n\t/**\n\t * Unique identifier of the aggregate root entity.\n\t */\n\treadonly id: TId;\n\n\t/**\n\t * Version number for optimistic concurrency control.\n\t * Incremented on each state change to detect concurrent modifications.\n\t * This version applies to the entire aggregate, including all child entities.\n\t */\n\treadonly version: Version;\n}\n\n/**\n * Structural interface representing an aggregate with state and events.\n * Used for type constraints in repositories and other infrastructure code.\n *\n * @template State - The type of the aggregate state\n * @template Evt - The union type of all domain events\n */\nexport interface Aggregate<State, Evt extends DomainEvent<string, unknown>> {\n\tstate: Readonly<State>;\n\tversion: Version;\n\tpendingEvents: ReadonlyArray<Evt>;\n}\n\nexport function aggregate<State, Evt extends DomainEvent<string, unknown>>(\n\tstate: State,\n\tversion: Version = 0 as Version,\n): Aggregate<State, Evt> {\n\treturn { state, version, pendingEvents: [] };\n}\n\nexport function withEvent<S, E extends DomainEvent<string, unknown>>(\n\tagg: Aggregate<S, E>,\n\tevt: E,\n): Aggregate<S, E> {\n\treturn { ...agg, pendingEvents: [...agg.pendingEvents, evt] };\n}\n\nexport function bump<S, E extends DomainEvent<string, unknown>>(\n\tagg: Aggregate<S, E>,\n): Aggregate<S, E> {\n\treturn { ...agg, version: (agg.version + 1) as Version };\n}\n\n/**\n * Creates a domain event with default values.\n * Sets occurredAt to current date and version to 1 if not provided.\n *\n * @param type - The event type\n * @param payload - The event payload\n * @param options - Optional event configuration\n * @returns A domain event\n *\n * @example\n * ```typescript\n * const event = createDomainEvent(\"OrderCreated\", { orderId: \"123\" });\n * ```\n */\nexport function createDomainEvent<T extends string, P>(\n\ttype: T,\n\tpayload: P,\n\toptions?: {\n\t\toccurredAt?: Date;\n\t\tversion?: number;\n\t\tmetadata?: EventMetadata;\n\t},\n): DomainEvent<T, P> {\n\treturn {\n\t\ttype,\n\t\tpayload,\n\t\toccurredAt: options?.occurredAt ?? new Date(),\n\t\tversion: options?.version ?? 1,\n\t\tmetadata: options?.metadata,\n\t};\n}\n\n/**\n * Creates a domain event with metadata for traceability.\n * Convenience function for creating events with correlation and causation IDs.\n *\n * @param type - The event type\n * @param payload - The event payload\n * @param metadata - Event metadata for traceability\n * @param options - Optional event configuration\n * @returns A domain event with metadata\n *\n * @example\n * ```typescript\n * const event = createDomainEventWithMetadata(\n * \"OrderCreated\",\n * { orderId: \"123\" },\n * {\n * correlationId: \"corr-123\",\n * causationId: \"cmd-456\",\n * userId: \"user-789\"\n * }\n * );\n * ```\n */\nexport function createDomainEventWithMetadata<T extends string, P>(\n\ttype: T,\n\tpayload: P,\n\tmetadata: EventMetadata,\n\toptions?: {\n\t\toccurredAt?: Date;\n\t\tversion?: number;\n\t},\n): DomainEvent<T, P> {\n\treturn createDomainEvent(type, payload, {\n\t\t...options,\n\t\tmetadata,\n\t});\n}\n\n/**\n * Copies metadata from a source event to a new event.\n * Useful for maintaining correlation chains in event-driven architectures.\n *\n * @param sourceEvent - The source event to copy metadata from\n * @param additionalMetadata - Additional metadata to merge in\n * @returns Event metadata with copied and merged values\n *\n * @example\n * ```typescript\n * const newEvent = createDomainEvent(\n * \"OrderShipped\",\n * { orderId: \"123\" },\n * {\n * metadata: copyMetadata(previousEvent, { causationId: previousEvent.type })\n * }\n * );\n * ```\n */\nexport function copyMetadata(\n\tsourceEvent: DomainEvent<string, unknown>,\n\tadditionalMetadata?: Partial<EventMetadata>,\n): EventMetadata {\n\treturn {\n\t\t...(sourceEvent.metadata ?? {}),\n\t\t...(additionalMetadata ?? {}),\n\t};\n}\n\n/**\n * Merges multiple metadata objects into one.\n * Later metadata objects override earlier ones for the same keys.\n *\n * @param metadataObjects - Array of metadata objects to merge\n * @returns Merged event metadata\n *\n * @example\n * ```typescript\n * const metadata = mergeMetadata(\n * { correlationId: \"corr-123\" },\n * { userId: \"user-456\" },\n * { source: \"order-service\" }\n * );\n * ```\n */\nexport function mergeMetadata(\n\t...metadataObjects: Array<EventMetadata | undefined>\n): EventMetadata {\n\treturn Object.assign({}, ...metadataObjects.filter(Boolean));\n}\n\n/**\n * Snapshot of an aggregate state at a specific point in time.\n * Used for optimizing event replay by starting from a snapshot\n * instead of replaying all events from the beginning.\n *\n * @template TState - The type of the aggregate state\n */\nexport interface AggregateSnapshot<TState> {\n\t/**\n\t * The state of the aggregate at the time of the snapshot.\n\t */\n\tstate: TState;\n\n\t/**\n\t * The version of the aggregate when the snapshot was taken.\n\t */\n\tversion: Version;\n\n\t/**\n\t * Timestamp when the snapshot was created.\n\t */\n\tsnapshotAt: Date;\n}\n\n/**\n * Checks if two aggregates are the same (same ID and version).\n * Useful for optimistic concurrency control checks.\n *\n * @param a - First aggregate\n * @param b - Second aggregate\n * @returns true if both aggregates have the same ID and version\n *\n * @example\n * ```typescript\n * const aggregate1 = await repository.getById(id);\n * // ... some operations ...\n * const aggregate2 = await repository.getById(id);\n *\n * if (!sameAggregate(aggregate1, aggregate2)) {\n * throw new Error(\"Aggregate was modified by another process\");\n * }\n * ```\n */\nexport function sameAggregate<TId extends Id<string>>(\n\ta: { id: TId; version: Version },\n\tb: { id: TId; version: Version },\n): boolean {\n\treturn a.id === b.id && a.version === b.version;\n}\n","import type { Id } from \"../core/id\";\nimport type {\n\tAggregateRoot,\n\tAggregateSnapshot,\n\tVersion,\n} from \"./aggregate\";\n\n/**\n * Configuration options for AggregateBase behavior.\n */\nexport interface AggregateConfig {\n\t/**\n\t * Whether to automatically bump the version when state changes.\n\t * Defaults to false. Set to true for automatic versioning.\n\t */\n\tautoVersionBump?: boolean;\n}\n\n/**\n * Base class for creating Aggregate Roots (Entities) without Event Sourcing.\n * \n * This class creates an Entity that serves as the Aggregate Root. The Aggregate Root\n * is the parent Entity of the aggregate and represents it externally. It has identity\n * (id) and version for optimistic concurrency control.\n * \n * The aggregate state (`TState`) contains:\n * - Child entities (Entities with id, but no own version)\n * - Value objects (immutable objects)\n * \n * All changes to child entities are versioned through the Aggregate Root. The version\n * applies to the entire aggregate, including all child entities.\n * \n * Provides core functionality:\n * - ID and Version management (for Optimistic Concurrency Control)\n * - State management (containing child entities and value objects)\n * - Snapshot support for performance optimization\n *\n * Implements `AggregateRoot<TId>` to mark this as an Aggregate Root Entity.\n *\n * Use this class when you don't need Event Sourcing but still want\n * aggregate patterns with versioning and state management.\n *\n * @template TState - The type of the aggregate state (contains child entities and value objects)\n * @template TId - The type of the aggregate root identifier\n *\n * @example\n * ```typescript\n * // Order is an Aggregate Root (an Entity)\n * class Order extends AggregateBase<OrderState, OrderId> implements AggregateRoot<OrderId> {\n * constructor(id: OrderId, initialState: OrderState) {\n * super(id, initialState);\n * }\n *\n * confirm(): void {\n * this._state = { ...this._state, status: \"confirmed\" };\n * this.bumpVersion(); // Versions the entire aggregate\n * }\n * }\n * ```\n */\nexport abstract class AggregateBase<TState, TId extends Id<string>>\n\timplements AggregateRoot<TId>\n{\n\tpublic readonly id: TId;\n\tpublic version: Version = 0 as Version;\n\n\tprivate readonly _config: AggregateConfig;\n\tprivate readonly _autoVersionBump: boolean;\n\n\tpublic get state(): TState {\n\t\treturn this._state;\n\t}\n\n\t/**\n\t * The state is 'protected' so that only the subclass can change it.\n\t * Subclasses can mutate this directly or use helper methods.\n\t */\n\tprotected _state: TState;\n\n\tprotected constructor(\n\t\tid: TId,\n\t\tinitialState: TState,\n\t\tconfig?: AggregateConfig,\n\t) {\n\t\tthis.id = id;\n\t\tthis._state = initialState;\n\t\tthis._config = config ?? {};\n\t\tthis._autoVersionBump = this._config.autoVersionBump ?? false;\n\t}\n\n\t/**\n\t * Manually bumps the aggregate version.\n\t * Call this after state changes for Optimistic Concurrency Control.\n\t *\n\t * If `autoVersionBump` is enabled, this is called automatically\n\t * when using `setState()`.\n\t */\n\tprotected bumpVersion(): void {\n\t\tthis.version = (this.version + 1) as Version;\n\t}\n\n\t/**\n\t * Sets the state and optionally bumps the version automatically.\n\t * This is a convenience method for state mutations.\n\t *\n\t * @param newState - The new state\n\t * @param bumpVersion - Whether to bump the version (defaults to autoVersionBump config)\n\t */\n\tprotected setState(\n\t\tnewState: TState,\n\t\tbumpVersion?: boolean,\n\t): void {\n\t\tthis._state = newState;\n\t\tconst shouldBump = bumpVersion ?? this._autoVersionBump;\n\t\tif (shouldBump) {\n\t\t\tthis.bumpVersion();\n\t\t}\n\t}\n\n\t/**\n\t * Creates a snapshot of the current aggregate state.\n\t * Useful for performance optimization, backup/restore, and audit trails.\n\t *\n\t * @returns A snapshot containing the current state and version\n\t *\n\t * @example\n\t * ```typescript\n\t * const snapshot = aggregate.createSnapshot();\n\t * await snapshotRepository.save(aggregate.id, snapshot);\n\t * ```\n\t */\n\tpublic createSnapshot(): AggregateSnapshot<TState> {\n\t\treturn {\n\t\t\tstate: { ...this._state } as TState,\n\t\t\tversion: this.version,\n\t\t\tsnapshotAt: new Date(),\n\t\t};\n\t}\n\n\t/**\n\t * Restores the aggregate from a snapshot.\n\t * This is useful for loading aggregates from snapshots instead of\n\t * rebuilding them from scratch.\n\t *\n\t * @param snapshot - The snapshot to restore from\n\t *\n\t * @example\n\t * ```typescript\n\t * const snapshot = await snapshotRepository.getLatest(aggregateId);\n\t * aggregate.restoreFromSnapshot(snapshot);\n\t * ```\n\t */\n\tpublic restoreFromSnapshot(snapshot: AggregateSnapshot<TState>): void {\n\t\tthis._state = snapshot.state;\n\t\tthis.version = snapshot.version;\n\t}\n}\n","export type Ok<T> = { ok: true; value: T };\nexport type Err<E> = { ok: false; error: E };\nexport type Result<T, E> = Ok<T> | Err<E>;\n\n/**\n * Creates an Ok result with a value.\n *\n * @param value - The success value\n * @returns An Ok result containing the value\n *\n * @example\n * ```typescript\n * const result = ok(42);\n * // result is Ok<number>\n * ```\n */\nexport function ok<T>(value: T): Ok<T>;\n\n/**\n * Creates an Ok result with void (no value).\n *\n * @returns An Ok<void> result\n *\n * @example\n * ```typescript\n * const result = ok();\n * // result is Ok<void>\n * ```\n */\nexport function ok(): Ok<void>;\n\nexport function ok<T>(value?: T): Ok<T> {\n\treturn { ok: true, value: value as T };\n}\n\n/**\n * Creates an Err result with an error.\n *\n * @param error - The error value\n * @returns An Err result containing the error\n *\n * @example\n * ```typescript\n * const result = err(\"Something went wrong\");\n * // result is Err<string>\n * ```\n */\nexport function err<E>(error: E): Err<E>;\n\n/**\n * Creates an Err result with void (no error value).\n *\n * @returns An Err<void> result\n *\n * @example\n * ```typescript\n * const result = err();\n * // result is Err<void>\n * ```\n */\nexport function err(): Err<void>;\n\nexport function err<E>(error?: E): Err<E> {\n\treturn { ok: false, error: error as E };\n}\n\n/**\n * Type guard to check if a Result is Ok.\n * Narrows the type to Ok<T> when returning true.\n *\n * @param result - The result to check\n * @returns true if the result is Ok, false otherwise\n *\n * @example\n * ```typescript\n * const result = voWithValidation(data, validator);\n * if (isOk(result)) {\n * // TypeScript knows result is Ok<VO<T>>\n * console.log(result.value);\n * }\n * ```\n */\nexport function isOk<T, E>(result: Result<T, E>): result is Ok<T> {\n\treturn result.ok === true;\n}\n\n/**\n * Type guard to check if a Result is Err.\n * Narrows the type to Err<E> when returning true.\n *\n * @param result - The result to check\n * @returns true if the result is Err, false otherwise\n *\n * @example\n * ```typescript\n * const result = voWithValidation(data, validator);\n * if (isErr(result)) {\n * // TypeScript knows result is Err<string>\n * console.error(result.error);\n * }\n * ```\n */\nexport function isErr<T, E>(result: Result<T, E>): result is Err<E> {\n\treturn result.ok === false;\n}\n\n/**\n * Chains Result operations (flatMap/bind).\n * If the result is Ok, applies the function to the value.\n * If Err, returns the error unchanged.\n *\n * @param result - The result to chain\n * @param fn - Function that takes the Ok value and returns a new Result\n * @returns A new Result\n *\n * @example\n * ```typescript\n * const result = validateUserId(\"123\")\n * .andThen(userId => validateEmail(\"test@example.com\")\n * .map(email => ({ id: userId, email }))\n * );\n * ```\n */\nexport function andThen<T, E, U>(\n\tresult: Result<T, E>,\n\tfn: (value: T) => Result<U, E>,\n): Result<U, E> {\n\tif (result.ok) {\n\t\treturn fn(result.value);\n\t}\n\treturn result;\n}\n\n/**\n * Transforms the Ok value using a function.\n * If the result is Err, returns the error unchanged.\n *\n * @param result - The result to transform\n * @param fn - Function to transform the Ok value\n * @returns A new Result with transformed value\n *\n * @example\n * ```typescript\n * const result = ok(5);\n * const doubled = map(result, x => x * 2); // Ok<10>\n * ```\n */\nexport function map<T, E, U>(\n\tresult: Result<T, E>,\n\tfn: (value: T) => U,\n): Result<U, E> {\n\tif (result.ok) {\n\t\treturn ok(fn(result.value));\n\t}\n\treturn result;\n}\n\n/**\n * Transforms the Err value using a function.\n * If the result is Ok, returns the value unchanged.\n *\n * @param result - The result to transform\n * @param fn - Function to transform the Err value\n * @returns A new Result with transformed error\n *\n * @example\n * ```typescript\n * const result = err(\"not found\");\n * const mapped = mapErr(result, e => `Error: ${e}`); // Err<\"Error: not found\">\n * ```\n */\nexport function mapErr<T, E, F>(\n\tresult: Result<T, E>,\n\tfn: (error: E) => F,\n): Result<T, F> {\n\tif (result.ok) {\n\t\treturn result;\n\t}\n\treturn err(fn(result.error));\n}\n\n/**\n * Returns the value if Ok, otherwise returns the default value.\n *\n * @param result - The result to unwrap\n * @param defaultValue - Default value to return if Err\n * @returns The Ok value or the default value\n *\n * @example\n * ```typescript\n * const result = validateUserId(\"123\");\n * const userId = unwrapOr(result, \"default-id\");\n * ```\n */\nexport function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {\n\treturn result.ok ? result.value : defaultValue;\n}\n\n/**\n * Returns the value if Ok, otherwise computes default from error.\n *\n * @param result - The result to unwrap\n * @param fn - Function to compute default from error\n * @returns The Ok value or computed default\n *\n * @example\n * ```typescript\n * const result = validateUserId(\"\");\n * const userId = unwrapOrElse(result, err => `fallback-${Date.now()}`);\n * ```\n */\nexport function unwrapOrElse<T, E>(\n\tresult: Result<T, E>,\n\tfn: (error: E) => T,\n): T {\n\treturn result.ok ? result.value : fn(result.error);\n}\n\n/**\n * Pattern matching for Result.\n * Applies one function if Ok, another if Err.\n *\n * @param result - The result to match\n * @param onOk - Function to apply if Ok\n * @param onErr - Function to apply if Err\n * @returns The result of applying the appropriate function\n *\n * @example\n * ```typescript\n * const message = match(result,\n * value => `Success: ${value}`,\n * error => `Error: ${error}`\n * );\n * ```\n *\n * @example Using object syntax\n * ```typescript\n * const message = match(result, {\n * ok: value => `Success: ${value}`,\n * err: error => `Error: ${error}`\n * });\n * ```\n */\nexport function match<T, E, R>(\n\tresult: Result<T, E>,\n\tonOk: (value: T) => R,\n\tonErr: (error: E) => R,\n): R;\nexport function match<T, E, R>(\n\tresult: Result<T, E>,\n\thandlers: { ok: (value: T) => R; err: (error: E) => R },\n): R;\nexport function match<T, E, R>(\n\tresult: Result<T, E>,\n\tonOkOrHandlers: ((value: T) => R) | { ok: (value: T) => R; err: (error: E) => R },\n\tonErr?: (error: E) => R,\n): R {\n\tif (typeof onOkOrHandlers === \"function\") {\n\t\t// Function syntax: match(result, onOk, onErr)\n\t\treturn result.ok ? onOkOrHandlers(result.value) : onErr!(result.error);\n\t}\n\t// Object syntax: match(result, { ok: ..., err: ... })\n\treturn result.ok\n\t\t? onOkOrHandlers.ok(result.value)\n\t\t: onOkOrHandlers.err(result.error);\n}\n\n/**\n * Async pattern matching for Result.\n * Applies one async function if Ok, another if Err.\n * Both handlers must return Promises.\n *\n * @param result - The result to match\n * @param onOk - Async function to apply if Ok\n * @param onErr - Async function to apply if Err\n * @returns Promise resolving to the result of applying the appropriate function\n *\n * @example\n * ```typescript\n * const message = await matchAsync(result,\n * async (value) => `Success: ${value}`,\n * async (error) => `Error: ${error}`\n * );\n * ```\n *\n * @example Using object syntax\n * ```typescript\n * const message = await matchAsync(result, {\n * ok: async (value) => `Success: ${value}`,\n * err: async (error) => `Error: ${error}`\n * });\n * ```\n */\nexport async function matchAsync<T, E, R>(\n\tresult: Result<T, E>,\n\tonOk: (value: T) => Promise<R>,\n\tonErr: (error: E) => Promise<R>,\n): Promise<R>;\nexport async function matchAsync<T, E, R>(\n\tresult: Result<T, E>,\n\thandlers: { ok: (value: T) => Promise<R>; err: (error: E) => Promise<R> },\n): Promise<R>;\nexport async function matchAsync<T, E, R>(\n\tresult: Result<T, E>,\n\tonOkOrHandlers:\n\t\t| ((value: T) => Promise<R>)\n\t\t| { ok: (value: T) => Promise<R>; err: (error: E) => Promise<R> },\n\tonErr?: (error: E) => Promise<R>,\n): Promise<R> {\n\tif (typeof onOkOrHandlers === \"function\") {\n\t\t// Function syntax: matchAsync(result, onOk, onErr)\n\t\treturn result.ok\n\t\t\t? onOkOrHandlers(result.value)\n\t\t\t: onErr!(result.error);\n\t}\n\t// Object syntax: matchAsync(result, { ok: ..., err: ... })\n\treturn result.ok\n\t\t? onOkOrHandlers.ok(result.value)\n\t\t: onOkOrHandlers.err(result.error);\n}\n\n/**\n * Pattern matching for Result that returns a Result.\n * Both handlers must return a Result, allowing you to transform\n * both the success and error cases while staying in Result context.\n *\n * @param result - The result to match\n * @param handlers - Object with ok and err handlers, both returning Result\n * @returns A new Result from the appropriate handler\n *\n * @example\n * ```typescript\n * const result = await fetchUser(id);\n * return matchResult(result, {\n * ok: (user) => ok(transformUser(user)),\n * err: (error) => err(mapToAppError(error))\n * });\n * ```\n */\nexport function matchResult<T, E, U, F>(\n\tresult: Result<T, E>,\n\thandlers: {\n\t\tok: (value: T) => Result<U, F>;\n\t\terr: (error: E) => Result<U, F>;\n\t},\n): Result<U, F>;\nexport function matchResult<T, E, U, F>(\n\tresult: Result<T, E>,\n\tonOk: (value: T) => Result<U, F>,\n\tonErr: (error: E) => Result<U, F>,\n): Result<U, F>;\nexport function matchResult<T, E, U, F>(\n\tresult: Result<T, E>,\n\tonOkOrHandlers:\n\t\t| ((value: T) => Result<U, F>)\n\t\t| { ok: (value: T) => Result<U, F>; err: (error: E) => Result<U, F> },\n\tonErr?: (error: E) => Result<U, F>,\n): Result<U, F> {\n\tif (typeof onOkOrHandlers === \"function\") {\n\t\treturn result.ok ? onOkOrHandlers(result.value) : onErr!(result.error);\n\t}\n\treturn result.ok\n\t\t? onOkOrHandlers.ok(result.value)\n\t\t: onOkOrHandlers.err(result.error);\n}\n\n/**\n * Pipes a Result through multiple operations.\n * Each function receives the previous Result and returns a new Result.\n * Stops on first error.\n *\n * @param initial - The initial Result value\n * @param fns - Array of functions that take the previous Result and return a new Result\n * @returns The final Result after all operations\n *\n * @example\n * ```typescript\n * // Instead of nested andThen calls:\n * andThen(\n * updateCountryCode(code),\n * () => andThen(updateCurrencyCode(currency), () => updateLanguageCode(lang))\n * )\n *\n * // Use pipe (cleaner and more readable):\n * pipe(\n * updateCountryCode(code),\n * () => updateCurrencyCode(currency),\n * () => updateLanguageCode(lang)\n * )\n * ```\n *\n * @example With void results\n * ```typescript\n * setInitialData(initialData: JobConfigProps[\"initialData\"]): Result<void, JobDomainError> {\n * return pipe(\n * this.updateCountryCode(initialData.countryCode),\n * () => this.updateCurrencyCode(initialData.currencyCode),\n * () => this.updateLanguageCode(initialData.languageCode)\n * );\n * }\n * ```\n */\nexport function pipe<T, E>(\n\tinitial: Result<T, E>,\n\t...fns: Array<(prev: Result<T, E>) => Result<T, E>>\n): Result<T, E> {\n\tlet current = initial;\n\tfor (const fn of fns) {\n\t\tcurrent = fn(current);\n\t\tif (!current.ok) {\n\t\t\treturn current;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * Wraps a function that may throw exceptions into a Result type.\n * Catches any thrown exceptions and converts them to Err results.\n *\n * @param fn - Function that may throw exceptions\n * @param errorMapper - Optional function to transform the caught error\n * @returns A Result containing the function's return value or error\n *\n * @example\n * ```typescript\n * function riskyOperation(): string {\n * if (Math.random() > 0.5) {\n * throw new Error(\"Something went wrong\");\n * }\n * return \"success\";\n * }\n *\n * const result = tryCatch(() => riskyOperation());\n * if (result.ok) {\n * console.log(result.value); // \"success\"\n * } else {\n * console.error(result.error.message); // \"Something went wrong\"\n * }\n * ```\n *\n * @example With custom error mapper\n * ```typescript\n * const result = tryCatch(\n * () => riskyOperation(),\n * (error) => `Custom: ${error instanceof Error ? error.message : String(error)}`\n * );\n * ```\n */\nexport function tryCatch<T, E = Error>(\n\tfn: () => T,\n\terrorMapper?: (error: unknown) => E,\n): Result<T, E> {\n\ttry {\n\t\treturn ok(fn());\n\t} catch (error) {\n\t\tif (errorMapper) {\n\t\t\treturn err(errorMapper(error));\n\t\t}\n\t\treturn err((error instanceof Error ? error : new Error(String(error))) as E);\n\t}\n}\n\n/**\n * Wraps an async function that may throw exceptions into a Promise<Result>.\n * Catches any thrown exceptions and converts them to Err results.\n *\n * @param fn - Async function that may throw exceptions\n * @param errorMapper - Optional function to transform the caught error\n * @returns A Promise resolving to a Result containing the function's return value or error\n *\n * @example\n * ```typescript\n * async function riskyAsyncOperation(): Promise<string> {\n * if (Math.random() > 0.5) {\n * throw new Error(\"Something went wrong\");\n * }\n * return \"success\";\n * }\n *\n * const result = await tryCatchAsync(() => riskyAsyncOperation());\n * if (result.ok) {\n * console.log(result.value); // \"success\"\n * } else {\n * console.error(result.error.message); // \"Something went wrong\"\n * }\n * ```\n */\nexport async function tryCatchAsync<T, E = Error>(\n\tfn: () => Promise<T>,\n\terrorMapper?: (error: unknown) => E,\n): Promise<Result<T, E>> {\n\ttry {\n\t\tconst value = await fn();\n\t\treturn ok(value);\n\t} catch (error) {\n\t\tif (errorMapper) {\n\t\t\treturn err(errorMapper(error));\n\t\t}\n\t\treturn err((error instanceof Error ? error : new Error(String(error))) as E);\n\t}\n}\n\n","import { err, ok, type Result } from \"../core/result\";\nimport type { Id } from \"../core/id\";\nimport { AggregateBase, type AggregateConfig } from \"./aggregate-base\";\nimport type {\n\tAggregateSnapshot,\n\tDomainEvent,\n\tVersion,\n} from \"./aggregate\";\n\ntype Handler<TState, TEvent> = (state: TState, event: TEvent) => TState;\n\n/**\n * Extended configuration options for AggregateEventSourced behavior.\n */\nexport interface AggregateEventSourcedConfig extends AggregateConfig {\n\t/**\n\t * Whether to automatically bump the version when applying new events.\n\t * Defaults to true. Set to false to manually control versioning.\n\t */\n\tautoVersionBump?: boolean;\n}\n\n/**\n * Base class for Event-Sourced Aggregate Roots (Entities).\n * \n * Extends `AggregateBase` to create an Aggregate Root Entity with Event Sourcing capabilities.\n * The Aggregate Root is the parent Entity of the aggregate and represents it externally.\n * \n * The aggregate state (`TState`) contains:\n * - Child entities (Entities with id, but no own version)\n * - Value objects (immutable objects)\n * \n * All changes to child entities are versioned through the Aggregate Root. The version\n * applies to the entire aggregate, including all child entities.\n * \n * Extends `AggregateBase` with Event Sourcing capabilities:\n * - Event tracking (pendingEvents)\n * - Event handlers for state transitions\n * - Event validation\n * - History replay\n *\n * Use this class when you want Event Sourcing with full event tracking\n * and replay capabilities.\n *\n * @template TState - The type of the aggregate state (contains child entities and value objects)\n * @template TEvent - The union type of all domain events\n * @template TId - The type of the aggregate root identifier\n *\n * @example\n * ```typescript\n * // Order is an Aggregate Root (an Entity) with Event Sourcing\n * class Order extends AggregateEventSourced<OrderState, OrderEvent, OrderId> {\n * confirm(): void {\n * this.apply(createDomainEvent(\"OrderConfirmed\", {}));\n * }\n *\n * protected readonly handlers = {\n * OrderConfirmed: (state: OrderState): OrderState => ({\n * ...state,\n * status: \"confirmed\",\n * }),\n * };\n * }\n * ```\n */\nexport abstract class AggregateEventSourced<\n\tTState,\n\tTEvent extends DomainEvent<string, unknown>,\n\tTId extends Id<string>,\n> extends AggregateBase<TState, TId> {\n\tprivate readonly _eventConfig: AggregateEventSourcedConfig;\n\tprivate readonly _eventAutoVersionBump: boolean;\n\n\tprivate readonly _pendingEvents: TEvent[] = [];\n\n\tprotected constructor(\n\t\tid: TId,\n\t\tinitialState: TState,\n\t\tconfig?: AggregateEventSourcedConfig,\n\t) {\n\t\tsuper(id, initialState, config);\n\t\tthis._eventConfig = config ?? {};\n\t\tthis._eventAutoVersionBump = this._eventConfig.autoVersionBump ?? true;\n\t}\n\n\t/**\n\t * Returns a read-only list of new, not-yet-persisted events.\n\t */\n\tpublic get pendingEvents(): ReadonlyArray<TEvent> {\n\t\treturn this._pendingEvents;\n\t}\n\n\t/**\n\t * Clears the list of pending events.\n\t * Typically called after the events have been persisted.\n\t */\n\tpublic clearPendingEvents(): void {\n\t\tthis._pendingEvents.length = 0;\n\t}\n\n\t/**\n\t * Validates an event before it is applied.\n\t * Override this method to add custom validation logic.\n\t * Return `ok(true)` if the event is valid, `err(message)` otherwise.\n\t *\n\t * @param event - The event to validate\n\t * @returns Result indicating if the event is valid\n\t *\n\t * @example\n\t * ```typescript\n\t * protected validateEvent(event: OrderEvent): Result<true, string> {\n\t * if (event.type === \"OrderShipped\" && this.state.status !== \"confirmed\") {\n\t * return err(\"Order must be confirmed before shipping\");\n\t * }\n\t * return ok(true);\n\t * }\n\t * ```\n\t */\n\tprotected validateEvent(_event: TEvent): Result<true, string> {\n\t\treturn ok(true);\n\t}\n\n\t/**\n\t * Applies an event to change the state and adds it\n\t * to the list of pending events.\n\t * Returns a Result type instead of throwing an error.\n\t *\n\t * @param event - The domain event to apply\n\t * @param isNew - Indicates whether the event is new (and needs to be persisted)\n\t * or if it is being loaded from history\n\t * @returns Result<void, string> - ok if successful, err with error message if validation fails or handler is missing\n\t */\n\tprotected apply(event: TEvent, isNew = true): Result<void, string> {\n\t\t// Validate event before applying\n\t\tconst validation = this.validateEvent(event);\n\t\tif (!validation.ok) {\n\t\t\treturn err(\n\t\t\t\t`Event validation failed for ${event.type}: ${validation.error}`,\n\t\t\t);\n\t\t}\n\n\t\tconst handler = this.handlers[event.type as keyof typeof this.handlers];\n\t\tif (!handler) {\n\t\t\treturn err(`Missing handler for event type: ${event.type}`);\n\t\t}\n\n\t\t// First, change the state\n\t\tthis._state = handler(\n\t\t\tthis._state,\n\t\t\tevent as Extract<TEvent, { type: TEvent[\"type\"] }>,\n\t\t);\n\n\t\t// Then (if new) add the event to the list and bump version\n\t\tif (isNew) {\n\t\t\tthis._pendingEvents.push(event);\n\t\t\tif (this._eventAutoVersionBump) {\n\t\t\t\tthis.version = (this.version + 1) as Version;\n\t\t\t}\n\t\t}\n\n\t\treturn ok();\n\t}\n\n\t/**\n\t * Applies an event to change the state and adds it\n\t * to the list of pending events.\n\t * Throws an error if validation fails or handler is missing.\n\t *\n\t * @param event - The domain event to apply\n\t * @param isNew - Indicates whether the event is new (and needs to be persisted)\n\t * or if it is being loaded from history\n\t * @throws Error if event validation fails or handler is missing\n\t */\n\tprotected applyUnsafe(event: TEvent, isNew = true): void {\n\t\t// Validate event before applying\n\t\tconst validation = this.validateEvent(event);\n\t\tif (!validation.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Event validation failed for ${event.type}: ${validation.error}`,\n\t\t\t);\n\t\t}\n\n\t\tconst handler = this.handlers[event.type as keyof typeof this.handlers];\n\t\tif (!handler) {\n\t\t\tthrow new Error(`Missing handler for event type: ${event.type}`);\n\t\t}\n\n\t\t// First, change the state\n\t\tthis._state = handler(\n\t\t\tthis._state,\n\t\t\tevent as Extract<TEvent, { type: TEvent[\"type\"] }>,\n\t\t);\n\n\t\t// Then (if new) add the event to the list and bump version\n\t\tif (isNew) {\n\t\t\tthis._pendingEvents.push(event);\n\t\t\tif (this._eventAutoVersionBump) {\n\t\t\t\tthis.version = (this.version + 1) as Version;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Manually bumps the aggregate version.\n\t * Only needed if `autoVersionBump` is disabled.\n\t */\n\tprotected bumpVersion(): void {\n\t\tthis.version = (this.version + 1) as Version;\n\t}\n\n\t/**\n\t * Reconstitutes the aggregate from an event history.\n\t * Sets the version to the number of events in the history.\n\t *\n\t * @param history - An ordered list of past events\n\t */\n\tpublic loadFromHistory(history: TEvent[]): Result<void, string> {\n\t\tfor (const event of history) {\n\t\t\tconst result = this.apply(event, false); // 'false' as it's not a new event\n\t\t\tif (!result.ok) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\t// Set version to the number of events in history\n\t\tthis.version = history.length as Version;\n\t\treturn ok();\n\t}\n\n\t/**\n\t * Checks if the aggregate has any pending events.\n\t *\n\t * @returns true if there are pending events, false otherwise\n\t */\n\tpublic hasPendingEvents(): boolean {\n\t\treturn this._pendingEvents.length > 0;\n\t}\n\n\t/**\n\t * Returns the number of pending events.\n\t *\n\t * @returns The count of pending events\n\t */\n\tpublic getEventCount(): number {\n\t\treturn this._pendingEvents.length;\n\t}\n\n\t/**\n\t * Returns the latest pending event, if any.\n\t *\n\t * @returns The most recent event or undefined if no events exist\n\t */\n\tpublic getLatestEvent(): TEvent | undefined {\n\t\treturn this._pendingEvents[this._pendingEvents.length - 1];\n\t}\n\n\t/**\n\t * Restores the aggregate from a snapshot and applies events that occurred after the snapshot.\n\t * This is more efficient than replaying all events from the beginning.\n\t *\n\t * @param snapshot - The snapshot to restore from\n\t * @param eventsAfterSnapshot - Events that occurred after the snapshot was taken\n\t *\n\t * @example\n\t * ```typescript\n\t * const snapshot = await snapshotRepository.getLatest(aggregateId);\n\t * const eventsAfter = await eventStore.getEventsAfter(aggregateId, snapshot.version);\n\t * aggregate.restoreFromSnapshotWithEvents(snapshot, eventsAfter);\n\t * ```\n\t */\n\tpublic restoreFromSnapshotWithEvents(\n\t\tsnapshot: AggregateSnapshot<TState>,\n\t\teventsAfterSnapshot: TEvent[],\n\t): Result<void, string> {\n\t\tthis._state = snapshot.state;\n\t\tthis.version = snapshot.version;\n\n\t\t// Apply events that occurred after the snapshot\n\t\tfor (const event of eventsAfterSnapshot) {\n\t\t\tconst result = this.apply(event, false);\n\t\t\tif (!result.ok) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\t// Set version to snapshot version + events after snapshot\n\t\tthis.version = (snapshot.version + eventsAfterSnapshot.length) as Version;\n\t\treturn ok();\n\t}\n\n\t/**\n\t * A map of event types to their corresponding handlers.\n\t * Subclasses MUST implement this property.\n\t */\n\tprotected abstract readonly handlers: {\n\t\t[K in TEvent[\"type\"]]: Handler<TState, Extract<TEvent, { type: K }>>;\n\t};\n}\n\n","import type { Result } from \"../core/result\";\nimport { err } from \"../core/result\";\nimport type { Command, CommandHandler } from \"./command\";\n\n/**\n * Command Bus interface for dispatching commands to their handlers.\n * Provides a centralized way to execute commands with handler registration.\n *\n * @example\n * ```typescript\n * const bus = new CommandBus();\n * bus.register(\"CreateOrder\", createOrderHandler);\n *\n * const result = await bus.execute({\n * type: \"CreateOrder\",\n * customerId: \"123\",\n * items: [...]\n * });\n * ```\n */\nexport interface ICommandBus {\n\t/**\n\t * Executes a command by dispatching it to the registered handler.\n\t *\n\t * @param command - The command to execute\n\t * @returns Result containing the success value or error message\n\t */\n\texecute<C extends Command, R>(command: C): Promise<Result<R, string>>;\n\n\t/**\n\t * Registers a handler for a specific command type.\n\t *\n\t * @param commandType - The command type to register the handler for\n\t * @param handler - The handler function for this command type\n\t */\n\tregister<C extends Command, R>(\n\t\tcommandType: C[\"type\"],\n\t\thandler: CommandHandler<C, R>,\n\t): void;\n}\n\n/**\n * Simple in-memory command bus implementation.\n * Handlers are stored in a Map and dispatched based on command type.\n *\n * **Note:** This is a basic implementation suitable for development and simple use cases.\n * For production environments, consider implementing or using a more feature-rich bus that includes:\n * - Middleware/Pipeline support (logging, validation, authorization)\n * - Error handling and retry logic\n * - Timeout handling\n * - Metrics and observability\n * - Transaction management\n * - Dead letter queue support\n *\n * The `CommandHandler` type can still be used with external production-grade buses\n * (e.g., RabbitMQ, AWS SQS) while maintaining type safety.\n *\n * @example\n * ```typescript\n * const bus = new CommandBus();\n * bus.register(\"CreateOrder\", async (cmd) => {\n * // ... handler logic\n * return ok(orderId);\n * });\n *\n * const result = await bus.execute({ type: \"CreateOrder\", ... });\n * ```\n */\nexport class CommandBus implements ICommandBus {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate readonly handlers = new Map<string, CommandHandler<any, any>>();\n\n\tregister<C extends Command, R>(\n\t\tcommandType: C[\"type\"],\n\t\thandler: CommandHandler<C, R>,\n\t): void {\n\t\tthis.handlers.set(commandType, handler);\n\t}\n\n\tasync execute<C extends Command, R>(\n\t\tcommand: C,\n\t): Promise<Result<R, string>> {\n\t\tconst handler = this.handlers.get(command.type);\n\t\tif (!handler) {\n\t\t\treturn err(`No handler registered for command type: ${command.type}`);\n\t\t}\n\t\treturn handler(command);\n\t}\n}\n\n","import type { EventBus, Outbox } from \"../events/ports\";\nimport type { UnitOfWork } from \"../repo/uow\";\n\n/**\n * Helper function for executing commands within a transaction.\n * Handles event persistence via outbox and optional event bus publishing.\n *\n * @param deps - Dependencies including outbox, optional event bus, and unit of work\n * @param fn - Function that returns result and events\n * @returns The result wrapped in a transaction\n *\n * @example\n * ```typescript\n * const result = await withCommit(\n * { outbox, bus, uow },\n * async () => {\n * const order = Order.create(customerId, items);\n * await repository.save(order);\n * return {\n * result: order.id,\n * events: order.pendingEvents\n * };\n * }\n * );\n * ```\n */\nexport function withCommit<Evt, R>(\n\tdeps: {\n\t\toutbox: Outbox<Evt>;\n\t\tbus?: EventBus<Evt>;\n\t\tuow: UnitOfWork;\n\t},\n\tfn: () => Promise<{ result: R; events: ReadonlyArray<Evt> }>,\n) {\n\treturn deps.uow.transactional(async () => {\n\t\tconst { result, events } = await fn();\n\t\tawait deps.outbox.add(events);\n\t\tif (deps.bus) await deps.bus.publish(events);\n\t\treturn result;\n\t});\n}\n","import { err, ok, type Result } from \"../core/result\";\nimport type { Query, QueryHandler } from \"./query\";\n\n/**\n * Query Bus interface for dispatching queries to their handlers.\n * Provides a centralized way to execute queries with handler registration.\n *\n * @example\n * ```typescript\n * const bus = new QueryBus();\n * bus.register(\"GetOrder\", getOrderHandler);\n *\n * const order = await bus.execute({\n * type: \"GetOrder\",\n * orderId: \"123\"\n * });\n * ```\n */\nexport interface IQueryBus {\n\t/**\n\t * Executes a query by dispatching it to the registered handler.\n\t * Returns a Result type instead of throwing an error.\n\t *\n\t * @param query - The query to execute\n\t * @returns Result containing the query result if successful, or an error message if no handler is registered\n\t */\n\texecute<Q extends Query, R>(query: Q): Promise<Result<R, string>>;\n\n\t/**\n\t * Executes a query by dispatching it to the registered handler.\n\t * Throws an error if no handler is registered.\n\t *\n\t * @param query - The query to execute\n\t * @returns The query result\n\t * @throws Error if no handler is registered for the query type\n\t */\n\texecuteUnsafe<Q extends Query, R>(query: Q): Promise<R>;\n\n\t/**\n\t * Registers a handler for a specific query type.\n\t *\n\t * @param queryType - The query type to register the handler for\n\t * @param handler - The handler function for this query type\n\t */\n\tregister<Q extends Query, R>(\n\t\tqueryType: Q[\"type\"],\n\t\thandler: QueryHandler<Q, R>,\n\t): void;\n}\n\n/**\n * Type map for query types to their return types.\n * Used to improve type inference in QueryBus.\n */\ntype QueryTypeMap = Record<string, unknown>;\n\n/**\n * Simple in-memory query bus implementation.\n * Handlers are stored in a Map and dispatched based on query type.\n *\n * **Note:** This is a basic implementation suitable for development and simple use cases.\n * For production environments, consider implementing or using a more feature-rich bus that includes:\n * - Middleware/Pipeline support (logging, caching, rate limiting)\n * - Error handling\n * - Timeout handling\n * - Metrics and observability\n * - Query result caching\n * - Rate limiting\n *\n * The `QueryHandler` type can still be used with external production-grade buses\n * (e.g., RabbitMQ, AWS SQS) while maintaining type safety.\n *\n * @example\n * ```typescript\n * const bus = new QueryBus();\n * bus.register(\"GetOrder\", async (query) => {\n * return await repository.getById(query.orderId);\n * });\n *\n * const order = await bus.execute({ type: \"GetOrder\", orderId: \"123\" });\n * ```\n */\nexport class QueryBus<TMap extends QueryTypeMap = QueryTypeMap>\n\timplements IQueryBus\n{\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate readonly handlers = new Map<string, QueryHandler<any, any>>();\n\n\tregister<Q extends Query, R>(\n\t\tqueryType: Q[\"type\"],\n\t\thandler: QueryHandler<Q, R>,\n\t): void {\n\t\tthis.handlers.set(queryType, handler);\n\t}\n\n\tasync execute<Q extends Query & { type: keyof TMap }>(\n\t\tquery: Q,\n\t): Promise<Result<TMap[Q[\"type\"]], string>>;\n\tasync execute<Q extends Query, R>(query: Q): Promise<Result<R, string>>;\n\tasync execute<Q extends Query, R>(query: Q): Promise<Result<R, string>> {\n\t\tconst handler = this.handlers.get(query.type);\n\t\tif (!handler) {\n\t\t\treturn err(`No handler registered for query type: ${query.type}`);\n\t\t}\n\t\ttry {\n\t\t\tconst result = await handler(query);\n\t\t\treturn ok(result);\n\t\t} catch (error) {\n\t\t\treturn err(\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t);\n\t\t}\n\t}\n\n\tasync executeUnsafe<Q extends Query, R>(query: Q): Promise<R> {\n\t\tconst handler = this.handlers.get(query.type);\n\t\tif (!handler) {\n\t\t\tthrow new Error(`No handler registered for query type: ${query.type}`);\n\t\t}\n\t\treturn handler(query);\n\t}\n}\n\n","import { err, ok, type Result } from \"./result\";\n\n/**\n * Guard function that validates a condition and returns a Result.\n * Returns `ok(true)` if the condition is met, otherwise `err(error)`.\n *\n * @param cond - The condition to check\n * @param error - Error message if condition fails\n * @returns Result<true, string>\n *\n * @example\n * ```typescript\n * const result = guard(id.length > 0, \"ID cannot be empty\");\n * if (!result.ok) {\n * return err(result.error);\n * }\n * ```\n */\nexport function guard(cond: boolean, error: string): Result<true, string> {\n\treturn cond ? ok(true) : err(error);\n}\n","/**\n * Interface for entities with identity.\n * \n * In Domain-Driven Design, there are two types of entities:\n * \n * 1. **Aggregate Root Entity**: The parent Entity of an aggregate.\n * - Has identity (id) and version\n * - Implemented by classes extending `AggregateBase` or `AggregateEventSourced`\n * - Represents the aggregate externally\n * - Loaded/saved through repositories\n * \n * 2. **Child Entities**: Entities within an aggregate.\n * - Have identity (id), but no own version\n * - Exist only within the aggregate boundary\n * - Versioned through the Aggregate Root\n * - Cannot be referenced directly from outside the aggregate\n * \n * This interface is used for child entities within aggregates. The Aggregate Root\n * also implements this interface (through `AggregateRoot<TId>`), but additionally\n * has version management.\n *\n * @template TId - The type of the entity identifier\n *\n * @example\n * ```typescript\n * // Child Entity within an aggregate\n * type OrderItem = Entity<ItemId> & {\n * productId: string;\n * quantity: number;\n * };\n * \n * // Aggregate Root (also an Entity, but with version)\n * class Order extends AggregateBase<OrderState, OrderId> \n * implements AggregateRoot<OrderId> {\n * // Order is an Entity (the Aggregate Root)\n * // OrderState contains OrderItem (child entities)\n * }\n * ```\n */\nexport interface Entity<TId> {\n\treadonly id: TId;\n}\n\n/**\n * Checks if two entities have the same ID.\n * Works with any object that has an 'id' property.\n *\n * @param a - First entity\n * @param b - Second entity\n * @returns true if both entities have the same ID, false otherwise\n *\n * @example\n * ```typescript\n * const item1: OrderItem = { id: itemId1, productId: \"prod-1\", quantity: 2 };\n * const item2: OrderItem = { id: itemId2, productId: \"prod-2\", quantity: 1 };\n *\n * sameEntity(item1, item2); // false\n * sameEntity(item1, item1); // true\n * ```\n */\nexport function sameEntity<TId>(a: { id: TId }, b: { id: TId }): boolean {\n\treturn a.id === b.id;\n}\n\n/**\n * Finds an entity by ID in a collection.\n * Returns undefined if not found.\n *\n * @param entities - Array of entities to search\n * @param id - The ID to search for\n * @returns The entity if found, undefined otherwise\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 },\n * { id: itemId2, productId: \"prod-2\", quantity: 1 }\n * ];\n *\n * const item = findEntityById(items, itemId1);\n * // item is { id: itemId1, productId: \"prod-1\", quantity: 2 }\n * ```\n */\nexport function findEntityById<TId, T extends { id: TId }>(\n\tentities: T[],\n\tid: TId,\n): T | undefined {\n\treturn entities.find((entity) => entity.id === id);\n}\n\n/**\n * Checks if an entity with the given ID exists in the collection.\n *\n * @param entities - Array of entities to search\n * @param id - The ID to check for\n * @returns true if an entity with the ID exists, false otherwise\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 }\n * ];\n *\n * hasEntityId(items, itemId1); // true\n * hasEntityId(items, itemId2); // false\n * ```\n */\nexport function hasEntityId<TId, T extends { id: TId }>(\n\tentities: T[],\n\tid: TId,\n): boolean {\n\treturn entities.some((entity) => entity.id === id);\n}\n\n/**\n * Removes an entity with the given ID from the collection.\n * Returns a new array without the entity.\n *\n * @param entities - Array of entities\n * @param id - The ID of the entity to remove\n * @returns A new array without the entity with the given ID\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 },\n * { id: itemId2, productId: \"prod-2\", quantity: 1 }\n * ];\n *\n * const updated = removeEntityById(items, itemId1);\n * // updated is [{ id: itemId2, productId: \"prod-2\", quantity: 1 }]\n * ```\n */\nexport function removeEntityById<TId, T extends { id: TId }>(\n\tentities: T[],\n\tid: TId,\n): T[] {\n\treturn entities.filter((entity) => entity.id !== id);\n}\n\n/**\n * Updates an entity with the given ID in the collection.\n * Returns a new array with the updated entity.\n * If the entity is not found, returns the original array unchanged.\n *\n * @param entities - Array of entities\n * @param id - The ID of the entity to update\n * @param updater - Function that takes the entity and returns the updated entity\n * @returns A new array with the updated entity\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 }\n * ];\n *\n * const updated = updateEntityById(items, itemId1, (item) => ({\n * ...item,\n * quantity: item.quantity + 1\n * }));\n * // updated is [{ id: itemId1, productId: \"prod-1\", quantity: 3 }]\n * ```\n */\nexport function updateEntityById<TId, T extends { id: TId }>(\n\tentities: T[],\n\tid: TId,\n\tupdater: (entity: T) => T,\n): T[] {\n\treturn entities.map((entity) => (entity.id === id ? updater(entity) : entity));\n}\n\n/**\n * Replaces an entity with the given ID in the collection.\n * Returns a new array with the replaced entity.\n * If the entity is not found, returns the original array unchanged.\n *\n * @param entities - Array of entities\n * @param id - The ID of the entity to replace\n * @param replacement - The replacement entity\n * @returns A new array with the replaced entity\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 }\n * ];\n *\n * const updated = replaceEntityById(items, itemId1, {\n * id: itemId1,\n * productId: \"prod-1\",\n * quantity: 5\n * });\n * ```\n */\nexport function replaceEntityById<TId, T extends { id: TId }>(\n\tentities: T[],\n\tid: TId,\n\treplacement: T,\n): T[] {\n\treturn entities.map((entity) => (entity.id === id ? replacement : entity));\n}\n\n/**\n * Extracts all IDs from a collection of entities.\n *\n * @param entities - Array of entities\n * @returns Array of entity IDs\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 },\n * { id: itemId2, productId: \"prod-2\", quantity: 1 }\n * ];\n *\n * const ids = entityIds(items);\n * // ids is [itemId1, itemId2]\n * ```\n */\nexport function entityIds<TId, T extends { id: TId }>(entities: T[]): TId[] {\n\treturn entities.map((entity) => entity.id);\n}\n\n","import type { DomainEvent } from \"../aggregate/aggregate\";\nimport type { EventBus, EventHandler } from \"./ports\";\n\n/**\n * Simple in-memory event bus implementation.\n * Supports multiple subscribers per event type (pub/sub pattern).\n *\n * @template Evt - The type of domain events (must extend DomainEvent)\n *\n * @example\n * ```typescript\n * const bus = new EventBusImpl<OrderEvent>();\n *\n * bus.subscribe(\"OrderCreated\", async (event) => {\n * await sendEmail(event.payload.customerId);\n * });\n *\n * bus.subscribe(\"OrderCreated\", async (event) => {\n * await logEvent(event);\n * });\n *\n * await bus.publish([orderCreatedEvent]);\n * // Both handlers will be called\n * ```\n */\nexport class EventBusImpl<Evt extends DomainEvent<string, unknown>>\n\timplements EventBus<Evt>\n{\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate readonly handlers = new Map<string, Set<EventHandler<any>>>();\n\n\tsubscribe<T extends Evt>(\n\t\teventType: string,\n\t\thandler: EventHandler<T>,\n\t): () => void {\n\t\tconst type = eventType;\n\t\tif (!this.handlers.has(type)) {\n\t\t\tthis.handlers.set(type, new Set());\n\t\t}\n\t\tconst handlersForType = this.handlers.get(type)!;\n\t\thandlersForType.add(handler);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\thandlersForType.delete(handler);\n\t\t\tif (handlersForType.size === 0) {\n\t\t\t\tthis.handlers.delete(type);\n\t\t\t}\n\t\t};\n\t}\n\n\tasync publish(events: ReadonlyArray<Evt>): Promise<void> {\n\t\tfor (const event of events) {\n\t\t\tconst handlersForType = this.handlers.get(event.type);\n\t\t\tif (handlersForType) {\n\t\t\t\t// Call all handlers for this event type\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tArray.from(handlersForType).map((handler) => handler(event)),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\n","/**\n * Checks if an object is a built-in JavaScript type that should be treated atomically.\n * This function automatically detects built-ins without requiring manual maintenance.\n *\n * Detection strategy:\n * 1. TypedArrays: Check if tag ends with \"Array]\" (covers all current and future TypedArrays)\n * 2. ArrayBuffer views: Use ArrayBuffer.isView() (covers DataView and all TypedArrays)\n * 3. Built-in constructors: Check if constructor exists in global scope and matches known patterns\n * 4. Tag-based: Fallback to tag matching for known built-ins\n *\n * @param obj - The object to check\n * @param tag - The result of `Object.prototype.toString.call(obj)`\n * @returns `true` if the object is a built-in type, `false` otherwise\n */\nexport function isBuiltInObject(obj: object, tag: string): boolean {\n\t// 1. TypedArrays: all end with \"Array]\" - future-proof for new TypedArrays\n\tif (tag.endsWith(\"Array]\")) {\n\t\treturn true;\n\t}\n\n\t// 2. ArrayBuffer views: covers DataView and all TypedArrays (future-proof)\n\tif (ArrayBuffer.isView(obj)) {\n\t\treturn true;\n\t}\n\n\t// 3. ArrayBuffer and SharedArrayBuffer\n\tif (tag === \"[object ArrayBuffer]\" || tag === \"[object SharedArrayBuffer]\") {\n\t\treturn true;\n\t}\n\n\t// 4. Check if constructor exists in global scope (future-proof for new globals)\n\tconst objConstructor = (obj as { constructor?: unknown }).constructor;\n\tif (objConstructor && typeof objConstructor === \"function\") {\n\t\tconst constructorName = objConstructor.name;\n\t\t// Check if it's a known global constructor\n\t\t// This covers: Date, RegExp, Map, Set, WeakMap, WeakSet, Promise, Error, etc.\n\t\tif (\n\t\t\tconstructorName &&\n\t\t\ttypeof globalThis !== \"undefined\" &&\n\t\t\tconstructorName in globalThis &&\n\t\t\t(globalThis as Record<string, unknown>)[constructorName] === objConstructor\n\t\t) {\n\t\t\t// Additional check: ensure it's not a user-defined class with same name\n\t\t\t// Built-ins typically have non-enumerable properties and specific prototypes\n\t\t\tconst proto = Object.getPrototypeOf(obj);\n\t\t\tif (proto !== Object.prototype && proto !== null) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// 5. Tag-based fallback for known built-ins (covers edge cases)\n\tconst knownBuiltInTags = new Set([\n\t\t\"[object Date]\",\n\t\t\"[object RegExp]\",\n\t\t\"[object Map]\",\n\t\t\"[object Set]\",\n\t\t\"[object WeakMap]\",\n\t\t\"[object WeakSet]\",\n\t\t\"[object Promise]\",\n\t\t\"[object Error]\",\n\t\t\"[object Boolean]\",\n\t\t\"[object Number]\",\n\t\t\"[object String]\",\n\t]);\n\n\treturn knownBuiltInTags.has(tag);\n}\n\n","import { isBuiltInObject } from \"./is-built-in\";\n\nconst objProto = Object.prototype;\nconst objToString = objProto.toString;\nconst objHasOwn = objProto.hasOwnProperty;\n\n/**\n * Performs a deep equality check between two values.\n *\n * This function compares values recursively, handling:\n * - Primitives (with special handling for NaN)\n * - Arrays (nested arrays supported)\n * - Objects (plain objects and class instances)\n * - TypedArrays (Uint8Array, Int32Array, etc.)\n * - DataView\n * - Maps and Sets\n * - Dates and RegExp\n * - Wrapper objects (Boolean, Number, String)\n * - Circular references (detected and handled)\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal, `false` otherwise\n *\n * @example\n * ```ts\n * deepEqual([1, 2, 3], [1, 2, 3]); // true\n * deepEqual({ a: 1, b: [2, 3] }, { a: 1, b: [2, 3] }); // true\n * deepEqual(NaN, NaN); // true\n * deepEqual([1, 2], [1, 2, 3]); // false\n * ```\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n\treturn deepEqualInner(a, b, new WeakMap<object, object>());\n}\n\n/**\n * Internal recursive function for deep equality comparison.\n * Tracks visited objects to detect and handle circular references.\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @param visited - WeakMap to track visited object pairs and detect cycles\n * @returns `true` if the values are deeply equal, `false` otherwise\n * @internal\n */\nfunction deepEqualInner(\n\ta: unknown,\n\tb: unknown,\n\tvisited: WeakMap<object, object>\n): boolean {\n\t// 1. Fast path: reference equality\n\tif (a === b) return true;\n\n\tconst typeA = typeof a;\n\tconst typeB = typeof b;\n\n\t// 2. If one is not an object → primitive / function\n\tif (typeA !== \"object\" || a === null || typeB !== \"object\" || b === null) {\n\t\t// Special case: NaN should be equal\n\t\tif (typeA === \"number\" && typeB === \"number\") {\n\t\t\treturn Number.isNaN(a as number) && Number.isNaN(b as number);\n\t\t}\n\t\t// Everything else is directly unequal with !== (including functions)\n\t\treturn false;\n\t}\n\n\t// From here on: both are non-null objects\n\n\tconst objA = a as object;\n\tconst objB = b as object;\n\n\t// 3. Cycles: already seen pair?\n\tconst cached = visited.get(objA);\n\tif (cached !== undefined) {\n\t\t// If we already paired this A with a different B → unequal\n\t\treturn cached === objB;\n\t}\n\tvisited.set(objA, objB);\n\n\t// 4. Handle Typed Arrays / DataView first\n\tif (ArrayBuffer.isView(objA) || ArrayBuffer.isView(objB)) {\n\t\tif (!ArrayBuffer.isView(objA) || !ArrayBuffer.isView(objB)) return false;\n\n\t\tconst tagA = objToString.call(objA);\n\t\tconst tagB = objToString.call(objB);\n\t\tif (tagA !== tagB) return false;\n\n\t\t// DataView: compare byte by byte\n\t\tif (tagA === \"[object DataView]\") {\n\t\t\tconst viewA = objA as DataView;\n\t\t\tconst viewB = objB as DataView;\n\t\t\tif (viewA.byteLength !== viewB.byteLength) return false;\n\n\t\t\tconst len = viewA.byteLength;\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (viewA.getUint8(i) !== viewB.getUint8(i)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t// Typed Arrays: element by element\n\t\tconst arrA = objA as unknown as ArrayLike<unknown>;\n\t\tconst arrB = objB as unknown as ArrayLike<unknown>;\n\n\t\tconst len = arrA.length;\n\t\tif (len !== arrB.length) return false;\n\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tif ((arrA as any)[i] !== (arrB as any)[i]) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// 5. Tag-based type detection (robust across realms)\n\tconst tagA = objToString.call(objA);\n\tconst tagB = objToString.call(objB);\n\tif (tagA !== tagB) return false;\n\n\tswitch (tagA) {\n\t\tcase \"[object Array]\": {\n\t\t\tconst arrA = objA as unknown[];\n\t\t\tconst arrB = objB as unknown[];\n\t\t\tconst len = arrA.length;\n\t\t\tif (len !== arrB.length) return false;\n\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (!deepEqualInner(arrA[i], arrB[i], visited)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Map]\": {\n\t\t\tconst mapA = objA as Map<unknown, unknown>;\n\t\t\tconst mapB = objB as Map<unknown, unknown>;\n\n\t\t\tif (mapA.size !== mapB.size) return false;\n\n\t\t\tfor (const [key, valA] of mapA) {\n\t\t\t\t// Map keys according to JS semantics: reference / SameValueZero\n\t\t\t\tif (!mapB.has(key)) return false;\n\t\t\t\tconst valB = mapB.get(key);\n\t\t\t\tif (!deepEqualInner(valA, valB, visited)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Set]\": {\n\t\t\tconst setA = objA as Set<unknown>;\n\t\t\tconst setB = objB as Set<unknown>;\n\n\t\t\tif (setA.size !== setB.size) return false;\n\n\t\t\t// Set elements: same reference (JS semantics)\n\t\t\tfor (const value of setA) {\n\t\t\t\tif (!setB.has(value)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Date]\": {\n\t\t\tconst timeA = (objA as Date).getTime();\n\t\t\tconst timeB = (objB as Date).getTime();\n\t\t\treturn timeA === timeB;\n\t\t}\n\n\t\tcase \"[object RegExp]\": {\n\t\t\tconst regA = objA as RegExp;\n\t\t\tconst regB = objB as RegExp;\n\t\t\treturn regA.source === regB.source && regA.flags === regB.flags;\n\t\t}\n\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Number]\":\n\t\tcase \"[object String]\": {\n\t\t\t// Wrapper objects (new Boolean/Number/String)\n\t\t\treturn (objA as any).valueOf() === (objB as any).valueOf();\n\t\t}\n\n\t\tdefault: {\n\t\t\t// 6. Check if this is an unhandled built-in type (future-proof)\n\t\t\t// If both are built-ins but not handled above, they should be compared by reference\n\t\t\t// (since we don't know their internal structure)\n\t\t\tif (isBuiltInObject(objA, tagA) && isBuiltInObject(objB, tagB)) {\n\t\t\t\t// Unhandled built-in types: compare by reference as fallback\n\t\t\t\t// This ensures new built-ins don't fall through to plain object comparison\n\t\t\t\treturn objA === objB;\n\t\t\t}\n\n\t\t\t// 7. Fallback: plain / custom objects → compare own enumerable keys + values\n\t\t\tconst stringKeysA = Object.keys(objA as any);\n\t\t\tconst stringKeysB = Object.keys(objB as any);\n\t\t\tconst symbolKeysA = Object.getOwnPropertySymbols(objA as any);\n\t\t\tconst symbolKeysB = Object.getOwnPropertySymbols(objB as any);\n\n\t\t\t// Compare string keys count\n\t\t\tif (stringKeysA.length !== stringKeysB.length) return false;\n\t\t\t// Compare symbol keys count\n\t\t\tif (symbolKeysA.length !== symbolKeysB.length) return false;\n\n\t\t\t// Check all string keys exist in both objects\n\t\t\tfor (const key of stringKeysA) {\n\t\t\t\tif (!objHasOwn.call(objB, key)) return false;\n\t\t\t}\n\n\t\t\t// Check all symbol keys exist in both objects\n\t\t\tfor (const key of symbolKeysA) {\n\t\t\t\tif (!Object.getOwnPropertySymbols(objB as any).includes(key)) return false;\n\t\t\t}\n\n\t\t\t// Compare string key values\n\t\t\tfor (const key of stringKeysA) {\n\t\t\t\tif (!deepEqualInner((objA as any)[key], (objB as any)[key], visited)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Compare symbol key values\n\t\t\tfor (const key of symbolKeysA) {\n\t\t\t\tif (!deepEqualInner((objA as any)[key], (objB as any)[key], visited)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t}\n}\n","import { isBuiltInObject } from \"./is-built-in\";\n\nexport type Key = string | symbol;\nexport type PathSegment = string | number | symbol;\n\nexport interface DeepOmitOptions {\n\t/**\n\t * Keys to ignore everywhere in the object tree.\n\t * Only applies to object properties, not Map/Set/TypedArray contents.\n\t */\n\treadonly ignoreKeys?: readonly Key[];\n\n\t/**\n\t * Fine-grained control: Key + path (without current key).\n\t * Example path: [\"user\", \"meta\", 0, \"data\"]\n\t */\n\treadonly ignoreKeyPredicate?: (\n\t\tkey: Key,\n\t\tpath: readonly PathSegment[],\n\t) => boolean;\n}\n\n/**\n * Creates a deep copy of `value` with certain keys removed according to the provided rules.\n *\n * This function recursively traverses the object tree and removes keys that match\n * the criteria specified in `options`. Built-in types (Date, Map, Set, TypedArrays, etc.)\n * are treated atomically and not modified.\n *\n * @param value - The value to create a deep copy from\n * @param options - Options specifying which keys to ignore\n * @returns A deep copy of `value` with specified keys removed\n *\n * @example\n * ```ts\n * const obj = { a: 1, b: { c: 2, d: 3 } };\n * const result = deepOmit(obj, { ignoreKeys: ['d'] });\n * // result: { a: 1, b: { c: 2 } }\n * ```\n */\nexport function deepOmit<T>(value: T, options: DeepOmitOptions): T {\n\tconst visited = new WeakMap<object, unknown>();\n\treturn omitInternal(value, options, [], visited) as T;\n}\n\nfunction omitInternal(\n\tvalue: unknown,\n\toptions: DeepOmitOptions,\n\tpath: PathSegment[],\n\tvisited: WeakMap<object, unknown>,\n): unknown {\n\tif (value === null) return value;\n\tconst type = typeof value;\n\n\t// Primitives and functions are passed through unchanged\n\tif (type !== \"object\") return value;\n\n\tconst obj = value as object;\n\n\t// Cycles: return cached value if already visited\n\tconst cached = visited.get(obj);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\n\tconst tag = Object.prototype.toString.call(obj);\n\n\t// Arrays: recursively process elements\n\tif (tag === \"[object Array]\") {\n\t\tconst arr = obj as unknown[];\n\t\tconst clone: unknown[] = new Array(arr.length);\n\t\tvisited.set(obj, clone);\n\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tpath.push(i);\n\t\t\tclone[i] = omitInternal(arr[i], options, path, visited);\n\t\t\tpath.pop();\n\t\t}\n\t\treturn clone;\n\t}\n\n\t// Built-ins: treat atomically, no key filtering inside\n\t// Future-proof detection: check if object is a built-in type\n\tif (isBuiltInObject(obj, tag)) {\n\t\treturn value;\n\t}\n\n\t// Plain / Custom Objects: filter keys, recursively process values\n\tconst clone = Object.create(Object.getPrototypeOf(obj));\n\tvisited.set(obj, clone);\n\n\tconst stringKeys = Object.keys(obj);\n\tconst symbolKeys = Object.getOwnPropertySymbols(obj);\n\tconst keys: Key[] = [...stringKeys, ...symbolKeys];\n\n\tfor (const key of keys) {\n\t\tif (shouldIgnoreKey(key, path, options)) continue;\n\n\t\tpath.push(key);\n\t\t(clone as Record<PropertyKey, unknown>)[key] = omitInternal(\n\t\t\t(obj as Record<PropertyKey, unknown>)[key],\n\t\t\toptions,\n\t\t\tpath,\n\t\t\tvisited,\n\t\t);\n\t\tpath.pop();\n\t}\n\n\treturn clone;\n}\n\nfunction shouldIgnoreKey(\n\tkey: Key,\n\tpath: readonly PathSegment[],\n\toptions: DeepOmitOptions,\n): boolean {\n\tif (options.ignoreKeys?.includes(key)) {\n\t\treturn true;\n\t}\n\tif (options.ignoreKeyPredicate?.(key, path)) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n","import { deepEqual } from \"./deep-equal\";\nimport { type DeepOmitOptions, deepOmit } from \"./deep-omit\";\n\nexport type DeepEqualExceptOptions = DeepOmitOptions;\n\n/**\n * Performs a deep equality comparison between two values after omitting specified keys.\n * \n * This function first removes the specified keys from both values using `deepOmit`,\n * then performs a deep equality check using `deepEqual`.\n * \n * @param a - The first value to compare\n * @param b - The second value to compare\n * @param options - Options specifying which keys to omit before comparison\n * @returns `true` if the values are deeply equal after omitting specified keys, `false` otherwise\n * \n * @example\n * ```ts\n * const obj1 = { id: 1, name: \"Alice\", updatedAt: \"2024-01-01\" };\n * const obj2 = { id: 2, name: \"Alice\", updatedAt: \"2024-01-02\" };\n * \n * deepEqualExcept(obj1, obj2, { ignoreKeys: [\"id\", \"updatedAt\"] }); // true\n * ```\n */\nexport function deepEqualExcept(\n\ta: unknown,\n\tb: unknown,\n\toptions: DeepEqualExceptOptions,\n): boolean {\n\tconst prunedA = deepOmit(a, options);\n\tconst prunedB = deepOmit(b, options);\n\treturn deepEqual(prunedA, prunedB);\n}\n","import { err, ok, type Result } from \"../core/result\";\nimport { deepEqual } from \"../utils/array/deep-equal\";\nimport {\n\tdeepEqualExcept,\n\ttype DeepEqualExceptOptions,\n} from \"../utils/array/deep-equal-except\";\n\nexport type VO<T> = Readonly<T>;\n\n/**\n * Deep freezes an object and all its nested properties recursively.\n * This ensures true immutability for value objects with nested structures.\n * Handles circular references by tracking visited objects.\n */\nexport function deepFreeze<T>(obj: T, visited = new WeakSet<object>()): Readonly<T> {\n\t// Handle null and non-objects\n\tif (obj === null || typeof obj !== \"object\") {\n\t\treturn obj as Readonly<T>;\n\t}\n\n\t// Handle circular references\n\tif (visited.has(obj as object)) {\n\t\treturn obj as Readonly<T>;\n\t}\n\n\t// Mark as visited\n\tvisited.add(obj as object);\n\n\t// Retrieve the property names defined on obj\n\tconst propNames = Object.getOwnPropertyNames(obj);\n\n\t// Freeze properties before freezing self\n\tfor (const name of propNames) {\n\t\tconst value = (obj as Record<string, unknown>)[name];\n\n\t\t// Freeze value if it is an object or array\n\t\tif (value && (typeof value === \"object\" || Array.isArray(value))) {\n\t\t\tdeepFreeze(value, visited);\n\t\t}\n\t}\n\n\treturn Object.freeze(obj) as Readonly<T>;\n}\n\n/**\n * Creates a deeply immutable value object from the given data.\n * All nested objects and arrays are frozen recursively.\n *\n * @param t - The data to convert into a value object\n * @returns A deeply frozen, immutable value object\n *\n * @example\n * ```typescript\n * const address = vo({\n * street: \"Main St\",\n * city: \"Berlin\",\n * coordinates: { lat: 52.5, lng: 13.4 }\n * });\n * // address.coordinates.lat = 99; // ❌ Error: Cannot assign to read-only property\n * ```\n */\nexport function vo<T>(t: T): VO<T> {\n\treturn deepFreeze({ ...t });\n}\n\n/**\n * Compares two value objects for equality based on their values.\n * Uses deep equality comparison that handles:\n * - Nested objects and arrays\n * - Primitives (including NaN)\n * - Dates, Maps, Sets, RegExp\n * - TypedArrays and DataView\n * - Symbol keys\n * - Circular references\n *\n * @param a - First value object\n * @param b - Second value object\n * @returns true if both objects have the same values, false otherwise\n *\n * @example\n * ```typescript\n * const money1 = vo({ amount: 100, currency: \"USD\" });\n * const money2 = vo({ amount: 100, currency: \"USD\" });\n * voEquals(money1, money2); // true\n *\n * const address1 = vo({\n * street: \"Main St\",\n * coordinates: { lat: 52.5, lng: 13.4 }\n * });\n * const address2 = vo({\n * street: \"Main St\",\n * coordinates: { lat: 52.5, lng: 13.4 }\n * });\n * voEquals(address1, address2); // true\n * ```\n */\nexport function voEquals<T>(a: VO<T>, b: VO<T>): boolean {\n\treturn deepEqual(a, b);\n}\n\n/**\n * Compares two value objects for equality while ignoring specified keys.\n * Useful for comparing value objects that contain metadata or optional fields\n * that should not affect equality comparison.\n *\n * @param a - First value object\n * @param b - Second value object\n * @param options - Options specifying which keys to ignore during comparison\n * @returns true if both objects have the same values (after ignoring specified keys), false otherwise\n *\n * @example\n * ```typescript\n * // Value object with metadata\n * const address1 = vo({\n * street: \"Main St\",\n * city: \"Berlin\",\n * metadata: { createdAt: \"2024-01-01\", updatedAt: \"2024-01-02\" }\n * });\n *\n * const address2 = vo({\n * street: \"Main St\",\n * city: \"Berlin\",\n * metadata: { createdAt: \"2024-01-01\", updatedAt: \"2024-01-03\" }\n * });\n *\n * // Compare ignoring metadata timestamps\n * voEqualsExcept(address1, address2, {\n * ignoreKeys: [\"updatedAt\"],\n * ignoreKeyPredicate: (key, path) => path.includes(\"metadata\")\n * }); // true\n *\n * // Compare ignoring all metadata\n * voEqualsExcept(address1, address2, {\n * ignoreKeyPredicate: (key, path) => path.includes(\"metadata\")\n * }); // true\n * ```\n */\nexport function voEqualsExcept<T>(\n\ta: VO<T>,\n\tb: VO<T>,\n\toptions: DeepEqualExceptOptions,\n): boolean {\n\treturn deepEqualExcept(a, b, options);\n}\n\n/**\n * Creates a value object with optional validation.\n * Returns a Result type instead of throwing an error.\n *\n * @param t - The data to convert into a value object\n * @param validate - Validation function that returns true if valid\n * @param errorMessage - Optional custom error message if validation fails\n * @returns Result containing the value object if valid, or an error message if validation fails\n *\n * @example\n * ```typescript\n * const result = voWithValidation(\n * { amount: 100, currency: \"USD\" },\n * (m) => m.amount >= 0 && m.currency.length === 3,\n * \"Invalid money: amount must be non-negative and currency must be 3 characters\"\n * );\n *\n * if (result.ok) {\n * console.log(result.value); // Use the value object\n * } else {\n * console.error(result.error); // Handle validation error\n * }\n * ```\n */\nexport function voWithValidation<T>(\n\tt: T,\n\tvalidate: (value: T) => boolean,\n\terrorMessage?: string,\n): Result<VO<T>, string> {\n\tif (!validate(t)) {\n\t\treturn err(\n\t\t\terrorMessage ?? `Validation failed for value object: ${JSON.stringify(t)}`,\n\t\t);\n\t}\n\treturn ok(vo(t));\n}\n\n/**\n * Creates a value object with optional validation.\n * Throws an error if validation fails.\n *\n * @param t - The data to convert into a value object\n * @param validate - Validation function that returns true if valid\n * @param errorMessage - Optional custom error message if validation fails\n * @returns A deeply frozen, immutable value object\n * @throws Error if validation fails\n *\n * @example\n * ```typescript\n * const money = voWithValidationUnsafe(\n * { amount: 100, currency: \"USD\" },\n * (m) => m.amount >= 0 && m.currency.length === 3,\n * \"Invalid money: amount must be non-negative and currency must be 3 characters\"\n * );\n * ```\n */\nexport function voWithValidationUnsafe<T>(\n\tt: T,\n\tvalidate: (value: T) => boolean,\n\terrorMessage?: string,\n): VO<T> {\n\tif (!validate(t)) {\n\t\tthrow new Error(\n\t\t\terrorMessage ?? `Validation failed for value object: ${JSON.stringify(t)}`,\n\t\t);\n\t}\n\treturn vo(t);\n}\n","import { deepEqual } from \"../utils/array/deep-equal\";\nimport { deepFreeze } from \"./vo\";\n\n/**\n * Abstract base class for creating Value Objects.\n * Value Objects are immutable and defined by their properties.\n *\n * @template T - The shape of the value object's properties\n */\nexport abstract class ValueObject<T extends object> {\n public readonly props: Readonly<T>;\n\n /**\n * Creates a new ValueObject.\n * The properties are deeply frozen to ensure immutability.\n *\n * @param props - The properties of the value object\n * @example\n * ```ts\n * class Money extends ValueObject<{ amount: number; currency: string }> {\n * constructor(props: { amount: number; currency: string }) {\n * super(props);\n * }\n * }\n * ```\n */\n constructor(props: T) {\n this.props = deepFreeze({ ...props });\n }\n\n /**\n * Checks if this value object is equal to another.\n * Uses deep equality comparison on the properties.\n *\n * @param other - The other value object to compare\n * @returns true if the properties are deeply equal\n */\n public equals(other: ValueObject<T>): boolean {\n if (other === null || other === undefined) {\n return false;\n }\n\n if (other.props === undefined) {\n return false;\n }\n\n return deepEqual(this.props, other.props);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/aggregate/aggregate.ts","../src/aggregate/aggregate-root.ts","../src/core/result/result.ts","../src/aggregate/aggregate-event-sourced.ts","../src/app/command-bus.ts","../src/app/handler.ts","../src/app/query-bus.ts","../src/core/guard.ts","../src/utils/array/is-built-in.ts","../src/utils/array/deep-equal.ts","../src/entity/entity.ts","../src/events/event-bus.ts","../src/utils/array/deep-omit.ts","../src/utils/array/deep-equal-except.ts","../src/value-object/vo.ts","../src/value-object/value-object.ts"],"names":["aggregate","state","version","__name","withEvent","agg","evt","bump","createDomainEvent","type","payload","options","createDomainEventWithMetadata","metadata","copyMetadata","sourceEvent","additionalMetadata","mergeMetadata","metadataObjects","sameAggregate","a","b","AggregateRoot","id","initialState","config","_state","event","newState","bumpVersion","snapshot","ok","value","err","error","AggregateEventSourced","_event","isNew","validation","handler","history","result","events","eventsAfterSnapshot","CommandBus","commandType","command","withCommit","deps","fn","QueryBus","queryType","query","guard","cond","isBuiltInObject","obj","tag","objConstructor","constructorName","proto","objProto","objToString","objHasOwn","deepEqual","deepEqualInner","visited","typeA","typeB","objA","objB","cached","tagA","tagB","viewA","viewB","len","i","arrA","arrB","mapA","mapB","key","valA","valB","setA","setB","timeA","timeB","regA","regB","stringKeysA","stringKeysB","symbolKeysA","symbolKeysB","Entity","other","isEntity","sameEntity","findEntityById","entities","entity","hasEntityId","removeEntityById","updateEntityById","updater","replaceEntityById","replacement","entityIds","EventBusImpl","eventType","handlersForType","deepOmit","omitInternal","path","arr","clone","stringKeys","symbolKeys","keys","shouldIgnoreKey","deepEqualExcept","prunedA","prunedB","deepFreeze","propNames","name","vo","voEquals","voEqualsExcept","voWithValidation","validate","errorMessage","voWithValidationUnsafe","ValueObject","props","Constructor"],"mappings":"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","file":"index.js","sourcesContent":["import type { Id } from \"../core/id\";\n\nexport type Version = number & { readonly __v: true };\n\n/**\n * Metadata associated with a domain event for traceability and correlation.\n * Used in event-driven architectures to track event flow across services.\n */\nexport interface EventMetadata {\n\t/**\n\t * Correlation ID for tracing events across multiple services/components.\n\t * Typically used to group related events in a distributed system.\n\t */\n\tcorrelationId?: string;\n\n\t/**\n\t * Causation ID referencing the event or command that caused this event.\n\t * Used to build event chains and understand causality.\n\t */\n\tcausationId?: string;\n\n\t/**\n\t * User ID of the person or system that triggered the event.\n\t */\n\tuserId?: string;\n\n\t/**\n\t * Source service or component that produced the event.\n\t */\n\tsource?: string;\n\n\t/**\n\t * Additional custom metadata fields.\n\t * Allows extensibility for domain-specific metadata.\n\t */\n\t[key: string]: unknown;\n}\n\n/**\n * Domain Event represents something meaningful that happened in the domain.\n * Events are immutable and carry information about what occurred.\n *\n * @template T - The event type name (e.g., \"OrderCreated\")\n * @template P - The event payload type\n */\nexport interface DomainEvent<T extends string, P> {\n\t/**\n\t * The type of the event, used for routing and handling.\n\t */\n\ttype: T;\n\n\t/**\n\t * The event payload containing the domain data.\n\t */\n\tpayload: P;\n\n\t/**\n\t * Timestamp when the event occurred.\n\t */\n\toccurredAt: Date;\n\n\t/**\n\t * Event schema version for handling schema evolution.\n\t * Defaults to 1 if not specified. Higher versions indicate schema changes.\n\t */\n\tversion?: number;\n\n\t/**\n\t * Optional metadata for traceability, correlation, and auditing.\n\t * Includes correlationId, causationId, userId, source, and custom fields.\n\t */\n\tmetadata?: EventMetadata;\n}\n\n// Re-export interfaces from their respective files for convenience\nexport type { IAggregateRoot } from \"./aggregate-root\";\nexport type { IAggregateEventSourced } from \"./aggregate-event-sourced\";\n\n/**\n * Structural interface representing an aggregate with state and events.\n * Used for type constraints in repositories and other infrastructure code.\n *\n * @template State - The type of the aggregate state\n * @template Evt - The union type of all domain events\n */\nexport interface Aggregate<State, Evt extends DomainEvent<string, unknown>> {\n\tstate: Readonly<State>;\n\tversion: Version;\n\tpendingEvents: ReadonlyArray<Evt>;\n}\n\nexport function aggregate<State, Evt extends DomainEvent<string, unknown>>(\n\tstate: State,\n\tversion: Version = 0 as Version,\n): Aggregate<State, Evt> {\n\treturn { state, version, pendingEvents: [] };\n}\n\nexport function withEvent<S, E extends DomainEvent<string, unknown>>(\n\tagg: Aggregate<S, E>,\n\tevt: E,\n): Aggregate<S, E> {\n\treturn { ...agg, pendingEvents: [...agg.pendingEvents, evt] };\n}\n\nexport function bump<S, E extends DomainEvent<string, unknown>>(\n\tagg: Aggregate<S, E>,\n): Aggregate<S, E> {\n\treturn { ...agg, version: (agg.version + 1) as Version };\n}\n\n/**\n * Creates a domain event with default values.\n * Sets occurredAt to current date and version to 1 if not provided.\n *\n * @param type - The event type\n * @param payload - The event payload\n * @param options - Optional event configuration\n * @returns A domain event\n *\n * @example\n * ```typescript\n * const event = createDomainEvent(\"OrderCreated\", { orderId: \"123\" });\n * ```\n */\nexport function createDomainEvent<T extends string, P>(\n\ttype: T,\n\tpayload: P,\n\toptions?: {\n\t\toccurredAt?: Date;\n\t\tversion?: number;\n\t\tmetadata?: EventMetadata;\n\t},\n): DomainEvent<T, P> {\n\treturn {\n\t\ttype,\n\t\tpayload,\n\t\toccurredAt: options?.occurredAt ?? new Date(),\n\t\tversion: options?.version ?? 1,\n\t\tmetadata: options?.metadata,\n\t};\n}\n\n/**\n * Creates a domain event with metadata for traceability.\n * Convenience function for creating events with correlation and causation IDs.\n *\n * @param type - The event type\n * @param payload - The event payload\n * @param metadata - Event metadata for traceability\n * @param options - Optional event configuration\n * @returns A domain event with metadata\n *\n * @example\n * ```typescript\n * const event = createDomainEventWithMetadata(\n * \"OrderCreated\",\n * { orderId: \"123\" },\n * {\n * correlationId: \"corr-123\",\n * causationId: \"cmd-456\",\n * userId: \"user-789\"\n * }\n * );\n * ```\n */\nexport function createDomainEventWithMetadata<T extends string, P>(\n\ttype: T,\n\tpayload: P,\n\tmetadata: EventMetadata,\n\toptions?: {\n\t\toccurredAt?: Date;\n\t\tversion?: number;\n\t},\n): DomainEvent<T, P> {\n\treturn createDomainEvent(type, payload, {\n\t\t...options,\n\t\tmetadata,\n\t});\n}\n\n/**\n * Copies metadata from a source event to a new event.\n * Useful for maintaining correlation chains in event-driven architectures.\n *\n * @param sourceEvent - The source event to copy metadata from\n * @param additionalMetadata - Additional metadata to merge in\n * @returns Event metadata with copied and merged values\n *\n * @example\n * ```typescript\n * const newEvent = createDomainEvent(\n * \"OrderShipped\",\n * { orderId: \"123\" },\n * {\n * metadata: copyMetadata(previousEvent, { causationId: previousEvent.type })\n * }\n * );\n * ```\n */\nexport function copyMetadata(\n\tsourceEvent: DomainEvent<string, unknown>,\n\tadditionalMetadata?: Partial<EventMetadata>,\n): EventMetadata {\n\treturn {\n\t\t...(sourceEvent.metadata ?? {}),\n\t\t...(additionalMetadata ?? {}),\n\t};\n}\n\n/**\n * Merges multiple metadata objects into one.\n * Later metadata objects override earlier ones for the same keys.\n *\n * @param metadataObjects - Array of metadata objects to merge\n * @returns Merged event metadata\n *\n * @example\n * ```typescript\n * const metadata = mergeMetadata(\n * { correlationId: \"corr-123\" },\n * { userId: \"user-456\" },\n * { source: \"order-service\" }\n * );\n * ```\n */\nexport function mergeMetadata(\n\t...metadataObjects: Array<EventMetadata | undefined>\n): EventMetadata {\n\treturn Object.assign({}, ...metadataObjects.filter(Boolean));\n}\n\n/**\n * Snapshot of an aggregate state at a specific point in time.\n * Used for optimizing event replay by starting from a snapshot\n * instead of replaying all events from the beginning.\n *\n * @template TState - The type of the aggregate state\n */\nexport interface AggregateSnapshot<TState> {\n\t/**\n\t * The state of the aggregate at the time of the snapshot.\n\t */\n\tstate: TState;\n\n\t/**\n\t * The version of the aggregate when the snapshot was taken.\n\t */\n\tversion: Version;\n\n\t/**\n\t * Timestamp when the snapshot was created.\n\t */\n\tsnapshotAt: Date;\n}\n\n/**\n * Checks if two aggregates are the same (same ID and version).\n * Useful for optimistic concurrency control checks.\n *\n * @param a - First aggregate\n * @param b - Second aggregate\n * @returns true if both aggregates have the same ID and version\n *\n * @example\n * ```typescript\n * const aggregate1 = await repository.getById(id);\n * // ... some operations ...\n * const aggregate2 = await repository.getById(id);\n *\n * if (!sameAggregate(aggregate1, aggregate2)) {\n * throw new Error(\"Aggregate was modified by another process\");\n * }\n * ```\n */\nexport function sameAggregate<TId extends Id<string>>(\n\ta: { id: TId; version: Version },\n\tb: { id: TId; version: Version },\n): boolean {\n\treturn a.id === b.id && a.version === b.version;\n}\n","import type { Id } from \"../core/id\";\nimport type { Identifiable } from \"../entity/entity\";\nimport type {\n\tAggregateSnapshot,\n\tVersion,\n} from \"./aggregate\";\n\n/**\n * Marker interface for Aggregate Roots.\n * \n * In Domain-Driven Design, an Aggregate Root is an Entity (the parent Entity of the aggregate).\n * It represents the aggregate externally and is the only object that external code\n * is allowed to hold references to. All access to child entities within the aggregate\n * must go through the Aggregate Root.\n * \n * An Aggregate consists of:\n * - One Aggregate Root (Entity with id + version)\n * - Optional child entities (Entities with id, but no own version)\n * - Optional value objects\n * \n * The Aggregate Root has identity (id) and version for optimistic concurrency control.\n * Child entities exist only within the aggregate boundary and are versioned through\n * the Aggregate Root.\n *\n * @template TId - The type of the aggregate root identifier\n *\n * @example\n * ```typescript\n * class Order extends AggregateRoot<OrderState, OrderId> implements IAggregateRoot<OrderId> {\n * // Order is an Aggregate Root (an Entity)\n * // OrderState contains child entities (e.g., OrderItem) and value objects\n * }\n * ```\n */\nexport interface IAggregateRoot<TId extends Id<string>> extends Identifiable<TId> {\n\t/**\n\t * Unique identifier of the aggregate root entity.\n\t */\n\treadonly id: TId;\n\n\t/**\n\t * Version number for optimistic concurrency control.\n\t * Incremented on each state change to detect concurrent modifications.\n\t * This version applies to the entire aggregate, including all child entities.\n\t */\n\treadonly version: Version;\n}\n\n/**\n * Configuration options for AggregateRoot behavior.\n */\nexport interface AggregateConfig {\n\t/**\n\t * Whether to automatically bump the version when state changes.\n\t * Defaults to false. Set to true for automatic versioning.\n\t */\n\tautoVersionBump?: boolean;\n}\n\n/**\n * Base class for creating Aggregate Roots (Entities) without Event Sourcing.\n * \n * This class creates an Entity that serves as the Aggregate Root. The Aggregate Root\n * is the parent Entity of the aggregate and represents it externally. It has identity\n * (id) and version for optimistic concurrency control.\n * \n * The aggregate state (`TState`) contains:\n * - Child entities (Entities with id, but no own version)\n * - Value objects (immutable objects)\n * \n * All changes to child entities are versioned through the Aggregate Root. The version\n * applies to the entire aggregate, including all child entities.\n * \n * Provides core functionality:\n * - ID and Version management (for Optimistic Concurrency Control)\n * - State management (containing child entities and value objects)\n * - Snapshot support for performance optimization\n *\n * Implements `IAggregateRoot<TId>` to mark this as an Aggregate Root Entity.\n *\n * Use this class when you don't need Event Sourcing but still want\n * aggregate patterns with versioning and state management.\n *\n * @template TState - The type of the aggregate state (contains child entities and value objects)\n * @template TId - The type of the aggregate root identifier\n *\n * @example\n * ```typescript\n * // Order is an Aggregate Root (an Entity)\n * class Order extends AggregateRoot<OrderState, OrderId> {\n * constructor(id: OrderId, initialState: OrderState) {\n * super(id, initialState);\n * }\n *\n * confirm(): void {\n * this._state = { ...this._state, status: \"confirmed\" };\n * this.bumpVersion(); // Versions the entire aggregate\n * }\n * }\n * ```\n */\nexport abstract class AggregateRoot<TState, TId extends Id<string>>\n\timplements IAggregateRoot<TId> {\n\tpublic readonly id: TId;\n\tpublic version: Version = 0 as Version;\n\n\tprivate readonly _config: AggregateConfig;\n\tprivate readonly _autoVersionBump: boolean;\n\tprivate _domainEvents: unknown[] = [];\n\n\tpublic get state(): TState {\n\t\treturn this._state;\n\t}\n\n\t/**\n\t * Returns a read-only list of domain events recorded by this aggregate.\n\t * These events are side-effects of state changes.\n\t */\n\tpublic get domainEvents(): ReadonlyArray<unknown> {\n\t\treturn this._domainEvents;\n\t}\n\n\t/**\n\t * Clears the list of recorded domain events.\n\t * Call this after dispatching the events.\n\t */\n\tpublic clearDomainEvents(): void {\n\t\tthis._domainEvents = [];\n\t}\n\n\t/**\n\t * The state is 'protected' so that only the subclass can change it.\n\t * Subclasses can mutate this directly or use helper methods.\n\t */\n\tprotected _state: TState;\n\n\tprotected constructor(\n\t\tid: TId,\n\t\tinitialState: TState,\n\t\tconfig?: AggregateConfig,\n\t) {\n\t\tif (id === null || id === undefined) {\n\t\t\tthrow new Error(\"Aggregate ID cannot be null or undefined\");\n\t\t}\n\t\tthis.id = id;\n\t\tthis._state = initialState;\n\t\tthis._config = config ?? {};\n\t\tthis._autoVersionBump = this._config.autoVersionBump ?? false;\n\t\tthis.validateState(this._state);\n\t}\n\n\t/**\n\t * Optional validation hook to ensure state invariants.\n\t * Called during construction, setState, and snapshot restoration.\n\t * Override this method to implement validation logic.\n\t *\n\t * @param state - The state to validate\n\t * @throws Error if validation fails\n\t */\n\tprotected validateState(_state: TState): void {\n\t\t// Default implementation does nothing\n\t}\n\n\t/**\n\t * Adds a domain event to the aggregate's list of changes.\n\t * Use this to record side-effects that should be published.\n\t *\n\t * @param event - The domain event to add\n\t */\n\tprotected addDomainEvent(event: unknown): void {\n\t\tthis._domainEvents.push(event);\n\t}\n\n\t/**\n\t * Manually bumps the aggregate version.\n\t * Call this after state changes for Optimistic Concurrency Control.\n\t *\n\t * If `autoVersionBump` is enabled, this is called automatically\n\t * when using `setState()`.\n\t */\n\tprotected bumpVersion(): void {\n\t\tthis.version = (this.version + 1) as Version;\n\t}\n\n\t/**\n\t * Sets the state and optionally bumps the version automatically.\n\t * This is a convenience method for state mutations.\n\t * Automatically validates the newState using `validateState()`.\n\t *\n\t * @param newState - The new state\n\t * @param bumpVersion - Whether to bump the version (defaults to autoVersionBump config)\n\t */\n\tprotected setState(\n\t\tnewState: TState,\n\t\tbumpVersion?: boolean,\n\t): void {\n\t\tthis.validateState(newState);\n\t\tthis._state = newState;\n\t\tconst shouldBump = bumpVersion ?? this._autoVersionBump;\n\t\tif (shouldBump) {\n\t\t\tthis.bumpVersion();\n\t\t}\n\t}\n\n\t/**\n\t * Creates a snapshot of the current aggregate state.\n\t * Useful for performance optimization, backup/restore, and audit trails.\n\t *\n\t * @returns A snapshot containing the current state and version\n\t *\n\t * @example\n\t * ```typescript\n\t * const snapshot = aggregate.createSnapshot();\n\t * await snapshotRepository.save(aggregate.id, snapshot);\n\t * ```\n\t */\n\tpublic createSnapshot(): AggregateSnapshot<TState> {\n\t\treturn {\n\t\t\tstate: { ...this._state } as TState,\n\t\t\tversion: this.version,\n\t\t\tsnapshotAt: new Date(),\n\t\t};\n\t}\n\n\t/**\n\t * Restores the aggregate from a snapshot.\n\t * This is useful for loading aggregates from snapshots instead of\n\t * rebuilding them from scratch.\n\t * Validates the restored state.\n\t *\n\t * @param snapshot - The snapshot to restore from\n\t *\n\t * @example\n\t * ```typescript\n\t * const snapshot = await snapshotRepository.getLatest(aggregateId);\n\t * aggregate.restoreFromSnapshot(snapshot);\n\t * ```\n\t */\n\tpublic restoreFromSnapshot(snapshot: AggregateSnapshot<TState>): void {\n\t\tthis.validateState(snapshot.state);\n\t\tthis._state = snapshot.state;\n\t\tthis.version = snapshot.version;\n\t}\n}\n","export type Ok<T> = { ok: true; value: T };\nexport type Err<E> = { ok: false; error: E };\nexport type Result<T, E> = Ok<T> | Err<E>;\n\n/**\n * Creates an Ok result with a value.\n *\n * @param value - The success value\n * @returns An Ok result containing the value\n *\n * @example\n * ```typescript\n * const result = ok(42);\n * // result is Ok<number>\n * ```\n */\nexport function ok<T>(value: T): Ok<T>;\n\n/**\n * Creates an Ok result with void (no value).\n *\n * @returns An Ok<void> result\n *\n * @example\n * ```typescript\n * const result = ok();\n * // result is Ok<void>\n * ```\n */\nexport function ok(): Ok<void>;\n\nexport function ok<T>(value?: T): Ok<T> {\n\treturn { ok: true, value: value as T };\n}\n\n/**\n * Creates an Err result with an error.\n *\n * @param error - The error value\n * @returns An Err result containing the error\n *\n * @example\n * ```typescript\n * const result = err(\"Something went wrong\");\n * // result is Err<string>\n * ```\n */\nexport function err<E>(error: E): Err<E>;\n\n/**\n * Creates an Err result with void (no error value).\n *\n * @returns An Err<void> result\n *\n * @example\n * ```typescript\n * const result = err();\n * // result is Err<void>\n * ```\n */\nexport function err(): Err<void>;\n\nexport function err<E>(error?: E): Err<E> {\n\treturn { ok: false, error: error as E };\n}\n\n/**\n * Type guard to check if a Result is Ok.\n * Narrows the type to Ok<T> when returning true.\n *\n * @param result - The result to check\n * @returns true if the result is Ok, false otherwise\n *\n * @example\n * ```typescript\n * const result = voWithValidation(data, validator);\n * if (isOk(result)) {\n * // TypeScript knows result is Ok<VO<T>>\n * console.log(result.value);\n * }\n * ```\n */\nexport function isOk<T, E>(result: Result<T, E>): result is Ok<T> {\n\treturn result.ok === true;\n}\n\n/**\n * Type guard to check if a Result is Err.\n * Narrows the type to Err<E> when returning true.\n *\n * @param result - The result to check\n * @returns true if the result is Err, false otherwise\n *\n * @example\n * ```typescript\n * const result = voWithValidation(data, validator);\n * if (isErr(result)) {\n * // TypeScript knows result is Err<string>\n * console.error(result.error);\n * }\n * ```\n */\nexport function isErr<T, E>(result: Result<T, E>): result is Err<E> {\n\treturn result.ok === false;\n}\n\n/**\n * Chains Result operations (flatMap/bind).\n * If the result is Ok, applies the function to the value.\n * If Err, returns the error unchanged.\n *\n * @param result - The result to chain\n * @param fn - Function that takes the Ok value and returns a new Result\n * @returns A new Result\n *\n * @example\n * ```typescript\n * const result = validateUserId(\"123\")\n * .andThen(userId => validateEmail(\"test@example.com\")\n * .map(email => ({ id: userId, email }))\n * );\n * ```\n */\nexport function andThen<T, E, U>(\n\tresult: Result<T, E>,\n\tfn: (value: T) => Result<U, E>,\n): Result<U, E> {\n\tif (result.ok) {\n\t\treturn fn(result.value);\n\t}\n\treturn result;\n}\n\n/**\n * Transforms the Ok value using a function.\n * If the result is Err, returns the error unchanged.\n *\n * @param result - The result to transform\n * @param fn - Function to transform the Ok value\n * @returns A new Result with transformed value\n *\n * @example\n * ```typescript\n * const result = ok(5);\n * const doubled = map(result, x => x * 2); // Ok<10>\n * ```\n */\nexport function map<T, E, U>(\n\tresult: Result<T, E>,\n\tfn: (value: T) => U,\n): Result<U, E> {\n\tif (result.ok) {\n\t\treturn ok(fn(result.value));\n\t}\n\treturn result;\n}\n\n/**\n * Transforms the Err value using a function.\n * If the result is Ok, returns the value unchanged.\n *\n * @param result - The result to transform\n * @param fn - Function to transform the Err value\n * @returns A new Result with transformed error\n *\n * @example\n * ```typescript\n * const result = err(\"not found\");\n * const mapped = mapErr(result, e => `Error: ${e}`); // Err<\"Error: not found\">\n * ```\n */\nexport function mapErr<T, E, F>(\n\tresult: Result<T, E>,\n\tfn: (error: E) => F,\n): Result<T, F> {\n\tif (result.ok) {\n\t\treturn result;\n\t}\n\treturn err(fn(result.error));\n}\n\n/**\n * Returns the value if Ok, otherwise returns the default value.\n *\n * @param result - The result to unwrap\n * @param defaultValue - Default value to return if Err\n * @returns The Ok value or the default value\n *\n * @example\n * ```typescript\n * const result = validateUserId(\"123\");\n * const userId = unwrapOr(result, \"default-id\");\n * ```\n */\nexport function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {\n\treturn result.ok ? result.value : defaultValue;\n}\n\n/**\n * Returns the value if Ok, otherwise computes default from error.\n *\n * @param result - The result to unwrap\n * @param fn - Function to compute default from error\n * @returns The Ok value or computed default\n *\n * @example\n * ```typescript\n * const result = validateUserId(\"\");\n * const userId = unwrapOrElse(result, err => `fallback-${Date.now()}`);\n * ```\n */\nexport function unwrapOrElse<T, E>(\n\tresult: Result<T, E>,\n\tfn: (error: E) => T,\n): T {\n\treturn result.ok ? result.value : fn(result.error);\n}\n\n/**\n * Pattern matching for Result.\n * Applies one function if Ok, another if Err.\n *\n * @param result - The result to match\n * @param onOk - Function to apply if Ok\n * @param onErr - Function to apply if Err\n * @returns The result of applying the appropriate function\n *\n * @example\n * ```typescript\n * const message = match(result,\n * value => `Success: ${value}`,\n * error => `Error: ${error}`\n * );\n * ```\n *\n * @example Using object syntax\n * ```typescript\n * const message = match(result, {\n * ok: value => `Success: ${value}`,\n * err: error => `Error: ${error}`\n * });\n * ```\n */\nexport function match<T, E, R>(\n\tresult: Result<T, E>,\n\tonOk: (value: T) => R,\n\tonErr: (error: E) => R,\n): R;\nexport function match<T, E, R>(\n\tresult: Result<T, E>,\n\thandlers: { ok: (value: T) => R; err: (error: E) => R },\n): R;\nexport function match<T, E, R>(\n\tresult: Result<T, E>,\n\tonOkOrHandlers: ((value: T) => R) | { ok: (value: T) => R; err: (error: E) => R },\n\tonErr?: (error: E) => R,\n): R {\n\tif (typeof onOkOrHandlers === \"function\") {\n\t\t// Function syntax: match(result, onOk, onErr)\n\t\treturn result.ok ? onOkOrHandlers(result.value) : onErr!(result.error);\n\t}\n\t// Object syntax: match(result, { ok: ..., err: ... })\n\treturn result.ok\n\t\t? onOkOrHandlers.ok(result.value)\n\t\t: onOkOrHandlers.err(result.error);\n}\n\n/**\n * Async pattern matching for Result.\n * Applies one async function if Ok, another if Err.\n * Both handlers must return Promises.\n *\n * @param result - The result to match\n * @param onOk - Async function to apply if Ok\n * @param onErr - Async function to apply if Err\n * @returns Promise resolving to the result of applying the appropriate function\n *\n * @example\n * ```typescript\n * const message = await matchAsync(result,\n * async (value) => `Success: ${value}`,\n * async (error) => `Error: ${error}`\n * );\n * ```\n *\n * @example Using object syntax\n * ```typescript\n * const message = await matchAsync(result, {\n * ok: async (value) => `Success: ${value}`,\n * err: async (error) => `Error: ${error}`\n * });\n * ```\n */\nexport async function matchAsync<T, E, R>(\n\tresult: Result<T, E>,\n\tonOk: (value: T) => Promise<R>,\n\tonErr: (error: E) => Promise<R>,\n): Promise<R>;\nexport async function matchAsync<T, E, R>(\n\tresult: Result<T, E>,\n\thandlers: { ok: (value: T) => Promise<R>; err: (error: E) => Promise<R> },\n): Promise<R>;\nexport async function matchAsync<T, E, R>(\n\tresult: Result<T, E>,\n\tonOkOrHandlers:\n\t\t| ((value: T) => Promise<R>)\n\t\t| { ok: (value: T) => Promise<R>; err: (error: E) => Promise<R> },\n\tonErr?: (error: E) => Promise<R>,\n): Promise<R> {\n\tif (typeof onOkOrHandlers === \"function\") {\n\t\t// Function syntax: matchAsync(result, onOk, onErr)\n\t\treturn result.ok\n\t\t\t? onOkOrHandlers(result.value)\n\t\t\t: onErr!(result.error);\n\t}\n\t// Object syntax: matchAsync(result, { ok: ..., err: ... })\n\treturn result.ok\n\t\t? onOkOrHandlers.ok(result.value)\n\t\t: onOkOrHandlers.err(result.error);\n}\n\n/**\n * Pattern matching for Result that returns a Result.\n * Both handlers must return a Result, allowing you to transform\n * both the success and error cases while staying in Result context.\n *\n * @param result - The result to match\n * @param handlers - Object with ok and err handlers, both returning Result\n * @returns A new Result from the appropriate handler\n *\n * @example\n * ```typescript\n * const result = await fetchUser(id);\n * return matchResult(result, {\n * ok: (user) => ok(transformUser(user)),\n * err: (error) => err(mapToAppError(error))\n * });\n * ```\n */\nexport function matchResult<T, E, U, F>(\n\tresult: Result<T, E>,\n\thandlers: {\n\t\tok: (value: T) => Result<U, F>;\n\t\terr: (error: E) => Result<U, F>;\n\t},\n): Result<U, F>;\nexport function matchResult<T, E, U, F>(\n\tresult: Result<T, E>,\n\tonOk: (value: T) => Result<U, F>,\n\tonErr: (error: E) => Result<U, F>,\n): Result<U, F>;\nexport function matchResult<T, E, U, F>(\n\tresult: Result<T, E>,\n\tonOkOrHandlers:\n\t\t| ((value: T) => Result<U, F>)\n\t\t| { ok: (value: T) => Result<U, F>; err: (error: E) => Result<U, F> },\n\tonErr?: (error: E) => Result<U, F>,\n): Result<U, F> {\n\tif (typeof onOkOrHandlers === \"function\") {\n\t\treturn result.ok ? onOkOrHandlers(result.value) : onErr!(result.error);\n\t}\n\treturn result.ok\n\t\t? onOkOrHandlers.ok(result.value)\n\t\t: onOkOrHandlers.err(result.error);\n}\n\n/**\n * Pipes a Result through multiple operations.\n * Each function receives the previous Result and returns a new Result.\n * Stops on first error.\n *\n * @param initial - The initial Result value\n * @param fns - Array of functions that take the previous Result and return a new Result\n * @returns The final Result after all operations\n *\n * @example\n * ```typescript\n * // Instead of nested andThen calls:\n * andThen(\n * updateCountryCode(code),\n * () => andThen(updateCurrencyCode(currency), () => updateLanguageCode(lang))\n * )\n *\n * // Use pipe (cleaner and more readable):\n * pipe(\n * updateCountryCode(code),\n * () => updateCurrencyCode(currency),\n * () => updateLanguageCode(lang)\n * )\n * ```\n *\n * @example With void results\n * ```typescript\n * setInitialData(initialData: JobConfigProps[\"initialData\"]): Result<void, JobDomainError> {\n * return pipe(\n * this.updateCountryCode(initialData.countryCode),\n * () => this.updateCurrencyCode(initialData.currencyCode),\n * () => this.updateLanguageCode(initialData.languageCode)\n * );\n * }\n * ```\n */\nexport function pipe<T, E>(\n\tinitial: Result<T, E>,\n\t...fns: Array<(prev: Result<T, E>) => Result<T, E>>\n): Result<T, E> {\n\tlet current = initial;\n\tfor (const fn of fns) {\n\t\tcurrent = fn(current);\n\t\tif (!current.ok) {\n\t\t\treturn current;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * Wraps a function that may throw exceptions into a Result type.\n * Catches any thrown exceptions and converts them to Err results.\n *\n * @param fn - Function that may throw exceptions\n * @param errorMapper - Optional function to transform the caught error\n * @returns A Result containing the function's return value or error\n *\n * @example\n * ```typescript\n * function riskyOperation(): string {\n * if (Math.random() > 0.5) {\n * throw new Error(\"Something went wrong\");\n * }\n * return \"success\";\n * }\n *\n * const result = tryCatch(() => riskyOperation());\n * if (result.ok) {\n * console.log(result.value); // \"success\"\n * } else {\n * console.error(result.error.message); // \"Something went wrong\"\n * }\n * ```\n *\n * @example With custom error mapper\n * ```typescript\n * const result = tryCatch(\n * () => riskyOperation(),\n * (error) => `Custom: ${error instanceof Error ? error.message : String(error)}`\n * );\n * ```\n */\nexport function tryCatch<T, E = Error>(\n\tfn: () => T,\n\terrorMapper?: (error: unknown) => E,\n): Result<T, E> {\n\ttry {\n\t\treturn ok(fn());\n\t} catch (error) {\n\t\tif (errorMapper) {\n\t\t\treturn err(errorMapper(error));\n\t\t}\n\t\treturn err((error instanceof Error ? error : new Error(String(error))) as E);\n\t}\n}\n\n/**\n * Wraps an async function that may throw exceptions into a Promise<Result>.\n * Catches any thrown exceptions and converts them to Err results.\n *\n * @param fn - Async function that may throw exceptions\n * @param errorMapper - Optional function to transform the caught error\n * @returns A Promise resolving to a Result containing the function's return value or error\n *\n * @example\n * ```typescript\n * async function riskyAsyncOperation(): Promise<string> {\n * if (Math.random() > 0.5) {\n * throw new Error(\"Something went wrong\");\n * }\n * return \"success\";\n * }\n *\n * const result = await tryCatchAsync(() => riskyAsyncOperation());\n * if (result.ok) {\n * console.log(result.value); // \"success\"\n * } else {\n * console.error(result.error.message); // \"Something went wrong\"\n * }\n * ```\n */\nexport async function tryCatchAsync<T, E = Error>(\n\tfn: () => Promise<T>,\n\terrorMapper?: (error: unknown) => E,\n): Promise<Result<T, E>> {\n\ttry {\n\t\tconst value = await fn();\n\t\treturn ok(value);\n\t} catch (error) {\n\t\tif (errorMapper) {\n\t\t\treturn err(errorMapper(error));\n\t\t}\n\t\treturn err((error instanceof Error ? error : new Error(String(error))) as E);\n\t}\n}\n\n","import { err, ok, type Result } from \"../core/result\";\nimport type { Id } from \"../core/id\";\nimport { AggregateRoot, type AggregateConfig, type IAggregateRoot } from \"./aggregate-root\";\nimport type {\n\tAggregateSnapshot,\n\tDomainEvent,\n\tVersion,\n} from \"./aggregate\";\n\n/**\n * Interface for Event-Sourced Aggregate Roots.\n * Defines the contract for aggregates that manage state changes via event sourcing.\n *\n * @template TId - The type of the aggregate root identifier\n * @template TEvent - The union type of all domain events\n */\nexport interface IAggregateEventSourced<\n\tTId extends Id<string>,\n\tTEvent extends DomainEvent<string, unknown>,\n> extends IAggregateRoot<TId> {\n\t/**\n\t * Returns a read-only list of new, not-yet-persisted events.\n\t */\n\treadonly pendingEvents: ReadonlyArray<TEvent>;\n\n\t/**\n\t * Reconstitutes the aggregate from an event history.\n\t *\n\t * @param history - An ordered list of past events\n\t */\n\tloadFromHistory(history: TEvent[]): Result<void, string>;\n\n\t/**\n\t * Clears the list of pending events.\n\t */\n\tclearPendingEvents(): void;\n\n\t/**\n\t * Checks if the aggregate has any pending events.\n\t */\n\thasPendingEvents(): boolean;\n\n\t/**\n\t * Returns the number of pending events.\n\t */\n\tgetEventCount(): number;\n\n\t/**\n\t * Returns the latest pending event, if any.\n\t */\n\tgetLatestEvent(): TEvent | undefined;\n}\n\ntype Handler<TState, TEvent> = (state: TState, event: TEvent) => TState;\n\n/**\n * Extended configuration options for AggregateEventSourced behavior.\n */\nexport interface AggregateEventSourcedConfig extends AggregateConfig {\n\t/**\n\t * Whether to automatically bump the version when applying new events.\n\t * Defaults to true. Set to false to manually control versioning.\n\t */\n\tautoVersionBump?: boolean;\n}\n\n/**\n * Base class for Event-Sourced Aggregate Roots (Entities).\n * \n * Extends `AggregateRoot` to create an Aggregate Root Entity with Event Sourcing capabilities.\n * The Aggregate Root is the parent Entity of the aggregate and represents it externally.\n * \n * The aggregate state (`TState`) contains:\n * - Child entities (Entities with id, but no own version)\n * - Value objects (immutable objects)\n * \n * All changes to child entities are versioned through the Aggregate Root. The version\n * applies to the entire aggregate, including all child entities.\n * \n * Extends `AggregateRoot` with Event Sourcing capabilities:\n * - Event tracking (pendingEvents)\n * - Event handlers for state transitions\n * - Event validation\n * - History replay\n *\n * Use this class when you want Event Sourcing with full event tracking\n * and replay capabilities.\n *\n * @template TState - The type of the aggregate state (contains child entities and value objects)\n * @template TEvent - The union type of all domain events\n * @template TId - The type of the aggregate root identifier\n *\n * @example\n * ```typescript\n * // Order is an Aggregate Root (an Entity) with Event Sourcing\n * class Order extends AggregateEventSourced<OrderState, OrderEvent, OrderId> {\n * confirm(): void {\n * this.apply(createDomainEvent(\"OrderConfirmed\", {}));\n * }\n *\n * protected readonly handlers = {\n * OrderConfirmed: (state: OrderState): OrderState => ({\n * ...state,\n * status: \"confirmed\",\n * }),\n * };\n * }\n * ```\n */\nexport abstract class AggregateEventSourced<\n\tTState,\n\tTEvent extends DomainEvent<string, unknown>,\n\tTId extends Id<string>,\n> extends AggregateRoot<TState, TId>\n\timplements IAggregateEventSourced<TId, TEvent> {\n\tprivate readonly _eventConfig: AggregateEventSourcedConfig;\n\tprivate readonly _eventAutoVersionBump: boolean;\n\n\tprotected constructor(\n\t\tid: TId,\n\t\tinitialState: TState,\n\t\tconfig?: AggregateEventSourcedConfig,\n\t) {\n\t\tsuper(id, initialState, config);\n\t\tthis._eventConfig = config ?? {};\n\t\tthis._eventAutoVersionBump = this._eventConfig.autoVersionBump ?? true;\n\t}\n\n\t/**\n\t * Returns a read-only list of new, not-yet-persisted events.\n\t */\n\tpublic get pendingEvents(): ReadonlyArray<TEvent> {\n\t\treturn this.domainEvents as ReadonlyArray<TEvent>;\n\t}\n\n\t/**\n\t * Clears the list of pending events.\n\t * Typically called after the events have been persisted.\n\t */\n\tpublic clearPendingEvents(): void {\n\t\tthis.clearDomainEvents();\n\t}\n\n\t/**\n\t * Validates an event before it is applied.\n\t * Override this method to add custom validation logic.\n\t * Return `ok(true)` if the event is valid, `err(message)` otherwise.\n\t *\n\t * @param event - The event to validate\n\t * @returns Result indicating if the event is valid\n\t *\n\t * @example\n\t * ```typescript\n\t * protected validateEvent(event: OrderEvent): Result<true, string> {\n\t * if (event.type === \"OrderShipped\" && this.state.status !== \"confirmed\") {\n\t * return err(\"Order must be confirmed before shipping\");\n\t * }\n\t * return ok(true);\n\t * }\n\t * ```\n\t */\n\tprotected validateEvent(_event: TEvent): Result<true, string> {\n\t\treturn ok(true);\n\t}\n\n\t/**\n\t * Applies an event to change the state and adds it\n\t * to the list of pending events.\n\t * Returns a Result type instead of throwing an error.\n\t *\n\t * @param event - The domain event to apply\n\t * @param isNew - Indicates whether the event is new (and needs to be persisted)\n\t * or if it is being loaded from history\n\t * @returns Result<void, string> - ok if successful, err with error message if validation fails or handler is missing\n\t */\n\tprotected apply(event: TEvent, isNew = true): Result<void, string> {\n\t\t// Validate event before applying\n\t\tconst validation = this.validateEvent(event);\n\t\tif (!validation.ok) {\n\t\t\treturn err(\n\t\t\t\t`Event validation failed for ${event.type}: ${validation.error}`,\n\t\t\t);\n\t\t}\n\n\t\tconst handler = this.handlers[event.type as keyof typeof this.handlers];\n\t\tif (!handler) {\n\t\t\treturn err(`Missing handler for event type: ${event.type}`);\n\t\t}\n\n\t\t// First, change the state\n\t\tthis._state = handler(\n\t\t\tthis._state,\n\t\t\tevent as Extract<TEvent, { type: TEvent[\"type\"] }>,\n\t\t);\n\n\t\t// Then (if new) add the event to the list and bump version\n\t\tif (isNew) {\n\t\t\tthis.addDomainEvent(event);\n\t\t\tif (this._eventAutoVersionBump) {\n\t\t\t\tthis.version = (this.version + 1) as Version;\n\t\t\t}\n\t\t}\n\n\t\treturn ok();\n\t}\n\n\t/**\n\t * Applies an event to change the state and adds it\n\t * to the list of pending events.\n\t * Throws an error if validation fails or handler is missing.\n\t *\n\t * @param event - The domain event to apply\n\t * @param isNew - Indicates whether the event is new (and needs to be persisted)\n\t * or if it is being loaded from history\n\t * @throws Error if event validation fails or handler is missing\n\t */\n\tprotected applyUnsafe(event: TEvent, isNew = true): void {\n\t\t// Validate event before applying\n\t\tconst validation = this.validateEvent(event);\n\t\tif (!validation.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Event validation failed for ${event.type}: ${validation.error}`,\n\t\t\t);\n\t\t}\n\n\t\tconst handler = this.handlers[event.type as keyof typeof this.handlers];\n\t\tif (!handler) {\n\t\t\tthrow new Error(`Missing handler for event type: ${event.type}`);\n\t\t}\n\n\t\t// First, change the state\n\t\tthis._state = handler(\n\t\t\tthis._state,\n\t\t\tevent as Extract<TEvent, { type: TEvent[\"type\"] }>,\n\t\t);\n\n\t\t// Then (if new) add the event to the list and bump version\n\t\tif (isNew) {\n\t\t\tthis.addDomainEvent(event);\n\t\t\tif (this._eventAutoVersionBump) {\n\t\t\t\tthis.version = (this.version + 1) as Version;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Manually bumps the aggregate version.\n\t * Only needed if `autoVersionBump` is disabled.\n\t */\n\tprotected bumpVersion(): void {\n\t\tthis.version = (this.version + 1) as Version;\n\t}\n\n\t/**\n\t * Reconstitutes the aggregate from an event history.\n\t * Sets the version to the number of events in the history.\n\t *\n\t * @param history - An ordered list of past events\n\t */\n\tpublic loadFromHistory(history: TEvent[]): Result<void, string> {\n\t\tfor (const event of history) {\n\t\t\tconst result = this.apply(event, false); // 'false' as it's not a new event\n\t\t\tif (!result.ok) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\t// Set version to the number of events in history\n\t\tthis.version = history.length as Version;\n\t\treturn ok();\n\t}\n\n\t/**\n\t * Checks if the aggregate has any pending events.\n\t *\n\t * @returns true if there are pending events, false otherwise\n\t */\n\tpublic hasPendingEvents(): boolean {\n\t\treturn this.domainEvents.length > 0;\n\t}\n\n\t/**\n\t * Returns the number of pending events.\n\t *\n\t * @returns The count of pending events\n\t */\n\tpublic getEventCount(): number {\n\t\treturn this.domainEvents.length;\n\t}\n\n\t/**\n\t * Returns the latest pending event, if any.\n\t *\n\t * @returns The most recent event or undefined if no events exist\n\t */\n\tpublic getLatestEvent(): TEvent | undefined {\n\t\tconst events = this.domainEvents;\n\t\treturn events[events.length - 1] as TEvent | undefined;\n\t}\n\n\t/**\n\t * Restores the aggregate from a snapshot and applies events that occurred after the snapshot.\n\t * This is more efficient than replaying all events from the beginning.\n\t *\n\t * @param snapshot - The snapshot to restore from\n\t * @param eventsAfterSnapshot - Events that occurred after the snapshot was taken\n\t *\n\t * @example\n\t * ```typescript\n\t * const snapshot = await snapshotRepository.getLatest(aggregateId);\n\t * const eventsAfter = await eventStore.getEventsAfter(aggregateId, snapshot.version);\n\t * aggregate.restoreFromSnapshotWithEvents(snapshot, eventsAfter);\n\t * ```\n\t */\n\tpublic restoreFromSnapshotWithEvents(\n\t\tsnapshot: AggregateSnapshot<TState>,\n\t\teventsAfterSnapshot: TEvent[],\n\t): Result<void, string> {\n\t\tthis._state = snapshot.state;\n\t\tthis.version = snapshot.version;\n\n\t\t// Apply events that occurred after the snapshot\n\t\tfor (const event of eventsAfterSnapshot) {\n\t\t\tconst result = this.apply(event, false);\n\t\t\tif (!result.ok) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\t// Set version to snapshot version + events after snapshot\n\t\tthis.version = (snapshot.version + eventsAfterSnapshot.length) as Version;\n\t\treturn ok();\n\t}\n\n\t/**\n\t * A map of event types to their corresponding handlers.\n\t * Subclasses MUST implement this property.\n\t */\n\tprotected abstract readonly handlers: {\n\t\t[K in TEvent[\"type\"]]: Handler<TState, Extract<TEvent, { type: K }>>;\n\t};\n}\n\n","import type { Result } from \"../core/result\";\nimport { err } from \"../core/result\";\nimport type { Command, CommandHandler } from \"./command\";\n\n/**\n * Command Bus interface for dispatching commands to their handlers.\n * Provides a centralized way to execute commands with handler registration.\n *\n * @example\n * ```typescript\n * const bus = new CommandBus();\n * bus.register(\"CreateOrder\", createOrderHandler);\n *\n * const result = await bus.execute({\n * type: \"CreateOrder\",\n * customerId: \"123\",\n * items: [...]\n * });\n * ```\n */\nexport interface ICommandBus {\n\t/**\n\t * Executes a command by dispatching it to the registered handler.\n\t *\n\t * @param command - The command to execute\n\t * @returns Result containing the success value or error message\n\t */\n\texecute<C extends Command, R>(command: C): Promise<Result<R, string>>;\n\n\t/**\n\t * Registers a handler for a specific command type.\n\t *\n\t * @param commandType - The command type to register the handler for\n\t * @param handler - The handler function for this command type\n\t */\n\tregister<C extends Command, R>(\n\t\tcommandType: C[\"type\"],\n\t\thandler: CommandHandler<C, R>,\n\t): void;\n}\n\n/**\n * Simple in-memory command bus implementation.\n * Handlers are stored in a Map and dispatched based on command type.\n *\n * **Note:** This is a basic implementation suitable for development and simple use cases.\n * For production environments, consider implementing or using a more feature-rich bus that includes:\n * - Middleware/Pipeline support (logging, validation, authorization)\n * - Error handling and retry logic\n * - Timeout handling\n * - Metrics and observability\n * - Transaction management\n * - Dead letter queue support\n *\n * The `CommandHandler` type can still be used with external production-grade buses\n * (e.g., RabbitMQ, AWS SQS) while maintaining type safety.\n *\n * @example\n * ```typescript\n * const bus = new CommandBus();\n * bus.register(\"CreateOrder\", async (cmd) => {\n * // ... handler logic\n * return ok(orderId);\n * });\n *\n * const result = await bus.execute({ type: \"CreateOrder\", ... });\n * ```\n */\nexport class CommandBus implements ICommandBus {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate readonly handlers = new Map<string, CommandHandler<any, any>>();\n\n\tregister<C extends Command, R>(\n\t\tcommandType: C[\"type\"],\n\t\thandler: CommandHandler<C, R>,\n\t): void {\n\t\tthis.handlers.set(commandType, handler);\n\t}\n\n\tasync execute<C extends Command, R>(\n\t\tcommand: C,\n\t): Promise<Result<R, string>> {\n\t\tconst handler = this.handlers.get(command.type);\n\t\tif (!handler) {\n\t\t\treturn err(`No handler registered for command type: ${command.type}`);\n\t\t}\n\t\treturn handler(command);\n\t}\n}\n\n","import type { EventBus, Outbox } from \"../events/ports\";\nimport type { UnitOfWork } from \"../repo/uow\";\n\n/**\n * Helper function for executing commands within a transaction.\n * Handles event persistence via outbox and optional event bus publishing.\n *\n * @param deps - Dependencies including outbox, optional event bus, and unit of work\n * @param fn - Function that returns result and events\n * @returns The result wrapped in a transaction\n *\n * @example\n * ```typescript\n * const result = await withCommit(\n * { outbox, bus, uow },\n * async () => {\n * const order = Order.create(customerId, items);\n * await repository.save(order);\n * return {\n * result: order.id,\n * events: order.pendingEvents\n * };\n * }\n * );\n * ```\n */\nexport function withCommit<Evt, R>(\n\tdeps: {\n\t\toutbox: Outbox<Evt>;\n\t\tbus?: EventBus<Evt>;\n\t\tuow: UnitOfWork;\n\t},\n\tfn: () => Promise<{ result: R; events: ReadonlyArray<Evt> }>,\n) {\n\treturn deps.uow.transactional(async () => {\n\t\tconst { result, events } = await fn();\n\t\tawait deps.outbox.add(events);\n\t\tif (deps.bus) await deps.bus.publish(events);\n\t\treturn result;\n\t});\n}\n","import { err, ok, type Result } from \"../core/result\";\nimport type { Query, QueryHandler } from \"./query\";\n\n/**\n * Query Bus interface for dispatching queries to their handlers.\n * Provides a centralized way to execute queries with handler registration.\n *\n * @example\n * ```typescript\n * const bus = new QueryBus();\n * bus.register(\"GetOrder\", getOrderHandler);\n *\n * const order = await bus.execute({\n * type: \"GetOrder\",\n * orderId: \"123\"\n * });\n * ```\n */\nexport interface IQueryBus {\n\t/**\n\t * Executes a query by dispatching it to the registered handler.\n\t * Returns a Result type instead of throwing an error.\n\t *\n\t * @param query - The query to execute\n\t * @returns Result containing the query result if successful, or an error message if no handler is registered\n\t */\n\texecute<Q extends Query, R>(query: Q): Promise<Result<R, string>>;\n\n\t/**\n\t * Executes a query by dispatching it to the registered handler.\n\t * Throws an error if no handler is registered.\n\t *\n\t * @param query - The query to execute\n\t * @returns The query result\n\t * @throws Error if no handler is registered for the query type\n\t */\n\texecuteUnsafe<Q extends Query, R>(query: Q): Promise<R>;\n\n\t/**\n\t * Registers a handler for a specific query type.\n\t *\n\t * @param queryType - The query type to register the handler for\n\t * @param handler - The handler function for this query type\n\t */\n\tregister<Q extends Query, R>(\n\t\tqueryType: Q[\"type\"],\n\t\thandler: QueryHandler<Q, R>,\n\t): void;\n}\n\n/**\n * Type map for query types to their return types.\n * Used to improve type inference in QueryBus.\n */\ntype QueryTypeMap = Record<string, unknown>;\n\n/**\n * Simple in-memory query bus implementation.\n * Handlers are stored in a Map and dispatched based on query type.\n *\n * **Note:** This is a basic implementation suitable for development and simple use cases.\n * For production environments, consider implementing or using a more feature-rich bus that includes:\n * - Middleware/Pipeline support (logging, caching, rate limiting)\n * - Error handling\n * - Timeout handling\n * - Metrics and observability\n * - Query result caching\n * - Rate limiting\n *\n * The `QueryHandler` type can still be used with external production-grade buses\n * (e.g., RabbitMQ, AWS SQS) while maintaining type safety.\n *\n * @example\n * ```typescript\n * const bus = new QueryBus();\n * bus.register(\"GetOrder\", async (query) => {\n * return await repository.getById(query.orderId);\n * });\n *\n * const order = await bus.execute({ type: \"GetOrder\", orderId: \"123\" });\n * ```\n */\nexport class QueryBus<TMap extends QueryTypeMap = QueryTypeMap>\n\timplements IQueryBus\n{\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate readonly handlers = new Map<string, QueryHandler<any, any>>();\n\n\tregister<Q extends Query, R>(\n\t\tqueryType: Q[\"type\"],\n\t\thandler: QueryHandler<Q, R>,\n\t): void {\n\t\tthis.handlers.set(queryType, handler);\n\t}\n\n\tasync execute<Q extends Query & { type: keyof TMap }>(\n\t\tquery: Q,\n\t): Promise<Result<TMap[Q[\"type\"]], string>>;\n\tasync execute<Q extends Query, R>(query: Q): Promise<Result<R, string>>;\n\tasync execute<Q extends Query, R>(query: Q): Promise<Result<R, string>> {\n\t\tconst handler = this.handlers.get(query.type);\n\t\tif (!handler) {\n\t\t\treturn err(`No handler registered for query type: ${query.type}`);\n\t\t}\n\t\ttry {\n\t\t\tconst result = await handler(query);\n\t\t\treturn ok(result);\n\t\t} catch (error) {\n\t\t\treturn err(\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t);\n\t\t}\n\t}\n\n\tasync executeUnsafe<Q extends Query, R>(query: Q): Promise<R> {\n\t\tconst handler = this.handlers.get(query.type);\n\t\tif (!handler) {\n\t\t\tthrow new Error(`No handler registered for query type: ${query.type}`);\n\t\t}\n\t\treturn handler(query);\n\t}\n}\n\n","import { err, ok, type Result } from \"./result\";\n\n/**\n * Guard function that validates a condition and returns a Result.\n * Returns `ok(true)` if the condition is met, otherwise `err(error)`.\n *\n * @param cond - The condition to check\n * @param error - Error message if condition fails\n * @returns Result<true, string>\n *\n * @example\n * ```typescript\n * const result = guard(id.length > 0, \"ID cannot be empty\");\n * if (!result.ok) {\n * return err(result.error);\n * }\n * ```\n */\nexport function guard(cond: boolean, error: string): Result<true, string> {\n\treturn cond ? ok(true) : err(error);\n}\n","/**\n * Checks if an object is a built-in JavaScript type that should be treated atomically.\n * This function automatically detects built-ins without requiring manual maintenance.\n *\n * Detection strategy:\n * 1. TypedArrays: Check if tag ends with \"Array]\" (covers all current and future TypedArrays)\n * 2. ArrayBuffer views: Use ArrayBuffer.isView() (covers DataView and all TypedArrays)\n * 3. Built-in constructors: Check if constructor exists in global scope and matches known patterns\n * 4. Tag-based: Fallback to tag matching for known built-ins\n *\n * @param obj - The object to check\n * @param tag - The result of `Object.prototype.toString.call(obj)`\n * @returns `true` if the object is a built-in type, `false` otherwise\n */\nexport function isBuiltInObject(obj: object, tag: string): boolean {\n\t// 1. TypedArrays: all end with \"Array]\" - future-proof for new TypedArrays\n\tif (tag.endsWith(\"Array]\")) {\n\t\treturn true;\n\t}\n\n\t// 2. ArrayBuffer views: covers DataView and all TypedArrays (future-proof)\n\tif (ArrayBuffer.isView(obj)) {\n\t\treturn true;\n\t}\n\n\t// 3. ArrayBuffer and SharedArrayBuffer\n\tif (tag === \"[object ArrayBuffer]\" || tag === \"[object SharedArrayBuffer]\") {\n\t\treturn true;\n\t}\n\n\t// 4. Check if constructor exists in global scope (future-proof for new globals)\n\tconst objConstructor = (obj as { constructor?: unknown }).constructor;\n\tif (objConstructor && typeof objConstructor === \"function\") {\n\t\tconst constructorName = objConstructor.name;\n\t\t// Check if it's a known global constructor\n\t\t// This covers: Date, RegExp, Map, Set, WeakMap, WeakSet, Promise, Error, etc.\n\t\tif (\n\t\t\tconstructorName &&\n\t\t\ttypeof globalThis !== \"undefined\" &&\n\t\t\tconstructorName in globalThis &&\n\t\t\t(globalThis as Record<string, unknown>)[constructorName] === objConstructor\n\t\t) {\n\t\t\t// Additional check: ensure it's not a user-defined class with same name\n\t\t\t// Built-ins typically have non-enumerable properties and specific prototypes\n\t\t\tconst proto = Object.getPrototypeOf(obj);\n\t\t\tif (proto !== Object.prototype && proto !== null) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// 5. Tag-based fallback for known built-ins (covers edge cases)\n\tconst knownBuiltInTags = new Set([\n\t\t\"[object Date]\",\n\t\t\"[object RegExp]\",\n\t\t\"[object Map]\",\n\t\t\"[object Set]\",\n\t\t\"[object WeakMap]\",\n\t\t\"[object WeakSet]\",\n\t\t\"[object Promise]\",\n\t\t\"[object Error]\",\n\t\t\"[object Boolean]\",\n\t\t\"[object Number]\",\n\t\t\"[object String]\",\n\t]);\n\n\treturn knownBuiltInTags.has(tag);\n}\n\n","import { isBuiltInObject } from \"./is-built-in\";\n\nconst objProto = Object.prototype;\nconst objToString = objProto.toString;\nconst objHasOwn = objProto.hasOwnProperty;\n\n/**\n * Performs a deep equality check between two values.\n *\n * This function compares values recursively, handling:\n * - Primitives (with special handling for NaN)\n * - Arrays (nested arrays supported)\n * - Objects (plain objects and class instances)\n * - TypedArrays (Uint8Array, Int32Array, etc.)\n * - DataView\n * - Maps and Sets\n * - Dates and RegExp\n * - Wrapper objects (Boolean, Number, String)\n * - Circular references (detected and handled)\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal, `false` otherwise\n *\n * @example\n * ```ts\n * deepEqual([1, 2, 3], [1, 2, 3]); // true\n * deepEqual({ a: 1, b: [2, 3] }, { a: 1, b: [2, 3] }); // true\n * deepEqual(NaN, NaN); // true\n * deepEqual([1, 2], [1, 2, 3]); // false\n * ```\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n\treturn deepEqualInner(a, b, new WeakMap<object, object>());\n}\n\n/**\n * Internal recursive function for deep equality comparison.\n * Tracks visited objects to detect and handle circular references.\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @param visited - WeakMap to track visited object pairs and detect cycles\n * @returns `true` if the values are deeply equal, `false` otherwise\n * @internal\n */\nfunction deepEqualInner(\n\ta: unknown,\n\tb: unknown,\n\tvisited: WeakMap<object, object>\n): boolean {\n\t// 1. Fast path: reference equality\n\tif (a === b) return true;\n\n\tconst typeA = typeof a;\n\tconst typeB = typeof b;\n\n\t// 2. If one is not an object → primitive / function\n\tif (typeA !== \"object\" || a === null || typeB !== \"object\" || b === null) {\n\t\t// Special case: NaN should be equal\n\t\tif (typeA === \"number\" && typeB === \"number\") {\n\t\t\treturn Number.isNaN(a as number) && Number.isNaN(b as number);\n\t\t}\n\t\t// Everything else is directly unequal with !== (including functions)\n\t\treturn false;\n\t}\n\n\t// From here on: both are non-null objects\n\n\tconst objA = a as object;\n\tconst objB = b as object;\n\n\t// 3. Cycles: already seen pair?\n\tconst cached = visited.get(objA);\n\tif (cached !== undefined) {\n\t\t// If we already paired this A with a different B → unequal\n\t\treturn cached === objB;\n\t}\n\tvisited.set(objA, objB);\n\n\t// 4. Handle Typed Arrays / DataView first\n\tif (ArrayBuffer.isView(objA) || ArrayBuffer.isView(objB)) {\n\t\tif (!ArrayBuffer.isView(objA) || !ArrayBuffer.isView(objB)) return false;\n\n\t\tconst tagA = objToString.call(objA);\n\t\tconst tagB = objToString.call(objB);\n\t\tif (tagA !== tagB) return false;\n\n\t\t// DataView: compare byte by byte\n\t\tif (tagA === \"[object DataView]\") {\n\t\t\tconst viewA = objA as DataView;\n\t\t\tconst viewB = objB as DataView;\n\t\t\tif (viewA.byteLength !== viewB.byteLength) return false;\n\n\t\t\tconst len = viewA.byteLength;\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (viewA.getUint8(i) !== viewB.getUint8(i)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t// Typed Arrays: element by element\n\t\tconst arrA = objA as unknown as ArrayLike<unknown>;\n\t\tconst arrB = objB as unknown as ArrayLike<unknown>;\n\n\t\tconst len = arrA.length;\n\t\tif (len !== arrB.length) return false;\n\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tif ((arrA as any)[i] !== (arrB as any)[i]) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// 5. Tag-based type detection (robust across realms)\n\tconst tagA = objToString.call(objA);\n\tconst tagB = objToString.call(objB);\n\tif (tagA !== tagB) return false;\n\n\tswitch (tagA) {\n\t\tcase \"[object Array]\": {\n\t\t\tconst arrA = objA as unknown[];\n\t\t\tconst arrB = objB as unknown[];\n\t\t\tconst len = arrA.length;\n\t\t\tif (len !== arrB.length) return false;\n\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (!deepEqualInner(arrA[i], arrB[i], visited)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Map]\": {\n\t\t\tconst mapA = objA as Map<unknown, unknown>;\n\t\t\tconst mapB = objB as Map<unknown, unknown>;\n\n\t\t\tif (mapA.size !== mapB.size) return false;\n\n\t\t\tfor (const [key, valA] of mapA) {\n\t\t\t\t// Map keys according to JS semantics: reference / SameValueZero\n\t\t\t\tif (!mapB.has(key)) return false;\n\t\t\t\tconst valB = mapB.get(key);\n\t\t\t\tif (!deepEqualInner(valA, valB, visited)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Set]\": {\n\t\t\tconst setA = objA as Set<unknown>;\n\t\t\tconst setB = objB as Set<unknown>;\n\n\t\t\tif (setA.size !== setB.size) return false;\n\n\t\t\t// Set elements: same reference (JS semantics)\n\t\t\tfor (const value of setA) {\n\t\t\t\tif (!setB.has(value)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Date]\": {\n\t\t\tconst timeA = (objA as Date).getTime();\n\t\t\tconst timeB = (objB as Date).getTime();\n\t\t\treturn timeA === timeB;\n\t\t}\n\n\t\tcase \"[object RegExp]\": {\n\t\t\tconst regA = objA as RegExp;\n\t\t\tconst regB = objB as RegExp;\n\t\t\treturn regA.source === regB.source && regA.flags === regB.flags;\n\t\t}\n\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Number]\":\n\t\tcase \"[object String]\": {\n\t\t\t// Wrapper objects (new Boolean/Number/String)\n\t\t\treturn (objA as any).valueOf() === (objB as any).valueOf();\n\t\t}\n\n\t\tdefault: {\n\t\t\t// 6. Check if this is an unhandled built-in type (future-proof)\n\t\t\t// If both are built-ins but not handled above, they should be compared by reference\n\t\t\t// (since we don't know their internal structure)\n\t\t\tif (isBuiltInObject(objA, tagA) && isBuiltInObject(objB, tagB)) {\n\t\t\t\t// Unhandled built-in types: compare by reference as fallback\n\t\t\t\t// This ensures new built-ins don't fall through to plain object comparison\n\t\t\t\treturn objA === objB;\n\t\t\t}\n\n\t\t\t// 7. Fallback: plain / custom objects → compare own enumerable keys + values\n\t\t\tconst stringKeysA = Object.keys(objA as any);\n\t\t\tconst stringKeysB = Object.keys(objB as any);\n\t\t\tconst symbolKeysA = Object.getOwnPropertySymbols(objA as any);\n\t\t\tconst symbolKeysB = Object.getOwnPropertySymbols(objB as any);\n\n\t\t\t// Compare string keys count\n\t\t\tif (stringKeysA.length !== stringKeysB.length) return false;\n\t\t\t// Compare symbol keys count\n\t\t\tif (symbolKeysA.length !== symbolKeysB.length) return false;\n\n\t\t\t// Check all string keys exist in both objects\n\t\t\tfor (const key of stringKeysA) {\n\t\t\t\tif (!objHasOwn.call(objB, key)) return false;\n\t\t\t}\n\n\t\t\t// Check all symbol keys exist in both objects\n\t\t\tfor (const key of symbolKeysA) {\n\t\t\t\tif (!Object.getOwnPropertySymbols(objB as any).includes(key)) return false;\n\t\t\t}\n\n\t\t\t// Compare string key values\n\t\t\tfor (const key of stringKeysA) {\n\t\t\t\tif (!deepEqualInner((objA as any)[key], (objB as any)[key], visited)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Compare symbol key values\n\t\t\tfor (const key of symbolKeysA) {\n\t\t\t\tif (!deepEqualInner((objA as any)[key], (objB as any)[key], visited)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t}\n}\n","/**\n * Interface for entities with identity.\n * \n * In Domain-Driven Design, there are two types of entities:\n * \n * 1. **Aggregate Root Entity**: The parent Entity of an aggregate.\n * - Has identity (id) and version\n * - Implemented by classes extending `AggregateRoot` or `AggregateEventSourced`\n * - Represents the aggregate externally\n * - Loaded/saved through repositories\n * \n * 2. **Child Entities**: Entities within an aggregate.\n * - Have identity (id), but no own version\n * - Exist only within the aggregate boundary\n * - Versioned through the Aggregate Root\n * - Cannot be referenced directly from outside the aggregate\n * \n * This interface is used for child entities within aggregates. The Aggregate Root\n * also implements this interface (through `AggregateRoot<TId>`), but additionally\n * has version management.\n *\n * @template TId - The type of the entity identifier\n *\n * @example\n * ```typescript\n * // Child Entity within an aggregate\n * type OrderItem = Entity<ItemId> & {\n * productId: string;\n * quantity: number;\n * };\n * \n * // Aggregate Root (also an Entity, but with version)\n * class Order extends AggregateRoot<OrderState, OrderId> \n * implements AggregateRoot<OrderId> {\n * // Order is an Entity (the Aggregate Root)\n * // OrderState contains OrderItem (child entities)\n * }\n * ```\n */\nimport { deepEqual } from \"../utils/array/deep-equal\";\n\n/**\n * Functional definition of an Entity via its capability.\n * An object is identifiable if it has an id.\n */\nexport type Identifiable<TId> = {\n\treadonly id: TId;\n};\n\n/**\n * Interface for Entities.\n * Extends Identifiable and adds equality comparison behavior.\n *\n * @template TId - The type of the entity identifier\n */\nexport interface IEntity<TId> extends Identifiable<TId> {\n\t/**\n\t * Checks if this entity is equal to another.\n\t * Two entities are equal if they have the same ID.\n\t *\n\t * @param other - The other entity to compare\n\t * @returns true if IDs are equal\n\t */\n\tequals(other: Identifiable<TId>): boolean;\n}\n\n/**\n * Abstract base class for Entities.\n * Provides identity equality and common behavior.\n * \n * @template TId - The type of the entity identifier\n */\nexport abstract class Entity<TId> implements IEntity<TId> {\n\tpublic readonly id: TId;\n\n\tconstructor(id: TId) {\n\t\tif (id === null || id === undefined) {\n\t\t\tthrow new Error(\"Entity ID cannot be null or undefined\");\n\t\t}\n\t\tthis.id = id;\n\t\tthis.validate();\n\t}\n\n\t/**\n\t * Optional validation hook that can be overridden by subclasses.\n\t * Should throw an error if validation fails.\n\t */\n\tprotected validate(): void {\n\t\t// Default implementation does nothing\n\t}\n\n\t/**\n\t * Serializes the entity to a plain object.\n\t * Default implementation returns the entity as is (since it's an object with properties).\n\t * Subclasses can override this to control JSON serialization.\n\t */\n\tpublic toJSON(): unknown {\n\t\treturn {\n\t\t\t...this,\n\t\t\tid: this.id, // Ensure ID is present\n\t\t};\n\t}\n\n\t/**\n\t * Checks if this entity is equal to another.\n\t * Two entities are equal if they have the same ID.\n\t * \n\t * @param other - The other entity to compare\n\t * @returns true if IDs are equal\n\t */\n\tpublic equals(other: Identifiable<TId>): boolean {\n\t\tif (other === null || other === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this === other) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!isEntity(other)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn sameEntity(this, other);\n\t}\n}\n\n/**\n * Type guard to check if an object is an Entity.\n */\nfunction isEntity(obj: unknown): obj is Identifiable<unknown> {\n\treturn typeof obj === \"object\" && obj !== null && \"id\" in obj;\n}\n\n\n/**\n * Checks if two entities have the same ID.\n * Works with any object that has an 'id' property.\n *\n * @param a - First entity\n * @param b - Second entity\n * @returns true if both entities have the same ID, false otherwise\n *\n * @example\n * ```typescript\n * const item1: OrderItem = { id: itemId1, productId: \"prod-1\", quantity: 2 };\n * const item2: OrderItem = { id: itemId2, productId: \"prod-2\", quantity: 1 };\n *\n * sameEntity(item1, item2); // false\n * sameEntity(item1, item1); // true\n * ```\n */\nexport function sameEntity<TId>(a: Identifiable<TId>, b: Identifiable<TId>): boolean {\n\treturn deepEqual(a.id, b.id);\n}\n\n/**\n * Finds an entity by ID in a collection.\n * Returns undefined if not found.\n *\n * @param entities - Array of entities to search\n * @param id - The ID to search for\n * @returns The entity if found, undefined otherwise\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 },\n * { id: itemId2, productId: \"prod-2\", quantity: 1 }\n * ];\n *\n * const item = findEntityById(items, itemId1);\n * // item is { id: itemId1, productId: \"prod-1\", quantity: 2 }\n * ```\n */\nexport function findEntityById<TId, T extends Identifiable<TId>>(\n\tentities: T[],\n\tid: TId,\n): T | undefined {\n\treturn entities.find((entity) => deepEqual(entity.id, id));\n}\n\n/**\n * Checks if an entity with the given ID exists in the collection.\n *\n * @param entities - Array of entities to search\n * @param id - The ID to check for\n * @returns true if an entity with the ID exists, false otherwise\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 }\n * ];\n *\n * hasEntityId(items, itemId1); // true\n * hasEntityId(items, itemId2); // false\n * ```\n */\nexport function hasEntityId<TId, T extends Identifiable<TId>>(\n\tentities: T[],\n\tid: TId,\n): boolean {\n\treturn entities.some((entity) => deepEqual(entity.id, id));\n}\n\n/**\n * Removes an entity with the given ID from the collection.\n * Returns a new array without the entity.\n *\n * @param entities - Array of entities\n * @param id - The ID of the entity to remove\n * @returns A new array without the entity with the given ID\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 },\n * { id: itemId2, productId: \"prod-2\", quantity: 1 }\n * ];\n *\n * const updated = removeEntityById(items, itemId1);\n * // updated is [{ id: itemId2, productId: \"prod-2\", quantity: 1 }]\n * ```\n */\nexport function removeEntityById<TId, T extends Identifiable<TId>>(\n\tentities: T[],\n\tid: TId,\n): T[] {\n\treturn entities.filter((entity) => !deepEqual(entity.id, id));\n}\n\n/**\n * Updates an entity with the given ID in the collection.\n * Returns a new array with the updated entity.\n * If the entity is not found, returns the original array unchanged.\n *\n * @param entities - Array of entities\n * @param id - The ID of the entity to update\n * @param updater - Function that takes the entity and returns the updated entity\n * @returns A new array with the updated entity\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 }\n * ];\n *\n * const updated = updateEntityById(items, itemId1, (item) => ({\n * ...item,\n * quantity: item.quantity + 1\n * }));\n * // updated is [{ id: itemId1, productId: \"prod-1\", quantity: 3 }]\n * ```\n */\nexport function updateEntityById<TId, T extends Identifiable<TId>>(\n\tentities: T[],\n\tid: TId,\n\tupdater: (entity: T) => T,\n): T[] {\n\treturn entities.map((entity) => (deepEqual(entity.id, id) ? updater(entity) : entity));\n}\n\n/**\n * Replaces an entity with the given ID in the collection.\n * Returns a new array with the replaced entity.\n * If the entity is not found, returns the original array unchanged.\n *\n * @param entities - Array of entities\n * @param id - The ID of the entity to replace\n * @param replacement - The replacement entity\n * @returns A new array with the replaced entity\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 }\n * ];\n *\n * const updated = replaceEntityById(items, itemId1, {\n * id: itemId1,\n * productId: \"prod-1\",\n * quantity: 5\n * });\n * ```\n */\nexport function replaceEntityById<TId, T extends Identifiable<TId>>(\n\tentities: T[],\n\tid: TId,\n\treplacement: T,\n): T[] {\n\treturn entities.map((entity) => (deepEqual(entity.id, id) ? replacement : entity));\n}\n\n/**\n * Extracts all IDs from a collection of entities.\n *\n * @param entities - Array of entities\n * @returns Array of entity IDs\n *\n * @example\n * ```typescript\n * const items: OrderItem[] = [\n * { id: itemId1, productId: \"prod-1\", quantity: 2 },\n * { id: itemId2, productId: \"prod-2\", quantity: 1 }\n * ];\n *\n * const ids = entityIds(items);\n * // ids is [itemId1, itemId2]\n * ```\n */\nexport function entityIds<TId, T extends Identifiable<TId>>(entities: T[]): TId[] {\n\treturn entities.map((entity) => entity.id);\n}\n\n","import type { DomainEvent } from \"../aggregate/aggregate\";\nimport type { EventBus, EventHandler } from \"./ports\";\n\n/**\n * Simple in-memory event bus implementation.\n * Supports multiple subscribers per event type (pub/sub pattern).\n *\n * @template Evt - The type of domain events (must extend DomainEvent)\n *\n * @example\n * ```typescript\n * const bus = new EventBusImpl<OrderEvent>();\n *\n * bus.subscribe(\"OrderCreated\", async (event) => {\n * await sendEmail(event.payload.customerId);\n * });\n *\n * bus.subscribe(\"OrderCreated\", async (event) => {\n * await logEvent(event);\n * });\n *\n * await bus.publish([orderCreatedEvent]);\n * // Both handlers will be called\n * ```\n */\nexport class EventBusImpl<Evt extends DomainEvent<string, unknown>>\n\timplements EventBus<Evt>\n{\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate readonly handlers = new Map<string, Set<EventHandler<any>>>();\n\n\tsubscribe<T extends Evt>(\n\t\teventType: string,\n\t\thandler: EventHandler<T>,\n\t): () => void {\n\t\tconst type = eventType;\n\t\tif (!this.handlers.has(type)) {\n\t\t\tthis.handlers.set(type, new Set());\n\t\t}\n\t\tconst handlersForType = this.handlers.get(type)!;\n\t\thandlersForType.add(handler);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\thandlersForType.delete(handler);\n\t\t\tif (handlersForType.size === 0) {\n\t\t\t\tthis.handlers.delete(type);\n\t\t\t}\n\t\t};\n\t}\n\n\tasync publish(events: ReadonlyArray<Evt>): Promise<void> {\n\t\tfor (const event of events) {\n\t\t\tconst handlersForType = this.handlers.get(event.type);\n\t\t\tif (handlersForType) {\n\t\t\t\t// Call all handlers for this event type\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tArray.from(handlersForType).map((handler) => handler(event)),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\n","import { isBuiltInObject } from \"./is-built-in\";\n\nexport type Key = string | symbol;\nexport type PathSegment = string | number | symbol;\n\nexport interface DeepOmitOptions {\n\t/**\n\t * Keys to ignore everywhere in the object tree.\n\t * Only applies to object properties, not Map/Set/TypedArray contents.\n\t */\n\treadonly ignoreKeys?: readonly Key[];\n\n\t/**\n\t * Fine-grained control: Key + path (without current key).\n\t * Example path: [\"user\", \"meta\", 0, \"data\"]\n\t */\n\treadonly ignoreKeyPredicate?: (\n\t\tkey: Key,\n\t\tpath: readonly PathSegment[],\n\t) => boolean;\n}\n\n/**\n * Creates a deep copy of `value` with certain keys removed according to the provided rules.\n *\n * This function recursively traverses the object tree and removes keys that match\n * the criteria specified in `options`. Built-in types (Date, Map, Set, TypedArrays, etc.)\n * are treated atomically and not modified.\n *\n * @param value - The value to create a deep copy from\n * @param options - Options specifying which keys to ignore\n * @returns A deep copy of `value` with specified keys removed\n *\n * @example\n * ```ts\n * const obj = { a: 1, b: { c: 2, d: 3 } };\n * const result = deepOmit(obj, { ignoreKeys: ['d'] });\n * // result: { a: 1, b: { c: 2 } }\n * ```\n */\nexport function deepOmit<T>(value: T, options: DeepOmitOptions): T {\n\tconst visited = new WeakMap<object, unknown>();\n\treturn omitInternal(value, options, [], visited) as T;\n}\n\nfunction omitInternal(\n\tvalue: unknown,\n\toptions: DeepOmitOptions,\n\tpath: PathSegment[],\n\tvisited: WeakMap<object, unknown>,\n): unknown {\n\tif (value === null) return value;\n\tconst type = typeof value;\n\n\t// Primitives and functions are passed through unchanged\n\tif (type !== \"object\") return value;\n\n\tconst obj = value as object;\n\n\t// Cycles: return cached value if already visited\n\tconst cached = visited.get(obj);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\n\tconst tag = Object.prototype.toString.call(obj);\n\n\t// Arrays: recursively process elements\n\tif (tag === \"[object Array]\") {\n\t\tconst arr = obj as unknown[];\n\t\tconst clone: unknown[] = new Array(arr.length);\n\t\tvisited.set(obj, clone);\n\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tpath.push(i);\n\t\t\tclone[i] = omitInternal(arr[i], options, path, visited);\n\t\t\tpath.pop();\n\t\t}\n\t\treturn clone;\n\t}\n\n\t// Built-ins: treat atomically, no key filtering inside\n\t// Future-proof detection: check if object is a built-in type\n\tif (isBuiltInObject(obj, tag)) {\n\t\treturn value;\n\t}\n\n\t// Plain / Custom Objects: filter keys, recursively process values\n\tconst clone = Object.create(Object.getPrototypeOf(obj));\n\tvisited.set(obj, clone);\n\n\tconst stringKeys = Object.keys(obj);\n\tconst symbolKeys = Object.getOwnPropertySymbols(obj);\n\tconst keys: Key[] = [...stringKeys, ...symbolKeys];\n\n\tfor (const key of keys) {\n\t\tif (shouldIgnoreKey(key, path, options)) continue;\n\n\t\tpath.push(key);\n\t\t(clone as Record<PropertyKey, unknown>)[key] = omitInternal(\n\t\t\t(obj as Record<PropertyKey, unknown>)[key],\n\t\t\toptions,\n\t\t\tpath,\n\t\t\tvisited,\n\t\t);\n\t\tpath.pop();\n\t}\n\n\treturn clone;\n}\n\nfunction shouldIgnoreKey(\n\tkey: Key,\n\tpath: readonly PathSegment[],\n\toptions: DeepOmitOptions,\n): boolean {\n\tif (options.ignoreKeys?.includes(key)) {\n\t\treturn true;\n\t}\n\tif (options.ignoreKeyPredicate?.(key, path)) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n","import { deepEqual } from \"./deep-equal\";\nimport { type DeepOmitOptions, deepOmit } from \"./deep-omit\";\n\nexport type DeepEqualExceptOptions = DeepOmitOptions;\n\n/**\n * Performs a deep equality comparison between two values after omitting specified keys.\n * \n * This function first removes the specified keys from both values using `deepOmit`,\n * then performs a deep equality check using `deepEqual`.\n * \n * @param a - The first value to compare\n * @param b - The second value to compare\n * @param options - Options specifying which keys to omit before comparison\n * @returns `true` if the values are deeply equal after omitting specified keys, `false` otherwise\n * \n * @example\n * ```ts\n * const obj1 = { id: 1, name: \"Alice\", updatedAt: \"2024-01-01\" };\n * const obj2 = { id: 2, name: \"Alice\", updatedAt: \"2024-01-02\" };\n * \n * deepEqualExcept(obj1, obj2, { ignoreKeys: [\"id\", \"updatedAt\"] }); // true\n * ```\n */\nexport function deepEqualExcept(\n\ta: unknown,\n\tb: unknown,\n\toptions: DeepEqualExceptOptions,\n): boolean {\n\tconst prunedA = deepOmit(a, options);\n\tconst prunedB = deepOmit(b, options);\n\treturn deepEqual(prunedA, prunedB);\n}\n","import { err, ok, type Result } from \"../core/result\";\nimport { deepEqual } from \"../utils/array/deep-equal\";\nimport {\n\tdeepEqualExcept,\n\ttype DeepEqualExceptOptions,\n} from \"../utils/array/deep-equal-except\";\n\nexport type VO<T> = Readonly<T>;\n\n/**\n * Deep freezes an object and all its nested properties recursively.\n * This ensures true immutability for value objects with nested structures.\n * Handles circular references by tracking visited objects.\n */\nexport function deepFreeze<T>(obj: T, visited = new WeakSet<object>()): Readonly<T> {\n\t// Handle null and non-objects\n\tif (obj === null || typeof obj !== \"object\") {\n\t\treturn obj as Readonly<T>;\n\t}\n\n\t// Handle circular references\n\tif (visited.has(obj as object)) {\n\t\treturn obj as Readonly<T>;\n\t}\n\n\t// Mark as visited\n\tvisited.add(obj as object);\n\n\t// Retrieve the property names defined on obj\n\tconst propNames = Object.getOwnPropertyNames(obj);\n\n\t// Freeze properties before freezing self\n\tfor (const name of propNames) {\n\t\tconst value = (obj as Record<string, unknown>)[name];\n\n\t\t// Freeze value if it is an object or array\n\t\tif (value && (typeof value === \"object\" || Array.isArray(value))) {\n\t\t\tdeepFreeze(value, visited);\n\t\t}\n\t}\n\n\treturn Object.freeze(obj) as Readonly<T>;\n}\n\n/**\n * Creates a deeply immutable value object from the given data.\n * All nested objects and arrays are frozen recursively.\n *\n * @param t - The data to convert into a value object\n * @returns A deeply frozen, immutable value object\n *\n * @example\n * ```typescript\n * const address = vo({\n * street: \"Main St\",\n * city: \"Berlin\",\n * coordinates: { lat: 52.5, lng: 13.4 }\n * });\n * // address.coordinates.lat = 99; // ❌ Error: Cannot assign to read-only property\n * ```\n */\nexport function vo<T>(t: T): VO<T> {\n\treturn deepFreeze({ ...t });\n}\n\n/**\n * Compares two value objects for equality based on their values.\n * Uses deep equality comparison that handles:\n * - Nested objects and arrays\n * - Primitives (including NaN)\n * - Dates, Maps, Sets, RegExp\n * - TypedArrays and DataView\n * - Symbol keys\n * - Circular references\n *\n * @param a - First value object\n * @param b - Second value object\n * @returns true if both objects have the same values, false otherwise\n *\n * @example\n * ```typescript\n * const money1 = vo({ amount: 100, currency: \"USD\" });\n * const money2 = vo({ amount: 100, currency: \"USD\" });\n * voEquals(money1, money2); // true\n *\n * const address1 = vo({\n * street: \"Main St\",\n * coordinates: { lat: 52.5, lng: 13.4 }\n * });\n * const address2 = vo({\n * street: \"Main St\",\n * coordinates: { lat: 52.5, lng: 13.4 }\n * });\n * voEquals(address1, address2); // true\n * ```\n */\nexport function voEquals<T>(a: VO<T>, b: VO<T>): boolean {\n\treturn deepEqual(a, b);\n}\n\n/**\n * Compares two value objects for equality while ignoring specified keys.\n * Useful for comparing value objects that contain metadata or optional fields\n * that should not affect equality comparison.\n *\n * @param a - First value object\n * @param b - Second value object\n * @param options - Options specifying which keys to ignore during comparison\n * @returns true if both objects have the same values (after ignoring specified keys), false otherwise\n *\n * @example\n * ```typescript\n * // Value object with metadata\n * const address1 = vo({\n * street: \"Main St\",\n * city: \"Berlin\",\n * metadata: { createdAt: \"2024-01-01\", updatedAt: \"2024-01-02\" }\n * });\n *\n * const address2 = vo({\n * street: \"Main St\",\n * city: \"Berlin\",\n * metadata: { createdAt: \"2024-01-01\", updatedAt: \"2024-01-03\" }\n * });\n *\n * // Compare ignoring metadata timestamps\n * voEqualsExcept(address1, address2, {\n * ignoreKeys: [\"updatedAt\"],\n * ignoreKeyPredicate: (key, path) => path.includes(\"metadata\")\n * }); // true\n *\n * // Compare ignoring all metadata\n * voEqualsExcept(address1, address2, {\n * ignoreKeyPredicate: (key, path) => path.includes(\"metadata\")\n * }); // true\n * ```\n */\nexport function voEqualsExcept<T>(\n\ta: VO<T>,\n\tb: VO<T>,\n\toptions: DeepEqualExceptOptions,\n): boolean {\n\treturn deepEqualExcept(a, b, options);\n}\n\n/**\n * Creates a value object with optional validation.\n * Returns a Result type instead of throwing an error.\n *\n * @param t - The data to convert into a value object\n * @param validate - Validation function that returns true if valid\n * @param errorMessage - Optional custom error message if validation fails\n * @returns Result containing the value object if valid, or an error message if validation fails\n *\n * @example\n * ```typescript\n * const result = voWithValidation(\n * { amount: 100, currency: \"USD\" },\n * (m) => m.amount >= 0 && m.currency.length === 3,\n * \"Invalid money: amount must be non-negative and currency must be 3 characters\"\n * );\n *\n * if (result.ok) {\n * console.log(result.value); // Use the value object\n * } else {\n * console.error(result.error); // Handle validation error\n * }\n * ```\n */\nexport function voWithValidation<T>(\n\tt: T,\n\tvalidate: (value: T) => boolean,\n\terrorMessage?: string,\n): Result<VO<T>, string> {\n\tif (!validate(t)) {\n\t\treturn err(\n\t\t\terrorMessage ?? `Validation failed for value object: ${JSON.stringify(t)}`,\n\t\t);\n\t}\n\treturn ok(vo(t));\n}\n\n/**\n * Creates a value object with optional validation.\n * Throws an error if validation fails.\n *\n * @param t - The data to convert into a value object\n * @param validate - Validation function that returns true if valid\n * @param errorMessage - Optional custom error message if validation fails\n * @returns A deeply frozen, immutable value object\n * @throws Error if validation fails\n *\n * @example\n * ```typescript\n * const money = voWithValidationUnsafe(\n * { amount: 100, currency: \"USD\" },\n * (m) => m.amount >= 0 && m.currency.length === 3,\n * \"Invalid money: amount must be non-negative and currency must be 3 characters\"\n * );\n * ```\n */\nexport function voWithValidationUnsafe<T>(\n\tt: T,\n\tvalidate: (value: T) => boolean,\n\terrorMessage?: string,\n): VO<T> {\n\tif (!validate(t)) {\n\t\tthrow new Error(\n\t\t\terrorMessage ?? `Validation failed for value object: ${JSON.stringify(t)}`,\n\t\t);\n\t}\n\treturn vo(t);\n}\n","import { deepEqual } from \"../utils/array/deep-equal\";\nimport { deepFreeze } from \"./vo\";\n\n/**\n * Interface for Value Objects.\n * Value Objects are immutable and defined by their properties.\n *\n * @template T - The shape of the value object's properties\n */\nexport interface IValueObject<T extends object> {\n /**\n * The immutable properties of the value object.\n */\n readonly props: Readonly<T>;\n\n /**\n * Checks if this value object is equal to another.\n * Uses deep equality comparison on the properties.\n *\n * @param other - The other value object to compare\n * @returns true if the properties are deeply equal\n */\n equals(other: IValueObject<T>): boolean;\n\n /**\n * Creates a clone of the value object with optional property overrides.\n *\n * @param props - Optional properties to override\n * @returns A new instance of the value object\n */\n clone(props?: Partial<T>): IValueObject<T>;\n\n /**\n * Serializes the value object to its raw properties for JSON operations.\n *\n * @returns The raw properties object\n */\n toJSON(): Readonly<T>;\n}\n\n/**\n * Abstract base class for creating Value Objects.\n * Value Objects are immutable and defined by their properties.\n *\n * @template T - The shape of the value object's properties\n */\nexport abstract class ValueObject<T extends object> implements IValueObject<T> {\n public readonly props: Readonly<T>;\n\n /**\n * Creates a new ValueObject.\n * The properties are deeply frozen to ensure immutability.\n *\n * @param props - The properties of the value object\n * @example\n * ```ts\n * class Money extends ValueObject<{ amount: number; currency: string }> {\n * constructor(props: { amount: number; currency: string }) {\n * super(props);\n * }\n *\n * protected validate(props: { amount: number; currency: string }): void {\n * if (props.amount < 0) throw new Error(\"Amount cannot be negative\");\n * }\n * }\n * ```\n */\n constructor(props: T) {\n this.validate(props);\n this.props = deepFreeze({ ...props });\n }\n\n /**\n * Optional validation hook that can be overridden by subclasses.\n * Should throw an error if validation fails.\n *\n * @param props - The properties to validate\n * @throws Error if validation fails\n */\n protected validate(props: T): void {\n // Default implementation does nothing\n }\n\n /**\n * Checks if this value object is equal to another.\n * Uses deep equality comparison on the properties and checks for constructor equality.\n *\n * @param other - The other value object to compare\n * @returns true if the properties are deeply equal and constructors match\n */\n public equals(other: ValueObject<T>): boolean {\n if (other === null || other === undefined) {\n return false;\n }\n\n if (this.constructor !== other.constructor) {\n return false;\n }\n\n return deepEqual(this.props, other.props);\n }\n\n /**\n * Creates a clone of the value object with optional property overrides.\n *\n * @param props - Optional properties to override\n * @returns A new instance of the value object\n */\n public clone(props?: Partial<T>): this {\n const Constructor = this.constructor as new (props: T) => this;\n return new Constructor({ ...this.props, ...(props || {}) });\n }\n\n /**\n * Serializes the value object to its raw properties for JSON operations.\n *\n * @returns The raw properties object\n */\n public toJSON(): Readonly<T> {\n return this.props;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shirudo/ddd-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Composable TypeScript toolkit for tactical DDD",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -63,4 +63,4 @@
|
|
|
63
63
|
"bugs": {
|
|
64
64
|
"url": "https://github.com/shi-rudo/ddd-kit-ts/issues"
|
|
65
65
|
}
|
|
66
|
-
}
|
|
66
|
+
}
|