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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js DELETED
@@ -1,2275 +0,0 @@
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";
12
- }
13
- /**
14
- * Atomic state transition for disposal
15
- */
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
- }
40
- }
41
- /**
42
- * Schedule disposal after a delay
43
- */
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));
56
- }
57
- /**
58
- * Cancel disposal if in disposal requested state
59
- */
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;
66
- }
67
- /**
68
- * Set disposal handler
69
- */
70
- setDisposalHandler(e) {
71
- this.disposalHandler = e;
72
- }
73
- /**
74
- * Get disposal handler
75
- */
76
- getDisposalHandler() {
77
- return this.disposalHandler;
78
- }
79
- /**
80
- * Clear disposal timer
81
- */
82
- clearDisposalTimer() {
83
- this.disposalTimer && (clearTimeout(this.disposalTimer), this.disposalTimer = void 0);
84
- }
85
- }
86
- class T {
87
- plugins = /* @__PURE__ */ new Map();
88
- metrics = /* @__PURE__ */ new Map();
89
- executionOrder = [];
90
- /**
91
- * Add a system plugin
92
- */
93
- add(e) {
94
- if (this.plugins.has(e.name))
95
- throw new Error(`Plugin '${e.name}' is already registered`);
96
- this.plugins.set(e.name, e), this.executionOrder.push(e.name), this.initializeMetrics(e.name);
97
- }
98
- /**
99
- * Remove a system plugin
100
- */
101
- remove(e) {
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;
105
- }
106
- /**
107
- * Get a plugin by name
108
- */
109
- get(e) {
110
- return this.plugins.get(e);
111
- }
112
- /**
113
- * Get all plugins in execution order
114
- */
115
- getAll() {
116
- return this.executionOrder.map((e) => this.plugins.get(e));
117
- }
118
- /**
119
- * Clear all plugins
120
- */
121
- clear() {
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
- }
140
- }
141
- }
142
- /**
143
- * Bootstrap all plugins
144
- */
145
- bootstrap() {
146
- this.executeHook("beforeBootstrap", []), this.executeHook("afterBootstrap", []);
147
- }
148
- /**
149
- * Shutdown all plugins
150
- */
151
- shutdown() {
152
- this.executeHook("beforeShutdown", []), this.executeHook("afterShutdown", []);
153
- }
154
- /**
155
- * Notify plugins of bloc creation
156
- */
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]);
165
- }
166
- /**
167
- * Notify plugins of state change
168
- */
169
- notifyStateChanged(e, t, s) {
170
- this.executeHook("onStateChanged", [e, t, s]);
171
- }
172
- /**
173
- * Notify plugins of event addition
174
- */
175
- notifyEventAdded(e, t) {
176
- this.executeHook("onEventAdded", [e, t]);
177
- }
178
- /**
179
- * Notify plugins of errors
180
- */
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
- });
185
- }
186
- /**
187
- * Notify plugins of adapter lifecycle events
188
- */
189
- notifyAdapterCreated(e, t) {
190
- this.executeHook("onAdapterCreated", [e, t]);
191
- }
192
- notifyAdapterMount(e, t) {
193
- this.executeHook("onAdapterMount", [e, t]);
194
- }
195
- notifyAdapterUnmount(e, t) {
196
- this.executeHook("onAdapterUnmount", [e, t]);
197
- }
198
- notifyAdapterRender(e, t) {
199
- this.executeHook("onAdapterRender", [e, t]);
200
- }
201
- notifyAdapterDisposed(e, t) {
202
- this.executeHook("onAdapterDisposed", [e, t]);
203
- }
204
- /**
205
- * Get metrics for a plugin
206
- */
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
224
- });
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
236
- });
237
- }
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);
243
- }
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}`;
247
- }
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);
254
- }
255
- };
256
- class f {
257
- static instance;
258
- handlers = /* @__PURE__ */ new Set();
259
- strategy = P;
260
- /**
261
- * Get the singleton instance of ErrorManager
262
- */
263
- static getInstance() {
264
- return f.instance || (f.instance = new f()), f.instance;
265
- }
266
- /**
267
- * Set a custom error handling strategy
268
- */
269
- setStrategy(e) {
270
- this.strategy = e;
271
- }
272
- /**
273
- * Add a custom error handler that will be called for all errors
274
- */
275
- addHandler(e) {
276
- this.handlers.add(e);
277
- }
278
- /**
279
- * Remove a previously added error handler
280
- */
281
- removeHandler(e) {
282
- this.handlers.delete(e);
283
- }
284
- /**
285
- * Process an error through all handlers and apply the configured strategy
286
- */
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;
296
- }
297
- /**
298
- * Convenience method for wrapping operations with error handling
299
- */
300
- wrap(e, t) {
301
- try {
302
- return e();
303
- } catch (s) {
304
- const i = t(s);
305
- this.handle(i);
306
- return;
307
- }
308
- }
309
- /**
310
- * Async version of wrap
311
- */
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
- }
320
- }
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`);
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
- }
931
- }
932
- /**
933
- * Notify plugins of error
934
- */
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;
968
- }
969
- subscriptions = /* @__PURE__ */ new Map();
970
- pathToSubscriptions = /* @__PURE__ */ new Map();
971
- weakRefCleanupScheduled = !1;
972
- totalNotifications = 0;
973
- /**
974
- * Subscribe to state changes
975
- */
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);
1005
- }
1006
- /**
1007
- * Unsubscribe by ID
1008
- */
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
- }
1021
- }
1022
- /**
1023
- * Notify all subscriptions of state change
1024
- */
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;
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
- }
1073
- }
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;
1105
- }
1106
- /**
1107
- * Check if a subscription should be notified based on changed paths
1108
- */
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;
1124
- }
1125
- /**
1126
- * Get statistics about subscriptions
1127
- */
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
- };
1139
- }
1140
- /**
1141
- * Clear all subscriptions
1142
- */
1143
- clear() {
1144
- this.subscriptions.clear(), this.pathToSubscriptions.clear();
1145
- }
1146
- /**
1147
- * Get subscription by ID
1148
- */
1149
- getSubscription(e) {
1150
- return this.subscriptions.get(e);
1151
- }
1152
- /**
1153
- * Check if there are any active subscriptions
1154
- */
1155
- get hasSubscriptions() {
1156
- return this.subscriptions.size > 0;
1157
- }
1158
- /**
1159
- * Get count of active subscriptions
1160
- */
1161
- get size() {
1162
- return this.subscriptions.size;
1163
- }
1164
- /**
1165
- * Clean up subscriptions with dead weak references
1166
- */
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;
1175
- }
1176
- /**
1177
- * Schedule weak reference cleanup for next tick
1178
- */
1179
- scheduleWeakRefCleanup() {
1180
- this.weakRefCleanupScheduled || (this.weakRefCleanupScheduled = !0, queueMicrotask(() => this.cleanupDeadReferences()));
1181
- }
1182
- }
1183
- class D {
1184
- pendingUpdates = [];
1185
- isBatching = !1;
1186
- /**
1187
- * Execute a callback with batched updates
1188
- */
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
- }
1203
- }
1204
- /**
1205
- * Add an update to the batch
1206
- */
1207
- addUpdate(e) {
1208
- this.isBatching && this.pendingUpdates.push(e);
1209
- }
1210
- /**
1211
- * Check if currently batching
1212
- */
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;
1227
- }
1228
- _isolated = !1;
1229
- _id;
1230
- _instanceRef;
1231
- _name;
1232
- /**
1233
- * Unified subscription manager for all state notifications
1234
- */
1235
- _subscriptionManager;
1236
- _state;
1237
- _lifecycleManager = new B();
1238
- _batchingManager = new D();
1239
- _keepAlive = !1;
1240
- lastUpdate;
1241
- _plugins = new w();
1242
- onDispose;
1243
- /**
1244
- * Creates a new BlocBase instance with unified subscription management
1245
- */
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);
1253
- }
1254
- /**
1255
- * Returns the current state
1256
- */
1257
- get state() {
1258
- return this._lifecycleManager.isDisposed ? this._state : this._state;
1259
- }
1260
- /**
1261
- * Subscribe to all state changes
1262
- */
1263
- subscribe(e) {
1264
- return this._subscriptionManager.subscribe({
1265
- type: "observer",
1266
- notify: (t) => e(t)
1267
- });
1268
- }
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)
1278
- });
1279
- }
1280
- /**
1281
- * Subscribe with React component reference for automatic cleanup
1282
- */
1283
- subscribeComponent(e, t) {
1284
- return this._subscriptionManager.subscribe({
1285
- type: "consumer",
1286
- weakRef: e,
1287
- notify: t
1288
- });
1289
- }
1290
- /**
1291
- * Get current subscription count
1292
- */
1293
- get subscriptionCount() {
1294
- return this._subscriptionManager.size;
1295
- }
1296
- /**
1297
- * Track property access for a subscription
1298
- */
1299
- trackAccess(e, t, s) {
1300
- this._subscriptionManager.trackAccess(e, t, s);
1301
- }
1302
- /**
1303
- * Emit a new state
1304
- */
1305
- emit(e, t) {
1306
- this._pushState(e, this._state, t);
1307
- }
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
- });
1347
- }
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
- }
1358
- }
1359
- /**
1360
- * Remove a plugin
1361
- */
1362
- removePlugin(e) {
1363
- this._plugins.remove(e.name);
1364
- }
1365
- /**
1366
- * Get all plugins
1367
- */
1368
- get plugins() {
1369
- return this._plugins.getAll();
1370
- }
1371
- /**
1372
- * Disposal management
1373
- */
1374
- get isDisposed() {
1375
- return this._lifecycleManager.isDisposed;
1376
- }
1377
- /**
1378
- * Atomic state transition for disposal
1379
- */
1380
- _atomicStateTransition(e, t) {
1381
- return this._lifecycleManager.atomicStateTransition(
1382
- e,
1383
- t
1384
- );
1385
- }
1386
- /**
1387
- * Dispose the bloc and clean up resources
1388
- */
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
- }
1417
- }
1418
- /**
1419
- * Schedule disposal when no subscriptions remain
1420
- */
1421
- _scheduleDisposal() {
1422
- this._subscriptionManager.size === 0 && !this._keepAlive && this._lifecycleManager.scheduleDisposal(
1423
- 16,
1424
- () => this._subscriptionManager.size === 0 && !this._keepAlive,
1425
- () => this.dispose()
1426
- );
1427
- }
1428
- /**
1429
- * Set disposal handler
1430
- */
1431
- setDisposalHandler(e) {
1432
- this._lifecycleManager.setDisposalHandler(
1433
- e
1434
- );
1435
- }
1436
- /**
1437
- * Check if disposal should be scheduled (called by subscription manager)
1438
- */
1439
- checkDisposal() {
1440
- this._subscriptionManager.size === 0 && !this._keepAlive && this._lifecycleManager.currentState === u.ACTIVE && this._scheduleDisposal();
1441
- }
1442
- /**
1443
- * Cancel disposal if bloc is in disposal_requested state
1444
- */
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
- );
1455
- }
1456
- }
1457
- class R extends C {
1458
- eventHandlers = /* @__PURE__ */ new Map();
1459
- /**
1460
- * @internal
1461
- * Event queue to ensure sequential processing of async events
1462
- */
1463
- _eventQueue = [];
1464
- /**
1465
- * @internal
1466
- * Flag indicating if an event is currently being processed
1467
- */
1468
- _isProcessingEvent = !1;
1469
- /**
1470
- * Registers an event handler for a specific event type.
1471
- * This method is typically called in the constructor of a derived Bloc class.
1472
- * @param eventConstructor The constructor of the event to handle (e.g., LoadDataEvent).
1473
- * @param handler A function that processes the event and can emit new states.
1474
- * The 'event' parameter in the handler will be typed to the specific eventConstructor.
1475
- */
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.`
1479
- ), this.eventHandlers.set(
1480
- e,
1481
- t
1482
- );
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
- };
1505
- /**
1506
- * @internal
1507
- * Processes events from the queue sequentially
1508
- */
1509
- async _processEventQueue() {
1510
- if (!this._isProcessingEvent) {
1511
- this._isProcessingEvent = !0;
1512
- try {
1513
- for (; this._eventQueue.length > 0; ) {
1514
- const e = this._eventQueue.shift();
1515
- await this._processEvent(e);
1516
- }
1517
- } finally {
1518
- this._isProcessingEvent = !1;
1519
- }
1520
- }
1521
- }
1522
- /**
1523
- * @internal
1524
- * Processes a single event
1525
- */
1526
- async _processEvent(e) {
1527
- const t = e.constructor, s = this.eventHandlers.get(t);
1528
- if (s) {
1529
- const i = (n) => {
1530
- const a = this.state;
1531
- this._pushState(n, a, e);
1532
- };
1533
- try {
1534
- await s(e, i);
1535
- } catch (n) {
1536
- const a = e.constructor.name || "UnnamedConstructor", c = {
1537
- blocName: this._name,
1538
- blocId: String(this._id),
1539
- eventType: a,
1540
- currentState: this.state,
1541
- action: e,
1542
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1543
- };
1544
- if (o.error(
1545
- `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${a}':`,
1546
- n,
1547
- "Context:",
1548
- c
1549
- ), n instanceof Error)
1550
- try {
1551
- this._plugins.notifyError(n, {
1552
- phase: "event-processing",
1553
- operation: "handler",
1554
- metadata: { event: e }
1555
- }), o.instance.plugins.notifyError(n, this, {
1556
- phase: "event-processing",
1557
- operation: "handler",
1558
- metadata: { event: e }
1559
- });
1560
- } catch (l) {
1561
- console.error("Error notifying plugins:", l);
1562
- }
1563
- if (n instanceof Error && n.name === "CriticalError")
1564
- throw n;
1565
- }
1566
- } else {
1567
- const i = e.constructor.name || "UnnamedConstructor";
1568
- o.warn(
1569
- `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${i}'.`,
1570
- "Registered handlers:",
1571
- Array.from(this.eventHandlers.keys()).map((n) => n.name),
1572
- "Action was:",
1573
- e
1574
- );
1575
- }
1576
- }
1577
- }
1578
- class O extends C {
1579
- /**
1580
- * Updates the current state and notifies all observers of the change.
1581
- * If the new state is identical to the current state (using Object.is),
1582
- * no update will occur.
1583
- * @param state - The new state to set
1584
- */
1585
- emit(e) {
1586
- if (Object.is(e, this.state))
1587
- return;
1588
- const t = this.state, s = e;
1589
- this._pushState(s, t);
1590
- }
1591
- /**
1592
- * Partially updates the current state by merging it with the provided state patch.
1593
- * This method is only applicable when the state is an object type.
1594
- *
1595
- * @param statePatch - A partial state object containing only the properties to update
1596
- * @param ignoreChangeCheck - If true, skips checking if the state has actually changed
1597
- * @throws {TypeError} If the state is not an object type
1598
- */
1599
- patch(e, t = !1) {
1600
- if (typeof this.state != "object" || this.state === null) {
1601
- o.warn(
1602
- "Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
1603
- );
1604
- return;
1605
- }
1606
- let s = !1;
1607
- if (t)
1608
- s = !0;
1609
- else
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)) {
1614
- s = !0;
1615
- break;
1616
- }
1617
- }
1618
- s && this.emit({
1619
- ...this.state,
1620
- ...e
1621
- });
1622
- }
1623
- }
1624
- class L {
1625
- constructor(e) {
1626
- this.props = e;
1627
- }
1628
- }
1629
- function V(r, e) {
1630
- if (Object.is(r, e))
1631
- return !0;
1632
- if (typeof r != "object" || r === null || typeof e != "object" || e === null)
1633
- return !1;
1634
- const t = Object.keys(r), s = Object.keys(e);
1635
- if (t.length !== s.length)
1636
- return !1;
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]))
1640
- return !1;
1641
- }
1642
- return !0;
1643
- }
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;
1777
- /**
1778
- * Sets up a clean test environment
1779
- */
1780
- static setUp() {
1781
- this.originalInstance = o.instance, o.resetInstance(), o.enableLog = !1;
1782
- }
1783
- /**
1784
- * Tears down the test environment and restores original state
1785
- */
1786
- static tearDown() {
1787
- o.resetInstance();
1788
- }
1789
- /**
1790
- * Creates a test bloc with automatic cleanup
1791
- */
1792
- static createBloc(e, ...t) {
1793
- const s = new e(...t);
1794
- return o.activateBloc(s), s;
1795
- }
1796
- /**
1797
- * Waits for a bloc to emit a specific state
1798
- */
1799
- static async waitForState(e, t, s = 5e3) {
1800
- return new Promise((i, n) => {
1801
- const a = setTimeout(() => {
1802
- n(
1803
- new Error(
1804
- `Timeout waiting for state matching predicate after ${s}ms`
1805
- )
1806
- );
1807
- }, s), c = e.subscribe((l) => {
1808
- t(l) && (clearTimeout(a), c(), i(l));
1809
- });
1810
- t(e.state) && (clearTimeout(a), c(), i(e.state));
1811
- });
1812
- }
1813
- /**
1814
- * Expects a bloc to emit specific states in order
1815
- */
1816
- static async expectStates(e, t, s = 5e3) {
1817
- const i = [];
1818
- return new Promise((n, a) => {
1819
- const c = setTimeout(() => {
1820
- a(
1821
- new Error(
1822
- `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(i)}`
1823
- )
1824
- );
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;
1837
- }
1838
- }
1839
- n();
1840
- }
1841
- });
1842
- });
1843
- }
1844
- }
1845
- class z extends R {
1846
- mockHandlers = /* @__PURE__ */ new Map();
1847
- constructor(e) {
1848
- super(e);
1849
- }
1850
- /**
1851
- * Mock an event handler for testing
1852
- */
1853
- mockEventHandler(e, t) {
1854
- this.on(e, t);
1855
- }
1856
- /**
1857
- * Get the number of registered handlers
1858
- */
1859
- getHandlerCount() {
1860
- return this.eventHandlers.size;
1861
- }
1862
- /**
1863
- * Check if a handler is registered for an event type
1864
- */
1865
- hasHandler(e) {
1866
- return this.eventHandlers.has(e);
1867
- }
1868
- }
1869
- class q extends O {
1870
- stateHistory = [];
1871
- constructor(e) {
1872
- super(e), this.stateHistory.push(e);
1873
- }
1874
- /**
1875
- * Override emit to track state history
1876
- */
1877
- emit(e) {
1878
- this.stateHistory.push(e), super.emit(e);
1879
- }
1880
- /**
1881
- * Get the history of all states
1882
- */
1883
- getStateHistory() {
1884
- return [...this.stateHistory];
1885
- }
1886
- /**
1887
- * Clear state history
1888
- */
1889
- clearStateHistory() {
1890
- this.stateHistory = [this.state];
1891
- }
1892
- }
1893
- class W {
1894
- initialStats;
1895
- constructor() {
1896
- this.initialStats = o.getMemoryStats();
1897
- }
1898
- /**
1899
- * Check for memory leaks and return a report
1900
- */
1901
- checkForLeaks() {
1902
- const e = o.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
1903
- Memory Leak Detection Report:
1904
- - Initial registered blocs: ${this.initialStats.registeredBlocs}
1905
- - Current registered blocs: ${e.registeredBlocs}
1906
- - Initial isolated blocs: ${this.initialStats.isolatedBlocs}
1907
- - Current isolated blocs: ${e.isolatedBlocs}
1908
- - Initial keep-alive blocs: ${this.initialStats.keepAliveBlocs}
1909
- - Current keep-alive blocs: ${e.keepAliveBlocs}
1910
- - Potential leaks detected: ${t ? "YES" : "NO"}
1911
- `.trim();
1912
- return {
1913
- hasLeaks: t,
1914
- report: s,
1915
- stats: e
1916
- };
1917
- }
1918
- }
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;
2019
- }
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);
2055
- }
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();
2094
- }
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)
2132
- try {
2133
- this.options.onUnmount(this.blocInstance);
2134
- } catch (t) {
2135
- console.error("Error in onUnmount hook:", t);
2136
- }
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();
2145
- }
2146
- }
2147
- // Set component name for rerender logging
2148
- setComponentName(e) {
2149
- this.componentName = e;
2150
- }
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);
2156
- }
2157
- // Get adapter metadata for plugins
2158
- getAdapterMetadata() {
2159
- return {
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
2168
- };
2169
- }
2170
- // Get value at a dot-notated path
2171
- getValueAtPath(e, t) {
2172
- const s = t.split(".");
2173
- let i = e;
2174
- for (const n of s) {
2175
- if (i == null) return;
2176
- i = i[n];
2177
- }
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;
2196
- }
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
- );
2213
- }
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
2233
- );
2234
- p.length > 0 ? i.push(...p) : i.push(c);
2235
- }
2236
- }
2237
- }
2238
- return i;
2239
- }
2240
- // Get last rerender reason
2241
- getLastRerenderReason() {
2242
- }
2243
- }
2244
- export {
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,
2262
- L as PropsUpdated,
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
2274
- };
2275
- //# sourceMappingURL=index.es.js.map