@blac/core 2.0.0-rc-7 → 2.0.0-rc-10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Blac.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- // TODO: Remove this eslint disable once any types are properly replaced
3
- import { BlocBase, BlocInstanceId } from "./BlocBase";
2
+ // TODO: The 'any' types in this file are necessary for proper type inference in complex generic scenarios.
3
+ // Specifically:
4
+ // 1. BlocConstructor<any> in Maps - allows any bloc type to be stored while maintaining type safety in usage
5
+ // 2. Type assertions for _disposalState - private property access across inheritance hierarchy
6
+ // 3. Constructor argument types - enables flexible bloc instantiation patterns
7
+ // These 'any' usages are carefully controlled and don't compromise runtime type safety.
8
+ import { BlocBase, BlocInstanceId, BlocLifecycleState } from './BlocBase';
4
9
  import {
5
- BlocBaseAbstract,
6
- BlocConstructor,
7
- BlocHookDependencyArrayFn,
8
- BlocState,
9
- InferPropsFromGeneric
10
- } from "./types";
10
+ BlocBaseAbstract,
11
+ BlocConstructor,
12
+ BlocHookDependencyArrayFn,
13
+ BlocState,
14
+ InferPropsFromGeneric,
15
+ } from './types';
11
16
 
12
17
  /**
13
18
  * Configuration options for the Blac instance
@@ -24,6 +29,8 @@ export interface GetBlocOptions<B extends BlocBase<unknown>> {
24
29
  onMount?: (bloc: B) => void;
25
30
  instanceRef?: string;
26
31
  throwIfNotFound?: boolean;
32
+ /** Force creation of a new instance for isolated blocs, bypassing instance lookup */
33
+ forceNewInstance?: boolean;
27
34
  }
28
35
 
29
36
  /**
@@ -43,7 +50,9 @@ class SingletonBlacManager implements BlacInstanceManager {
43
50
 
44
51
  getInstance(): Blac {
45
52
  if (!SingletonBlacManager._instance) {
46
- SingletonBlacManager._instance = new Blac({ __unsafe_ignore_singleton: true });
53
+ SingletonBlacManager._instance = new Blac({
54
+ __unsafe_ignore_singleton: true,
55
+ });
47
56
  }
48
57
  return SingletonBlacManager._instance;
49
58
  }
@@ -54,8 +63,10 @@ class SingletonBlacManager implements BlacInstanceManager {
54
63
 
55
64
  resetInstance(): void {
56
65
  const oldInstance = SingletonBlacManager._instance;
57
- SingletonBlacManager._instance = new Blac({ __unsafe_ignore_singleton: true });
58
-
66
+ SingletonBlacManager._instance = new Blac({
67
+ __unsafe_ignore_singleton: true,
68
+ });
69
+
59
70
  // Transfer any keep-alive blocs to the new instance
60
71
  if (oldInstance) {
61
72
  for (const bloc of oldInstance.keepAliveBlocs) {
@@ -82,14 +93,13 @@ export function setBlacInstanceManager(manager: BlacInstanceManager): void {
82
93
  * Main Blac class that manages the state management system.
83
94
  * Can work with singleton pattern or dependency injection.
84
95
  * Handles bloc lifecycle, and instance tracking.
85
- *
96
+ *
86
97
  * Key responsibilities:
87
98
  * - Managing bloc instances (creation, disposal, lookup)
88
99
  * - Handling isolated and non-isolated blocs
89
100
  * - Providing logging and debugging capabilities
90
101
  */
