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

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/dist/index.cjs.js +2 -2
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.d.ts +522 -297
  4. package/dist/index.es.js +1833 -1550
  5. package/dist/index.es.js.map +1 -1
  6. package/package.json +6 -7
  7. package/src/Blac.ts +38 -71
  8. package/src/Bloc.ts +8 -9
  9. package/src/BlocBase.ts +246 -540
  10. package/src/Cubit.ts +1 -16
  11. package/src/__tests__/Blac.config.test.ts +10 -17
  12. package/src/__tests__/Bloc.event.test.ts +27 -52
  13. package/src/__tests__/BlocBase.subscription.test.ts +349 -0
  14. package/src/__tests__/Cubit.test.ts +39 -50
  15. package/src/__tests__/memory-leaks.test.ts +383 -0
  16. package/src/__tests__/plugins.test.ts +107 -97
  17. package/src/adapter/BlacAdapter.ts +347 -207
  18. package/src/adapter/ProxyFactory.ts +196 -255
  19. package/src/adapter/__tests__/BlacAdapter.test.ts +71 -77
  20. package/src/adapter/__tests__/ProxyFactory.test.ts +1 -1
  21. package/src/adapter/index.ts +0 -1
  22. package/src/errors/BlacError.ts +69 -0
  23. package/src/errors/ErrorManager.ts +101 -0
  24. package/src/errors/handleError.ts +114 -0
  25. package/src/errors/index.ts +13 -0
  26. package/src/events.ts +7 -1
  27. package/src/index.ts +7 -1
  28. package/src/lifecycle/BlocLifecycle.ts +156 -0
  29. package/src/lifecycle/index.ts +1 -0
  30. package/src/plugins/BlocPluginRegistry.ts +71 -51
  31. package/src/plugins/SystemPluginRegistry.ts +63 -13
  32. package/src/plugins/__tests__/BlocPluginRegistry.test.ts +450 -0
  33. package/src/plugins/__tests__/SystemPluginRegistry.test.ts +404 -0
  34. package/src/plugins/types.ts +32 -3
  35. package/src/subscription/README.md +132 -0
  36. package/src/subscription/SubscriptionManager.ts +395 -0
  37. package/src/subscription/__tests__/SubscriptionManager.test.ts +355 -0
  38. package/src/subscription/index.ts +2 -0
  39. package/src/subscription/types.ts +90 -0
  40. package/src/testing.ts +31 -37
  41. package/src/types.ts +4 -21
  42. package/src/utils/BatchingManager.ts +59 -0
  43. package/src/utils/RerenderLogger.ts +265 -0
  44. package/src/utils/__tests__/generateInstanceId.test.ts +104 -0
  45. package/src/utils/__tests__/shallowEqual.test.ts +171 -0
  46. package/src/utils/__tests__/uuid.test.ts +144 -0
  47. package/src/utils/generateInstanceId.ts +54 -0
  48. package/src/utils/shallowEqual.ts +1 -1
  49. package/README.md +0 -329
  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
