@blac/core 2.0.6 → 2.0.8
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 +2 -5
- package/dist/{StateContainerRegistry-CVPTMaHn.cjs → StateContainerRegistry-COxgpYAw.cjs} +6 -34
- package/dist/StateContainerRegistry-COxgpYAw.cjs.map +1 -0
- package/dist/{StateContainerRegistry-Brmferpf.js → StateContainerRegistry-DS_wyKck.js} +7 -29
- package/dist/StateContainerRegistry-DS_wyKck.js.map +1 -0
- package/dist/{config-BmFnPVM0.js → config-BD9MkJ0k.js} +4 -4
- package/dist/{config-BmFnPVM0.js.map → config-BD9MkJ0k.js.map} +1 -1
- package/dist/{config-BInS_9WT.cjs → config-DTuCbHcJ.cjs} +4 -4
- package/dist/{config-BInS_9WT.cjs.map → config-DTuCbHcJ.cjs.map} +1 -1
- package/dist/constants.d.cts +0 -8
- package/dist/constants.d.ts +0 -8
- package/dist/core/Cubit.d.ts +0 -17
- package/dist/core/StateContainer.d.ts +12 -113
- package/dist/core/StateContainerRegistry.d.ts +2 -3
- package/dist/core/symbols.d.ts +2 -0
- package/dist/debug.cjs +2 -2
- package/dist/debug.js +2 -2
- package/dist/decorators/blac.d.ts +3 -10
- package/dist/index.cjs +54 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +53 -145
- package/dist/index.js.map +1 -1
- package/dist/plugin/BlacPlugin.d.ts +0 -2
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.js +1 -1
- package/dist/registry/management.d.ts +1 -1
- package/dist/{resolve-dependencies-Cvq0glJF.js → resolve-dependencies-8xtWXd53.js} +2 -2
- package/dist/{resolve-dependencies-Cvq0glJF.js.map → resolve-dependencies-8xtWXd53.js.map} +1 -1
- package/dist/{resolve-dependencies-B22YjFGk.cjs → resolve-dependencies-DJ2UBTq1.cjs} +2 -2
- package/dist/{resolve-dependencies-B22YjFGk.cjs.map → resolve-dependencies-DJ2UBTq1.cjs.map} +1 -1
- package/dist/{tracked-I_q9buYg.js → tracked-12W-U7tq.js} +3 -3
- package/dist/{tracked-I_q9buYg.js.map → tracked-12W-U7tq.js.map} +1 -1
- package/dist/{tracked-B_MUXIpe.cjs → tracked-DLnq137F.cjs} +3 -3
- package/dist/{tracked-B_MUXIpe.cjs.map → tracked-DLnq137F.cjs.map} +1 -1
- package/dist/tracking.cjs +1 -1
- package/dist/tracking.js +1 -1
- package/dist/types/utilities.d.ts +0 -1
- package/dist/utils/idGenerator.d.ts +0 -16
- package/dist/utils/static-props.d.ts +0 -7
- package/dist/watch-entry.cjs +1 -1
- package/dist/watch-entry.js +1 -1
- package/package.json +2 -1
- package/dist/StateContainerRegistry-Brmferpf.js.map +0 -1
- package/dist/StateContainerRegistry-CVPTMaHn.cjs.map +0 -1
|
@@ -1,38 +1,19 @@
|
|
|
1
1
|
import type { StateContainerConstructor } from '../types/utilities';
|
|
2
|
-
|
|
3
|
-
* Configuration options for initializing a StateContainer instance
|
|
4
|
-
*/
|
|
2
|
+
import { EMIT, UPDATE } from './symbols';
|
|
5
3
|
export interface StateContainerConfig {
|
|
6
|
-
/** Display name for the instance (defaults to class name) */
|
|
7
4
|
name?: string;
|
|
8
|
-
/** Enable debug logging for this instance */
|
|
9
5
|
debug?: boolean;
|
|
10
|
-
/** Custom instance identifier */
|
|
11
6
|
instanceId?: string;
|
|
12
7
|
}
|
|
13
8
|
export type HydrationStatus = 'idle' | 'hydrating' | 'hydrated' | 'error';
|
|
14
|
-
/**
|
|
15
|
-
* Listener function for state changes
|
|
16
|
-
* @internal
|
|
17
|
-
*/
|
|
18
9
|
type StateListener<S> = (state: S) => void;
|
|
19
|
-
/**
|
|
20
|
-
* System events emitted by StateContainer lifecycle
|
|
21
|
-
*/
|
|
22
10
|
export type SystemEvent = 'stateChanged' | 'dispose' | 'hydrationChanged';
|
|
23
|
-
/**
|
|
24
|
-
* Payload types for each system event
|
|
25
|
-
* @template S - State type
|
|
26
|
-
*/
|
|
27
11
|
export interface SystemEventPayloads<S> {
|
|
28
|
-
/** Emitted when state changes via emit() or update() */
|
|
29
12
|
stateChanged: {
|
|
30
13
|
state: S;
|
|
31
14
|
previousState: S;
|
|
32
15
|
};
|
|
33
|
-
/** Emitted when the instance is disposed */
|
|
34
16
|
dispose: void;
|
|
35
|
-
/** Emitted when hydration status changes */
|
|
36
17
|
hydrationChanged: {
|
|
37
18
|
status: HydrationStatus;
|
|
38
19
|
previousStatus: HydrationStatus;
|
|
@@ -40,137 +21,55 @@ export interface SystemEventPayloads<S> {
|
|
|
40
21
|
changedWhileHydrating: boolean;
|
|
41
22
|
};
|
|
42
23
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Handler function for system events
|
|
45
|
-
* @internal
|
|
46
|
-
*/
|
|
47
24
|
type SystemEventHandler<S, E extends SystemEvent> = (payload: SystemEventPayloads<S>[E]) => void;
|
|
48
|
-
/**
|
|
49
|
-
* Abstract base class for all state containers in BlaC.
|
|
50
|
-
* Provides lifecycle management, subscription handling, ref counting,
|
|
51
|
-
* and integration with the global registry.
|
|
52
|
-
*
|
|
53
|
-
* @template S - State type managed by this container
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* ```ts
|
|
57
|
-
* class CounterBloc extends StateContainer<{ count: number }> {
|
|
58
|
-
* constructor() {
|
|
59
|
-
* super({ count: 0 });
|
|
60
|
-
* }
|
|
61
|
-
* increment() {
|
|
62
|
-
* this.emit({ count: this.state.count + 1 });
|
|
63
|
-
* }
|
|
64
|
-
* }
|
|
65
|
-
* ```
|
|
66
|
-
*/
|
|
67
25
|
export declare abstract class StateContainer<S extends object = any> {
|
|
68
26
|
static __excludeFromDevTools: boolean;
|
|
69
27
|
static enableStackTrace: boolean;
|
|
70
28
|
private _state;
|
|
71
|
-
private readonly
|
|
29
|
+
private readonly _listeners;
|
|
72
30
|
private _disposed;
|
|
73
31
|
private _hydrationStatus;
|
|
74
32
|
private _hydrationError?;
|
|
75
33
|
private _changedWhileHydrating;
|
|
76
|
-
private
|
|
77
|
-
private
|
|
78
|
-
private
|
|
79
|
-
private
|
|
80
|
-
private
|
|
81
|
-
private readonly
|
|
82
|
-
|
|
34
|
+
private _hydrationPromise;
|
|
35
|
+
private _resolveHydrationPromise?;
|
|
36
|
+
private _rejectHydrationPromise?;
|
|
37
|
+
private _hydrationPromiseSettled;
|
|
38
|
+
private _config;
|
|
39
|
+
private readonly _systemEventHandlers;
|
|
40
|
+
private _dependencies;
|
|
83
41
|
name: string;
|
|
84
|
-
/** Whether debug logging is enabled */
|
|
85
42
|
debug: boolean;
|
|
86
|
-
/** Unique identifier for this instance */
|
|
87
43
|
instanceId: string;
|
|
88
|
-
/** Timestamp when this instance was created */
|
|
89
44
|
createdAt: number;
|
|
90
|
-
|
|
45
|
+
lastUpdateTimestamp: number;
|
|
91
46
|
get dependencies(): ReadonlyMap<StateContainerConstructor, string>;
|
|
92
47
|
protected depend<T extends StateContainerConstructor>(Type: T, instanceKey?: string): () => InstanceType<T>;
|
|
93
48
|
constructor(initialState: S);
|
|
94
|
-
/**
|
|
95
|
-
* Initialize configuration for this instance.
|
|
96
|
-
* Called by the registry after construction.
|
|
97
|
-
* @param config - Configuration options
|
|
98
|
-
*/
|
|
99
49
|
initConfig(config: StateContainerConfig): void;
|
|
100
|
-
/** Current state value */
|
|
101
50
|
get state(): Readonly<S>;
|
|
102
|
-
/** Whether this instance has been disposed */
|
|
103
51
|
get isDisposed(): boolean;
|
|
104
|
-
/** Current hydration status for this instance */
|
|
105
52
|
get hydrationStatus(): HydrationStatus;
|
|
106
|
-
/** Error from the latest failed hydration, if any */
|
|
107
53
|
get hydrationError(): Error | undefined;
|
|
108
|
-
/** Whether this instance has completed hydration successfully */
|
|
109
54
|
get isHydrated(): boolean;
|
|
110
|
-
/** Whether user state changes happened while hydration was pending */
|
|
111
55
|
get changedWhileHydrating(): boolean;
|
|
112
|
-
/**
|
|
113
|
-
* Subscribe to state changes
|
|
114
|
-
* @param listener - Function called when state changes
|
|
115
|
-
* @returns Unsubscribe function
|
|
116
|
-
*/
|
|
117
56
|
subscribe(listener: StateListener<S>): () => void;
|
|
118
|
-
/**
|
|
119
|
-
* Dispose this instance and clean up resources.
|
|
120
|
-
* Clears all listeners and emits the 'dispose' system event.
|
|
121
|
-
*/
|
|
122
57
|
dispose(): void;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* @param newState - The new state value
|
|
126
|
-
* @protected
|
|
127
|
-
*/
|
|
128
|
-
protected emit(newState: S): void;
|
|
129
|
-
/**
|
|
130
|
-
* Mark this instance as hydrating. Plugins should call this before starting
|
|
131
|
-
* asynchronous rehydration work.
|
|
132
|
-
*/
|
|
58
|
+
protected [EMIT](newState: S): void;
|
|
59
|
+
protected [UPDATE](updater: (current: S) => S): void;
|
|
133
60
|
beginHydration(): void;
|
|
134
|
-
/**
|
|
135
|
-
* Apply hydrated state if no user writes happened since hydration started.
|
|
136
|
-
* Returns false when hydration should be skipped.
|
|
137
|
-
*/
|
|
138
61
|
applyHydratedState(newState: S): boolean;
|
|
139
|
-
/**
|
|
140
|
-
* Mark hydration as completed.
|
|
141
|
-
*/
|
|
142
62
|
finishHydration(): void;
|
|
143
|
-
/**
|
|
144
|
-
* Mark hydration as failed.
|
|
145
|
-
*/
|
|
146
63
|
failHydration(error: Error): void;
|
|
147
|
-
/**
|
|
148
|
-
* Wait until the current hydration cycle finishes.
|
|
149
|
-
*/
|
|
150
64
|
waitForHydration(): Promise<void>;
|
|
151
65
|
private captureStackTrace;
|
|
152
66
|
private formatStackLine;
|
|
153
67
|
private cleanFilePath;
|
|
154
|
-
/** Timestamp of the last state update */
|
|
155
|
-
lastUpdateTimestamp: number;
|
|
156
|
-
/**
|
|
157
|
-
* Update state using a transform function.
|
|
158
|
-
* @param updater - Function that receives current state and returns new state
|
|
159
|
-
* @protected
|
|
160
|
-
*/
|
|
161
|
-
protected update(updater: (current: S) => S): void;
|
|
162
68
|
private applyState;
|
|
163
69
|
private setHydrationStatus;
|
|
164
70
|
private ensureHydrationPromise;
|
|
165
71
|
private resolveHydration;
|
|
166
72
|
private rejectHydration;
|
|
167
|
-
/**
|
|
168
|
-
* Subscribe to system lifecycle events.
|
|
169
|
-
* @param event - The event type to listen for
|
|
170
|
-
* @param handler - Handler function called when event occurs
|
|
171
|
-
* @returns Unsubscribe function
|
|
172
|
-
* @protected
|
|
173
|
-
*/
|
|
174
73
|
protected onSystemEvent: <E extends SystemEvent>(event: E, handler: SystemEventHandler<S, E>) => (() => void);
|
|
175
74
|
private emitSystemEvent;
|
|
176
75
|
}
|
|
@@ -36,7 +36,7 @@ export type LifecycleListener<E extends LifecycleEvent> = E extends 'created' ?
|
|
|
36
36
|
export declare class StateContainerRegistry {
|
|
37
37
|
private readonly instancesByConstructor;
|
|
38
38
|
private readonly types;
|
|
39
|
-
private readonly
|
|
39
|
+
private readonly registeredTypeNames;
|
|
40
40
|
private readonly listeners;
|
|
41
41
|
/**
|
|
42
42
|
* Register a type for lifecycle event tracking
|
|
@@ -46,10 +46,9 @@ export declare class StateContainerRegistry {
|
|
|
46
46
|
/**
|
|
47
47
|
* Register a StateContainer class with configuration
|
|
48
48
|
* @param constructor - The StateContainer class constructor
|
|
49
|
-
* @param isolated - Whether instances should be isolated (component-scoped)
|
|
50
49
|
* @throws Error if type is already registered
|
|
51
50
|
*/
|
|
52
|
-
register<T extends StateContainerConstructor>(constructor: T
|
|
51
|
+
register<T extends StateContainerConstructor>(constructor: T): void;
|
|
53
52
|
private ensureInstancesMap;
|
|
54
53
|
/**
|
|
55
54
|
* Get the instances Map for a specific class (public API for stats/debugging)
|
package/dist/debug.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_StateContainerRegistry = require("./StateContainerRegistry-
|
|
3
|
-
const require_config = require("./config-
|
|
2
|
+
const require_StateContainerRegistry = require("./StateContainerRegistry-COxgpYAw.cjs");
|
|
3
|
+
const require_config = require("./config-DTuCbHcJ.cjs");
|
|
4
4
|
exports.forEach = require_config.forEach;
|
|
5
5
|
exports.getAll = require_config.getAll;
|
|
6
6
|
exports.getRefCount = require_config.getRefCount;
|
package/dist/debug.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as globalRegistry } from "./StateContainerRegistry-
|
|
2
|
-
import { c as getAll, l as getRefCount, n as getStats, o as register, r as setRegistry, s as forEach, t as getRegistry, u as hasInstance } from "./config-
|
|
1
|
+
import { n as globalRegistry } from "./StateContainerRegistry-DS_wyKck.js";
|
|
2
|
+
import { c as getAll, l as getRefCount, n as getStats, o as register, r as setRegistry, s as forEach, t as getRegistry, u as hasInstance } from "./config-BD9MkJ0k.js";
|
|
3
3
|
export { forEach, getAll, getRefCount, getRegistry, getStats, globalRegistry, hasInstance, register, setRegistry };
|
|
@@ -3,12 +3,8 @@
|
|
|
3
3
|
* Only one option can be specified at a time (union type).
|
|
4
4
|
*/
|
|
5
5
|
export type BlacOptions =
|
|
6
|
-
/** Mark bloc as isolated (each component gets its own instance) */
|
|
7
|
-
{
|
|
8
|
-
isolated: true;
|
|
9
|
-
}
|
|
10
6
|
/** Mark bloc to never be auto-disposed when ref count reaches 0 */
|
|
11
|
-
|
|
7
|
+
{
|
|
12
8
|
keepAlive: true;
|
|
13
9
|
}
|
|
14
10
|
/** Exclude bloc from DevTools tracking (prevents infinite loops) */
|
|
@@ -20,9 +16,6 @@ export type BlacOptions =
|
|
|
20
16
|
*
|
|
21
17
|
* @example Decorator syntax (requires experimentalDecorators or TC39 decorators)
|
|
22
18
|
* ```ts
|
|
23
|
-
* @blac({ isolated: true })
|
|
24
|
-
* class FormBloc extends Cubit<FormState> {}
|
|
25
|
-
*
|
|
26
19
|
* @blac({ keepAlive: true })
|
|
27
20
|
* class AuthBloc extends Cubit<AuthState> {}
|
|
28
21
|
*
|
|
@@ -32,8 +25,8 @@ export type BlacOptions =
|
|
|
32
25
|
*
|
|
33
26
|
* @example Function syntax (no decorator support needed)
|
|
34
27
|
* ```ts
|
|
35
|
-
* const
|
|
36
|
-
* class extends Cubit<
|
|
28
|
+
* const AuthBloc = blac({ keepAlive: true })(
|
|
29
|
+
* class extends Cubit<AuthState> {}
|
|
37
30
|
* );
|
|
38
31
|
* ```
|
|
39
32
|
*/
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_StateContainerRegistry = require("./StateContainerRegistry-
|
|
3
|
-
const require_tracked = require("./tracked-
|
|
4
|
-
const require_config = require("./config-
|
|
2
|
+
const require_StateContainerRegistry = require("./StateContainerRegistry-COxgpYAw.cjs");
|
|
3
|
+
const require_tracked = require("./tracked-DLnq137F.cjs");
|
|
4
|
+
const require_config = require("./config-DTuCbHcJ.cjs");
|
|
5
5
|
const require_branded = require("./branded-DndTHjv2.cjs");
|
|
6
6
|
//#region src/utils/idGenerator.ts
|
|
7
7
|
/**
|
|
@@ -22,40 +22,13 @@ function generateSimpleId(prefix, affix) {
|
|
|
22
22
|
if (affix) return `${prefix}:${affix}`;
|
|
23
23
|
return `${prefix}:${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* Format: "isolated-{9-char-random-string}"
|
|
30
|
-
* Example: "isolated-k7x2m9p4q"
|
|
31
|
-
*
|
|
32
|
-
* @returns A unique isolated instance key
|
|
33
|
-
*/
|
|
34
|
-
function generateIsolatedKey() {
|
|
35
|
-
return `isolated-${Math.random().toString(36).slice(2, 11)}`;
|
|
36
|
-
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/core/symbols.ts
|
|
27
|
+
const EMIT = Symbol("blac.emit");
|
|
28
|
+
const UPDATE = Symbol("blac.update");
|
|
37
29
|
//#endregion
|
|
38
30
|
//#region src/core/StateContainer.ts
|
|
39
31
|
const EMPTY_DEPS = /* @__PURE__ */ new Map();
|
|
40
|
-
/**
|
|
41
|
-
* Abstract base class for all state containers in BlaC.
|
|
42
|
-
* Provides lifecycle management, subscription handling, ref counting,
|
|
43
|
-
* and integration with the global registry.
|
|
44
|
-
*
|
|
45
|
-
* @template S - State type managed by this container
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* ```ts
|
|
49
|
-
* class CounterBloc extends StateContainer<{ count: number }> {
|
|
50
|
-
* constructor() {
|
|
51
|
-
* super({ count: 0 });
|
|
52
|
-
* }
|
|
53
|
-
* increment() {
|
|
54
|
-
* this.emit({ count: this.state.count + 1 });
|
|
55
|
-
* }
|
|
56
|
-
* }
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
32
|
var StateContainer = class StateContainer {
|
|
60
33
|
static {
|
|
61
34
|
this.__excludeFromDevTools = false;
|
|
@@ -72,25 +45,25 @@ var StateContainer = class StateContainer {
|
|
|
72
45
|
return () => require_StateContainerRegistry.globalRegistry.ensure(Type, instanceKey);
|
|
73
46
|
}
|
|
74
47
|
constructor(initialState) {
|
|
75
|
-
this.
|
|
48
|
+
this._listeners = /* @__PURE__ */ new Set();
|
|
76
49
|
this._disposed = false;
|
|
77
50
|
this._hydrationStatus = "idle";
|
|
78
51
|
this._changedWhileHydrating = false;
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
81
|
-
this.
|
|
82
|
-
this.
|
|
52
|
+
this._hydrationPromise = null;
|
|
53
|
+
this._hydrationPromiseSettled = false;
|
|
54
|
+
this._config = {};
|
|
55
|
+
this._systemEventHandlers = /* @__PURE__ */ new Map();
|
|
56
|
+
this._dependencies = null;
|
|
83
57
|
this.name = this.constructor.name;
|
|
84
58
|
this.debug = false;
|
|
85
59
|
this.instanceId = generateSimpleId(this.constructor.name, "main");
|
|
86
60
|
this.createdAt = Date.now();
|
|
87
|
-
this._dependencies = null;
|
|
88
61
|
this.lastUpdateTimestamp = Date.now();
|
|
89
62
|
this.onSystemEvent = (event, handler) => {
|
|
90
|
-
let handlers = this.
|
|
63
|
+
let handlers = this._systemEventHandlers.get(event);
|
|
91
64
|
if (!handlers) {
|
|
92
65
|
handlers = /* @__PURE__ */ new Set();
|
|
93
|
-
this.
|
|
66
|
+
this._systemEventHandlers.set(event, handlers);
|
|
94
67
|
}
|
|
95
68
|
handlers.add(handler);
|
|
96
69
|
return () => {
|
|
@@ -99,103 +72,71 @@ var StateContainer = class StateContainer {
|
|
|
99
72
|
};
|
|
100
73
|
this._state = initialState;
|
|
101
74
|
}
|
|
102
|
-
/**
|
|
103
|
-
* Initialize configuration for this instance.
|
|
104
|
-
* Called by the registry after construction.
|
|
105
|
-
* @param config - Configuration options
|
|
106
|
-
*/
|
|
107
75
|
initConfig(config) {
|
|
108
|
-
this.
|
|
109
|
-
this.name = this.
|
|
110
|
-
this.debug = this.
|
|
111
|
-
this.instanceId = generateSimpleId(this.constructor.name, this.
|
|
76
|
+
this._config = { ...config };
|
|
77
|
+
this.name = this._config.name || this.constructor.name;
|
|
78
|
+
this.debug = this._config.debug ?? false;
|
|
79
|
+
this.instanceId = generateSimpleId(this.constructor.name, this._config.instanceId);
|
|
112
80
|
require_StateContainerRegistry.globalRegistry.emit("created", this);
|
|
113
81
|
}
|
|
114
|
-
/** Current state value */
|
|
115
82
|
get state() {
|
|
116
83
|
return this._state;
|
|
117
84
|
}
|
|
118
|
-
/** Whether this instance has been disposed */
|
|
119
85
|
get isDisposed() {
|
|
120
86
|
return this._disposed;
|
|
121
87
|
}
|
|
122
|
-
/** Current hydration status for this instance */
|
|
123
88
|
get hydrationStatus() {
|
|
124
89
|
return this._hydrationStatus;
|
|
125
90
|
}
|
|
126
|
-
/** Error from the latest failed hydration, if any */
|
|
127
91
|
get hydrationError() {
|
|
128
92
|
return this._hydrationError;
|
|
129
93
|
}
|
|
130
|
-
/** Whether this instance has completed hydration successfully */
|
|
131
94
|
get isHydrated() {
|
|
132
95
|
return this._hydrationStatus === "hydrated";
|
|
133
96
|
}
|
|
134
|
-
/** Whether user state changes happened while hydration was pending */
|
|
135
97
|
get changedWhileHydrating() {
|
|
136
98
|
return this._changedWhileHydrating;
|
|
137
99
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Subscribe to state changes
|
|
140
|
-
* @param listener - Function called when state changes
|
|
141
|
-
* @returns Unsubscribe function
|
|
142
|
-
*/
|
|
143
100
|
subscribe(listener) {
|
|
144
101
|
if (this._disposed) throw new Error(`Cannot subscribe to disposed container ${this.name}`);
|
|
145
|
-
this.
|
|
146
|
-
return () => this.
|
|
102
|
+
this._listeners.add(listener);
|
|
103
|
+
return () => this._listeners.delete(listener);
|
|
147
104
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Dispose this instance and clean up resources.
|
|
150
|
-
* Clears all listeners and emits the 'dispose' system event.
|
|
151
|
-
*/
|
|
152
105
|
dispose() {
|
|
153
106
|
if (this._disposed) return;
|
|
154
107
|
if (this.debug) console.log(`[${this.name}] Disposing...`);
|
|
155
108
|
this._disposed = true;
|
|
156
109
|
if (this._hydrationStatus === "hydrating") this.failHydration(/* @__PURE__ */ new Error(`Hydration cancelled because ${this.name} was disposed`));
|
|
157
110
|
this.emitSystemEvent("dispose", void 0);
|
|
158
|
-
this.
|
|
159
|
-
this.
|
|
111
|
+
this._listeners.clear();
|
|
112
|
+
this._systemEventHandlers.clear();
|
|
160
113
|
require_StateContainerRegistry.globalRegistry.emit("disposed", this);
|
|
161
114
|
if (this.debug) console.log(`[${this.name}] Disposed successfully`);
|
|
162
115
|
}
|
|
163
|
-
|
|
164
|
-
* Emit a new state value and notify all listeners.
|
|
165
|
-
* @param newState - The new state value
|
|
166
|
-
* @protected
|
|
167
|
-
*/
|
|
168
|
-
emit(newState) {
|
|
116
|
+
[EMIT](newState) {
|
|
169
117
|
this.applyState(newState, "default");
|
|
170
118
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
119
|
+
[UPDATE](updater) {
|
|
120
|
+
if (this._disposed) throw new Error(`Cannot update state from disposed container ${this.name}`);
|
|
121
|
+
this[EMIT](updater(this._state));
|
|
122
|
+
}
|
|
175
123
|
beginHydration() {
|
|
176
124
|
if (this._disposed) throw new Error(`Cannot begin hydration for disposed container ${this.name}`);
|
|
177
125
|
this._changedWhileHydrating = false;
|
|
178
126
|
this._hydrationError = void 0;
|
|
179
|
-
this.
|
|
180
|
-
this.
|
|
181
|
-
this.
|
|
182
|
-
this.
|
|
127
|
+
this._hydrationPromise = null;
|
|
128
|
+
this._resolveHydrationPromise = void 0;
|
|
129
|
+
this._rejectHydrationPromise = void 0;
|
|
130
|
+
this._hydrationPromiseSettled = false;
|
|
183
131
|
this.ensureHydrationPromise();
|
|
184
132
|
this.setHydrationStatus("hydrating");
|
|
185
133
|
}
|
|
186
|
-
/**
|
|
187
|
-
* Apply hydrated state if no user writes happened since hydration started.
|
|
188
|
-
* Returns false when hydration should be skipped.
|
|
189
|
-
*/
|
|
190
134
|
applyHydratedState(newState) {
|
|
191
135
|
if (this._disposed) return false;
|
|
192
136
|
if (this._hydrationStatus !== "hydrating" || this._changedWhileHydrating) return false;
|
|
193
137
|
this.applyState(newState, "hydration");
|
|
194
138
|
return true;
|
|
195
139
|
}
|
|
196
|
-
/**
|
|
197
|
-
* Mark hydration as completed.
|
|
198
|
-
*/
|
|
199
140
|
finishHydration() {
|
|
200
141
|
if (this._hydrationStatus !== "hydrating") {
|
|
201
142
|
if (this._hydrationStatus === "hydrated") return;
|
|
@@ -204,18 +145,12 @@ var StateContainer = class StateContainer {
|
|
|
204
145
|
this.setHydrationStatus("hydrated");
|
|
205
146
|
this.resolveHydration();
|
|
206
147
|
}
|
|
207
|
-
/**
|
|
208
|
-
* Mark hydration as failed.
|
|
209
|
-
*/
|
|
210
148
|
failHydration(error) {
|
|
211
149
|
const err = error instanceof Error ? error : /* @__PURE__ */ new Error(`Hydration failed: ${error}`);
|
|
212
150
|
this._hydrationError = err;
|
|
213
151
|
this.setHydrationStatus("error", err);
|
|
214
152
|
this.rejectHydration(err);
|
|
215
153
|
}
|
|
216
|
-
/**
|
|
217
|
-
* Wait until the current hydration cycle finishes.
|
|
218
|
-
*/
|
|
219
154
|
waitForHydration() {
|
|
220
155
|
if (this._hydrationStatus === "idle" || this._hydrationStatus === "hydrated") return Promise.resolve();
|
|
221
156
|
if (this._hydrationStatus === "error") return Promise.reject(this._hydrationError ?? /* @__PURE__ */ new Error(`Hydration failed for container ${this.name}`));
|
|
@@ -228,7 +163,7 @@ var StateContainer = class StateContainer {
|
|
|
228
163
|
const formattedLines = [];
|
|
229
164
|
for (const line of relevantLines) {
|
|
230
165
|
if (!line.trim()) continue;
|
|
231
|
-
if (line.includes("StateContainer.emit") || line.includes("StateContainer.update") || line.includes("StateContainer.captureStackTrace") || line.includes("Cubit.patch")) continue;
|
|
166
|
+
if (line.includes("StateContainer.emit") || line.includes("StateContainer.update") || line.includes("StateContainer.captureStackTrace") || line.includes("[blac.emit]") || line.includes("[blac.update]") || line.includes("Cubit.patch") || line.includes("/blac-core/dist/") || line.includes("@blac/core/")) continue;
|
|
232
167
|
if (line.includes("node_modules") || line.includes("react-dom") || line.includes("react_jsx") || line.includes(".vite/deps") || line.includes("executeDispatch") || line.includes("runWithFiber") || line.includes("invokeGuarded") || line.includes("callCallback") || line.includes("processDispatchQueue") || line.includes("dispatchEvent") || line.includes("batchedUpdates")) continue;
|
|
233
168
|
const formatted = this.formatStackLine(line);
|
|
234
169
|
if (formatted) formattedLines.push(formatted);
|
|
@@ -259,15 +194,6 @@ var StateContainer = class StateContainer {
|
|
|
259
194
|
if (segments.length > 3) path = segments.slice(-3).join("/");
|
|
260
195
|
return path;
|
|
261
196
|
}
|
|
262
|
-
/**
|
|
263
|
-
* Update state using a transform function.
|
|
264
|
-
* @param updater - Function that receives current state and returns new state
|
|
265
|
-
* @protected
|
|
266
|
-
*/
|
|
267
|
-
update(updater) {
|
|
268
|
-
if (this._disposed) throw new Error(`Cannot update state from disposed container ${this.name}`);
|
|
269
|
-
this.emit(updater(this._state));
|
|
270
|
-
}
|
|
271
197
|
applyState(newState, source) {
|
|
272
198
|
if (this._disposed) throw new Error(`Cannot emit state from disposed container ${this.name}`);
|
|
273
199
|
if (this._state === newState) return;
|
|
@@ -278,7 +204,7 @@ var StateContainer = class StateContainer {
|
|
|
278
204
|
state: newState,
|
|
279
205
|
previousState
|
|
280
206
|
});
|
|
281
|
-
const listeners = Array.from(this.
|
|
207
|
+
const listeners = Array.from(this._listeners);
|
|
282
208
|
for (const listener of listeners) try {
|
|
283
209
|
listener(newState);
|
|
284
210
|
} catch (error) {
|
|
@@ -300,33 +226,33 @@ var StateContainer = class StateContainer {
|
|
|
300
226
|
});
|
|
301
227
|
}
|
|
302
228
|
ensureHydrationPromise() {
|
|
303
|
-
if (!this.
|
|
304
|
-
this.
|
|
305
|
-
this.
|
|
306
|
-
this.
|
|
307
|
-
if (this.
|
|
308
|
-
this.
|
|
229
|
+
if (!this._hydrationPromise || this._hydrationPromiseSettled) {
|
|
230
|
+
this._hydrationPromiseSettled = false;
|
|
231
|
+
this._hydrationPromise = new Promise((resolve, reject) => {
|
|
232
|
+
this._resolveHydrationPromise = () => {
|
|
233
|
+
if (this._hydrationPromiseSettled) return;
|
|
234
|
+
this._hydrationPromiseSettled = true;
|
|
309
235
|
resolve();
|
|
310
236
|
};
|
|
311
|
-
this.
|
|
312
|
-
if (this.
|
|
313
|
-
this.
|
|
237
|
+
this._rejectHydrationPromise = (error) => {
|
|
238
|
+
if (this._hydrationPromiseSettled) return;
|
|
239
|
+
this._hydrationPromiseSettled = true;
|
|
314
240
|
reject(error);
|
|
315
241
|
};
|
|
316
242
|
});
|
|
317
|
-
this.
|
|
243
|
+
this._hydrationPromise.catch(() => {});
|
|
318
244
|
}
|
|
319
|
-
return this.
|
|
245
|
+
return this._hydrationPromise;
|
|
320
246
|
}
|
|
321
247
|
resolveHydration() {
|
|
322
|
-
this.
|
|
248
|
+
this._resolveHydrationPromise?.();
|
|
323
249
|
}
|
|
324
250
|
rejectHydration(error) {
|
|
325
251
|
this.ensureHydrationPromise();
|
|
326
|
-
this.
|
|
252
|
+
this._rejectHydrationPromise?.(error);
|
|
327
253
|
}
|
|
328
254
|
emitSystemEvent(event, payload) {
|
|
329
|
-
const handlers = this.
|
|
255
|
+
const handlers = this._systemEventHandlers.get(event);
|
|
330
256
|
if (!handlers) return;
|
|
331
257
|
for (const handler of handlers) try {
|
|
332
258
|
handler(payload);
|
|
@@ -337,12 +263,6 @@ var StateContainer = class StateContainer {
|
|
|
337
263
|
};
|
|
338
264
|
//#endregion
|
|
339
265
|
//#region src/core/Cubit.ts
|
|
340
|
-
/**
|
|
341
|
-
* Simple state container with direct state emission.
|
|
342
|
-
* Extends StateContainer with public methods for emitting and updating state.
|
|
343
|
-
*
|
|
344
|
-
* @template S - State type
|
|
345
|
-
*/
|
|
346
266
|
var Cubit = class extends StateContainer {
|
|
347
267
|
constructor(initialState) {
|
|
348
268
|
super(initialState);
|
|
@@ -360,19 +280,11 @@ var Cubit = class extends StateContainer {
|
|
|
360
280
|
}));
|
|
361
281
|
});
|
|
362
282
|
}
|
|
363
|
-
/**
|
|
364
|
-
* Replace state with a new value and notify all listeners
|
|
365
|
-
* @param newState - The new state value
|
|
366
|
-
*/
|
|
367
283
|
emit(newState) {
|
|
368
|
-
|
|
284
|
+
this[EMIT](newState);
|
|
369
285
|
}
|
|
370
|
-
/**
|
|
371
|
-
* Transform current state using an updater function and emit the new state
|
|
372
|
-
* @param updater - Function that receives current state and returns new state
|
|
373
|
-
*/
|
|
374
286
|
update(updater) {
|
|
375
|
-
|
|
287
|
+
this[UPDATE](updater);
|
|
376
288
|
}
|
|
377
289
|
};
|
|
378
290
|
//#endregion
|
|
@@ -403,9 +315,6 @@ function release(BlocClass, instanceKey, forceDispose = false) {
|
|
|
403
315
|
*
|
|
404
316
|
* @example Decorator syntax (requires experimentalDecorators or TC39 decorators)
|
|
405
317
|
* ```ts
|
|
406
|
-
* @blac({ isolated: true })
|
|
407
|
-
* class FormBloc extends Cubit<FormState> {}
|
|
408
|
-
*
|
|
409
318
|
* @blac({ keepAlive: true })
|
|
410
319
|
* class AuthBloc extends Cubit<AuthState> {}
|
|
411
320
|
*
|
|
@@ -415,14 +324,13 @@ function release(BlocClass, instanceKey, forceDispose = false) {
|
|
|
415
324
|
*
|
|
416
325
|
* @example Function syntax (no decorator support needed)
|
|
417
326
|
* ```ts
|
|
418
|
-
* const
|
|
419
|
-
* class extends Cubit<
|
|
327
|
+
* const AuthBloc = blac({ keepAlive: true })(
|
|
328
|
+
* class extends Cubit<AuthState> {}
|
|
420
329
|
* );
|
|
421
330
|
* ```
|
|
422
331
|
*/
|
|
423
332
|
function blac(options) {
|
|
424
333
|
return function(target, _context) {
|
|
425
|
-
if ("isolated" in options && options.isolated) target[require_StateContainerRegistry.BLAC_STATIC_PROPS.ISOLATED] = true;
|
|
426
334
|
if ("keepAlive" in options && options.keepAlive) target[require_StateContainerRegistry.BLAC_STATIC_PROPS.KEEP_ALIVE] = true;
|
|
427
335
|
if ("excludeFromDevTools" in options && options.excludeFromDevTools) target[require_StateContainerRegistry.BLAC_STATIC_PROPS.EXCLUDE_FROM_DEVTOOLS] = true;
|
|
428
336
|
return target;
|
|
@@ -430,9 +338,11 @@ function blac(options) {
|
|
|
430
338
|
}
|
|
431
339
|
//#endregion
|
|
432
340
|
exports.Cubit = Cubit;
|
|
341
|
+
exports.EMIT = EMIT;
|
|
433
342
|
exports.PluginManager = require_StateContainerRegistry.PluginManager;
|
|
434
343
|
exports.StateContainer = StateContainer;
|
|
435
344
|
exports.TrackedContext = require_tracked.TrackedContext;
|
|
345
|
+
exports.UPDATE = UPDATE;
|
|
436
346
|
exports.acquire = acquire;
|
|
437
347
|
exports.blac = blac;
|
|
438
348
|
exports.borrow = borrow;
|
|
@@ -442,7 +352,6 @@ exports.clearAll = require_config.clearAll;
|
|
|
442
352
|
exports.createTrackedContext = require_tracked.createTrackedContext;
|
|
443
353
|
exports.ensure = require_tracked.ensure;
|
|
444
354
|
exports.forEach = require_config.forEach;
|
|
445
|
-
exports.generateIsolatedKey = generateIsolatedKey;
|
|
446
355
|
exports.getAll = require_config.getAll;
|
|
447
356
|
exports.getPluginManager = require_StateContainerRegistry.getPluginManager;
|
|
448
357
|
exports.getRefCount = require_config.getRefCount;
|
|
@@ -452,7 +361,6 @@ exports.globalRegistry = require_StateContainerRegistry.globalRegistry;
|
|
|
452
361
|
exports.hasInstance = require_config.hasInstance;
|
|
453
362
|
exports.instance = require_tracked.instance;
|
|
454
363
|
exports.instanceId = require_branded.instanceId;
|
|
455
|
-
exports.isIsolatedClass = require_StateContainerRegistry.isIsolatedClass;
|
|
456
364
|
exports.register = require_config.register;
|
|
457
365
|
exports.release = release;
|
|
458
366
|
exports.setRegistry = require_config.setRegistry;
|