@blac/core 2.0.0 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +137 -177
  2. package/dist/StateContainerRegistry.cjs.map +1 -0
  3. package/dist/StateContainerRegistry.js.map +1 -0
  4. package/dist/debug.cjs +27 -0
  5. package/dist/debug.cjs.map +1 -0
  6. package/dist/debug.js +19 -0
  7. package/dist/debug.js.map +1 -0
  8. package/dist/dependency-manager.cjs.map +1 -0
  9. package/dist/dependency-manager.js.map +1 -0
  10. package/dist/index.cjs +346 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.cts +794 -0
  13. package/dist/index.d.ts +675 -386
  14. package/dist/index.js +310 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/management.cjs.map +1 -0
  17. package/dist/management.js.map +1 -0
  18. package/dist/plugins.cjs +4 -0
  19. package/dist/plugins.js +3 -0
  20. package/dist/tracking/dependency-manager.d.ts +37 -0
  21. package/dist/tracking/index.d.ts +12 -0
  22. package/dist/tracking/path-utils.d.ts +52 -0
  23. package/dist/tracking/tracked.d.ts +70 -0
  24. package/dist/tracking/tracking-proxy.d.ts +197 -0
  25. package/dist/tracking-proxy.cjs.map +1 -0
  26. package/dist/tracking-proxy.js.map +1 -0
  27. package/dist/tracking.cjs +19 -0
  28. package/dist/tracking.d.cts +9 -0
  29. package/dist/tracking.d.ts +9 -0
  30. package/dist/tracking.js +4 -0
  31. package/dist/types.cjs +14 -0
  32. package/dist/types.cjs.map +1 -0
  33. package/dist/types.d.cts +8 -0
  34. package/dist/types.d.ts +8 -0
  35. package/dist/types.js +13 -0
  36. package/dist/types.js.map +1 -0
  37. package/dist/watch-entry.cjs +111 -0
  38. package/dist/watch-entry.cjs.map +1 -0
  39. package/dist/watch-entry.js +107 -0
  40. package/dist/watch-entry.js.map +1 -0
  41. package/dist/watch.cjs.map +1 -0
  42. package/dist/watch.js.map +1 -0
  43. package/package.json +122 -19
  44. package/dist/index.cjs.js +0 -2
  45. package/dist/index.cjs.js.map +0 -1
  46. package/dist/index.es.js +0 -670
  47. package/dist/index.es.js.map +0 -1
  48. package/src/Blac.ts +0 -483
  49. package/src/BlacEvent.ts +0 -5
  50. package/src/BlacObservable.ts +0 -88
  51. package/src/BlacObserver.ts +0 -129
  52. package/src/BlacPlugin.ts +0 -13
  53. package/src/Bloc.ts +0 -109
  54. package/src/BlocBase.ts +0 -248
  55. package/src/Cubit.ts +0 -69
  56. package/src/addons/BlacAddon.ts +0 -17
  57. package/src/addons/Persist.ts +0 -105
  58. package/src/addons/index.ts +0 -1
  59. package/src/index.ts +0 -8
  60. package/src/types.ts +0 -63
