@blac/core 2.0.0-rc-8 → 2.0.0-rc-11
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/README.md +27 -0
- package/dist/index.cjs.js +2 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +224 -14
- package/dist/index.es.js +1122 -556
- package/dist/index.es.js.map +1 -1
- package/package.json +5 -4
- package/src/Blac.ts +109 -47
- package/src/BlacObserver.ts +58 -24
- package/src/Bloc.ts +120 -160
- package/src/BlocBase.ts +266 -90
- package/src/Cubit.ts +15 -1
- package/src/__tests__/Blac.config.test.ts +86 -0
- package/src/__tests__/Bloc.event.test.ts +419 -0
- package/src/__tests__/BlocBase.lifecycle.test.ts +441 -0
- package/src/__tests__/Cubit.test.ts +473 -0
- package/src/__tests__/props.test.ts +256 -0
- package/src/adapter/BlacAdapter.ts +327 -0
- package/src/adapter/ConsumerTracker.ts +241 -0
- package/src/adapter/ProxyFactory.ts +308 -0
- package/src/adapter/__tests__/BlacAdapter.test.ts +561 -0
- package/src/adapter/__tests__/ConsumerTracker.test.ts +562 -0
- package/src/adapter/__tests__/ProxyFactory.test.ts +655 -0
- package/src/adapter/index.ts +3 -0
- package/src/events.ts +3 -0
- package/src/index.ts +4 -1
- package/src/testing.ts +60 -47
- package/src/types.ts +12 -13
- package/src/utils/shallowEqual.ts +40 -0
- package/src/utils/uuid.ts +4 -4
- package/src/BlacEvent.ts +0 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export declare interface AdapterOptions<B extends BlocBase<any>> {
|
|
2
|
+
id?: string;
|
|
3
|
+
dependencies?: (bloc: B) => unknown[];
|
|
4
|
+
props?: any;
|
|
5
|
+
onMount?: (bloc: B) => void;
|
|
6
|
+
onUnmount?: (bloc: B) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
1
9
|
/**
|
|
2
10
|
* Main Blac class that manages the state management system.
|
|
3
11
|
* Can work with singleton pattern or dependency injection.
|
|
@@ -9,19 +17,28 @@
|
|
|
9
17
|
* - Providing logging and debugging capabilities
|
|
10
18
|
*/
|
|
11
19
|
export declare class Blac {
|
|
12
|
-
/** @deprecated Use getInstance() instead */
|
|
13
20
|
static get instance(): Blac;
|
|
14
21
|
/** Timestamp when the instance was created */
|
|
15
22
|
createdAt: number;
|
|
16
23
|
static get getAllBlocs(): <B extends BlocConstructor<any>>(blocClass: B, options?: {
|
|
17
24
|
searchIsolated?: boolean;
|
|
18
25
|
}) => InstanceType<B>[];
|
|
26
|
+
/** Private static configuration */
|
|
27
|
+
private static _config;
|
|
28
|
+
/** Get current configuration */
|
|
29
|
+
static get config(): Readonly<BlacConfig>;
|
|
30
|
+
/**
|
|
31
|
+
* Set or update Blac configuration
|
|
32
|
+
* @param config - Partial configuration to merge with existing config
|
|
33
|
+
* @throws Error if configuration is invalid
|
|
34
|
+
*/
|
|
35
|
+
static setConfig(config: Partial<BlacConfig>): void;
|
|
19
36
|
/** Map storing all registered bloc instances by their class name and ID */
|
|
20
37
|
blocInstanceMap: Map<string, BlocBase<unknown>>;
|
|
21
38
|
/** Map storing isolated bloc instances grouped by their constructor */
|
|
22
39
|
isolatedBlocMap: Map<BlocConstructor<any>, BlocBase<unknown>[]>;
|
|
23
40
|
/** Map for O(1) lookup of isolated blocs by UID */
|
|
24
|
-
|
|
41
|
+
isolatedBlocIndex: Map<string, BlocBase<unknown>>;
|
|
25
42
|
/** Map tracking UIDs to prevent memory leaks */
|
|
26
43
|
uidRegistry: Map<string, BlocBase<unknown>>;
|
|
27
44
|
/** Set of keep-alive blocs for controlled cleanup */
|
|
@@ -38,6 +55,7 @@ export declare class Blac {
|
|
|
38
55
|
/** Flag to enable/disable logging */
|
|
39
56
|
static enableLog: boolean;
|
|
40
57
|
static logLevel: 'warn' | 'log';
|
|
58
|
+
static logSpy: ((...args: unknown[]) => void) | null;
|
|
41
59
|
/**
|
|
42
60
|
* Logs messages to console when logging is enabled
|
|
43
61
|
* @param args - Arguments to log
|
|
@@ -205,12 +223,69 @@ export declare class Blac {
|
|
|
205
223
|
static get validateConsumers(): () => void;
|
|
206
224
|
}
|
|
207
225
|
|
|
226
|
+
/**
|
|
227
|
+
* BlacAdapter orchestrates the connection between Bloc instances and React components.
|
|
228
|
+
* It manages dependency tracking, lifecycle hooks, and proxy creation.
|
|
229
|
+
*/
|
|
230
|
+
export declare class BlacAdapter<B extends BlocConstructor<BlocBase<any>>> {
|
|
231
|
+
readonly id: string;
|
|
232
|
+
readonly blocConstructor: B;
|
|
233
|
+
readonly componentRef: {
|
|
234
|
+
current: object;
|
|
235
|
+
};
|
|
236
|
+
blocInstance: InstanceType<B>;
|
|
237
|
+
private consumerTracker;
|
|
238
|
+
private static propsOwners;
|
|
239
|
+
private lastProps?;
|
|
240
|
+
unmountTime: number;
|
|
241
|
+
mountTime: number;
|
|
242
|
+
private dependencyValues?;
|
|
243
|
+
private isUsingDependencies;
|
|
244
|
+
private hasMounted;
|
|
245
|
+
private mountCount;
|
|
246
|
+
options?: AdapterOptions<InstanceType<B>>;
|
|
247
|
+
constructor(instanceProps: {
|
|
248
|
+
componentRef: {
|
|
249
|
+
current: object;
|
|
250
|
+
};
|
|
251
|
+
blocConstructor: B;
|
|
252
|
+
}, options?: typeof BlacAdapter.options);
|
|
253
|
+
trackAccess(consumerRef: object, type: 'state' | 'class', path: string, value?: any): void;
|
|
254
|
+
getConsumerDependencies(consumerRef: object): DependencyArray | null;
|
|
255
|
+
shouldNotifyConsumer(consumerRef: object, changedPaths: Set<string>): boolean;
|
|
256
|
+
updateLastNotified(consumerRef: object): void;
|
|
257
|
+
resetConsumerTracking(): void;
|
|
258
|
+
createStateProxy: <T extends object>(props: {
|
|
259
|
+
target: T;
|
|
260
|
+
}) => T;
|
|
261
|
+
createClassProxy: <T extends object>(props: {
|
|
262
|
+
target: T;
|
|
263
|
+
}) => T;
|
|
264
|
+
updateBlocInstance(): InstanceType<B>;
|
|
265
|
+
createSubscription: (options: {
|
|
266
|
+
onChange: () => void;
|
|
267
|
+
}) => () => void;
|
|
268
|
+
mount: () => void;
|
|
269
|
+
unmount: () => void;
|
|
270
|
+
getProxyState: (state: BlocState<InstanceType<B>>) => BlocState<InstanceType<B>>;
|
|
271
|
+
getProxyBlocInstance: () => InstanceType<B>;
|
|
272
|
+
get calledOnMount(): boolean;
|
|
273
|
+
updateProps(props: any): void;
|
|
274
|
+
private hasDependencyValuesChanged;
|
|
275
|
+
}
|
|
276
|
+
|
|
208
277
|
/**
|
|
209
278
|
* Configuration options for the Blac instance
|
|
210
279
|
*/
|
|
211
280
|
export declare interface BlacConfig {
|
|
212
281
|
/** Whether to expose the Blac instance globally */
|
|
213
282
|
exposeBlacInstance?: boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Whether to enable proxy dependency tracking for automatic re-render optimization.
|
|
285
|
+
* When false, state changes always cause re-renders unless dependencies are manually specified.
|
|
286
|
+
* Default: true
|
|
287
|
+
*/
|
|
288
|
+
proxyDependencyTracking?: boolean;
|
|
214
289
|
}
|
|
215
290
|
|
|
216
291
|
/**
|
|
@@ -281,7 +356,7 @@ export declare type BlacObserver<S> = {
|
|
|
281
356
|
/** Dispose function for the observer */
|
|
282
357
|
dispose?: () => void;
|
|
283
358
|
/** Cached state values used for dependency comparison */
|
|
284
|
-
lastState?: unknown[]
|
|
359
|
+
lastState?: unknown[];
|
|
285
360
|
/** Unique identifier for the observer */
|
|
286
361
|
id: string;
|
|
287
362
|
};
|
|
@@ -354,6 +429,7 @@ export declare abstract class BlocBase<S, P = unknown> {
|
|
|
354
429
|
*/
|
|
355
430
|
readonly _createdAt: number;
|
|
356
431
|
/* Excluded from this release type: _disposalState */
|
|
432
|
+
/* Excluded from this release type: _disposalRequestTime */
|
|
357
433
|
/* Excluded from this release type: _state */
|
|
358
434
|
/* Excluded from this release type: _oldState */
|
|
359
435
|
/**
|
|
@@ -375,10 +451,17 @@ export declare abstract class BlocBase<S, P = unknown> {
|
|
|
375
451
|
/**
|
|
376
452
|
* Returns the current state of the Bloc.
|
|
377
453
|
* Use this getter to access the state in a read-only manner.
|
|
454
|
+
* Returns the state even during transitional lifecycle states for React compatibility.
|
|
378
455
|
*/
|
|
379
456
|
get state(): S;
|
|
457
|
+
/**
|
|
458
|
+
* Returns whether this Bloc instance has been disposed.
|
|
459
|
+
* @returns true if the bloc is in DISPOSED state
|
|
460
|
+
*/
|
|
461
|
+
get isDisposed(): boolean;
|
|
380
462
|
/* Excluded from this release type: _name */
|
|
381
463
|
/* Excluded from this release type: _updateId */
|
|
464
|
+
/* Excluded from this release type: _atomicStateTransition */
|
|
382
465
|
/* Excluded from this release type: _dispose */
|
|
383
466
|
/* Excluded from this release type: onDispose */
|
|
384
467
|
/* Excluded from this release type: _consumers */
|
|
@@ -412,7 +495,10 @@ export declare type BlocClassNoParams<B> = new (args: never[]) => B;
|
|
|
412
495
|
* Represents a constructor type for a Bloc that can take any parameters
|
|
413
496
|
* @template B - The type of the Bloc instance
|
|
414
497
|
*/
|
|
415
|
-
export declare type BlocConstructor<B> = new (...args: any) => B
|
|
498
|
+
export declare type BlocConstructor<B> = (new (...args: any) => B) & {
|
|
499
|
+
isolated?: boolean;
|
|
500
|
+
keepAlive?: boolean;
|
|
501
|
+
};
|
|
416
502
|
|
|
417
503
|
/**
|
|
418
504
|
* Extracts the constructor parameters type from a BlocBase
|
|
@@ -431,19 +517,10 @@ export declare interface BlocErrorBoundary<S, A extends BlocEventConstraint> {
|
|
|
431
517
|
shouldRethrow?: (error: Error, event: A) => boolean;
|
|
432
518
|
}
|
|
433
519
|
|
|
434
|
-
/**
|
|
435
|
-
* Base interface for all Bloc events
|
|
436
|
-
* Events must be objects with a constructor to enable proper type matching
|
|
437
|
-
*/
|
|
438
|
-
export declare interface BlocEvent {
|
|
439
|
-
readonly type?: string;
|
|
440
|
-
readonly timestamp?: number;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
520
|
/**
|
|
444
521
|
* Enhanced constraint for Bloc events - must be objects with proper constructor
|
|
445
522
|
*/
|
|
446
|
-
export declare type BlocEventConstraint =
|
|
523
|
+
export declare type BlocEventConstraint = object;
|
|
447
524
|
|
|
448
525
|
/**
|
|
449
526
|
* Function type for determining dependencies that trigger re-renders
|
|
@@ -459,6 +536,17 @@ export declare type BlocHookDependencyArrayFn<S, I = any> = (currentState: S, pr
|
|
|
459
536
|
|
|
460
537
|
export declare type BlocInstanceId = string | number | undefined;
|
|
461
538
|
|
|
539
|
+
/**
|
|
540
|
+
* Enum representing the lifecycle states of a Bloc instance
|
|
541
|
+
* Used for atomic state transitions to prevent race conditions
|
|
542
|
+
*/
|
|
543
|
+
export declare enum BlocLifecycleState {
|
|
544
|
+
ACTIVE = "active",
|
|
545
|
+
DISPOSAL_REQUESTED = "disposal_requested",
|
|
546
|
+
DISPOSING = "disposing",
|
|
547
|
+
DISPOSED = "disposed"
|
|
548
|
+
}
|
|
549
|
+
|
|
462
550
|
/**
|
|
463
551
|
* Extracts the state type from either a Bloc or Cubit
|
|
464
552
|
* @template T - The Bloc or Cubit type to extract the state from
|
|
@@ -492,6 +580,49 @@ export declare class BlocTest {
|
|
|
492
580
|
static expectStates<T extends BlocBase<S>, S>(bloc: T, expectedStates: S[], timeout?: number): Promise<void>;
|
|
493
581
|
}
|
|
494
582
|
|
|
583
|
+
export declare interface ConsumerInfo {
|
|
584
|
+
id: string;
|
|
585
|
+
lastNotified: number;
|
|
586
|
+
hasRendered: boolean;
|
|
587
|
+
stateAccesses: Set<string>;
|
|
588
|
+
classAccesses: Set<string>;
|
|
589
|
+
stateValues: Map<string, TrackedValue>;
|
|
590
|
+
classValues: Map<string, TrackedValue>;
|
|
591
|
+
accessCount: number;
|
|
592
|
+
lastAccessTime: number;
|
|
593
|
+
firstAccessTime: number;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* ConsumerTracker manages both consumer registration and dependency tracking.
|
|
598
|
+
* It uses a WeakMap for automatic garbage collection when consumers are no longer referenced.
|
|
599
|
+
*/
|
|
600
|
+
export declare class ConsumerTracker {
|
|
601
|
+
private consumers;
|
|
602
|
+
private registrationCount;
|
|
603
|
+
private activeConsumers;
|
|
604
|
+
register(consumerRef: object, consumerId: string): void;
|
|
605
|
+
unregister(consumerRef: object): void;
|
|
606
|
+
trackAccess(consumerRef: object, type: 'state' | 'class', path: string, value?: any): void;
|
|
607
|
+
resetTracking(consumerRef: object): void;
|
|
608
|
+
getDependencies(consumerRef: object): DependencyArray | null;
|
|
609
|
+
hasValuesChanged(consumerRef: object, newState: any, newBlocInstance: any): boolean;
|
|
610
|
+
shouldNotifyConsumer(consumerRef: object, changedPaths: Set<string>): boolean;
|
|
611
|
+
updateLastNotified(consumerRef: object): void;
|
|
612
|
+
getConsumerInfo(consumerRef: object): ConsumerInfo | undefined;
|
|
613
|
+
setHasRendered(consumerRef: object, hasRendered: boolean): void;
|
|
614
|
+
hasConsumer(consumerRef: object): boolean;
|
|
615
|
+
getStats(): {
|
|
616
|
+
totalRegistrations: number;
|
|
617
|
+
activeConsumers: number;
|
|
618
|
+
};
|
|
619
|
+
private getValueAtPath;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
declare interface ConsumerTracker_2 {
|
|
623
|
+
trackAccess: (consumerRef: object, type: 'state' | 'class', path: string, value?: any) => void;
|
|
624
|
+
}
|
|
625
|
+
|
|
495
626
|
/**
|
|
496
627
|
* A Cubit is a simpler version of a Bloc that doesn't handle events.
|
|
497
628
|
* It manages state and provides methods to update it.
|
|
@@ -499,6 +630,11 @@ export declare class BlocTest {
|
|
|
499
630
|
* @template P - The type of parameters (optional, defaults to null)
|
|
500
631
|
*/
|
|
501
632
|
export declare abstract class Cubit<S, P = null> extends BlocBase<S, P> {
|
|
633
|
+
/* Excluded from this release type: _updateProps */
|
|
634
|
+
/**
|
|
635
|
+
* Optional override for props handling
|
|
636
|
+
*/
|
|
637
|
+
protected onPropsChanged?(oldProps: P | undefined, newProps: P): void;
|
|
502
638
|
/**
|
|
503
639
|
* Updates the current state and notifies all observers of the change.
|
|
504
640
|
* If the new state is identical to the current state (using Object.is),
|
|
@@ -517,6 +653,11 @@ export declare abstract class Cubit<S, P = null> extends BlocBase<S, P> {
|
|
|
517
653
|
patch(statePatch: S extends object ? Partial<S> : S, ignoreChangeCheck?: boolean): void;
|
|
518
654
|
}
|
|
519
655
|
|
|
656
|
+
export declare interface DependencyArray {
|
|
657
|
+
statePaths: string[];
|
|
658
|
+
classPaths: string[];
|
|
659
|
+
}
|
|
660
|
+
|
|
520
661
|
declare type DependencySelector<S> = (currentState: S, previousState: S | undefined, instance: any) => unknown[];
|
|
521
662
|
|
|
522
663
|
/**
|
|
@@ -536,6 +677,8 @@ export declare interface GetBlocOptions<B extends BlocBase<unknown>> {
|
|
|
536
677
|
onMount?: (bloc: B) => void;
|
|
537
678
|
instanceRef?: string;
|
|
538
679
|
throwIfNotFound?: boolean;
|
|
680
|
+
/** Force creation of a new instance for isolated blocs, bypassing instance lookup */
|
|
681
|
+
forceNewInstance?: boolean;
|
|
539
682
|
}
|
|
540
683
|
|
|
541
684
|
/**
|
|
@@ -600,11 +743,78 @@ export declare class MockCubit<S> extends Cubit<S> {
|
|
|
600
743
|
clearStateHistory(): void;
|
|
601
744
|
}
|
|
602
745
|
|
|
746
|
+
export declare class PropsUpdated<P = any> {
|
|
747
|
+
readonly props: P;
|
|
748
|
+
constructor(props: P);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
export declare class ProxyFactory {
|
|
752
|
+
static createStateProxy<T extends object>(options: {
|
|
753
|
+
target: T;
|
|
754
|
+
consumerRef: object;
|
|
755
|
+
consumerTracker: ConsumerTracker_2;
|
|
756
|
+
path?: string;
|
|
757
|
+
}): T;
|
|
758
|
+
static createClassProxy<T extends object>(options: {
|
|
759
|
+
target: T;
|
|
760
|
+
consumerRef: object;
|
|
761
|
+
consumerTracker: ConsumerTracker_2;
|
|
762
|
+
}): T;
|
|
763
|
+
static getProxyState<B extends BlocBase<any>>(options: {
|
|
764
|
+
state: BlocState<B>;
|
|
765
|
+
consumerRef: object;
|
|
766
|
+
consumerTracker: ConsumerTracker_2;
|
|
767
|
+
}): BlocState<B>;
|
|
768
|
+
static getProxyBlocInstance<B extends BlocBase<any>>(options: {
|
|
769
|
+
blocInstance: B;
|
|
770
|
+
consumerRef: object;
|
|
771
|
+
consumerTracker: ConsumerTracker_2;
|
|
772
|
+
}): B;
|
|
773
|
+
static getStats(): {
|
|
774
|
+
totalProxies: number;
|
|
775
|
+
cacheEfficiency: string;
|
|
776
|
+
lifetime: string;
|
|
777
|
+
proxiesPerSecond: string;
|
|
778
|
+
stateProxiesCreated: number;
|
|
779
|
+
classProxiesCreated: number;
|
|
780
|
+
cacheHits: number;
|
|
781
|
+
cacheMisses: number;
|
|
782
|
+
propertyAccesses: number;
|
|
783
|
+
nestedProxiesCreated: number;
|
|
784
|
+
totalProxiesCreated: number;
|
|
785
|
+
createdAt: number;
|
|
786
|
+
};
|
|
787
|
+
static resetStats(): void;
|
|
788
|
+
}
|
|
789
|
+
|
|
603
790
|
/**
|
|
604
791
|
* Sets a custom instance manager (useful for testing or advanced patterns)
|
|
605
792
|
*/
|
|
606
793
|
export declare function setBlacInstanceManager(manager: BlacInstanceManager): void;
|
|
607
794
|
|
|
795
|
+
/**
|
|
796
|
+
* Performs a shallow equality comparison between two values.
|
|
797
|
+
* For objects, it checks if all top-level properties are equal using Object.is.
|
|
798
|
+
* @param a First value to compare
|
|
799
|
+
* @param b Second value to compare
|
|
800
|
+
* @returns true if values are shallowly equal, false otherwise
|
|
801
|
+
*/
|
|
802
|
+
export declare function shallowEqual(a: any, b: any): boolean;
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Result of an atomic state transition operation
|
|
806
|
+
*/
|
|
807
|
+
export declare interface StateTransitionResult {
|
|
808
|
+
success: boolean;
|
|
809
|
+
currentState: BlocLifecycleState;
|
|
810
|
+
previousState: BlocLifecycleState;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
export declare interface TrackedValue {
|
|
814
|
+
value: any;
|
|
815
|
+
lastAccessTime: number;
|
|
816
|
+
}
|
|
817
|
+
|
|
608
818
|
/**
|
|
609
819
|
* Extracts the state type from a BlocBase instance
|
|
610
820
|
* @template B - The BlocBase type to extract the state from
|