@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.cjs ADDED
@@ -0,0 +1,346 @@
1
+ const require_StateContainerRegistry = require('./StateContainerRegistry.cjs');
2
+ const require_tracking_proxy = require('./tracking-proxy.cjs');
3
+ const require_management = require('./management.cjs');
4
+ const require_watch = require('./watch.cjs');
5
+ const require_dependency_manager = require('./dependency-manager.cjs');
6
+ require('./tracking.cjs');
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
+ require_StateContainerRegistry.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
+ require_StateContainerRegistry.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
+ require_StateContainerRegistry.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 require_StateContainerRegistry.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 require_StateContainerRegistry.globalRegistry.borrow(BlocClass, instanceKey);
264
+ }
265
+ function borrowSafe(BlocClass, instanceKey) {
266
+ return require_StateContainerRegistry.globalRegistry.borrowSafe(BlocClass, instanceKey);
267
+ }
268
+
269
+ //#endregion
270
+ //#region src/registry/release.ts
271
+ function release(BlocClass, instanceKey, forceDispose = false) {
272
+ require_StateContainerRegistry.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[require_tracking_proxy.BLAC_STATIC_PROPS.ISOLATED] = true;
302
+ if ("keepAlive" in options && options.keepAlive) target[require_tracking_proxy.BLAC_STATIC_PROPS.KEEP_ALIVE] = true;
303
+ if ("excludeFromDevTools" in options && options.excludeFromDevTools) target[require_tracking_proxy.BLAC_STATIC_PROPS.EXCLUDE_FROM_DEVTOOLS] = true;
304
+ return target;
305
+ };
306
+ }
307
+
308
+ //#endregion
309
+ exports.Cubit = Cubit;
310
+ exports.DependencyManager = require_dependency_manager.DependencyManager;
311
+ exports.PluginManager = require_StateContainerRegistry.PluginManager;
312
+ exports.StateContainer = StateContainer;
313
+ exports.acquire = acquire;
314
+ exports.blac = blac;
315
+ exports.borrow = borrow;
316
+ exports.borrowSafe = borrowSafe;
317
+ exports.capturePaths = require_tracking_proxy.capturePaths;
318
+ exports.clear = require_management.clear;
319
+ exports.clearActiveTracker = require_tracking_proxy.clearActiveTracker;
320
+ exports.clearAll = require_management.clearAll;
321
+ exports.clearExternalDependencies = require_tracking_proxy.clearExternalDependencies;
322
+ exports.commitTrackedGetters = require_tracking_proxy.commitTrackedGetters;
323
+ exports.createBlocProxy = require_tracking_proxy.createBlocProxy;
324
+ exports.createDependencyProxy = require_tracking_proxy.createDependencyProxy;
325
+ exports.createDependencyState = require_tracking_proxy.createDependencyState;
326
+ exports.createGetterState = require_tracking_proxy.createGetterState;
327
+ exports.ensure = require_watch.ensure;
328
+ exports.forEach = require_management.forEach;
329
+ exports.generateIsolatedKey = generateIsolatedKey;
330
+ exports.getAll = require_management.getAll;
331
+ exports.getPluginManager = require_StateContainerRegistry.getPluginManager;
332
+ exports.getRefCount = require_management.getRefCount;
333
+ exports.globalRegistry = require_StateContainerRegistry.globalRegistry;
334
+ exports.hasDependencyChanges = require_tracking_proxy.hasDependencyChanges;
335
+ exports.hasGetterChanges = require_tracking_proxy.hasGetterChanges;
336
+ exports.hasInstance = require_management.hasInstance;
337
+ exports.hasTrackedData = require_tracking_proxy.hasTrackedData;
338
+ exports.instance = require_watch.instance;
339
+ exports.invalidateRenderCache = require_tracking_proxy.invalidateRenderCache;
340
+ exports.isIsolatedClass = require_StateContainerRegistry.isIsolatedClass;
341
+ exports.release = release;
342
+ exports.setActiveTracker = require_tracking_proxy.setActiveTracker;
343
+ exports.shallowEqual = require_tracking_proxy.shallowEqual;
344
+ exports.startDependency = require_tracking_proxy.startDependency;
345
+ exports.watch = require_watch.watch;
346
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["globalRegistry","globalRegistry","BLAC_STATIC_PROPS"],"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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"}