package/dist/index.es.js CHANGED
@@ -1,141 +1,107 @@
1
- var R = Object.defineProperty;
2
- var O = (c, e, t) => e in c ? R(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t;
3
- var i = (c, e, t) => O(c, typeof e != "symbol" ? e + "" : e, t);
4
- class H {
5
- /**
6
- * Creates a new BlacObservable instance
7
- * @param bloc - The Bloc instance to observe
8
- */
9
- constructor(e) {
10
- /** The Bloc instance this observable is associated with */
11
- i(this, "bloc");
12
- i(this, "_observers", /* @__PURE__ */ new Set());
13
- this.bloc = e;
1
+ var u = /* @__PURE__ */ ((r) => (r.ACTIVE = "active", r.DISPOSAL_REQUESTED = "disposal_requested", r.DISPOSING = "disposing", r.DISPOSED = "disposed", r))(u || {});
2
+ class B {
3
+ disposalState = "active";
4
+ disposalLock = !1;
5
+ disposalTimer;
6
+ disposalHandler;
7
+ get currentState() {
8
+ return this.disposalState;
9
+ }
10
+ get isDisposed() {
11
+ return this.disposalState === "disposed";
14
12
  }
15
13
  /**
16
- * Gets the number of active observers
17
- * @returns The number of observers currently subscribed
14
+ * Atomic state transition for disposal
18
15
  */
19
- get size() {
20
- return this._observers.size;
16
+ atomicStateTransition(e, t) {
17
+ if (this.disposalLock)
18
+ return {
19
+ success: !1,
20
+ currentState: this.disposalState,
21
+ previousState: this.disposalState
22
+ };
23
+ this.disposalLock = !0;
24
+ try {
25
+ if (this.disposalState !== e)
26
+ return {
27
+ success: !1,
28
+ currentState: this.disposalState,
29
+ previousState: this.disposalState
30
+ };
31
+ const s = this.disposalState;
32
+ return this.disposalState = t, {
33
+ success: !0,
34
+ currentState: t,
35
+ previousState: s
36
+ };
37
+ } finally {
38
+ this.disposalLock = !1;
39
+ }
21
40
  }
22
41
  /**
23
- * Gets the set of all observers
24
- * @returns The Set of all BlacObserver instances
42
+ * Schedule disposal after a delay
25
43
  */
26
- get observers() {
27
- return this._observers;
44
+ scheduleDisposal(e, t, s) {
45
+ this.disposalTimer && (clearTimeout(this.disposalTimer), this.disposalTimer = void 0), this.atomicStateTransition(
46
+ "active",
47
+ "disposal_requested"
48
+ /* DISPOSAL_REQUESTED */
49
+ ).success && (this.disposalTimer = setTimeout(() => {
50
+ t() && this.disposalState === "disposal_requested" ? s() : this.atomicStateTransition(
51
+ "disposal_requested",
52
+ "active"
53
+ /* ACTIVE */
54
+ );
55
+ }, e));
28
56
  }
29
57
  /**
30
- * Subscribes an observer to state changes
31
- * @param observer - The observer to subscribe
32
- * @returns A function that can be called to unsubscribe the observer
58
+ * Cancel disposal if in disposal requested state
33
59
  */
34
- subscribe(e) {
35
- const t = this.bloc._disposalState;
36
- return t === y.DISPOSED || t === y.DISPOSING ? (u.log(
37
- "BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.",
38
- this.bloc,
39
- e
40
- ), () => {
41
- }) : (u.log(
42
- "BlacObservable.subscribe: Subscribing observer.",
43
- this.bloc,
44
- e
45
- ), this._observers.add(e), t === y.DISPOSAL_REQUESTED && (u.log(
46
- "BlacObservable.subscribe: Cancelling disposal due to new subscription.",
47
- this.bloc
48
- ), this.bloc._atomicStateTransition(
49
- y.DISPOSAL_REQUESTED,
50
- y.ACTIVE
51
- )), () => {
52
- u.log(
53
- "BlacObservable.subscribe: Unsubscribing observer.",
54
- this.bloc,
55
- e
56
- ), this.unsubscribe(e);
57
- });
60
+ cancelDisposal() {
61
+ return this.disposalState === "disposal_requested" ? (this.disposalTimer && (clearTimeout(this.disposalTimer), this.disposalTimer = void 0), this.atomicStateTransition(
62
+ "disposal_requested",
63
+ "active"
64
+ /* ACTIVE */
65
+ ).success) : !1;
58
66
  }
59
67
  /**
60
- * Unsubscribes an observer from state changes
61
- * @param observer - The observer to unsubscribe
68
+ * Set disposal handler
62
69
  */
63
- unsubscribe(e) {
64
- 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(
65
- `[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`
66
- ), this.bloc._scheduleDisposal()));
70
+ setDisposalHandler(e) {
71
+ this.disposalHandler = e;
67
72
  }
68
73
  /**
69
- * Notifies all observers of a state change
70
- * @param newState - The new state value
71
- * @param oldState - The previous state value
72
- * @param action - Optional action that triggered the state change
74
+ * Get disposal handler
73
75
  */
74
- notify(e, t, s) {
75
- this._observers.forEach((r) => {
76
- let n = !1;
77
- if (r.dependencyArray) {
78
- const o = r.lastState, a = r.dependencyArray(
79
- e,
80
- t,
81
- this.bloc
82
- );
83
- if (!o)
84
- n = !0;
85
- else if (o.length !== a.length)
86
- n = !0;
87
- else
88
- for (let l = 0; l < a.length; l++)
89
- if (!Object.is(o[l], a[l])) {
90
- n = !0;
91
- break;
92
- }
93
- r.lastState = a;
94
- } else
95
- n = !0;
96
- n && r.fn(e, t, s);
97
- }), u.instance.plugins.notifyStateChanged(this.bloc, t, e);
76
+ getDisposalHandler() {
77
+ return this.disposalHandler;
98
78
  }
99
79
  /**
100
- * Clears the observer set
80
+ * Clear disposal timer
101
81
  */
102
- clear() {
103
- this._observers.clear();
82
+ clearDisposalTimer() {
83
+ this.disposalTimer && (clearTimeout(this.disposalTimer), this.disposalTimer = void 0);
104
84
  }
105
85
  }
106
- function $() {
107
- return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
108
- const e = Math.random() * 16 | 0;
109
- return (c === "x" ? e : e & 3 | 8).toString(16);
110
- });
111
- }
112
- class V {
113
- constructor() {
114
- i(this, "plugins", /* @__PURE__ */ new Map());
115
- i(this, "executionOrder", []);
116
- i(this, "attached", !1);
117
- }
86
+ class T {
87
+ plugins = /* @__PURE__ */ new Map();
88
+ metrics = /* @__PURE__ */ new Map();
89
+ executionOrder = [];
118
90
  /**
119
- * Add a bloc plugin
91
+ * Add a system plugin
120
92
  */
121
93
  add(e) {
122
94
  if (this.plugins.has(e.name))
123
95
  throw new Error(`Plugin '${e.name}' is already registered`);
124
- e.capabilities && this.validateCapabilities(e), this.plugins.set(e.name, e), this.executionOrder.push(e.name);
96
+ this.plugins.set(e.name, e), this.executionOrder.push(e.name), this.initializeMetrics(e.name);
125
97
  }
126
98
  /**
127
- * Remove a bloc plugin
99
+ * Remove a system plugin
128
100
  */
129
101
  remove(e) {
130
- const t = this.plugins.get(e);
131
- if (!t) return !1;
132
- if (this.attached && t.onDetach)
133
- try {
134
- t.onDetach();
135
- } catch (s) {
136
- console.error(`Plugin '${e}' error in onDetach:`, s);
137
- }
138
- return this.plugins.delete(e), this.executionOrder = this.executionOrder.filter((s) => s !== e), !0;
102
+ return this.plugins.get(e) ? (this.plugins.delete(e), this.metrics.delete(e), this.executionOrder = this.executionOrder.filter(
103
+ (s) => s !== e
104
+ ), !0) : !1;
139
105
  }
140
106
  /**
141
107
  * Get a plugin by name
@@ -153,1111 +119,1353 @@ class V {
153
119
  * Clear all plugins
154
120
  */
155
121
  clear() {
156
- if (this.attached) {
157
- for (const e of this.getAll())
158
- if (e.onDetach)
159
- try {
160
- e.onDetach();
161
- } catch (t) {
162
- console.error(`Plugin '${e.name}' error in onDetach:`, t);
163
- }
122
+ this.plugins.clear(), this.metrics.clear(), this.executionOrder = [];
123
+ }
124
+ /**
125
+ * Execute a hook on all plugins
126
+ */
127
+ executeHook(e, t, s) {
128
+ for (const i of this.executionOrder) {
129
+ const n = this.plugins.get(i), a = n[e];
130
+ if (typeof a != "function") continue;
131
+ const c = performance.now();
132
+ try {
133
+ a.apply(n, t), this.recordSuccess(i, e, c);
134
+ } catch (l) {
135
+ this.recordError(i, e, l), s ? s(l, n) : console.error(
136
+ `Plugin '${i}' error in hook '${e}':`,
137
+ l
138
+ );
139
+ }
164
140
  }
165
- this.plugins.clear(), this.executionOrder = [], this.attached = !1;
166
141
  }
167
142
  /**
168
- * Attach all plugins to a bloc
143
+ * Bootstrap all plugins
169
144
  */
170
- attach(e) {
171
- if (this.attached)
172
- throw new Error("Plugins are already attached");
173
- for (const t of this.getAll())
174
- if (t.onAttach)
175
- try {
176
- t.onAttach(e);
177
- } catch (s) {
178
- console.error(`Plugin '${t.name}' error in onAttach:`, s), this.remove(t.name);
179
- }
180
- this.attached = !0;
145
+ bootstrap() {
146
+ this.executeHook("beforeBootstrap", []), this.executeHook("afterBootstrap", []);
181
147
  }
182
148
  /**
183
- * Transform state through all plugins
149
+ * Shutdown all plugins
184
150
  */
185
- transformState(e, t) {
186
- let s = t;
187
- for (const r of this.getAll())
188
- if (r.transformState && this.canTransformState(r))
189
- try {
190
- s = r.transformState(e, s);
191
- } catch (n) {
192
- console.error(`Plugin '${r.name}' error in transformState:`, n);
193
- }
194
- return s;
151
+ shutdown() {
152
+ this.executeHook("beforeShutdown", []), this.executeHook("afterShutdown", []);
195
153
  }
196
154
  /**
197
- * Transform event through all plugins
155
+ * Notify plugins of bloc creation
198
156
  */
199
- transformEvent(e) {
200
- let t = e;
201
- for (const s of this.getAll()) {
202
- if (t === null) break;
203
- if (s.transformEvent && this.canInterceptEvents(s))
204
- try {
205
- t = s.transformEvent(t);
206
- } catch (r) {
207
- console.error(`Plugin '${s.name}' error in transformEvent:`, r);
208
- }
209
- }
210
- return t;
157
+ notifyBlocCreated(e) {
158
+ this.executeHook("onBlocCreated", [e]);
159
+ }
160
+ /**
161
+ * Notify plugins of bloc disposal
162
+ */
163
+ notifyBlocDisposed(e) {
164
+ this.executeHook("onBlocDisposed", [e]);
211
165
  }
212
166
  /**
213
167
  * Notify plugins of state change
214
168
  */
215
- notifyStateChange(e, t) {
216
- for (const s of this.getAll())
217
- if (s.onStateChange && this.canReadState(s))
218
- try {
219
- s.onStateChange(e, t);
220
- } catch (r) {
221
- console.error(`Plugin '${s.name}' error in onStateChange:`, r);
222
- }
169
+ notifyStateChanged(e, t, s) {
170
+ this.executeHook("onStateChanged", [e, t, s]);
223
171
  }
224
172
  /**
225
- * Notify plugins of event
173
+ * Notify plugins of event addition
226
174
  */
227
- notifyEvent(e) {
228
- for (const t of this.getAll())
229
- if (t.onEvent && this.canReadState(t))
230
- try {
231
- t.onEvent(e);
232
- } catch (s) {
233
- console.error(`Plugin '${t.name}' error in onEvent:`, s);
234
- }
175
+ notifyEventAdded(e, t) {
176
+ this.executeHook("onEventAdded", [e, t]);
235
177
  }
236
178
  /**
237
- * Notify plugins of error
179
+ * Notify plugins of errors
238
180
  */
239
- notifyError(e, t) {
240
- for (const s of this.getAll())
241
- if (s.onError)
242
- try {
243
- s.onError(e, t);
244
- } catch (r) {
245
- console.error(`Plugin '${s.name}' error in onError:`, r);
246
- }
181
+ notifyError(e, t, s) {
182
+ this.executeHook("onError", [e, t, s], (i, n) => {
183
+ console.error(`Plugin '${n.name}' error handler failed:`, i);
184
+ });
247
185
  }
248
- validateCapabilities(e) {
249
- const t = e.capabilities;
250
- if (t.transformState && !t.readState)
251
- throw new Error(`Plugin '${e.name}': transformState requires readState capability`);
252
- if (t.interceptEvents && !t.readState)
253
- throw new Error(`Plugin '${e.name}': interceptEvents requires readState capability`);
186
+ /**
187
+ * Notify plugins of adapter lifecycle events
188
+ */
189
+ notifyAdapterCreated(e, t) {
190
+ this.executeHook("onAdapterCreated", [e, t]);
254
191
  }
255
- canReadState(e) {
256
- return !e.capabilities || e.capabilities.readState !== !1;
192
+ notifyAdapterMount(e, t) {
193
+ this.executeHook("onAdapterMount", [e, t]);
257
194
  }
258
- canTransformState(e) {
259
- return !e.capabilities || e.capabilities.transformState === !0;
195
+ notifyAdapterUnmount(e, t) {
196
+ this.executeHook("onAdapterUnmount", [e, t]);
260
197
  }
261
- canInterceptEvents(e) {
262
- return !e.capabilities || e.capabilities.interceptEvents === !0;
198
+ notifyAdapterRender(e, t) {
199
+ this.executeHook("onAdapterRender", [e, t]);
200
+ }
201
+ notifyAdapterDisposed(e, t) {
202
+ this.executeHook("onAdapterDisposed", [e, t]);
263
203
  }
264
- }
265
- var y = /* @__PURE__ */ ((c) => (c.ACTIVE = "active", c.DISPOSAL_REQUESTED = "disposal_requested", c.DISPOSING = "disposing", c.DISPOSED = "disposed", c))(y || {});
266
- class k {
267
204
  /**
268
- * Creates a new BlocBase instance with the given initial state.
269
- * Sets up the observer, registers with the Blac manager, and initializes addons.
270
- *
271
- * @param initialState The initial state value for this Bloc
205
+ * Get metrics for a plugin
272
206
  */
273
- constructor(e) {
274
- i(this, "uid", $());
275
- /**
276
- * Defines how dependencies are selected from the state for efficient updates.
277
- * When provided, observers will only be notified when selected dependencies change.
278
- */
279
- i(this, "defaultDependencySelector");
280
- /**
281
- * @internal
282
- * Indicates if this specific Bloc instance is isolated from others of the same type.
283
- */
284
- i(this, "_isolated", !1);
285
- /**
286
- * @internal
287
- * Observable responsible for managing state listeners and notifying consumers.
288
- */
289
- i(this, "_observer");
290
- /**
291
- * The unique identifier for this Bloc instance.
292
- * Defaults to the class name, but can be customized.
293
- */
294
- i(this, "_id");
295
- /**
296
- * @internal
297
- * Reference string used internally for tracking and debugging.
298
- */
299
- i(this, "_instanceRef");
300
- /**
301
- * @internal
302
- * Indicates if this specific Bloc instance should be kept alive when no consumers are present.
303
- */
304
- i(this, "_keepAlive", !1);
305
- /**
306
- * @readonly
307
- * Timestamp when this Bloc instance was created, useful for debugging and performance tracking.
308
- */
309
- i(this, "_createdAt", Date.now());
310
- /**
311
- * @internal
312
- * Atomic disposal state to prevent race conditions
313
- */
314
- i(this, "_disposalState", "active");
315
- /**
316
- * @internal
317
- * Timestamp when disposal was requested (for React Strict Mode grace period)
318
- */
319
- i(this, "_disposalRequestTime", 0);
320
- /**
321
- * @internal
322
- * The current state of the Bloc.
323
- */
324
- i(this, "_state");
325
- /**
326
- * @internal
327
- * The previous state of the Bloc, maintained for comparison and history.
328
- */
329
- i(this, "_oldState");
330
- /**
331
- * Props passed during Bloc instance creation.
332
- * Can be used to configure or parameterize the Bloc's behavior.
333
- */
334
- i(this, "props", null);
335
- /**
336
- * @internal
337
- * Flag to prevent batching race conditions
338
- */
339
- i(this, "_batchingLock", !1);
340
- /**
341
- * @internal
342
- * Pending batched updates
343
- */
344
- i(this, "_pendingUpdates", []);
345
- /**
346
- * @internal
347
- * Map of consumer IDs to their WeakRef objects for proper cleanup
348
- */
349
- i(this, "_consumerRefs", /* @__PURE__ */ new Map());
350
- /**
351
- * Plugin registry for this bloc instance
352
- */
353
- i(this, "_plugins");
354
- /**
355
- * @internal
356
- * Validates that all consumer references are still alive
357
- * Removes dead consumers automatically
358
- */
359
- i(this, "_validateConsumers", () => {
360
- const e = [];
361
- for (const [t, s] of this._consumerRefs)
362
- s.deref() === void 0 && e.push(t);
363
- for (const t of e)
364
- this._consumers.delete(t), this._consumerRefs.delete(t);
365
- this._consumers.size === 0 && !this._keepAlive && this._disposalState === "active" && this._scheduleDisposal();
366
- });
367
- /**
368
- * @internal
369
- * Updates the Bloc instance's ID to a new value.
370
- * Only updates if the new ID is defined and different from the current one.
371
- *
372
- * @param id The new ID to assign to this Bloc instance
373
- */
374
- i(this, "_updateId", (e) => {
375
- const t = this._id;
376
- !e || e === t || (this._id = e);
377
- });
378
- /**
379
- * @internal
380
- * Optional function to be called when the Bloc is disposed.
381
- */
382
- i(this, "onDispose");
383
- /**
384
- * @internal
385
- * Set of consumer IDs currently listening to this Bloc's state changes.
386
- */
387
- i(this, "_consumers", /* @__PURE__ */ new Set());
388
- /**
389
- * @internal
390
- * Registers a new consumer to this Bloc instance.
391
- * Notifies the Blac manager that a consumer has been added.
392
- *
393
- * @param consumerId The unique ID of the consumer being added
394
- * @param consumerRef Optional reference to the consumer object for cleanup validation
395
- */
396
- i(this, "_addConsumer", (e, t) => {
397
- var s;
398
- 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(
399
- `[${this._name}:${this._id}] Consumer added. Total consumers: ${this._consumers.size}`
400
- )), !0);
401
- });
402
- /**
403
- * @internal
404
- * Unregisters a consumer from this Bloc instance.
405
- * Notifies the Blac manager that a consumer has been removed.
406
- *
407
- * @param consumerId The unique ID of the consumer being removed
408
- */
409
- i(this, "_removeConsumer", (e) => {
410
- var t, s;
411
- this._consumers.has(e) && (this._consumers.delete(e), this._consumerRefs.delete(e), (t = globalThis.Blac) == null || t.log(
412
- `[${this._name}:${this._id}] Consumer removed. Remaining consumers: ${this._consumers.size}, keepAlive: ${this._keepAlive}`
413
- ), this._consumers.size === 0 && !this._keepAlive && this._disposalState === "active" && ((s = globalThis.Blac) == null || s.log(
414
- `[${this._name}:${this._id}] No consumers left and not keep-alive. Scheduling disposal.`
415
- ), this._scheduleDisposal()));
416
- });
417
- /**
418
- * @internal
419
- * Handler function for disposal (can be set by Blac manager)
420
- */
421
- i(this, "_disposalHandler");
422
- i(this, "lastUpdate", Date.now());
423
- /**
424
- * @internal
425
- * Flag to indicate if batching is enabled for this bloc
426
- */
427
- i(this, "_batchingEnabled", !1);
428
- /**
429
- * @internal
430
- * Updates the state and notifies all observers of the change.
431
- *
432
- * @param newState The new state to be set
433
- * @param oldState The previous state for comparison
434
- * @param action Optional metadata about what caused the state change
435
- */
436
- i(this, "_pushState", (e, t, s) => {
437
- if (e === void 0 || s !== void 0 && typeof s != "object" && typeof s != "function")
438
- return;
439
- let r = e;
440
- try {
441
- r = this._plugins.transformState(t, e);
442
- } catch (n) {
443
- this._plugins.notifyError(n, {
444
- phase: "state-change",
445
- operation: "transformState"
446
- });
447
- }
448
- if (this._batchingEnabled) {
449
- this._pendingUpdates.push({ newState: r, oldState: t, action: s }), this._oldState = t, this._state = r;
450
- return;
451
- }
452
- this._oldState = t, this._state = r;
453
- try {
454
- this._plugins.notifyStateChange(t, r);
455
- } catch (n) {
456
- console.error("Error notifying bloc plugins of state change:", n);
457
- }
458
- this._observer.notify(r, t, s), this.lastUpdate = Date.now();
207
+ getMetrics(e) {
208
+ return this.metrics.get(e);
209
+ }
210
+ initializeMetrics(e) {
211
+ this.metrics.set(e, /* @__PURE__ */ new Map());
212
+ }
213
+ recordSuccess(e, t, s) {
214
+ const i = this.metrics.get(e), n = i.get(t) || {
215
+ executionTime: 0,
216
+ executionCount: 0,
217
+ errorCount: 0
218
+ }, a = performance.now() - s;
219
+ i.set(t, {
220
+ ...n,
221
+ executionTime: n.executionTime + a,
222
+ executionCount: n.executionCount + 1,
223
+ lastExecutionTime: a
459
224
  });
460
- /**
461
- * Enables batching for multiple state updates
462
- * @param batchFn Function to execute with batching enabled
463
- */
464
- i(this, "batch", (e) => {
465
- if (this._batchingLock)
466
- return e();
467
- this._batchingLock = !0, this._batchingEnabled = !0, this._pendingUpdates = [];
468
- try {
469
- const t = e();
470
- if (this._pendingUpdates.length > 0) {
471
- const s = this._pendingUpdates[this._pendingUpdates.length - 1];
472
- this._observer.notify(
473
- s.newState,
474
- s.oldState,
475
- s.action
476
- ), this.lastUpdate = Date.now();
477
- }
478
- return t;
479
- } finally {
480
- this._batchingEnabled = !1, this._batchingLock = !1, this._pendingUpdates = [];
481
- }
225
+ }
226
+ recordError(e, t, s) {
227
+ const i = this.metrics.get(e), n = i.get(t) || {
228
+ executionTime: 0,
229
+ executionCount: 0,
230
+ errorCount: 0
231
+ };
232
+ i.set(t, {
233
+ ...n,
234
+ errorCount: n.errorCount + 1,
235
+ lastError: s
482
236
  });
483
- this._state = e, this._observer = new H(this), this._id = this.constructor.name;
484
- const t = this.constructor;
485
- if (this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1, this._plugins = new V(), t.plugins && Array.isArray(t.plugins))
486
- for (const s of t.plugins)
487
- this.addPlugin(s);
488
237
  }
489
- get isIsolated() {
490
- return this._isolated;
238
+ }
239
+ var v = /* @__PURE__ */ ((r) => (r.LIFECYCLE = "LIFECYCLE", r.STATE = "STATE", r.PLUGIN = "PLUGIN", r.VALIDATION = "VALIDATION", r.DISPOSAL = "DISPOSAL", r.CONSUMER = "CONSUMER", r))(v || {}), y = /* @__PURE__ */ ((r) => (r.FATAL = "FATAL", r.ERROR = "ERROR", r.WARNING = "WARNING", r.INFO = "INFO", r))(y || {});
240
+ class m extends Error {
241
+ constructor(e, t, s, i, n) {
242
+ super(e), this.category = t, this.severity = s, this.context = i, this.cause = n, this.name = "BlacError", Object.setPrototypeOf(this, m.prototype);
491
243
  }
492
- get isKeepAlive() {
493
- return this._keepAlive;
244
+ toString() {
245
+ const e = this.context ? ` [${Object.entries(this.context).filter(([t, s]) => s !== void 0).map(([t, s]) => `${t}: ${s}`).join(", ")}]` : "";
246
+ return `${this.name} [${this.severity}/${this.category}]: ${this.message}${e}`;
494
247
  }
495
- /**
496
- * Returns the current state of the Bloc.
497
- * Use this getter to access the state in a read-only manner.
498
- * Returns the state even during transitional lifecycle states for React compatibility.
499
- */
500
- get state() {
501
- return this._disposalState === "disposed" ? this._state : this._state;
248
+ }
249
+ const P = {
250
+ shouldPropagate: (r) => r.severity === "FATAL",
251
+ shouldLog: (r) => r.severity !== "INFO",
252
+ handle: (r) => {
253
+ P.shouldLog(r) && console.error(r.toString(), r.cause);
502
254
  }
255
+ };
256
+ class f {
257
+ static instance;
258
+ handlers = /* @__PURE__ */ new Set();
259
+ strategy = P;
503
260
  /**
504
- * Returns whether this Bloc instance has been disposed.
505
- * @returns true if the bloc is in DISPOSED state
261
+ * Get the singleton instance of ErrorManager
506
262
  */
507
- get isDisposed() {
508
- return this._disposalState === "disposed";
263
+ static getInstance() {
264
+ return f.instance || (f.instance = new f()), f.instance;
509
265
  }
510
266
  /**
511
- * @internal
512
- * Returns the name of the Bloc class for identification and debugging.
267
+ * Set a custom error handling strategy
513
268
  */
514
- get _name() {
515
- return this.constructor.name;
269
+ setStrategy(e) {
270
+ this.strategy = e;
516
271
  }
517
272
  /**
518
- * @internal
519
- * Performs atomic state transition using compare-and-swap semantics
520
- * @param expectedState The expected current state
521
- * @param newState The desired new state
522
- * @returns Result indicating success/failure and state information
273
+ * Add a custom error handler that will be called for all errors
523
274
  */
524
- _atomicStateTransition(e, t) {
525
- var s, r, n, o;
526
- if (this._disposalState === e) {
527
- const a = this._disposalState;
528
- return this._disposalState = t, (s = globalThis.Blac) != null && s.enableLog && ((r = globalThis.Blac) == null || r.log(
529
- `[${this._name}:${this._id}] State transition: ${a} -> ${t} (SUCCESS)`
530
- )), {
531
- success: !0,
532
- currentState: t,
533
- previousState: a
534
- };
535
- }
536
- return (n = globalThis.Blac) != null && n.enableLog && ((o = globalThis.Blac) == null || o.log(
537
- `[${this._name}:${this._id}] State transition failed: expected ${e}, current ${this._disposalState}`
538
- )), {
539
- success: !1,
540
- currentState: this._disposalState,
541
- previousState: e
542
- };
275
+ addHandler(e) {
276
+ this.handlers.add(e);
543
277
  }
544
278
  /**
545
- * @internal
546
- * Cleans up resources and removes this Bloc from the system.
547
- * Notifies the Blac manager and clears all observers.
279
+ * Remove a previously added error handler
548
280
  */
549
- _dispose() {
550
- var t;
551
- let e = this._atomicStateTransition(
552
- "active",
553
- "disposing"
554
- /* DISPOSING */
555
- );
556
- if (e.success || (e = this._atomicStateTransition(
557
- "disposal_requested",
558
- "disposing"
559
- /* DISPOSING */
560
- )), !e.success)
561
- return !1;
562
- try {
563
- return this._consumers.clear(), this._consumerRefs.clear(), this._observer.clear(), (t = this.onDispose) == null || t.call(this), this._atomicStateTransition(
564
- "disposing",
565
- "disposed"
566
- /* DISPOSED */
567
- ).success;
568
- } catch (s) {
569
- throw this._disposalState = "active", s;
570
- }
281
+ removeHandler(e) {
282
+ this.handlers.delete(e);
571
283
  }
572
284
  /**
573
- * @internal
574
- * Sets the disposal handler for this bloc
285
+ * Process an error through all handlers and apply the configured strategy
575
286
  */
576
- _setDisposalHandler(e) {
577
- this._disposalHandler = e;
287
+ handle(e) {
288
+ if (this.handlers.forEach((t) => {
289
+ try {
290
+ t(e);
291
+ } catch (s) {
292
+ console.error("Error in error handler:", s);
293
+ }
294
+ }), this.strategy.handle(e), this.strategy.shouldPropagate(e))
295
+ throw e;
578
296
  }
579
297
  /**
580
- * @internal
581
- * Schedules disposal of this bloc instance if it has no consumers
582
- * Uses atomic state transitions to prevent race conditions
298
+ * Convenience method for wrapping operations with error handling
583
299
  */
584
- _scheduleDisposal() {
585
- if (!this._atomicStateTransition(
586
- "active",
587
- "disposal_requested"
588
- /* DISPOSAL_REQUESTED */
589
- ).success)
590
- return;
591
- if (!(this._consumers.size === 0 && !this._keepAlive)) {
592
- this._atomicStateTransition(
593
- "disposal_requested",
594
- "active"
595
- /* ACTIVE */
596
- );
300
+ wrap(e, t) {
301
+ try {
302
+ return e();
303
+ } catch (s) {
304
+ const i = t(s);
305
+ this.handle(i);
597
306
  return;
598
307
  }
599
- this._disposalRequestTime = Date.now(), queueMicrotask(() => {
600
- this._consumers.size === 0 && !this._keepAlive && this._observer.size === 0 && this._disposalState === "disposal_requested" ? this._disposalHandler ? this._disposalHandler(this) : this._dispose() : this._atomicStateTransition(
601
- "disposal_requested",
602
- "active"
603
- /* ACTIVE */
604
- );
605
- });
606
308
  }
607
309
  /**
608
- * Notify observers of a state change
609
- * @internal Used by plugins for state hydration
610
- * @param newState The new state
611
- * @param oldState The old state
310
+ * Async version of wrap
612
311
  */
613
- _notifyObservers(e, t) {
614
- this._observer.notify(e, t);
312
+ async wrapAsync(e, t) {
313
+ try {
314
+ return await e();
315
+ } catch (s) {
316
+ const i = t(s);
317
+ this.handle(i);
318
+ return;
319
+ }
615
320
  }
616
- /**
617
- * Add a plugin to this bloc instance
618
- */
619
- addPlugin(e) {
620
- if (this._plugins.add(e), this._disposalState === "active")
621
- try {
622
- e.onAttach && e.onAttach(this);
623
- } catch (t) {
624
- throw console.error(`Failed to attach plugin '${e.name}':`, t), this._plugins.remove(e.name), t;
321
+ }
322
+ class g {
323
+ static _instance;
324
+ getInstance() {
325
+ return g._instance || (g._instance = new o({
326
+ __unsafe_ignore_singleton: !0
327
+ })), g._instance;
328
+ }
329
+ setInstance(e) {
330
+ g._instance = e;
331
+ }
332
+ resetInstance() {
333
+ const e = g._instance;
334
+ if (g._instance = new o({
335
+ __unsafe_ignore_singleton: !0
336
+ }), e)
337
+ for (const t of e.keepAliveBlocs)
338
+ g._instance.keepAliveBlocs.add(t), g._instance.uidRegistry.set(t.uid, t);
339
+ }
340
+ }
341
+ let b = new g();
342
+ function H(r) {
343
+ b = r;
344
+ }
345
+ class o {
346
+ static get instance() {
347
+ return b.getInstance();
348
+ }
349
+ /** Timestamp when the instance was created */
350
+ createdAt = Date.now();
351
+ errorManager = f.getInstance();
352
+ static get getAllBlocs() {
353
+ return o.instance.getAllBlocs;
354
+ }
355
+ /** Private static configuration */
356
+ static _config = {
357
+ proxyDependencyTracking: !0
358
+ };
359
+ /** Get current configuration */
360
+ static get config() {
361
+ return { ...this._config };
362
+ }
363
+ /**
364
+ * Set or update Blac configuration
365
+ * @param config - Partial configuration to merge with existing config
366
+ * @throws Error if configuration is invalid
367
+ */
368
+ static setConfig(e) {
369
+ if (e.proxyDependencyTracking !== void 0 && typeof e.proxyDependencyTracking != "boolean") {
370
+ const t = new m(
371
+ "BlacConfig.proxyDependencyTracking must be a boolean",
372
+ v.VALIDATION,
373
+ y.FATAL
374
+ );
375
+ this.instance.errorManager.handle(t);
376
+ }
377
+ this._config = {
378
+ ...this._config,
379
+ ...e
380
+ }, this.enableLog && this.instance.log("Blac config updated:", this._config);
381
+ }
382
+ /** Map storing all registered bloc instances by their class name and ID */
383
+ blocInstanceMap = /* @__PURE__ */ new Map();
384
+ /** Map storing isolated bloc instances grouped by their constructor */
385
+ // Using BlocConstructor<BlocBase<unknown>> would break type inference when storing
386
+ // different bloc types in the same map. The 'any' allows proper polymorphic storage
387
+ // while maintaining type safety at usage sites through the BlocConstructor constraint.
388
+ isolatedBlocMap = /* @__PURE__ */ new Map();
389
+ /** Map for O(1) lookup of isolated blocs by UID */
390
+ isolatedBlocIndex = /* @__PURE__ */ new Map();
391
+ /** Map tracking UIDs to prevent memory leaks */
392
+ uidRegistry = /* @__PURE__ */ new Map();
393
+ /** Set of keep-alive blocs for controlled cleanup */
394
+ keepAliveBlocs = /* @__PURE__ */ new Set();
395
+ /** Flag to control whether changes should be posted to document */
396
+ postChangesToDocument = !1;
397
+ /** System plugin registry */
398
+ plugins = new T();
399
+ /**
400
+ * Creates a new Blac instance.
401
+ * @param options - Configuration options including singleton control
402
+ */
403
+ constructor(e = {}) {
404
+ const { __unsafe_ignore_singleton: t = !1 } = e;
405
+ if (!t)
406
+ return o.instance;
407
+ b.setInstance(this), this.plugins.bootstrap();
408
+ }
409
+ /** Flag to enable/disable logging */
410
+ static enableLog = !1;
411
+ static logLevel = "warn";
412
+ static logSpy = null;
413
+ /**
414
+ * Logs messages to console when logging is enabled
415
+ * @param args - Arguments to log
416
+ */
417
+ log = (...e) => {
418
+ o.logSpy && o.logSpy(e), o.enableLog && o.logLevel, o.enableLog && o.logLevel;
419
+ };
420
+ static get log() {
421
+ return o.instance.log;
422
+ }
423
+ /**
424
+ * Gets the current Blac instance
425
+ * @returns The Blac instance
426
+ */
427
+ static getInstance() {
428
+ return b.getInstance();
429
+ }
430
+ /**
431
+ * Logs a warning message
432
+ * @param message - Warning message
433
+ * @param args - Additional arguments
434
+ */
435
+ warn = (e, ...t) => {
436
+ console.warn(e, ...t);
437
+ };
438
+ static get warn() {
439
+ return o.instance.warn;
440
+ }
441
+ /**
442
+ * Logs an error message
443
+ * @param message - Error message
444
+ * @param args - Additional arguments
445
+ */
446
+ error = (e, ...t) => {
447
+ o.enableLog && console.error(e, ...t);
448
+ };
449
+ static get error() {
450
+ return o.instance.error;
451
+ }
452
+ /**
453
+ * Resets the Blac instance to a new one, disposing non-keepAlive blocs
454
+ * from the old instance.
455
+ */
456
+ resetInstance = () => {
457
+ this.log("Reset Blac instance");
458
+ const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
459
+ e.forEach((s) => {
460
+ !s._keepAlive && s._disposalState === u.ACTIVE && this.disposeBloc(s);
461
+ }), t.forEach((s) => {
462
+ s.forEach((i) => {
463
+ !i._keepAlive && i._disposalState === u.ACTIVE && this.disposeBloc(i);
464
+ });
465
+ }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), b.resetInstance();
466
+ };
467
+ static resetInstance = () => {
468
+ b.resetInstance();
469
+ };
470
+ /**
471
+ * Disposes of a bloc instance by removing it from the appropriate registry
472
+ * @param bloc - The bloc instance to dispose
473
+ */
474
+ disposeBloc = (e) => {
475
+ const t = e._disposalState;
476
+ if (![
477
+ u.ACTIVE,
478
+ u.DISPOSAL_REQUESTED
479
+ ].includes(t)) {
480
+ this.log(
481
+ `[${e._name}:${String(e._id)}] disposeBloc called on bloc in invalid state: ${t}`
482
+ );
483
+ return;
484
+ }
485
+ const i = e.constructor, n = this.createBlocInstanceMapKey(e._name, e._id);
486
+ this.log(
487
+ `[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(i.isolated)}`
488
+ ), e.dispose(), this.plugins.notifyBlocDisposed(e), i.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(n)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
489
+ };
490
+ static get disposeBloc() {
491
+ return o.instance.disposeBloc;
492
+ }
493
+ /**
494
+ * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
495
+ * @param blocClassName - The name of the bloc class
496
+ * @param id - The instance ID
497
+ * @returns A unique key string in the format "className:id"
498
+ */
499
+ createBlocInstanceMapKey(e, t) {
500
+ return `${e}:${String(t)}`;
501
+ }
502
+ /**
503
+ * Unregister a bloc instance from the main registry
504
+ * @param bloc - The bloc instance to unregister
505
+ */
506
+ unregisterBlocInstance(e) {
507
+ const t = this.createBlocInstanceMapKey(e._name, e._id);
508
+ this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
509
+ }
510
+ /**
511
+ * Registers a bloc instance in the main registry
512
+ * @param bloc - The bloc instance to register
513
+ */
514
+ registerBlocInstance(e) {
515
+ const t = this.createBlocInstanceMapKey(e._name, e._id);
516
+ this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
517
+ }
518
+ /**
519
+ * Finds a registered bloc instance by its class and ID
520
+ * @param blocClass - The bloc class to search for
521
+ * @param id - The instance ID
522
+ * @returns The found bloc instance or undefined if not found
523
+ */
524
+ findRegisteredBlocInstance(e, t) {
525
+ if (e.isolated) return;
526
+ const i = this.createBlocInstanceMapKey(e.name, t), n = this.blocInstanceMap.get(i);
527
+ if (!(n && n.isDisposed))
528
+ return n;
529
+ }
530
+ /**
531
+ * Registers an isolated bloc instance in the isolated registry
532
+ * @param bloc - The isolated bloc instance to register
533
+ */
534
+ registerIsolatedBlocInstance(e) {
535
+ const t = e.constructor, s = this.isolatedBlocMap.get(t);
536
+ 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);
537
+ }
538
+ /**
539
+ * Unregister an isolated bloc instance from the isolated registry
540
+ * @param bloc - The isolated bloc instance to unregister
541
+ */
542
+ unregisterIsolatedBlocInstance(e) {
543
+ const t = e.constructor, s = this.isolatedBlocMap.get(t);
544
+ let i = !1;
545
+ if (s) {
546
+ const a = s.findIndex((c) => c.uid === e.uid);
547
+ a !== -1 && (s.splice(a, 1), i = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
548
+ }
549
+ const n = this.isolatedBlocIndex.delete(e.uid);
550
+ this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), i !== n && this.warn(
551
+ `[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${i}, Index removal: ${n}`
552
+ );
553
+ }
554
+ /**
555
+ * Finds an isolated bloc instance by its class and ID (O(n) lookup)
556
+ */
557
+ findIsolatedBlocInstance(e, t) {
558
+ if (!e.isolated) return;
559
+ const i = this.isolatedBlocMap.get(e);
560
+ return i ? i.find((a) => a._id === t && !a.isDisposed) : void 0;
561
+ }
562
+ /**
563
+ * Finds an isolated bloc instance by UID (O(1) lookup)
564
+ */
565
+ findIsolatedBlocInstanceByUid(e) {
566
+ return this.isolatedBlocIndex.get(e);
567
+ }
568
+ /**
569
+ * Creates a new bloc instance and registers it in the appropriate registry
570
+ * @param blocClass - The bloc class to instantiate
571
+ * @param id - The instance ID
572
+ * @param props - Properties to pass to the bloc constructor
573
+ * @param instanceRef - Optional reference string for the instance
574
+ * @returns The newly created bloc instance
575
+ */
576
+ createNewBlocInstance(e, t, s = {}) {
577
+ const { constructorParams: i, instanceRef: n } = s, a = new e(i);
578
+ return a.blacInstance = this, a._instanceRef = n, a._id = t, a.setDisposalHandler((c) => this.disposeBloc(c)), a.isIsolated ? this.registerIsolatedBlocInstance(a) : this.registerBlocInstance(a), this.plugins.notifyBlocCreated(a), a;
579
+ }
580
+ activateBloc = (e) => {
581
+ if (e._disposalState !== u.ACTIVE) {
582
+ this.log(
583
+ `[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`
584
+ );
585
+ return;
586
+ }
587
+ const t = e.constructor;
588
+ (e.isIsolated ? this.findIsolatedBlocInstance(t, e._id) : this.findRegisteredBlocInstance(t, e._id)) || (this.log(
589
+ `[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`
590
+ ), e.isIsolated ? this.registerIsolatedBlocInstance(e) : this.registerBlocInstance(e));
591
+ };
592
+ static get activateBloc() {
593
+ return o.instance.activateBloc;
594
+ }
595
+ /**
596
+ * Gets or creates a bloc instance based on the provided class and options.
597
+ * If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
598
+ *
599
+ * @param blocClass - The bloc class to get or create
600
+ * @param options - Options including:
601
+ * - id: The instance ID (defaults to class name if not provided)
602
+ * - props: Properties to pass to the bloc constructor
603
+ * - instanceRef: Optional reference string for the instance
604
+ * @returns The bloc instance
605
+ */
606
+ getBloc = (e, t = {}) => {
607
+ const { id: s, forceNewInstance: i } = t, n = e, a = s ?? e.name;
608
+ if (this.log(`[${e.name}:${String(a)}] (getBloc) Called:`, {
609
+ options: t,
610
+ base: n
611
+ }), !i)
612
+ if (n.isolated) {
613
+ const l = this.findIsolatedBlocInstance(
614
+ e,
615
+ t.instanceRef ?? a
616
+ );
617
+ if (l)
618
+ return l;
619
+ if (t.throwIfNotFound)
620
+ throw new Error(`Isolated bloc ${e.name} not found`);
621
+ } else {
622
+ const l = this.findRegisteredBlocInstance(
623
+ e,
624
+ a
625
+ );
626
+ if (l)
627
+ return l;
628
+ if (t.throwIfNotFound)
629
+ throw new Error(`Registered bloc ${e.name} not found`);
625
630
  }
631
+ const c = this.createNewBlocInstance(e, a, t);
632
+ if (this.log(
633
+ `[${e.name}:${String(a)}] (getBloc) No existing instance found. Creating new one.`,
634
+ t,
635
+ c
636
+ ), !c)
637
+ throw new Error(
638
+ `[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
639
+ );
640
+ return c;
641
+ };
642
+ static get getBloc() {
643
+ return o.instance.getBloc;
644
+ }
645
+ /**
646
+ * Gets all instances of a specific bloc class
647
+ * @param blocClass - The bloc class to search for
648
+ * @param options - Options including:
649
+ * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
650
+ * @returns Array of matching bloc instances
651
+ */
652
+ getAllBlocs = (e, t = {}) => {
653
+ const s = [];
654
+ if (this.blocInstanceMap.forEach((i) => {
655
+ i.constructor === e && s.push(i);
656
+ }), t.searchIsolated !== !1) {
657
+ const i = this.isolatedBlocMap.get(e);
658
+ i && s.push(...i.map((n) => n));
659
+ }
660
+ return s;
661
+ };
662
+ /**
663
+ * Disposes all keep-alive blocs of a specific type
664
+ * @param blocClass - The bloc class to dispose
665
+ */
666
+ disposeKeepAliveBlocs = (e) => {
667
+ const t = [];
668
+ for (const s of this.keepAliveBlocs)
669
+ (!e || s.constructor === e) && t.push(s);
670
+ t.forEach((s) => s.dispose());
671
+ };
672
+ static get disposeKeepAliveBlocs() {
673
+ return o.instance.disposeKeepAliveBlocs;
674
+ }
675
+ /**
676
+ * Disposes all blocs matching a pattern
677
+ * @param predicate - Function to test each bloc for disposal
678
+ */
679
+ disposeBlocs = (e) => {
680
+ const t = [];
681
+ for (const s of this.blocInstanceMap.values())
682
+ e(s) && t.push(s);
683
+ for (const s of this.isolatedBlocMap.values())
684
+ for (const i of s)
685
+ e(i) && t.push(i);
686
+ t.forEach((s) => s.dispose());
687
+ };
688
+ static get disposeBlocs() {
689
+ return o.instance.disposeBlocs;
690
+ }
691
+ /**
692
+ * Gets memory usage statistics for debugging
693
+ */
694
+ getMemoryStats = () => ({
695
+ totalBlocs: this.uidRegistry.size,
696
+ registeredBlocs: this.blocInstanceMap.size,
697
+ isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(
698
+ (e, t) => e + t.length,
699
+ 0
700
+ ),
701
+ keepAliveBlocs: this.keepAliveBlocs.size,
702
+ isolatedBlocTypes: this.isolatedBlocMap.size
703
+ });
704
+ static get getMemoryStats() {
705
+ return o.instance.getMemoryStats;
706
+ }
707
+ /**
708
+ * Validates subscription references and cleans up orphaned blocs
709
+ */
710
+ validateConsumers = () => {
711
+ for (const e of this.uidRegistry.values())
712
+ e.subscriptionCount === 0 && !e._keepAlive && e._disposalState === u.ACTIVE && setTimeout(() => {
713
+ e.subscriptionCount === 0 && !e._keepAlive && e._disposalState === u.ACTIVE && this.disposeBloc(e);
714
+ }, 1e3);
715
+ };
716
+ static get validateConsumers() {
717
+ return o.instance.validateConsumers;
718
+ }
719
+ /**
720
+ * Bootstrap the Blac instance and all plugins
721
+ */
722
+ bootstrap() {
723
+ this.plugins.bootstrap();
724
+ }
725
+ /**
726
+ * Shutdown the Blac instance and all plugins
727
+ */
728
+ shutdown() {
729
+ this.plugins.shutdown();
730
+ for (const e of this.blocInstanceMap.values())
731
+ e._keepAlive || this.disposeBloc(e);
732
+ for (const e of this.isolatedBlocMap.values())
733
+ for (const t of e)
734
+ t._keepAlive || this.disposeBloc(t);
735
+ }
736
+ }
737
+ function A() {
738
+ return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(r) {
739
+ const e = Math.random() * 16 | 0;
740
+ return (r === "x" ? e : e & 3 | 8).toString(16);
741
+ });
742
+ }
743
+ const x = {
744
+ fatal: (r, e, t, s) => {
745
+ const i = new m(
746
+ r,
747
+ e,
748
+ y.FATAL,
749
+ t,
750
+ s
751
+ );
752
+ throw f.getInstance().handle(i), i;
753
+ },
754
+ error: (r, e, t, s) => {
755
+ const i = new m(
756
+ r,
757
+ e,
758
+ y.ERROR,
759
+ t,
760
+ s
761
+ );
762
+ f.getInstance().handle(i);
763
+ },
764
+ warn: (r, e, t, s) => {
765
+ const i = new m(
766
+ r,
767
+ e,
768
+ y.WARNING,
769
+ t,
770
+ s
771
+ );
772
+ f.getInstance().handle(i);
773
+ },
774
+ info: (r, e, t) => {
775
+ const s = new m(r, e, y.INFO, t);
776
+ f.getInstance().handle(s);
777
+ },
778
+ /**
779
+ * Wraps a function to catch and handle errors
780
+ */
781
+ wrap: (r, e, t, s = y.ERROR) => {
782
+ try {
783
+ return r();
784
+ } catch (i) {
785
+ const n = i instanceof Error ? i.message : String(i), a = new m(n, e, s, t, i);
786
+ f.getInstance().handle(a);
787
+ return;
788
+ }
789
+ },
790
+ /**
791
+ * Wraps an async function to catch and handle errors
792
+ */
793
+ wrapAsync: async (r, e, t, s = y.ERROR) => {
794
+ try {
795
+ return await r();
796
+ } catch (i) {
797
+ const n = i instanceof Error ? i.message : String(i), a = new m(n, e, s, t, i);
798
+ f.getInstance().handle(a);
799
+ return;
800
+ }
801
+ }
802
+ };
803
+ class w {
804
+ plugins = /* @__PURE__ */ new Map();
805
+ executionOrder = [];
806
+ attached = !1;
807
+ /**
808
+ * Add a bloc plugin
809
+ */
810
+ add(e) {
811
+ if (this.plugins.has(e.name))
812
+ throw new Error(`Plugin '${e.name}' is already registered`);
813
+ e.capabilities && this.validateCapabilities(e), this.plugins.set(e.name, e), this.executionOrder.push(e.name);
814
+ }
815
+ /**
816
+ * Remove a bloc plugin
817
+ */
818
+ remove(e) {
819
+ const t = this.plugins.get(e);
820
+ return t ? (this.attached && t.onDetach && x.wrap(() => t.onDetach(), v.PLUGIN, {
821
+ pluginName: e,
822
+ operation: "onDetach"
823
+ }), this.plugins.delete(e), this.executionOrder = this.executionOrder.filter(
824
+ (s) => s !== e
825
+ ), !0) : !1;
826
+ }
827
+ /**
828
+ * Get a plugin by name
829
+ */
830
+ get(e) {
831
+ return this.plugins.get(e);
832
+ }
833
+ /**
834
+ * Get all plugins in execution order
835
+ */
836
+ getAll() {
837
+ return this.executionOrder.map((e) => this.plugins.get(e));
838
+ }
839
+ /**
840
+ * Clear all plugins
841
+ */
842
+ clear() {
843
+ if (this.attached)
844
+ for (const e of this.getAll())
845
+ e.onDetach && x.wrap(() => e.onDetach(), v.PLUGIN, {
846
+ pluginName: e.name,
847
+ operation: "onDetach"
848
+ });
849
+ this.plugins.clear(), this.executionOrder = [], this.attached = !1;
850
+ }
851
+ /**
852
+ * Attach all plugins to a bloc
853
+ */
854
+ attach(e) {
855
+ if (this.attached)
856
+ throw new Error("Plugins are already attached");
857
+ for (const t of this.getAll())
858
+ if (t.onAttach)
859
+ try {
860
+ t.onAttach(e);
861
+ } catch (s) {
862
+ console.error(`Plugin '${t.name}' error in onAttach:`, s), this.remove(t.name);
863
+ }
864
+ this.attached = !0;
865
+ }
866
+ /**
867
+ * Transform state through all plugins
868
+ */
869
+ transformState(e, t) {
870
+ let s = t;
871
+ for (const i of this.getAll())
872
+ if (i.transformState && this.canTransformState(i))
873
+ try {
874
+ s = i.transformState(
875
+ e,
876
+ s
877
+ );
878
+ } catch (n) {
879
+ console.error(
880
+ `Plugin '${i.name}' error in transformState:`,
881
+ n
882
+ );
883
+ }
884
+ return s;
885
+ }
886
+ /**
887
+ * Transform event through all plugins
888
+ */
889
+ transformEvent(e) {
890
+ let t = e;
891
+ for (const s of this.getAll()) {
892
+ if (t === null) break;
893
+ if (s.transformEvent && this.canInterceptEvents(s))
894
+ try {
895
+ t = s.transformEvent(t);
896
+ } catch (i) {
897
+ console.error(
898
+ `Plugin '${s.name}' error in transformEvent:`,
899
+ i
900
+ );
901
+ }
902
+ }
903
+ return t;
904
+ }
905
+ /**
906
+ * Notify plugins of state change
907
+ */
908
+ notifyStateChange(e, t) {
909
+ for (const s of this.getAll())
910
+ if (s.onStateChange && this.canReadState(s))
911
+ try {
912
+ s.onStateChange(e, t);
913
+ } catch (i) {
914
+ console.error(
915
+ `Plugin '${s.name}' error in onStateChange:`,
916
+ i
917
+ );
918
+ }
919
+ }
920
+ /**
921
+ * Notify plugins of event
922
+ */
923
+ notifyEvent(e) {
924
+ for (const t of this.getAll())
925
+ if (t.onEvent && this.canReadState(t))
926
+ try {
927
+ t.onEvent(e);
928
+ } catch (s) {
929
+ console.error(`Plugin '${t.name}' error in onEvent:`, s);
930
+ }
626
931
  }
627
932
  /**
628
- * Remove a plugin from this bloc instance
933
+ * Notify plugins of error
629
934
  */
630
- removePlugin(e) {
631
- return this._plugins.remove(e);
935
+ notifyError(e, t) {
936
+ for (const s of this.getAll())
937
+ if (s.onError)
938
+ try {
939
+ s.onError(e, t);
940
+ } catch (i) {
941
+ console.error(`Plugin '${s.name}' error in onError:`, i);
942
+ }
943
+ }
944
+ validateCapabilities(e) {
945
+ const t = e.capabilities;
946
+ if (t.transformState && !t.readState)
947
+ throw new Error(
948
+ `Plugin '${e.name}': transformState requires readState capability`
949
+ );
950
+ if (t.interceptEvents && !t.readState)
951
+ throw new Error(
952
+ `Plugin '${e.name}': interceptEvents requires readState capability`
953
+ );
954
+ }
955
+ canReadState(e) {
956
+ return !e.capabilities || e.capabilities.readState !== !1;
957
+ }
958
+ canTransformState(e) {
959
+ return !e.capabilities || e.capabilities.transformState === !0;
960
+ }
961
+ canInterceptEvents(e) {
962
+ return !e.capabilities || e.capabilities.interceptEvents === !0;
963
+ }
964
+ }
965
+ class E {
966
+ constructor(e) {
967
+ this.bloc = e;
632
968
  }
969
+ subscriptions = /* @__PURE__ */ new Map();
970
+ pathToSubscriptions = /* @__PURE__ */ new Map();
971
+ weakRefCleanupScheduled = !1;
972
+ totalNotifications = 0;
633
973
  /**
634
- * Get a plugin by name
974
+ * Subscribe to state changes
635
975
  */
636
- getPlugin(e) {
637
- return this._plugins.get(e);
976
+ subscribe(e) {
977
+ const t = `${e.type}-${A()}`, s = {
978
+ id: t,
979
+ type: e.type,
980
+ selector: e.selector,
981
+ equalityFn: e.equalityFn || Object.is,
982
+ notify: e.notify,
983
+ priority: e.priority ?? 0,
984
+ weakRef: e.weakRef,
985
+ dependencies: /* @__PURE__ */ new Set(),
986
+ metadata: {
987
+ lastNotified: Date.now(),
988
+ hasRendered: !1,
989
+ accessCount: 0,
990
+ firstAccessTime: Date.now()
991
+ }
992
+ };
993
+ if (s.selector)
994
+ try {
995
+ s.lastValue = s.selector(
996
+ this.bloc.state,
997
+ this.bloc
998
+ );
999
+ } catch (i) {
1000
+ o.error(`SubscriptionManager: Error in selector for ${t}:`, i);
1001
+ }
1002
+ return this.subscriptions.set(t, s), o.log(
1003
+ `[${this.bloc._name}:${this.bloc._id}] Subscription added: ${t}. Total: ${this.subscriptions.size}`
1004
+ ), this.bloc._cancelDisposalIfRequested(), () => this.unsubscribe(t);
638
1005
  }
639
1006
  /**
640
- * Get all plugins
1007
+ * Unsubscribe by ID
641
1008
  */
642
- getPlugins() {
643
- return this._plugins.getAll();
1009
+ unsubscribe(e) {
1010
+ const t = this.subscriptions.get(e);
1011
+ if (t) {
1012
+ if (t.dependencies)
1013
+ for (const s of t.dependencies) {
1014
+ const i = this.pathToSubscriptions.get(s);
1015
+ i && (i.delete(e), i.size === 0 && this.pathToSubscriptions.delete(s));
1016
+ }
1017
+ this.subscriptions.delete(e), o.log(
1018
+ `[${this.bloc._name}:${this.bloc._id}] Subscription removed: ${e}. Remaining: ${this.subscriptions.size}`
1019
+ ), this.bloc.checkDisposal();
1020
+ }
644
1021
  }
645
1022
  /**
646
- * @internal
647
- * Activate plugins when bloc becomes active
1023
+ * Notify all subscriptions of state change
648
1024
  */
649
- _activatePlugins() {
650
- if (this._disposalState === "active")
651
- try {
652
- this._plugins.attach(this);
653
- } catch (e) {
654
- console.error(`Failed to activate plugins for ${this._name}:`, e);
1025
+ notify(e, t, s) {
1026
+ this.cleanupDeadReferences();
1027
+ const i = Array.from(this.subscriptions.values()).sort(
1028
+ (n, a) => (a.priority ?? 0) - (n.priority ?? 0)
1029
+ );
1030
+ for (const n of i) {
1031
+ if (n.weakRef && !n.weakRef.deref()) {
1032
+ this.scheduleWeakRefCleanup();
1033
+ continue;
1034
+ }
1035
+ let a = !1, c, l;
1036
+ if (n.selector)
1037
+ try {
1038
+ c = n.selector(e, this.bloc), l = n.lastValue, a = !(n.equalityFn || Object.is)(l, c), a && (n.lastValue = c);
1039
+ } catch (h) {
1040
+ o.error(
1041
+ `SubscriptionManager: Error in selector for ${n.id}:`,
1042
+ h
1043
+ );
1044
+ continue;
1045
+ }
1046
+ else {
1047
+ if (n.dependencies && n.dependencies.size > 0) {
1048
+ const h = this.getChangedPaths(t, e);
1049
+ a = this.shouldNotifyForPaths(
1050
+ n.id,
1051
+ h
1052
+ ), o.config.logLevel === "debug" && (o.log(
1053
+ `[SubscriptionManager] Subscription ${n.id} dependencies:`,
1054
+ Array.from(n.dependencies)
1055
+ ), o.log(
1056
+ "[SubscriptionManager] Changed paths:",
1057
+ Array.from(h)
1058
+ ), o.log("[SubscriptionManager] Should notify:", a));
1059
+ } else
1060
+ a = !0;
1061
+ c = e, l = t;
655
1062
  }
1063
+ if (a)
1064
+ try {
1065
+ n.notify(c, l, s), this.totalNotifications++, n.metadata && (n.metadata.lastNotified = Date.now(), n.metadata.hasRendered = !0);
1066
+ } catch (h) {
1067
+ o.error(
1068
+ `SubscriptionManager: Error in notify for ${n.id}:`,
1069
+ h
1070
+ );
1071
+ }
1072
+ }
656
1073
  }
657
- }
658
- /**
659
- * When true, every consumer will receive its own unique instance of this Bloc.
660
- * Use this when state should not be shared between components.
661
- * @default false
662
- */
663
- i(k, "isolated", !1), /**
664
- * When true, the Bloc instance persists even when there are no active consumers.
665
- * Useful for maintaining state between component unmount/remount cycles.
666
- * @default false
667
- */
668
- i(k, "keepAlive", !1);
669
- class U {
670
- constructor() {
671
- i(this, "plugins", /* @__PURE__ */ new Map());
672
- i(this, "metrics", /* @__PURE__ */ new Map());
673
- i(this, "executionOrder", []);
1074
+ /**
1075
+ * Track a path access for a subscription
1076
+ */
1077
+ trackAccess(e, t, s) {
1078
+ const i = this.subscriptions.get(e);
1079
+ if (!i) return;
1080
+ i.dependencies || (i.dependencies = /* @__PURE__ */ new Set()), i.dependencies.add(t);
1081
+ let n = this.pathToSubscriptions.get(t);
1082
+ n || (n = /* @__PURE__ */ new Set(), this.pathToSubscriptions.set(t, n)), n.add(e), i.metadata && (i.metadata.accessCount = (i.metadata.accessCount || 0) + 1, i.metadata.lastAccessTime = Date.now());
1083
+ }
1084
+ /**
1085
+ * Get the paths that changed between two states
1086
+ */
1087
+ getChangedPaths(e, t, s = "") {
1088
+ const i = /* @__PURE__ */ new Set();
1089
+ if (e === t) return i;
1090
+ if (typeof e != "object" || typeof t != "object" || e === null || t === null)
1091
+ return s && i.add(s), i;
1092
+ const n = /* @__PURE__ */ new Set([
1093
+ ...Object.keys(e),
1094
+ ...Object.keys(t)
1095
+ ]);
1096
+ for (const a of n) {
1097
+ const c = s ? `${s}.${a}` : a, l = e[a], h = t[a];
1098
+ l !== h && (i.add(c), typeof l == "object" && typeof h == "object" && l !== null && h !== null && this.getChangedPaths(
1099
+ l,
1100
+ h,
1101
+ c
1102
+ ).forEach((S) => i.add(S)));
1103
+ }
1104
+ return i;
674
1105
  }
675
1106
  /**
676
- * Add a system plugin
1107
+ * Check if a subscription should be notified based on changed paths
677
1108
  */
678
- add(e) {
679
- if (this.plugins.has(e.name))
680
- throw new Error(`Plugin '${e.name}' is already registered`);
681
- this.plugins.set(e.name, e), this.executionOrder.push(e.name), this.initializeMetrics(e.name);
1109
+ shouldNotifyForPaths(e, t) {
1110
+ const s = this.subscriptions.get(e);
1111
+ if (!s || !s.dependencies) return !0;
1112
+ for (const i of s.dependencies) {
1113
+ if (i.startsWith("_class.")) {
1114
+ if (t.size > 0)
1115
+ return !0;
1116
+ continue;
1117
+ }
1118
+ if (t.has(i)) return !0;
1119
+ for (const n of t)
1120
+ if (n.startsWith(i + ".") || i.startsWith(n + "."))
1121
+ return !0;
1122
+ }
1123
+ return !1;
682
1124
  }
683
1125
  /**
684
- * Remove a system plugin
1126
+ * Get statistics about subscriptions
685
1127
  */
686
- remove(e) {
687
- return this.plugins.get(e) ? (this.plugins.delete(e), this.metrics.delete(e), this.executionOrder = this.executionOrder.filter((s) => s !== e), !0) : !1;
1128
+ getStats() {
1129
+ let e = 0, t = 0;
1130
+ for (const s of this.subscriptions.values())
1131
+ s.type === "consumer" ? e++ : t++;
1132
+ return {
1133
+ activeSubscriptions: this.subscriptions.size,
1134
+ consumerCount: e,
1135
+ observerCount: t,
1136
+ totalNotifications: this.totalNotifications,
1137
+ trackedDependencies: this.pathToSubscriptions.size
1138
+ };
688
1139
  }
689
1140
  /**
690
- * Get a plugin by name
1141
+ * Clear all subscriptions
691
1142
  */
692
- get(e) {
693
- return this.plugins.get(e);
1143
+ clear() {
1144
+ this.subscriptions.clear(), this.pathToSubscriptions.clear();
694
1145
  }
695
1146
  /**
696
- * Get all plugins in execution order
1147
+ * Get subscription by ID
697
1148
  */
698
- getAll() {
699
- return this.executionOrder.map((e) => this.plugins.get(e));
1149
+ getSubscription(e) {
1150
+ return this.subscriptions.get(e);
700
1151
  }
701
1152
  /**
702
- * Clear all plugins
1153
+ * Check if there are any active subscriptions
703
1154
  */
704
- clear() {
705
- this.plugins.clear(), this.metrics.clear(), this.executionOrder = [];
1155
+ get hasSubscriptions() {
1156
+ return this.subscriptions.size > 0;
706
1157
  }
707
1158
  /**
708
- * Execute a hook on all plugins
1159
+ * Get count of active subscriptions
709
1160
  */
710
- executeHook(e, t, s) {
711
- for (const r of this.executionOrder) {
712
- const n = this.plugins.get(r), o = n[e];
713
- if (typeof o != "function") continue;
714
- const a = performance.now();
715
- try {
716
- o.apply(n, t), this.recordSuccess(r, e, a);
717
- } catch (l) {
718
- this.recordError(r, e, l), s ? s(l, n) : console.error(`Plugin '${r}' error in hook '${e}':`, l);
719
- }
720
- }
1161
+ get size() {
1162
+ return this.subscriptions.size;
721
1163
  }
722
1164
  /**
723
- * Bootstrap all plugins
1165
+ * Clean up subscriptions with dead weak references
724
1166
  */
725
- bootstrap() {
726
- this.executeHook("beforeBootstrap", []), this.executeHook("afterBootstrap", []);
1167
+ cleanupDeadReferences() {
1168
+ if (!this.weakRefCleanupScheduled) return;
1169
+ const e = [];
1170
+ for (const [t, s] of this.subscriptions)
1171
+ s.weakRef && !s.weakRef.deref() && e.push(t);
1172
+ for (const t of e)
1173
+ this.unsubscribe(t);
1174
+ this.weakRefCleanupScheduled = !1;
727
1175
  }
728
1176
  /**
729
- * Shutdown all plugins
1177
+ * Schedule weak reference cleanup for next tick
730
1178
  */
731
- shutdown() {
732
- this.executeHook("beforeShutdown", []), this.executeHook("afterShutdown", []);
1179
+ scheduleWeakRefCleanup() {
1180
+ this.weakRefCleanupScheduled || (this.weakRefCleanupScheduled = !0, queueMicrotask(() => this.cleanupDeadReferences()));
733
1181
  }
1182
+ }
1183
+ class D {
1184
+ pendingUpdates = [];
1185
+ isBatching = !1;
734
1186
  /**
735
- * Notify plugins of bloc creation
1187
+ * Execute a callback with batched updates
736
1188
  */
737
- notifyBlocCreated(e) {
738
- this.executeHook("onBlocCreated", [e]);
1189
+ batchUpdates(e, t) {
1190
+ if (this.isBatching) {
1191
+ e();
1192
+ return;
1193
+ }
1194
+ this.isBatching = !0, this.pendingUpdates = [];
1195
+ try {
1196
+ if (e(), this.pendingUpdates.length > 0) {
1197
+ const s = this.pendingUpdates[this.pendingUpdates.length - 1];
1198
+ t(s);
1199
+ }
1200
+ } finally {
1201
+ this.isBatching = !1, this.pendingUpdates = [];
1202
+ }
739
1203
  }
740
1204
  /**
741
- * Notify plugins of bloc disposal
1205
+ * Add an update to the batch
742
1206
  */
743
- notifyBlocDisposed(e) {
744
- this.executeHook("onBlocDisposed", [e]);
1207
+ addUpdate(e) {
1208
+ this.isBatching && this.pendingUpdates.push(e);
745
1209
  }
746
1210
  /**
747
- * Notify plugins of state change
1211
+ * Check if currently batching
748
1212
  */
749
- notifyStateChanged(e, t, s) {
750
- this.executeHook("onStateChanged", [e, t, s]);
1213
+ get isCurrentlyBatching() {
1214
+ return this.isBatching;
1215
+ }
1216
+ }
1217
+ class C {
1218
+ uid = A();
1219
+ blacInstance;
1220
+ static isolated = !1;
1221
+ get isIsolated() {
1222
+ return this._isolated;
1223
+ }
1224
+ static keepAlive = !1;
1225
+ get isKeepAlive() {
1226
+ return this._keepAlive;
751
1227
  }
1228
+ _isolated = !1;
1229
+ _id;
1230
+ _instanceRef;
1231
+ _name;
752
1232
  /**
753
- * Notify plugins of event addition
1233
+ * Unified subscription manager for all state notifications
754
1234
  */
755
- notifyEventAdded(e, t) {
756
- this.executeHook("onEventAdded", [e, t]);
757
- }
1235
+ _subscriptionManager;
1236
+ _state;
1237
+ _lifecycleManager = new B();
1238
+ _batchingManager = new D();
1239
+ _keepAlive = !1;
1240
+ lastUpdate;
1241
+ _plugins = new w();
1242
+ onDispose;
758
1243
  /**
759
- * Notify plugins of errors
1244
+ * Creates a new BlocBase instance with unified subscription management
760
1245
  */
761
- notifyError(e, t, s) {
762
- this.executeHook("onError", [e, t, s], (r, n) => {
763
- console.error(`Plugin '${n.name}' error handler failed:`, r);
764
- });
1246
+ constructor(e) {
1247
+ this._state = e, this._id = this.constructor.name, this._name = this.constructor.name, this._subscriptionManager = new E(this);
1248
+ const t = this.constructor;
1249
+ if (this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1, this._plugins = new w(), t.plugins && Array.isArray(t.plugins))
1250
+ for (const s of t.plugins)
1251
+ this._plugins.add(s);
1252
+ this._plugins.attach(this);
765
1253
  }
766
1254
  /**
767
- * Get metrics for a plugin
1255
+ * Returns the current state
768
1256
  */
769
- getMetrics(e) {
770
- return this.metrics.get(e);
771
- }
772
- initializeMetrics(e) {
773
- this.metrics.set(e, /* @__PURE__ */ new Map());
1257
+ get state() {
1258
+ return this._lifecycleManager.isDisposed ? this._state : this._state;
774
1259
  }
775
- recordSuccess(e, t, s) {
776
- const r = this.metrics.get(e), n = r.get(t) || {
777
- executionTime: 0,
778
- executionCount: 0,
779
- errorCount: 0
780
- }, o = performance.now() - s;
781
- r.set(t, {
782
- ...n,
783
- executionTime: n.executionTime + o,
784
- executionCount: n.executionCount + 1,
785
- lastExecutionTime: o
1260
+ /**
1261
+ * Subscribe to all state changes
1262
+ */
1263
+ subscribe(e) {
1264
+ return this._subscriptionManager.subscribe({
1265
+ type: "observer",
1266
+ notify: (t) => e(t)
786
1267
  });
787
1268
  }
788
- recordError(e, t, s) {
789
- const r = this.metrics.get(e), n = r.get(t) || {
790
- executionTime: 0,
791
- executionCount: 0,
792
- errorCount: 0
793
- };
794
- r.set(t, {
795
- ...n,
796
- errorCount: n.errorCount + 1,
797
- lastError: s
1269
+ /**
1270
+ * Subscribe with a selector for optimized updates
1271
+ */
1272
+ subscribeWithSelector(e, t, s) {
1273
+ return this._subscriptionManager.subscribe({
1274
+ type: "consumer",
1275
+ selector: e,
1276
+ equalityFn: s,
1277
+ notify: (i) => t(i)
798
1278
  });
799
1279
  }
800
- }
801
- const _ = class _ {
802
- getInstance() {
803
- return _._instance || (_._instance = new u({
804
- __unsafe_ignore_singleton: !0
805
- })), _._instance;
806
- }
807
- setInstance(e) {
808
- _._instance = e;
809
- }
810
- resetInstance() {
811
- const e = _._instance;
812
- if (_._instance = new u({
813
- __unsafe_ignore_singleton: !0
814
- }), e)
815
- for (const t of e.keepAliveBlocs)
816
- _._instance.keepAliveBlocs.add(t), _._instance.uidRegistry.set(t.uid, t);
817
- }
818
- };
819
- i(_, "_instance");
820
- let E = _, S = new E();
821
- function W(c) {
822
- S = c;
823
- }
824
- const h = class h {
825
1280
  /**
826
- * Creates a new Blac instance.
827
- * @param options - Configuration options including singleton control
1281
+ * Subscribe with React component reference for automatic cleanup
828
1282
  */
829
- constructor(e = {}) {
830
- /** Timestamp when the instance was created */
831
- i(this, "createdAt", Date.now());
832
- /** Map storing all registered bloc instances by their class name and ID */
833
- i(this, "blocInstanceMap", /* @__PURE__ */ new Map());
834
- /** Map storing isolated bloc instances grouped by their constructor */
835
- // Using BlocConstructor<BlocBase<unknown>> would break type inference when storing
836
- // different bloc types in the same map. The 'any' allows proper polymorphic storage
837
- // while maintaining type safety at usage sites through the BlocConstructor constraint.
838
- i(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
839
- /** Map for O(1) lookup of isolated blocs by UID */
840
- i(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
841
- /** Map tracking UIDs to prevent memory leaks */
842
- i(this, "uidRegistry", /* @__PURE__ */ new Map());
843
- /** Set of keep-alive blocs for controlled cleanup */
844
- i(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
845
- /** Flag to control whether changes should be posted to document */
846
- i(this, "postChangesToDocument", !1);
847
- /** System plugin registry */
848
- i(this, "plugins", new U());
849
- /**
850
- * Logs messages to console when logging is enabled
851
- * @param args - Arguments to log
852
- */
853
- i(this, "log", (...e) => {
854
- h.logSpy && h.logSpy(e), h.enableLog && h.logLevel, h.enableLog && h.logLevel;
855
- });
856
- /**
857
- * Logs a warning message
858
- * @param message - Warning message
859
- * @param args - Additional arguments
860
- */
861
- i(this, "warn", (e, ...t) => {
862
- h.enableLog;
863
- });
864
- /**
865
- * Logs an error message
866
- * @param message - Error message
867
- * @param args - Additional arguments
868
- */
869
- i(this, "error", (e, ...t) => {
870
- h.enableLog;
871
- });
872
- /**
873
- * Resets the Blac instance to a new one, disposing non-keepAlive blocs
874
- * from the old instance.
875
- */
876
- i(this, "resetInstance", () => {
877
- this.log("Reset Blac instance");
878
- const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
879
- e.forEach((s) => {
880
- !s._keepAlive && s._disposalState === y.ACTIVE && this.disposeBloc(s);
881
- }), t.forEach((s) => {
882
- s.forEach((r) => {
883
- !r._keepAlive && r._disposalState === y.ACTIVE && this.disposeBloc(r);
884
- });
885
- }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), S.resetInstance();
886
- });
887
- /**
888
- * Disposes of a bloc instance by removing it from the appropriate registry
889
- * @param bloc - The bloc instance to dispose
890
- */
891
- i(this, "disposeBloc", (e) => {
892
- const t = e._disposalState;
893
- if (![
894
- y.ACTIVE,
895
- y.DISPOSAL_REQUESTED
896
- ].includes(t)) {
897
- this.log(
898
- `[${e._name}:${String(e._id)}] disposeBloc called on bloc in invalid state: ${t}`
899
- );
900
- return;
901
- }
902
- const r = e.constructor, n = this.createBlocInstanceMapKey(e._name, e._id);
903
- this.log(
904
- `[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(r.isolated)}`
905
- ), e._dispose(), this.plugins.notifyBlocDisposed(e), r.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(n)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
906
- });
907
- i(this, "activateBloc", (e) => {
908
- if (e._disposalState !== y.ACTIVE) {
909
- this.log(
910
- `[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`
911
- );
912
- return;
913
- }
914
- const t = e.constructor;
915
- (e.isIsolated ? this.findIsolatedBlocInstance(t, e._id) : this.findRegisteredBlocInstance(t, e._id)) || (this.log(
916
- `[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`
917
- ), e.isIsolated ? this.registerIsolatedBlocInstance(e) : this.registerBlocInstance(e));
918
- });
919
- /**
920
- * Gets or creates a bloc instance based on the provided class and options.
921
- * If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
922
- *
923
- * @param blocClass - The bloc class to get or create
924
- * @param options - Options including:
925
- * - id: The instance ID (defaults to class name if not provided)
926
- * - props: Properties to pass to the bloc constructor
927
- * - instanceRef: Optional reference string for the instance
928
- * @returns The bloc instance
929
- */
930
- i(this, "getBloc", (e, t = {}) => {
931
- const { id: s, forceNewInstance: r } = t, n = e, o = s ?? e.name;
932
- if (this.log(`[${e.name}:${String(o)}] (getBloc) Called:`, {
933
- options: t,
934
- base: n
935
- }), !r)
936
- if (n.isolated) {
937
- const l = this.findIsolatedBlocInstance(
938
- e,
939
- t.instanceRef ?? o
940
- );
941
- if (l)
942
- return l;
943
- if (t.throwIfNotFound)
944
- throw new Error(`Isolated bloc ${e.name} not found`);
945
- } else {
946
- const l = this.findRegisteredBlocInstance(
947
- e,
948
- o
949
- );
950
- if (l)
951
- return l;
952
- if (t.throwIfNotFound)
953
- throw new Error(`Registered bloc ${e.name} not found`);
954
- }
955
- const a = this.createNewBlocInstance(e, o, t);
956
- if (this.log(
957
- `[${e.name}:${String(o)}] (getBloc) No existing instance found. Creating new one.`,
958
- t,
959
- a
960
- ), !a)
961
- throw new Error(
962
- `[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
963
- );
964
- return a;
965
- });
966
- /**
967
- * Gets a bloc instance or throws an error if it doesn't exist
968
- * @param blocClass - The bloc class to get
969
- * @param options - Options including:
970
- * - id: The instance ID (defaults to class name if not provided)
971
- * - props: Properties to pass to the bloc constructor
972
- * - instanceRef: Optional reference string for the instance
973
- */
974
- i(this, "getBlocOrThrow", (e, t = {}) => {
975
- const s = e.isolated, r = t.id || e.name, n = s ? this.findIsolatedBlocInstance(e, r) : this.findRegisteredBlocInstance(e, r);
976
- if (n)
977
- return n;
978
- throw new Error(`Bloc ${e.name} not found`);
979
- });
980
- /**
981
- * Gets all instances of a specific bloc class
982
- * @param blocClass - The bloc class to search for
983
- * @param options - Options including:
984
- * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
985
- * @returns Array of matching bloc instances
986
- */
987
- i(this, "getAllBlocs", (e, t = {}) => {
988
- const s = [];
989
- if (this.blocInstanceMap.forEach((r) => {
990
- r.constructor === e && s.push(r);
991
- }), t.searchIsolated !== !1) {
992
- const r = this.isolatedBlocMap.get(e);
993
- r && s.push(...r.map((n) => n));
994
- }
995
- return s;
996
- });
997
- /**
998
- * Disposes all keep-alive blocs of a specific type
999
- * @param blocClass - The bloc class to dispose
1000
- */
1001
- i(this, "disposeKeepAliveBlocs", (e) => {
1002
- const t = [];
1003
- for (const s of this.keepAliveBlocs)
1004
- (!e || s.constructor === e) && t.push(s);
1005
- t.forEach((s) => s._dispose());
1006
- });
1007
- /**
1008
- * Disposes all blocs matching a pattern
1009
- * @param predicate - Function to test each bloc for disposal
1010
- */
1011
- i(this, "disposeBlocs", (e) => {
1012
- const t = [];
1013
- for (const s of this.blocInstanceMap.values())
1014
- e(s) && t.push(s);
1015
- for (const s of this.isolatedBlocMap.values())
1016
- for (const r of s)
1017
- e(r) && t.push(r);
1018
- t.forEach((s) => s._dispose());
1283
+ subscribeComponent(e, t) {
1284
+ return this._subscriptionManager.subscribe({
1285
+ type: "consumer",
1286
+ weakRef: e,
1287
+ notify: t
1019
1288
  });
1020
- /**
1021
- * Gets memory usage statistics for debugging
1022
- */
1023
- i(this, "getMemoryStats", () => ({
1024
- totalBlocs: this.uidRegistry.size,
1025
- registeredBlocs: this.blocInstanceMap.size,
1026
- isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(
1027
- (e, t) => e + t.length,
1028
- 0
1029
- ),
1030
- keepAliveBlocs: this.keepAliveBlocs.size,
1031
- isolatedBlocTypes: this.isolatedBlocMap.size
1032
- }));
1033
- /**
1034
- * Validates consumer references and cleans up orphaned consumers
1035
- */
1036
- i(this, "validateConsumers", () => {
1037
- for (const e of this.uidRegistry.values())
1038
- e._validateConsumers(), e._consumers.size === 0 && !e._keepAlive && e._disposalState === y.ACTIVE && setTimeout(() => {
1039
- e._consumers.size === 0 && !e._keepAlive && e._disposalState === y.ACTIVE && this.disposeBloc(e);
1040
- }, 1e3);
1041
- });
1042
- const { __unsafe_ignore_singleton: t = !1 } = e;
1043
- if (!t)
1044
- return h.instance;
1045
- S.setInstance(this), this.plugins.bootstrap();
1046
- }
1047
- static get instance() {
1048
- return S.getInstance();
1049
- }
1050
- static get getAllBlocs() {
1051
- return h.instance.getAllBlocs;
1052
- }
1053
- /** Get current configuration */
1054
- static get config() {
1055
- return { ...this._config };
1056
1289
  }
1057
1290
  /**
1058
- * Set or update Blac configuration
1059
- * @param config - Partial configuration to merge with existing config
1060
- * @throws Error if configuration is invalid
1291
+ * Get current subscription count
1061
1292
  */
1062
- static setConfig(e) {
1063
- if (e.proxyDependencyTracking !== void 0 && typeof e.proxyDependencyTracking != "boolean")
1064
- throw new Error("BlacConfig.proxyDependencyTracking must be a boolean");
1065
- if (e.exposeBlacInstance !== void 0 && typeof e.exposeBlacInstance != "boolean")
1066
- throw new Error("BlacConfig.exposeBlacInstance must be a boolean");
1067
- this._config = {
1068
- ...this._config,
1069
- ...e
1070
- }, this.enableLog && this.instance.log("Blac config updated:", this._config);
1071
- }
1072
- static get log() {
1073
- return h.instance.log;
1293
+ get subscriptionCount() {
1294
+ return this._subscriptionManager.size;
1074
1295
  }
1075
1296
  /**
1076
- * Gets the current Blac instance
1077
- * @returns The Blac instance
1297
+ * Track property access for a subscription
1078
1298
  */
1079
- static getInstance() {
1080
- return S.getInstance();
1299
+ trackAccess(e, t, s) {
1300
+ this._subscriptionManager.trackAccess(e, t, s);
1081
1301
  }
1082
- static get warn() {
1083
- return h.instance.warn;
1302
+ /**
1303
+ * Emit a new state
1304
+ */
1305
+ emit(e, t) {
1306
+ this._pushState(e, this._state, t);
1084
1307
  }
1085
- static get error() {
1086
- return h.instance.error;
1308
+ /**
1309
+ * Internal state push method used by Bloc
1310
+ */
1311
+ _pushState(e, t, s) {
1312
+ if (this._lifecycleManager.currentState !== u.ACTIVE) {
1313
+ this.blacInstance?.error(
1314
+ `[${this._name}:${this._id}] Attempted state update on ${this._lifecycleManager.currentState} bloc. Update ignored.`
1315
+ );
1316
+ return;
1317
+ }
1318
+ if (e === void 0)
1319
+ return;
1320
+ this._state = e;
1321
+ const i = this._plugins.transformState(
1322
+ t,
1323
+ e
1324
+ );
1325
+ if (this._state = i, this._plugins.notifyStateChange(t, i), this.blacInstance?.plugins.notifyStateChanged(
1326
+ this,
1327
+ t,
1328
+ i
1329
+ ), this._batchingManager.isCurrentlyBatching) {
1330
+ this._batchingManager.addUpdate({
1331
+ newState: i,
1332
+ oldState: t,
1333
+ action: s
1334
+ });
1335
+ return;
1336
+ }
1337
+ this._subscriptionManager.notify(i, t, s), this.lastUpdate = Date.now();
1338
+ }
1339
+ _batchUpdates(e) {
1340
+ this._batchingManager.batchUpdates(e, (t) => {
1341
+ this._subscriptionManager.notify(
1342
+ t.newState,
1343
+ t.oldState,
1344
+ t.action
1345
+ );
1346
+ });
1087
1347
  }
1088
- static get disposeBloc() {
1089
- return h.instance.disposeBloc;
1348
+ /**
1349
+ * Add a plugin
1350
+ */
1351
+ addPlugin(e) {
1352
+ if (this._plugins.add(e), this._plugins.attached && e.onAttach)
1353
+ try {
1354
+ e.onAttach(this);
1355
+ } catch (t) {
1356
+ console.error(`Plugin '${e.name}' error in onAttach:`, t);
1357
+ }
1090
1358
  }
1091
1359
  /**
1092
- * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
1093
- * @param blocClassName - The name of the bloc class
1094
- * @param id - The instance ID
1095
- * @returns A unique key string in the format "className:id"
1360
+ * Remove a plugin
1096
1361
  */
1097
- createBlocInstanceMapKey(e, t) {
1098
- return `${e}:${String(t)}`;
1362
+ removePlugin(e) {
1363
+ this._plugins.remove(e.name);
1099
1364
  }
1100
1365
  /**
1101
- * Unregister a bloc instance from the main registry
1102
- * @param bloc - The bloc instance to unregister
1366
+ * Get all plugins
1103
1367
  */
1104
- unregisterBlocInstance(e) {
1105
- const t = this.createBlocInstanceMapKey(e._name, e._id);
1106
- this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
1368
+ get plugins() {
1369
+ return this._plugins.getAll();
1107
1370
  }
1108
1371
  /**
1109
- * Registers a bloc instance in the main registry
1110
- * @param bloc - The bloc instance to register
1372
+ * Disposal management
1111
1373
  */
1112
- registerBlocInstance(e) {
1113
- const t = this.createBlocInstanceMapKey(e._name, e._id);
1114
- this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
1374
+ get isDisposed() {
1375
+ return this._lifecycleManager.isDisposed;
1115
1376
  }
1116
1377
  /**
1117
- * Finds a registered bloc instance by its class and ID
1118
- * @param blocClass - The bloc class to search for
1119
- * @param id - The instance ID
1120
- * @returns The found bloc instance or undefined if not found
1378
+ * Atomic state transition for disposal
1121
1379
  */
1122
- findRegisteredBlocInstance(e, t) {
1123
- if (e.isolated) return;
1124
- const r = this.createBlocInstanceMapKey(e.name, t);
1125
- return this.blocInstanceMap.get(r);
1380
+ _atomicStateTransition(e, t) {
1381
+ return this._lifecycleManager.atomicStateTransition(
1382
+ e,
1383
+ t
1384
+ );
1126
1385
  }
1127
1386
  /**
1128
- * Registers an isolated bloc instance in the isolated registry
1129
- * @param bloc - The isolated bloc instance to register
1387
+ * Dispose the bloc and clean up resources
1130
1388
  */
1131
- registerIsolatedBlocInstance(e) {
1132
- const t = e.constructor, s = this.isolatedBlocMap.get(t);
1133
- 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);
1389
+ async dispose() {
1390
+ if (!this._lifecycleManager.atomicStateTransition(
1391
+ u.ACTIVE,
1392
+ u.DISPOSING
1393
+ ).success)
1394
+ if (this._lifecycleManager.currentState === u.DISPOSAL_REQUESTED)
1395
+ this._lifecycleManager.atomicStateTransition(
1396
+ u.DISPOSAL_REQUESTED,
1397
+ u.DISPOSING
1398
+ );
1399
+ else
1400
+ return;
1401
+ try {
1402
+ this._subscriptionManager.clear(), this.onDispose && this.onDispose();
1403
+ for (const s of this._plugins.getAll())
1404
+ try {
1405
+ "onDispose" in s && typeof s.onDispose == "function" && s.onDispose(this);
1406
+ } catch (i) {
1407
+ console.error("Plugin disposal error:", i);
1408
+ }
1409
+ const t = this._lifecycleManager.getDisposalHandler();
1410
+ t && t(this);
1411
+ } finally {
1412
+ this._lifecycleManager.atomicStateTransition(
1413
+ u.DISPOSING,
1414
+ u.DISPOSED
1415
+ );
1416
+ }
1134
1417
  }
1135
1418
  /**
1136
- * Unregister an isolated bloc instance from the isolated registry
1137
- * @param bloc - The isolated bloc instance to unregister
1419
+ * Schedule disposal when no subscriptions remain
1138
1420
  */
1139
- unregisterIsolatedBlocInstance(e) {
1140
- const t = e.constructor, s = this.isolatedBlocMap.get(t);
1141
- let r = !1;
1142
- if (s) {
1143
- const o = s.findIndex((a) => a.uid === e.uid);
1144
- o !== -1 && (s.splice(o, 1), r = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
1145
- }
1146
- const n = this.isolatedBlocIndex.delete(e.uid);
1147
- this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), r !== n && this.warn(
1148
- `[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${r}, Index removal: ${n}`
1421
+ _scheduleDisposal() {
1422
+ this._subscriptionManager.size === 0 && !this._keepAlive && this._lifecycleManager.scheduleDisposal(
1423
+ 16,
1424
+ () => this._subscriptionManager.size === 0 && !this._keepAlive,
1425
+ () => this.dispose()
1149
1426
  );
1150
1427
  }
1151
1428
  /**
1152
- * Finds an isolated bloc instance by its class and ID (O(n) lookup)
1429
+ * Set disposal handler
1153
1430
  */
1154
- findIsolatedBlocInstance(e, t) {
1155
- if (!e.isolated) return;
1156
- const r = this.isolatedBlocMap.get(e);
1157
- return r ? r.find((o) => o._id === t) : void 0;
1431
+ setDisposalHandler(e) {
1432
+ this._lifecycleManager.setDisposalHandler(
1433
+ e
1434
+ );
1158
1435
  }
1159
1436
  /**
1160
- * Finds an isolated bloc instance by UID (O(1) lookup)
1437
+ * Check if disposal should be scheduled (called by subscription manager)
1161
1438
  */
1162
- findIsolatedBlocInstanceByUid(e) {
1163
- return this.isolatedBlocIndex.get(e);
1439
+ checkDisposal() {
1440
+ this._subscriptionManager.size === 0 && !this._keepAlive && this._lifecycleManager.currentState === u.ACTIVE && this._scheduleDisposal();
1164
1441
  }
1165
1442
  /**
1166
- * Creates a new bloc instance and registers it in the appropriate registry
1167
- * @param blocClass - The bloc class to instantiate
1168
- * @param id - The instance ID
1169
- * @param props - Properties to pass to the bloc constructor
1170
- * @param instanceRef - Optional reference string for the instance
1171
- * @returns The newly created bloc instance
1443
+ * Cancel disposal if bloc is in disposal_requested state
1172
1444
  */
1173
- createNewBlocInstance(e, t, s = {}) {
1174
- const { props: r, instanceRef: n } = s, o = new e(r);
1175
- 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;
1176
- }
1177
- static get activateBloc() {
1178
- return h.instance.activateBloc;
1179
- }
1180
- static get getBloc() {
1181
- return h.instance.getBloc;
1182
- }
1183
- static get getBlocOrThrow() {
1184
- return h.instance.getBlocOrThrow;
1185
- }
1186
- static get disposeKeepAliveBlocs() {
1187
- return h.instance.disposeKeepAliveBlocs;
1188
- }
1189
- static get disposeBlocs() {
1190
- return h.instance.disposeBlocs;
1191
- }
1192
- static get getMemoryStats() {
1193
- return h.instance.getMemoryStats;
1194
- }
1195
- static get validateConsumers() {
1196
- return h.instance.validateConsumers;
1445
+ _cancelDisposalIfRequested() {
1446
+ this.blacInstance?.log(
1447
+ `[${this._name}:${this._id}] _cancelDisposalIfRequested called. Current state: ${this._lifecycleManager.currentState}`
1448
+ ), this._lifecycleManager.cancelDisposal() ? this.blacInstance?.log(
1449
+ `[${this._name}:${this._id}] Disposal cancelled - new subscription added`
1450
+ ) : this._lifecycleManager.currentState === u.DISPOSAL_REQUESTED ? this.blacInstance?.warn(
1451
+ `[${this._name}:${this._id}] Failed to cancel disposal. Current state: ${this._lifecycleManager.currentState}`
1452
+ ) : this._lifecycleManager.isDisposed && this.blacInstance?.error(
1453
+ `[${this._name}:${this._id}] Cannot cancel disposal - bloc is already disposed`
1454
+ );
1197
1455
  }
1456
+ }
1457
+ class R extends C {
1458
+ eventHandlers = /* @__PURE__ */ new Map();
1198
1459
  /**
1199
- * Bootstrap the Blac instance and all plugins
1460
+ * @internal
1461
+ * Event queue to ensure sequential processing of async events
1200
1462
  */
1201
- bootstrap() {
1202
- this.plugins.bootstrap();
1203
- }
1463
+ _eventQueue = [];
1204
1464
  /**
1205
- * Shutdown the Blac instance and all plugins
1465
+ * @internal
1466
+ * Flag indicating if an event is currently being processed
1206
1467
  */
1207
- shutdown() {
1208
- this.plugins.shutdown();
1209
- for (const e of this.blocInstanceMap.values())
1210
- e._keepAlive || this.disposeBloc(e);
1211
- for (const e of this.isolatedBlocMap.values())
1212
- for (const t of e)
1213
- t._keepAlive || this.disposeBloc(t);
1214
- }
1215
- };
1216
- /** Private static configuration */
1217
- i(h, "_config", {
1218
- exposeBlacInstance: !1,
1219
- proxyDependencyTracking: !0
1220
- }), /** Flag to enable/disable logging */
1221
- i(h, "enableLog", !1), i(h, "logLevel", "warn"), i(h, "logSpy", null), i(h, "resetInstance", () => {
1222
- S.resetInstance();
1223
- });
1224
- let u = h;
1225
- class j extends k {
1226
- constructor() {
1227
- super(...arguments);
1228
- i(this, "eventHandlers", /* @__PURE__ */ new Map());
1229
- /**
1230
- * @internal
1231
- * Event queue to ensure sequential processing of async events
1232
- */
1233
- i(this, "_eventQueue", []);
1234
- /**
1235
- * @internal
1236
- * Flag indicating if an event is currently being processed
1237
- */
1238
- i(this, "_isProcessingEvent", !1);
1239
- /**
1240
- * Dispatches an action/event to the Bloc.
1241
- * Events are queued and processed sequentially to prevent race conditions.
1242
- * @param action The action/event instance to be processed.
1243
- */
1244
- i(this, "add", async (t) => {
1245
- let s = t;
1246
- try {
1247
- s = this._plugins.transformEvent(t);
1248
- } catch (r) {
1249
- console.error("Error transforming event:", r);
1250
- }
1251
- if (s !== null) {
1252
- try {
1253
- this._plugins.notifyEvent(s);
1254
- } catch (r) {
1255
- console.error("Error notifying plugins of event:", r);
1256
- }
1257
- u.instance.plugins.notifyEventAdded(this, s), this._eventQueue.push(s), this._isProcessingEvent || await this._processEventQueue();
1258
- }
1259
- });
1260
- }
1468
+ _isProcessingEvent = !1;
1261
1469
  /**
1262
1470
  * Registers an event handler for a specific event type.
1263
1471
  * This method is typically called in the constructor of a derived Bloc class.
@@ -1265,14 +1473,35 @@ class j extends k {
1265
1473
  * @param handler A function that processes the event and can emit new states.
1266
1474
  * The 'event' parameter in the handler will be typed to the specific eventConstructor.
1267
1475
  */
1268
- on(t, s) {
1269
- this.eventHandlers.has(t) && u.warn(
1270
- `[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`
1476
+ on(e, t) {
1477
+ this.eventHandlers.has(e) && o.warn(
1478
+ `[Bloc ${this._name}:${String(this._id)}] Handler for event '${e.name}' already registered. It will be overwritten.`
1271
1479
  ), this.eventHandlers.set(
1272
- t,
1273
- s
1480
+ e,
1481
+ t
1274
1482
  );
1275
1483
  }
1484
+ /**
1485
+ * Dispatches an action/event to the Bloc.
1486
+ * Events are queued and processed sequentially to prevent race conditions.
1487
+ * @param action The action/event instance to be processed.
1488
+ */
1489
+ add = async (e) => {
1490
+ let t = e;
1491
+ try {
1492
+ t = this._plugins.transformEvent(e);
1493
+ } catch (s) {
1494
+ console.error("Error transforming event:", s);
1495
+ }
1496
+ if (t !== null) {
1497
+ try {
1498
+ this._plugins.notifyEvent(t);
1499
+ } catch (s) {
1500
+ console.error("Error notifying plugins of event:", s);
1501
+ }
1502
+ o.instance.plugins.notifyEventAdded(this, t), this._eventQueue.push(t), this._isProcessingEvent || await this._processEventQueue();
1503
+ }
1504
+ };
1276
1505
  /**
1277
1506
  * @internal
1278
1507
  * Processes events from the queue sequentially
@@ -1282,8 +1511,8 @@ class j extends k {
1282
1511
  this._isProcessingEvent = !0;
1283
1512
  try {
1284
1513
  for (; this._eventQueue.length > 0; ) {
1285
- const t = this._eventQueue.shift();
1286
- await this._processEvent(t);
1514
+ const e = this._eventQueue.shift();
1515
+ await this._processEvent(e);
1287
1516
  }
1288
1517
  } finally {
1289
1518
  this._isProcessingEvent = !1;
@@ -1294,68 +1523,59 @@ class j extends k {
1294
1523
  * @internal
1295
1524
  * Processes a single event
1296
1525
  */
1297
- async _processEvent(t) {
1298
- const s = t.constructor, r = this.eventHandlers.get(s);
1299
- if (r) {
1300
- const n = (o) => {
1526
+ async _processEvent(e) {
1527
+ const t = e.constructor, s = this.eventHandlers.get(t);
1528
+ if (s) {
1529
+ const i = (n) => {
1301
1530
  const a = this.state;
1302
- this._pushState(o, a, t);
1531
+ this._pushState(n, a, e);
1303
1532
  };
1304
1533
  try {
1305
- await r(t, n);
1306
- } catch (o) {
1307
- const a = t.constructor.name || "UnnamedConstructor", l = {
1534
+ await s(e, i);
1535
+ } catch (n) {
1536
+ const a = e.constructor.name || "UnnamedConstructor", c = {
1308
1537
  blocName: this._name,
1309
1538
  blocId: String(this._id),
1310
1539
  eventType: a,
1311
1540
  currentState: this.state,
1312
- action: t,
1541
+ action: e,
1313
1542
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1314
1543
  };
1315
- if (u.error(
1544
+ if (o.error(
1316
1545
  `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${a}':`,
1317
- o,
1546
+ n,
1318
1547
  "Context:",
1319
- l
1320
- ), o instanceof Error)
1548
+ c
1549
+ ), n instanceof Error)
1321
1550
  try {
1322
- this._plugins.notifyError(o, {
1551
+ this._plugins.notifyError(n, {
1323
1552
  phase: "event-processing",
1324
1553
  operation: "handler",
1325
- metadata: { event: t }
1326
- }), u.instance.plugins.notifyError(o, this, {
1554
+ metadata: { event: e }
1555
+ }), o.instance.plugins.notifyError(n, this, {
1327
1556
  phase: "event-processing",
1328
1557
  operation: "handler",
1329
- metadata: { event: t }
1558
+ metadata: { event: e }
1330
1559
  });
1331
- } catch (d) {
1332
- console.error("Error notifying plugins:", d);
1560
+ } catch (l) {
1561
+ console.error("Error notifying plugins:", l);
1333
1562
  }
1334
- if (o instanceof Error && o.name === "CriticalError")
1335
- throw o;
1563
+ if (n instanceof Error && n.name === "CriticalError")
1564
+ throw n;
1336
1565
  }
1337
1566
  } else {
1338
- const n = t.constructor.name || "UnnamedConstructor";
1339
- u.warn(
1340
- `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${n}'.`,
1567
+ const i = e.constructor.name || "UnnamedConstructor";
1568
+ o.warn(
1569
+ `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${i}'.`,
1341
1570
  "Registered handlers:",
1342
- Array.from(this.eventHandlers.keys()).map((o) => o.name),
1571
+ Array.from(this.eventHandlers.keys()).map((n) => n.name),
1343
1572
  "Action was:",
1344
- t
1573
+ e
1345
1574
  );
1346
1575
  }
1347
1576
  }
1348
1577
  }
1349
- class z extends k {
1350
- /**
1351
- * @internal
1352
- * Protected method for useBloc to call
1353
- */
1354
- _updateProps(e) {
1355
- var s;
1356
- const t = this.props;
1357
- this.props = e, (s = this.onPropsChanged) == null || s.call(this, t, e);
1358
- }
1578
+ class O extends C {
1359
1579
  /**
1360
1580
  * Updates the current state and notifies all observers of the change.
1361
1581
  * If the new state is identical to the current state (using Object.is),
@@ -1378,7 +1598,7 @@ class z extends k {
1378
1598
  */
1379
1599
  patch(e, t = !1) {
1380
1600
  if (typeof this.state != "object" || this.state === null) {
1381
- u.warn(
1601
+ o.warn(
1382
1602
  "Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
1383
1603
  );
1384
1604
  return;
@@ -1387,10 +1607,10 @@ class z extends k {
1387
1607
  if (t)
1388
1608
  s = !0;
1389
1609
  else
1390
- for (const r in e)
1391
- if (Object.prototype.hasOwnProperty.call(e, r)) {
1392
- const o = this.state[r];
1393
- if (!Object.is(e[r], o)) {
1610
+ for (const i in e)
1611
+ if (Object.prototype.hasOwnProperty.call(e, i)) {
1612
+ const a = this.state[i];
1613
+ if (!Object.is(e[i], a)) {
1394
1614
  s = !0;
1395
1615
  break;
1396
1616
  }
@@ -1406,107 +1626,232 @@ class L {
1406
1626
  this.props = e;
1407
1627
  }
1408
1628
  }
1409
- function N(c, e) {
1410
- if (Object.is(c, e))
1629
+ function V(r, e) {
1630
+ if (Object.is(r, e))
1411
1631
  return !0;
1412
- if (typeof c != "object" || c === null || typeof e != "object" || e === null)
1632
+ if (typeof r != "object" || r === null || typeof e != "object" || e === null)
1413
1633
  return !1;
1414
- const t = Object.keys(c), s = Object.keys(e);
1634
+ const t = Object.keys(r), s = Object.keys(e);
1415
1635
  if (t.length !== s.length)
1416
1636
  return !1;
1417
- for (let r = 0; r < t.length; r++) {
1418
- const n = t[r];
1419
- if (!Object.prototype.hasOwnProperty.call(e, n) || !Object.is(c[n], e[n]))
1637
+ for (let i = 0; i < t.length; i++) {
1638
+ const n = t[i];
1639
+ if (!Object.prototype.hasOwnProperty.call(e, n) || !Object.is(r[n], e[n]))
1420
1640
  return !1;
1421
1641
  }
1422
1642
  return !0;
1423
1643
  }
1424
- class q {
1644
+ function N(r) {
1645
+ if (!r || typeof r != "object")
1646
+ return;
1647
+ const e = [];
1648
+ for (const [s, i] of Object.entries(r)) {
1649
+ const n = typeof i;
1650
+ (n === "string" || n === "number" || n === "boolean" || i === null || i === void 0) && e.push([s, i]);
1651
+ }
1652
+ if (e.length === 0)
1653
+ return;
1654
+ e.sort(([s], [i]) => s.localeCompare(i));
1655
+ const t = [];
1656
+ for (const [s, i] of e)
1657
+ i === null ? t.push(`${s}:null`) : i === void 0 ? t.push(`${s}:undefined`) : t.push(`${s}:${String(i)}`);
1658
+ return t.join("|");
1659
+ }
1660
+ class F {
1661
+ static componentRenderCounts = /* @__PURE__ */ new Map();
1662
+ static lastRenderTimestamps = /* @__PURE__ */ new Map();
1663
+ static groupedLogs = /* @__PURE__ */ new Map();
1664
+ static groupTimeouts = /* @__PURE__ */ new Map();
1665
+ /**
1666
+ * Log a component rerender with detailed information
1667
+ */
1668
+ static logRerender(e) {
1669
+ const t = o._config?.rerenderLogging;
1670
+ if (!t) return;
1671
+ const s = this.parseConfig(t);
1672
+ if (!s.enabled || s.filter && !s.filter({
1673
+ componentName: e.componentName,
1674
+ blocName: e.blocName
1675
+ }))
1676
+ return;
1677
+ const i = `${e.componentName}-${e.blocId}`, n = this.componentRenderCounts.get(i) || 0;
1678
+ this.componentRenderCounts.set(i, n + 1), e.renderCount = n + 1;
1679
+ const a = this.lastRenderTimestamps.get(i);
1680
+ a && (e.duration = e.timestamp - a), this.lastRenderTimestamps.set(i, e.timestamp), s.includeStackTrace && s.level === "detailed" && (e.stackTrace = new Error().stack), s.groupRerenders ? this.logGrouped(e, s) : this.logImmediate(e, s);
1681
+ }
1682
+ /**
1683
+ * Parse the logging configuration
1684
+ */
1685
+ static parseConfig(e) {
1686
+ return e === !0 ? { enabled: !0, level: "normal" } : typeof e == "string" ? {
1687
+ enabled: !0,
1688
+ level: e === "minimal" ? "minimal" : "detailed"
1689
+ } : {
1690
+ enabled: e.enabled,
1691
+ level: e.level || "normal",
1692
+ filter: e.filter,
1693
+ includeStackTrace: e.includeStackTrace,
1694
+ groupRerenders: e.groupRerenders
1695
+ };
1696
+ }
1697
+ /**
1698
+ * Log immediately without grouping
1699
+ */
1700
+ static logImmediate(e, t) {
1701
+ const s = this.formatMessage(e, t.level);
1702
+ t.level === "detailed" ? (console.group(s.header), s.details && console.log(s.details), s.values && console.table(s.values), e.stackTrace && console.log("Stack trace:", e.stackTrace), console.groupEnd()) : console.log(s.header, s.details || "");
1703
+ }
1704
+ /**
1705
+ * Log with grouping (batch multiple rerenders)
1706
+ */
1707
+ static logGrouped(e, t) {
1708
+ const s = `${e.componentName}-${e.blocId}`, i = this.groupTimeouts.get(s);
1709
+ i && clearTimeout(i);
1710
+ const n = this.groupedLogs.get(s) || [];
1711
+ n.push(e), this.groupedLogs.set(s, n);
1712
+ const a = setTimeout(() => {
1713
+ const c = this.groupedLogs.get(s) || [];
1714
+ this.groupedLogs.delete(s), this.groupTimeouts.delete(s), c.length === 1 ? this.logImmediate(c[0], t) : (console.group(
1715
+ `🔄 ${e.componentName} rendered ${c.length} times (${e.blocName})`
1716
+ ), c.forEach((l, h) => {
1717
+ const p = this.formatMessage(l, t.level);
1718
+ console.log(` ${h + 1}. ${p.details || p.header}`);
1719
+ }), console.groupEnd());
1720
+ }, 50);
1721
+ this.groupTimeouts.set(s, a);
1722
+ }
1723
+ /**
1724
+ * Format the log message based on level
1725
+ */
1726
+ static formatMessage(e, t) {
1727
+ const s = this.getReasonEmoji(e.reason.type);
1728
+ if (t === "minimal")
1729
+ return {
1730
+ header: `${s} ${e.componentName} #${e.renderCount}`,
1731
+ details: null,
1732
+ values: null
1733
+ };
1734
+ const i = `${s} ${e.componentName} rerender #${e.renderCount} (${e.blocName})`;
1735
+ let n = `Reason: ${e.reason.description || e.reason.type}`;
1736
+ e.duration !== void 0 && (n += ` | Time since last: ${e.duration}ms`), t === "normal" && e.reason.changedPaths && e.reason.changedPaths.length > 0 && (n += ` | Changed: ${e.reason.changedPaths.join(", ")}`);
1737
+ let a = null;
1738
+ return t === "detailed" && e.reason.changedPaths && e.reason.changedPaths.length > 0 && (a = {}, e.reason.changedPaths.forEach((c) => {
1739
+ a[c] = {
1740
+ old: e.reason.oldValues?.[c],
1741
+ new: e.reason.newValues?.[c]
1742
+ };
1743
+ }), Object.keys(a).length === 0 && (a = null)), { header: i, details: n, values: a };
1744
+ }
1745
+ /**
1746
+ * Get emoji for reason type
1747
+ */
1748
+ static getReasonEmoji(e) {
1749
+ switch (e) {
1750
+ case "state-change":
1751
+ return "📊";
1752
+ case "dependency-change":
1753
+ return "🔗";
1754
+ case "mount":
1755
+ return "🚀";
1756
+ case "props-change":
1757
+ return "📦";
1758
+ default:
1759
+ return "🔄";
1760
+ }
1761
+ }
1762
+ /**
1763
+ * Clear all tracking data
1764
+ */
1765
+ static clear() {
1766
+ this.componentRenderCounts.clear(), this.lastRenderTimestamps.clear(), this.groupedLogs.clear(), this.groupTimeouts.forEach((e) => clearTimeout(e)), this.groupTimeouts.clear();
1767
+ }
1768
+ /**
1769
+ * Get render count for a component
1770
+ */
1771
+ static getRenderCount(e, t) {
1772
+ return this.componentRenderCounts.get(`${e}-${t}`) || 0;
1773
+ }
1774
+ }
1775
+ class j {
1776
+ static originalInstance;
1425
1777
  /**
1426
1778
  * Sets up a clean test environment
1427
1779
  */
1428
1780
  static setUp() {
1429
- this.originalInstance = u.instance, u.resetInstance(), u.enableLog = !1;
1781
+ this.originalInstance = o.instance, o.resetInstance(), o.enableLog = !1;
1430
1782
  }
1431
1783
  /**
1432
1784
  * Tears down the test environment and restores original state
1433
1785
  */
1434
1786
  static tearDown() {
1435
- u.resetInstance();
1787
+ o.resetInstance();
1436
1788
  }
1437
1789
  /**
1438
1790
  * Creates a test bloc with automatic cleanup
1439
1791
  */
1440
1792
  static createBloc(e, ...t) {
1441
1793
  const s = new e(...t);
1442
- return u.activateBloc(s), s;
1794
+ return o.activateBloc(s), s;
1443
1795
  }
1444
1796
  /**
1445
1797
  * Waits for a bloc to emit a specific state
1446
1798
  */
1447
1799
  static async waitForState(e, t, s = 5e3) {
1448
- return new Promise((r, n) => {
1449
- const o = setTimeout(() => {
1800
+ return new Promise((i, n) => {
1801
+ const a = setTimeout(() => {
1450
1802
  n(
1451
1803
  new Error(
1452
1804
  `Timeout waiting for state matching predicate after ${s}ms`
1453
1805
  )
1454
1806
  );
1455
- }, s), a = e._observer.subscribe({
1456
- id: `test-waiter-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
1457
- fn: (l) => {
1458
- t(l) && (clearTimeout(o), a(), r(l));
1459
- }
1807
+ }, s), c = e.subscribe((l) => {
1808
+ t(l) && (clearTimeout(a), c(), i(l));
1460
1809
  });
1461
- t(e.state) && (clearTimeout(o), a(), r(e.state));
1810
+ t(e.state) && (clearTimeout(a), c(), i(e.state));
1462
1811
  });
1463
1812
  }
1464
1813
  /**
1465
1814
  * Expects a bloc to emit specific states in order
1466
1815
  */
1467
1816
  static async expectStates(e, t, s = 5e3) {
1468
- const r = [];
1469
- return new Promise((n, o) => {
1470
- const a = setTimeout(() => {
1471
- o(
1817
+ const i = [];
1818
+ return new Promise((n, a) => {
1819
+ const c = setTimeout(() => {
1820
+ a(
1472
1821
  new Error(
1473
- `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(r)}`
1822
+ `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(i)}`
1474
1823
  )
1475
1824
  );
1476
- }, s), l = e._observer.subscribe({
1477
- id: `test-expecter-${crypto.randomUUID()}`,
1478
- fn: (d) => {
1479
- if (r.push(d), r.length === t.length) {
1480
- clearTimeout(a), l();
1481
- for (let f = 0; f < t.length; f++) {
1482
- const m = t[f], v = r[f];
1483
- if (JSON.stringify(m) !== JSON.stringify(v)) {
1484
- o(
1485
- new Error(
1486
- `State mismatch at index ${f}. Expected: ${JSON.stringify(m)}, Received: ${JSON.stringify(v)}`
1487
- )
1488
- );
1489
- return;
1490
- }
1825
+ }, s), l = e.subscribe((h) => {
1826
+ if (i.push(h), i.length === t.length) {
1827
+ clearTimeout(c), l();
1828
+ for (let p = 0; p < t.length; p++) {
1829
+ const S = t[p], k = i[p];
1830
+ if (JSON.stringify(S) !== JSON.stringify(k)) {
1831
+ a(
1832
+ new Error(
1833
+ `State mismatch at index ${p}. Expected: ${JSON.stringify(S)}, Received: ${JSON.stringify(k)}`
1834
+ )
1835
+ );
1836
+ return;
1491
1837
  }
1492
- n();
1493
1838
  }
1839
+ n();
1494
1840
  }
1495
1841
  });
1496
1842
  });
1497
1843
  }
1498
1844
  }
1499
- i(q, "originalInstance");
1500
- class F extends j {
1501
- constructor(t) {
1502
- super(t);
1503
- i(this, "mockHandlers", /* @__PURE__ */ new Map());
1845
+ class z extends R {
1846
+ mockHandlers = /* @__PURE__ */ new Map();
1847
+ constructor(e) {
1848
+ super(e);
1504
1849
  }
1505
1850
  /**
1506
1851
  * Mock an event handler for testing
1507
1852
  */
1508
- mockEventHandler(t, s) {
1509
- this.on(t, s);
1853
+ mockEventHandler(e, t) {
1854
+ this.on(e, t);
1510
1855
  }
1511
1856
  /**
1512
1857
  * Get the number of registered handlers
@@ -1517,21 +1862,20 @@ class F extends j {
1517
1862
  /**
1518
1863
  * Check if a handler is registered for an event type
1519
1864
  */
1520
- hasHandler(t) {
1521
- return this.eventHandlers.has(t);
1865
+ hasHandler(e) {
1866
+ return this.eventHandlers.has(e);
1522
1867
  }
1523
1868
  }
1524
- class G extends z {
1525
- constructor(t) {
1526
- super(t);
1527
- i(this, "stateHistory", []);
1528
- this.stateHistory.push(t);
1869
+ class q extends O {
1870
+ stateHistory = [];
1871
+ constructor(e) {
1872
+ super(e), this.stateHistory.push(e);
1529
1873
  }
1530
1874
  /**
1531
1875
  * Override emit to track state history
1532
1876
  */
1533
- emit(t) {
1534
- this.stateHistory.push(t), super.emit(t);
1877
+ emit(e) {
1878
+ this.stateHistory.push(e), super.emit(e);
1535
1879
  }
1536
1880
  /**
1537
1881
  * Get the history of all states
@@ -1546,16 +1890,16 @@ class G extends z {
1546
1890
  this.stateHistory = [this.state];
1547
1891
  }
1548
1892
  }
1549
- class J {
1893
+ class W {
1894
+ initialStats;
1550
1895
  constructor() {
1551
- i(this, "initialStats");
1552
- this.initialStats = u.getMemoryStats();
1896
+ this.initialStats = o.getMemoryStats();
1553
1897
  }
1554
1898
  /**
1555
1899
  * Check for memory leaks and return a report
1556
1900
  */
1557
1901
  checkForLeaks() {
1558
- const e = u.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
1902
+ const e = o.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
1559
1903
  Memory Leak Detection Report:
1560
1904
  - Initial registered blocs: ${this.initialStats.registeredBlocs}
1561
1905
  - Current registered blocs: ${e.registeredBlocs}
@@ -1572,421 +1916,360 @@ Memory Leak Detection Report:
1572
1916
  };
1573
1917
  }
1574
1918
  }
1575
- class K {
1576
- constructor() {
1577
- i(this, "consumers", /* @__PURE__ */ new WeakMap());
1578
- i(this, "registrationCount", 0);
1579
- i(this, "activeConsumers", 0);
1919
+ const I = /* @__PURE__ */ new WeakMap(), d = {
1920
+ stateProxiesCreated: 0,
1921
+ classProxiesCreated: 0,
1922
+ cacheHits: 0,
1923
+ cacheMisses: 0,
1924
+ totalProxiesCreated: 0
1925
+ }, _ = (r, e, t, s = "") => {
1926
+ if (!e || !t || typeof r != "object" || r === null)
1927
+ return r;
1928
+ if (!s) {
1929
+ let n = I.get(r);
1930
+ n || (n = /* @__PURE__ */ new WeakMap(), I.set(r, n));
1931
+ const a = n.get(e);
1932
+ if (a)
1933
+ return d.cacheHits++, a;
1934
+ d.cacheMisses++;
1935
+ }
1936
+ const i = new Proxy(r, {
1937
+ get(n, a) {
1938
+ if (typeof a == "symbol" || a === "constructor")
1939
+ return Reflect.get(n, a);
1940
+ const c = s ? `${s}.${a}` : a, l = Reflect.get(n, a), h = l && typeof l == "object";
1941
+ return t.trackAccess(
1942
+ e,
1943
+ "state",
1944
+ c,
1945
+ h ? void 0 : l
1946
+ ), h && (Array.isArray(l) || Object.getPrototypeOf(l) === Object.prototype) ? _(l, e, t, c) : l;
1947
+ },
1948
+ set: () => !1,
1949
+ // State should be immutable
1950
+ deleteProperty: () => !1
1951
+ // State properties should not be deleted
1952
+ });
1953
+ return s || (I.get(r).set(e, i), d.stateProxiesCreated++, d.totalProxiesCreated++), i;
1954
+ }, M = (r, e, t) => {
1955
+ if (!e || !t)
1956
+ return r;
1957
+ let s = I.get(r);
1958
+ s || (s = /* @__PURE__ */ new WeakMap(), I.set(r, s));
1959
+ const i = s.get(e);
1960
+ if (i)
1961
+ return d.cacheHits++, i;
1962
+ d.cacheMisses++;
1963
+ const n = new Proxy(r, {
1964
+ get(a, c) {
1965
+ const l = Reflect.get(a, c);
1966
+ if (U(a, c)?.get) {
1967
+ const p = l !== null && typeof l != "object";
1968
+ t.trackAccess(
1969
+ e,
1970
+ "class",
1971
+ String(c),
1972
+ p ? l : void 0
1973
+ );
1974
+ }
1975
+ return l;
1976
+ }
1977
+ });
1978
+ return s.set(e, n), d.classProxiesCreated++, d.totalProxiesCreated++, n;
1979
+ }, U = (r, e, t = 10) => {
1980
+ let s = r, i = 0;
1981
+ for (; s && i < t; ) {
1982
+ const n = Object.getOwnPropertyDescriptor(s, e);
1983
+ if (n) return n;
1984
+ s = Object.getPrototypeOf(s), i++;
1985
+ }
1986
+ }, $ = {
1987
+ createStateProxy: (r) => _(
1988
+ r.target,
1989
+ r.consumerRef,
1990
+ r.consumerTracker,
1991
+ r.path
1992
+ ),
1993
+ createClassProxy: (r) => M(
1994
+ r.target,
1995
+ r.consumerRef,
1996
+ r.consumerTracker
1997
+ ),
1998
+ getProxyState: (r) => _(
1999
+ r.state,
2000
+ r.consumerRef,
2001
+ r.consumerTracker
2002
+ ),
2003
+ getProxyBlocInstance: (r) => M(
2004
+ r.blocInstance,
2005
+ r.consumerRef,
2006
+ r.consumerTracker
2007
+ ),
2008
+ // Compatibility functions that return expected structure
2009
+ getStats: () => ({
2010
+ ...d,
2011
+ propertyAccesses: 0,
2012
+ nestedProxiesCreated: 0,
2013
+ cacheEfficiency: d.cacheHits + d.cacheMisses > 0 ? `${(d.cacheHits / (d.cacheHits + d.cacheMisses) * 100).toFixed(1)}%` : "N/A",
2014
+ lifetime: "0ms",
2015
+ proxiesPerSecond: "N/A"
2016
+ }),
2017
+ resetStats: () => {
2018
+ d.stateProxiesCreated = 0, d.classProxiesCreated = 0, d.cacheHits = 0, d.cacheMisses = 0, d.totalProxiesCreated = 0;
1580
2019
  }
1581
- register(e, t) {
1582
- this.registrationCount++, this.consumers.get(e) || this.activeConsumers++, this.consumers.set(e, {
1583
- id: t,
1584
- lastNotified: Date.now(),
1585
- hasRendered: !1,
1586
- stateAccesses: /* @__PURE__ */ new Set(),
1587
- classAccesses: /* @__PURE__ */ new Set(),
1588
- stateValues: /* @__PURE__ */ new Map(),
1589
- classValues: /* @__PURE__ */ new Map(),
1590
- accessCount: 0,
1591
- lastAccessTime: 0,
1592
- firstAccessTime: 0
1593
- });
2020
+ };
2021
+ class G {
2022
+ id = `adapter-${A()}`;
2023
+ blocConstructor;
2024
+ componentRef = { current: {} };
2025
+ blocInstance;
2026
+ unmountTime = 0;
2027
+ mountTime = 0;
2028
+ // Subscription management
2029
+ subscriptionId;
2030
+ unsubscribe;
2031
+ // Dependency tracking
2032
+ dependencyValues;
2033
+ isUsingDependencies = !1;
2034
+ trackedPaths = /* @__PURE__ */ new Set();
2035
+ pendingTrackedPaths = /* @__PURE__ */ new Set();
2036
+ // Paths tracked before subscription exists
2037
+ // Proxy caching
2038
+ cachedStateProxy;
2039
+ cachedBlocProxy;
2040
+ lastProxiedState;
2041
+ // Lifecycle state
2042
+ hasMounted = !1;
2043
+ mountCount = 0;
2044
+ // Rerender tracking
2045
+ lastState;
2046
+ lastDependencyValues;
2047
+ componentName;
2048
+ renderCount = 0;
2049
+ lastDependenciesFn;
2050
+ options;
2051
+ constructor(e, t) {
2052
+ this.options = t, this.blocConstructor = e.blocConstructor, this.componentRef = e.componentRef, this.isUsingDependencies = !!t?.dependencies, this.updateBlocInstance(), this.isUsingDependencies && t?.dependencies && (this.dependencyValues = t.dependencies(this.blocInstance));
2053
+ const s = this.getAdapterMetadata();
2054
+ o.getInstance().plugins.notifyAdapterCreated(this, s);
1594
2055
  }
1595
- unregister(e) {
1596
- e && this.consumers.get(e) && (this.consumers.delete(e), this.activeConsumers = Math.max(0, this.activeConsumers - 1));
1597
- }
1598
- trackAccess(e, t, s, r) {
1599
- const n = this.consumers.get(e);
1600
- if (!n) return;
1601
- const o = Date.now();
1602
- 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 }));
1603
- }
1604
- resetTracking(e) {
1605
- const t = this.consumers.get(e);
1606
- t && (t.stateAccesses.clear(), t.classAccesses.clear(), t.stateValues.clear(), t.classValues.clear(), t.accessCount = 0, t.firstAccessTime = 0);
1607
- }
1608
- getDependencies(e) {
1609
- const t = this.consumers.get(e);
1610
- return t ? {
1611
- statePaths: Array.from(t.stateAccesses),
1612
- classPaths: Array.from(t.classAccesses)
1613
- } : null;
1614
- }
1615
- hasValuesChanged(e, t, s) {
1616
- const r = this.consumers.get(e);
1617
- if (!r) return !0;
1618
- let n = !1;
1619
- const o = Date.now();
1620
- if (r.stateValues.size === 0 && r.classValues.size === 0 && (r.stateAccesses.size > 0 || r.classAccesses.size > 0))
1621
- return !0;
1622
- for (const [a, l] of r.stateValues)
1623
- try {
1624
- const d = this.getValueAtPath(t, a);
1625
- d !== l.value && (r.stateValues.set(a, {
1626
- value: d,
1627
- lastAccessTime: o
1628
- }), n = !0);
1629
- } catch {
1630
- n = !0;
2056
+ trackAccess(e, t, s, i) {
2057
+ const n = t === "class" ? `_class.${s}` : s;
2058
+ this.trackedPaths.add(n), this.subscriptionId ? this.blocInstance.trackAccess(this.subscriptionId, n, i) : (this.pendingTrackedPaths.add(n), o.config.logLevel === "debug" && o.log(`[BlacAdapter] trackAccess storing pending path: ${s}`));
2059
+ }
2060
+ updateBlocInstance() {
2061
+ let e = this.options?.instanceId;
2062
+ if (!e && this.options?.staticProps) {
2063
+ const t = N(this.options.staticProps);
2064
+ t && (e = t);
2065
+ }
2066
+ return this.blocInstance = o.instance.getBloc(this.blocConstructor, {
2067
+ constructorParams: this.options?.staticProps,
2068
+ id: e,
2069
+ instanceRef: this.id
2070
+ }), this.blocInstance;
2071
+ }
2072
+ createSubscription = (e) => {
2073
+ if (this.isUsingDependencies && this.options?.dependencies)
2074
+ this.unsubscribe = this.blocInstance.subscribeWithSelector(
2075
+ (t) => this.options.dependencies(this.blocInstance),
2076
+ (t) => {
2077
+ this.hasDependencyValuesChanged(
2078
+ this.dependencyValues,
2079
+ t
2080
+ ) && (this.dependencyValues = t, e.onChange());
2081
+ }
2082
+ );
2083
+ else {
2084
+ const t = new WeakRef(this.componentRef.current);
2085
+ this.unsubscribe = this.blocInstance.subscribeComponent(
2086
+ t,
2087
+ e.onChange
2088
+ );
2089
+ const s = this.blocInstance._subscriptionManager.subscriptions;
2090
+ if (this.subscriptionId = Array.from(s.keys()).pop(), this.subscriptionId && this.pendingTrackedPaths.size > 0) {
2091
+ for (const i of this.pendingTrackedPaths)
2092
+ this.blocInstance.trackAccess(this.subscriptionId, i);
2093
+ this.pendingTrackedPaths.clear();
1631
2094
  }
1632
- for (const [a, l] of r.classValues)
2095
+ }
2096
+ return () => {
2097
+ this.unsubscribe && (this.unsubscribe(), this.unsubscribe = void 0, this.subscriptionId = void 0);
2098
+ };
2099
+ };
2100
+ hasDependencyValuesChanged = (e, t) => {
2101
+ if (!e || e.length !== t.length) return !0;
2102
+ for (let s = 0; s < e.length; s++)
2103
+ if (!Object.is(e[s], t[s]))
2104
+ return !0;
2105
+ return !1;
2106
+ };
2107
+ getStateProxy = () => {
2108
+ if (this.isUsingDependencies || !o.config.proxyDependencyTracking)
2109
+ return this.blocInstance.state;
2110
+ const e = this.blocInstance.state;
2111
+ return this.cachedStateProxy && this.lastProxiedState === e ? this.cachedStateProxy : (this.lastProxiedState = e, this.cachedStateProxy = this.createStateProxy({ target: e }), this.cachedStateProxy);
2112
+ };
2113
+ getBlocProxy = () => this.isUsingDependencies || !o.config.proxyDependencyTracking ? this.blocInstance : this.cachedBlocProxy ? this.cachedBlocProxy : (this.cachedBlocProxy = this.createClassProxy({ target: this.blocInstance }), this.cachedBlocProxy);
2114
+ createStateProxy = (e) => $.createStateProxy({
2115
+ target: e.target,
2116
+ consumerRef: this.componentRef.current,
2117
+ consumerTracker: this
2118
+ });
2119
+ createClassProxy = (e) => $.createClassProxy({
2120
+ target: e.target,
2121
+ consumerRef: this.componentRef.current,
2122
+ consumerTracker: this
2123
+ });
2124
+ // Lifecycle methods
2125
+ mount = () => {
2126
+ this.hasMounted = !0, this.mountCount++, this.mountTime = Date.now(), this.options?.onMount && this.options.onMount(this.blocInstance), this.isUsingDependencies && this.options?.dependencies && (this.dependencyValues = this.options.dependencies(this.blocInstance));
2127
+ const e = this.getAdapterMetadata();
2128
+ o.getInstance().plugins.notifyAdapterMount(this, e);
2129
+ };
2130
+ unmount = () => {
2131
+ if (this.unmountTime = Date.now(), this.unsubscribe && (this.unsubscribe(), this.unsubscribe = void 0, this.subscriptionId = void 0), this.options?.onUnmount)
1633
2132
  try {
1634
- const d = this.getValueAtPath(s, a);
1635
- d !== l.value && (r.classValues.set(a, {
1636
- value: d,
1637
- lastAccessTime: o
1638
- }), n = !0);
1639
- } catch {
1640
- n = !0;
2133
+ this.options.onUnmount(this.blocInstance);
2134
+ } catch (t) {
2135
+ console.error("Error in onUnmount hook:", t);
1641
2136
  }
1642
- return n;
1643
- }
1644
- shouldNotifyConsumer(e, t) {
1645
- const s = this.consumers.get(e);
1646
- if (!s) return !1;
1647
- for (const r of t) {
1648
- if (s.stateAccesses.has(r) || s.classAccesses.has(r)) return !0;
1649
- for (const n of s.stateAccesses)
1650
- if (r.startsWith(n + ".") || n.startsWith(r + "."))
1651
- return !0;
2137
+ const e = this.getAdapterMetadata();
2138
+ o.getInstance().plugins.notifyAdapterUnmount(this, e);
2139
+ };
2140
+ // Reset tracking for next render
2141
+ resetTracking() {
2142
+ if (this.trackedPaths.clear(), this.pendingTrackedPaths.clear(), this.subscriptionId) {
2143
+ const e = this.blocInstance._subscriptionManager.subscriptions.get(this.subscriptionId);
2144
+ e && e.dependencies && e.dependencies.clear();
1652
2145
  }
1653
- return !1;
1654
- }
1655
- updateLastNotified(e) {
1656
- const t = this.consumers.get(e);
1657
- t && (t.lastNotified = Date.now());
1658
2146
  }
1659
- getConsumerInfo(e) {
1660
- return this.consumers.get(e);
2147
+ // Set component name for rerender logging
2148
+ setComponentName(e) {
2149
+ this.componentName = e;
1661
2150
  }
1662
- setHasRendered(e, t) {
1663
- const s = this.consumers.get(e);
1664
- s && (s.hasRendered = t);
2151
+ // Notify plugins about render
2152
+ notifyRender() {
2153
+ this.renderCount++, this.isUsingDependencies && this.options?.dependencies && (this.lastDependencyValues = this.dependencyValues, this.dependencyValues = this.options.dependencies(this.blocInstance));
2154
+ const e = this.getAdapterMetadata();
2155
+ o.getInstance().plugins.notifyAdapterRender(this, e);
1665
2156
  }
1666
- hasConsumer(e) {
1667
- return this.consumers.has(e);
1668
- }
1669
- getStats() {
2157
+ // Get adapter metadata for plugins
2158
+ getAdapterMetadata() {
1670
2159
  return {
1671
- totalRegistrations: this.registrationCount,
1672
- activeConsumers: this.activeConsumers
2160
+ componentName: this.componentName,
2161
+ blocInstance: this.blocInstance,
2162
+ renderCount: this.renderCount,
2163
+ trackedPaths: Array.from(this.trackedPaths),
2164
+ isUsingDependencies: this.isUsingDependencies,
2165
+ lastState: this.lastState,
2166
+ lastDependencyValues: this.lastDependencyValues,
2167
+ currentDependencyValues: this.dependencyValues
1673
2168
  };
1674
2169
  }
2170
+ // Get value at a dot-notated path
1675
2171
  getValueAtPath(e, t) {
1676
2172
  const s = t.split(".");
1677
- let r = e;
2173
+ let i = e;
1678
2174
  for (const n of s) {
1679
- if (r == null) return;
1680
- r = r[n];
2175
+ if (i == null) return;
2176
+ i = i[n];
1681
2177
  }
1682
- return r;
2178
+ return i;
2179
+ }
2180
+ // Get paths that changed between states
2181
+ getStateChangedPaths(e, t) {
2182
+ const s = [];
2183
+ if (this.trackedPaths.size > 0)
2184
+ for (const i of this.trackedPaths) {
2185
+ if (i.startsWith("_class.")) continue;
2186
+ const n = this.getValueAtPath(e, i), a = this.getValueAtPath(t, i);
2187
+ Object.is(n, a) || s.push(i);
2188
+ }
2189
+ else if (e !== t) {
2190
+ const i = this.getDeepChangedPaths(e, t);
2191
+ if (i.length > 0)
2192
+ return i;
2193
+ s.push("(entire state)");
2194
+ }
2195
+ return s;
1683
2196
  }
1684
- }
1685
- const x = /* @__PURE__ */ new WeakMap();
1686
- let p = {
1687
- stateProxiesCreated: 0,
1688
- classProxiesCreated: 0,
1689
- cacheHits: 0,
1690
- cacheMisses: 0,
1691
- propertyAccesses: 0,
1692
- nestedProxiesCreated: 0,
1693
- totalProxiesCreated: 0,
1694
- createdAt: Date.now()
1695
- };
1696
- class I {
1697
- static createStateProxy(e) {
1698
- const { target: t, consumerRef: s, consumerTracker: r, path: n = "" } = e;
1699
- if (!s || !r || typeof t != "object" || t === null)
1700
- return t;
1701
- let o = x.get(t);
1702
- o || (o = /* @__PURE__ */ new WeakMap(), x.set(t, o));
1703
- const a = o.get(s);
1704
- if (a)
1705
- return p.cacheHits++, a;
1706
- p.cacheMisses++;
1707
- const l = {
1708
- get(f, m) {
1709
- if (typeof m == "symbol" || m === "constructor")
1710
- return Reflect.get(f, m);
1711
- const v = n ? `${n}.${m}` : m;
1712
- p.propertyAccesses++;
1713
- const g = Reflect.get(f, m), B = g && typeof g === "object" && g !== null ? void 0 : g;
1714
- if (r.trackAccess(s, "state", v, B), g && typeof g == "object" && g !== null) {
1715
- const w = Object.getPrototypeOf(g) === Object.prototype, T = Array.isArray(g);
1716
- if (w || T)
1717
- return p.nestedProxiesCreated++, I.createStateProxy({
1718
- target: g,
1719
- consumerRef: s,
1720
- consumerTracker: r,
1721
- path: v
1722
- });
1723
- }
1724
- return g;
1725
- },
1726
- has(f, m) {
1727
- return m in f;
1728
- },
1729
- ownKeys(f) {
1730
- return Reflect.ownKeys(f);
1731
- },
1732
- getOwnPropertyDescriptor(f, m) {
1733
- return Reflect.getOwnPropertyDescriptor(f, m);
1734
- },
1735
- set() {
1736
- return !1;
1737
- },
1738
- deleteProperty() {
1739
- return !1;
2197
+ // Deep comparison to find all changed paths
2198
+ getDeepChangedPaths(e, t, s = "") {
2199
+ const i = [];
2200
+ if (e === t) return i;
2201
+ if (e == null || t == null)
2202
+ return i.push(s || "(root)"), i;
2203
+ if (typeof e != "object" || typeof t != "object")
2204
+ return e !== t && i.push(s || "(root)"), i;
2205
+ if (Array.isArray(e) || Array.isArray(t)) {
2206
+ if (!Array.isArray(e) || !Array.isArray(t) || e.length !== t.length)
2207
+ return i.push(s || "(root)"), i;
2208
+ for (let a = 0; a < e.length; a++) {
2209
+ const c = s ? `${s}[${a}]` : `[${a}]`;
2210
+ i.push(
2211
+ ...this.getDeepChangedPaths(e[a], t[a], c)
2212
+ );
1740
2213
  }
1741
- }, d = new Proxy(t, l);
1742
- return o.set(s, d), p.stateProxiesCreated++, p.totalProxiesCreated++, d;
1743
- }
1744
- static createClassProxy(e) {
1745
- const { target: t, consumerRef: s, consumerTracker: r } = e;
1746
- if (!s || !r)
1747
- return t;
1748
- let n = x.get(t);
1749
- n || (n = /* @__PURE__ */ new WeakMap(), x.set(t, n));
1750
- const o = n.get(s);
1751
- if (o)
1752
- return p.cacheHits++, o;
1753
- p.cacheMisses++;
1754
- const a = {
1755
- get(d, f) {
1756
- const m = Reflect.get(d, f);
1757
- let v = !1, g = d;
1758
- const A = /* @__PURE__ */ new WeakSet(), P = 10;
1759
- let B = 0;
1760
- for (; g && !v && B < P && !A.has(g); ) {
1761
- A.add(g);
1762
- try {
1763
- const C = Object.getOwnPropertyDescriptor(
1764
- g,
1765
- f
2214
+ return i;
2215
+ }
2216
+ const n = /* @__PURE__ */ new Set([...Object.keys(e), ...Object.keys(t)]);
2217
+ for (const a of n) {
2218
+ const c = s ? `${s}.${a}` : a;
2219
+ if (!(a in e))
2220
+ i.push(`${c} (added)`);
2221
+ else if (!(a in t))
2222
+ i.push(`${c} (removed)`);
2223
+ else {
2224
+ const l = e[a], h = t[a];
2225
+ if (!Object.is(l, h))
2226
+ if (typeof l != "object" || typeof h != "object" || l === null || h === null)
2227
+ i.push(c);
2228
+ else {
2229
+ const p = this.getDeepChangedPaths(
2230
+ l,
2231
+ h,
2232
+ c
1766
2233
  );
1767
- if (C && C.get) {
1768
- v = !0;
1769
- break;
1770
- }
1771
- g = Object.getPrototypeOf(g), B++;
1772
- } catch {
1773
- break;
2234
+ p.length > 0 ? i.push(...p) : i.push(c);
1774
2235
  }
1775
- }
1776
- if (!v)
1777
- return m;
1778
- p.propertyAccesses++;
1779
- const w = m, M = w !== null && typeof w != "object" ? w : void 0;
1780
- return r.trackAccess(
1781
- s,
1782
- "class",
1783
- String(f),
1784
- M
1785
- ), m;
1786
- },
1787
- has(d, f) {
1788
- return f in d;
1789
- },
1790
- ownKeys(d) {
1791
- return Reflect.ownKeys(d);
1792
- },
1793
- getOwnPropertyDescriptor(d, f) {
1794
- return Reflect.getOwnPropertyDescriptor(d, f);
1795
- }
1796
- }, l = new Proxy(t, a);
1797
- return n.set(s, l), p.classProxiesCreated++, p.totalProxiesCreated++, l;
1798
- }
1799
- static getProxyState(e) {
1800
- return I.createStateProxy({
1801
- target: e.state,
1802
- consumerRef: e.consumerRef,
1803
- consumerTracker: e.consumerTracker
1804
- });
1805
- }
1806
- static getProxyBlocInstance(e) {
1807
- return I.createClassProxy({
1808
- target: e.blocInstance,
1809
- consumerRef: e.consumerRef,
1810
- consumerTracker: e.consumerTracker
1811
- });
1812
- }
1813
- static getStats() {
1814
- const e = Date.now() - p.createdAt;
1815
- return {
1816
- ...p,
1817
- totalProxies: p.stateProxiesCreated + p.classProxiesCreated,
1818
- cacheEfficiency: p.cacheHits + p.cacheMisses > 0 ? `${(p.cacheHits / (p.cacheHits + p.cacheMisses) * 100).toFixed(1)}%` : "N/A",
1819
- lifetime: `${e}ms`,
1820
- proxiesPerSecond: e > 0 ? (p.totalProxiesCreated / (e / 1e3)).toFixed(2) : "N/A"
1821
- };
1822
- }
1823
- static resetStats() {
1824
- p = {
1825
- stateProxiesCreated: 0,
1826
- classProxiesCreated: 0,
1827
- cacheHits: 0,
1828
- cacheMisses: 0,
1829
- propertyAccesses: 0,
1830
- nestedProxiesCreated: 0,
1831
- totalProxiesCreated: 0,
1832
- createdAt: Date.now()
1833
- };
1834
- }
1835
- }
1836
- const b = class b {
1837
- constructor(e, t) {
1838
- i(this, "id", `consumer-${$()}`);
1839
- i(this, "blocConstructor");
1840
- i(this, "componentRef", { current: {} });
1841
- i(this, "blocInstance");
1842
- // Core components
1843
- i(this, "consumerTracker");
1844
- i(this, "lastProps");
1845
- i(this, "unmountTime", 0);
1846
- i(this, "mountTime", 0);
1847
- // Dependency tracking
1848
- i(this, "dependencyValues");
1849
- i(this, "isUsingDependencies", !1);
1850
- // Lifecycle state
1851
- i(this, "hasMounted", !1);
1852
- i(this, "mountCount", 0);
1853
- i(this, "options");
1854
- i(this, "createStateProxy", (e) => I.createStateProxy({
1855
- target: e.target,
1856
- consumerRef: this.componentRef.current,
1857
- consumerTracker: this
1858
- }));
1859
- i(this, "createClassProxy", (e) => I.createClassProxy({
1860
- target: e.target,
1861
- consumerRef: this.componentRef.current,
1862
- consumerTracker: this
1863
- }));
1864
- i(this, "createSubscription", (e) => this.blocInstance._observer.subscribe({
1865
- id: this.id,
1866
- fn: (s, r) => {
1867
- var n;
1868
- if (this.isUsingDependencies && ((n = this.options) != null && n.dependencies)) {
1869
- const o = this.options.dependencies(this.blocInstance);
1870
- if (!this.hasDependencyValuesChanged(
1871
- this.dependencyValues,
1872
- o
1873
- ))
1874
- return;
1875
- this.dependencyValues = o;
1876
- } else if (u.config.proxyDependencyTracking) {
1877
- const o = this.consumerTracker.getConsumerInfo(
1878
- this.componentRef.current
1879
- );
1880
- if (o && o.hasRendered && !this.consumerTracker.hasValuesChanged(
1881
- this.componentRef.current,
1882
- s,
1883
- this.blocInstance
1884
- ))
1885
- return;
1886
- } else {
1887
- e.onChange();
1888
- return;
1889
- }
1890
- e.onChange();
1891
2236
  }
1892
- }));
1893
- i(this, "mount", () => {
1894
- var e, t;
1895
- 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))
1896
- try {
1897
- this.options.onMount(this.blocInstance);
1898
- } catch (s) {
1899
- throw s;
1900
- }
1901
- });
1902
- i(this, "unmount", () => {
1903
- var e;
1904
- if (this.unmountTime = Date.now(), this.consumerTracker.unregister(this.componentRef.current), this.blocInstance._removeConsumer(this.id), b.propsOwners.get(this.blocInstance) === this.id && b.propsOwners.delete(this.blocInstance), (e = this.options) != null && e.onUnmount)
1905
- try {
1906
- this.options.onUnmount(this.blocInstance);
1907
- } catch {
1908
- }
1909
- });
1910
- i(this, "getProxyState", (e) => this.isUsingDependencies || !u.config.proxyDependencyTracking ? e : I.getProxyState({
1911
- state: e,
1912
- consumerRef: this.componentRef.current,
1913
- consumerTracker: this
1914
- }));
1915
- i(this, "getProxyBlocInstance", () => this.isUsingDependencies || !u.config.proxyDependencyTracking ? this.blocInstance : I.getProxyBlocInstance({
1916
- blocInstance: this.blocInstance,
1917
- consumerRef: this.componentRef.current,
1918
- consumerTracker: this
1919
- }));
1920
- this.options = t, this.blocConstructor = e.blocConstructor, this.componentRef = e.componentRef, this.isUsingDependencies = !!(t != null && t.dependencies), this.consumerTracker = new K(), 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);
1921
- }
1922
- trackAccess(e, t, s, r) {
1923
- this.consumerTracker.trackAccess(e, t, s, r);
1924
- }
1925
- getConsumerDependencies(e) {
1926
- return this.consumerTracker.getDependencies(e);
1927
- }
1928
- shouldNotifyConsumer(e, t) {
1929
- const s = this.consumerTracker.getConsumerInfo(e);
1930
- return !s || !s.hasRendered ? !0 : this.consumerTracker.shouldNotifyConsumer(e, t);
1931
- }
1932
- updateLastNotified(e) {
1933
- this.consumerTracker.updateLastNotified(e), this.consumerTracker.setHasRendered(e, !0);
1934
- }
1935
- resetConsumerTracking() {
1936
- this.consumerTracker.resetTracking(this.componentRef.current);
1937
- }
1938
- updateBlocInstance() {
1939
- var e, t;
1940
- return this.blocInstance = u.instance.getBloc(this.blocConstructor, {
1941
- props: (e = this.options) == null ? void 0 : e.props,
1942
- id: (t = this.options) == null ? void 0 : t.id,
1943
- instanceRef: this.id
1944
- }), this.blocInstance;
1945
- }
1946
- // Expose calledOnMount for backward compatibility
1947
- get calledOnMount() {
1948
- return this.hasMounted;
1949
- }
1950
- updateProps(e) {
1951
- const t = this.blocInstance;
1952
- if (b.propsOwners.has(t) || b.propsOwners.set(t, this.id), b.propsOwners.get(t) !== this.id) {
1953
- u.warn(
1954
- `[BlacAdapter] Attempted to set props on ${t.constructor.name} from non-owner adapter`
1955
- );
1956
- return;
1957
2237
  }
1958
- t._disposalState === y.DISPOSED || t._disposalState === y.DISPOSING || N(this.lastProps, e) || ("add" in t && typeof t.add == "function" ? t.add(new L(e)) : "_updateProps" in t && typeof t._updateProps == "function" && t._updateProps(e), this.lastProps = e);
2238
+ return i;
1959
2239
  }
1960
- hasDependencyValuesChanged(e, t) {
1961
- if (!e || e.length !== t.length) return !0;
1962
- for (let s = 0; s < e.length; s++)
1963
- if (!Object.is(e[s], t[s]))
1964
- return !0;
1965
- return !1;
2240
+ // Get last rerender reason
2241
+ getLastRerenderReason() {
1966
2242
  }
1967
- };
1968
- // Props ownership tracking
1969
- i(b, "propsOwners", /* @__PURE__ */ new WeakMap());
1970
- let D = b;
2243
+ }
1971
2244
  export {
1972
- u as Blac,
1973
- D as BlacAdapter,
1974
- H as BlacObservable,
1975
- j as Bloc,
1976
- k as BlocBase,
1977
- y as BlocLifecycleState,
1978
- V as BlocPluginRegistry,
1979
- q as BlocTest,
1980
- K as ConsumerTracker,
1981
- z as Cubit,
1982
- J as MemoryLeakDetector,
1983
- F as MockBloc,
1984
- G as MockCubit,
2245
+ o as Blac,
2246
+ G as BlacAdapter,
2247
+ m as BlacError,
2248
+ R as Bloc,
2249
+ C as BlocBase,
2250
+ B as BlocLifecycleManager,
2251
+ u as BlocLifecycleState,
2252
+ w as BlocPluginRegistry,
2253
+ j as BlocTest,
2254
+ O as Cubit,
2255
+ P as DefaultErrorStrategy,
2256
+ v as ErrorCategory,
2257
+ f as ErrorManager,
2258
+ y as ErrorSeverity,
2259
+ W as MemoryLeakDetector,
2260
+ z as MockBloc,
2261
+ q as MockCubit,
1985
2262
  L as PropsUpdated,
1986
- I as ProxyFactory,
1987
- U as SystemPluginRegistry,
1988
- $ as generateUUID,
1989
- W as setBlacInstanceManager,
1990
- N as shallowEqual
2263
+ $ as ProxyFactory,
2264
+ F as RerenderLogger,
2265
+ E as SubscriptionManager,
2266
+ T as SystemPluginRegistry,
2267
+ M as createBlocProxy,
2268
+ _ as createStateProxy,
2269
+ N as generateInstanceIdFromProps,
2270
+ A as generateUUID,
2271
+ x as handleError,
2272
+ H as setBlacInstanceManager,
2273
+ V as shallowEqual
1991
2274
  };
1992
2275
  //# sourceMappingURL=index.es.js.map