package/dist/index.js ADDED
@@ -0,0 +1,310 @@
1
+ import { i as PluginManager, n as globalRegistry, r as isIsolatedClass, t as getPluginManager } from "./StateContainerRegistry.js";
2
+ import { _ as setActiveTracker, a as createBlocProxy, c as createGetterState, g as invalidateRenderCache, h as hasTrackedData, i as commitTrackedGetters, m as hasGetterChanges, n as clearActiveTracker, o as createDependencyProxy, p as hasDependencyChanges, r as clearExternalDependencies, s as createDependencyState, t as capturePaths, v as startDependency, w as BLAC_STATIC_PROPS, x as shallowEqual } from "./tracking-proxy.js";
3
+ import { a as getAll, i as forEach, n as clearAll, o as getRefCount, s as hasInstance, t as clear } from "./management.js";
4
+ import { n as watch, r as ensure, t as instance } from "./watch.js";
5
+ import { t as DependencyManager } from "./dependency-manager.js";
6
+ import "./tracking.js";
7
+
8
+ //#region src/utils/idGenerator.ts
9
+ /**
10
+ * Generate simple ID with timestamp and random (no counter tracking)
11
+ *
12
+ * Format: `${prefix}:${timestamp}_${random}`
13
+ *
14
+ * @param prefix - Prefix for the ID
15
+ * @returns Branded ID string
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const id = generateSimpleId('CounterBloc');
20
+ * // Returns: "CounterBloc:1698765432100_a3k9d7f2q"
21
+ * ```
22
+ */
23
+ function generateSimpleId(prefix, affix) {
24
+ if (affix) return `${prefix}:${affix}`;
25
+ return `${prefix}:${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
26
+ }
27
+ /**
28
+ * Generate a unique isolated instance key
29
+ * Uses base36 encoding for compact, URL-safe identifiers
30
+ *
31
+ * Format: "isolated-{9-char-random-string}"
32
+ * Example: "isolated-k7x2m9p4q"
33
+ *
34
+ * @returns A unique isolated instance key
35
+ */
36
+ function generateIsolatedKey() {
37
+ return `isolated-${Math.random().toString(36).slice(2, 11)}`;
38
+ }
39
+
40
+ //#endregion
41
+ //#region src/core/StateContainer.ts
42
+ /**
43
+ * Abstract base class for all state containers in BlaC.
44
+ * Provides lifecycle management, subscription handling, ref counting,
45
+ * and integration with the global registry.
46
+ *
47
+ * @template S - State type managed by this container
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * class CounterBloc extends StateContainer<{ count: number }> {
52
+ * constructor() {
53
+ * super({ count: 0 });
54
+ * }
55
+ * increment() {
56
+ * this.emit({ count: this.state.count + 1 });
57
+ * }
58
+ * }
59
+ * ```
60
+ */
61
+ var StateContainer = class StateContainer {
62
+ static {
63
+ this.__excludeFromDevTools = false;
64
+ }
65
+ static {
66
+ this.enableStackTrace = true;
67
+ }
68
+ constructor(initialState) {
69
+ this.listeners = /* @__PURE__ */ new Set();
70
+ this._disposed = false;
71
+ this.config = {};
72
+ this.systemEventHandlers = /* @__PURE__ */ new Map();
73
+ this.name = this.constructor.name;
74
+ this.debug = false;
75
+ this.instanceId = generateSimpleId(this.constructor.name, "main");
76
+ this.createdAt = Date.now();
77
+ this.lastUpdateTimestamp = Date.now();
78
+ this.onSystemEvent = (event, handler) => {
79
+ let handlers = this.systemEventHandlers.get(event);
80
+ if (!handlers) {
81
+ handlers = /* @__PURE__ */ new Set();
82
+ this.systemEventHandlers.set(event, handlers);
83
+ }
84
+ handlers.add(handler);
85
+ return () => {
86
+ handlers?.delete(handler);
87
+ };
88
+ };
89
+ this._state = initialState;
90
+ }
91
+ /**
92
+ * Initialize configuration for this instance.
93
+ * Called by the registry after construction.
94
+ * @param config - Configuration options
95
+ */
96
+ initConfig(config) {
97
+ this.config = { ...config };
98
+ this.name = this.config.name || this.constructor.name;
99
+ this.debug = this.config.debug ?? false;
100
+ this.instanceId = generateSimpleId(this.constructor.name, this.config.instanceId);
101
+ globalRegistry.emit("created", this);
102
+ }
103
+ /** Current state value */
104
+ get state() {
105
+ return this._state;
106
+ }
107
+ /** Whether this instance has been disposed */
108
+ get isDisposed() {
109
+ return this._disposed;
110
+ }
111
+ /**
112
+ * Subscribe to state changes
113
+ * @param listener - Function called when state changes
114
+ * @returns Unsubscribe function
115
+ */
116
+ subscribe(listener) {
117
+ if (this._disposed) throw new Error(`Cannot subscribe to disposed container ${this.name}`);
118
+ this.listeners.add(listener);
119
+ return () => this.listeners.delete(listener);
120
+ }
121
+ /**
122
+ * Dispose this instance and clean up resources.
123
+ * Clears all listeners and emits the 'dispose' system event.
124
+ */
125
+ dispose() {
126
+ if (this._disposed) return;
127
+ if (this.debug) console.log(`[${this.name}] Disposing...`);
128
+ this._disposed = true;
129
+ this.emitSystemEvent("dispose", void 0);
130
+ this.listeners.clear();
131
+ this.systemEventHandlers.clear();
132
+ globalRegistry.emit("disposed", this);
133
+ if (this.debug) console.log(`[${this.name}] Disposed successfully`);
134
+ }
135
+ /**
136
+ * Emit a new state value and notify all listeners.
137
+ * @param newState - The new state value
138
+ * @protected
139
+ */
140
+ emit(newState) {
141
+ if (this._disposed) throw new Error(`Cannot emit state from disposed container ${this.name}`);
142
+ if (this._state === newState) return;
143
+ const previousState = this._state;
144
+ this._state = newState;
145
+ this.emitSystemEvent("stateChanged", {
146
+ state: newState,
147
+ previousState
148
+ });
149
+ for (const listener of this.listeners) try {
150
+ listener(newState);
151
+ } catch (error) {
152
+ console.error(`[${this.name}] Error in listener:`, error);
153
+ }
154
+ const stackTrace = this.captureStackTrace();
155
+ globalRegistry.emit("stateChanged", this, previousState, newState, stackTrace);
156
+ this.lastUpdateTimestamp = Date.now();
157
+ }
158
+ captureStackTrace() {
159
+ if (!StateContainer.enableStackTrace || typeof process !== "undefined" && process.env?.NODE_ENV === "production") return "";
160
+ try {
161
+ const relevantLines = ((/* @__PURE__ */ new Error()).stack || "").split("\n").slice(1);
162
+ const formattedLines = [];
163
+ for (const line of relevantLines) {
164
+ if (!line.trim()) continue;
165
+ if (line.includes("StateContainer.emit") || line.includes("StateContainer.update") || line.includes("StateContainer.captureStackTrace") || line.includes("Cubit.patch")) continue;
166
+ 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;
167
+ const formatted = this.formatStackLine(line);
168
+ if (formatted) formattedLines.push(formatted);
169
+ }
170
+ return formattedLines.join("\n");
171
+ } catch {
172
+ return "";
173
+ }
174
+ }
175
+ formatStackLine(line) {
176
+ const match = line.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
177
+ if (!match) {
178
+ const simpleMatch = line.match(/at\s+(.+?):(\d+):(\d+)/);
179
+ if (simpleMatch) {
180
+ const [, url, lineNum, col] = simpleMatch;
181
+ return ` at ${this.cleanFilePath(url)}:${lineNum}:${col}`;
182
+ }
183
+ return null;
184
+ }
185
+ const [, functionName, url, lineNum, col] = match;
186
+ return ` at ${functionName} (${this.cleanFilePath(url)}:${lineNum}:${col})`;
187
+ }
188
+ cleanFilePath(url) {
189
+ let path = url.replace(/http:\/\/localhost:\d+\/@fs/, "").replace(/http:\/\/localhost:\d+\//, "").replace(/\?t=\d+/, "").replace(/\?v=[a-f0-9]+/, "");
190
+ const projectMatch = path.match(/\/Projects\/blac\/(.+)/);
191
+ if (projectMatch) path = projectMatch[1];
192
+ const segments = path.split("/");
193
+ if (segments.length > 3) path = segments.slice(-3).join("/");
194
+ return path;
195
+ }
196
+ /**
197
+ * Update state using a transform function.
198
+ * @param updater - Function that receives current state and returns new state
199
+ * @protected
200
+ */
201
+ update(updater) {
202
+ if (this._disposed) throw new Error(`Cannot update state from disposed container ${this.name}`);
203
+ this.emit(updater(this._state));
204
+ }
205
+ emitSystemEvent(event, payload) {
206
+ const handlers = this.systemEventHandlers.get(event);
207
+ if (!handlers) return;
208
+ for (const handler of handlers) try {
209
+ handler(payload);
210
+ } catch (error) {
211
+ console.error(`[${this.name}] Error in system event handler:`, error);
212
+ }
213
+ }
214
+ };
215
+
216
+ //#endregion
217
+ //#region src/core/Cubit.ts
218
+ /**
219
+ * Simple state container with direct state emission.
220
+ * Extends StateContainer with public methods for emitting and updating state.
221
+ *
222
+ * @template S - State type
223
+ */
224
+ var Cubit = class extends StateContainer {
225
+ constructor(initialState) {
226
+ super(initialState);
227
+ this.patch = ((partial) => {
228
+ if (typeof this.state !== "object" || this.state === null) throw new Error("patch() is only available for object state types");
229
+ this.update((current) => ({
230
+ ...current,
231
+ ...partial
232
+ }));
233
+ });
234
+ }
235
+ /**
236
+ * Replace state with a new value and notify all listeners
237
+ * @param newState - The new state value
238
+ */
239
+ emit(newState) {
240
+ super["emit"](newState);
241
+ }
242
+ /**
243
+ * Transform current state using an updater function and emit the new state
244
+ * @param updater - Function that receives current state and returns new state
245
+ */
246
+ update(updater) {
247
+ super["update"](updater);
248
+ }
249
+ };
250
+
251
+ //#endregion
252
+ //#region src/registry/acquire.ts
253
+ function acquire(BlocClass, instanceKey) {
254
+ return globalRegistry.acquire(BlocClass, instanceKey, {
255
+ canCreate: true,
256
+ countRef: true
257
+ });
258
+ }
259
+
260
+ //#endregion
261
+ //#region src/registry/borrow.ts
262
+ function borrow(BlocClass, instanceKey) {
263
+ return globalRegistry.borrow(BlocClass, instanceKey);
264
+ }
265
+ function borrowSafe(BlocClass, instanceKey) {
266
+ return globalRegistry.borrowSafe(BlocClass, instanceKey);
267
+ }
268
+
269
+ //#endregion
270
+ //#region src/registry/release.ts
271
+ function release(BlocClass, instanceKey, forceDispose = false) {
272
+ globalRegistry.release(BlocClass, instanceKey, forceDispose);
273
+ }
274
+
275
+ //#endregion
276
+ //#region src/decorators/blac.ts
277
+ /**
278
+ * Decorator to configure StateContainer classes.
279
+ *
280
+ * @example Decorator syntax (requires experimentalDecorators or TC39 decorators)
281
+ * ```ts
282
+ * @blac({ isolated: true })
283
+ * class FormBloc extends Cubit<FormState> {}
284
+ *
285
+ * @blac({ keepAlive: true })
286
+ * class AuthBloc extends Cubit<AuthState> {}
287
+ *
288
+ * @blac({ excludeFromDevTools: true })
289
+ * class InternalBloc extends Cubit<InternalState> {}
290
+ * ```
291
+ *
292
+ * @example Function syntax (no decorator support needed)
293
+ * ```ts
294
+ * const FormBloc = blac({ isolated: true })(
295
+ * class extends Cubit<FormState> {}
296
+ * );
297
+ * ```
298
+ */
299
+ function blac(options) {
300
+ return function(target, _context) {
301
+ if ("isolated" in options && options.isolated) target[BLAC_STATIC_PROPS.ISOLATED] = true;
302
+ if ("keepAlive" in options && options.keepAlive) target[BLAC_STATIC_PROPS.KEEP_ALIVE] = true;
303
+ if ("excludeFromDevTools" in options && options.excludeFromDevTools) target[BLAC_STATIC_PROPS.EXCLUDE_FROM_DEVTOOLS] = true;
304
+ return target;
305
+ };
306
+ }
307
+
308
+ //#endregion
309
+ export { Cubit, DependencyManager, PluginManager, StateContainer, acquire, blac, borrow, borrowSafe, capturePaths, clear, clearActiveTracker, clearAll, clearExternalDependencies, commitTrackedGetters, createBlocProxy, createDependencyProxy, createDependencyState, createGetterState, ensure, forEach, generateIsolatedKey, getAll, getPluginManager, getRefCount, globalRegistry, hasDependencyChanges, hasGetterChanges, hasInstance, hasTrackedData, instance, invalidateRenderCache, isIsolatedClass, release, setActiveTracker, shallowEqual, startDependency, watch };
310
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/utils/idGenerator.ts","../src/core/StateContainer.ts","../src/core/Cubit.ts","../src/registry/acquire.ts","../src/registry/borrow.ts","../src/registry/release.ts","../src/decorators/blac.ts"],"sourcesContent":["/**\n * Centralized ID Generation\n *\n * Provides consistent, collision-resistant ID generation for all BlaC subsystems.\n * Uses timestamp + counter + random suffix for uniqueness.\n */\n\n// Global counter map for ID generation\nconst globalCounters = new Map<string, number>();\n\n/**\n * Creates an ID generator with isolated counter state\n *\n * @param prefix - Prefix for generated IDs\n * @returns Object with next(), nextSimple(), and reset() methods\n *\n * @example\n * ```ts\n * const generator = createIdGenerator('sub');\n * const id1 = generator.next(); // \"sub:1698765432100_1_a3k9d7f2q\"\n * const id2 = generator.next(); // \"sub:1698765432101_2_b4n8e9g3r\"\n * ```\n */\nexport function createIdGenerator(prefix: string) {\n let counter = 0;\n return {\n next: () =>\n `${prefix}:${Date.now()}_${++counter}_${Math.random().toString(36).substring(2, 11)}`,\n nextSimple: () => `${prefix}:${++counter}`,\n reset: () => {\n counter = 0;\n },\n };\n}\n\n/**\n * Generate ID with timestamp, counter, and random suffix (tree-shakeable)\n *\n * Format: `${prefix}:${timestamp}_${counter}_${random}`\n *\n * @param prefix - Prefix for the ID (e.g., 'sub', 'consumer', 'stage')\n * @returns Branded ID string\n *\n * @example\n * const id = generateId('sub');\n * // Returns: \"sub:1698765432100_1_a3k9d7f2q\"\n */\nexport function generateId(prefix: string): string {\n const counter = (globalCounters.get(prefix) ?? 0) + 1;\n globalCounters.set(prefix, counter);\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 11);\n return `${prefix}:${timestamp}_${counter}_${random}`;\n}\n\n/**\n * Generate simple ID with timestamp and random (no counter tracking)\n *\n * Format: `${prefix}:${timestamp}_${random}`\n *\n * @param prefix - Prefix for the ID\n * @returns Branded ID string\n *\n * @example\n * ```ts\n * const id = generateSimpleId('CounterBloc');\n * // Returns: \"CounterBloc:1698765432100_a3k9d7f2q\"\n * ```\n */\nexport function generateSimpleId(prefix: string, affix?: string): string {\n if (affix) {\n return `${prefix}:${affix}`;\n }\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 11);\n return `${prefix}:${timestamp}_${random}`;\n}\n\n/**\n * Reset all counters for testing purposes\n * @internal\n */\nexport function __resetIdCounters(): void {\n globalCounters.clear();\n}\n\n/**\n * Generate a unique isolated instance key\n * Uses base36 encoding for compact, URL-safe identifiers\n *\n * Format: \"isolated-{9-char-random-string}\"\n * Example: \"isolated-k7x2m9p4q\"\n *\n * @returns A unique isolated instance key\n */\nexport function generateIsolatedKey(): string {\n const randomPart = Math.random().toString(36).slice(2, 11);\n return `isolated-${randomPart}`;\n}\n\n/**\n * Check if a key is an isolated instance key\n * @param key - The instance key to check\n * @returns true if the key is an isolated instance key\n */\nexport function isIsolatedKey(key: string): boolean {\n return key.startsWith('isolated-');\n}\n","import { generateSimpleId } from '../utils/idGenerator';\nimport { globalRegistry } from './StateContainerRegistry';\n\n/**\n * Configuration options for initializing a StateContainer instance\n */\nexport interface StateContainerConfig {\n /** Display name for the instance (defaults to class name) */\n name?: string;\n /** Enable debug logging for this instance */\n debug?: boolean;\n /** Custom instance identifier */\n instanceId?: string;\n}\n\n/**\n * Listener function for state changes\n * @internal\n */\ntype StateListener<S> = (state: S) => void;\n\n/**\n * System events emitted by StateContainer lifecycle\n */\nexport type SystemEvent = 'stateChanged' | 'dispose';\n\n/**\n * Payload types for each system event\n * @template S - State type\n */\nexport interface SystemEventPayloads<S> {\n /** Emitted when state changes via emit() or update() */\n stateChanged: { state: S; previousState: S };\n /** Emitted when the instance is disposed */\n dispose: void;\n}\n\n/**\n * Handler function for system events\n * @internal\n */\ntype SystemEventHandler<S, E extends SystemEvent> = (\n payload: SystemEventPayloads<S>[E],\n) => void;\n\n/**\n * Abstract base class for all state containers in BlaC.\n * Provides lifecycle management, subscription handling, ref counting,\n * and integration with the global registry.\n *\n * @template S - State type managed by this container\n *\n * @example\n * ```ts\n * class CounterBloc extends StateContainer<{ count: number }> {\n * constructor() {\n * super({ count: 0 });\n * }\n * increment() {\n * this.emit({ count: this.state.count + 1 });\n * }\n * }\n * ```\n */\nexport abstract class StateContainer<S extends object = any> {\n static __excludeFromDevTools = false;\n static enableStackTrace = true;\n\n private _state: S;\n private readonly listeners = new Set<StateListener<S>>();\n private _disposed = false;\n private config: StateContainerConfig = {};\n private readonly systemEventHandlers = new Map<\n SystemEvent,\n Set<SystemEventHandler<S, any>>\n >();\n\n /** Display name for this instance */\n name: string = this.constructor.name;\n /** Whether debug logging is enabled */\n debug: boolean = false;\n /** Unique identifier for this instance */\n instanceId: string = generateSimpleId(this.constructor.name, 'main');\n /** Timestamp when this instance was created */\n createdAt: number = Date.now();\n\n constructor(initialState: S) {\n this._state = initialState;\n }\n\n /**\n * Initialize configuration for this instance.\n * Called by the registry after construction.\n * @param config - Configuration options\n */\n initConfig(config: StateContainerConfig): void {\n this.config = { ...config };\n this.name = this.config.name || this.constructor.name;\n this.debug = this.config.debug ?? false;\n this.instanceId = generateSimpleId(\n this.constructor.name,\n this.config.instanceId,\n );\n\n globalRegistry.emit('created', this);\n }\n\n /** Current state value */\n get state(): Readonly<S> {\n return this._state;\n }\n\n /** Whether this instance has been disposed */\n get isDisposed(): boolean {\n return this._disposed;\n }\n\n /**\n * Subscribe to state changes\n * @param listener - Function called when state changes\n * @returns Unsubscribe function\n */\n subscribe(listener: StateListener<S>): () => void {\n if (this._disposed) {\n throw new Error(`Cannot subscribe to disposed container ${this.name}`);\n }\n\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Dispose this instance and clean up resources.\n * Clears all listeners and emits the 'dispose' system event.\n */\n dispose(): void {\n if (this._disposed) return;\n\n if (this.debug) {\n console.log(`[${this.name}] Disposing...`);\n }\n\n this._disposed = true;\n\n this.emitSystemEvent('dispose', undefined as void);\n\n this.listeners.clear();\n this.systemEventHandlers.clear();\n\n globalRegistry.emit('disposed', this);\n\n if (this.debug) {\n console.log(`[${this.name}] Disposed successfully`);\n }\n }\n\n /**\n * Emit a new state value and notify all listeners.\n * @param newState - The new state value\n * @protected\n */\n protected emit(newState: S): void {\n if (this._disposed) {\n throw new Error(`Cannot emit state from disposed container ${this.name}`);\n }\n\n if (this._state === newState) return;\n\n const previousState = this._state;\n this._state = newState;\n\n this.emitSystemEvent('stateChanged', {\n state: newState,\n previousState,\n });\n\n for (const listener of this.listeners) {\n try {\n listener(newState);\n } catch (error) {\n console.error(`[${this.name}] Error in listener:`, error);\n }\n }\n\n const stackTrace = this.captureStackTrace();\n\n globalRegistry.emit(\n 'stateChanged',\n this,\n previousState,\n newState,\n stackTrace,\n );\n this.lastUpdateTimestamp = Date.now();\n }\n\n private captureStackTrace(): string {\n if (\n !StateContainer.enableStackTrace ||\n (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production')\n ) {\n return '';\n }\n\n try {\n const error = new Error();\n const stack = error.stack || '';\n const lines = stack.split('\\n');\n const relevantLines = lines.slice(1);\n const formattedLines: string[] = [];\n\n for (const line of relevantLines) {\n if (!line.trim()) continue;\n\n if (\n line.includes('StateContainer.emit') ||\n line.includes('StateContainer.update') ||\n line.includes('StateContainer.captureStackTrace') ||\n line.includes('Cubit.patch')\n ) {\n continue;\n }\n\n if (\n line.includes('node_modules') ||\n line.includes('react-dom') ||\n line.includes('react_jsx') ||\n line.includes('.vite/deps') ||\n line.includes('executeDispatch') ||\n line.includes('runWithFiber') ||\n line.includes('invokeGuarded') ||\n line.includes('callCallback') ||\n line.includes('processDispatchQueue') ||\n line.includes('dispatchEvent') ||\n line.includes('batchedUpdates')\n ) {\n continue;\n }\n\n const formatted = this.formatStackLine(line);\n if (formatted) {\n formattedLines.push(formatted);\n }\n }\n\n return formattedLines.join('\\n');\n } catch {\n return '';\n }\n }\n\n private formatStackLine(line: string): string | null {\n const match = line.match(/at\\s+(.+?)\\s+\\((.+?):(\\d+):(\\d+)\\)/);\n if (!match) {\n const simpleMatch = line.match(/at\\s+(.+?):(\\d+):(\\d+)/);\n if (simpleMatch) {\n const [, url, lineNum, col] = simpleMatch;\n const cleanPath = this.cleanFilePath(url);\n return ` at ${cleanPath}:${lineNum}:${col}`;\n }\n return null;\n }\n\n const [, functionName, url, lineNum, col] = match;\n const cleanPath = this.cleanFilePath(url);\n\n return ` at ${functionName} (${cleanPath}:${lineNum}:${col})`;\n }\n\n private cleanFilePath(url: string): string {\n let path = url\n .replace(/http:\\/\\/localhost:\\d+\\/@fs/, '')\n .replace(/http:\\/\\/localhost:\\d+\\//, '')\n .replace(/\\?t=\\d+/, '')\n .replace(/\\?v=[a-f0-9]+/, '');\n\n const projectMatch = path.match(/\\/Projects\\/blac\\/(.+)/);\n if (projectMatch) {\n path = projectMatch[1];\n }\n\n const segments = path.split('/');\n if (segments.length > 3) {\n path = segments.slice(-3).join('/');\n }\n\n return path;\n }\n\n /** Timestamp of the last state update */\n lastUpdateTimestamp: number = Date.now();\n\n /**\n * Update state using a transform function.\n * @param updater - Function that receives current state and returns new state\n * @protected\n */\n protected update(updater: (current: S) => S): void {\n if (this._disposed) {\n throw new Error(\n `Cannot update state from disposed container ${this.name}`,\n );\n }\n this.emit(updater(this._state));\n }\n\n /**\n * Subscribe to system lifecycle events.\n * @param event - The event type to listen for\n * @param handler - Handler function called when event occurs\n * @returns Unsubscribe function\n * @protected\n */\n protected onSystemEvent = <E extends SystemEvent>(\n event: E,\n handler: SystemEventHandler<S, E>,\n ): (() => void) => {\n let handlers = this.systemEventHandlers.get(event);\n if (!handlers) {\n handlers = new Set();\n this.systemEventHandlers.set(event, handlers);\n }\n handlers.add(handler as SystemEventHandler<S, any>);\n\n return () => {\n handlers?.delete(handler as SystemEventHandler<S, any>);\n };\n };\n\n private emitSystemEvent<E extends SystemEvent>(\n event: E,\n payload: SystemEventPayloads<S>[E],\n ): void {\n const handlers = this.systemEventHandlers.get(event);\n if (!handlers) return;\n\n for (const handler of handlers) {\n try {\n handler(payload);\n } catch (error) {\n console.error(`[${this.name}] Error in system event handler:`, error);\n }\n }\n }\n}\n","import { StateContainer } from './StateContainer';\n\n/**\n * Simple state container with direct state emission.\n * Extends StateContainer with public methods for emitting and updating state.\n *\n * @template S - State type\n */\nexport abstract class Cubit<S extends object = any> extends StateContainer<S> {\n constructor(initialState: S) {\n super(initialState);\n }\n\n /**\n * Replace state with a new value and notify all listeners\n * @param newState - The new state value\n */\n public emit(newState: S): void {\n super['emit'](newState);\n }\n\n /**\n * Transform current state using an updater function and emit the new state\n * @param updater - Function that receives current state and returns new state\n */\n public update(updater: (current: S) => S): void {\n super['update'](updater);\n }\n\n /**\n * Merge partial state changes into current state (only for object states)\n */\n public patch = ((partial: S extends object ? Partial<S> : never): void => {\n if (typeof this.state !== 'object' || this.state === null) {\n throw new Error('patch() is only available for object state types');\n }\n this.update((current) => ({ ...current, ...partial }) as S);\n }) as S extends object ? (partial: Partial<S>) => void : never;\n}\n","import { globalRegistry } from '../core/StateContainerRegistry';\nimport type { StateContainerConstructor } from '../types/utilities';\n\nexport function acquire<T extends StateContainerConstructor>(\n BlocClass: T,\n instanceKey?: string,\n): InstanceType<T> {\n return globalRegistry.acquire(BlocClass, instanceKey, {\n canCreate: true,\n countRef: true,\n });\n}\n","import { globalRegistry } from '../core/StateContainerRegistry';\nimport type { StateContainerConstructor } from '../types/utilities';\n\nexport function borrow<T extends StateContainerConstructor>(\n BlocClass: T,\n instanceKey?: string,\n): InstanceType<T> {\n return globalRegistry.borrow(BlocClass, instanceKey);\n}\n\nexport function borrowSafe<T extends StateContainerConstructor>(\n BlocClass: T,\n instanceKey?: string,\n):\n | { error: Error; instance: null }\n | { error: null; instance: InstanceType<T> } {\n return globalRegistry.borrowSafe(BlocClass, instanceKey);\n}\n","import { globalRegistry } from '../core/StateContainerRegistry';\nimport type { StateContainerConstructor } from '../types/utilities';\n\nexport function release<T extends StateContainerConstructor>(\n BlocClass: T,\n instanceKey?: string,\n forceDispose = false,\n): void {\n globalRegistry.release(BlocClass, instanceKey, forceDispose);\n}\n","import { BLAC_STATIC_PROPS } from '../constants';\n\n/**\n * Configuration options for the @blac decorator.\n * Only one option can be specified at a time (union type).\n */\nexport type BlacOptions =\n /** Mark bloc as isolated (each component gets its own instance) */\n | { isolated: true }\n /** Mark bloc to never be auto-disposed when ref count reaches 0 */\n | { keepAlive: true }\n /** Exclude bloc from DevTools tracking (prevents infinite loops) */\n | { excludeFromDevTools: true };\n\n/**\n * Decorator to configure StateContainer classes.\n *\n * @example Decorator syntax (requires experimentalDecorators or TC39 decorators)\n * ```ts\n * @blac({ isolated: true })\n * class FormBloc extends Cubit<FormState> {}\n *\n * @blac({ keepAlive: true })\n * class AuthBloc extends Cubit<AuthState> {}\n *\n * @blac({ excludeFromDevTools: true })\n * class InternalBloc extends Cubit<InternalState> {}\n * ```\n *\n * @example Function syntax (no decorator support needed)\n * ```ts\n * const FormBloc = blac({ isolated: true })(\n * class extends Cubit<FormState> {}\n * );\n * ```\n */\nexport function blac(options: BlacOptions) {\n return function <T extends new (...args: any[]) => any>(\n target: T,\n _context?: ClassDecoratorContext,\n ): T {\n if ('isolated' in options && options.isolated) {\n (target as any)[BLAC_STATIC_PROPS.ISOLATED] = true;\n }\n if ('keepAlive' in options && options.keepAlive) {\n (target as any)[BLAC_STATIC_PROPS.KEEP_ALIVE] = true;\n }\n if ('excludeFromDevTools' in options && options.excludeFromDevTools) {\n (target as any)[BLAC_STATIC_PROPS.EXCLUDE_FROM_DEVTOOLS] = true;\n }\n return target;\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"management.cjs","names":["globalRegistry"],"sources":["../src/registry/queries.ts","../src/registry/management.ts"],"sourcesContent":["import { globalRegistry } from '../core/StateContainerRegistry';\nimport type {\n StateContainerConstructor,\n InstanceReadonlyState,\n} from '../types/utilities';\n\nexport function hasInstance<T extends StateContainerConstructor>(\n BlocClass: T,\n instanceKey?: string,\n): boolean {\n return globalRegistry.hasInstance(BlocClass, instanceKey);\n}\n\nexport function getRefCount<T extends StateContainerConstructor>(\n BlocClass: T,\n instanceKey?: string,\n): number {\n return globalRegistry.getRefCount(BlocClass, instanceKey);\n}\n\nexport function getAll<T extends StateContainerConstructor>(\n BlocClass: T,\n): InstanceReadonlyState<T>[] {\n return globalRegistry.getAll(BlocClass);\n}\n\nexport function forEach<T extends StateContainerConstructor>(\n BlocClass: T,\n callback: (instance: InstanceReadonlyState<T>) => void,\n): void {\n globalRegistry.forEach(BlocClass, callback);\n}\n","import { globalRegistry } from '../core/StateContainerRegistry';\nimport type { StateContainerConstructor } from '../types/utilities';\n\nexport function clear<T extends StateContainerConstructor>(BlocClass: T): void {\n globalRegistry.clear(BlocClass);\n}\n\nexport function clearAll(): void {\n globalRegistry.clearAll();\n}\n\nexport function register<T extends StateContainerConstructor>(\n BlocClass: T,\n isolated = false,\n): void {\n globalRegistry.register(BlocClass, isolated);\n}\n"],"mappings":";;;AAMA,SAAgB,YACd,WACA,aACS;AACT,QAAOA,8CAAe,YAAY,WAAW,YAAY;;AAG3D,SAAgB,YACd,WACA,aACQ;AACR,QAAOA,8CAAe,YAAY,WAAW,YAAY;;AAG3D,SAAgB,OACd,WAC4B;AAC5B,QAAOA,8CAAe,OAAO,UAAU;;AAGzC,SAAgB,QACd,WACA,UACM;AACN,+CAAe,QAAQ,WAAW,SAAS;;;;;AC3B7C,SAAgB,MAA2C,WAAoB;AAC7E,+CAAe,MAAM,UAAU;;AAGjC,SAAgB,WAAiB;AAC/B,+CAAe,UAAU;;AAG3B,SAAgB,SACd,WACA,WAAW,OACL;AACN,+CAAe,SAAS,WAAW,SAAS"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"management.js","names":[],"sources":["../src/registry/queries.ts","../src/registry/management.ts"],"sourcesContent":["import { globalRegistry } from '../core/StateContainerRegistry';\nimport type {\n StateContainerConstructor,\n InstanceReadonlyState,\n} from '../types/utilities';\n\nexport function hasInstance<T extends StateContainerConstructor>(\n BlocClass: T,\n instanceKey?: string,\n): boolean {\n return globalRegistry.hasInstance(BlocClass, instanceKey);\n}\n\nexport function getRefCount<T extends StateContainerConstructor>(\n BlocClass: T,\n instanceKey?: string,\n): number {\n return globalRegistry.getRefCount(BlocClass, instanceKey);\n}\n\nexport function getAll<T extends StateContainerConstructor>(\n BlocClass: T,\n): InstanceReadonlyState<T>[] {\n return globalRegistry.getAll(BlocClass);\n}\n\nexport function forEach<T extends StateContainerConstructor>(\n BlocClass: T,\n callback: (instance: InstanceReadonlyState<T>) => void,\n): void {\n globalRegistry.forEach(BlocClass, callback);\n}\n","import { globalRegistry } from '../core/StateContainerRegistry';\nimport type { StateContainerConstructor } from '../types/utilities';\n\nexport function clear<T extends StateContainerConstructor>(BlocClass: T): void {\n globalRegistry.clear(BlocClass);\n}\n\nexport function clearAll(): void {\n globalRegistry.clearAll();\n}\n\nexport function register<T extends StateContainerConstructor>(\n BlocClass: T,\n isolated = false,\n): void {\n globalRegistry.register(BlocClass, isolated);\n}\n"],"mappings":";;;AAMA,SAAgB,YACd,WACA,aACS;AACT,QAAO,eAAe,YAAY,WAAW,YAAY;;AAG3D,SAAgB,YACd,WACA,aACQ;AACR,QAAO,eAAe,YAAY,WAAW,YAAY;;AAG3D,SAAgB,OACd,WAC4B;AAC5B,QAAO,eAAe,OAAO,UAAU;;AAGzC,SAAgB,QACd,WACA,UACM;AACN,gBAAe,QAAQ,WAAW,SAAS;;;;;AC3B7C,SAAgB,MAA2C,WAAoB;AAC7E,gBAAe,MAAM,UAAU;;AAGjC,SAAgB,WAAiB;AAC/B,gBAAe,UAAU;;AAG3B,SAAgB,SACd,WACA,WAAW,OACL;AACN,gBAAe,SAAS,WAAW,SAAS"}
@@ -0,0 +1,4 @@
1
+ const require_StateContainerRegistry = require('./StateContainerRegistry.cjs');
2
+
3
+ exports.PluginManager = require_StateContainerRegistry.PluginManager;
4
+ exports.getPluginManager = require_StateContainerRegistry.getPluginManager;
@@ -0,0 +1,3 @@
1
+ import { i as PluginManager, t as getPluginManager } from "./StateContainerRegistry.js";
2
+
3
+ export { PluginManager, getPluginManager };
@@ -0,0 +1,37 @@
1
+ import type { StateContainerInstance } from '../types/utilities';
2
+ /**
3
+ * Manages subscriptions to state container dependencies.
4
+ * Provides efficient sync mechanism to add/remove subscriptions
5
+ * as dependencies change between callback invocations.
6
+ */
7
+ export declare class DependencyManager {
8
+ private subscriptions;
9
+ private currentDeps;
10
+ /**
11
+ * Sync subscriptions with a new set of dependencies.
12
+ * Adds subscriptions for new deps, removes subscriptions for stale deps.
13
+ *
14
+ * @param newDeps - The new set of dependencies to subscribe to
15
+ * @param onChange - Callback to invoke when any dependency changes
16
+ * @param exclude - Optional instance to exclude from subscriptions (e.g., primary bloc)
17
+ * @returns true if the dependency set changed, false if unchanged
18
+ */
19
+ sync(newDeps: Set<StateContainerInstance>, onChange: () => void, exclude?: StateContainerInstance): boolean;
20
+ /**
21
+ * Add a single dependency subscription.
22
+ */
23
+ add(dep: StateContainerInstance, onChange: () => void): void;
24
+ /**
25
+ * Check if a dependency is currently subscribed.
26
+ */
27
+ has(dep: StateContainerInstance): boolean;
28
+ /**
29
+ * Get the current set of dependencies.
30
+ */
31
+ getDependencies(): Set<StateContainerInstance>;
32
+ /**
33
+ * Clean up all active subscriptions.
34
+ */
35
+ cleanup(): void;
36
+ private areSetsEqual;
37
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Dependency Tracking
3
+ *
4
+ * Framework-agnostic dependency tracking utilities for automatic reactivity.
5
+ * These utilities are used by framework adapters (React, Vue, Angular, etc.)
6
+ * to track property accesses and detect changes.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ export { type DependencyState, type PathInfo, createDependencyState, startDependency, createDependencyProxy, capturePaths, hasDependencyChanges, hasTrackedData, type GetterState, createGetterState, createBlocProxy, hasGetterChanges, setActiveTracker, clearActiveTracker, commitTrackedGetters, invalidateRenderCache, clearExternalDependencies, } from './tracking-proxy';
11
+ export { shallowEqual } from './path-utils';
12
+ export { DependencyManager } from './dependency-manager';
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Path utilities for dependency tracking
3
+ *
4
+ * Provides utilities for parsing property paths and extracting values
5
+ * from nested objects using path strings.
6
+ *
7
+ * @internal
8
+ */
9
+ /**
10
+ * Parse a property path string into an array of segments
11
+ *
12
+ * @internal
13
+ *
14
+ * Handles both dot notation (a.b.c) and bracket notation (a[0].b)
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * parsePath('user.name') // ['user', 'name']
19
+ * parsePath('items[0].name') // ['items', '0', 'name']
20
+ * parsePath('data.users[2].address.city') // ['data', 'users', '2', 'address', 'city']
21
+ * ```
22
+ */
23
+ export declare function parsePath(path: string): string[];
24
+ /**
25
+ * Get a value from an object using a path of segments
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const obj = { user: { name: 'Alice', age: 30 } }
30
+ * getValueAtPath(obj, ['user', 'name']) // 'Alice'
31
+ * getValueAtPath(obj, ['user', 'age']) // 30
32
+ * getValueAtPath(obj, ['user', 'missing']) // undefined
33
+ * ```
34
+ *
35
+ * @internal
36
+ */
37
+ export declare function getValueAtPath(obj: any, segments: string[]): any;
38
+ /**
39
+ * Shallow equality comparison for arrays
40
+ *
41
+ * Compares two arrays element-by-element using Object.is
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * shallowEqual([1, 2, 3], [1, 2, 3]) // true
46
+ * shallowEqual([1, 2, 3], [1, 2, 4]) // false
47
+ * shallowEqual([1, 2], [1, 2, 3]) // false
48
+ * ```
49
+ *
50
+ * @internal
51
+ */
52
+ export declare function shallowEqual(arr1: unknown[], arr2: unknown[]): boolean;
@@ -0,0 +1,70 @@
1
+ import type { StateContainerInstance } from '../types/utilities';
2
+ import { DependencyManager } from './dependency-manager';
3
+ /**
4
+ * Result of running a tracked callback.
5
+ */
6
+ export interface TrackedResult<T> {
7
+ result: T;
8
+ dependencies: Set<StateContainerInstance>;
9
+ }
10
+ /**
11
+ * Options for the tracked() function.
12
+ */
13
+ export interface TrackedOptions {
14
+ exclude?: StateContainerInstance;
15
+ }
16
+ /**
17
+ * Run a callback while tracking all bloc dependencies accessed.
18
+ * Returns both the result and the set of discovered dependencies.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const { result, dependencies } = tracked(() => {
23
+ * const user = ensure(UserBloc);
24
+ * return user.fullName; // getter that may access other blocs
25
+ * });
26
+ * // dependencies contains UserBloc + any blocs accessed in fullName getter
27
+ * ```
28
+ */
29
+ export declare function tracked<T>(callback: () => T, options?: TrackedOptions): TrackedResult<T>;
30
+ /**
31
+ * Context for running tracked callbacks with bloc proxies.
32
+ * Provides methods to create proxies and check for changes.
33
+ */
34
+ export declare class TrackedContext {
35
+ private tracker;
36
+ private proxiedBlocs;
37
+ private primaryBlocs;
38
+ constructor();
39
+ /**
40
+ * Get a tracking proxy for a bloc instance.
41
+ * The proxy will track state and getter accesses.
42
+ */
43
+ proxy<T extends StateContainerInstance>(bloc: T): T;
44
+ /**
45
+ * Start tracking for a new callback execution.
46
+ */
47
+ start(): void;
48
+ /**
49
+ * Stop tracking and get discovered dependencies.
50
+ * Excludes primary blocs (those explicitly proxied via proxy()).
51
+ */
52
+ stop(): Set<StateContainerInstance>;
53
+ /**
54
+ * Check if any tracked state or getters have changed.
55
+ */
56
+ changed(): boolean;
57
+ /**
58
+ * Get all primary blocs (those explicitly proxied).
59
+ */
60
+ getPrimaryBlocs(): Set<StateContainerInstance>;
61
+ /**
62
+ * Reset the context for reuse.
63
+ */
64
+ reset(): void;
65
+ }
66
+ /**
67
+ * Create a new tracked context for manual control over tracking.
68
+ */
69
+ export declare function createTrackedContext(): TrackedContext;
70
+ export { DependencyManager };