@blac/core 2.0.0-rc-7 → 2.0.0-rc-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +2 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +194 -7
- package/dist/index.es.js +1096 -563
- package/dist/index.es.js.map +1 -1
- package/package.json +5 -4
- package/src/Blac.ts +204 -99
- package/src/BlacObserver.ts +62 -25
- package/src/Bloc.ts +166 -149
- package/src/BlocBase.ts +269 -85
- package/src/Cubit.ts +1 -1
- package/src/__tests__/Bloc.event.test.ts +419 -0
- package/src/__tests__/BlocBase.lifecycle.test.ts +441 -0
- package/src/__tests__/Cubit.test.ts +473 -0
- package/src/adapter/BlacAdapter.ts +262 -0
- package/src/adapter/ConsumerTracker.ts +241 -0
- package/src/adapter/ProxyFactory.ts +308 -0
- package/src/adapter/__tests__/BlacAdapter.test.ts +561 -0
- package/src/adapter/__tests__/ConsumerTracker.test.ts +562 -0
- package/src/adapter/__tests__/ProxyFactory.test.ts +655 -0
- package/src/adapter/index.ts +3 -0
- package/src/index.ts +2 -1
- package/src/testing.ts +60 -47
- package/src/types.ts +21 -6
- package/src/utils/uuid.ts +4 -4
- package/src/BlacEvent.ts +0 -5
package/dist/index.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var k=Object.defineProperty;var M=(d,e,t)=>e in d?k(d,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[e]=t;var i=(d,e,t)=>M(d,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=class u{getInstance(){return u._instance||(u._instance=new l({__unsafe_ignore_singleton:!0})),u._instance}setInstance(e){u._instance=e}resetInstance(){const e=u._instance;if(u._instance=new l({__unsafe_ignore_singleton:!0}),e)for(const t of e.keepAliveBlocs)u._instance.keepAliveBlocs.add(t),u._instance.uidRegistry.set(t.uid,t)}};i(u,"_instance");let v=u,g=new v;function x(d){g=d}const c=class c{constructor(e={}){i(this,"createdAt",Date.now());i(this,"blocInstanceMap",new Map);i(this,"isolatedBlocMap",new Map);i(this,"isolatedBlocIndex",new Map);i(this,"uidRegistry",new Map);i(this,"keepAliveBlocs",new Set);i(this,"postChangesToDocument",!1);i(this,"log",(...e)=>{c.enableLog&&console.warn(`☢️ [Blac ${this.createdAt.toString()}]`,...e)});i(this,"warn",(e,...t)=>{c.enableLog&&console.warn(`🚨 [Blac ${String(c.instance.createdAt)}]`,e,...t)});i(this,"error",(e,...t)=>{c.enableLog&&console.error(`🚨 [Blac ${String(c.instance.createdAt)}]`,e,...t)});i(this,"resetInstance",()=>{this.log("Reset Blac instance");const e=new Map(this.blocInstanceMap),t=new Map(this.isolatedBlocMap);e.forEach(s=>{!s._keepAlive&&s._disposalState==="active"&&this.disposeBloc(s)}),t.forEach(s=>{s.forEach(n=>{!n._keepAlive&&n._disposalState==="active"&&this.disposeBloc(n)})}),this.blocInstanceMap.clear(),this.isolatedBlocMap.clear(),this.isolatedBlocIndex.clear(),g.resetInstance()});i(this,"disposeBloc",e=>{if(e._disposalState!=="active"){this.log(`[${e._name}:${String(e._id)}] disposeBloc called on already disposed bloc`);return}const t=e.constructor,s=this.createBlocInstanceMapKey(e._name,e._id);this.log(`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(t.isolated)}`),e._dispose(),t.isolated?(this.unregisterIsolatedBlocInstance(e),this.blocInstanceMap.delete(s)):this.unregisterBlocInstance(e),this.log("dispatched bloc",e)});i(this,"activateBloc",e=>{const t=e.constructor;(e.isIsolated?this.findIsolatedBlocInstance(t,e._id):this.findRegisteredBlocInstance(t,e._id))||(this.log(`[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`),e.isIsolated?this.registerIsolatedBlocInstance(e):this.registerBlocInstance(e))});i(this,"getBloc",(e,t={})=>{const{id:s}=t,n=e,o=s??e.name;if(n.isolated){const r=this.findIsolatedBlocInstance(e,o);if(r)return this.log(`[${e.name}:${String(o)}] (getBloc) Found existing isolated instance.`,t),r;if(t.throwIfNotFound)throw new Error(`Isolated bloc ${e.name} not found`)}else{const r=this.findRegisteredBlocInstance(e,o);if(r)return this.log(`[${e.name}:${String(o)}] (getBloc) Found existing registered instance.`,t),r;if(t.throwIfNotFound)throw new Error(`Registered bloc ${e.name} not found`)}const a=this.createNewBlocInstance(e,o,t);if(this.log(`[${e.name}:${String(o)}] (getBloc) No existing instance found. Creating new one.`,t,a),!a)throw new Error(`[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`);return a});i(this,"getBlocOrThrow",(e,t={})=>{const s=e.isolated,n=t.id||e.name,o=s?this.findIsolatedBlocInstance(e,n):this.findRegisteredBlocInstance(e,n);if(o)return o;throw new Error(`Bloc ${e.name} not found`)});i(this,"getAllBlocs",(e,t={})=>{const s=[];if(this.blocInstanceMap.forEach(n=>{n.constructor===e&&s.push(n)}),t.searchIsolated!==!1){const n=this.isolatedBlocMap.get(e);n&&s.push(...n.map(o=>o))}return s});i(this,"disposeKeepAliveBlocs",e=>{const t=[];for(const s of this.keepAliveBlocs)(!e||s.constructor===e)&&t.push(s);t.forEach(s=>s._dispose())});i(this,"disposeBlocs",e=>{const t=[];for(const s of this.blocInstanceMap.values())e(s)&&t.push(s);for(const s of this.isolatedBlocMap.values())for(const n of s)e(n)&&t.push(n);t.forEach(s=>s._dispose())});i(this,"getMemoryStats",()=>({totalBlocs:this.uidRegistry.size,registeredBlocs:this.blocInstanceMap.size,isolatedBlocs:Array.from(this.isolatedBlocMap.values()).reduce((e,t)=>e+t.length,0),keepAliveBlocs:this.keepAliveBlocs.size,isolatedBlocTypes:this.isolatedBlocMap.size}));i(this,"validateConsumers",()=>{for(const e of this.uidRegistry.values())e._validateConsumers(),e._consumers.size===0&&!e._keepAlive&&e._disposalState==="active"&&setTimeout(()=>{e._consumers.size===0&&!e._keepAlive&&e._disposalState==="active"&&this.disposeBloc(e)},1e3)});const{__unsafe_ignore_singleton:t=!1}=e;if(!t)return c.instance;g.setInstance(this)}static get instance(){return g.getInstance()}static get getAllBlocs(){return c.instance.getAllBlocs}static get log(){return c.instance.log}static getInstance(){return g.getInstance()}static get warn(){return c.instance.warn}static get error(){return c.instance.error}static get disposeBloc(){return c.instance.disposeBloc}createBlocInstanceMapKey(e,t){return`${e}:${String(t)}`}unregisterBlocInstance(e){const t=this.createBlocInstanceMapKey(e._name,e._id);this.blocInstanceMap.delete(t),this.uidRegistry.delete(e.uid),this.keepAliveBlocs.delete(e)}registerBlocInstance(e){const t=this.createBlocInstanceMapKey(e._name,e._id);this.blocInstanceMap.set(t,e),this.uidRegistry.set(e.uid,e),e._keepAlive&&this.keepAliveBlocs.add(e)}findRegisteredBlocInstance(e,t){if(e.isolated)return;const n=this.createBlocInstanceMapKey(e.name,t);return this.blocInstanceMap.get(n)}registerIsolatedBlocInstance(e){const t=e.constructor,s=this.isolatedBlocMap.get(t);s?s.push(e):this.isolatedBlocMap.set(t,[e]),this.isolatedBlocIndex.set(e.uid,e),this.uidRegistry.set(e.uid,e),e._keepAlive&&this.keepAliveBlocs.add(e)}unregisterIsolatedBlocInstance(e){const t=e.constructor,s=this.isolatedBlocMap.get(t);let n=!1;if(s){const a=s.findIndex(r=>r.uid===e.uid);a!==-1&&(s.splice(a,1),n=!0),s.length===0&&this.isolatedBlocMap.delete(t)}const o=this.isolatedBlocIndex.delete(e.uid);this.uidRegistry.delete(e.uid),this.keepAliveBlocs.delete(e),n!==o&&this.warn(`[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${n}, Index removal: ${o}`)}findIsolatedBlocInstance(e,t){if(!e.isolated)return;const n=this.isolatedBlocMap.get(e);return n?n.find(a=>a._id===t):void 0}findIsolatedBlocInstanceByUid(e){return this.isolatedBlocIndex.get(e)}createNewBlocInstance(e,t,s={}){const{props:n,instanceRef:o}=s,a=new e(n);return a._instanceRef=o,a.props=n||null,a._updateId(t),a._setDisposalHandler(r=>this.disposeBloc(r)),a.isIsolated?(this.registerIsolatedBlocInstance(a),a):(this.registerBlocInstance(a),a)}static get activateBloc(){return c.instance.activateBloc}static get getBloc(){return c.instance.getBloc}static get getBlocOrThrow(){return c.instance.getBlocOrThrow}static get disposeKeepAliveBlocs(){return c.instance.disposeKeepAliveBlocs}static get disposeBlocs(){return c.instance.disposeBlocs}static get getMemoryStats(){return c.instance.getMemoryStats}static get validateConsumers(){return c.instance.validateConsumers}};i(c,"enableLog",!1),i(c,"resetInstance",()=>{g.resetInstance()});let l=c;class m{constructor(e){i(this,"bloc");i(this,"_observers",new Set);this.bloc=e}get size(){return this._observers.size}get observers(){return this._observers}subscribe(e){return l.log("BlacObservable.subscribe: Subscribing observer.",this.bloc,e),this._observers.add(e),()=>{l.log("BlacObservable.subscribe: Unsubscribing observer.",this.bloc,e),this.unsubscribe(e)}}unsubscribe(e){this._observers.delete(e),this.size===0&&l.log("BlacObservable.unsubscribe: No observers left.",this.bloc)}notify(e,t,s){this._observers.forEach(n=>{let o=!1;if(n.dependencyArray){const a=n.lastState,r=n.dependencyArray(e);if(!a)o=!0;else if(a.length!==r.length)o=!0;else for(let h=0;h<r.length;h++){const _=r[h],p=a[h]||[];if(_.length!==p.length){o=!0;break}for(let f=0;f<_.length;f++)if(!Object.is(_[f],p[f])){o=!0;break}if(o)break}n.lastState=r}else o=!0;o&&n.fn(e,t,s)})}clear(){this._observers.clear()}}function y(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(d){const e=Math.random()*16|0;return(d==="x"?e:e&3|8).toString(16)})}class B{constructor(e){i(this,"uid",y());i(this,"defaultDependencySelector");i(this,"_isolated",!1);i(this,"_observer");i(this,"_id");i(this,"_instanceRef");i(this,"_keepAlive",!1);i(this,"_createdAt",Date.now());i(this,"_disposalState","active");i(this,"_state");i(this,"_oldState");i(this,"props",null);i(this,"_batchingLock",!1);i(this,"_pendingUpdates",[]);i(this,"_consumerRefs",new Map);i(this,"_validateConsumers",()=>{const e=[];for(const[t,s]of this._consumerRefs)s.deref()===void 0&&e.push(t);for(const t of e)this._consumers.delete(t),this._consumerRefs.delete(t);this._consumers.size===0&&!this._keepAlive&&this._disposalState==="active"&&this._scheduleDisposal()});i(this,"_updateId",e=>{const t=this._id;!e||e===t||(this._id=e)});i(this,"onDispose");i(this,"_consumers",new Set);i(this,"_addConsumer",(e,t)=>{this._disposalState==="active"&&(this._consumers.has(e)||(this._consumers.add(e),t&&this._consumerRefs.set(e,new WeakRef(t))))});i(this,"_removeConsumer",e=>{this._consumers.has(e)&&(this._consumers.delete(e),this._consumerRefs.delete(e),this._consumers.size===0&&!this._keepAlive&&this._disposalState==="active"&&this._scheduleDisposal())});i(this,"_disposalHandler");i(this,"lastUpdate",Date.now());i(this,"_batchingEnabled",!1);i(this,"_pushState",(e,t,s)=>{if(e===void 0){console.warn("BlocBase._pushState: newState is undefined",this);return}if(s!==void 0&&typeof s!="object"&&typeof s!="function"){console.warn("BlocBase._pushState: Invalid action type",this,s);return}if(this._batchingEnabled){this._pendingUpdates.push({newState:e,oldState:t,action:s}),this._oldState=t,this._state=e;return}this._oldState=t,this._state=e,this._observer.notify(e,t,s),this.lastUpdate=Date.now()});i(this,"batch",e=>{if(this._batchingLock)return e();this._batchingLock=!0,this._batchingEnabled=!0,this._pendingUpdates=[];try{const t=e();if(this._pendingUpdates.length>0){const s=this._pendingUpdates[this._pendingUpdates.length-1];this._observer.notify(s.newState,s.oldState,s.action),this.lastUpdate=Date.now()}return t}finally{this._batchingEnabled=!1,this._batchingLock=!1,this._pendingUpdates=[]}});this._state=e,this._observer=new m(this),this._id=this.constructor.name;const t=this.constructor;this._keepAlive=typeof t.keepAlive=="boolean"?t.keepAlive:!1,this._isolated=typeof t.isolated=="boolean"?t.isolated:!1}get isIsolated(){return this._isolated}get isKeepAlive(){return this._keepAlive}get state(){return this._state}get _name(){return this.constructor.name}_dispose(){var e;this._disposalState==="active"&&(this._disposalState="disposing",this._consumers.clear(),this._consumerRefs.clear(),this._observer.clear(),(e=this.onDispose)==null||e.call(this),this._disposalState="disposed")}_setDisposalHandler(e){this._disposalHandler=e}_scheduleDisposal(){this._disposalState==="active"&&this._consumers.size===0&&!this._keepAlive&&(this._disposalHandler?this._disposalHandler(this):this._dispose())}}i(B,"isolated",!1),i(B,"keepAlive",!1);class w extends B{constructor(){super(...arguments);i(this,"eventHandlers",new Map);i(this,"_eventQueue",[]);i(this,"_isProcessingEvent",!1);i(this,"add",async t=>{this._eventQueue.push(t),this._isProcessingEvent||await this._processEventQueue()})}on(t,s){this.eventHandlers.has(t)&&l.warn(`[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`),this.eventHandlers.set(t,s)}async _processEventQueue(){if(!this._isProcessingEvent){this._isProcessingEvent=!0;try{for(;this._eventQueue.length>0;){const t=this._eventQueue.shift();await this._processEvent(t)}}finally{this._isProcessingEvent=!1}}}async _processEvent(t){const s=t.constructor,n=this.eventHandlers.get(s);if(n){const o=a=>{const r=this.state;this._pushState(a,r,t)};try{await n(t,o)}catch(a){const r=t.constructor.name||"UnnamedConstructor",h={blocName:this._name,blocId:String(this._id),eventType:r,currentState:this.state,action:t,timestamp:new Date().toISOString()};if(l.error(`[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${r}':`,a,"Context:",h),a instanceof Error&&a.name==="CriticalError")throw a}}else{const o=t.constructor.name||"UnnamedConstructor";l.warn(`[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${o}'.`,"Registered handlers:",Array.from(this.eventHandlers.keys()).map(a=>a.name),"Action was:",t)}}}class S extends B{emit(e){if(Object.is(e,this.state))return;const t=this.state,s=e;this._pushState(s,t)}patch(e,t=!1){if(typeof this.state!="object"||this.state===null){l.warn("Cubit.patch: was called on a cubit where the state is not an object. This is a no-op.");return}let s=!1;if(t)s=!0;else for(const n in e)if(Object.prototype.hasOwnProperty.call(e,n)){const a=this.state[n];if(!Object.is(e[n],a)){s=!0;break}}s&&this.emit({...this.state,...e})}}class b{static setUp(){this.originalInstance=l.instance,l.resetInstance(),l.enableLog=!1}static tearDown(){l.resetInstance()}static createBloc(e,...t){const s=new e(...t);return l.activateBloc(s),s}static async waitForState(e,t,s=5e3){return new Promise((n,o)=>{const a=setTimeout(()=>{o(new Error(`Timeout waiting for state matching predicate after ${s}ms`))},s),r=e._observer.subscribe({id:`test-waiter-${crypto.randomUUID()}`,fn:h=>{t(h)&&(clearTimeout(a),r(),n(h))}});t(e.state)&&(clearTimeout(a),r(),n(e.state))})}static async expectStates(e,t,s=5e3){const n=[];return new Promise((o,a)=>{const r=setTimeout(()=>{a(new Error(`Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(n)}`))},s),h=e._observer.subscribe({id:`test-expecter-${crypto.randomUUID()}`,fn:_=>{if(n.push(_),n.length===t.length){clearTimeout(r),h();for(let p=0;p<t.length;p++){const f=t[p],I=n[p];if(JSON.stringify(f)!==JSON.stringify(I)){a(new Error(`State mismatch at index ${p}. Expected: ${JSON.stringify(f)}, Received: ${JSON.stringify(I)}`));return}}o()}}})})}}i(b,"originalInstance");class $ extends w{constructor(t){super(t);i(this,"mockHandlers",new Map)}mockEventHandler(t,s){this.on(t,s)}getHandlerCount(){return this.eventHandlers.size}hasHandler(t){return this.eventHandlers.has(t)}}class A extends S{constructor(t){super(t);i(this,"stateHistory",[]);this.stateHistory.push(t)}emit(t){this.stateHistory.push(t),super.emit(t)}getStateHistory(){return[...this.stateHistory]}clearStateHistory(){this.stateHistory=[this.state]}}class E{constructor(){i(this,"initialStats");this.initialStats=l.getMemoryStats()}checkForLeaks(){const e=l.getMemoryStats(),t=e.registeredBlocs>this.initialStats.registeredBlocs||e.isolatedBlocs>this.initialStats.isolatedBlocs||e.keepAliveBlocs>this.initialStats.keepAliveBlocs,s=`
|
|
1
|
+
"use strict";var U=Object.defineProperty;var H=(u,e,t)=>e in u?U(u,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):u[e]=t;var n=(u,e,t)=>H(u,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class R{constructor(e){n(this,"bloc");n(this,"_observers",new Set);this.bloc=e}get size(){return this._observers.size}get observers(){return this._observers}subscribe(e){const t=this.bloc._disposalState;return t===_.DISPOSED||t===_.DISPOSING?(d.log("BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.",this.bloc,e),()=>{}):(d.log("BlacObservable.subscribe: Subscribing observer.",this.bloc,e),this._observers.add(e),t===_.DISPOSAL_REQUESTED&&(d.log("BlacObservable.subscribe: Cancelling disposal due to new subscription.",this.bloc),this.bloc._atomicStateTransition(_.DISPOSAL_REQUESTED,_.ACTIVE)),()=>{d.log("BlacObservable.subscribe: Unsubscribing observer.",this.bloc,e),this.unsubscribe(e)})}unsubscribe(e){this._observers.delete(e),this.size===0&&(d.log("BlacObservable.unsubscribe: No observers left.",this.bloc),this.bloc._consumers.size===0&&!this.bloc._keepAlive&&this.bloc._disposalState===_.ACTIVE&&(d.log(`[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`),this.bloc._scheduleDisposal()))}notify(e,t,s){this._observers.forEach(i=>{let r=!1;if(i.dependencyArray){const a=i.lastState,o=i.dependencyArray(e,t,this.bloc);if(!a)r=!0;else if(a.length!==o.length)r=!0;else for(let l=0;l<o.length;l++)if(!Object.is(a[l],o[l])){r=!0;break}i.lastState=o}else r=!0;r&&i.fn(e,t,s)})}clear(){this._observers.clear()}}function C(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(u){const e=Math.random()*16|0;return(u==="x"?e:e&3|8).toString(16)})}var _=(u=>(u.ACTIVE="active",u.DISPOSAL_REQUESTED="disposal_requested",u.DISPOSING="disposing",u.DISPOSED="disposed",u))(_||{});class S{constructor(e){n(this,"uid",C());n(this,"defaultDependencySelector");n(this,"_isolated",!1);n(this,"_observer");n(this,"_id");n(this,"_instanceRef");n(this,"_keepAlive",!1);n(this,"_createdAt",Date.now());n(this,"_disposalState","active");n(this,"_disposalRequestTime",0);n(this,"_state");n(this,"_oldState");n(this,"props",null);n(this,"_batchingLock",!1);n(this,"_pendingUpdates",[]);n(this,"_consumerRefs",new Map);n(this,"_validateConsumers",()=>{const e=[];for(const[t,s]of this._consumerRefs)s.deref()===void 0&&e.push(t);for(const t of e)this._consumers.delete(t),this._consumerRefs.delete(t);this._consumers.size===0&&!this._keepAlive&&this._disposalState==="active"&&this._scheduleDisposal()});n(this,"_updateId",e=>{const t=this._id;!e||e===t||(this._id=e)});n(this,"onDispose");n(this,"_consumers",new Set);n(this,"_addConsumer",(e,t)=>{var s;return this._disposalState!=="active"?!1:(this._consumers.has(e)||(this._consumers.add(e),t&&this._consumerRefs.set(e,new WeakRef(t)),(s=globalThis.Blac)==null||s.log(`[${this._name}:${this._id}] Consumer added. Total consumers: ${this._consumers.size}`)),!0)});n(this,"_removeConsumer",e=>{var t,s;this._consumers.has(e)&&(this._consumers.delete(e),this._consumerRefs.delete(e),(t=globalThis.Blac)==null||t.log(`[${this._name}:${this._id}] Consumer removed. Remaining consumers: ${this._consumers.size}, keepAlive: ${this._keepAlive}`),this._consumers.size===0&&!this._keepAlive&&this._disposalState==="active"&&((s=globalThis.Blac)==null||s.log(`[${this._name}:${this._id}] No consumers left and not keep-alive. Scheduling disposal.`),this._scheduleDisposal()))});n(this,"_disposalHandler");n(this,"lastUpdate",Date.now());n(this,"_batchingEnabled",!1);n(this,"_pushState",(e,t,s)=>{if(e!==void 0&&!(s!==void 0&&typeof s!="object"&&typeof s!="function")){if(this._batchingEnabled){this._pendingUpdates.push({newState:e,oldState:t,action:s}),this._oldState=t,this._state=e;return}this._oldState=t,this._state=e,this._observer.notify(e,t,s),this.lastUpdate=Date.now()}});n(this,"batch",e=>{if(this._batchingLock)return e();this._batchingLock=!0,this._batchingEnabled=!0,this._pendingUpdates=[];try{const t=e();if(this._pendingUpdates.length>0){const s=this._pendingUpdates[this._pendingUpdates.length-1];this._observer.notify(s.newState,s.oldState,s.action),this.lastUpdate=Date.now()}return t}finally{this._batchingEnabled=!1,this._batchingLock=!1,this._pendingUpdates=[]}});this._state=e,this._observer=new R(this),this._id=this.constructor.name;const t=this.constructor;this._keepAlive=typeof t.keepAlive=="boolean"?t.keepAlive:!1,this._isolated=typeof t.isolated=="boolean"?t.isolated:!1}get isIsolated(){return this._isolated}get isKeepAlive(){return this._keepAlive}get state(){return this._disposalState==="disposed"?this._state:this._state}get isDisposed(){return this._disposalState==="disposed"}get _name(){return this.constructor.name}_atomicStateTransition(e,t){var s,i,r,a;if(this._disposalState===e){const o=this._disposalState;return this._disposalState=t,(s=globalThis.Blac)!=null&&s.enableLog&&((i=globalThis.Blac)==null||i.log(`[${this._name}:${this._id}] State transition: ${o} -> ${t} (SUCCESS)`)),{success:!0,currentState:t,previousState:o}}return(r=globalThis.Blac)!=null&&r.enableLog&&((a=globalThis.Blac)==null||a.log(`[${this._name}:${this._id}] State transition failed: expected ${e}, current ${this._disposalState}`)),{success:!1,currentState:this._disposalState,previousState:e}}_dispose(){var t;let e=this._atomicStateTransition("active","disposing");if(e.success||(e=this._atomicStateTransition("disposal_requested","disposing")),!e.success)return!1;try{return this._consumers.clear(),this._consumerRefs.clear(),this._observer.clear(),(t=this.onDispose)==null||t.call(this),this._atomicStateTransition("disposing","disposed").success}catch(s){throw this._disposalState="active",s}}_setDisposalHandler(e){this._disposalHandler=e}_scheduleDisposal(){if(!this._atomicStateTransition("active","disposal_requested").success)return;if(!(this._consumers.size===0&&!this._keepAlive)){this._atomicStateTransition("disposal_requested","active");return}this._disposalRequestTime=Date.now(),queueMicrotask(()=>{this._consumers.size===0&&!this._keepAlive&&this._observer.size===0&&this._disposalState==="disposal_requested"?this._disposalHandler?this._disposalHandler(this):this._dispose():this._atomicStateTransition("disposal_requested","active")})}}n(S,"isolated",!1),n(S,"keepAlive",!1);const I=class I{getInstance(){return I._instance||(I._instance=new d({__unsafe_ignore_singleton:!0})),I._instance}setInstance(e){I._instance=e}resetInstance(){const e=I._instance;if(I._instance=new d({__unsafe_ignore_singleton:!0}),e)for(const t of e.keepAliveBlocs)I._instance.keepAliveBlocs.add(t),I._instance.uidRegistry.set(t.uid,t)}};n(I,"_instance");let T=I,b=new T;function N(u){b=u}const c=class c{constructor(e={}){n(this,"createdAt",Date.now());n(this,"blocInstanceMap",new Map);n(this,"isolatedBlocMap",new Map);n(this,"isolatedBlocIndex",new Map);n(this,"uidRegistry",new Map);n(this,"keepAliveBlocs",new Set);n(this,"postChangesToDocument",!1);n(this,"log",(...e)=>{c.logSpy&&c.logSpy(e),c.enableLog&&c.logLevel,c.enableLog&&c.logLevel});n(this,"warn",(e,...t)=>{c.enableLog});n(this,"error",(e,...t)=>{c.enableLog});n(this,"resetInstance",()=>{this.log("Reset Blac instance");const e=new Map(this.blocInstanceMap),t=new Map(this.isolatedBlocMap);e.forEach(s=>{!s._keepAlive&&s._disposalState===_.ACTIVE&&this.disposeBloc(s)}),t.forEach(s=>{s.forEach(i=>{!i._keepAlive&&i._disposalState===_.ACTIVE&&this.disposeBloc(i)})}),this.blocInstanceMap.clear(),this.isolatedBlocMap.clear(),this.isolatedBlocIndex.clear(),b.resetInstance()});n(this,"disposeBloc",e=>{const t=e._disposalState;if(![_.ACTIVE,_.DISPOSAL_REQUESTED].includes(t)){this.log(`[${e._name}:${String(e._id)}] disposeBloc called on bloc in invalid state: ${t}`);return}const i=e.constructor,r=this.createBlocInstanceMapKey(e._name,e._id);this.log(`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(i.isolated)}`),e._dispose(),i.isolated?(this.unregisterIsolatedBlocInstance(e),this.blocInstanceMap.delete(r)):this.unregisterBlocInstance(e),this.log("dispatched bloc",e)});n(this,"activateBloc",e=>{if(e._disposalState!==_.ACTIVE){this.log(`[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`);return}const t=e.constructor;(e.isIsolated?this.findIsolatedBlocInstance(t,e._id):this.findRegisteredBlocInstance(t,e._id))||(this.log(`[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`),e.isIsolated?this.registerIsolatedBlocInstance(e):this.registerBlocInstance(e))});n(this,"getBloc",(e,t={})=>{const{id:s,forceNewInstance:i}=t,r=e,a=s??e.name;if(this.log(`[${e.name}:${String(a)}] (getBloc) Called:`,{options:t,base:r}),!i)if(r.isolated){const l=this.findIsolatedBlocInstance(e,t.instanceRef??a);if(l)return l;if(t.throwIfNotFound)throw new Error(`Isolated bloc ${e.name} not found`)}else{const l=this.findRegisteredBlocInstance(e,a);if(l)return l;if(t.throwIfNotFound)throw new Error(`Registered bloc ${e.name} not found`)}const o=this.createNewBlocInstance(e,a,t);if(this.log(`[${e.name}:${String(a)}] (getBloc) No existing instance found. Creating new one.`,t,o),!o)throw new Error(`[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`);return o});n(this,"getBlocOrThrow",(e,t={})=>{const s=e.isolated,i=t.id||e.name,r=s?this.findIsolatedBlocInstance(e,i):this.findRegisteredBlocInstance(e,i);if(r)return r;throw new Error(`Bloc ${e.name} not found`)});n(this,"getAllBlocs",(e,t={})=>{const s=[];if(this.blocInstanceMap.forEach(i=>{i.constructor===e&&s.push(i)}),t.searchIsolated!==!1){const i=this.isolatedBlocMap.get(e);i&&s.push(...i.map(r=>r))}return s});n(this,"disposeKeepAliveBlocs",e=>{const t=[];for(const s of this.keepAliveBlocs)(!e||s.constructor===e)&&t.push(s);t.forEach(s=>s._dispose())});n(this,"disposeBlocs",e=>{const t=[];for(const s of this.blocInstanceMap.values())e(s)&&t.push(s);for(const s of this.isolatedBlocMap.values())for(const i of s)e(i)&&t.push(i);t.forEach(s=>s._dispose())});n(this,"getMemoryStats",()=>({totalBlocs:this.uidRegistry.size,registeredBlocs:this.blocInstanceMap.size,isolatedBlocs:Array.from(this.isolatedBlocMap.values()).reduce((e,t)=>e+t.length,0),keepAliveBlocs:this.keepAliveBlocs.size,isolatedBlocTypes:this.isolatedBlocMap.size}));n(this,"validateConsumers",()=>{for(const e of this.uidRegistry.values())e._validateConsumers(),e._consumers.size===0&&!e._keepAlive&&e._disposalState===_.ACTIVE&&setTimeout(()=>{e._consumers.size===0&&!e._keepAlive&&e._disposalState===_.ACTIVE&&this.disposeBloc(e)},1e3)});const{__unsafe_ignore_singleton:t=!1}=e;if(!t)return c.instance;b.setInstance(this)}static get instance(){return b.getInstance()}static get getAllBlocs(){return c.instance.getAllBlocs}static get log(){return c.instance.log}static getInstance(){return b.getInstance()}static get warn(){return c.instance.warn}static get error(){return c.instance.error}static get disposeBloc(){return c.instance.disposeBloc}createBlocInstanceMapKey(e,t){return`${e}:${String(t)}`}unregisterBlocInstance(e){const t=this.createBlocInstanceMapKey(e._name,e._id);this.blocInstanceMap.delete(t),this.uidRegistry.delete(e.uid),this.keepAliveBlocs.delete(e)}registerBlocInstance(e){const t=this.createBlocInstanceMapKey(e._name,e._id);this.blocInstanceMap.set(t,e),this.uidRegistry.set(e.uid,e),e._keepAlive&&this.keepAliveBlocs.add(e)}findRegisteredBlocInstance(e,t){if(e.isolated)return;const i=this.createBlocInstanceMapKey(e.name,t);return this.blocInstanceMap.get(i)}registerIsolatedBlocInstance(e){const t=e.constructor,s=this.isolatedBlocMap.get(t);s?s.push(e):this.isolatedBlocMap.set(t,[e]),this.isolatedBlocIndex.set(e.uid,e),this.uidRegistry.set(e.uid,e),e._keepAlive&&this.keepAliveBlocs.add(e)}unregisterIsolatedBlocInstance(e){const t=e.constructor,s=this.isolatedBlocMap.get(t);let i=!1;if(s){const a=s.findIndex(o=>o.uid===e.uid);a!==-1&&(s.splice(a,1),i=!0),s.length===0&&this.isolatedBlocMap.delete(t)}const r=this.isolatedBlocIndex.delete(e.uid);this.uidRegistry.delete(e.uid),this.keepAliveBlocs.delete(e),i!==r&&this.warn(`[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${i}, Index removal: ${r}`)}findIsolatedBlocInstance(e,t){if(!e.isolated)return;const i=this.isolatedBlocMap.get(e);return i?i.find(a=>a._id===t):void 0}findIsolatedBlocInstanceByUid(e){return this.isolatedBlocIndex.get(e)}createNewBlocInstance(e,t,s={}){const{props:i,instanceRef:r}=s,a=new e(i);return a._instanceRef=r,a.props=i||null,a._updateId(t),a._setDisposalHandler(o=>this.disposeBloc(o)),a.isIsolated?(this.registerIsolatedBlocInstance(a),a):(this.registerBlocInstance(a),a)}static get activateBloc(){return c.instance.activateBloc}static get getBloc(){return c.instance.getBloc}static get getBlocOrThrow(){return c.instance.getBlocOrThrow}static get disposeKeepAliveBlocs(){return c.instance.disposeKeepAliveBlocs}static get disposeBlocs(){return c.instance.disposeBlocs}static get getMemoryStats(){return c.instance.getMemoryStats}static get validateConsumers(){return c.instance.validateConsumers}};n(c,"enableLog",!1),n(c,"logLevel","warn"),n(c,"logSpy",null),n(c,"resetInstance",()=>{b.resetInstance()});let d=c;class $ extends S{constructor(){super(...arguments);n(this,"eventHandlers",new Map);n(this,"_eventQueue",[]);n(this,"_isProcessingEvent",!1);n(this,"add",async t=>{this._eventQueue.push(t),this._isProcessingEvent||await this._processEventQueue()})}on(t,s){this.eventHandlers.has(t)&&d.warn(`[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`),this.eventHandlers.set(t,s)}async _processEventQueue(){if(!this._isProcessingEvent){this._isProcessingEvent=!0;try{for(;this._eventQueue.length>0;){const t=this._eventQueue.shift();await this._processEvent(t)}}finally{this._isProcessingEvent=!1}}}async _processEvent(t){const s=t.constructor,i=this.eventHandlers.get(s);if(i){const r=a=>{const o=this.state;this._pushState(a,o,t)};try{await i(t,r)}catch(a){const o=t.constructor.name||"UnnamedConstructor",l={blocName:this._name,blocId:String(this._id),eventType:o,currentState:this.state,action:t,timestamp:new Date().toISOString()};if(d.error(`[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${o}':`,a,"Context:",l),a instanceof Error&&a.name==="CriticalError")throw a}}else{const r=t.constructor.name||"UnnamedConstructor";d.warn(`[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${r}'.`,"Registered handlers:",Array.from(this.eventHandlers.keys()).map(a=>a.name),"Action was:",t)}}}class P extends S{emit(e){if(Object.is(e,this.state))return;const t=this.state,s=e;this._pushState(s,t)}patch(e,t=!1){if(typeof this.state!="object"||this.state===null){d.warn("Cubit.patch: was called on a cubit where the state is not an object. This is a no-op.");return}let s=!1;if(t)s=!0;else for(const i in e)if(Object.prototype.hasOwnProperty.call(e,i)){const a=this.state[i];if(!Object.is(e[i],a)){s=!0;break}}s&&this.emit({...this.state,...e})}}class E{static setUp(){this.originalInstance=d.instance,d.resetInstance(),d.enableLog=!1}static tearDown(){d.resetInstance()}static createBloc(e,...t){const s=new e(...t);return d.activateBloc(s),s}static async waitForState(e,t,s=5e3){return new Promise((i,r)=>{const a=setTimeout(()=>{r(new Error(`Timeout waiting for state matching predicate after ${s}ms`))},s),o=e._observer.subscribe({id:`test-waiter-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,fn:l=>{t(l)&&(clearTimeout(a),o(),i(l))}});t(e.state)&&(clearTimeout(a),o(),i(e.state))})}static async expectStates(e,t,s=5e3){const i=[];return new Promise((r,a)=>{const o=setTimeout(()=>{a(new Error(`Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(i)}`))},s),l=e._observer.subscribe({id:`test-expecter-${crypto.randomUUID()}`,fn:p=>{if(i.push(p),i.length===t.length){clearTimeout(o),l();for(let h=0;h<t.length;h++){const m=t[h],v=i[h];if(JSON.stringify(m)!==JSON.stringify(v)){a(new Error(`State mismatch at index ${h}. Expected: ${JSON.stringify(m)}, Received: ${JSON.stringify(v)}`));return}}r()}}})})}}n(E,"originalInstance");class L extends ${constructor(t){super(t);n(this,"mockHandlers",new Map)}mockEventHandler(t,s){this.on(t,s)}getHandlerCount(){return this.eventHandlers.size}hasHandler(t){return this.eventHandlers.has(t)}}class z extends P{constructor(t){super(t);n(this,"stateHistory",[]);this.stateHistory.push(t)}emit(t){this.stateHistory.push(t),super.emit(t)}getStateHistory(){return[...this.stateHistory]}clearStateHistory(){this.stateHistory=[this.state]}}class j{constructor(){n(this,"initialStats");this.initialStats=d.getMemoryStats()}checkForLeaks(){const e=d.getMemoryStats(),t=e.registeredBlocs>this.initialStats.registeredBlocs||e.isolatedBlocs>this.initialStats.isolatedBlocs||e.keepAliveBlocs>this.initialStats.keepAliveBlocs,s=`
|
|
2
2
|
Memory Leak Detection Report:
|
|
3
3
|
- Initial registered blocs: ${this.initialStats.registeredBlocs}
|
|
4
4
|
- Current registered blocs: ${e.registeredBlocs}
|
|
@@ -7,5 +7,5 @@ Memory Leak Detection Report:
|
|
|
7
7
|
- Initial keep-alive blocs: ${this.initialStats.keepAliveBlocs}
|
|
8
8
|
- Current keep-alive blocs: ${e.keepAliveBlocs}
|
|
9
9
|
- Potential leaks detected: ${t?"YES":"NO"}
|
|
10
|
-
`.trim();return{hasLeaks:t,report:s,stats:e}}}exports.Blac=
|
|
10
|
+
`.trim();return{hasLeaks:t,report:s,stats:e}}}class O{constructor(){n(this,"consumers",new WeakMap);n(this,"registrationCount",0);n(this,"activeConsumers",0)}register(e,t){this.registrationCount++,this.consumers.get(e)||this.activeConsumers++,this.consumers.set(e,{id:t,lastNotified:Date.now(),hasRendered:!1,stateAccesses:new Set,classAccesses:new Set,stateValues:new Map,classValues:new Map,accessCount:0,lastAccessTime:0,firstAccessTime:0})}unregister(e){e&&this.consumers.get(e)&&(this.consumers.delete(e),this.activeConsumers=Math.max(0,this.activeConsumers-1))}trackAccess(e,t,s,i){const r=this.consumers.get(e);if(!r)return;const a=Date.now();r.firstAccessTime||(r.firstAccessTime=a),r.accessCount++,r.lastAccessTime=a,t==="state"?(r.stateAccesses.add(s),i!==void 0&&r.stateValues.set(s,{value:i,lastAccessTime:a})):(r.classAccesses.add(s),i!==void 0&&r.classValues.set(s,{value:i,lastAccessTime:a}))}resetTracking(e){const t=this.consumers.get(e);t&&(t.stateAccesses.clear(),t.classAccesses.clear(),t.stateValues.clear(),t.classValues.clear(),t.accessCount=0,t.firstAccessTime=0)}getDependencies(e){const t=this.consumers.get(e);return t?{statePaths:Array.from(t.stateAccesses),classPaths:Array.from(t.classAccesses)}:null}hasValuesChanged(e,t,s){const i=this.consumers.get(e);if(!i)return!0;let r=!1;const a=Date.now();if(i.stateValues.size===0&&i.classValues.size===0&&(i.stateAccesses.size>0||i.classAccesses.size>0))return!0;for(const[o,l]of i.stateValues)try{const p=this.getValueAtPath(t,o);p!==l.value&&(i.stateValues.set(o,{value:p,lastAccessTime:a}),r=!0)}catch{r=!0}for(const[o,l]of i.classValues)try{const p=this.getValueAtPath(s,o);p!==l.value&&(i.classValues.set(o,{value:p,lastAccessTime:a}),r=!0)}catch{r=!0}return r}shouldNotifyConsumer(e,t){const s=this.consumers.get(e);if(!s)return!1;for(const i of t){if(s.stateAccesses.has(i)||s.classAccesses.has(i))return!0;for(const r of s.stateAccesses)if(i.startsWith(r+".")||r.startsWith(i+"."))return!0}return!1}updateLastNotified(e){const t=this.consumers.get(e);t&&(t.lastNotified=Date.now())}getConsumerInfo(e){return this.consumers.get(e)}setHasRendered(e,t){const s=this.consumers.get(e);s&&(s.hasRendered=t)}hasConsumer(e){return this.consumers.has(e)}getStats(){return{totalRegistrations:this.registrationCount,activeConsumers:this.activeConsumers}}getValueAtPath(e,t){const s=t.split(".");let i=e;for(const r of s){if(i==null)return;i=i[r]}return i}}const w=new WeakMap;let f={stateProxiesCreated:0,classProxiesCreated:0,cacheHits:0,cacheMisses:0,propertyAccesses:0,nestedProxiesCreated:0,totalProxiesCreated:0,createdAt:Date.now()};class y{static createStateProxy(e){const{target:t,consumerRef:s,consumerTracker:i,path:r=""}=e;if(!s||!i||typeof t!="object"||t===null)return t;let a=w.get(t);a||(a=new WeakMap,w.set(t,a));const o=a.get(s);if(o)return f.cacheHits++,o;f.cacheMisses++;const l={get(h,m){if(typeof m=="symbol"||m==="constructor")return Reflect.get(h,m);const v=r?`${r}.${m}`:m;f.propertyAccesses++;const g=Reflect.get(h,m),k=g&&typeof g==="object"&&g!==null?void 0:g;if(i.trackAccess(s,"state",v,k),g&&typeof g=="object"&&g!==null){const B=Object.getPrototypeOf(g)===Object.prototype,M=Array.isArray(g);if(B||M)return f.nestedProxiesCreated++,y.createStateProxy({target:g,consumerRef:s,consumerTracker:i,path:v})}return g},has(h,m){return m in h},ownKeys(h){return Reflect.ownKeys(h)},getOwnPropertyDescriptor(h,m){return Reflect.getOwnPropertyDescriptor(h,m)},set(){return!1},deleteProperty(){return!1}},p=new Proxy(t,l);return a.set(s,p),f.stateProxiesCreated++,f.totalProxiesCreated++,p}static createClassProxy(e){const{target:t,consumerRef:s,consumerTracker:i}=e;if(!s||!i)return t;let r=w.get(t);r||(r=new WeakMap,w.set(t,r));const a=r.get(s);if(a)return f.cacheHits++,a;f.cacheMisses++;const o={get(p,h){const m=Reflect.get(p,h);let v=!1,g=p;const A=new WeakSet,D=10;let k=0;for(;g&&!v&&k<D&&!A.has(g);){A.add(g);try{const x=Object.getOwnPropertyDescriptor(g,h);if(x&&x.get){v=!0;break}g=Object.getPrototypeOf(g),k++}catch{break}}if(!v)return m;f.propertyAccesses++;const B=m,V=B!==null&&typeof B!="object"?B:void 0;return i.trackAccess(s,"class",String(h),V),m},has(p,h){return h in p},ownKeys(p){return Reflect.ownKeys(p)},getOwnPropertyDescriptor(p,h){return Reflect.getOwnPropertyDescriptor(p,h)}},l=new Proxy(t,o);return r.set(s,l),f.classProxiesCreated++,f.totalProxiesCreated++,l}static getProxyState(e){return y.createStateProxy({target:e.state,consumerRef:e.consumerRef,consumerTracker:e.consumerTracker})}static getProxyBlocInstance(e){return y.createClassProxy({target:e.blocInstance,consumerRef:e.consumerRef,consumerTracker:e.consumerTracker})}static getStats(){const e=Date.now()-f.createdAt;return{...f,totalProxies:f.stateProxiesCreated+f.classProxiesCreated,cacheEfficiency:f.cacheHits+f.cacheMisses>0?`${(f.cacheHits/(f.cacheHits+f.cacheMisses)*100).toFixed(1)}%`:"N/A",lifetime:`${e}ms`,proxiesPerSecond:e>0?(f.totalProxiesCreated/(e/1e3)).toFixed(2):"N/A"}}static resetStats(){f={stateProxiesCreated:0,classProxiesCreated:0,cacheHits:0,cacheMisses:0,propertyAccesses:0,nestedProxiesCreated:0,totalProxiesCreated:0,createdAt:Date.now()}}}class K{constructor(e,t){n(this,"id",`consumer-${C()}`);n(this,"blocConstructor");n(this,"componentRef",{current:{}});n(this,"blocInstance");n(this,"consumerTracker");n(this,"unmountTime",0);n(this,"mountTime",0);n(this,"dependencyValues");n(this,"isUsingDependencies",!1);n(this,"hasMounted",!1);n(this,"mountCount",0);n(this,"options");n(this,"createStateProxy",e=>y.createStateProxy({target:e.target,consumerRef:this.componentRef.current,consumerTracker:this}));n(this,"createClassProxy",e=>y.createClassProxy({target:e.target,consumerRef:this.componentRef.current,consumerTracker:this}));n(this,"createSubscription",e=>this.blocInstance._observer.subscribe({id:this.id,fn:(s,i)=>{var r;if(this.isUsingDependencies&&((r=this.options)!=null&&r.dependencies)){const a=this.options.dependencies(this.blocInstance);if(!this.hasDependencyValuesChanged(this.dependencyValues,a))return;this.dependencyValues=a}else{const a=this.consumerTracker.getConsumerInfo(this.componentRef.current);if(a&&a.hasRendered&&!this.consumerTracker.hasValuesChanged(this.componentRef.current,s,this.blocInstance))return}e.onChange()}}));n(this,"mount",()=>{var e,t;if(this.isUsingDependencies&&((e=this.options)!=null&&e.dependencies)&&(this.dependencyValues=this.options.dependencies(this.blocInstance)),this.mountCount++,this.blocInstance._addConsumer(this.id,this.componentRef.current),!this.hasMounted&&(this.hasMounted=!0,this.mountTime=Date.now(),(t=this.options)!=null&&t.onMount))try{this.options.onMount(this.blocInstance)}catch(s){throw s}});n(this,"unmount",()=>{var e;if(this.unmountTime=Date.now(),this.consumerTracker.unregister(this.componentRef.current),this.blocInstance._removeConsumer(this.id),(e=this.options)!=null&&e.onUnmount)try{this.options.onUnmount(this.blocInstance)}catch{}});n(this,"getProxyState",e=>this.isUsingDependencies?e:y.getProxyState({state:e,consumerRef:this.componentRef.current,consumerTracker:this}));n(this,"getProxyBlocInstance",()=>this.isUsingDependencies?this.blocInstance:y.getProxyBlocInstance({blocInstance:this.blocInstance,consumerRef:this.componentRef.current,consumerTracker:this}));this.options=t,this.blocConstructor=e.blocConstructor,this.componentRef=e.componentRef,this.isUsingDependencies=!!(t!=null&&t.dependencies),this.consumerTracker=new O,this.blocInstance=this.updateBlocInstance(),this.consumerTracker.register(e.componentRef.current,this.id),this.isUsingDependencies&&(t!=null&&t.dependencies)&&(this.dependencyValues=t.dependencies(this.blocInstance))}trackAccess(e,t,s,i){this.consumerTracker.trackAccess(e,t,s,i)}getConsumerDependencies(e){return this.consumerTracker.getDependencies(e)}shouldNotifyConsumer(e,t){const s=this.consumerTracker.getConsumerInfo(e);return!s||!s.hasRendered?!0:this.consumerTracker.shouldNotifyConsumer(e,t)}updateLastNotified(e){this.consumerTracker.updateLastNotified(e),this.consumerTracker.setHasRendered(e,!0)}resetConsumerTracking(){this.consumerTracker.resetTracking(this.componentRef.current)}updateBlocInstance(){var e,t;return this.blocInstance=d.instance.getBloc(this.blocConstructor,{props:(e=this.options)==null?void 0:e.props,id:(t=this.options)==null?void 0:t.id,instanceRef:this.id}),this.blocInstance}get calledOnMount(){return this.hasMounted}hasDependencyValuesChanged(e,t){if(!e||e.length!==t.length)return!0;for(let s=0;s<e.length;s++)if(!Object.is(e[s],t[s]))return!0;return!1}}exports.Blac=d;exports.BlacAdapter=K;exports.BlacObservable=R;exports.Bloc=$;exports.BlocBase=S;exports.BlocLifecycleState=_;exports.BlocTest=E;exports.ConsumerTracker=O;exports.Cubit=P;exports.MemoryLeakDetector=j;exports.MockBloc=L;exports.MockCubit=z;exports.ProxyFactory=y;exports.generateUUID=C;exports.setBlacInstanceManager=N;
|
|
11
11
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/Blac.ts","../src/BlacObserver.ts","../src/utils/uuid.ts","../src/BlocBase.ts","../src/Bloc.ts","../src/Cubit.ts","../src/testing.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n// TODO: Remove this eslint disable once any types are properly replaced\nimport { BlocBase, BlocInstanceId } from \"./BlocBase\";\nimport {\n BlocBaseAbstract,\n BlocConstructor,\n BlocHookDependencyArrayFn,\n BlocState,\n InferPropsFromGeneric\n} from \"./types\";\n\n/**\n * Configuration options for the Blac instance\n */\nexport interface BlacConfig {\n /** Whether to expose the Blac instance globally */\n exposeBlacInstance?: boolean;\n}\n\nexport interface GetBlocOptions<B extends BlocBase<unknown>> {\n id?: string;\n selector?: BlocHookDependencyArrayFn<BlocState<B>>;\n props?: InferPropsFromGeneric<B>;\n onMount?: (bloc: B) => void;\n instanceRef?: string;\n throwIfNotFound?: boolean;\n}\n\n/**\n * Interface for Blac instance management\n */\nexport interface BlacInstanceManager {\n getInstance(): Blac;\n setInstance(instance: Blac): void;\n resetInstance(): void;\n}\n\n/**\n * Default singleton implementation of BlacInstanceManager\n */\nclass SingletonBlacManager implements BlacInstanceManager {\n private static _instance: Blac;\n\n getInstance(): Blac {\n if (!SingletonBlacManager._instance) {\n SingletonBlacManager._instance = new Blac({ __unsafe_ignore_singleton: true });\n }\n return SingletonBlacManager._instance;\n }\n\n setInstance(instance: Blac): void {\n SingletonBlacManager._instance = instance;\n }\n\n resetInstance(): void {\n const oldInstance = SingletonBlacManager._instance;\n SingletonBlacManager._instance = new Blac({ __unsafe_ignore_singleton: true });\n \n // Transfer any keep-alive blocs to the new instance\n if (oldInstance) {\n for (const bloc of oldInstance.keepAliveBlocs) {\n SingletonBlacManager._instance.keepAliveBlocs.add(bloc);\n SingletonBlacManager._instance.uidRegistry.set(bloc.uid, bloc);\n }\n }\n }\n}\n\n/**\n * Global instance manager (can be replaced for testing or different patterns)\n */\nlet instanceManager: BlacInstanceManager = new SingletonBlacManager();\n\n/**\n * Sets a custom instance manager (useful for testing or advanced patterns)\n */\nexport function setBlacInstanceManager(manager: BlacInstanceManager): void {\n instanceManager = manager;\n}\n\n/**\n * Main Blac class that manages the state management system.\n * Can work with singleton pattern or dependency injection.\n * Handles bloc lifecycle, and instance tracking.\n * \n * Key responsibilities:\n * - Managing bloc instances (creation, disposal, lookup)\n * - Handling isolated and non-isolated blocs\n * - Providing logging and debugging capabilities\n */\nexport class Blac {\n /** @deprecated Use getInstance() instead */\n static get instance(): Blac {\n return instanceManager.getInstance();\n }\n /** Timestamp when the instance was created */\n createdAt = Date.now();\n static get getAllBlocs() {\n return Blac.instance.getAllBlocs;\n }\n /** Map storing all registered bloc instances by their class name and ID */\n blocInstanceMap: Map<string, BlocBase<unknown>> = new Map();\n /** Map storing isolated bloc instances grouped by their constructor */\n isolatedBlocMap: Map<BlocConstructor<any>, BlocBase<unknown>[]> = new Map();\n /** Map for O(1) lookup of isolated blocs by UID */\n private isolatedBlocIndex: Map<string, BlocBase<unknown>> = new Map();\n /** Map tracking UIDs to prevent memory leaks */\n uidRegistry: Map<string, BlocBase<unknown>> = new Map();\n /** Set of keep-alive blocs for controlled cleanup */\n keepAliveBlocs: Set<BlocBase<unknown>> = new Set();\n /** Flag to control whether changes should be posted to document */\n postChangesToDocument = false;\n\n /**\n * Creates a new Blac instance.\n * @param options - Configuration options including singleton control\n */\n constructor(options: { __unsafe_ignore_singleton?: boolean } = {}) {\n const { __unsafe_ignore_singleton = false } = options;\n if (!__unsafe_ignore_singleton) {\n return Blac.instance;\n }\n instanceManager.setInstance(this);\n }\n\n /** Flag to enable/disable logging */\n static enableLog = false;\n\n /**\n * Logs messages to console when logging is enabled\n * @param args - Arguments to log\n */\n log = (...args: unknown[]) => {\n if (Blac.enableLog) console.warn(`☢️ [Blac ${this.createdAt.toString()}]`, ...args);\n };\n static get log() { return Blac.instance.log; }\n\n /**\n * Gets the current Blac instance\n * @returns The Blac instance\n */\n static getInstance(): Blac {\n return instanceManager.getInstance();\n }\n\n\n /**\n * Logs a warning message\n * @param message - Warning message\n * @param args - Additional arguments\n */\n warn = (message: string, ...args: unknown[]) => {\n if (Blac.enableLog) {\n console.warn(`🚨 [Blac ${String(Blac.instance.createdAt)}]`, message, ...args);\n }\n };\n static get warn() { return Blac.instance.warn; }\n /**\n * Logs an error message\n * @param message - Error message\n * @param args - Additional arguments\n */\n error = (message: string, ...args: unknown[]) => {\n if (Blac.enableLog) {\n console.error(`🚨 [Blac ${String(Blac.instance.createdAt)}]`, message, ...args);\n }\n };\n static get error() { return Blac.instance.error; }\n\n /**\n * Resets the Blac instance to a new one, disposing non-keepAlive blocs\n * from the old instance.\n */\n resetInstance = (): void => {\n this.log(\"Reset Blac instance\");\n\n // Create snapshots to avoid concurrent modification issues\n const oldBlocInstanceMap = new Map(this.blocInstanceMap);\n const oldIsolatedBlocMap = new Map(this.isolatedBlocMap);\n\n // Dispose non-keepAlive blocs from the current instance\n // Use disposeBloc method to ensure proper cleanup\n oldBlocInstanceMap.forEach((bloc) => {\n if (!bloc._keepAlive && (bloc as any)._disposalState === 'active') {\n this.disposeBloc(bloc);\n }\n });\n\n oldIsolatedBlocMap.forEach((blocArray) => {\n blocArray.forEach((bloc) => {\n if (!bloc._keepAlive && (bloc as any)._disposalState === 'active') {\n this.disposeBloc(bloc);\n }\n });\n });\n\n // Clear registries (keep-alive blocs will be re-added by instance manager)\n this.blocInstanceMap.clear();\n this.isolatedBlocMap.clear();\n this.isolatedBlocIndex.clear();\n\n // Use instance manager to reset\n instanceManager.resetInstance();\n }\n static resetInstance = (): void => {\n instanceManager.resetInstance();\n };\n\n /**\n * Disposes of a bloc instance by removing it from the appropriate registry\n * @param bloc - The bloc instance to dispose\n */\n disposeBloc = (bloc: BlocBase<unknown>): void => {\n // Check if bloc is already disposed to prevent double disposal\n if ((bloc as any)._disposalState !== 'active') {\n this.log(`[${bloc._name}:${String(bloc._id)}] disposeBloc called on already disposed bloc`);\n return;\n }\n\n const base = bloc.constructor as unknown as BlocBaseAbstract;\n const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);\n this.log(`[${bloc._name}:${String(bloc._id)}] disposeBloc called. Isolated: ${String(base.isolated)}`);\n\n // First dispose the bloc to prevent further operations\n bloc._dispose();\n \n // Then clean up from registries\n if (base.isolated) {\n this.unregisterIsolatedBlocInstance(bloc);\n this.blocInstanceMap.delete(key);\n } else {\n this.unregisterBlocInstance(bloc);\n }\n \n this.log('dispatched bloc', bloc)\n };\n static get disposeBloc() { return Blac.instance.disposeBloc; }\n\n /**\n * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID\n * @param blocClassName - The name of the bloc class\n * @param id - The instance ID\n * @returns A unique key string in the format \"className:id\"\n */\n createBlocInstanceMapKey(blocClassName: string, id: BlocInstanceId): string {\n return `${blocClassName}:${String(id)}`;\n }\n\n /**\n * Unregister a bloc instance from the main registry\n * @param bloc - The bloc instance to unregister\n */\n unregisterBlocInstance(bloc: BlocBase<unknown>): void {\n const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);\n this.blocInstanceMap.delete(key);\n \n // Clean up UID tracking\n this.uidRegistry.delete(bloc.uid);\n \n // Remove from keep-alive set\n this.keepAliveBlocs.delete(bloc);\n }\n\n /**\n * Registers a bloc instance in the main registry\n * @param bloc - The bloc instance to register\n */\n registerBlocInstance(bloc: BlocBase<unknown>): void {\n const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);\n this.blocInstanceMap.set(key, bloc);\n \n // Track UID for cleanup\n this.uidRegistry.set(bloc.uid, bloc);\n \n // Track keep-alive blocs\n if (bloc._keepAlive) {\n this.keepAliveBlocs.add(bloc);\n }\n }\n\n /**\n * Finds a registered bloc instance by its class and ID\n * @param blocClass - The bloc class to search for\n * @param id - The instance ID\n * @returns The found bloc instance or undefined if not found\n */\n findRegisteredBlocInstance<B extends BlocConstructor<any>>(\n blocClass: B,\n id: BlocInstanceId,\n ): InstanceType<B> | undefined {\n const base = blocClass as unknown as BlocBaseAbstract;\n if (base.isolated) return undefined;\n\n const key = this.createBlocInstanceMapKey(blocClass.name, id);\n const found = this.blocInstanceMap.get(key) as InstanceType<B> | undefined;\n return found\n }\n\n /**\n * Registers an isolated bloc instance in the isolated registry\n * @param bloc - The isolated bloc instance to register\n */\n registerIsolatedBlocInstance(bloc: BlocBase<unknown>): void {\n const blocClass = bloc.constructor as BlocConstructor<any>;\n const blocs = this.isolatedBlocMap.get(blocClass);\n if (blocs) {\n blocs.push(bloc);\n } else {\n this.isolatedBlocMap.set(blocClass, [bloc]);\n }\n \n // Add to isolated index for O(1) lookups\n this.isolatedBlocIndex.set(bloc.uid, bloc);\n \n // Track UID for cleanup\n this.uidRegistry.set(bloc.uid, bloc);\n \n // Track keep-alive blocs\n if (bloc._keepAlive) {\n this.keepAliveBlocs.add(bloc);\n }\n }\n\n /**\n * Unregister an isolated bloc instance from the isolated registry\n * @param bloc - The isolated bloc instance to unregister\n */\n unregisterIsolatedBlocInstance(bloc: BlocBase<unknown>): void {\n const blocClass = bloc.constructor;\n const blocs = this.isolatedBlocMap.get(blocClass as BlocConstructor<any>);\n \n // Ensure both data structures are synchronized\n let wasRemoved = false;\n \n if (blocs) {\n const index = blocs.findIndex((b) => b.uid === bloc.uid);\n if (index !== -1) {\n blocs.splice(index, 1);\n wasRemoved = true;\n }\n\n if (blocs.length === 0) {\n this.isolatedBlocMap.delete(blocClass as BlocConstructor<any>);\n }\n }\n \n // Always try to remove from isolated index, even if not found in map\n const wasInIndex = this.isolatedBlocIndex.delete(bloc.uid);\n \n // Clean up UID tracking\n this.uidRegistry.delete(bloc.uid);\n \n // Remove from keep-alive set\n this.keepAliveBlocs.delete(bloc);\n \n // Log inconsistency for debugging\n if (wasRemoved !== wasInIndex) {\n this.warn(\n `[Blac] Inconsistent state detected during isolated bloc cleanup for ${bloc._name}:${bloc.uid}. ` +\n `Map removal: ${wasRemoved}, Index removal: ${wasInIndex}`\n );\n }\n }\n\n /**\n * Finds an isolated bloc instance by its class and ID (O(n) lookup)\n */\n findIsolatedBlocInstance<B extends BlocConstructor<any>>(\n blocClass: B,\n id: BlocInstanceId,\n ): InstanceType<B> | undefined {\n const base = blocClass as unknown as BlocBaseAbstract;\n if (!base.isolated) return undefined;\n\n const blocs = this.isolatedBlocMap.get(blocClass);\n if (!blocs) {\n return undefined;\n }\n // Find the specific bloc by ID within the isolated array\n const found = blocs.find((b) => b._id === id) as InstanceType<B> | undefined;\n return found;\n }\n\n /**\n * Finds an isolated bloc instance by UID (O(1) lookup)\n */\n findIsolatedBlocInstanceByUid<B extends BlocBase<unknown>>(\n uid: string\n ): B | undefined {\n return this.isolatedBlocIndex.get(uid) as B | undefined;\n }\n\n /**\n * Creates a new bloc instance and registers it in the appropriate registry\n * @param blocClass - The bloc class to instantiate\n * @param id - The instance ID\n * @param props - Properties to pass to the bloc constructor\n * @param instanceRef - Optional reference string for the instance\n * @returns The newly created bloc instance\n */\n createNewBlocInstance<B extends BlocConstructor<BlocBase<any>>>(\n blocClass: B,\n id: BlocInstanceId,\n options: GetBlocOptions<InstanceType<B>> = {},\n ): InstanceType<B> {\n const { props, instanceRef } = options;\n const newBloc = new blocClass(props as never) as InstanceType<B>;\n newBloc._instanceRef = instanceRef;\n newBloc.props = props || null;\n newBloc._updateId(id);\n\n // Set up disposal handler to break circular dependency\n newBloc._setDisposalHandler((bloc) => this.disposeBloc(bloc));\n\n if (newBloc.isIsolated) {\n this.registerIsolatedBlocInstance(newBloc);\n return newBloc;\n }\n\n this.registerBlocInstance(newBloc);\n return newBloc;\n }\n\n\n activateBloc = (bloc: BlocBase<unknown>): void => {\n const base = bloc.constructor as unknown as BlocConstructor<BlocBase<any>>;\n const isIsolated = bloc.isIsolated;\n\n let found = isIsolated ? this.findIsolatedBlocInstance(base, bloc._id) : this.findRegisteredBlocInstance(base, bloc._id);\n if (found) {\n return;\n }\n\n this.log(`[${bloc._name}:${String(bloc._id)}] activateBloc called. Isolated: ${String(bloc.isIsolated)}`);\n if (bloc.isIsolated) {\n this.registerIsolatedBlocInstance(bloc);\n } else {\n this.registerBlocInstance(bloc);\n }\n };\n static get activateBloc() { return Blac.instance.activateBloc; }\n\n /**\n * Gets or creates a bloc instance based on the provided class and options.\n * If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.\n * \n * @param blocClass - The bloc class to get or create\n * @param options - Options including:\n * - id: The instance ID (defaults to class name if not provided)\n * - props: Properties to pass to the bloc constructor\n * - instanceRef: Optional reference string for the instance\n * @returns The bloc instance\n */\n getBloc = <B extends BlocConstructor<BlocBase<any>>>(\n blocClass: B,\n options: GetBlocOptions<InstanceType<B>> = {},\n ): InstanceType<B> => {\n const { id } = options;\n const base = blocClass as unknown as BlocBaseAbstract;\n const blocId = id ?? blocClass.name;\n\n\n if (base.isolated) {\n const isolatedBloc = this.findIsolatedBlocInstance<B>(blocClass, blocId)\n if (isolatedBloc) {\n this.log(`[${blocClass.name}:${String(blocId)}] (getBloc) Found existing isolated instance.`, options);\n return isolatedBloc;\n } else {\n if (options.throwIfNotFound) {\n throw new Error(`Isolated bloc ${blocClass.name} not found`);\n }\n }\n } else {\n const registeredBloc = this.findRegisteredBlocInstance(blocClass, blocId)\n if (registeredBloc) {\n this.log(`[${blocClass.name}:${String(blocId)}] (getBloc) Found existing registered instance.`, options);\n return registeredBloc\n } else {\n if (options.throwIfNotFound) {\n throw new Error(`Registered bloc ${blocClass.name} not found`);\n }\n }\n }\n\n const bloc = this.createNewBlocInstance(\n blocClass,\n blocId,\n options,\n );\n this.log(`[${blocClass.name}:${String(blocId)}] (getBloc) No existing instance found. Creating new one.`, options, bloc);\n \n if (!bloc) {\n throw new Error(`[getBloc] Failed to create bloc instance for ${blocClass.name}. This should never happen.`);\n }\n \n return bloc;\n };\n static get getBloc() { return Blac.instance.getBloc; }\n\n /**\n * Gets a bloc instance or throws an error if it doesn't exist\n * @param blocClass - The bloc class to get\n * @param options - Options including:\n * - id: The instance ID (defaults to class name if not provided)\n * - props: Properties to pass to the bloc constructor\n * - instanceRef: Optional reference string for the instance\n */\n getBlocOrThrow = <B extends BlocConstructor<any>>(\n blocClass: B,\n options: {\n id?: BlocInstanceId;\n props?: InferPropsFromGeneric<B>;\n instanceRef?: string;\n } = {},\n ): InstanceType<B> => {\n const isIsolated = (blocClass as unknown as BlocBaseAbstract).isolated;\n const id = options.id || blocClass.name;\n\n const registered = isIsolated\n ? this.findIsolatedBlocInstance(blocClass, id)\n : this.findRegisteredBlocInstance(blocClass, id);\n\n if (registered) {\n return registered;\n }\n throw new Error(`Bloc ${blocClass.name} not found`);\n };\n static get getBlocOrThrow() { return Blac.instance.getBlocOrThrow; }\n\n /**\n * Gets all instances of a specific bloc class\n * @param blocClass - The bloc class to search for\n * @param options - Options including:\n * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)\n * @returns Array of matching bloc instances\n */\n getAllBlocs = <B extends BlocConstructor<any>>(\n blocClass: B,\n options: {\n searchIsolated?: boolean;\n } = {},\n ): InstanceType<B>[] => {\n const results: InstanceType<B>[] = [];\n // const blocClassName = (blocClass as any).name; // Temporarily removed for debugging\n\n // Search non-isolated blocs\n this.blocInstanceMap.forEach((blocInstance) => {\n if (blocInstance.constructor === blocClass) { // Strict constructor check\n results.push(blocInstance as InstanceType<B>);\n }\n });\n\n // Optionally search isolated blocs\n if (options.searchIsolated !== false) {\n const isolatedBlocs = this.isolatedBlocMap.get(blocClass);\n if (isolatedBlocs) {\n results.push(...isolatedBlocs.map(bloc => bloc as InstanceType<B>));\n }\n }\n\n return results;\n };\n\n /**\n * Disposes all keep-alive blocs of a specific type\n * @param blocClass - The bloc class to dispose\n */\n disposeKeepAliveBlocs = <B extends BlocConstructor<any>>(\n blocClass?: B\n ): void => {\n const toDispose: BlocBase<unknown>[] = [];\n \n for (const bloc of this.keepAliveBlocs) {\n if (!blocClass || bloc.constructor === blocClass) {\n toDispose.push(bloc);\n }\n }\n \n toDispose.forEach(bloc => bloc._dispose());\n };\n static get disposeKeepAliveBlocs() { return Blac.instance.disposeKeepAliveBlocs; }\n\n /**\n * Disposes all blocs matching a pattern\n * @param predicate - Function to test each bloc for disposal\n */\n disposeBlocs = (predicate: (bloc: BlocBase<unknown>) => boolean): void => {\n const toDispose: BlocBase<unknown>[] = [];\n \n // Check registered blocs\n for (const bloc of this.blocInstanceMap.values()) {\n if (predicate(bloc)) {\n toDispose.push(bloc);\n }\n }\n \n // Check isolated blocs\n for (const blocs of this.isolatedBlocMap.values()) {\n for (const bloc of blocs) {\n if (predicate(bloc)) {\n toDispose.push(bloc);\n }\n }\n }\n \n toDispose.forEach(bloc => bloc._dispose());\n };\n static get disposeBlocs() { return Blac.instance.disposeBlocs; }\n\n /**\n * Gets memory usage statistics for debugging\n */\n getMemoryStats = () => {\n return {\n totalBlocs: this.uidRegistry.size,\n registeredBlocs: this.blocInstanceMap.size,\n isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce((sum, arr) => sum + arr.length, 0),\n keepAliveBlocs: this.keepAliveBlocs.size,\n isolatedBlocTypes: this.isolatedBlocMap.size,\n };\n };\n static get getMemoryStats() { return Blac.instance.getMemoryStats; }\n\n /**\n * Validates consumer references and cleans up orphaned consumers\n */\n validateConsumers = (): void => {\n for (const bloc of this.uidRegistry.values()) {\n // Validate consumers using the bloc's own validation method\n bloc._validateConsumers();\n \n // Check if bloc should be disposed after validation\n if (bloc._consumers.size === 0 && !bloc._keepAlive && (bloc as any)._disposalState === 'active') {\n // Schedule disposal for blocs with no consumers\n setTimeout(() => {\n // Double-check conditions before disposal\n if (bloc._consumers.size === 0 && !bloc._keepAlive && (bloc as any)._disposalState === 'active') {\n this.disposeBloc(bloc);\n }\n }, 1000); // Give a grace period\n }\n }\n };\n static get validateConsumers() { return Blac.instance.validateConsumers; }\n}\n","import { Blac } from './Blac';\nimport { BlocBase } from './BlocBase';\nimport { BlocHookDependencyArrayFn } from './types';\n\n/**\n * Represents an observer that can subscribe to state changes in a Bloc\n * @template S - The type of state being observed\n */\nexport type BlacObserver<S> = {\n /** Function to be called when state changes */\n fn: (newState: S, oldState: S, action?: unknown) => void | Promise<void>;\n /** Optional function to determine if the observer should be notified of state changes */\n dependencyArray?: BlocHookDependencyArrayFn<S>;\n /** Dispose function for the observer */\n dispose?: () => void;\n /** Cached state values used for dependency comparison */\n lastState?: unknown[][];\n /** Unique identifier for the observer */\n id: string;\n};\n\n/**\n * A class that manages observers for a Bloc's state changes\n * @template S - The type of state being observed\n */\nexport class BlacObservable<S = unknown> {\n /** The Bloc instance this observable is associated with */\n bloc: BlocBase<S>;\n\n /**\n * Creates a new BlacObservable instance\n * @param bloc - The Bloc instance to observe\n */\n constructor(bloc: BlocBase<S>) {\n this.bloc = bloc;\n }\n\n private _observers = new Set<BlacObserver<S>>();\n\n /**\n * Gets the number of active observers\n * @returns The number of observers currently subscribed\n */\n get size(): number {\n return this._observers.size;\n }\n\n /**\n * Gets the set of all observers\n * @returns The Set of all BlacObserver instances\n */\n get observers() {\n return this._observers;\n }\n\n /**\n * Subscribes an observer to state changes\n * @param observer - The observer to subscribe\n * @returns A function that can be called to unsubscribe the observer\n */\n subscribe(observer: BlacObserver<S>): () => void {\n Blac.log('BlacObservable.subscribe: Subscribing observer.', this.bloc, observer);\n this._observers.add(observer);\n // Don't initialize lastState here - let it remain undefined for first-time detection\n return () => {\n Blac.log('BlacObservable.subscribe: Unsubscribing observer.', this.bloc, observer);\n this.unsubscribe(observer);\n }\n }\n\n /**\n * Unsubscribes an observer from state changes\n * @param observer - The observer to unsubscribe\n */\n unsubscribe(observer: BlacObserver<S>) {\n this._observers.delete(observer);\n // Blac.instance.dispatchEvent(BlacLifecycleEvent.LISTENER_REMOVED, this.bloc, { listenerId: observer.id });\n\n if (this.size === 0) {\n Blac.log('BlacObservable.unsubscribe: No observers left.', this.bloc);\n // The bloc will handle its own disposal through consumer management\n }\n }\n\n /**\n * Notifies all observers of a state change\n * @param newState - The new state value\n * @param oldState - The previous state value\n * @param action - Optional action that triggered the state change\n */\n notify(newState: S, oldState: S, action?: unknown) {\n this._observers.forEach((observer) => {\n let shouldUpdate = false;\n\n if (observer.dependencyArray) {\n const lastDependencyCheck = observer.lastState;\n const newDependencyCheck = observer.dependencyArray(newState);\n\n // If this is the first time (no lastState), always update\n if (!lastDependencyCheck) {\n shouldUpdate = true;\n } else {\n // Compare dependency arrays for changes\n if (lastDependencyCheck.length !== newDependencyCheck.length) {\n shouldUpdate = true;\n } else {\n // Compare each part of the dependency arrays\n for (let o = 0; o < newDependencyCheck.length; o++) {\n const partNew = newDependencyCheck[o];\n const partOld = lastDependencyCheck[o] || [];\n \n // If the part lengths are different, definitely update\n if (partNew.length !== partOld.length) {\n shouldUpdate = true;\n break;\n }\n \n // Compare each value in the parts\n for (let i = 0; i < partNew.length; i++) {\n if (!Object.is(partNew[i], partOld[i])) {\n shouldUpdate = true;\n break;\n }\n }\n \n if (shouldUpdate) break;\n }\n }\n }\n\n observer.lastState = newDependencyCheck;\n } else {\n shouldUpdate = true;\n }\n\n if (shouldUpdate) {\n void observer.fn(newState, oldState, action);\n }\n });\n }\n\n /**\n * Clears the observer set\n */\n clear() {\n // Just clear the observers without calling unsubscribe to avoid circular disposal\n this._observers.clear();\n }\n}\n","/**\n * Cross-platform UUID v4 generator that works in all environments including React Native/Hermes\n * Falls back to crypto.randomUUID() when available, otherwise uses Math.random()\n */\n\n/**\n * Generates a UUID v4 string compatible with all JavaScript environments\n * @returns A UUID v4 string in the format xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\n */\nexport function generateUUID(): string {\n // Try to use crypto.randomUUID() if available (Node.js 16+, modern browsers)\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback implementation for React Native/Hermes and older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}","import { BlacObservable } from './BlacObserver';\nimport { generateUUID } from './utils/uuid';\n\nexport type BlocInstanceId = string | number | undefined;\ntype DependencySelector<S> = (newState: S) => unknown[][];\n\n// Define an interface for the static properties expected on a Bloc/Cubit constructor\ninterface BlocStaticProperties {\n isolated: boolean;\n keepAlive: boolean;\n}\n\n/**\n * Base class for both Blocs and Cubits that provides core state management functionality.\n * Handles state transitions, observer notifications, lifecycle management, and addon integration.\n * \n * @abstract This class should be extended, not instantiated directly\n * @template S The type of state managed by this Bloc\n * @template P The type of props that can be passed during instance creation (optional)\n */\nexport abstract class BlocBase<\n S,\n P = unknown\n> {\n public uid = generateUUID();\n /**\n * When true, every consumer will receive its own unique instance of this Bloc.\n * Use this when state should not be shared between components.\n * @default false\n */\n static isolated = false;\n get isIsolated() {\n return this._isolated;\n }\n \n /**\n * When true, the Bloc instance persists even when there are no active consumers.\n * Useful for maintaining state between component unmount/remount cycles.\n * @default false\n */\n static keepAlive = false;\n get isKeepAlive() {\n return this._keepAlive;\n }\n \n /**\n * Defines how dependencies are selected from the state for efficient updates.\n * When provided, observers will only be notified when selected dependencies change.\n */\n defaultDependencySelector: DependencySelector<S> | undefined;\n \n /**\n * @internal\n * Indicates if this specific Bloc instance is isolated from others of the same type.\n */\n public _isolated = false;\n \n /**\n * @internal\n * Observable responsible for managing state listeners and notifying consumers.\n */\n public _observer: BlacObservable<S>;\n \n /**\n * The unique identifier for this Bloc instance.\n * Defaults to the class name, but can be customized.\n */\n public _id: BlocInstanceId;\n \n /**\n * @internal\n * Reference string used internally for tracking and debugging.\n */\n public _instanceRef?: string;\n \n /**\n * @internal\n * Indicates if this specific Bloc instance should be kept alive when no consumers are present.\n */\n public _keepAlive = false;\n \n /**\n * @readonly\n * Timestamp when this Bloc instance was created, useful for debugging and performance tracking.\n */\n public readonly _createdAt = Date.now();\n\n /**\n * @internal\n * Disposal state to prevent race conditions\n */\n private _disposalState: 'active' | 'disposing' | 'disposed' = 'active';\n\n /**\n * @internal\n * The current state of the Bloc.\n */\n public _state: S;\n \n /**\n * @internal\n * The previous state of the Bloc, maintained for comparison and history.\n */\n public _oldState: S | undefined;\n \n /**\n * Props passed during Bloc instance creation.\n * Can be used to configure or parameterize the Bloc's behavior.\n */\n public props: P | null = null;\n\n /**\n * @internal\n * Flag to prevent batching race conditions\n */\n private _batchingLock = false;\n\n /**\n * @internal\n * Pending batched updates\n */\n private _pendingUpdates: Array<{newState: S, oldState: S, action?: unknown}> = [];\n\n /**\n * @internal\n * Map of consumer IDs to their WeakRef objects for proper cleanup\n */\n private _consumerRefs = new Map<string, WeakRef<object>>();\n\n /**\n * @internal\n * Validates that all consumer references are still alive\n * Removes dead consumers automatically\n */\n _validateConsumers = (): void => {\n const deadConsumers: string[] = [];\n \n for (const [consumerId, weakRef] of this._consumerRefs) {\n if (weakRef.deref() === undefined) {\n deadConsumers.push(consumerId);\n }\n }\n \n // Clean up dead consumers\n for (const consumerId of deadConsumers) {\n this._consumers.delete(consumerId);\n this._consumerRefs.delete(consumerId);\n }\n \n // Schedule disposal if no live consumers remain\n if (this._consumers.size === 0 && !this._keepAlive && this._disposalState === 'active') {\n this._scheduleDisposal();\n }\n };\n\n /**\n * Creates a new BlocBase instance with the given initial state.\n * Sets up the observer, registers with the Blac manager, and initializes addons.\n * \n * @param initialState The initial state value for this Bloc\n */\n constructor(initialState: S) {\n this._state = initialState;\n this._observer = new BlacObservable(this);\n this._id = this.constructor.name;\n\n // Access static properties safely with proper type checking\n const Constructor = this.constructor as typeof BlocBase & BlocStaticProperties;\n \n // Validate that the static properties exist and are boolean\n this._keepAlive = typeof Constructor.keepAlive === 'boolean' ? Constructor.keepAlive : false;\n this._isolated = typeof Constructor.isolated === 'boolean' ? Constructor.isolated : false;\n }\n\n /**\n * Returns the current state of the Bloc.\n * Use this getter to access the state in a read-only manner.\n */\n get state(): S {\n return this._state;\n }\n\n /**\n * @internal\n * Returns the name of the Bloc class for identification and debugging.\n */\n get _name() {\n return this.constructor.name;\n }\n\n /**\n * @internal\n * Updates the Bloc instance's ID to a new value.\n * Only updates if the new ID is defined and different from the current one.\n * \n * @param id The new ID to assign to this Bloc instance\n */\n _updateId = (id?: BlocInstanceId) => {\n const originalId = this._id;\n if (!id || id === originalId) return;\n this._id = id;\n };\n\n /**\n * @internal\n * Cleans up resources and removes this Bloc from the system.\n * Notifies the Blac manager and clears all observers.\n */\n _dispose() {\n // Prevent re-entrant disposal using atomic state change\n if (this._disposalState !== 'active') {\n return;\n }\n this._disposalState = 'disposing';\n \n // Clear all consumers and their references\n this._consumers.clear();\n this._consumerRefs.clear();\n \n // Clear observer subscriptions\n this._observer.clear();\n \n // Call user-defined disposal hook\n this.onDispose?.();\n \n // Mark as fully disposed\n this._disposalState = 'disposed';\n \n // The Blac manager will handle removal from registry\n // This method is called by Blac.disposeBloc, so we don't need to call it again\n }\n\n /**\n * @internal\n * Optional function to be called when the Bloc is disposed.\n */\n onDispose?: () => void;\n\n /**\n * @internal\n * Set of consumer IDs currently listening to this Bloc's state changes.\n */\n _consumers = new Set<string>();\n\n /**\n * @internal\n * Registers a new consumer to this Bloc instance.\n * Notifies the Blac manager that a consumer has been added.\n * \n * @param consumerId The unique ID of the consumer being added\n * @param consumerRef Optional reference to the consumer object for cleanup validation\n */\n _addConsumer = (consumerId: string, consumerRef?: object) => {\n // Prevent adding consumers to disposed blocs\n if (this._disposalState !== 'active') {\n return;\n }\n \n if (this._consumers.has(consumerId)) return;\n this._consumers.add(consumerId);\n \n // Store WeakRef for proper memory management\n if (consumerRef) {\n this._consumerRefs.set(consumerId, new WeakRef(consumerRef));\n }\n \n // this._blac.dispatchEvent(BlacLifecycleEvent.BLOC_CONSUMER_ADDED, this, { consumerId });\n };\n\n /**\n * @internal\n * Unregisters a consumer from this Bloc instance.\n * Notifies the Blac manager that a consumer has been removed.\n * \n * @param consumerId The unique ID of the consumer being removed\n */\n _removeConsumer = (consumerId: string) => {\n if (!this._consumers.has(consumerId)) return;\n \n this._consumers.delete(consumerId);\n this._consumerRefs.delete(consumerId);\n // this._blac.dispatchEvent(BlacLifecycleEvent.BLOC_CONSUMER_REMOVED, this, { consumerId });\n \n // If no consumers remain and not keep-alive, schedule disposal\n if (this._consumers.size === 0 && !this._keepAlive && this._disposalState === 'active') {\n this._scheduleDisposal();\n }\n };\n\n /**\n * @internal\n * Handler function for disposal (can be set by Blac manager)\n */\n private _disposalHandler?: (bloc: BlocBase<unknown>) => void;\n\n /**\n * @internal\n * Sets the disposal handler for this bloc\n */\n _setDisposalHandler(handler: (bloc: BlocBase<unknown>) => void) {\n this._disposalHandler = handler;\n }\n\n /**\n * @internal\n * Schedules disposal of this bloc instance if it has no consumers\n */\n private _scheduleDisposal() {\n // Prevent multiple disposal attempts\n if (this._disposalState !== 'active') {\n return;\n }\n \n // Double-check conditions before disposal\n if (this._consumers.size === 0 && !this._keepAlive) {\n if (this._disposalHandler) {\n this._disposalHandler(this as any);\n } else {\n this._dispose();\n }\n }\n }\n\n lastUpdate = Date.now();\n\n /**\n * @internal\n * Flag to indicate if batching is enabled for this bloc\n */\n private _batchingEnabled = false;\n\n /**\n * @internal\n * Updates the state and notifies all observers of the change.\n * \n * @param newState The new state to be set\n * @param oldState The previous state for comparison\n * @param action Optional metadata about what caused the state change\n */\n _pushState = (newState: S, oldState: S, action?: unknown): void => {\n // Validate newState\n if (newState === undefined) {\n console.warn('BlocBase._pushState: newState is undefined', this);\n return;\n }\n\n // Validate action type if provided\n if (action !== undefined && typeof action !== 'object' && typeof action !== 'function') {\n console.warn('BlocBase._pushState: Invalid action type', this, action);\n return;\n }\n\n if (this._batchingEnabled) {\n // When batching, just accumulate the updates\n this._pendingUpdates.push({ newState, oldState, action });\n \n // Update internal state for consistency\n this._oldState = oldState;\n this._state = newState;\n return;\n }\n\n // Normal state update flow\n this._oldState = oldState;\n this._state = newState;\n \n // Notify observers of the state change\n this._observer.notify(newState, oldState, action);\n this.lastUpdate = Date.now();\n };\n\n /**\n * Enables batching for multiple state updates\n * @param batchFn Function to execute with batching enabled\n */\n batch = <T>(batchFn: () => T): T => {\n // Prevent batching race conditions\n if (this._batchingLock) {\n // If already batching, just execute the function without nesting batches\n return batchFn();\n }\n \n this._batchingLock = true;\n this._batchingEnabled = true;\n this._pendingUpdates = [];\n\n try {\n const result = batchFn();\n \n // Process all batched updates\n if (this._pendingUpdates.length > 0) {\n // Only notify once with the final state\n const finalUpdate = this._pendingUpdates[this._pendingUpdates.length - 1];\n this._observer.notify(finalUpdate.newState, finalUpdate.oldState, finalUpdate.action);\n this.lastUpdate = Date.now();\n }\n \n return result;\n } finally {\n this._batchingEnabled = false;\n this._batchingLock = false;\n this._pendingUpdates = [];\n }\n };\n}\n","import { Blac } from './Blac';\nimport { BlocBase } from './BlocBase';\nimport { BlocEventConstraint } from './types';\n\n// A should be the base type for all events this Bloc handles and must extend BlocEventConstraint\n// to access action.constructor and ensure proper event structure.\n// P is for props, changed from any to unknown.\nexport abstract class Bloc<\n S, // State type\n A extends BlocEventConstraint = BlocEventConstraint, // Base Action/Event type with proper constraints\n P = unknown // Props type\n> extends BlocBase<S, P> {\n // Stores handlers: Map<EventConstructor (subtype of A), HandlerFunction>\n // The handler's event parameter will be correctly typed to the specific EventConstructor\n // by the 'on' method's signature.\n readonly eventHandlers: Map<\n // Key: Constructor of a specific event E (where E extends A)\n // Using 'any[]' for constructor arguments for broader compatibility.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n new (...args: any[]) => A,\n // Value: Handler function. 'event: A' is used here for the stored function type.\n // The 'on' method ensures the specific handler (event: E) is correctly typed.\n (event: A, emit: (newState: S) => void) => void | Promise<void>\n > = new Map();\n\n /**\n * @internal\n * Event queue to ensure sequential processing of async events\n */\n private _eventQueue: A[] = [];\n \n /**\n * @internal\n * Flag indicating if an event is currently being processed\n */\n private _isProcessingEvent = false;\n\n /**\n * Registers an event handler for a specific event type.\n * This method is typically called in the constructor of a derived Bloc class.\n * @param eventConstructor The constructor of the event to handle (e.g., LoadDataEvent).\n * @param handler A function that processes the event and can emit new states.\n * The 'event' parameter in the handler will be typed to the specific eventConstructor.\n */\n protected on<E extends A>(\n // Using 'any[]' for constructor arguments for broader compatibility.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n eventConstructor: new (...args: any[]) => E, \n handler: (event: E, emit: (newState: S) => void) => void | Promise<void>\n ): void {\n if (this.eventHandlers.has(eventConstructor)) {\n // Using Blac.warn or a similar logging mechanism from BlocBase if available,\n // otherwise console.warn. Assuming this._name and this._id are available from BlocBase.\n Blac.warn(\n `[Bloc ${this._name}:${String(this._id)}] Handler for event '${eventConstructor.name}' already registered. It will be overwritten.`\n );\n }\n // Cast the specific handler (event: E) to a more general (event: A) for storage.\n // This is safe because E extends A. When the handler is called with an 'action' of type A,\n // if it was originally registered for type E, 'action' must be an instance of E.\n this.eventHandlers.set(\n eventConstructor,\n handler as (event: A, emit: (newState: S) => void) => void | Promise<void>\n );\n }\n\n /**\n * Dispatches an action/event to the Bloc.\n * Events are queued and processed sequentially to prevent race conditions.\n * @param action The action/event instance to be processed.\n */\n public add = async (action: A): Promise<void> => {\n // Add event to queue\n this._eventQueue.push(action);\n \n // If not already processing, start processing the queue\n if (!this._isProcessingEvent) {\n await this._processEventQueue();\n }\n };\n\n /**\n * @internal\n * Processes events from the queue sequentially\n */\n private async _processEventQueue(): Promise<void> {\n // Prevent concurrent processing\n if (this._isProcessingEvent) {\n return;\n }\n \n this._isProcessingEvent = true;\n \n try {\n while (this._eventQueue.length > 0) {\n const action = this._eventQueue.shift()!;\n await this._processEvent(action);\n }\n } finally {\n this._isProcessingEvent = false;\n }\n }\n\n /**\n * @internal\n * Processes a single event\n */\n private async _processEvent(action: A): Promise<void> {\n // Using 'any[]' for constructor arguments for broader compatibility.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const eventConstructor = action.constructor as new (...args: any[]) => A;\n const handler = this.eventHandlers.get(eventConstructor);\n\n if (handler) {\n // Define the 'emit' function that handlers will use to update state.\n // It captures the current state ('this.state') right before each emission\n // to provide the correct 'previousState' to _pushState.\n const emit = (newState: S): void => {\n const previousState = this.state; // State just before this specific emission\n // The 'action' passed to _pushState is the original action that triggered the handler,\n // providing context for the state change (e.g., for logging or plugins).\n this._pushState(newState, previousState, action);\n };\n\n try {\n // Await the handler in case it's an async function (e.g., performs API calls).\n // The 'action' is passed to the handler, and due to the way 'on' is typed,\n // the 'event' parameter within the handler function will be correctly\n // typed to its specific class (e.g., LoadMyFeatureData).\n await handler(action, emit);\n } catch (error) {\n // Enhanced error handling with better context\n const constructorName = (action.constructor as { name?: string }).name || 'UnnamedConstructor';\n const errorContext = {\n blocName: this._name,\n blocId: String(this._id),\n eventType: constructorName,\n currentState: this.state,\n action: action,\n timestamp: new Date().toISOString()\n };\n \n Blac.error(\n `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${constructorName}':`,\n error,\n \"Context:\", errorContext\n );\n \n // TODO: Consider implementing error boundary pattern\n // For now, we log and continue, but applications may want to:\n // 1. Emit an error state\n // 2. Re-throw the error \n // 3. Call an error handler callback\n \n // Optional: Re-throw for critical errors (can be configured)\n if (error instanceof Error && error.name === 'CriticalError') {\n throw error;\n }\n }\n } else {\n // Enhanced warning with more context\n const constructorName = (action.constructor as { name?: string }).name || 'UnnamedConstructor';\n Blac.warn(\n `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${constructorName}'.`,\n \"Registered handlers:\", Array.from(this.eventHandlers.keys()).map(k => k.name),\n \"Action was:\", action\n );\n }\n }\n}\n","import { Blac } from './Blac';\nimport { BlocBase } from './BlocBase';\n\n/**\n * A Cubit is a simpler version of a Bloc that doesn't handle events.\n * It manages state and provides methods to update it.\n * @template S - The type of state this Cubit manages\n * @template P - The type of parameters (optional, defaults to null)\n */\nexport abstract class Cubit<S, P = null> extends BlocBase<S, P> {\n /**\n * Updates the current state and notifies all observers of the change.\n * If the new state is identical to the current state (using Object.is),\n * no update will occur.\n * @param state - The new state to set\n */\n emit(state: S): void {\n if (Object.is(state, this.state)) {\n return;\n }\n\n const oldState = this.state;\n const newState = state;\n this._pushState(newState, oldState);\n }\n\n /**\n * Partially updates the current state by merging it with the provided state patch.\n * This method is only applicable when the state is an object type.\n * \n * @param statePatch - A partial state object containing only the properties to update\n * @param ignoreChangeCheck - If true, skips checking if the state has actually changed\n * @throws {TypeError} If the state is not an object type\n */\n patch(\n statePatch: S extends object ? Partial<S> : S,\n ignoreChangeCheck = false,\n ): void {\n if (typeof this.state !== 'object' || this.state === null) {\n Blac.warn(\n 'Cubit.patch: was called on a cubit where the state is not an object. This is a no-op.',\n );\n return;\n }\n\n let changes = false;\n if (!ignoreChangeCheck) {\n for (const key in statePatch) {\n if (Object.prototype.hasOwnProperty.call(statePatch, key)) {\n const s = this.state;\n const current = s[key as keyof S];\n if (!Object.is(statePatch[key as keyof S], current)) {\n changes = true;\n break;\n }\n }\n }\n } else {\n changes = true;\n }\n\n if (changes) {\n this.emit({\n ...this.state,\n ...(statePatch as Partial<S>),\n } as S);\n }\n }\n}\n","import { Blac } from './Blac';\nimport { Bloc } from './Bloc';\nimport { BlocBase } from './BlocBase';\nimport { Cubit } from './Cubit';\nimport { BlocEventConstraint } from './types';\n\n/**\n * Test utilities for Blac state management\n */\nexport class BlocTest {\n private static originalInstance: Blac;\n \n /**\n * Sets up a clean test environment\n */\n static setUp(): void {\n this.originalInstance = Blac.instance;\n Blac.resetInstance();\n Blac.enableLog = false; // Disable logging in tests by default\n }\n \n /**\n * Tears down the test environment and restores original state\n */\n static tearDown(): void {\n Blac.resetInstance();\n // Note: Cannot restore original instance due to singleton pattern\n // Tests should use setUp/tearDown properly to manage state\n }\n \n /**\n * Creates a test bloc with automatic cleanup\n */\n static createBloc<T extends BlocBase<any>>(\n BlocClass: new (...args: any[]) => T,\n ...args: any[]\n ): T {\n const bloc = new BlocClass(...args);\n Blac.activateBloc(bloc);\n return bloc;\n }\n \n /**\n * Waits for a bloc to emit a specific state\n */\n static async waitForState<T extends BlocBase<S>, S>(\n bloc: T,\n predicate: (state: S) => boolean,\n timeout = 5000\n ): Promise<S> {\n return new Promise<S>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error(`Timeout waiting for state matching predicate after ${timeout}ms`));\n }, timeout);\n \n const unsubscribe = bloc._observer.subscribe({\n id: `test-waiter-${crypto.randomUUID()}`,\n fn: (newState: S) => {\n if (predicate(newState)) {\n clearTimeout(timeoutId);\n unsubscribe();\n resolve(newState);\n }\n }\n });\n \n // Check current state immediately\n if (predicate(bloc.state)) {\n clearTimeout(timeoutId);\n unsubscribe();\n resolve(bloc.state);\n }\n });\n }\n \n /**\n * Expects a bloc to emit specific states in order\n */\n static async expectStates<T extends BlocBase<S>, S>(\n bloc: T,\n expectedStates: S[],\n timeout = 5000\n ): Promise<void> {\n const receivedStates: S[] = [];\n \n return new Promise<void>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error(\n `Timeout waiting for states. Expected: ${JSON.stringify(expectedStates)}, ` +\n `Received: ${JSON.stringify(receivedStates)}`\n ));\n }, timeout);\n \n const unsubscribe = bloc._observer.subscribe({\n id: `test-expecter-${crypto.randomUUID()}`,\n fn: (newState: S) => {\n receivedStates.push(newState);\n \n // Check if we have all expected states\n if (receivedStates.length === expectedStates.length) {\n clearTimeout(timeoutId);\n unsubscribe();\n \n // Verify all states match using deep equality\n for (let i = 0; i < expectedStates.length; i++) {\n const expected = expectedStates[i];\n const received = receivedStates[i];\n \n // Use JSON comparison for deep equality\n if (JSON.stringify(expected) !== JSON.stringify(received)) {\n reject(new Error(\n `State mismatch at index ${i}. Expected: ${JSON.stringify(expected)}, ` +\n `Received: ${JSON.stringify(received)}`\n ));\n return;\n }\n }\n \n resolve();\n }\n }\n });\n });\n }\n}\n\n/**\n * Mock Bloc for testing\n */\nexport class MockBloc<S, A extends BlocEventConstraint = BlocEventConstraint> extends Bloc<S, A> {\n private mockHandlers = new Map<string, (event: A, emit: (newState: S) => void) => void | Promise<void>>();\n \n constructor(initialState: S) {\n super(initialState);\n }\n \n /**\n * Mock an event handler for testing\n */\n mockEventHandler<E extends A>(\n eventConstructor: new (...args: any[]) => E,\n handler: (event: E, emit: (newState: S) => void) => void | Promise<void>\n ): void {\n // Use the on method to register the mock handler\n this.on(eventConstructor, handler);\n }\n \n /**\n * Get the number of registered handlers\n */\n getHandlerCount(): number {\n return this.eventHandlers.size;\n }\n \n /**\n * Check if a handler is registered for an event type\n */\n hasHandler(eventConstructor: new (...args: any[]) => A): boolean {\n return this.eventHandlers.has(eventConstructor);\n }\n}\n\n/**\n * Mock Cubit for testing\n */\nexport class MockCubit<S> extends Cubit<S> {\n private stateHistory: S[] = [];\n \n constructor(initialState: S) {\n super(initialState);\n this.stateHistory.push(initialState);\n }\n \n /**\n * Override emit to track state history\n */\n emit(newState: S): void {\n this.stateHistory.push(newState);\n super.emit(newState);\n }\n \n /**\n * Get the history of all states\n */\n getStateHistory(): S[] {\n return [...this.stateHistory];\n }\n \n /**\n * Clear state history\n */\n clearStateHistory(): void {\n this.stateHistory = [this.state];\n }\n}\n\n/**\n * Memory leak detector for tests\n */\nexport class MemoryLeakDetector {\n private initialStats: ReturnType<typeof Blac.getMemoryStats>;\n \n constructor() {\n this.initialStats = Blac.getMemoryStats();\n }\n \n /**\n * Check for memory leaks and return a report\n */\n checkForLeaks(): {\n hasLeaks: boolean;\n report: string;\n stats: ReturnType<typeof Blac.getMemoryStats>;\n } {\n const currentStats = Blac.getMemoryStats();\n const hasLeaks = (\n currentStats.registeredBlocs > this.initialStats.registeredBlocs ||\n currentStats.isolatedBlocs > this.initialStats.isolatedBlocs ||\n currentStats.keepAliveBlocs > this.initialStats.keepAliveBlocs\n );\n \n const report = `\nMemory Leak Detection Report:\n- Initial registered blocs: ${this.initialStats.registeredBlocs}\n- Current registered blocs: ${currentStats.registeredBlocs}\n- Initial isolated blocs: ${this.initialStats.isolatedBlocs} \n- Current isolated blocs: ${currentStats.isolatedBlocs}\n- Initial keep-alive blocs: ${this.initialStats.keepAliveBlocs}\n- Current keep-alive blocs: ${currentStats.keepAliveBlocs}\n- Potential leaks detected: ${hasLeaks ? 'YES' : 'NO'}\n `.trim();\n \n return {\n hasLeaks,\n report,\n stats: currentStats\n };\n }\n} "],"names":["_SingletonBlacManager","Blac","instance","oldInstance","bloc","__publicField","SingletonBlacManager","instanceManager","setBlacInstanceManager","manager","_Blac","options","args","message","oldBlocInstanceMap","oldIsolatedBlocMap","blocArray","base","key","blocClass","id","blocId","isolatedBloc","registeredBloc","isIsolated","registered","results","blocInstance","isolatedBlocs","toDispose","predicate","blocs","sum","arr","__unsafe_ignore_singleton","blocClassName","wasRemoved","index","b","wasInIndex","uid","props","instanceRef","newBloc","BlacObservable","observer","newState","oldState","action","shouldUpdate","lastDependencyCheck","newDependencyCheck","o","partNew","partOld","i","generateUUID","c","r","BlocBase","initialState","deadConsumers","consumerId","weakRef","originalId","consumerRef","batchFn","result","finalUpdate","Constructor","_a","handler","Bloc","eventConstructor","emit","previousState","error","constructorName","errorContext","k","Cubit","state","statePatch","ignoreChangeCheck","changes","current","BlocTest","BlocClass","timeout","resolve","reject","timeoutId","unsubscribe","expectedStates","receivedStates","expected","received","MockBloc","MockCubit","MemoryLeakDetector","currentStats","hasLeaks","report"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/BlacObserver.ts","../src/utils/uuid.ts","../src/BlocBase.ts","../src/Blac.ts","../src/Bloc.ts","../src/Cubit.ts","../src/testing.ts","../src/adapter/ConsumerTracker.ts","../src/adapter/ProxyFactory.ts","../src/adapter/BlacAdapter.ts"],"sourcesContent":["import { Blac } from './Blac';\nimport { BlocLifecycleState } from './BlocBase';\nimport { BlocBase } from './BlocBase';\nimport { BlocHookDependencyArrayFn } from './types';\n\n/**\n * Represents an observer that can subscribe to state changes in a Bloc\n * @template S - The type of state being observed\n */\nexport type BlacObserver<S> = {\n /** Function to be called when state changes */\n fn: (newState: S, oldState: S, action?: unknown) => void | Promise<void>;\n /** Optional function to determine if the observer should be notified of state changes */\n dependencyArray?: BlocHookDependencyArrayFn<S>;\n /** Dispose function for the observer */\n dispose?: () => void;\n /** Cached state values used for dependency comparison */\n lastState?: unknown[];\n /** Unique identifier for the observer */\n id: string;\n};\n\n/**\n * A class that manages observers for a Bloc's state changes\n * @template S - The type of state being observed\n */\nexport class BlacObservable<S = unknown> {\n /** The Bloc instance this observable is associated with */\n bloc: BlocBase<S>;\n\n /**\n * Creates a new BlacObservable instance\n * @param bloc - The Bloc instance to observe\n */\n constructor(bloc: BlocBase<S>) {\n this.bloc = bloc;\n }\n\n private _observers = new Set<BlacObserver<S>>();\n\n /**\n * Gets the number of active observers\n * @returns The number of observers currently subscribed\n */\n get size(): number {\n return this._observers.size;\n }\n\n /**\n * Gets the set of all observers\n * @returns The Set of all BlacObserver instances\n */\n get observers() {\n return this._observers;\n }\n\n /**\n * Subscribes an observer to state changes\n * @param observer - The observer to subscribe\n * @returns A function that can be called to unsubscribe the observer\n */\n subscribe(observer: BlacObserver<S>): () => void {\n // Check if bloc is disposed or in disposal process\n const disposalState = (this.bloc as any)._disposalState;\n if (\n disposalState === BlocLifecycleState.DISPOSED ||\n disposalState === BlocLifecycleState.DISPOSING\n ) {\n Blac.log(\n 'BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.',\n this.bloc,\n observer,\n );\n return () => {}; // Return no-op unsubscribe\n }\n\n Blac.log(\n 'BlacObservable.subscribe: Subscribing observer.',\n this.bloc,\n observer,\n );\n this._observers.add(observer);\n\n // If we're in DISPOSAL_REQUESTED state, cancel the disposal since we have a new observer\n if (disposalState === BlocLifecycleState.DISPOSAL_REQUESTED) {\n Blac.log(\n 'BlacObservable.subscribe: Cancelling disposal due to new subscription.',\n this.bloc,\n );\n // Transition back to active state\n (this.bloc as any)._atomicStateTransition(\n BlocLifecycleState.DISPOSAL_REQUESTED,\n BlocLifecycleState.ACTIVE,\n );\n }\n\n // Don't initialize lastState here - let it remain undefined for first-time detection\n return () => {\n Blac.log(\n 'BlacObservable.subscribe: Unsubscribing observer.',\n this.bloc,\n observer,\n );\n this.unsubscribe(observer);\n };\n }\n\n /**\n * Unsubscribes an observer from state changes\n * @param observer - The observer to unsubscribe\n */\n unsubscribe(observer: BlacObserver<S>) {\n this._observers.delete(observer);\n // Blac.instance.dispatchEvent(BlacLifecycleEvent.LISTENER_REMOVED, this.bloc, { listenerId: observer.id });\n\n if (this.size === 0) {\n Blac.log('BlacObservable.unsubscribe: No observers left.', this.bloc);\n // Check if bloc should be disposed when both observers and consumers are gone\n if (\n this.bloc._consumers.size === 0 &&\n !this.bloc._keepAlive &&\n (this.bloc as any)._disposalState === BlocLifecycleState.ACTIVE\n ) {\n Blac.log(\n `[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`,\n );\n (this.bloc as any)._scheduleDisposal();\n }\n }\n }\n\n /**\n * Notifies all observers of a state change\n * @param newState - The new state value\n * @param oldState - The previous state value\n * @param action - Optional action that triggered the state change\n */\n notify(newState: S, oldState: S, action?: unknown) {\n this._observers.forEach((observer) => {\n let shouldUpdate = false;\n\n if (observer.dependencyArray) {\n const lastDependencyCheck = observer.lastState;\n const newDependencyCheck = observer.dependencyArray(\n newState,\n oldState,\n this.bloc,\n );\n\n // If this is the first time (no lastState), trigger initial render\n if (!lastDependencyCheck) {\n shouldUpdate = true;\n } else {\n // Compare dependency arrays\n if (lastDependencyCheck.length !== newDependencyCheck.length) {\n shouldUpdate = true;\n } else {\n // Compare each dependency value using Object.is (same as React)\n for (let i = 0; i < newDependencyCheck.length; i++) {\n if (!Object.is(lastDependencyCheck[i], newDependencyCheck[i])) {\n shouldUpdate = true;\n break;\n }\n }\n }\n }\n\n observer.lastState = newDependencyCheck;\n } else {\n shouldUpdate = true;\n }\n\n if (shouldUpdate) {\n void observer.fn(newState, oldState, action);\n }\n });\n }\n\n /**\n * Clears the observer set\n */\n clear() {\n // Just clear the observers without calling unsubscribe to avoid circular disposal\n this._observers.clear();\n }\n}\n","/**\n * Cross-platform UUID v4 generator that works in all environments including React Native/Hermes\n * Falls back to crypto.randomUUID() when available, otherwise uses Math.random()\n */\n\n/**\n * Generates a UUID v4 string compatible with all JavaScript environments\n * @returns A UUID v4 string in the format xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\n */\nexport function generateUUID(): string {\n // Try to use crypto.randomUUID() if available (Node.js 16+, modern browsers)\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback implementation for React Native/Hermes and older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","import { BlacObservable } from './BlacObserver';\nimport { generateUUID } from './utils/uuid';\n\nexport type BlocInstanceId = string | number | undefined;\ntype DependencySelector<S> = (\n currentState: S,\n previousState: S | undefined,\n instance: any,\n) => unknown[];\n\n/**\n * Enum representing the lifecycle states of a Bloc instance\n * Used for atomic state transitions to prevent race conditions\n */\nexport enum BlocLifecycleState {\n ACTIVE = 'active',\n DISPOSAL_REQUESTED = 'disposal_requested',\n DISPOSING = 'disposing',\n DISPOSED = 'disposed',\n}\n\n/**\n * Result of an atomic state transition operation\n */\nexport interface StateTransitionResult {\n success: boolean;\n currentState: BlocLifecycleState;\n previousState: BlocLifecycleState;\n}\n\n// Define an interface for the static properties expected on a Bloc/Cubit constructor\ninterface BlocStaticProperties {\n isolated: boolean;\n keepAlive: boolean;\n}\n\n/**\n * Base class for both Blocs and Cubits that provides core state management functionality.\n * Handles state transitions, observer notifications, lifecycle management, and addon integration.\n *\n * @abstract This class should be extended, not instantiated directly\n * @template S The type of state managed by this Bloc\n * @template P The type of props that can be passed during instance creation (optional)\n */\nexport abstract class BlocBase<S, P = unknown> {\n public uid = generateUUID();\n /**\n * When true, every consumer will receive its own unique instance of this Bloc.\n * Use this when state should not be shared between components.\n * @default false\n */\n static isolated = false;\n get isIsolated() {\n return this._isolated;\n }\n\n /**\n * When true, the Bloc instance persists even when there are no active consumers.\n * Useful for maintaining state between component unmount/remount cycles.\n * @default false\n */\n static keepAlive = false;\n get isKeepAlive() {\n return this._keepAlive;\n }\n\n /**\n * Defines how dependencies are selected from the state for efficient updates.\n * When provided, observers will only be notified when selected dependencies change.\n */\n defaultDependencySelector: DependencySelector<S> | undefined;\n\n /**\n * @internal\n * Indicates if this specific Bloc instance is isolated from others of the same type.\n */\n public _isolated = false;\n\n /**\n * @internal\n * Observable responsible for managing state listeners and notifying consumers.\n */\n public _observer: BlacObservable<S>;\n\n /**\n * The unique identifier for this Bloc instance.\n * Defaults to the class name, but can be customized.\n */\n public _id: BlocInstanceId;\n\n /**\n * @internal\n * Reference string used internally for tracking and debugging.\n */\n public _instanceRef?: string;\n\n /**\n * @internal\n * Indicates if this specific Bloc instance should be kept alive when no consumers are present.\n */\n public _keepAlive = false;\n\n /**\n * @readonly\n * Timestamp when this Bloc instance was created, useful for debugging and performance tracking.\n */\n public readonly _createdAt = Date.now();\n\n /**\n * @internal\n * Atomic disposal state to prevent race conditions\n */\n private _disposalState: BlocLifecycleState = BlocLifecycleState.ACTIVE;\n\n /**\n * @internal\n * Timestamp when disposal was requested (for React Strict Mode grace period)\n */\n private _disposalRequestTime: number = 0;\n\n /**\n * @internal\n * The current state of the Bloc.\n */\n public _state: S;\n\n /**\n * @internal\n * The previous state of the Bloc, maintained for comparison and history.\n */\n public _oldState: S | undefined;\n\n /**\n * Props passed during Bloc instance creation.\n * Can be used to configure or parameterize the Bloc's behavior.\n */\n public props: P | null = null;\n\n /**\n * @internal\n * Flag to prevent batching race conditions\n */\n private _batchingLock = false;\n\n /**\n * @internal\n * Pending batched updates\n */\n private _pendingUpdates: Array<{\n newState: S;\n oldState: S;\n action?: unknown;\n }> = [];\n\n /**\n * @internal\n * Map of consumer IDs to their WeakRef objects for proper cleanup\n */\n private _consumerRefs = new Map<string, WeakRef<object>>();\n\n /**\n * @internal\n * Validates that all consumer references are still alive\n * Removes dead consumers automatically\n */\n _validateConsumers = (): void => {\n const deadConsumers: string[] = [];\n\n for (const [consumerId, weakRef] of this._consumerRefs) {\n if (weakRef.deref() === undefined) {\n deadConsumers.push(consumerId);\n }\n }\n\n // Clean up dead consumers\n for (const consumerId of deadConsumers) {\n this._consumers.delete(consumerId);\n this._consumerRefs.delete(consumerId);\n }\n\n // Schedule disposal if no live consumers remain\n if (\n this._consumers.size === 0 &&\n !this._keepAlive &&\n this._disposalState === BlocLifecycleState.ACTIVE\n ) {\n this._scheduleDisposal();\n }\n };\n\n /**\n * Creates a new BlocBase instance with the given initial state.\n * Sets up the observer, registers with the Blac manager, and initializes addons.\n *\n * @param initialState The initial state value for this Bloc\n */\n constructor(initialState: S) {\n this._state = initialState;\n this._observer = new BlacObservable(this);\n this._id = this.constructor.name;\n\n // Access static properties safely with proper type checking\n const Constructor = this.constructor as typeof BlocBase &\n BlocStaticProperties;\n\n // Validate that the static properties exist and are boolean\n this._keepAlive =\n typeof Constructor.keepAlive === 'boolean'\n ? Constructor.keepAlive\n : false;\n this._isolated =\n typeof Constructor.isolated === 'boolean' ? Constructor.isolated : false;\n }\n\n /**\n * Returns the current state of the Bloc.\n * Use this getter to access the state in a read-only manner.\n * Returns the state even during transitional lifecycle states for React compatibility.\n */\n get state(): S {\n // Allow state access during all states except DISPOSED for React compatibility\n if (this._disposalState === BlocLifecycleState.DISPOSED) {\n // Return the last known state for disposed blocs to prevent crashes\n return this._state;\n }\n return this._state;\n }\n\n /**\n * Returns whether this Bloc instance has been disposed.\n * @returns true if the bloc is in DISPOSED state\n */\n get isDisposed(): boolean {\n return this._disposalState === BlocLifecycleState.DISPOSED;\n }\n\n /**\n * @internal\n * Returns the name of the Bloc class for identification and debugging.\n */\n get _name() {\n return this.constructor.name;\n }\n\n /**\n * @internal\n * Updates the Bloc instance's ID to a new value.\n * Only updates if the new ID is defined and different from the current one.\n *\n * @param id The new ID to assign to this Bloc instance\n */\n _updateId = (id?: BlocInstanceId) => {\n const originalId = this._id;\n if (!id || id === originalId) return;\n this._id = id;\n };\n\n /**\n * @internal\n * Performs atomic state transition using compare-and-swap semantics\n * @param expectedState The expected current state\n * @param newState The desired new state\n * @returns Result indicating success/failure and state information\n */\n _atomicStateTransition(\n expectedState: BlocLifecycleState,\n newState: BlocLifecycleState,\n ): StateTransitionResult {\n if (this._disposalState === expectedState) {\n const previousState = this._disposalState;\n this._disposalState = newState;\n\n // Log state transition for debugging\n if ((globalThis as any).Blac?.enableLog) {\n (globalThis as any).Blac?.log(\n `[${this._name}:${this._id}] State transition: ${previousState} -> ${newState} (SUCCESS)`,\n );\n }\n\n return {\n success: true,\n currentState: newState,\n previousState,\n };\n }\n\n // Log failed transition attempt\n if ((globalThis as any).Blac?.enableLog) {\n (globalThis as any).Blac?.log(\n `[${this._name}:${this._id}] State transition failed: expected ${expectedState}, current ${this._disposalState}`,\n );\n }\n\n return {\n success: false,\n currentState: this._disposalState,\n previousState: expectedState,\n };\n }\n\n /**\n * @internal\n * Cleans up resources and removes this Bloc from the system.\n * Notifies the Blac manager and clears all observers.\n */\n _dispose(): boolean {\n // Step 1: Attempt atomic transition to DISPOSING state from either ACTIVE or DISPOSAL_REQUESTED\n let transitionResult = this._atomicStateTransition(\n BlocLifecycleState.ACTIVE,\n BlocLifecycleState.DISPOSING,\n );\n\n // If that failed, try from DISPOSAL_REQUESTED state\n if (!transitionResult.success) {\n transitionResult = this._atomicStateTransition(\n BlocLifecycleState.DISPOSAL_REQUESTED,\n BlocLifecycleState.DISPOSING,\n );\n }\n\n if (!transitionResult.success) {\n // Already disposing or disposed - idempotent operation\n return false;\n }\n\n try {\n // Step 2: Perform cleanup operations\n this._consumers.clear();\n this._consumerRefs.clear();\n this._observer.clear();\n\n // Call user-defined disposal hook\n this.onDispose?.();\n\n // Step 3: Final state transition to DISPOSED\n const finalResult = this._atomicStateTransition(\n BlocLifecycleState.DISPOSING,\n BlocLifecycleState.DISPOSED,\n );\n\n return finalResult.success;\n } catch (error) {\n // Recovery: Reset state on cleanup failure\n this._disposalState = BlocLifecycleState.ACTIVE;\n throw error;\n }\n }\n\n /**\n * @internal\n * Optional function to be called when the Bloc is disposed.\n */\n onDispose?: () => void;\n\n /**\n * @internal\n * Set of consumer IDs currently listening to this Bloc's state changes.\n */\n _consumers = new Set<string>();\n\n /**\n * @internal\n * Registers a new consumer to this Bloc instance.\n * Notifies the Blac manager that a consumer has been added.\n *\n * @param consumerId The unique ID of the consumer being added\n * @param consumerRef Optional reference to the consumer object for cleanup validation\n */\n _addConsumer = (consumerId: string, consumerRef?: object): boolean => {\n // Atomic state validation - only allow consumer addition in ACTIVE state\n if (this._disposalState !== BlocLifecycleState.ACTIVE) {\n return false; // Clear failure indication\n }\n\n // Prevent duplicate consumers\n if (this._consumers.has(consumerId)) return true;\n\n // Safe consumer addition\n this._consumers.add(consumerId);\n\n // Store WeakRef for proper memory management\n if (consumerRef) {\n this._consumerRefs.set(consumerId, new WeakRef(consumerRef));\n }\n\n // @ts-ignore - Blac is available globally\n (globalThis as any).Blac?.log(\n `[${this._name}:${this._id}] Consumer added. Total consumers: ${this._consumers.size}`,\n );\n\n // this._blac.dispatchEvent(BlacLifecycleEvent.BLOC_CONSUMER_ADDED, this, { consumerId });\n return true;\n };\n\n /**\n * @internal\n * Unregisters a consumer from this Bloc instance.\n * Notifies the Blac manager that a consumer has been removed.\n *\n * @param consumerId The unique ID of the consumer being removed\n */\n _removeConsumer = (consumerId: string) => {\n if (!this._consumers.has(consumerId)) return;\n\n this._consumers.delete(consumerId);\n this._consumerRefs.delete(consumerId);\n // this._blac.dispatchEvent(BlacLifecycleEvent.BLOC_CONSUMER_REMOVED, this, { consumerId });\n\n // @ts-ignore - Blac is available globally\n (globalThis as any).Blac?.log(\n `[${this._name}:${this._id}] Consumer removed. Remaining consumers: ${this._consumers.size}, keepAlive: ${this._keepAlive}`,\n );\n\n // If no consumers remain and not keep-alive, schedule disposal\n if (\n this._consumers.size === 0 &&\n !this._keepAlive &&\n this._disposalState === BlocLifecycleState.ACTIVE\n ) {\n // @ts-ignore - Blac is available globally\n (globalThis as any).Blac?.log(\n `[${this._name}:${this._id}] No consumers left and not keep-alive. Scheduling disposal.`,\n );\n this._scheduleDisposal();\n }\n };\n\n /**\n * @internal\n * Handler function for disposal (can be set by Blac manager)\n */\n private _disposalHandler?: (bloc: BlocBase<unknown>) => void;\n\n /**\n * @internal\n * Sets the disposal handler for this bloc\n */\n _setDisposalHandler(handler: (bloc: BlocBase<unknown>) => void) {\n this._disposalHandler = handler;\n }\n\n /**\n * @internal\n * Schedules disposal of this bloc instance if it has no consumers\n * Uses atomic state transitions to prevent race conditions\n */\n private _scheduleDisposal(): void {\n // Step 1: Atomic transition to DISPOSAL_REQUESTED\n const requestResult = this._atomicStateTransition(\n BlocLifecycleState.ACTIVE,\n BlocLifecycleState.DISPOSAL_REQUESTED,\n );\n\n if (!requestResult.success) {\n // Already requested, disposing, or disposed\n return;\n }\n\n // Step 2: Verify disposal conditions under atomic protection\n const shouldDispose = this._consumers.size === 0 && !this._keepAlive;\n\n if (!shouldDispose) {\n // Conditions no longer met, revert to active\n this._atomicStateTransition(\n BlocLifecycleState.DISPOSAL_REQUESTED,\n BlocLifecycleState.ACTIVE,\n );\n return;\n }\n\n // Record disposal request time for tracking\n this._disposalRequestTime = Date.now();\n\n // Step 3: Defer disposal until after current execution completes\n // This allows React Strict Mode's immediate remount to cancel disposal\n queueMicrotask(() => {\n // Re-verify disposal conditions - React Strict Mode remount may have cancelled this\n const stillShouldDispose =\n this._consumers.size === 0 &&\n !this._keepAlive &&\n this._observer.size === 0 &&\n (this as any)._disposalState === BlocLifecycleState.DISPOSAL_REQUESTED;\n\n if (stillShouldDispose) {\n // No cancellation occurred, proceed with disposal\n if (this._disposalHandler) {\n this._disposalHandler(this as any);\n } else {\n this._dispose();\n }\n } else {\n // Disposal was cancelled (React Strict Mode remount), revert to active\n this._atomicStateTransition(\n BlocLifecycleState.DISPOSAL_REQUESTED,\n BlocLifecycleState.ACTIVE,\n );\n }\n });\n }\n\n lastUpdate = Date.now();\n\n /**\n * @internal\n * Flag to indicate if batching is enabled for this bloc\n */\n private _batchingEnabled = false;\n\n /**\n * @internal\n * Updates the state and notifies all observers of the change.\n *\n * @param newState The new state to be set\n * @param oldState The previous state for comparison\n * @param action Optional metadata about what caused the state change\n */\n _pushState = (newState: S, oldState: S, action?: unknown): void => {\n // Validate newState\n if (newState === undefined) {\n return;\n }\n\n // Validate action type if provided\n if (\n action !== undefined &&\n typeof action !== 'object' &&\n typeof action !== 'function'\n ) {\n return;\n }\n\n if (this._batchingEnabled) {\n // When batching, just accumulate the updates\n this._pendingUpdates.push({ newState, oldState, action });\n\n // Update internal state for consistency\n this._oldState = oldState;\n this._state = newState;\n return;\n }\n\n // Normal state update flow\n this._oldState = oldState;\n this._state = newState;\n\n // Notify observers of the state change\n this._observer.notify(newState, oldState, action);\n this.lastUpdate = Date.now();\n };\n\n /**\n * Enables batching for multiple state updates\n * @param batchFn Function to execute with batching enabled\n */\n batch = <T>(batchFn: () => T): T => {\n // Prevent batching race conditions\n if (this._batchingLock) {\n // If already batching, just execute the function without nesting batches\n return batchFn();\n }\n\n this._batchingLock = true;\n this._batchingEnabled = true;\n this._pendingUpdates = [];\n\n try {\n const result = batchFn();\n\n // Process all batched updates\n if (this._pendingUpdates.length > 0) {\n // Only notify once with the final state\n const finalUpdate =\n this._pendingUpdates[this._pendingUpdates.length - 1];\n this._observer.notify(\n finalUpdate.newState,\n finalUpdate.oldState,\n finalUpdate.action,\n );\n this.lastUpdate = Date.now();\n }\n\n return result;\n } finally {\n this._batchingEnabled = false;\n this._batchingLock = false;\n this._pendingUpdates = [];\n }\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// TODO: The 'any' types in this file are necessary for proper type inference in complex generic scenarios.\n// Specifically:\n// 1. BlocConstructor<any> in Maps - allows any bloc type to be stored while maintaining type safety in usage\n// 2. Type assertions for _disposalState - private property access across inheritance hierarchy\n// 3. Constructor argument types - enables flexible bloc instantiation patterns\n// These 'any' usages are carefully controlled and don't compromise runtime type safety.\nimport { BlocBase, BlocInstanceId, BlocLifecycleState } from './BlocBase';\nimport {\n BlocBaseAbstract,\n BlocConstructor,\n BlocHookDependencyArrayFn,\n BlocState,\n InferPropsFromGeneric,\n} from './types';\n\n/**\n * Configuration options for the Blac instance\n */\nexport interface BlacConfig {\n /** Whether to expose the Blac instance globally */\n exposeBlacInstance?: boolean;\n}\n\nexport interface GetBlocOptions<B extends BlocBase<unknown>> {\n id?: string;\n selector?: BlocHookDependencyArrayFn<BlocState<B>>;\n props?: InferPropsFromGeneric<B>;\n onMount?: (bloc: B) => void;\n instanceRef?: string;\n throwIfNotFound?: boolean;\n /** Force creation of a new instance for isolated blocs, bypassing instance lookup */\n forceNewInstance?: boolean;\n}\n\n/**\n * Interface for Blac instance management\n */\nexport interface BlacInstanceManager {\n getInstance(): Blac;\n setInstance(instance: Blac): void;\n resetInstance(): void;\n}\n\n/**\n * Default singleton implementation of BlacInstanceManager\n */\nclass SingletonBlacManager implements BlacInstanceManager {\n private static _instance: Blac;\n\n getInstance(): Blac {\n if (!SingletonBlacManager._instance) {\n SingletonBlacManager._instance = new Blac({\n __unsafe_ignore_singleton: true,\n });\n }\n return SingletonBlacManager._instance;\n }\n\n setInstance(instance: Blac): void {\n SingletonBlacManager._instance = instance;\n }\n\n resetInstance(): void {\n const oldInstance = SingletonBlacManager._instance;\n SingletonBlacManager._instance = new Blac({\n __unsafe_ignore_singleton: true,\n });\n\n // Transfer any keep-alive blocs to the new instance\n if (oldInstance) {\n for (const bloc of oldInstance.keepAliveBlocs) {\n SingletonBlacManager._instance.keepAliveBlocs.add(bloc);\n SingletonBlacManager._instance.uidRegistry.set(bloc.uid, bloc);\n }\n }\n }\n}\n\n/**\n * Global instance manager (can be replaced for testing or different patterns)\n */\nlet instanceManager: BlacInstanceManager = new SingletonBlacManager();\n\n/**\n * Sets a custom instance manager (useful for testing or advanced patterns)\n */\nexport function setBlacInstanceManager(manager: BlacInstanceManager): void {\n instanceManager = manager;\n}\n\n/**\n * Main Blac class that manages the state management system.\n * Can work with singleton pattern or dependency injection.\n * Handles bloc lifecycle, and instance tracking.\n *\n * Key responsibilities:\n * - Managing bloc instances (creation, disposal, lookup)\n * - Handling isolated and non-isolated blocs\n * - Providing logging and debugging capabilities\n */\nexport class Blac {\n static get instance(): Blac {\n return instanceManager.getInstance();\n }\n /** Timestamp when the instance was created */\n createdAt = Date.now();\n static get getAllBlocs() {\n return Blac.instance.getAllBlocs;\n }\n /** Map storing all registered bloc instances by their class name and ID */\n blocInstanceMap: Map<string, BlocBase<unknown>> = new Map();\n /** Map storing isolated bloc instances grouped by their constructor */\n // Using BlocConstructor<BlocBase<unknown>> would break type inference when storing\n // different bloc types in the same map. The 'any' allows proper polymorphic storage\n // while maintaining type safety at usage sites through the BlocConstructor constraint.\n isolatedBlocMap: Map<BlocConstructor<any>, BlocBase<unknown>[]> = new Map();\n /** Map for O(1) lookup of isolated blocs by UID */\n isolatedBlocIndex: Map<string, BlocBase<unknown>> = new Map();\n /** Map tracking UIDs to prevent memory leaks */\n uidRegistry: Map<string, BlocBase<unknown>> = new Map();\n /** Set of keep-alive blocs for controlled cleanup */\n keepAliveBlocs: Set<BlocBase<unknown>> = new Set();\n /** Flag to control whether changes should be posted to document */\n postChangesToDocument = false;\n\n /**\n * Creates a new Blac instance.\n * @param options - Configuration options including singleton control\n */\n constructor(options: { __unsafe_ignore_singleton?: boolean } = {}) {\n const { __unsafe_ignore_singleton = false } = options;\n if (!__unsafe_ignore_singleton) {\n return Blac.instance;\n }\n instanceManager.setInstance(this);\n }\n\n /** Flag to enable/disable logging */\n static enableLog = false;\n static logLevel: 'warn' | 'log' = 'warn';\n static logSpy: ((...args: unknown[]) => void) | null = null;\n\n /**\n * Logs messages to console when logging is enabled\n * @param args - Arguments to log\n */\n log = (...args: unknown[]) => {\n if (Blac.logSpy) {\n Blac.logSpy(args);\n }\n if (Blac.enableLog && Blac.logLevel === 'warn') {\n // Logging disabled - console.warn removed\n }\n if (Blac.enableLog && Blac.logLevel === 'log') {\n // Logging disabled - console.log removed\n }\n };\n static get log() {\n return Blac.instance.log;\n }\n\n /**\n * Gets the current Blac instance\n * @returns The Blac instance\n */\n static getInstance(): Blac {\n return instanceManager.getInstance();\n }\n\n /**\n * Logs a warning message\n * @param message - Warning message\n * @param args - Additional arguments\n */\n warn = (message: string, ...args: unknown[]) => {\n if (Blac.enableLog) {\n // Logging disabled - console.warn removed\n }\n };\n static get warn() {\n return Blac.instance.warn;\n }\n /**\n * Logs an error message\n * @param message - Error message\n * @param args - Additional arguments\n */\n error = (message: string, ...args: unknown[]) => {\n if (Blac.enableLog) {\n // Logging disabled - console.error removed\n }\n };\n static get error() {\n return Blac.instance.error;\n }\n\n /**\n * Resets the Blac instance to a new one, disposing non-keepAlive blocs\n * from the old instance.\n */\n resetInstance = (): void => {\n this.log('Reset Blac instance');\n\n // Create snapshots to avoid concurrent modification issues\n const oldBlocInstanceMap = new Map(this.blocInstanceMap);\n const oldIsolatedBlocMap = new Map(this.isolatedBlocMap);\n\n // Dispose non-keepAlive blocs from the current instance\n // Use disposeBloc method to ensure proper cleanup\n oldBlocInstanceMap.forEach((bloc) => {\n // TODO: Type assertion for private property access (see explanation above)\n if (\n !bloc._keepAlive &&\n (bloc as any)._disposalState === BlocLifecycleState.ACTIVE\n ) {\n this.disposeBloc(bloc);\n }\n });\n\n oldIsolatedBlocMap.forEach((blocArray) => {\n blocArray.forEach((bloc) => {\n // TODO: Type assertion for private property access (see explanation above)\n if (\n !bloc._keepAlive &&\n (bloc as any)._disposalState === BlocLifecycleState.ACTIVE\n ) {\n this.disposeBloc(bloc);\n }\n });\n });\n\n // Clear registries (keep-alive blocs will be re-added by instance manager)\n this.blocInstanceMap.clear();\n this.isolatedBlocMap.clear();\n this.isolatedBlocIndex.clear();\n\n // Use instance manager to reset\n instanceManager.resetInstance();\n };\n static resetInstance = (): void => {\n instanceManager.resetInstance();\n };\n\n /**\n * Disposes of a bloc instance by removing it from the appropriate registry\n * @param bloc - The bloc instance to dispose\n */\n disposeBloc = (bloc: BlocBase<unknown>): void => {\n // Check if bloc is already disposed to prevent double disposal\n // TODO: Type assertion needed to access private _disposalState property from external class.\n // This is safe because we know BlocBase has this property, but TypeScript can't verify\n // private property access across class boundaries. Alternative would be to make\n // _disposalState protected, but that would expose internal implementation details.\n const currentState = (bloc as any)._disposalState;\n const validStatesForDisposal = [\n BlocLifecycleState.ACTIVE,\n BlocLifecycleState.DISPOSAL_REQUESTED,\n ];\n\n if (!validStatesForDisposal.includes(currentState)) {\n this.log(\n `[${bloc._name}:${String(bloc._id)}] disposeBloc called on bloc in invalid state: ${currentState}`,\n );\n return;\n }\n\n const base = bloc.constructor as unknown as BlocBaseAbstract;\n const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);\n this.log(\n `[${bloc._name}:${String(bloc._id)}] disposeBloc called. Isolated: ${String(base.isolated)}`,\n );\n\n // First dispose the bloc to prevent further operations\n bloc._dispose();\n\n // Then clean up from registries\n if (base.isolated) {\n this.unregisterIsolatedBlocInstance(bloc);\n this.blocInstanceMap.delete(key);\n } else {\n this.unregisterBlocInstance(bloc);\n }\n\n this.log('dispatched bloc', bloc);\n };\n static get disposeBloc() {\n return Blac.instance.disposeBloc;\n }\n\n /**\n * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID\n * @param blocClassName - The name of the bloc class\n * @param id - The instance ID\n * @returns A unique key string in the format \"className:id\"\n */\n createBlocInstanceMapKey(blocClassName: string, id: BlocInstanceId): string {\n return `${blocClassName}:${String(id)}`;\n }\n\n /**\n * Unregister a bloc instance from the main registry\n * @param bloc - The bloc instance to unregister\n */\n unregisterBlocInstance(bloc: BlocBase<unknown>): void {\n const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);\n this.blocInstanceMap.delete(key);\n\n // Clean up UID tracking\n this.uidRegistry.delete(bloc.uid);\n\n // Remove from keep-alive set\n this.keepAliveBlocs.delete(bloc);\n }\n\n /**\n * Registers a bloc instance in the main registry\n * @param bloc - The bloc instance to register\n */\n registerBlocInstance(bloc: BlocBase<unknown>): void {\n const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);\n this.blocInstanceMap.set(key, bloc);\n\n // Track UID for cleanup\n this.uidRegistry.set(bloc.uid, bloc);\n\n // Track keep-alive blocs\n if (bloc._keepAlive) {\n this.keepAliveBlocs.add(bloc);\n }\n }\n\n /**\n * Finds a registered bloc instance by its class and ID\n * @param blocClass - The bloc class to search for\n * @param id - The instance ID\n * @returns The found bloc instance or undefined if not found\n */\n findRegisteredBlocInstance<B extends BlocConstructor<any>>(\n blocClass: B,\n id: BlocInstanceId,\n ): InstanceType<B> | undefined {\n const base = blocClass as unknown as BlocBaseAbstract;\n if (base.isolated) return undefined;\n\n const key = this.createBlocInstanceMapKey(blocClass.name, id);\n const found = this.blocInstanceMap.get(key) as InstanceType<B> | undefined;\n return found;\n }\n\n /**\n * Registers an isolated bloc instance in the isolated registry\n * @param bloc - The isolated bloc instance to register\n */\n registerIsolatedBlocInstance(bloc: BlocBase<unknown>): void {\n const blocClass = bloc.constructor as BlocConstructor<any>;\n const blocs = this.isolatedBlocMap.get(blocClass);\n if (blocs) {\n blocs.push(bloc);\n } else {\n this.isolatedBlocMap.set(blocClass, [bloc]);\n }\n\n // Add to isolated index for O(1) lookups\n this.isolatedBlocIndex.set(bloc.uid, bloc);\n\n // Track UID for cleanup\n this.uidRegistry.set(bloc.uid, bloc);\n\n // Track keep-alive blocs\n if (bloc._keepAlive) {\n this.keepAliveBlocs.add(bloc);\n }\n }\n\n /**\n * Unregister an isolated bloc instance from the isolated registry\n * @param bloc - The isolated bloc instance to unregister\n */\n unregisterIsolatedBlocInstance(bloc: BlocBase<unknown>): void {\n const blocClass = bloc.constructor;\n const blocs = this.isolatedBlocMap.get(blocClass as BlocConstructor<any>);\n\n // Ensure both data structures are synchronized\n let wasRemoved = false;\n\n if (blocs) {\n const index = blocs.findIndex((b) => b.uid === bloc.uid);\n if (index !== -1) {\n blocs.splice(index, 1);\n wasRemoved = true;\n }\n\n if (blocs.length === 0) {\n this.isolatedBlocMap.delete(blocClass as BlocConstructor<any>);\n }\n }\n\n // Always try to remove from isolated index, even if not found in map\n const wasInIndex = this.isolatedBlocIndex.delete(bloc.uid);\n\n // Clean up UID tracking\n this.uidRegistry.delete(bloc.uid);\n\n // Remove from keep-alive set\n this.keepAliveBlocs.delete(bloc);\n\n // Log inconsistency for debugging\n if (wasRemoved !== wasInIndex) {\n this.warn(\n `[Blac] Inconsistent state detected during isolated bloc cleanup for ${bloc._name}:${bloc.uid}. ` +\n `Map removal: ${wasRemoved}, Index removal: ${wasInIndex}`,\n );\n }\n }\n\n /**\n * Finds an isolated bloc instance by its class and ID (O(n) lookup)\n */\n findIsolatedBlocInstance<B extends BlocConstructor<any>>(\n blocClass: B,\n id: BlocInstanceId,\n ): InstanceType<B> | undefined {\n const base = blocClass as unknown as BlocBaseAbstract;\n if (!base.isolated) return undefined;\n\n const blocs = this.isolatedBlocMap.get(blocClass);\n if (!blocs) {\n return undefined;\n }\n // Find the specific bloc by ID within the isolated array\n const found = blocs.find((b) => b._id === id) as\n | InstanceType<B>\n | undefined;\n return found;\n }\n\n /**\n * Finds an isolated bloc instance by UID (O(1) lookup)\n */\n findIsolatedBlocInstanceByUid<B extends BlocBase<unknown>>(\n uid: string,\n ): B | undefined {\n return this.isolatedBlocIndex.get(uid) as B | undefined;\n }\n\n /**\n * Creates a new bloc instance and registers it in the appropriate registry\n * @param blocClass - The bloc class to instantiate\n * @param id - The instance ID\n * @param props - Properties to pass to the bloc constructor\n * @param instanceRef - Optional reference string for the instance\n * @returns The newly created bloc instance\n */\n createNewBlocInstance<B extends BlocConstructor<BlocBase<any>>>(\n blocClass: B,\n id: BlocInstanceId,\n options: GetBlocOptions<InstanceType<B>> = {},\n ): InstanceType<B> {\n const { props, instanceRef } = options;\n const newBloc = new blocClass(props as never) as InstanceType<B>;\n newBloc._instanceRef = instanceRef;\n newBloc.props = props || null;\n newBloc._updateId(id);\n\n // Set up disposal handler to break circular dependency\n newBloc._setDisposalHandler((bloc) => this.disposeBloc(bloc));\n\n if (newBloc.isIsolated) {\n this.registerIsolatedBlocInstance(newBloc);\n return newBloc;\n }\n\n this.registerBlocInstance(newBloc);\n return newBloc;\n }\n\n activateBloc = (bloc: BlocBase<unknown>): void => {\n // Don't activate disposed blocs\n if ((bloc as any)._disposalState !== BlocLifecycleState.ACTIVE) {\n this.log(\n `[${bloc._name}:${String(bloc._id)}] activateBloc called on disposed bloc. Ignoring.`,\n );\n return;\n }\n\n const base = bloc.constructor as unknown as BlocConstructor<BlocBase<any>>;\n const isIsolated = bloc.isIsolated;\n\n let found = isIsolated\n ? this.findIsolatedBlocInstance(base, bloc._id)\n : this.findRegisteredBlocInstance(base, bloc._id);\n if (found) {\n return;\n }\n\n this.log(\n `[${bloc._name}:${String(bloc._id)}] activateBloc called. Isolated: ${String(bloc.isIsolated)}`,\n );\n if (bloc.isIsolated) {\n this.registerIsolatedBlocInstance(bloc);\n } else {\n this.registerBlocInstance(bloc);\n }\n };\n static get activateBloc() {\n return Blac.instance.activateBloc;\n }\n\n /**\n * Gets or creates a bloc instance based on the provided class and options.\n * If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.\n *\n * @param blocClass - The bloc class to get or create\n * @param options - Options including:\n * - id: The instance ID (defaults to class name if not provided)\n * - props: Properties to pass to the bloc constructor\n * - instanceRef: Optional reference string for the instance\n * @returns The bloc instance\n */\n getBloc = <B extends BlocConstructor<BlocBase<any>>>(\n blocClass: B,\n options: GetBlocOptions<InstanceType<B>> = {},\n ): InstanceType<B> => {\n const { id, forceNewInstance } = options;\n const base = blocClass as unknown as BlocBaseAbstract;\n const blocId = id ?? blocClass.name;\n this.log(`[${blocClass.name}:${String(blocId)}] (getBloc) Called:`, {\n options,\n base,\n });\n\n // Skip instance lookup if forceNewInstance is true for isolated blocs\n if (!forceNewInstance) {\n if (base.isolated) {\n const isolatedBloc = this.findIsolatedBlocInstance<B>(\n blocClass,\n options.instanceRef ?? blocId,\n );\n if (isolatedBloc) {\n return isolatedBloc;\n } else {\n if (options.throwIfNotFound) {\n throw new Error(`Isolated bloc ${blocClass.name} not found`);\n }\n }\n } else {\n const registeredBloc = this.findRegisteredBlocInstance(\n blocClass,\n blocId,\n );\n if (registeredBloc) {\n return registeredBloc;\n } else {\n if (options.throwIfNotFound) {\n throw new Error(`Registered bloc ${blocClass.name} not found`);\n }\n }\n }\n }\n\n const bloc = this.createNewBlocInstance(blocClass, blocId, options);\n this.log(\n `[${blocClass.name}:${String(blocId)}] (getBloc) No existing instance found. Creating new one.`,\n options,\n bloc,\n );\n\n if (!bloc) {\n throw new Error(\n `[getBloc] Failed to create bloc instance for ${blocClass.name}. This should never happen.`,\n );\n }\n\n return bloc;\n };\n static get getBloc() {\n return Blac.instance.getBloc;\n }\n\n /**\n * Gets a bloc instance or throws an error if it doesn't exist\n * @param blocClass - The bloc class to get\n * @param options - Options including:\n * - id: The instance ID (defaults to class name if not provided)\n * - props: Properties to pass to the bloc constructor\n * - instanceRef: Optional reference string for the instance\n */\n getBlocOrThrow = <B extends BlocConstructor<any>>(\n blocClass: B,\n options: {\n id?: BlocInstanceId;\n props?: InferPropsFromGeneric<B>;\n instanceRef?: string;\n } = {},\n ): InstanceType<B> => {\n const isIsolated = (blocClass as unknown as BlocBaseAbstract).isolated;\n const id = options.id || blocClass.name;\n\n const registered = isIsolated\n ? this.findIsolatedBlocInstance(blocClass, id)\n : this.findRegisteredBlocInstance(blocClass, id);\n\n if (registered) {\n return registered;\n }\n throw new Error(`Bloc ${blocClass.name} not found`);\n };\n static get getBlocOrThrow() {\n return Blac.instance.getBlocOrThrow;\n }\n\n /**\n * Gets all instances of a specific bloc class\n * @param blocClass - The bloc class to search for\n * @param options - Options including:\n * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)\n * @returns Array of matching bloc instances\n */\n getAllBlocs = <B extends BlocConstructor<any>>(\n blocClass: B,\n options: {\n searchIsolated?: boolean;\n } = {},\n ): InstanceType<B>[] => {\n const results: InstanceType<B>[] = [];\n // const blocClassName = (blocClass as any).name; // Temporarily removed for debugging\n\n // Search non-isolated blocs\n this.blocInstanceMap.forEach((blocInstance) => {\n if (blocInstance.constructor === blocClass) {\n // Strict constructor check\n results.push(blocInstance as InstanceType<B>);\n }\n });\n\n // Optionally search isolated blocs\n if (options.searchIsolated !== false) {\n const isolatedBlocs = this.isolatedBlocMap.get(blocClass);\n if (isolatedBlocs) {\n results.push(...isolatedBlocs.map((bloc) => bloc as InstanceType<B>));\n }\n }\n\n return results;\n };\n\n /**\n * Disposes all keep-alive blocs of a specific type\n * @param blocClass - The bloc class to dispose\n */\n disposeKeepAliveBlocs = <B extends BlocConstructor<any>>(\n blocClass?: B,\n ): void => {\n const toDispose: BlocBase<unknown>[] = [];\n\n for (const bloc of this.keepAliveBlocs) {\n if (!blocClass || bloc.constructor === blocClass) {\n toDispose.push(bloc);\n }\n }\n\n toDispose.forEach((bloc) => bloc._dispose());\n };\n static get disposeKeepAliveBlocs() {\n return Blac.instance.disposeKeepAliveBlocs;\n }\n\n /**\n * Disposes all blocs matching a pattern\n * @param predicate - Function to test each bloc for disposal\n */\n disposeBlocs = (predicate: (bloc: BlocBase<unknown>) => boolean): void => {\n const toDispose: BlocBase<unknown>[] = [];\n\n // Check registered blocs\n for (const bloc of this.blocInstanceMap.values()) {\n if (predicate(bloc)) {\n toDispose.push(bloc);\n }\n }\n\n // Check isolated blocs\n for (const blocs of this.isolatedBlocMap.values()) {\n for (const bloc of blocs) {\n if (predicate(bloc)) {\n toDispose.push(bloc);\n }\n }\n }\n\n toDispose.forEach((bloc) => bloc._dispose());\n };\n static get disposeBlocs() {\n return Blac.instance.disposeBlocs;\n }\n\n /**\n * Gets memory usage statistics for debugging\n */\n getMemoryStats = () => {\n return {\n totalBlocs: this.uidRegistry.size,\n registeredBlocs: this.blocInstanceMap.size,\n isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(\n (sum, arr) => sum + arr.length,\n 0,\n ),\n keepAliveBlocs: this.keepAliveBlocs.size,\n isolatedBlocTypes: this.isolatedBlocMap.size,\n };\n };\n static get getMemoryStats() {\n return Blac.instance.getMemoryStats;\n }\n\n /**\n * Validates consumer references and cleans up orphaned consumers\n */\n validateConsumers = (): void => {\n for (const bloc of this.uidRegistry.values()) {\n // Validate consumers using the bloc's own validation method\n bloc._validateConsumers();\n\n // Check if bloc should be disposed after validation\n // TODO: Type assertion for private property access (see explanation above)\n if (\n bloc._consumers.size === 0 &&\n !bloc._keepAlive &&\n (bloc as any)._disposalState === BlocLifecycleState.ACTIVE\n ) {\n // Schedule disposal for blocs with no consumers\n setTimeout(() => {\n // Double-check conditions before disposal\n // TODO: Type assertion for private property access (see explanation above)\n if (\n bloc._consumers.size === 0 &&\n !bloc._keepAlive &&\n (bloc as any)._disposalState === BlocLifecycleState.ACTIVE\n ) {\n this.disposeBloc(bloc);\n }\n }, 1000); // Give a grace period\n }\n }\n };\n static get validateConsumers() {\n return Blac.instance.validateConsumers;\n }\n}\n","import { Blac } from './Blac';\nimport { BlocBase } from './BlocBase';\nimport { BlocEventConstraint } from './types';\n\n// A should be the base type for all events this Bloc handles and must extend BlocEventConstraint\n// to access action.constructor and ensure proper event structure.\n// P is for props, changed from any to unknown.\nexport abstract class Bloc<\n S, // State type\n A extends BlocEventConstraint = BlocEventConstraint, // Base Action/Event type with proper constraints\n P = unknown, // Props type\n> extends BlocBase<S, P> {\n // Stores handlers: Map<EventConstructor (subtype of A), HandlerFunction>\n // The handler's event parameter will be correctly typed to the specific EventConstructor\n // by the 'on' method's signature.\n readonly eventHandlers: Map<\n // Key: Constructor of a specific event E (where E extends A)\n // TODO: 'any[]' is required for constructor arguments to allow flexible event instantiation.\n // Using specific parameter types would break type inference for events with different\n // constructor signatures. The 'any[]' enables polymorphic event handling while\n // maintaining type safety through the generic constraint 'E extends A'.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n new (...args: any[]) => A,\n // Value: Handler function. 'event: A' is used here for the stored function type.\n // The 'on' method ensures the specific handler (event: E) is correctly typed.\n (event: A, emit: (newState: S) => void) => void | Promise<void>\n > = new Map();\n\n /**\n * @internal\n * Event queue to ensure sequential processing of async events\n */\n private _eventQueue: A[] = [];\n\n /**\n * @internal\n * Flag indicating if an event is currently being processed\n */\n private _isProcessingEvent = false;\n\n /**\n * Registers an event handler for a specific event type.\n * This method is typically called in the constructor of a derived Bloc class.\n * @param eventConstructor The constructor of the event to handle (e.g., LoadDataEvent).\n * @param handler A function that processes the event and can emit new states.\n * The 'event' parameter in the handler will be typed to the specific eventConstructor.\n */\n protected on<E extends A>(\n // TODO: 'any[]' is required for constructor arguments (see explanation above).\n // This allows events with different constructor signatures to be handled uniformly.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n eventConstructor: new (...args: any[]) => E,\n handler: (event: E, emit: (newState: S) => void) => void | Promise<void>,\n ): void {\n if (this.eventHandlers.has(eventConstructor)) {\n // Using Blac.warn or a similar logging mechanism from BlocBase if available,\n // otherwise console.warn. Assuming this._name and this._id are available from BlocBase.\n Blac.warn(\n `[Bloc ${this._name}:${String(this._id)}] Handler for event '${eventConstructor.name}' already registered. It will be overwritten.`,\n );\n }\n // Cast the specific handler (event: E) to a more general (event: A) for storage.\n // This is safe because E extends A. When the handler is called with an 'action' of type A,\n // if it was originally registered for type E, 'action' must be an instance of E.\n this.eventHandlers.set(\n eventConstructor,\n handler as (\n event: A,\n emit: (newState: S) => void,\n ) => void | Promise<void>,\n );\n }\n\n /**\n * Dispatches an action/event to the Bloc.\n * Events are queued and processed sequentially to prevent race conditions.\n * @param action The action/event instance to be processed.\n */\n public add = async (action: A): Promise<void> => {\n // Add event to queue\n this._eventQueue.push(action);\n\n // If not already processing, start processing the queue\n if (!this._isProcessingEvent) {\n await this._processEventQueue();\n }\n };\n\n /**\n * @internal\n * Processes events from the queue sequentially\n */\n private async _processEventQueue(): Promise<void> {\n // Prevent concurrent processing\n if (this._isProcessingEvent) {\n return;\n }\n\n this._isProcessingEvent = true;\n\n try {\n while (this._eventQueue.length > 0) {\n const action = this._eventQueue.shift()!;\n await this._processEvent(action);\n }\n } finally {\n this._isProcessingEvent = false;\n }\n }\n\n /**\n * @internal\n * Processes a single event\n */\n private async _processEvent(action: A): Promise<void> {\n // Using 'any[]' for constructor arguments for broader compatibility.\n // TODO: Type assertion required to cast action.constructor to proper event constructor type.\n // JavaScript's constructor property returns 'Function', but we need the specific event\n // constructor type to look up handlers. This is safe because we validate the action\n // extends the BlocEventConstraint interface.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const eventConstructor = action.constructor as new (...args: any[]) => A;\n const handler = this.eventHandlers.get(eventConstructor);\n\n if (handler) {\n // Define the 'emit' function that handlers will use to update state.\n // It captures the current state ('this.state') right before each emission\n // to provide the correct 'previousState' to _pushState.\n const emit = (newState: S): void => {\n const previousState = this.state; // State just before this specific emission\n // The 'action' passed to _pushState is the original action that triggered the handler,\n // providing context for the state change (e.g., for logging or plugins).\n this._pushState(newState, previousState, action);\n };\n\n try {\n // Await the handler in case it's an async function (e.g., performs API calls).\n // The 'action' is passed to the handler, and due to the way 'on' is typed,\n // the 'event' parameter within the handler function will be correctly\n // typed to its specific class (e.g., LoadMyFeatureData).\n await handler(action, emit);\n } catch (error) {\n // Enhanced error handling with better context\n const constructorName =\n (action.constructor as { name?: string }).name ||\n 'UnnamedConstructor';\n const errorContext = {\n blocName: this._name,\n blocId: String(this._id),\n eventType: constructorName,\n currentState: this.state,\n action: action,\n timestamp: new Date().toISOString(),\n };\n\n Blac.error(\n `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${constructorName}':`,\n error,\n 'Context:',\n errorContext,\n );\n\n // TODO: Consider implementing error boundary pattern\n // For now, we log and continue, but applications may want to:\n // 1. Emit an error state\n // 2. Re-throw the error\n // 3. Call an error handler callback\n\n // Optional: Re-throw for critical errors (can be configured)\n if (error instanceof Error && error.name === 'CriticalError') {\n throw error;\n }\n }\n } else {\n // Enhanced warning with more context\n const constructorName =\n (action.constructor as { name?: string }).name || 'UnnamedConstructor';\n Blac.warn(\n `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${constructorName}'.`,\n 'Registered handlers:',\n Array.from(this.eventHandlers.keys()).map((k) => k.name),\n 'Action was:',\n action,\n );\n }\n }\n}\n","import { Blac } from './Blac';\nimport { BlocBase } from './BlocBase';\n\n/**\n * A Cubit is a simpler version of a Bloc that doesn't handle events.\n * It manages state and provides methods to update it.\n * @template S - The type of state this Cubit manages\n * @template P - The type of parameters (optional, defaults to null)\n */\nexport abstract class Cubit<S, P = null> extends BlocBase<S, P> {\n /**\n * Updates the current state and notifies all observers of the change.\n * If the new state is identical to the current state (using Object.is),\n * no update will occur.\n * @param state - The new state to set\n */\n emit(state: S): void {\n if (Object.is(state, this.state)) {\n return;\n }\n\n const oldState = this.state;\n const newState = state;\n this._pushState(newState, oldState);\n }\n\n /**\n * Partially updates the current state by merging it with the provided state patch.\n * This method is only applicable when the state is an object type.\n *\n * @param statePatch - A partial state object containing only the properties to update\n * @param ignoreChangeCheck - If true, skips checking if the state has actually changed\n * @throws {TypeError} If the state is not an object type\n */\n patch(\n statePatch: S extends object ? Partial<S> : S,\n ignoreChangeCheck = false,\n ): void {\n if (typeof this.state !== 'object' || this.state === null) {\n Blac.warn(\n 'Cubit.patch: was called on a cubit where the state is not an object. This is a no-op.',\n );\n return;\n }\n\n let changes = false;\n if (!ignoreChangeCheck) {\n for (const key in statePatch) {\n if (Object.prototype.hasOwnProperty.call(statePatch, key)) {\n const s = this.state;\n const current = s[key as keyof S];\n if (!Object.is(statePatch[key as keyof S], current)) {\n changes = true;\n break;\n }\n }\n }\n } else {\n changes = true;\n }\n\n if (changes) {\n this.emit({\n ...this.state,\n ...(statePatch as Partial<S>),\n } as S);\n }\n }\n}\n","import { Blac } from './Blac';\nimport { Bloc } from './Bloc';\nimport { BlocBase } from './BlocBase';\nimport { Cubit } from './Cubit';\nimport { BlocEventConstraint } from './types';\n\n/**\n * Test utilities for Blac state management\n */\nexport class BlocTest {\n private static originalInstance: Blac;\n\n /**\n * Sets up a clean test environment\n */\n static setUp(): void {\n this.originalInstance = Blac.instance;\n Blac.resetInstance();\n Blac.enableLog = false; // Disable logging in tests by default\n }\n\n /**\n * Tears down the test environment and restores original state\n */\n static tearDown(): void {\n Blac.resetInstance();\n // Note: Cannot restore original instance due to singleton pattern\n // Tests should use setUp/tearDown properly to manage state\n }\n\n /**\n * Creates a test bloc with automatic cleanup\n */\n static createBloc<T extends BlocBase<any>>(\n BlocClass: new (...args: any[]) => T,\n ...args: any[]\n ): T {\n const bloc = new BlocClass(...args);\n Blac.activateBloc(bloc);\n return bloc;\n }\n\n /**\n * Waits for a bloc to emit a specific state\n */\n static async waitForState<T extends BlocBase<S>, S>(\n bloc: T,\n predicate: (state: S) => boolean,\n timeout = 5000,\n ): Promise<S> {\n return new Promise<S>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(\n new Error(\n `Timeout waiting for state matching predicate after ${timeout}ms`,\n ),\n );\n }, timeout);\n\n const unsubscribe = bloc._observer.subscribe({\n id: `test-waiter-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n fn: (newState: S) => {\n if (predicate(newState)) {\n clearTimeout(timeoutId);\n unsubscribe();\n resolve(newState);\n }\n },\n });\n\n // Check current state immediately\n if (predicate(bloc.state)) {\n clearTimeout(timeoutId);\n unsubscribe();\n resolve(bloc.state);\n }\n });\n }\n\n /**\n * Expects a bloc to emit specific states in order\n */\n static async expectStates<T extends BlocBase<S>, S>(\n bloc: T,\n expectedStates: S[],\n timeout = 5000,\n ): Promise<void> {\n const receivedStates: S[] = [];\n\n return new Promise<void>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(\n new Error(\n `Timeout waiting for states. Expected: ${JSON.stringify(expectedStates)}, ` +\n `Received: ${JSON.stringify(receivedStates)}`,\n ),\n );\n }, timeout);\n\n const unsubscribe = bloc._observer.subscribe({\n id: `test-expecter-${crypto.randomUUID()}`,\n fn: (newState: S) => {\n receivedStates.push(newState);\n\n // Check if we have all expected states\n if (receivedStates.length === expectedStates.length) {\n clearTimeout(timeoutId);\n unsubscribe();\n\n // Verify all states match using deep equality\n for (let i = 0; i < expectedStates.length; i++) {\n const expected = expectedStates[i];\n const received = receivedStates[i];\n\n // Use JSON comparison for deep equality\n if (JSON.stringify(expected) !== JSON.stringify(received)) {\n reject(\n new Error(\n `State mismatch at index ${i}. Expected: ${JSON.stringify(expected)}, ` +\n `Received: ${JSON.stringify(received)}`,\n ),\n );\n return;\n }\n }\n\n resolve();\n }\n },\n });\n });\n }\n}\n\n/**\n * Mock Bloc for testing\n */\nexport class MockBloc<\n S,\n A extends BlocEventConstraint = BlocEventConstraint,\n> extends Bloc<S, A> {\n private mockHandlers = new Map<\n string,\n (event: A, emit: (newState: S) => void) => void | Promise<void>\n >();\n\n constructor(initialState: S) {\n super(initialState);\n }\n\n /**\n * Mock an event handler for testing\n */\n mockEventHandler<E extends A>(\n eventConstructor: new (...args: any[]) => E,\n handler: (event: E, emit: (newState: S) => void) => void | Promise<void>,\n ): void {\n // Use the on method to register the mock handler\n this.on(eventConstructor, handler);\n }\n\n /**\n * Get the number of registered handlers\n */\n getHandlerCount(): number {\n return this.eventHandlers.size;\n }\n\n /**\n * Check if a handler is registered for an event type\n */\n hasHandler(eventConstructor: new (...args: any[]) => A): boolean {\n return this.eventHandlers.has(eventConstructor);\n }\n}\n\n/**\n * Mock Cubit for testing\n */\nexport class MockCubit<S> extends Cubit<S> {\n private stateHistory: S[] = [];\n\n constructor(initialState: S) {\n super(initialState);\n this.stateHistory.push(initialState);\n }\n\n /**\n * Override emit to track state history\n */\n emit(newState: S): void {\n this.stateHistory.push(newState);\n super.emit(newState);\n }\n\n /**\n * Get the history of all states\n */\n getStateHistory(): S[] {\n return [...this.stateHistory];\n }\n\n /**\n * Clear state history\n */\n clearStateHistory(): void {\n this.stateHistory = [this.state];\n }\n}\n\n/**\n * Memory leak detector for tests\n */\nexport class MemoryLeakDetector {\n private initialStats: ReturnType<typeof Blac.getMemoryStats>;\n\n constructor() {\n this.initialStats = Blac.getMemoryStats();\n }\n\n /**\n * Check for memory leaks and return a report\n */\n checkForLeaks(): {\n hasLeaks: boolean;\n report: string;\n stats: ReturnType<typeof Blac.getMemoryStats>;\n } {\n const currentStats = Blac.getMemoryStats();\n const hasLeaks =\n currentStats.registeredBlocs > this.initialStats.registeredBlocs ||\n currentStats.isolatedBlocs > this.initialStats.isolatedBlocs ||\n currentStats.keepAliveBlocs > this.initialStats.keepAliveBlocs;\n\n const report = `\nMemory Leak Detection Report:\n- Initial registered blocs: ${this.initialStats.registeredBlocs}\n- Current registered blocs: ${currentStats.registeredBlocs}\n- Initial isolated blocs: ${this.initialStats.isolatedBlocs} \n- Current isolated blocs: ${currentStats.isolatedBlocs}\n- Initial keep-alive blocs: ${this.initialStats.keepAliveBlocs}\n- Current keep-alive blocs: ${currentStats.keepAliveBlocs}\n- Potential leaks detected: ${hasLeaks ? 'YES' : 'NO'}\n `.trim();\n\n return {\n hasLeaks,\n report,\n stats: currentStats,\n };\n }\n}\n","export interface DependencyArray {\n statePaths: string[];\n classPaths: string[];\n}\n\nexport interface TrackedValue {\n value: any;\n lastAccessTime: number;\n}\n\nexport interface ConsumerInfo {\n id: string;\n lastNotified: number;\n hasRendered: boolean;\n // Dependency tracking\n stateAccesses: Set<string>;\n classAccesses: Set<string>;\n stateValues: Map<string, TrackedValue>;\n classValues: Map<string, TrackedValue>;\n accessCount: number;\n lastAccessTime: number;\n firstAccessTime: number;\n}\n\n/**\n * ConsumerTracker manages both consumer registration and dependency tracking.\n * It uses a WeakMap for automatic garbage collection when consumers are no longer referenced.\n */\nexport class ConsumerTracker {\n private consumers = new WeakMap<object, ConsumerInfo>();\n private registrationCount = 0;\n private activeConsumers = 0;\n\n register(consumerRef: object, consumerId: string): void {\n this.registrationCount++;\n\n const existingConsumer = this.consumers.get(consumerRef);\n if (!existingConsumer) {\n this.activeConsumers++;\n }\n\n this.consumers.set(consumerRef, {\n id: consumerId,\n lastNotified: Date.now(),\n hasRendered: false,\n stateAccesses: new Set(),\n classAccesses: new Set(),\n stateValues: new Map(),\n classValues: new Map(),\n accessCount: 0,\n lastAccessTime: 0,\n firstAccessTime: 0,\n });\n }\n\n unregister(consumerRef: object): void {\n if (consumerRef) {\n const consumerInfo = this.consumers.get(consumerRef);\n if (consumerInfo) {\n this.consumers.delete(consumerRef);\n this.activeConsumers = Math.max(0, this.activeConsumers - 1);\n }\n }\n }\n\n trackAccess(\n consumerRef: object,\n type: 'state' | 'class',\n path: string,\n value?: any,\n ): void {\n const consumerInfo = this.consumers.get(consumerRef);\n if (!consumerInfo) return;\n\n const now = Date.now();\n\n if (!consumerInfo.firstAccessTime) {\n consumerInfo.firstAccessTime = now;\n }\n\n consumerInfo.accessCount++;\n consumerInfo.lastAccessTime = now;\n\n if (type === 'state') {\n consumerInfo.stateAccesses.add(path);\n if (value !== undefined) {\n consumerInfo.stateValues.set(path, { value, lastAccessTime: now });\n }\n } else {\n consumerInfo.classAccesses.add(path);\n if (value !== undefined) {\n consumerInfo.classValues.set(path, { value, lastAccessTime: now });\n }\n }\n }\n\n resetTracking(consumerRef: object): void {\n const consumerInfo = this.consumers.get(consumerRef);\n if (!consumerInfo) return;\n\n consumerInfo.stateAccesses.clear();\n consumerInfo.classAccesses.clear();\n consumerInfo.stateValues.clear();\n consumerInfo.classValues.clear();\n consumerInfo.accessCount = 0;\n consumerInfo.firstAccessTime = 0;\n }\n\n getDependencies(consumerRef: object): DependencyArray | null {\n const consumerInfo = this.consumers.get(consumerRef);\n if (!consumerInfo) return null;\n\n return {\n statePaths: Array.from(consumerInfo.stateAccesses),\n classPaths: Array.from(consumerInfo.classAccesses),\n };\n }\n\n hasValuesChanged(\n consumerRef: object,\n newState: any,\n newBlocInstance: any,\n ): boolean {\n const consumerInfo = this.consumers.get(consumerRef);\n if (!consumerInfo) return true;\n\n let hasChanged = false;\n const now = Date.now();\n\n // If we haven't tracked any values yet, consider it changed to establish baseline\n if (\n consumerInfo.stateValues.size === 0 &&\n consumerInfo.classValues.size === 0 &&\n (consumerInfo.stateAccesses.size > 0 ||\n consumerInfo.classAccesses.size > 0)\n ) {\n return true;\n }\n\n // Check state values\n for (const [path, trackedValue] of consumerInfo.stateValues) {\n try {\n const currentValue = this.getValueAtPath(newState, path);\n if (currentValue !== trackedValue.value) {\n consumerInfo.stateValues.set(path, {\n value: currentValue,\n lastAccessTime: now,\n });\n hasChanged = true;\n }\n } catch (error) {\n hasChanged = true;\n }\n }\n\n // Check class getter values\n for (const [path, trackedValue] of consumerInfo.classValues) {\n try {\n const currentValue = this.getValueAtPath(newBlocInstance, path);\n if (currentValue !== trackedValue.value) {\n consumerInfo.classValues.set(path, {\n value: currentValue,\n lastAccessTime: now,\n });\n hasChanged = true;\n }\n } catch (error) {\n hasChanged = true;\n }\n }\n\n return hasChanged;\n }\n\n shouldNotifyConsumer(\n consumerRef: object,\n changedPaths: Set<string>,\n ): boolean {\n const consumerInfo = this.consumers.get(consumerRef);\n if (!consumerInfo) return false;\n\n // Check if any changed paths match tracked dependencies\n for (const changedPath of changedPaths) {\n if (consumerInfo.stateAccesses.has(changedPath)) return true;\n if (consumerInfo.classAccesses.has(changedPath)) return true;\n\n // Check for nested path changes\n for (const trackedPath of consumerInfo.stateAccesses) {\n if (\n changedPath.startsWith(trackedPath + '.') ||\n trackedPath.startsWith(changedPath + '.')\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n updateLastNotified(consumerRef: object): void {\n const consumerInfo = this.consumers.get(consumerRef);\n if (consumerInfo) {\n consumerInfo.lastNotified = Date.now();\n }\n }\n\n getConsumerInfo(consumerRef: object): ConsumerInfo | undefined {\n return this.consumers.get(consumerRef);\n }\n\n setHasRendered(consumerRef: object, hasRendered: boolean): void {\n const consumerInfo = this.consumers.get(consumerRef);\n if (consumerInfo) {\n consumerInfo.hasRendered = hasRendered;\n }\n }\n\n hasConsumer(consumerRef: object): boolean {\n return this.consumers.has(consumerRef);\n }\n\n getStats() {\n return {\n totalRegistrations: this.registrationCount,\n activeConsumers: this.activeConsumers,\n };\n }\n\n private getValueAtPath(obj: any, path: string): any {\n const parts = path.split('.');\n let current = obj;\n\n for (const part of parts) {\n if (current == null) return undefined;\n current = current[part];\n }\n\n return current;\n }\n}\n","import { BlocBase } from '../BlocBase';\nimport { BlocState } from '../types';\n\ninterface ConsumerTracker {\n trackAccess: (\n consumerRef: object,\n type: 'state' | 'class',\n path: string,\n value?: any,\n ) => void;\n}\n\n// Cache for proxies to ensure consistent object identity\nconst proxyCache = new WeakMap<object, WeakMap<object, any>>();\n\n// Statistics tracking\nlet proxyStats = {\n stateProxiesCreated: 0,\n classProxiesCreated: 0,\n cacheHits: 0,\n cacheMisses: 0,\n propertyAccesses: 0,\n nestedProxiesCreated: 0,\n totalProxiesCreated: 0,\n createdAt: Date.now(),\n};\n\nexport class ProxyFactory {\n static createStateProxy<T extends object>(options: {\n target: T;\n consumerRef: object;\n consumerTracker: ConsumerTracker;\n path?: string;\n }): T {\n const { target, consumerRef, consumerTracker, path = '' } = options;\n\n if (!consumerRef || !consumerTracker) {\n return target;\n }\n\n if (typeof target !== 'object' || target === null) {\n return target;\n }\n\n // Check cache to ensure consistent proxy identity\n let refCache = proxyCache.get(target);\n if (!refCache) {\n refCache = new WeakMap();\n proxyCache.set(target, refCache);\n }\n\n const existingProxy = refCache.get(consumerRef);\n if (existingProxy) {\n proxyStats.cacheHits++;\n return existingProxy;\n }\n\n proxyStats.cacheMisses++;\n\n const handler: ProxyHandler<T> = {\n get(obj: T, prop: string | symbol): any {\n // Handle symbols and special properties\n if (typeof prop === 'symbol' || prop === 'constructor') {\n return Reflect.get(obj, prop);\n }\n\n const fullPath = path ? `${path}.${prop}` : prop;\n proxyStats.propertyAccesses++;\n\n const value = Reflect.get(obj, prop);\n const valueType = typeof value;\n const isObject = value && valueType === 'object' && value !== null;\n\n // Track the access with value (only for primitives at root level)\n const trackValue = !isObject ? value : undefined;\n consumerTracker.trackAccess(consumerRef, 'state', fullPath, trackValue);\n\n // Recursively proxy nested objects and arrays\n if (value && typeof value === 'object' && value !== null) {\n // Support arrays, plain objects, and other object types\n const isPlainObject =\n Object.getPrototypeOf(value) === Object.prototype;\n const isArray = Array.isArray(value);\n\n if (isPlainObject || isArray) {\n proxyStats.nestedProxiesCreated++;\n return ProxyFactory.createStateProxy({\n target: value,\n consumerRef,\n consumerTracker,\n path: fullPath,\n });\n }\n }\n\n return value;\n },\n\n has(obj: T, prop: string | symbol): boolean {\n return prop in obj;\n },\n\n ownKeys(obj: T): (string | symbol)[] {\n return Reflect.ownKeys(obj);\n },\n\n getOwnPropertyDescriptor(\n obj: T,\n prop: string | symbol,\n ): PropertyDescriptor | undefined {\n return Reflect.getOwnPropertyDescriptor(obj, prop);\n },\n\n set(): boolean {\n // State should not be mutated directly. Use emit() or patch() methods.\n return false;\n },\n\n deleteProperty(): boolean {\n // State properties should not be deleted directly.\n return false;\n },\n };\n\n const proxy = new Proxy(target, handler);\n refCache.set(consumerRef, proxy);\n\n proxyStats.stateProxiesCreated++;\n proxyStats.totalProxiesCreated++;\n\n return proxy;\n }\n\n static createClassProxy<T extends object>(options: {\n target: T;\n consumerRef: object;\n consumerTracker: ConsumerTracker;\n }): T {\n const { target, consumerRef, consumerTracker } = options;\n\n if (!consumerRef || !consumerTracker) {\n return target;\n }\n\n // Check cache for class proxies\n let refCache = proxyCache.get(target);\n if (!refCache) {\n refCache = new WeakMap();\n proxyCache.set(target, refCache);\n }\n\n const existingProxy = refCache.get(consumerRef);\n if (existingProxy) {\n proxyStats.cacheHits++;\n return existingProxy;\n }\n\n proxyStats.cacheMisses++;\n\n const handler: ProxyHandler<T> = {\n get(obj: T, prop: string | symbol): any {\n const value = Reflect.get(obj, prop);\n // Check for getter on the prototype chain with safety limits\n let isGetter = false;\n let currentObj: any = obj;\n const visitedPrototypes = new WeakSet();\n const MAX_PROTOTYPE_DEPTH = 10; // Reasonable depth limit\n let depth = 0;\n\n while (currentObj && !isGetter && depth < MAX_PROTOTYPE_DEPTH) {\n // Check for circular references\n if (visitedPrototypes.has(currentObj)) {\n break;\n }\n visitedPrototypes.add(currentObj);\n\n try {\n const descriptor = Object.getOwnPropertyDescriptor(\n currentObj,\n prop,\n );\n if (descriptor && descriptor.get) {\n isGetter = true;\n break;\n }\n currentObj = Object.getPrototypeOf(currentObj);\n depth++;\n } catch (error) {\n break;\n }\n }\n\n if (!isGetter) {\n // bind methods to the object if they are functions\n /*\n if (typeof value === 'function') {\n proxyStats.propertyAccesses++;\n console.log(\n `🏭 [ProxyFactory] 🔧 Method accessed: ${String(prop)}`,\n );\n console.log(`🏭 [ProxyFactory] Binding method to object instance`);\n return value.bind(obj);\n }\n */\n\n // Return the value directly if it's not a getter or method\n return value;\n }\n\n // For getters, track access and value\n proxyStats.propertyAccesses++;\n\n // Track the getter value if it's a primitive\n const getterValue = value;\n const isGetterValuePrimitive =\n getterValue !== null && typeof getterValue !== 'object';\n const trackValue = isGetterValuePrimitive ? getterValue : undefined;\n\n // Track access with value for primitives\n consumerTracker.trackAccess(\n consumerRef,\n 'class',\n String(prop),\n trackValue,\n );\n return value;\n },\n\n has(obj: T, prop: string | symbol): boolean {\n return prop in obj;\n },\n\n ownKeys(obj: T): (string | symbol)[] {\n return Reflect.ownKeys(obj);\n },\n\n getOwnPropertyDescriptor(\n obj: T,\n prop: string | symbol,\n ): PropertyDescriptor | undefined {\n return Reflect.getOwnPropertyDescriptor(obj, prop);\n },\n };\n\n const proxy = new Proxy(target, handler);\n refCache.set(consumerRef, proxy);\n\n proxyStats.classProxiesCreated++;\n proxyStats.totalProxiesCreated++;\n\n return proxy;\n }\n\n static getProxyState<B extends BlocBase<any>>(options: {\n state: BlocState<B>;\n consumerRef: object;\n consumerTracker: ConsumerTracker;\n }): BlocState<B> {\n return ProxyFactory.createStateProxy({\n target: options.state,\n consumerRef: options.consumerRef,\n consumerTracker: options.consumerTracker,\n });\n }\n\n static getProxyBlocInstance<B extends BlocBase<any>>(options: {\n blocInstance: B;\n consumerRef: object;\n consumerTracker: ConsumerTracker;\n }): B {\n return ProxyFactory.createClassProxy({\n target: options.blocInstance,\n consumerRef: options.consumerRef,\n consumerTracker: options.consumerTracker,\n });\n }\n\n static getStats() {\n const lifetime = Date.now() - proxyStats.createdAt;\n return {\n ...proxyStats,\n totalProxies:\n proxyStats.stateProxiesCreated + proxyStats.classProxiesCreated,\n cacheEfficiency:\n proxyStats.cacheHits + proxyStats.cacheMisses > 0\n ? `${((proxyStats.cacheHits / (proxyStats.cacheHits + proxyStats.cacheMisses)) * 100).toFixed(1)}%`\n : 'N/A',\n lifetime: `${lifetime}ms`,\n proxiesPerSecond:\n lifetime > 0\n ? (proxyStats.totalProxiesCreated / (lifetime / 1000)).toFixed(2)\n : 'N/A',\n };\n }\n\n static resetStats() {\n proxyStats = {\n stateProxiesCreated: 0,\n classProxiesCreated: 0,\n cacheHits: 0,\n cacheMisses: 0,\n propertyAccesses: 0,\n nestedProxiesCreated: 0,\n totalProxiesCreated: 0,\n createdAt: Date.now(),\n };\n }\n}\n","import { Blac } from '../Blac';\nimport { BlocBase } from '../BlocBase';\nimport { BlocConstructor, BlocState, InferPropsFromGeneric } from '../types';\nimport { generateUUID } from '../utils/uuid';\nimport { ConsumerTracker, DependencyArray } from './ConsumerTracker';\nimport { ProxyFactory } from './ProxyFactory';\n\nexport interface AdapterOptions<B extends BlocBase<any>> {\n id?: string;\n dependencies?: (bloc: B) => unknown[];\n props?: InferPropsFromGeneric<B>;\n onMount?: (bloc: B) => void;\n onUnmount?: (bloc: B) => void;\n}\n\n/**\n * BlacAdapter orchestrates the connection between Bloc instances and React components.\n * It manages dependency tracking, lifecycle hooks, and proxy creation.\n */\nexport class BlacAdapter<B extends BlocConstructor<BlocBase<any>>> {\n public readonly id = `consumer-${generateUUID()}`;\n public readonly blocConstructor: B;\n public readonly componentRef: { current: object } = { current: {} };\n public blocInstance: InstanceType<B>;\n\n // Core components\n private consumerTracker: ConsumerTracker;\n\n unmountTime: number = 0;\n mountTime: number = 0;\n\n // Dependency tracking\n private dependencyValues?: unknown[];\n private isUsingDependencies: boolean = false;\n\n // Lifecycle state\n private hasMounted = false;\n private mountCount = 0;\n\n options?: AdapterOptions<InstanceType<B>>;\n\n constructor(\n instanceProps: { componentRef: { current: object }; blocConstructor: B },\n options?: typeof this.options,\n ) {\n this.options = options;\n this.blocConstructor = instanceProps.blocConstructor;\n this.componentRef = instanceProps.componentRef;\n this.isUsingDependencies = !!options?.dependencies;\n\n // Initialize consumer tracker\n this.consumerTracker = new ConsumerTracker();\n\n // Initialize bloc instance and register consumer\n this.blocInstance = this.updateBlocInstance();\n this.consumerTracker.register(instanceProps.componentRef.current, this.id);\n\n // Initialize dependency values if using dependencies\n if (this.isUsingDependencies && options?.dependencies) {\n this.dependencyValues = options.dependencies(this.blocInstance);\n }\n }\n\n trackAccess(\n consumerRef: object,\n type: 'state' | 'class',\n path: string,\n value?: any,\n ): void {\n this.consumerTracker.trackAccess(consumerRef, type, path, value);\n }\n\n getConsumerDependencies(consumerRef: object): DependencyArray | null {\n return this.consumerTracker.getDependencies(consumerRef);\n }\n\n shouldNotifyConsumer(\n consumerRef: object,\n changedPaths: Set<string>,\n ): boolean {\n const consumerInfo = this.consumerTracker.getConsumerInfo(consumerRef);\n if (!consumerInfo) {\n return true; // If consumer not registered yet, notify by default\n }\n\n // First render - always notify to establish baseline\n if (!consumerInfo.hasRendered) {\n return true;\n }\n\n // Use built-in method from ConsumerTracker\n return this.consumerTracker.shouldNotifyConsumer(consumerRef, changedPaths);\n }\n\n updateLastNotified(consumerRef: object): void {\n this.consumerTracker.updateLastNotified(consumerRef);\n this.consumerTracker.setHasRendered(consumerRef, true);\n }\n\n resetConsumerTracking(): void {\n this.consumerTracker.resetTracking(this.componentRef.current);\n }\n\n createStateProxy = <T extends object>(props: { target: T }): T => {\n return ProxyFactory.createStateProxy({\n target: props.target,\n consumerRef: this.componentRef.current,\n consumerTracker: this as any,\n });\n };\n\n createClassProxy = <T extends object>(props: { target: T }): T => {\n return ProxyFactory.createClassProxy({\n target: props.target,\n consumerRef: this.componentRef.current,\n consumerTracker: this as any,\n });\n };\n\n updateBlocInstance(): InstanceType<B> {\n this.blocInstance = Blac.instance.getBloc<B>(this.blocConstructor, {\n props: this.options?.props,\n id: this.options?.id,\n instanceRef: this.id,\n });\n return this.blocInstance;\n }\n\n createSubscription = (options: { onChange: () => void }) => {\n const unsubscribe = this.blocInstance._observer.subscribe({\n id: this.id,\n fn: (\n newState: BlocState<InstanceType<B>>,\n oldState: BlocState<InstanceType<B>>,\n ) => {\n // Handle dependency-based change detection\n if (this.isUsingDependencies && this.options?.dependencies) {\n const newValues = this.options.dependencies(this.blocInstance);\n const hasChanged = this.hasDependencyValuesChanged(\n this.dependencyValues,\n newValues,\n );\n\n if (!hasChanged) {\n return; // Don't trigger re-render\n }\n\n this.dependencyValues = newValues;\n } else {\n // Check if any tracked values have changed (proxy-based tracking)\n const consumerInfo = this.consumerTracker.getConsumerInfo(\n this.componentRef.current,\n );\n if (consumerInfo && consumerInfo.hasRendered) {\n // Only check dependencies if component has rendered at least once\n const hasChanged = this.consumerTracker.hasValuesChanged(\n this.componentRef.current,\n newState,\n this.blocInstance,\n );\n\n if (!hasChanged) {\n return; // Don't trigger re-render\n }\n }\n }\n\n options.onChange();\n },\n });\n\n return unsubscribe;\n };\n\n mount = (): void => {\n // Re-run dependencies on mount to ensure fresh values\n if (this.isUsingDependencies && this.options?.dependencies) {\n this.dependencyValues = this.options.dependencies(this.blocInstance);\n }\n\n // Lifecycle management\n this.mountCount++;\n this.blocInstance._addConsumer(this.id, this.componentRef.current);\n\n // Call onMount callback if provided and not already called\n if (!this.hasMounted) {\n this.hasMounted = true;\n this.mountTime = Date.now();\n\n if (this.options?.onMount) {\n try {\n this.options.onMount(this.blocInstance);\n } catch (error) {\n throw error;\n }\n }\n }\n };\n\n unmount = (): void => {\n this.unmountTime = Date.now();\n this.consumerTracker.unregister(this.componentRef.current);\n this.blocInstance._removeConsumer(this.id);\n\n // Call onUnmount callback\n if (this.options?.onUnmount) {\n try {\n this.options.onUnmount(this.blocInstance);\n } catch (error) {\n // Don't re-throw on unmount to allow cleanup to continue\n }\n }\n };\n\n getProxyState = (\n state: BlocState<InstanceType<B>>,\n ): BlocState<InstanceType<B>> => {\n if (this.isUsingDependencies) {\n return state; // Return raw state when using dependencies\n }\n\n return ProxyFactory.getProxyState({\n state,\n consumerRef: this.componentRef.current,\n consumerTracker: this as any,\n });\n };\n\n getProxyBlocInstance = (): InstanceType<B> => {\n if (this.isUsingDependencies) {\n return this.blocInstance; // Return raw instance when using dependencies\n }\n\n return ProxyFactory.getProxyBlocInstance({\n blocInstance: this.blocInstance,\n consumerRef: this.componentRef.current,\n consumerTracker: this as any,\n });\n };\n\n // Expose calledOnMount for backward compatibility\n get calledOnMount(): boolean {\n return this.hasMounted;\n }\n\n private hasDependencyValuesChanged(\n prev: unknown[] | undefined,\n next: unknown[],\n ): boolean {\n if (!prev) return true; // First run, always trigger\n if (prev.length !== next.length) return true;\n\n // Use Object.is for comparison (handles NaN, +0/-0 correctly)\n for (let i = 0; i < prev.length; i++) {\n if (!Object.is(prev[i], next[i])) {\n return true;\n }\n }\n\n return false;\n }\n}\n"],"names":["BlacObservable","bloc","__publicField","observer","disposalState","BlocLifecycleState","Blac","newState","oldState","action","shouldUpdate","lastDependencyCheck","newDependencyCheck","i","generateUUID","c","r","BlocBase","initialState","deadConsumers","consumerId","weakRef","id","originalId","consumerRef","_a","_b","batchFn","result","finalUpdate","Constructor","expectedState","previousState","_c","_d","transitionResult","error","handler","_SingletonBlacManager","instance","oldInstance","SingletonBlacManager","instanceManager","setBlacInstanceManager","manager","_Blac","options","args","message","oldBlocInstanceMap","oldIsolatedBlocMap","blocArray","currentState","base","key","blocClass","forceNewInstance","blocId","isolatedBloc","registeredBloc","isIsolated","registered","results","blocInstance","isolatedBlocs","toDispose","predicate","blocs","sum","arr","__unsafe_ignore_singleton","blocClassName","wasRemoved","index","b","wasInIndex","uid","props","instanceRef","newBloc","Bloc","eventConstructor","emit","constructorName","errorContext","k","Cubit","state","statePatch","ignoreChangeCheck","changes","current","BlocTest","BlocClass","timeout","resolve","reject","timeoutId","unsubscribe","expectedStates","receivedStates","expected","received","MockBloc","MockCubit","MemoryLeakDetector","currentStats","hasLeaks","report","ConsumerTracker","type","path","value","consumerInfo","now","newBlocInstance","hasChanged","trackedValue","currentValue","changedPaths","changedPath","trackedPath","hasRendered","obj","parts","part","proxyCache","proxyStats","ProxyFactory","target","consumerTracker","refCache","existingProxy","prop","fullPath","trackValue","isPlainObject","isArray","proxy","isGetter","currentObj","visitedPrototypes","MAX_PROTOTYPE_DEPTH","depth","descriptor","getterValue","lifetime","BlacAdapter","instanceProps","newValues","prev","next"],"mappings":"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"}
|