91
102
  export class Blac {
92
- /** @deprecated Use getInstance() instead */
93
103
  static get instance(): Blac {
94
104
  return instanceManager.getInstance();
95
105
  }
@@ -101,9 +111,12 @@ export class Blac {
101
111
  /** Map storing all registered bloc instances by their class name and ID */
102
112
  blocInstanceMap: Map<string, BlocBase<unknown>> = new Map();
103
113
  /** Map storing isolated bloc instances grouped by their constructor */
114
+ // Using BlocConstructor<BlocBase<unknown>> would break type inference when storing
115
+ // different bloc types in the same map. The 'any' allows proper polymorphic storage
116
+ // while maintaining type safety at usage sites through the BlocConstructor constraint.
104
117
  isolatedBlocMap: Map<BlocConstructor<any>, BlocBase<unknown>[]> = new Map();
105
118
  /** Map for O(1) lookup of isolated blocs by UID */
106
- private isolatedBlocIndex: Map<string, BlocBase<unknown>> = new Map();
119
+ isolatedBlocIndex: Map<string, BlocBase<unknown>> = new Map();
107
120
  /** Map tracking UIDs to prevent memory leaks */
108
121
  uidRegistry: Map<string, BlocBase<unknown>> = new Map();
109
122
  /** Set of keep-alive blocs for controlled cleanup */
@@ -125,15 +138,27 @@ export class Blac {
125
138
 
126
139
  /** Flag to enable/disable logging */
127
140
  static enableLog = false;
141
+ static logLevel: 'warn' | 'log' = 'warn';
142
+ static logSpy: ((...args: unknown[]) => void) | null = null;
128
143
 
129
144
  /**
130
145
  * Logs messages to console when logging is enabled
131
146
  * @param args - Arguments to log
132
147
  */
133
148
  log = (...args: unknown[]) => {
134
- if (Blac.enableLog) console.warn(`☢️ [Blac ${this.createdAt.toString()}]`, ...args);
149
+ if (Blac.logSpy) {
150
+ Blac.logSpy(args);
151
+ }
152
+ if (Blac.enableLog && Blac.logLevel === 'warn') {
153
+ // Logging disabled - console.warn removed
154
+ }
155
+ if (Blac.enableLog && Blac.logLevel === 'log') {
156
+ // Logging disabled - console.log removed
157
+ }
135
158
  };
136
- static get log() { return Blac.instance.log; }
159
+ static get log() {
160
+ return Blac.instance.log;
161
+ }
137
162
 
138
163
  /**
139
164
  * Gets the current Blac instance
@@ -143,7 +168,6 @@ export class Blac {
143
168
  return instanceManager.getInstance();
144
169
  }
145
170
 
146
-
147
171
  /**
148
172
  * Logs a warning message
149
173
  * @param message - Warning message
@@ -151,10 +175,12 @@ export class Blac {
151
175
  */
152
176
  warn = (message: string, ...args: unknown[]) => {
153
177
  if (Blac.enableLog) {
154
- console.warn(`🚨 [Blac ${String(Blac.instance.createdAt)}]`, message, ...args);
178
+ // Logging disabled - console.warn removed
155
179
  }
156
180
  };
157
- static get warn() { return Blac.instance.warn; }
181
+ static get warn() {
182
+ return Blac.instance.warn;
183
+ }
158
184
  /**
159
185
  * Logs an error message
160
186
  * @param message - Error message
@@ -162,17 +188,19 @@ export class Blac {
162
188
  */
163
189
  error = (message: string, ...args: unknown[]) => {
164
190
  if (Blac.enableLog) {
165
- console.error(`🚨 [Blac ${String(Blac.instance.createdAt)}]`, message, ...args);
191
+ // Logging disabled - console.error removed
166
192
  }
167
193
  };
168
- static get error() { return Blac.instance.error; }
194
+ static get error() {
195
+ return Blac.instance.error;
196
+ }
169
197
 
170
198
  /**
171
199
  * Resets the Blac instance to a new one, disposing non-keepAlive blocs
172
200
  * from the old instance.
173
201
  */
174
202
  resetInstance = (): void => {
175
- this.log("Reset Blac instance");
203
+ this.log('Reset Blac instance');
176
204
 
177
205
  // Create snapshots to avoid concurrent modification issues
178
206
  const oldBlocInstanceMap = new Map(this.blocInstanceMap);
@@ -181,14 +209,22 @@ export class Blac {
181
209
  // Dispose non-keepAlive blocs from the current instance
182
210
  // Use disposeBloc method to ensure proper cleanup
183
211
  oldBlocInstanceMap.forEach((bloc) => {
184
- if (!bloc._keepAlive && (bloc as any)._disposalState === 'active') {
212
+ // TODO: Type assertion for private property access (see explanation above)
213
+ if (
214
+ !bloc._keepAlive &&
215
+ (bloc as any)._disposalState === BlocLifecycleState.ACTIVE
216
+ ) {
185
217
  this.disposeBloc(bloc);
186
218
  }
187
219
  });
188
220
 
189
221
  oldIsolatedBlocMap.forEach((blocArray) => {
190
222
  blocArray.forEach((bloc) => {
191
- if (!bloc._keepAlive && (bloc as any)._disposalState === 'active') {
223
+ // TODO: Type assertion for private property access (see explanation above)
224
+ if (
225
+ !bloc._keepAlive &&
226
+ (bloc as any)._disposalState === BlocLifecycleState.ACTIVE
227
+ ) {
192
228
  this.disposeBloc(bloc);
193
229
  }
194
230
  });
@@ -201,7 +237,7 @@ export class Blac {
201
237
 
202
238
  // Use instance manager to reset
203
239
  instanceManager.resetInstance();
204
- }
240
+ };
205
241
  static resetInstance = (): void => {
206
242
  instanceManager.resetInstance();
207
243
  };
@@ -212,18 +248,32 @@ export class Blac {
212
248
  */
213
249
  disposeBloc = (bloc: BlocBase<unknown>): void => {
214
250
  // Check if bloc is already disposed to prevent double disposal
215
- if ((bloc as any)._disposalState !== 'active') {
216
- this.log(`[${bloc._name}:${String(bloc._id)}] disposeBloc called on already disposed bloc`);
251
+ // TODO: Type assertion needed to access private _disposalState property from external class.
252
+ // This is safe because we know BlocBase has this property, but TypeScript can't verify
253
+ // private property access across class boundaries. Alternative would be to make
254
+ // _disposalState protected, but that would expose internal implementation details.
255
+ const currentState = (bloc as any)._disposalState;
256
+ const validStatesForDisposal = [
257
+ BlocLifecycleState.ACTIVE,
258
+ BlocLifecycleState.DISPOSAL_REQUESTED,
259
+ ];
260
+
261
+ if (!validStatesForDisposal.includes(currentState)) {
262
+ this.log(
263
+ `[${bloc._name}:${String(bloc._id)}] disposeBloc called on bloc in invalid state: ${currentState}`,
264
+ );
217
265
  return;
218
266
  }
219
267
 
220
268
  const base = bloc.constructor as unknown as BlocBaseAbstract;
221
269
  const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);
222
- this.log(`[${bloc._name}:${String(bloc._id)}] disposeBloc called. Isolated: ${String(base.isolated)}`);
270
+ this.log(
271
+ `[${bloc._name}:${String(bloc._id)}] disposeBloc called. Isolated: ${String(base.isolated)}`,
272
+ );
223
273
 
224
274
  // First dispose the bloc to prevent further operations
225
275
  bloc._dispose();
226
-
276
+
227
277
  // Then clean up from registries
228
278
  if (base.isolated) {
229
279
  this.unregisterIsolatedBlocInstance(bloc);
@@ -231,10 +281,12 @@ export class Blac {
231
281
  } else {
232
282
  this.unregisterBlocInstance(bloc);
233
283
  }
234
-
235
- this.log('dispatched bloc', bloc)
284
+
285
+ this.log('dispatched bloc', bloc);
236
286
  };
237
- static get disposeBloc() { return Blac.instance.disposeBloc; }
287
+ static get disposeBloc() {
288
+ return Blac.instance.disposeBloc;
289
+ }
238
290
 
239
291
  /**
240
292
  * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
@@ -253,10 +305,10 @@ export class Blac {
253
305
  unregisterBlocInstance(bloc: BlocBase<unknown>): void {
254
306
  const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);
255
307
  this.blocInstanceMap.delete(key);
256
-
308
+
257
309
  // Clean up UID tracking
258
310
  this.uidRegistry.delete(bloc.uid);
259
-
311
+
260
312
  // Remove from keep-alive set
261
313
  this.keepAliveBlocs.delete(bloc);
262
314
  }
@@ -268,10 +320,10 @@ export class Blac {
268
320
  registerBlocInstance(bloc: BlocBase<unknown>): void {
269
321
  const key = this.createBlocInstanceMapKey(bloc._name, bloc._id);
270
322
  this.blocInstanceMap.set(key, bloc);
271
-
323
+
272
324
  // Track UID for cleanup
273
325
  this.uidRegistry.set(bloc.uid, bloc);
274
-
326
+
275
327
  // Track keep-alive blocs
276
328
  if (bloc._keepAlive) {
277
329
  this.keepAliveBlocs.add(bloc);
@@ -293,7 +345,7 @@ export class Blac {
293
345
 
294
346
  const key = this.createBlocInstanceMapKey(blocClass.name, id);
295
347
  const found = this.blocInstanceMap.get(key) as InstanceType<B> | undefined;
296
- return found
348
+ return found;
297
349
  }
298
350
 
299
351
  /**
@@ -308,13 +360,13 @@ export class Blac {
308
360
  } else {
309
361
  this.isolatedBlocMap.set(blocClass, [bloc]);
310
362
  }
311
-
363
+
312
364
  // Add to isolated index for O(1) lookups
313
365
  this.isolatedBlocIndex.set(bloc.uid, bloc);
314
-
366
+
315
367
  // Track UID for cleanup
316
368
  this.uidRegistry.set(bloc.uid, bloc);
317
-
369
+
318
370
  // Track keep-alive blocs
319
371
  if (bloc._keepAlive) {
320
372
  this.keepAliveBlocs.add(bloc);
@@ -328,10 +380,10 @@ export class Blac {
328
380
  unregisterIsolatedBlocInstance(bloc: BlocBase<unknown>): void {
329
381
  const blocClass = bloc.constructor;
330
382
  const blocs = this.isolatedBlocMap.get(blocClass as BlocConstructor<any>);
331
-
383
+
332
384
  // Ensure both data structures are synchronized
333
385
  let wasRemoved = false;
334
-
386
+
335
387
  if (blocs) {
336
388
  const index = blocs.findIndex((b) => b.uid === bloc.uid);
337
389
  if (index !== -1) {
@@ -343,21 +395,21 @@ export class Blac {
343
395
  this.isolatedBlocMap.delete(blocClass as BlocConstructor<any>);
344
396
  }
345
397
  }
346
-
398
+
347
399
  // Always try to remove from isolated index, even if not found in map
348
400
  const wasInIndex = this.isolatedBlocIndex.delete(bloc.uid);
349
-
401
+
350
402
  // Clean up UID tracking
351
403
  this.uidRegistry.delete(bloc.uid);
352
-
404
+
353
405
  // Remove from keep-alive set
354
406
  this.keepAliveBlocs.delete(bloc);
355
-
407
+
356
408
  // Log inconsistency for debugging
357
409
  if (wasRemoved !== wasInIndex) {
358
410
  this.warn(
359
411
  `[Blac] Inconsistent state detected during isolated bloc cleanup for ${bloc._name}:${bloc.uid}. ` +
360
- `Map removal: ${wasRemoved}, Index removal: ${wasInIndex}`
412
+ `Map removal: ${wasRemoved}, Index removal: ${wasInIndex}`,
361
413
  );
362
414
  }
363
415
  }
@@ -377,7 +429,9 @@ export class Blac {
377
429
  return undefined;
378
430
  }
379
431
  // Find the specific bloc by ID within the isolated array
380
- const found = blocs.find((b) => b._id === id) as InstanceType<B> | undefined;
432
+ const found = blocs.find((b) => b._id === id) as
433
+ | InstanceType<B>
434
+ | undefined;
381
435
  return found;
382
436
  }
383
437
 
@@ -385,7 +439,7 @@ export class Blac {
385
439
  * Finds an isolated bloc instance by UID (O(1) lookup)
386
440
  */
387
441
  findIsolatedBlocInstanceByUid<B extends BlocBase<unknown>>(
388
- uid: string
442
+ uid: string,
389
443
  ): B | undefined {
390
444
  return this.isolatedBlocIndex.get(uid) as B | undefined;
391
445
  }
@@ -421,29 +475,42 @@ export class Blac {
421
475
  return newBloc;
422
476
  }
423
477
 
424
-
425
478
  activateBloc = (bloc: BlocBase<unknown>): void => {
479
+ // Don't activate disposed blocs
480
+ if ((bloc as any)._disposalState !== BlocLifecycleState.ACTIVE) {
481
+ this.log(
482
+ `[${bloc._name}:${String(bloc._id)}] activateBloc called on disposed bloc. Ignoring.`,
483
+ );
484
+ return;
485
+ }
486
+
426
487
  const base = bloc.constructor as unknown as BlocConstructor<BlocBase<any>>;
427
488
  const isIsolated = bloc.isIsolated;
428
489
 
429
- let found = isIsolated ? this.findIsolatedBlocInstance(base, bloc._id) : this.findRegisteredBlocInstance(base, bloc._id);
490
+ let found = isIsolated
491
+ ? this.findIsolatedBlocInstance(base, bloc._id)
492
+ : this.findRegisteredBlocInstance(base, bloc._id);
430
493
  if (found) {
431
494
  return;
432
495
  }
433
496
 
434
- this.log(`[${bloc._name}:${String(bloc._id)}] activateBloc called. Isolated: ${String(bloc.isIsolated)}`);
497
+ this.log(
498
+ `[${bloc._name}:${String(bloc._id)}] activateBloc called. Isolated: ${String(bloc.isIsolated)}`,
499
+ );
435
500
  if (bloc.isIsolated) {
436
501
  this.registerIsolatedBlocInstance(bloc);
437
502
  } else {
438
503
  this.registerBlocInstance(bloc);
439
504
  }
440
505
  };
441
- static get activateBloc() { return Blac.instance.activateBloc; }
506
+ static get activateBloc() {
507
+ return Blac.instance.activateBloc;
508
+ }
442
509
 
443
510
  /**
444
511
  * Gets or creates a bloc instance based on the provided class and options.
445
512
  * If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
446
- *
513
+ *
447
514
  * @param blocClass - The bloc class to get or create
448
515
  * @param options - Options including:
449
516
  * - id: The instance ID (defaults to class name if not provided)
@@ -455,47 +522,61 @@ export class Blac {
455
522
  blocClass: B,
456
523
  options: GetBlocOptions<InstanceType<B>> = {},
457
524
  ): InstanceType<B> => {
458
- const { id } = options;
525
+ const { id, forceNewInstance } = options;
459
526
  const base = blocClass as unknown as BlocBaseAbstract;
460
527
  const blocId = id ?? blocClass.name;
528
+ this.log(`[${blocClass.name}:${String(blocId)}] (getBloc) Called:`, {
529
+ options,
530
+ base,
531
+ });
461
532
 
462
-
463
- if (base.isolated) {
464
- const isolatedBloc = this.findIsolatedBlocInstance<B>(blocClass, blocId)
465
- if (isolatedBloc) {
466
- this.log(`[${blocClass.name}:${String(blocId)}] (getBloc) Found existing isolated instance.`, options);
467
- return isolatedBloc;
468
- } else {
469
- if (options.throwIfNotFound) {
470
- throw new Error(`Isolated bloc ${blocClass.name} not found`);
533
+ // Skip instance lookup if forceNewInstance is true for isolated blocs
534
+ if (!forceNewInstance) {
535
+ if (base.isolated) {
536
+ const isolatedBloc = this.findIsolatedBlocInstance<B>(
537
+ blocClass,
538
+ options.instanceRef ?? blocId,
539
+ );
540
+ if (isolatedBloc) {
541
+ return isolatedBloc;
542
+ } else {
543
+ if (options.throwIfNotFound) {
544
+ throw new Error(`Isolated bloc ${blocClass.name} not found`);
545
+ }
471
546
  }
472
- }
473
- } else {
474
- const registeredBloc = this.findRegisteredBlocInstance(blocClass, blocId)
475
- if (registeredBloc) {
476
- this.log(`[${blocClass.name}:${String(blocId)}] (getBloc) Found existing registered instance.`, options);
477
- return registeredBloc
478
547
  } else {
479
- if (options.throwIfNotFound) {
480
- throw new Error(`Registered bloc ${blocClass.name} not found`);
548
+ const registeredBloc = this.findRegisteredBlocInstance(
549
+ blocClass,
550
+ blocId,
551
+ );
552
+ if (registeredBloc) {
553
+ return registeredBloc;
554
+ } else {
555
+ if (options.throwIfNotFound) {
556
+ throw new Error(`Registered bloc ${blocClass.name} not found`);
557
+ }
481
558
  }
482
559
  }
483
560
  }
484
561
 
485
- const bloc = this.createNewBlocInstance(
486
- blocClass,
487
- blocId,
562
+ const bloc = this.createNewBlocInstance(blocClass, blocId, options);
563
+ this.log(
564
+ `[${blocClass.name}:${String(blocId)}] (getBloc) No existing instance found. Creating new one.`,
488
565
  options,
566
+ bloc,
489
567
  );
490
- this.log(`[${blocClass.name}:${String(blocId)}] (getBloc) No existing instance found. Creating new one.`, options, bloc);
491
-
568
+
492
569
  if (!bloc) {
493
- throw new Error(`[getBloc] Failed to create bloc instance for ${blocClass.name}. This should never happen.`);
570
+ throw new Error(
571
+ `[getBloc] Failed to create bloc instance for ${blocClass.name}. This should never happen.`,
572
+ );
494
573
  }
495
-
574
+
496
575
  return bloc;
497
576
  };
498
- static get getBloc() { return Blac.instance.getBloc; }
577
+ static get getBloc() {
578
+ return Blac.instance.getBloc;
579
+ }
499
580
 
500
581
  /**
501
582
  * Gets a bloc instance or throws an error if it doesn't exist
@@ -525,7 +606,9 @@ export class Blac {
525
606
  }
526
607
  throw new Error(`Bloc ${blocClass.name} not found`);
527
608
  };
528
- static get getBlocOrThrow() { return Blac.instance.getBlocOrThrow; }
609
+ static get getBlocOrThrow() {
610
+ return Blac.instance.getBlocOrThrow;
611
+ }
529
612
 
530
613
  /**
531
614
  * Gets all instances of a specific bloc class
@@ -545,7 +628,8 @@ export class Blac {
545
628
 
546
629
  // Search non-isolated blocs
547
630
  this.blocInstanceMap.forEach((blocInstance) => {
548
- if (blocInstance.constructor === blocClass) { // Strict constructor check
631
+ if (blocInstance.constructor === blocClass) {
632
+ // Strict constructor check
549
633
  results.push(blocInstance as InstanceType<B>);
550
634
  }
551
635
  });
@@ -554,7 +638,7 @@ export class Blac {
554
638
  if (options.searchIsolated !== false) {
555
639
  const isolatedBlocs = this.isolatedBlocMap.get(blocClass);
556
640
  if (isolatedBlocs) {
557
- results.push(...isolatedBlocs.map(bloc => bloc as InstanceType<B>));
641
+ results.push(...isolatedBlocs.map((bloc) => bloc as InstanceType<B>));
558
642
  }
559
643
  }
560
644
 
@@ -566,19 +650,21 @@ export class Blac {
566
650
  * @param blocClass - The bloc class to dispose
567
651
  */
568
652
  disposeKeepAliveBlocs = <B extends BlocConstructor<any>>(
569
- blocClass?: B
653
+ blocClass?: B,
570
654
  ): void => {
571
655
  const toDispose: BlocBase<unknown>[] = [];
572
-
656
+
573
657
  for (const bloc of this.keepAliveBlocs) {
574
658
  if (!blocClass || bloc.constructor === blocClass) {
575
659
  toDispose.push(bloc);
576
660
  }
577
661
  }
578
-
579
- toDispose.forEach(bloc => bloc._dispose());
662
+
663
+ toDispose.forEach((bloc) => bloc._dispose());
580
664
  };
581
- static get disposeKeepAliveBlocs() { return Blac.instance.disposeKeepAliveBlocs; }
665
+ static get disposeKeepAliveBlocs() {
666
+ return Blac.instance.disposeKeepAliveBlocs;
667
+ }
582
668
 
583
669
  /**
584
670
  * Disposes all blocs matching a pattern
@@ -586,14 +672,14 @@ export class Blac {
586
672
  */
587
673
  disposeBlocs = (predicate: (bloc: BlocBase<unknown>) => boolean): void => {
588
674
  const toDispose: BlocBase<unknown>[] = [];
589
-
675
+
590
676
  // Check registered blocs
591
677
  for (const bloc of this.blocInstanceMap.values()) {
592
678
  if (predicate(bloc)) {
593
679
  toDispose.push(bloc);
594
680
  }
595
681
  }
596
-
682
+
597
683
  // Check isolated blocs
598
684
  for (const blocs of this.isolatedBlocMap.values()) {
599
685
  for (const bloc of blocs) {
@@ -602,10 +688,12 @@ export class Blac {
602
688
  }
603
689
  }
604
690
  }
605
-
606
- toDispose.forEach(bloc => bloc._dispose());
691
+
692
+ toDispose.forEach((bloc) => bloc._dispose());
607
693
  };
608
- static get disposeBlocs() { return Blac.instance.disposeBlocs; }
694
+ static get disposeBlocs() {
695
+ return Blac.instance.disposeBlocs;
696
+ }
609
697
 
610
698
  /**
611
699
  * Gets memory usage statistics for debugging
@@ -614,12 +702,17 @@ export class Blac {
614
702
  return {
615
703
  totalBlocs: this.uidRegistry.size,
616
704
  registeredBlocs: this.blocInstanceMap.size,
617
- isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce((sum, arr) => sum + arr.length, 0),
705
+ isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(
706
+ (sum, arr) => sum + arr.length,
707
+ 0,
708
+ ),
618
709
  keepAliveBlocs: this.keepAliveBlocs.size,
619
710
  isolatedBlocTypes: this.isolatedBlocMap.size,
620
711
  };
621
712
  };
622
- static get getMemoryStats() { return Blac.instance.getMemoryStats; }
713
+ static get getMemoryStats() {
714
+ return Blac.instance.getMemoryStats;
715
+ }
623
716
 
624
717
  /**
625
718
  * Validates consumer references and cleans up orphaned consumers
@@ -628,18 +721,30 @@ export class Blac {
628
721
  for (const bloc of this.uidRegistry.values()) {
629
722
  // Validate consumers using the bloc's own validation method
630
723
  bloc._validateConsumers();
631
-
724
+
632
725
  // Check if bloc should be disposed after validation
633
- if (bloc._consumers.size === 0 && !bloc._keepAlive && (bloc as any)._disposalState === 'active') {
726
+ // TODO: Type assertion for private property access (see explanation above)
727
+ if (
728
+ bloc._consumers.size === 0 &&
729
+ !bloc._keepAlive &&
730
+ (bloc as any)._disposalState === BlocLifecycleState.ACTIVE
731
+ ) {
634
732
  // Schedule disposal for blocs with no consumers
635
733
  setTimeout(() => {
636
734
  // Double-check conditions before disposal
637
- if (bloc._consumers.size === 0 && !bloc._keepAlive && (bloc as any)._disposalState === 'active') {
735
+ // TODO: Type assertion for private property access (see explanation above)
736
+ if (
737
+ bloc._consumers.size === 0 &&
738
+ !bloc._keepAlive &&
739
+ (bloc as any)._disposalState === BlocLifecycleState.ACTIVE
740
+ ) {
638
741
  this.disposeBloc(bloc);
639
742
  }
640
743
  }, 1000); // Give a grace period
641
744
  }
642
745
  }
643
746
  };
644
- static get validateConsumers() { return Blac.instance.validateConsumers; }
747
+ static get validateConsumers() {
748
+ return Blac.instance.validateConsumers;
749
+ }
645
750
  }