@blac/core 2.0.0-rc-13 → 2.0.0-rc-16

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.
Files changed (54) hide show
  1. package/package.json +10 -15
  2. package/src/Blac.ts +38 -71
  3. package/src/Bloc.ts +8 -9
  4. package/src/BlocBase.ts +246 -540
  5. package/src/Cubit.ts +1 -16
  6. package/src/__tests__/Blac.config.test.ts +10 -17
  7. package/src/__tests__/Bloc.event.test.ts +27 -52
  8. package/src/__tests__/BlocBase.subscription.test.ts +349 -0
  9. package/src/__tests__/Cubit.test.ts +39 -50
  10. package/src/__tests__/memory-leaks.test.ts +383 -0
  11. package/src/__tests__/plugins.test.ts +107 -97
  12. package/src/adapter/BlacAdapter.ts +347 -207
  13. package/src/adapter/ProxyFactory.ts +196 -255
  14. package/src/adapter/__tests__/BlacAdapter.test.ts +71 -77
  15. package/src/adapter/__tests__/ProxyFactory.test.ts +1 -1
  16. package/src/adapter/index.ts +0 -1
  17. package/src/errors/BlacError.ts +69 -0
  18. package/src/errors/ErrorManager.ts +101 -0
  19. package/src/errors/handleError.ts +114 -0
  20. package/src/errors/index.ts +13 -0
  21. package/src/events.ts +7 -1
  22. package/src/index.ts +7 -1
  23. package/src/lifecycle/BlocLifecycle.ts +156 -0
  24. package/src/lifecycle/index.ts +1 -0
  25. package/src/plugins/BlocPluginRegistry.ts +71 -51
  26. package/src/plugins/SystemPluginRegistry.ts +63 -13
  27. package/src/plugins/__tests__/BlocPluginRegistry.test.ts +450 -0
  28. package/src/plugins/__tests__/SystemPluginRegistry.test.ts +404 -0
  29. package/src/plugins/types.ts +32 -3
  30. package/src/subscription/README.md +132 -0
  31. package/src/subscription/SubscriptionManager.ts +395 -0
  32. package/src/subscription/__tests__/SubscriptionManager.test.ts +355 -0
  33. package/src/subscription/index.ts +2 -0
  34. package/src/subscription/types.ts +90 -0
  35. package/src/testing.ts +31 -37
  36. package/src/types.ts +4 -21
  37. package/src/utils/BatchingManager.ts +59 -0
  38. package/src/utils/RerenderLogger.ts +265 -0
  39. package/src/utils/__tests__/generateInstanceId.test.ts +104 -0
  40. package/src/utils/__tests__/shallowEqual.test.ts +171 -0
  41. package/src/utils/__tests__/uuid.test.ts +144 -0
  42. package/src/utils/generateInstanceId.ts +54 -0
  43. package/src/utils/shallowEqual.ts +1 -1
  44. package/README.md +0 -329
  45. package/dist/index.cjs.js +0 -11
  46. package/dist/index.cjs.js.map +0 -1
  47. package/dist/index.d.ts +0 -1078
  48. package/dist/index.es.js +0 -1992
  49. package/dist/index.es.js.map +0 -1
  50. package/src/BlacObserver.ts +0 -189
  51. package/src/__tests__/BlocBase.lifecycle.test.ts +0 -441
  52. package/src/__tests__/props.test.ts +0 -256
  53. package/src/adapter/ConsumerTracker.ts +0 -241
  54. package/src/adapter/__tests__/ConsumerTracker.test.ts +0 -562
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Generates a deterministic instance ID from static props by extracting primitive values
3
+ *
4
+ * Rules:
5
+ * 1. Only considers primitive types: string, number, boolean, null, undefined
6
+ * 2. Ignores complex types: objects, arrays, functions, symbols
7
+ * 3. Sorts keys alphabetically for deterministic output
8
+ * 4. Returns undefined if no primitives found (caller should use default ID)
9
+ */
10
+ export function generateInstanceIdFromProps(
11
+ props: unknown,
12
+ ): string | undefined {
13
+ if (!props || typeof props !== 'object') {
14
+ return undefined;
15
+ }
16
+
17
+ const primitives: Array<[string, unknown]> = [];
18
+
19
+ // Extract primitive values
20
+ for (const [key, value] of Object.entries(props)) {
21
+ const type = typeof value;
22
+ if (
23
+ type === 'string' ||
24
+ type === 'number' ||
25
+ type === 'boolean' ||
26
+ value === null ||
27
+ value === undefined
28
+ ) {
29
+ primitives.push([key, value]);
30
+ }
31
+ }
32
+
33
+ // No primitives found
34
+ if (primitives.length === 0) {
35
+ return undefined;
36
+ }
37
+
38
+ // Sort by key for deterministic output
39
+ primitives.sort(([a], [b]) => a.localeCompare(b));
40
+
41
+ // Create instance ID
42
+ const parts: string[] = [];
43
+ for (const [key, value] of primitives) {
44
+ if (value === null) {
45
+ parts.push(`${key}:null`);
46
+ } else if (value === undefined) {
47
+ parts.push(`${key}:undefined`);
48
+ } else {
49
+ parts.push(`${key}:${String(value)}`);
50
+ }
51
+ }
52
+
53
+ return parts.join('|');
54
+ }
@@ -37,4 +37,4 @@ export function shallowEqual(a: any, b: any): boolean {
37
37
  }
38
38
 
39
39
  return true;
40
- }
40
+ }
package/README.md DELETED
@@ -1,329 +0,0 @@
1
- # @blac/core
2
-
3
- A lightweight, flexible state management library for JavaScript/TypeScript applications focusing on predictable state transitions.
4
-
5
- ## Features
6
-
7
- - 🔄 Predictable unidirectional data flow
8
- - 🧩 Modular architecture with Blocs and Cubits
9
- - 🧪 Unit test friendly
10
- - 🔒 Isolated state instances when needed
11
- - 🔌 Plugin system for extensibility
12
-
13
- ## Installation
14
-
15
- Install `@blac/core` using your favorite package manager:
16
-
17
- ```bash
18
- # pnpm
19
- pnpm add @blac/core
20
-
21
- # yarn
22
- yarn add @blac/core
23
-
24
- # npm
25
- npm install @blac/core
26
- ```
27
-
28
- ## Configuration
29
-
30
- BlaC provides global configuration options to customize its behavior:
31
-
32
- ```typescript
33
- import { Blac } from '@blac/core';
34
-
35
- // Configure BlaC before using it
36
- Blac.setConfig({
37
- // Enable/disable automatic dependency tracking for optimized re-renders
38
- proxyDependencyTracking: true, // default: true
39
-
40
- // Expose Blac instance globally for debugging
41
- exposeBlacInstance: false // default: false
42
- });
43
-
44
- // Read current configuration
45
- const config = Blac.config;
46
- console.log(config.proxyDependencyTracking); // true
47
- ```
48
-
49
- ### Configuration Options
50
-
51
- - **`proxyDependencyTracking`**: When enabled (default), BlaC automatically tracks which state properties your components access and only triggers re-renders when those specific properties change. Disable this for simpler behavior where any state change triggers re-renders.
52
-
53
- - **`exposeBlacInstance`**: When enabled, exposes the BlaC instance globally (useful for debugging). Not recommended for production.
54
-
55
- ## Testing
56
-
57
- Blac provides comprehensive testing utilities to make testing your state management logic simple and powerful:
58
-
59
- ```typescript
60
- import { BlocTest, MockCubit, MemoryLeakDetector } from '@blac/core';
61
-
62
- describe('Counter Tests', () => {
63
- beforeEach(() => BlocTest.setUp());
64
- afterEach(() => BlocTest.tearDown());
65
-
66
- it('should increment counter', async () => {
67
- const counter = BlocTest.createBloc(CounterCubit);
68
-
69
- counter.increment();
70
-
71
- expect(counter.state.count).toBe(1);
72
- });
73
-
74
- it('should track state history', () => {
75
- const mockCubit = new MockCubit({ count: 0 });
76
-
77
- mockCubit.emit({ count: 1 });
78
- mockCubit.emit({ count: 2 });
79
-
80
- const history = mockCubit.getStateHistory();
81
- expect(history).toHaveLength(3); // Initial + 2 emissions
82
- });
83
-
84
- it('should detect memory leaks', () => {
85
- const detector = new MemoryLeakDetector();
86
-
87
- // Create and use blocs...
88
-
89
- const result = detector.checkForLeaks();
90
- expect(result.hasLeaks).toBe(false);
91
- });
92
- });
93
- ```
94
-
95
- **[📚 View Complete Testing Documentation](./docs/testing.md)**
96
-
97
- ## Core Concepts
98
-
99
- ### Blocs and Cubits
100
-
101
- **Cubit**: A simple state container with methods to emit new states.
102
-
103
- ```typescript
104
- class CounterCubit extends Cubit<number> {
105
- constructor() {
106
- super(0); // Initial state
107
- }
108
-
109
- increment = () => {
110
- this.emit(this.state + 1);
111
- }
112
-
113
- decrement = () => {
114
- this.emit(this.state - 1);
115
- }
116
- }
117
- ```
118
-
119
- **Bloc**: More powerful state container that uses an event-handler pattern for type-safe, event-driven state transitions. Events (instances of classes) are dispatched via `this.add()`, and handlers are registered using `this.on(EventClass, handler)`.
120
-
121
- ```typescript
122
- // Define event classes
123
- class IncrementEvent { constructor(public readonly amount: number = 1) {} }
124
- class DecrementEvent { constructor(public readonly amount: number = 1) {} }
125
-
126
- // Optional: Union type for all events
127
- type CounterEvent = IncrementEvent | DecrementEvent;
128
-
129
- class CounterBloc extends Bloc<number, CounterEvent> {
130
- constructor() {
131
- super(0); // Initial state
132
-
133
- // Register event handlers
134
- this.on(IncrementEvent, (event, emit) => {
135
- emit(this.state + event.amount);
136
- });
137
-
138
- this.on(DecrementEvent, (event, emit) => {
139
- emit(this.state - event.amount);
140
- });
141
- }
142
-
143
- // Helper methods to dispatch event instances (optional)
144
- increment = (amount = 1) => {
145
- this.add(new IncrementEvent(amount));
146
- }
147
-
148
- decrement = (amount = 1) => {
149
- this.add(new DecrementEvent(amount));
150
- }
151
- }
152
- ```
153
-
154
- ### Important: Arrow Functions Required
155
-
156
- All methods in Bloc or Cubit classes must use arrow function syntax (`method = () => {}`) instead of the traditional method syntax (`method() {}`). This is because arrow functions automatically bind `this` to the class instance. Without this binding, methods called from React components would lose their context and could not access instance properties like `this.state` or `this.emit()`.
157
-
158
- ### State Management Patterns
159
-
160
- #### Shared State (Default)
161
-
162
- By default, bloc instances are shared across all consumers:
163
-
164
- ```typescript
165
- class GlobalCounterCubit extends Cubit<number> {
166
- constructor() {
167
- super(0);
168
- }
169
-
170
- increment = () => {
171
- this.emit(this.state + 1);
172
- }
173
- }
174
- ```
175
-
176
- #### Isolated State
177
-
178
- When each consumer needs its own state instance:
179
-
180
- ```typescript
181
- class LocalCounterCubit extends Cubit<number> {
182
- static isolated = true; // Each consumer gets its own instance
183
-
184
- constructor() {
185
- super(0);
186
- }
187
-
188
- increment = () => {
189
- this.emit(this.state + 1);
190
- }
191
- }
192
- ```
193
-
194
- #### Persistent State
195
-
196
- Keep state alive even when no consumers are using it:
197
-
198
- ```typescript
199
- class PersistentCounterCubit extends Cubit<number> {
200
- static keepAlive = true; // State persists even when no consumers
201
-
202
- constructor() {
203
- super(0);
204
- }
205
-
206
- increment = () => {
207
- this.emit(this.state + 1);
208
- }
209
- }
210
- ```
211
-
212
- ## Advanced Usage
213
-
214
- ### Custom Plugins
215
-
216
- Create plugins to add functionality like logging, persistence, or analytics:
217
-
218
- ```typescript
219
- import { BlacPlugin, BlacLifecycleEvent, BlocBase } from '@blac/core';
220
-
221
- class LoggerPlugin implements BlacPlugin {
222
- name = 'LoggerPlugin';
223
-
224
- onEvent(event: BlacLifecycleEvent, bloc: BlocBase, params?: any) {
225
- if (event === BlacLifecycleEvent.STATE_CHANGED) {
226
- console.log(`[${bloc._name}] State changed:`, bloc.state);
227
- }
228
- }
229
- }
230
-
231
- // Add the plugin to Blac
232
- import { Blac } from '@blac/core';
233
- Blac.addPlugin(new LoggerPlugin());
234
- ```
235
-
236
- ### Using Props with Blocs
237
-
238
- Blocs can be designed to accept properties through their constructor, allowing for configurable instances. Here's an example of a `UserProfileBloc` that takes a `userId` prop:
239
-
240
- ```typescript
241
- import { Bloc } from '@blac/core'; // Or your specific import path
242
-
243
- // Define props interface (optional, but good practice)
244
- interface UserProfileProps {
245
- userId: string;
246
- }
247
-
248
- // Define state interface
249
- interface UserProfileState {
250
- loading: boolean;
251
- userData: { id: string; name: string; bio?: string } | null;
252
- error: string | null;
253
- }
254
-
255
- // Define Event Classes for UserProfileBloc
256
- class UserProfileFetchEvent {}
257
- class UserProfileDataLoadedEvent { constructor(public readonly data: any) {} }
258
- class UserProfileErrorEvent { constructor(public readonly error: string) {} }
259
-
260
- type UserProfileEvents = UserProfileFetchEvent | UserProfileDataLoadedEvent | UserProfileErrorEvent;
261
-
262
- class UserProfileBloc extends Bloc<UserProfileState, UserProfileEvents, UserProfileProps> {
263
- private userId: string;
264
-
265
- constructor(props: UserProfileProps) {
266
- super({ loading: true, userData: null, error: null }); // Initial state
267
- this.userId = props.userId;
268
- this._name = `UserProfileBloc_${this.userId}`;
269
-
270
- // Register event handlers
271
- this.on(UserProfileFetchEvent, this.handleFetchUserProfile);
272
- this.on(UserProfileDataLoadedEvent, (event, emit) => {
273
- emit({ ...this.state, loading: false, userData: event.data, error: null });
274
- });
275
- this.on(UserProfileErrorEvent, (event, emit) => {
276
- emit({ ...this.state, loading: false, error: event.error });
277
- });
278
-
279
- // Initial fetch
280
- this.add(new UserProfileFetchEvent());
281
- }
282
-
283
- private handleFetchUserProfile = async (_event: UserProfileFetchEvent, emit: (state: UserProfileState) => void) => {
284
- // Emit loading state directly if not already covered by initial state or another event
285
- // For this example, constructor sets loading: true, so an immediate emit here might be redundant
286
- // unless an event handler could set loading to false before this runs.
287
- // emit({ ...this.state, loading: true }); // Ensure loading is true
288
- try {
289
- await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate API call
290
- const mockUserData = { id: this.userId, name: `User ${this.userId}`, bio: 'Loves Blac states!' };
291
- this.add(new UserProfileDataLoadedEvent(mockUserData));
292
- } catch (e:any) {
293
- this.add(new UserProfileErrorEvent(e.message || 'Failed to fetch user profile'));
294
- }
295
- }
296
-
297
- // Public method to re-trigger fetch if needed
298
- refetchUserProfile = () => {
299
- this.add(new UserProfileFetchEvent());
300
- }
301
- }
302
- ```
303
-
304
- ## API Reference
305
-
306
- ### Core Classes
307
-
308
- - `BlocBase<S, P>`: Base class for state containers
309
- - `Cubit<S, P>`: Simple state container with `emit()` and `patch()`
310
- - `Bloc<S, E, P>`: Event-driven state container with `on(EventClass, handler)` and `add(eventInstance)` methods.
311
- - `Blac`: Singleton manager for all Bloc instances
312
-
313
- ### React Hooks
314
-
315
- - `useBloc<B>(BlocClass, options?)`: Connect a component to a Bloc
316
-
317
- ### Lifecycle Events
318
-
319
- - `BLOC_CREATED`: When a new Bloc is instantiated
320
- - `BLOC_DISPOSED`: When a Bloc is disposed
321
- - `LISTENER_ADDED`: When a state listener is added
322
- - `LISTENER_REMOVED`: When a state listener is removed
323
- - `STATE_CHANGED`: When state is updated
324
- - `BLOC_CONSUMER_ADDED`: When a new consumer starts using a Bloc
325
- - `BLOC_CONSUMER_REMOVED`: When a consumer stops using a Bloc
326
-
327
- ## License
328
-
329
- This project is licensed under the MIT License - see the [LICENSE](../../LICENSE) file for details.
package/dist/index.cjs.js DELETED
@@ -1,11 +0,0 @@
1
- "use strict";var q=Object.defineProperty;var K=(c,e,t)=>e in c?q(c,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):c[e]=t;var i=(c,e,t)=>K(c,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});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){const t=this.bloc._disposalState;return t===y.DISPOSED||t===y.DISPOSING?(u.log("BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.",this.bloc,e),()=>{}):(u.log("BlacObservable.subscribe: Subscribing observer.",this.bloc,e),this._observers.add(e),t===y.DISPOSAL_REQUESTED&&(u.log("BlacObservable.subscribe: Cancelling disposal due to new subscription.",this.bloc),this.bloc._atomicStateTransition(y.DISPOSAL_REQUESTED,y.ACTIVE)),()=>{u.log("BlacObservable.subscribe: Unsubscribing observer.",this.bloc,e),this.unsubscribe(e)})}unsubscribe(e){this._observers.delete(e),this.size===0&&(u.log("BlacObservable.unsubscribe: No observers left.",this.bloc),this.bloc._consumers.size===0&&!this.bloc._keepAlive&&this.bloc._disposalState===y.ACTIVE&&(u.log(`[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`),this.bloc._scheduleDisposal()))}notify(e,t,s){this._observers.forEach(r=>{let n=!1;if(r.dependencyArray){const o=r.lastState,a=r.dependencyArray(e,t,this.bloc);if(!o)n=!0;else if(o.length!==a.length)n=!0;else for(let l=0;l<a.length;l++)if(!Object.is(o[l],a[l])){n=!0;break}r.lastState=a}else n=!0;n&&r.fn(e,t,s)}),u.instance.plugins.notifyStateChanged(this.bloc,t,e)}clear(){this._observers.clear()}}function E(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(c){const e=Math.random()*16|0;return(c==="x"?e:e&3|8).toString(16)})}class R{constructor(){i(this,"plugins",new Map);i(this,"executionOrder",[]);i(this,"attached",!1)}add(e){if(this.plugins.has(e.name))throw new Error(`Plugin '${e.name}' is already registered`);e.capabilities&&this.validateCapabilities(e),this.plugins.set(e.name,e),this.executionOrder.push(e.name)}remove(e){const t=this.plugins.get(e);if(!t)return!1;if(this.attached&&t.onDetach)try{t.onDetach()}catch(s){console.error(`Plugin '${e}' error in onDetach:`,s)}return this.plugins.delete(e),this.executionOrder=this.executionOrder.filter(s=>s!==e),!0}get(e){return this.plugins.get(e)}getAll(){return this.executionOrder.map(e=>this.plugins.get(e))}clear(){if(this.attached){for(const e of this.getAll())if(e.onDetach)try{e.onDetach()}catch(t){console.error(`Plugin '${e.name}' error in onDetach:`,t)}}this.plugins.clear(),this.executionOrder=[],this.attached=!1}attach(e){if(this.attached)throw new Error("Plugins are already attached");for(const t of this.getAll())if(t.onAttach)try{t.onAttach(e)}catch(s){console.error(`Plugin '${t.name}' error in onAttach:`,s),this.remove(t.name)}this.attached=!0}transformState(e,t){let s=t;for(const r of this.getAll())if(r.transformState&&this.canTransformState(r))try{s=r.transformState(e,s)}catch(n){console.error(`Plugin '${r.name}' error in transformState:`,n)}return s}transformEvent(e){let t=e;for(const s of this.getAll()){if(t===null)break;if(s.transformEvent&&this.canInterceptEvents(s))try{t=s.transformEvent(t)}catch(r){console.error(`Plugin '${s.name}' error in transformEvent:`,r)}}return t}notifyStateChange(e,t){for(const s of this.getAll())if(s.onStateChange&&this.canReadState(s))try{s.onStateChange(e,t)}catch(r){console.error(`Plugin '${s.name}' error in onStateChange:`,r)}}notifyEvent(e){for(const t of this.getAll())if(t.onEvent&&this.canReadState(t))try{t.onEvent(e)}catch(s){console.error(`Plugin '${t.name}' error in onEvent:`,s)}}notifyError(e,t){for(const s of this.getAll())if(s.onError)try{s.onError(e,t)}catch(r){console.error(`Plugin '${s.name}' error in onError:`,r)}}validateCapabilities(e){const t=e.capabilities;if(t.transformState&&!t.readState)throw new Error(`Plugin '${e.name}': transformState requires readState capability`);if(t.interceptEvents&&!t.readState)throw new Error(`Plugin '${e.name}': interceptEvents requires readState capability`)}canReadState(e){return!e.capabilities||e.capabilities.readState!==!1}canTransformState(e){return!e.capabilities||e.capabilities.transformState===!0}canInterceptEvents(e){return!e.capabilities||e.capabilities.interceptEvents===!0}}var y=(c=>(c.ACTIVE="active",c.DISPOSAL_REQUESTED="disposal_requested",c.DISPOSING="disposing",c.DISPOSED="disposed",c))(y||{});class w{constructor(e){i(this,"uid",E());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,"_disposalRequestTime",0);i(this,"_state");i(this,"_oldState");i(this,"props",null);i(this,"_batchingLock",!1);i(this,"_pendingUpdates",[]);i(this,"_consumerRefs",new Map);i(this,"_plugins");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)=>{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)});i(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()))});i(this,"_disposalHandler");i(this,"lastUpdate",Date.now());i(this,"_batchingEnabled",!1);i(this,"_pushState",(e,t,s)=>{if(e===void 0||s!==void 0&&typeof s!="object"&&typeof s!="function")return;let r=e;try{r=this._plugins.transformState(t,e)}catch(n){this._plugins.notifyError(n,{phase:"state-change",operation:"transformState"})}if(this._batchingEnabled){this._pendingUpdates.push({newState:r,oldState:t,action:s}),this._oldState=t,this._state=r;return}this._oldState=t,this._state=r;try{this._plugins.notifyStateChange(t,r)}catch(n){console.error("Error notifying bloc plugins of state change:",n)}this._observer.notify(r,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;if(this._keepAlive=typeof t.keepAlive=="boolean"?t.keepAlive:!1,this._isolated=typeof t.isolated=="boolean"?t.isolated:!1,this._plugins=new R,t.plugins&&Array.isArray(t.plugins))for(const s of t.plugins)this.addPlugin(s)}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,r,n,o;if(this._disposalState===e){const a=this._disposalState;return this._disposalState=t,(s=globalThis.Blac)!=null&&s.enableLog&&((r=globalThis.Blac)==null||r.log(`[${this._name}:${this._id}] State transition: ${a} -> ${t} (SUCCESS)`)),{success:!0,currentState:t,previousState:a}}return(n=globalThis.Blac)!=null&&n.enableLog&&((o=globalThis.Blac)==null||o.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")})}_notifyObservers(e,t){this._observer.notify(e,t)}addPlugin(e){if(this._plugins.add(e),this._disposalState==="active")try{e.onAttach&&e.onAttach(this)}catch(t){throw console.error(`Failed to attach plugin '${e.name}':`,t),this._plugins.remove(e.name),t}}removePlugin(e){return this._plugins.remove(e)}getPlugin(e){return this._plugins.get(e)}getPlugins(){return this._plugins.getAll()}_activatePlugins(){if(this._disposalState==="active")try{this._plugins.attach(this)}catch(e){console.error(`Failed to activate plugins for ${this._name}:`,e)}}}i(w,"isolated",!1),i(w,"keepAlive",!1);class O{constructor(){i(this,"plugins",new Map);i(this,"metrics",new Map);i(this,"executionOrder",[])}add(e){if(this.plugins.has(e.name))throw new Error(`Plugin '${e.name}' is already registered`);this.plugins.set(e.name,e),this.executionOrder.push(e.name),this.initializeMetrics(e.name)}remove(e){return this.plugins.get(e)?(this.plugins.delete(e),this.metrics.delete(e),this.executionOrder=this.executionOrder.filter(s=>s!==e),!0):!1}get(e){return this.plugins.get(e)}getAll(){return this.executionOrder.map(e=>this.plugins.get(e))}clear(){this.plugins.clear(),this.metrics.clear(),this.executionOrder=[]}executeHook(e,t,s){for(const r of this.executionOrder){const n=this.plugins.get(r),o=n[e];if(typeof o!="function")continue;const a=performance.now();try{o.apply(n,t),this.recordSuccess(r,e,a)}catch(l){this.recordError(r,e,l),s?s(l,n):console.error(`Plugin '${r}' error in hook '${e}':`,l)}}}bootstrap(){this.executeHook("beforeBootstrap",[]),this.executeHook("afterBootstrap",[])}shutdown(){this.executeHook("beforeShutdown",[]),this.executeHook("afterShutdown",[])}notifyBlocCreated(e){this.executeHook("onBlocCreated",[e])}notifyBlocDisposed(e){this.executeHook("onBlocDisposed",[e])}notifyStateChanged(e,t,s){this.executeHook("onStateChanged",[e,t,s])}notifyEventAdded(e,t){this.executeHook("onEventAdded",[e,t])}notifyError(e,t,s){this.executeHook("onError",[e,t,s],(r,n)=>{console.error(`Plugin '${n.name}' error handler failed:`,r)})}getMetrics(e){return this.metrics.get(e)}initializeMetrics(e){this.metrics.set(e,new Map)}recordSuccess(e,t,s){const r=this.metrics.get(e),n=r.get(t)||{executionTime:0,executionCount:0,errorCount:0},o=performance.now()-s;r.set(t,{...n,executionTime:n.executionTime+o,executionCount:n.executionCount+1,lastExecutionTime:o})}recordError(e,t,s){const r=this.metrics.get(e),n=r.get(t)||{executionTime:0,executionCount:0,errorCount:0};r.set(t,{...n,errorCount:n.errorCount+1,lastError:s})}}const _=class _{getInstance(){return _._instance||(_._instance=new u({__unsafe_ignore_singleton:!0})),_._instance}setInstance(e){_._instance=e}resetInstance(){const e=_._instance;if(_._instance=new u({__unsafe_ignore_singleton:!0}),e)for(const t of e.keepAliveBlocs)_._instance.keepAliveBlocs.add(t),_._instance.uidRegistry.set(t.uid,t)}};i(_,"_instance");let P=_,S=new P;function Q(c){S=c}const h=class h{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,"plugins",new O);i(this,"log",(...e)=>{h.logSpy&&h.logSpy(e),h.enableLog&&h.logLevel,h.enableLog&&h.logLevel});i(this,"warn",(e,...t)=>{h.enableLog});i(this,"error",(e,...t)=>{h.enableLog});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===y.ACTIVE&&this.disposeBloc(s)}),t.forEach(s=>{s.forEach(r=>{!r._keepAlive&&r._disposalState===y.ACTIVE&&this.disposeBloc(r)})}),this.blocInstanceMap.clear(),this.isolatedBlocMap.clear(),this.isolatedBlocIndex.clear(),S.resetInstance()});i(this,"disposeBloc",e=>{const t=e._disposalState;if(![y.ACTIVE,y.DISPOSAL_REQUESTED].includes(t)){this.log(`[${e._name}:${String(e._id)}] disposeBloc called on bloc in invalid state: ${t}`);return}const r=e.constructor,n=this.createBlocInstanceMapKey(e._name,e._id);this.log(`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(r.isolated)}`),e._dispose(),this.plugins.notifyBlocDisposed(e),r.isolated?(this.unregisterIsolatedBlocInstance(e),this.blocInstanceMap.delete(n)):this.unregisterBlocInstance(e),this.log("dispatched bloc",e)});i(this,"activateBloc",e=>{if(e._disposalState!==y.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))});i(this,"getBloc",(e,t={})=>{const{id:s,forceNewInstance:r}=t,n=e,o=s??e.name;if(this.log(`[${e.name}:${String(o)}] (getBloc) Called:`,{options:t,base:n}),!r)if(n.isolated){const l=this.findIsolatedBlocInstance(e,t.instanceRef??o);if(l)return l;if(t.throwIfNotFound)throw new Error(`Isolated bloc ${e.name} not found`)}else{const l=this.findRegisteredBlocInstance(e,o);if(l)return l;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,r=t.id||e.name,n=s?this.findIsolatedBlocInstance(e,r):this.findRegisteredBlocInstance(e,r);if(n)return n;throw new Error(`Bloc ${e.name} not found`)});i(this,"getAllBlocs",(e,t={})=>{const s=[];if(this.blocInstanceMap.forEach(r=>{r.constructor===e&&s.push(r)}),t.searchIsolated!==!1){const r=this.isolatedBlocMap.get(e);r&&s.push(...r.map(n=>n))}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 r of s)e(r)&&t.push(r);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===y.ACTIVE&&setTimeout(()=>{e._consumers.size===0&&!e._keepAlive&&e._disposalState===y.ACTIVE&&this.disposeBloc(e)},1e3)});const{__unsafe_ignore_singleton:t=!1}=e;if(!t)return h.instance;S.setInstance(this),this.plugins.bootstrap()}static get instance(){return S.getInstance()}static get getAllBlocs(){return h.instance.getAllBlocs}static get config(){return{...this._config}}static setConfig(e){if(e.proxyDependencyTracking!==void 0&&typeof e.proxyDependencyTracking!="boolean")throw new Error("BlacConfig.proxyDependencyTracking must be a boolean");if(e.exposeBlacInstance!==void 0&&typeof e.exposeBlacInstance!="boolean")throw new Error("BlacConfig.exposeBlacInstance must be a boolean");this._config={...this._config,...e},this.enableLog&&this.instance.log("Blac config updated:",this._config)}static get log(){return h.instance.log}static getInstance(){return S.getInstance()}static get warn(){return h.instance.warn}static get error(){return h.instance.error}static get disposeBloc(){return h.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 r=this.createBlocInstanceMapKey(e.name,t);return this.blocInstanceMap.get(r)}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 r=!1;if(s){const o=s.findIndex(a=>a.uid===e.uid);o!==-1&&(s.splice(o,1),r=!0),s.length===0&&this.isolatedBlocMap.delete(t)}const n=this.isolatedBlocIndex.delete(e.uid);this.uidRegistry.delete(e.uid),this.keepAliveBlocs.delete(e),r!==n&&this.warn(`[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${r}, Index removal: ${n}`)}findIsolatedBlocInstance(e,t){if(!e.isolated)return;const r=this.isolatedBlocMap.get(e);return r?r.find(o=>o._id===t):void 0}findIsolatedBlocInstanceByUid(e){return this.isolatedBlocIndex.get(e)}createNewBlocInstance(e,t,s={}){const{props:r,instanceRef:n}=s,o=new e(r);return o._instanceRef=n,o.props=r||null,o._updateId(t),o._setDisposalHandler(a=>this.disposeBloc(a)),o.isIsolated?this.registerIsolatedBlocInstance(o):this.registerBlocInstance(o),o._activatePlugins(),this.plugins.notifyBlocCreated(o),o}static get activateBloc(){return h.instance.activateBloc}static get getBloc(){return h.instance.getBloc}static get getBlocOrThrow(){return h.instance.getBlocOrThrow}static get disposeKeepAliveBlocs(){return h.instance.disposeKeepAliveBlocs}static get disposeBlocs(){return h.instance.disposeBlocs}static get getMemoryStats(){return h.instance.getMemoryStats}static get validateConsumers(){return h.instance.validateConsumers}bootstrap(){this.plugins.bootstrap()}shutdown(){this.plugins.shutdown();for(const e of this.blocInstanceMap.values())e._keepAlive||this.disposeBloc(e);for(const e of this.isolatedBlocMap.values())for(const t of e)t._keepAlive||this.disposeBloc(t)}};i(h,"_config",{exposeBlacInstance:!1,proxyDependencyTracking:!0}),i(h,"enableLog",!1),i(h,"logLevel","warn"),i(h,"logSpy",null),i(h,"resetInstance",()=>{S.resetInstance()});let u=h;class H extends w{constructor(){super(...arguments);i(this,"eventHandlers",new Map);i(this,"_eventQueue",[]);i(this,"_isProcessingEvent",!1);i(this,"add",async t=>{let s=t;try{s=this._plugins.transformEvent(t)}catch(r){console.error("Error transforming event:",r)}if(s!==null){try{this._plugins.notifyEvent(s)}catch(r){console.error("Error notifying plugins of event:",r)}u.instance.plugins.notifyEventAdded(this,s),this._eventQueue.push(s),this._isProcessingEvent||await this._processEventQueue()}})}on(t,s){this.eventHandlers.has(t)&&u.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,r=this.eventHandlers.get(s);if(r){const n=o=>{const a=this.state;this._pushState(o,a,t)};try{await r(t,n)}catch(o){const a=t.constructor.name||"UnnamedConstructor",l={blocName:this._name,blocId:String(this._id),eventType:a,currentState:this.state,action:t,timestamp:new Date().toISOString()};if(u.error(`[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${a}':`,o,"Context:",l),o instanceof Error)try{this._plugins.notifyError(o,{phase:"event-processing",operation:"handler",metadata:{event:t}}),u.instance.plugins.notifyError(o,this,{phase:"event-processing",operation:"handler",metadata:{event:t}})}catch(d){console.error("Error notifying plugins:",d)}if(o instanceof Error&&o.name==="CriticalError")throw o}}else{const n=t.constructor.name||"UnnamedConstructor";u.warn(`[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${n}'.`,"Registered handlers:",Array.from(this.eventHandlers.keys()).map(o=>o.name),"Action was:",t)}}}class U extends w{_updateProps(e){var s;const t=this.props;this.props=e,(s=this.onPropsChanged)==null||s.call(this,t,e)}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){u.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 r in e)if(Object.prototype.hasOwnProperty.call(e,r)){const o=this.state[r];if(!Object.is(e[r],o)){s=!0;break}}s&&this.emit({...this.state,...e})}}class V{constructor(e){this.props=e}}function L(c,e){if(Object.is(c,e))return!0;if(typeof c!="object"||c===null||typeof e!="object"||e===null)return!1;const t=Object.keys(c),s=Object.keys(e);if(t.length!==s.length)return!1;for(let r=0;r<t.length;r++){const n=t[r];if(!Object.prototype.hasOwnProperty.call(e,n)||!Object.is(c[n],e[n]))return!1}return!0}class j{static setUp(){this.originalInstance=u.instance,u.resetInstance(),u.enableLog=!1}static tearDown(){u.resetInstance()}static createBloc(e,...t){const s=new e(...t);return u.activateBloc(s),s}static async waitForState(e,t,s=5e3){return new Promise((r,n)=>{const o=setTimeout(()=>{n(new Error(`Timeout waiting for state matching predicate after ${s}ms`))},s),a=e._observer.subscribe({id:`test-waiter-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,fn:l=>{t(l)&&(clearTimeout(o),a(),r(l))}});t(e.state)&&(clearTimeout(o),a(),r(e.state))})}static async expectStates(e,t,s=5e3){const r=[];return new Promise((n,o)=>{const a=setTimeout(()=>{o(new Error(`Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(r)}`))},s),l=e._observer.subscribe({id:`test-expecter-${crypto.randomUUID()}`,fn:d=>{if(r.push(d),r.length===t.length){clearTimeout(a),l();for(let f=0;f<t.length;f++){const m=t[f],v=r[f];if(JSON.stringify(m)!==JSON.stringify(v)){o(new Error(`State mismatch at index ${f}. Expected: ${JSON.stringify(m)}, Received: ${JSON.stringify(v)}`));return}}n()}}})})}}i(j,"originalInstance");class F extends H{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 W extends U{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 G{constructor(){i(this,"initialStats");this.initialStats=u.getMemoryStats()}checkForLeaks(){const e=u.getMemoryStats(),t=e.registeredBlocs>this.initialStats.registeredBlocs||e.isolatedBlocs>this.initialStats.isolatedBlocs||e.keepAliveBlocs>this.initialStats.keepAliveBlocs,s=`
2
- Memory Leak Detection Report:
3
- - Initial registered blocs: ${this.initialStats.registeredBlocs}
4
- - Current registered blocs: ${e.registeredBlocs}
5
- - Initial isolated blocs: ${this.initialStats.isolatedBlocs}
6
- - Current isolated blocs: ${e.isolatedBlocs}
7
- - Initial keep-alive blocs: ${this.initialStats.keepAliveBlocs}
8
- - Current keep-alive blocs: ${e.keepAliveBlocs}
9
- - Potential leaks detected: ${t?"YES":"NO"}
10
- `.trim();return{hasLeaks:t,report:s,stats:e}}}class z{constructor(){i(this,"consumers",new WeakMap);i(this,"registrationCount",0);i(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,r){const n=this.consumers.get(e);if(!n)return;const o=Date.now();n.firstAccessTime||(n.firstAccessTime=o),n.accessCount++,n.lastAccessTime=o,t==="state"?(n.stateAccesses.add(s),r!==void 0&&n.stateValues.set(s,{value:r,lastAccessTime:o})):(n.classAccesses.add(s),r!==void 0&&n.classValues.set(s,{value:r,lastAccessTime:o}))}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 r=this.consumers.get(e);if(!r)return!0;let n=!1;const o=Date.now();if(r.stateValues.size===0&&r.classValues.size===0&&(r.stateAccesses.size>0||r.classAccesses.size>0))return!0;for(const[a,l]of r.stateValues)try{const d=this.getValueAtPath(t,a);d!==l.value&&(r.stateValues.set(a,{value:d,lastAccessTime:o}),n=!0)}catch{n=!0}for(const[a,l]of r.classValues)try{const d=this.getValueAtPath(s,a);d!==l.value&&(r.classValues.set(a,{value:d,lastAccessTime:o}),n=!0)}catch{n=!0}return n}shouldNotifyConsumer(e,t){const s=this.consumers.get(e);if(!s)return!1;for(const r of t){if(s.stateAccesses.has(r)||s.classAccesses.has(r))return!0;for(const n of s.stateAccesses)if(r.startsWith(n+".")||n.startsWith(r+"."))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 r=e;for(const n of s){if(r==null)return;r=r[n]}return r}}const k=new WeakMap;let p={stateProxiesCreated:0,classProxiesCreated:0,cacheHits:0,cacheMisses:0,propertyAccesses:0,nestedProxiesCreated:0,totalProxiesCreated:0,createdAt:Date.now()};class b{static createStateProxy(e){const{target:t,consumerRef:s,consumerTracker:r,path:n=""}=e;if(!s||!r||typeof t!="object"||t===null)return t;let o=k.get(t);o||(o=new WeakMap,k.set(t,o));const a=o.get(s);if(a)return p.cacheHits++,a;p.cacheMisses++;const l={get(f,m){if(typeof m=="symbol"||m==="constructor")return Reflect.get(f,m);const v=n?`${n}.${m}`:m;p.propertyAccesses++;const g=Reflect.get(f,m),x=g&&typeof g==="object"&&g!==null?void 0:g;if(r.trackAccess(s,"state",v,x),g&&typeof g=="object"&&g!==null){const B=Object.getPrototypeOf(g)===Object.prototype,$=Array.isArray(g);if(B||$)return p.nestedProxiesCreated++,b.createStateProxy({target:g,consumerRef:s,consumerTracker:r,path:v})}return g},has(f,m){return m in f},ownKeys(f){return Reflect.ownKeys(f)},getOwnPropertyDescriptor(f,m){return Reflect.getOwnPropertyDescriptor(f,m)},set(){return!1},deleteProperty(){return!1}},d=new Proxy(t,l);return o.set(s,d),p.stateProxiesCreated++,p.totalProxiesCreated++,d}static createClassProxy(e){const{target:t,consumerRef:s,consumerTracker:r}=e;if(!s||!r)return t;let n=k.get(t);n||(n=new WeakMap,k.set(t,n));const o=n.get(s);if(o)return p.cacheHits++,o;p.cacheMisses++;const a={get(d,f){const m=Reflect.get(d,f);let v=!1,g=d;const A=new WeakSet,D=10;let x=0;for(;g&&!v&&x<D&&!A.has(g);){A.add(g);try{const C=Object.getOwnPropertyDescriptor(g,f);if(C&&C.get){v=!0;break}g=Object.getPrototypeOf(g),x++}catch{break}}if(!v)return m;p.propertyAccesses++;const B=m,N=B!==null&&typeof B!="object"?B:void 0;return r.trackAccess(s,"class",String(f),N),m},has(d,f){return f in d},ownKeys(d){return Reflect.ownKeys(d)},getOwnPropertyDescriptor(d,f){return Reflect.getOwnPropertyDescriptor(d,f)}},l=new Proxy(t,a);return n.set(s,l),p.classProxiesCreated++,p.totalProxiesCreated++,l}static getProxyState(e){return b.createStateProxy({target:e.state,consumerRef:e.consumerRef,consumerTracker:e.consumerTracker})}static getProxyBlocInstance(e){return b.createClassProxy({target:e.blocInstance,consumerRef:e.consumerRef,consumerTracker:e.consumerTracker})}static getStats(){const e=Date.now()-p.createdAt;return{...p,totalProxies:p.stateProxiesCreated+p.classProxiesCreated,cacheEfficiency:p.cacheHits+p.cacheMisses>0?`${(p.cacheHits/(p.cacheHits+p.cacheMisses)*100).toFixed(1)}%`:"N/A",lifetime:`${e}ms`,proxiesPerSecond:e>0?(p.totalProxiesCreated/(e/1e3)).toFixed(2):"N/A"}}static resetStats(){p={stateProxiesCreated:0,classProxiesCreated:0,cacheHits:0,cacheMisses:0,propertyAccesses:0,nestedProxiesCreated:0,totalProxiesCreated:0,createdAt:Date.now()}}}const I=class I{constructor(e,t){i(this,"id",`consumer-${E()}`);i(this,"blocConstructor");i(this,"componentRef",{current:{}});i(this,"blocInstance");i(this,"consumerTracker");i(this,"lastProps");i(this,"unmountTime",0);i(this,"mountTime",0);i(this,"dependencyValues");i(this,"isUsingDependencies",!1);i(this,"hasMounted",!1);i(this,"mountCount",0);i(this,"options");i(this,"createStateProxy",e=>b.createStateProxy({target:e.target,consumerRef:this.componentRef.current,consumerTracker:this}));i(this,"createClassProxy",e=>b.createClassProxy({target:e.target,consumerRef:this.componentRef.current,consumerTracker:this}));i(this,"createSubscription",e=>this.blocInstance._observer.subscribe({id:this.id,fn:(s,r)=>{var n;if(this.isUsingDependencies&&((n=this.options)!=null&&n.dependencies)){const o=this.options.dependencies(this.blocInstance);if(!this.hasDependencyValuesChanged(this.dependencyValues,o))return;this.dependencyValues=o}else if(u.config.proxyDependencyTracking){const o=this.consumerTracker.getConsumerInfo(this.componentRef.current);if(o&&o.hasRendered&&!this.consumerTracker.hasValuesChanged(this.componentRef.current,s,this.blocInstance))return}else{e.onChange();return}e.onChange()}}));i(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}});i(this,"unmount",()=>{var e;if(this.unmountTime=Date.now(),this.consumerTracker.unregister(this.componentRef.current),this.blocInstance._removeConsumer(this.id),I.propsOwners.get(this.blocInstance)===this.id&&I.propsOwners.delete(this.blocInstance),(e=this.options)!=null&&e.onUnmount)try{this.options.onUnmount(this.blocInstance)}catch{}});i(this,"getProxyState",e=>this.isUsingDependencies||!u.config.proxyDependencyTracking?e:b.getProxyState({state:e,consumerRef:this.componentRef.current,consumerTracker:this}));i(this,"getProxyBlocInstance",()=>this.isUsingDependencies||!u.config.proxyDependencyTracking?this.blocInstance:b.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 z,this.blocInstance=this.updateBlocInstance(),this.consumerTracker.register(e.componentRef.current,this.id),this.isUsingDependencies&&(t!=null&&t.dependencies)&&(this.dependencyValues=t.dependencies(this.blocInstance)),(t==null?void 0:t.props)!==void 0&&this.updateProps(t.props)}trackAccess(e,t,s,r){this.consumerTracker.trackAccess(e,t,s,r)}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=u.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}updateProps(e){const t=this.blocInstance;if(I.propsOwners.has(t)||I.propsOwners.set(t,this.id),I.propsOwners.get(t)!==this.id){u.warn(`[BlacAdapter] Attempted to set props on ${t.constructor.name} from non-owner adapter`);return}t._disposalState===y.DISPOSED||t._disposalState===y.DISPOSING||L(this.lastProps,e)||("add"in t&&typeof t.add=="function"?t.add(new V(e)):"_updateProps"in t&&typeof t._updateProps=="function"&&t._updateProps(e),this.lastProps=e)}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}};i(I,"propsOwners",new WeakMap);let T=I;exports.Blac=u;exports.BlacAdapter=T;exports.BlacObservable=M;exports.Bloc=H;exports.BlocBase=w;exports.BlocLifecycleState=y;exports.BlocPluginRegistry=R;exports.BlocTest=j;exports.ConsumerTracker=z;exports.Cubit=U;exports.MemoryLeakDetector=G;exports.MockBloc=F;exports.MockCubit=W;exports.PropsUpdated=V;exports.ProxyFactory=b;exports.SystemPluginRegistry=O;exports.generateUUID=E;exports.setBlacInstanceManager=Q;exports.shallowEqual=L;
11
- //# sourceMappingURL=index.cjs.js.map