@blac/core 2.0.0-rc.1 → 2.0.0-rc.2

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 (121) hide show
  1. package/dist/index.cjs +1361 -38
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.cts +868 -0
  4. package/dist/index.d.ts +867 -16
  5. package/dist/index.js +1315 -37
  6. package/dist/index.js.map +1 -1
  7. package/package.json +17 -11
  8. package/dist/.tsbuildinfo +0 -1
  9. package/dist/Blac.d.ts +0 -246
  10. package/dist/Blac.d.ts.map +0 -1
  11. package/dist/Blac.js +0 -624
  12. package/dist/Blac.js.map +0 -1
  13. package/dist/Bloc.d.ts +0 -41
  14. package/dist/Bloc.d.ts.map +0 -1
  15. package/dist/Bloc.js +0 -140
  16. package/dist/Bloc.js.map +0 -1
  17. package/dist/BlocBase.d.ts +0 -110
  18. package/dist/BlocBase.d.ts.map +0 -1
  19. package/dist/BlocBase.js +0 -287
  20. package/dist/BlocBase.js.map +0 -1
  21. package/dist/Cubit.d.ts +0 -25
  22. package/dist/Cubit.d.ts.map +0 -1
  23. package/dist/Cubit.js +0 -64
  24. package/dist/Cubit.js.map +0 -1
  25. package/dist/adapter/BlacAdapter.d.ts +0 -67
  26. package/dist/adapter/BlacAdapter.d.ts.map +0 -1
  27. package/dist/adapter/BlacAdapter.js +0 -263
  28. package/dist/adapter/BlacAdapter.js.map +0 -1
  29. package/dist/adapter/ProxyFactory.d.ts +0 -50
  30. package/dist/adapter/ProxyFactory.d.ts.map +0 -1
  31. package/dist/adapter/ProxyFactory.js +0 -150
  32. package/dist/adapter/ProxyFactory.js.map +0 -1
  33. package/dist/adapter/index.d.ts +0 -3
  34. package/dist/adapter/index.d.ts.map +0 -1
  35. package/dist/adapter/index.js +0 -19
  36. package/dist/adapter/index.js.map +0 -1
  37. package/dist/errors/BlacError.d.ts +0 -38
  38. package/dist/errors/BlacError.d.ts.map +0 -1
  39. package/dist/errors/BlacError.js +0 -55
  40. package/dist/errors/BlacError.js.map +0 -1
  41. package/dist/errors/ErrorManager.d.ts +0 -39
  42. package/dist/errors/ErrorManager.d.ts.map +0 -1
  43. package/dist/errors/ErrorManager.js +0 -91
  44. package/dist/errors/ErrorManager.js.map +0 -1
  45. package/dist/errors/handleError.d.ts +0 -24
  46. package/dist/errors/handleError.d.ts.map +0 -1
  47. package/dist/errors/handleError.js +0 -62
  48. package/dist/errors/handleError.js.map +0 -1
  49. package/dist/errors/index.d.ts +0 -5
  50. package/dist/errors/index.d.ts.map +0 -1
  51. package/dist/errors/index.js +0 -13
  52. package/dist/errors/index.js.map +0 -1
  53. package/dist/events.d.ts +0 -11
  54. package/dist/events.d.ts.map +0 -1
  55. package/dist/events.js +0 -17
  56. package/dist/events.js.map +0 -1
  57. package/dist/index.d.ts.map +0 -1
  58. package/dist/lifecycle/BlocLifecycle.d.ts +0 -51
  59. package/dist/lifecycle/BlocLifecycle.d.ts.map +0 -1
  60. package/dist/lifecycle/BlocLifecycle.js +0 -123
  61. package/dist/lifecycle/BlocLifecycle.js.map +0 -1
  62. package/dist/lifecycle/index.d.ts +0 -2
  63. package/dist/lifecycle/index.d.ts.map +0 -1
  64. package/dist/lifecycle/index.js +0 -18
  65. package/dist/lifecycle/index.js.map +0 -1
  66. package/dist/plugins/BlocPluginRegistry.d.ts +0 -58
  67. package/dist/plugins/BlocPluginRegistry.d.ts.map +0 -1
  68. package/dist/plugins/BlocPluginRegistry.js +0 -201
  69. package/dist/plugins/BlocPluginRegistry.js.map +0 -1
  70. package/dist/plugins/SystemPluginRegistry.d.ts +0 -79
  71. package/dist/plugins/SystemPluginRegistry.d.ts.map +0 -1
  72. package/dist/plugins/SystemPluginRegistry.js +0 -184
  73. package/dist/plugins/SystemPluginRegistry.js.map +0 -1
  74. package/dist/plugins/index.d.ts +0 -4
  75. package/dist/plugins/index.d.ts.map +0 -1
  76. package/dist/plugins/index.js +0 -26
  77. package/dist/plugins/index.js.map +0 -1
  78. package/dist/plugins/types.d.ts +0 -103
  79. package/dist/plugins/types.d.ts.map +0 -1
  80. package/dist/plugins/types.js +0 -3
  81. package/dist/plugins/types.js.map +0 -1
  82. package/dist/subscription/SubscriptionManager.d.ts +0 -67
  83. package/dist/subscription/SubscriptionManager.d.ts.map +0 -1
  84. package/dist/subscription/SubscriptionManager.js +0 -317
  85. package/dist/subscription/SubscriptionManager.js.map +0 -1
  86. package/dist/subscription/index.d.ts +0 -3
  87. package/dist/subscription/index.d.ts.map +0 -1
  88. package/dist/subscription/index.js +0 -19
  89. package/dist/subscription/index.js.map +0 -1
  90. package/dist/subscription/types.d.ts +0 -65
  91. package/dist/subscription/types.d.ts.map +0 -1
  92. package/dist/subscription/types.js +0 -3
  93. package/dist/subscription/types.js.map +0 -1
  94. package/dist/testing.d.ts +0 -33
  95. package/dist/testing.d.ts.map +0 -1
  96. package/dist/testing.js +0 -68
  97. package/dist/testing.js.map +0 -1
  98. package/dist/types.d.ts +0 -57
  99. package/dist/types.d.ts.map +0 -1
  100. package/dist/types.js +0 -3
  101. package/dist/types.js.map +0 -1
  102. package/dist/utils/BatchingManager.d.ts +0 -28
  103. package/dist/utils/BatchingManager.d.ts.map +0 -1
  104. package/dist/utils/BatchingManager.js +0 -48
  105. package/dist/utils/BatchingManager.js.map +0 -1
  106. package/dist/utils/RerenderLogger.d.ts +0 -60
  107. package/dist/utils/RerenderLogger.d.ts.map +0 -1
  108. package/dist/utils/RerenderLogger.js +0 -205
  109. package/dist/utils/RerenderLogger.js.map +0 -1
  110. package/dist/utils/generateInstanceId.d.ts +0 -11
  111. package/dist/utils/generateInstanceId.d.ts.map +0 -1
  112. package/dist/utils/generateInstanceId.js +0 -50
  113. package/dist/utils/generateInstanceId.js.map +0 -1
  114. package/dist/utils/shallowEqual.d.ts +0 -9
  115. package/dist/utils/shallowEqual.d.ts.map +0 -1
  116. package/dist/utils/shallowEqual.js +0 -35
  117. package/dist/utils/shallowEqual.js.map +0 -1
  118. package/dist/utils/uuid.d.ts +0 -10
  119. package/dist/utils/uuid.d.ts.map +0 -1
  120. package/dist/utils/uuid.js +0 -24
  121. package/dist/utils/uuid.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,38 +1,1316 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./Blac"), exports);
18
- __exportStar(require("./Bloc"), exports);
19
- __exportStar(require("./BlocBase"), exports);
20
- __exportStar(require("./Cubit"), exports);
21
- __exportStar(require("./types"), exports);
22
- __exportStar(require("./events"), exports);
23
- __exportStar(require("./subscription"), exports);
24
- __exportStar(require("./lifecycle"), exports);
25
- // Utilities
26
- __exportStar(require("./utils/uuid"), exports);
27
- __exportStar(require("./utils/shallowEqual"), exports);
28
- __exportStar(require("./utils/generateInstanceId"), exports);
29
- __exportStar(require("./utils/RerenderLogger"), exports);
30
- // Test utilities
31
- __exportStar(require("./testing"), exports);
32
- // Adapter
33
- __exportStar(require("./adapter"), exports);
34
- // Plugins
35
- __exportStar(require("./plugins"), exports);
36
- // Error handling
37
- __exportStar(require("./errors"), exports);
1
+ //#region src/utils/idGenerator.ts
2
+ /**
3
+ * Centralized ID Generation
4
+ *
5
+ * Provides consistent, collision-resistant ID generation for all BlaC subsystems.
6
+ * Uses timestamp + counter + random suffix for uniqueness.
7
+ */
8
+ const globalCounters = /* @__PURE__ */ new Map();
9
+ /**
10
+ * Creates an ID generator with isolated counter state
11
+ *
12
+ * @param prefix - Prefix for generated IDs
13
+ * @returns Object with next(), nextSimple(), and reset() methods
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const generator = createIdGenerator('sub');
18
+ * const id1 = generator.next(); // "sub_1698765432100_1_a3k9d7f2q"
19
+ * const id2 = generator.next(); // "sub_1698765432101_2_b4n8e9g3r"
20
+ * ```
21
+ */
22
+ function createIdGenerator(prefix) {
23
+ let counter = 0;
24
+ return {
25
+ next: () => `${prefix}_${Date.now()}_${++counter}_${Math.random().toString(36).substring(2, 11)}`,
26
+ nextSimple: () => `${prefix}_${++counter}`,
27
+ reset: () => {
28
+ counter = 0;
29
+ }
30
+ };
31
+ }
32
+ /**
33
+ * Generate ID with timestamp, counter, and random suffix (tree-shakeable)
34
+ *
35
+ * Format: `${prefix}_${timestamp}_${counter}_${random}`
36
+ *
37
+ * @param prefix - Prefix for the ID (e.g., 'sub', 'consumer', 'stage')
38
+ * @returns Branded ID string
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const id = generateId('sub');
43
+ * // Returns: "sub_1698765432100_1_a3k9d7f2q"
44
+ * ```
45
+ */
46
+ function generateId(prefix) {
47
+ const counter = (globalCounters.get(prefix) ?? 0) + 1;
48
+ globalCounters.set(prefix, counter);
49
+ return `${prefix}_${Date.now()}_${counter}_${Math.random().toString(36).substring(2, 11)}`;
50
+ }
51
+ /**
52
+ * Generate simple ID with timestamp and random (no counter tracking)
53
+ *
54
+ * Format: `${prefix}_${timestamp}_${random}`
55
+ *
56
+ * @param prefix - Prefix for the ID
57
+ * @returns Branded ID string
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const id = generateSimpleId('CounterBloc');
62
+ * // Returns: "CounterBloc_1698765432100_a3k9d7f2q"
63
+ * ```
64
+ */
65
+ function generateSimpleId(prefix) {
66
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
67
+ }
68
+ /**
69
+ * Reset all counters for testing purposes
70
+ * @internal
71
+ */
72
+ function __resetIdCounters() {
73
+ globalCounters.clear();
74
+ }
75
+
76
+ //#endregion
77
+ //#region src/core/StateContainerRegistry.ts
78
+ /**
79
+ * Registry for managing StateContainer instances
80
+ */
81
+ var StateContainerRegistry = class {
82
+ instances = /* @__PURE__ */ new Map();
83
+ types = /* @__PURE__ */ new Map();
84
+ /**
85
+ * Register a type with isolation mode
86
+ */
87
+ register(constructor, isolated = false) {
88
+ const className = constructor.name;
89
+ if (!isolated && constructor.isolated === true) isolated = true;
90
+ if (this.types.has(className)) throw new Error(`Type "${className}" is already registered`);
91
+ this.types.set(className, { isolated });
92
+ }
93
+ /**
94
+ * Get or create a StateContainer instance
95
+ * For isolated: always creates new
96
+ * For shared: singleton per key
97
+ */
98
+ getOrCreate(constructor, key, ...args) {
99
+ const className = constructor.name;
100
+ let config = this.types.get(className);
101
+ if (!config) {
102
+ const isolated = constructor.isolated === true;
103
+ this.types.set(className, { isolated });
104
+ config = this.types.get(className);
105
+ }
106
+ if (config.isolated) return new constructor(...args);
107
+ const instanceKey = `${className}:${key || "default"}`;
108
+ const existing = this.instances.get(instanceKey);
109
+ if (existing) {
110
+ existing.refCount++;
111
+ return existing.instance;
112
+ }
113
+ const instance = new constructor(...args);
114
+ this.instances.set(instanceKey, {
115
+ instance,
116
+ refCount: 1
117
+ });
118
+ return instance;
119
+ }
120
+ /**
121
+ * Release a reference to an instance
122
+ * Disposes when ref count reaches zero (unless keepAlive)
123
+ */
124
+ release(constructor, key, forceDispose = false) {
125
+ const instanceKey = `${constructor.name}:${key || "default"}`;
126
+ const entry = this.instances.get(instanceKey);
127
+ if (!entry) return;
128
+ if (forceDispose) {
129
+ entry.instance.dispose();
130
+ this.instances.delete(instanceKey);
131
+ return;
132
+ }
133
+ entry.refCount--;
134
+ if (entry.refCount <= 0 && !entry.instance.keepAlive) {
135
+ entry.instance.dispose();
136
+ this.instances.delete(instanceKey);
137
+ }
138
+ }
139
+ /**
140
+ * Get all instances of a type (shared only, isolated aren't tracked)
141
+ */
142
+ getAll(constructor) {
143
+ const prefix = `${constructor.name}:`;
144
+ const results = [];
145
+ for (const [key, entry] of this.instances) if (key.startsWith(prefix)) results.push(entry.instance);
146
+ return results;
147
+ }
148
+ /**
149
+ * Clear all instances of a type
150
+ */
151
+ clear(constructor) {
152
+ const prefix = `${constructor.name}:`;
153
+ const toDelete = [];
154
+ for (const [key, entry] of this.instances) if (key.startsWith(prefix)) {
155
+ if (!entry.instance.isDisposed) entry.instance.dispose();
156
+ toDelete.push(key);
157
+ }
158
+ for (const key of toDelete) this.instances.delete(key);
159
+ }
160
+ /**
161
+ * Clear all instances from all types (for testing)
162
+ */
163
+ clearAll() {
164
+ for (const entry of this.instances.values()) if (!entry.instance.isDisposed) entry.instance.dispose();
165
+ this.instances.clear();
166
+ this.types.clear();
167
+ }
168
+ /**
169
+ * Get registry statistics (for debugging)
170
+ */
171
+ getStats() {
172
+ const typeBreakdown = {};
173
+ for (const key of this.instances.keys()) {
174
+ const typeName = key.split(":")[0];
175
+ typeBreakdown[typeName] = (typeBreakdown[typeName] || 0) + 1;
176
+ }
177
+ return {
178
+ registeredTypes: this.types.size,
179
+ totalInstances: this.instances.size,
180
+ typeBreakdown
181
+ };
182
+ }
183
+ /**
184
+ * Get reference count for an instance
185
+ */
186
+ getRefCount(constructor, key) {
187
+ const instanceKey = `${constructor.name}:${key || "default"}`;
188
+ return this.instances.get(instanceKey)?.refCount ?? 0;
189
+ }
190
+ /**
191
+ * Check if an instance exists
192
+ */
193
+ hasInstance(constructor, key) {
194
+ const instanceKey = `${constructor.name}:${key || "default"}`;
195
+ return this.instances.has(instanceKey);
196
+ }
197
+ };
198
+ /**
199
+ * Global default registry instance
200
+ */
201
+ const globalRegistry = new StateContainerRegistry();
202
+
203
+ //#endregion
204
+ //#region src/core/StateContainer.ts
205
+ /**
206
+ * Base abstract class for all state containers
207
+ */
208
+ var StateContainer = class StateContainer {
209
+ static _registry = globalRegistry;
210
+ /**
211
+ * Set a custom registry (mainly for testing)
212
+ */
213
+ static setRegistry(registry) {
214
+ StateContainer._registry = registry;
215
+ }
216
+ /**
217
+ * Register a type as isolated or shared
218
+ */
219
+ static register(isolated = false) {
220
+ StateContainer._registry.register(this, isolated);
221
+ }
222
+ /**
223
+ * Get or create an instance
224
+ * @param key - Optional instance key for shared instances
225
+ * @param args - Constructor arguments
226
+ */
227
+ static getOrCreate(key, ...args) {
228
+ return StateContainer._registry.getOrCreate(this, key, ...args);
229
+ }
230
+ /**
231
+ * Release a reference to an instance
232
+ * @param key - Optional instance key
233
+ * @param forceDispose - Force dispose regardless of ref count or keepAlive
234
+ */
235
+ static release(key, forceDispose = false) {
236
+ StateContainer._registry.release(this, key, forceDispose);
237
+ }
238
+ /**
239
+ * Get all instances of this type
240
+ */
241
+ static getAll() {
242
+ return StateContainer._registry.getAll(this);
243
+ }
244
+ /**
245
+ * Clear all instances of this type
246
+ */
247
+ static clear() {
248
+ StateContainer._registry.clear(this);
249
+ }
250
+ /**
251
+ * Clear all instances from all types (for testing)
252
+ */
253
+ static clearAllInstances() {
254
+ StateContainer._registry.clearAll();
255
+ }
256
+ /**
257
+ * Get registry statistics (for debugging)
258
+ */
259
+ static getStats() {
260
+ return StateContainer._registry.getStats();
261
+ }
262
+ /**
263
+ * Get reference count for an instance
264
+ * @param key - Optional instance key
265
+ */
266
+ static getRefCount(key) {
267
+ return StateContainer._registry.getRefCount(this, key);
268
+ }
269
+ /**
270
+ * Check if an instance exists
271
+ * @param key - Optional instance key
272
+ */
273
+ static hasInstance(key) {
274
+ return StateContainer._registry.hasInstance(this, key);
275
+ }
276
+ _state;
277
+ listeners = /* @__PURE__ */ new Set();
278
+ _disposed = false;
279
+ config;
280
+ name;
281
+ keepAlive;
282
+ debug;
283
+ instanceId;
284
+ /**
285
+ * Create a new StateContainer
286
+ */
287
+ constructor(initialState, config = {}) {
288
+ this._state = initialState;
289
+ this.config = config;
290
+ this.name = config.name || this.constructor.name;
291
+ this.keepAlive = config.keepAlive ?? false;
292
+ this.debug = config.debug ?? false;
293
+ this.instanceId = config.instanceId || generateSimpleId(this.constructor.name);
294
+ }
295
+ /**
296
+ * Get the current state
297
+ */
298
+ get state() {
299
+ return this._state;
300
+ }
301
+ /**
302
+ * Check if disposed
303
+ */
304
+ get isDisposed() {
305
+ return this._disposed;
306
+ }
307
+ /**
308
+ * Subscribe to state changes
309
+ * @returns Unsubscribe function
310
+ */
311
+ subscribe(listener) {
312
+ if (this._disposed) throw new Error(`Cannot subscribe to disposed container ${this.name}`);
313
+ this.listeners.add(listener);
314
+ return () => this.listeners.delete(listener);
315
+ }
316
+ /**
317
+ * Dispose the container
318
+ */
319
+ dispose() {
320
+ if (this._disposed) return;
321
+ if (this.debug) console.log(`[${this.name}] Disposing...`);
322
+ this._disposed = true;
323
+ this.onDispose?.();
324
+ this.listeners.clear();
325
+ if (this.debug) console.log(`[${this.name}] Disposed successfully`);
326
+ }
327
+ /**
328
+ * Emit a new state (with change detection)
329
+ */
330
+ emit(newState) {
331
+ if (this._disposed) throw new Error(`Cannot emit state from disposed container ${this.name}`);
332
+ if (this._state === newState) return;
333
+ const previousState = this._state;
334
+ this._state = newState;
335
+ this.onStateChange?.(newState, previousState);
336
+ for (const listener of this.listeners) try {
337
+ listener(newState);
338
+ } catch (error$1) {
339
+ console.error(`[${this.name}] Error in listener:`, error$1);
340
+ }
341
+ }
342
+ /**
343
+ * Update state using a function
344
+ */
345
+ update(updater) {
346
+ if (this._disposed) throw new Error(`Cannot update state from disposed container ${this.name}`);
347
+ this.emit(updater(this._state));
348
+ }
349
+ };
350
+
351
+ //#endregion
352
+ //#region src/core/Cubit.ts
353
+ /**
354
+ * Cubit is a simple state container that allows direct state emission
355
+ *
356
+ * Unlike StateContainer (where emit is protected), Cubit exposes emit and update
357
+ * as public methods to allow direct state management.
358
+ */
359
+ var Cubit = class extends StateContainer {
360
+ /**
361
+ * Create a new Cubit
362
+ * @param initialState Initial state value
363
+ * @param config Configuration options
364
+ */
365
+ constructor(initialState, config) {
366
+ super(initialState, config);
367
+ }
368
+ /**
369
+ * Emit a new state (public override of protected parent method)
370
+ */
371
+ emit(newState) {
372
+ super["emit"](newState);
373
+ }
374
+ /**
375
+ * Update state using a function (public override of protected parent method)
376
+ */
377
+ update(updater) {
378
+ super["update"](updater);
379
+ }
380
+ /**
381
+ * Patch state with partial updates (shallow merge)
382
+ * Only available when state is an object type
383
+ * Arrow function to maintain correct 'this' binding in React
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * // Update single field
388
+ * this.patch({ count: 5 });
389
+ *
390
+ * // Update multiple fields
391
+ * this.patch({ count: 5, name: 'Updated' });
392
+ * ```
393
+ */
394
+ patch = ((partial) => {
395
+ if (typeof this.state !== "object" || this.state === null) throw new Error("patch() is only available for object state types");
396
+ this.update((current) => ({
397
+ ...current,
398
+ ...partial
399
+ }));
400
+ });
401
+ };
402
+ /**
403
+ * Example: Counter Cubit
404
+ */
405
+ var CounterCubit = class extends Cubit {
406
+ constructor() {
407
+ super(0, { name: "CounterCubit" });
408
+ }
409
+ increment = () => {
410
+ this.emit(this.state + 1);
411
+ };
412
+ decrement = () => {
413
+ this.emit(this.state - 1);
414
+ };
415
+ reset = () => {
416
+ this.emit(0);
417
+ };
418
+ addAmount = (amount) => {
419
+ this.emit(this.state + amount);
420
+ };
421
+ };
422
+ var TodoCubit = class extends Cubit {
423
+ nextId = 0;
424
+ constructor() {
425
+ super({
426
+ todos: [],
427
+ filter: "all",
428
+ isLoading: false
429
+ }, {
430
+ name: "TodoCubit",
431
+ keepAlive: true
432
+ });
433
+ }
434
+ addTodo = (text) => {
435
+ this.update((state) => ({
436
+ ...state,
437
+ todos: [...state.todos, {
438
+ id: `todo-${Date.now()}-${this.nextId++}`,
439
+ text,
440
+ done: false
441
+ }]
442
+ }));
443
+ };
444
+ toggleTodo = (id) => {
445
+ this.update((state) => ({
446
+ ...state,
447
+ todos: state.todos.map((todo) => todo.id === id ? {
448
+ ...todo,
449
+ done: !todo.done
450
+ } : todo)
451
+ }));
452
+ };
453
+ removeTodo = (id) => {
454
+ this.update((state) => ({
455
+ ...state,
456
+ todos: state.todos.filter((todo) => todo.id !== id)
457
+ }));
458
+ };
459
+ setFilter = (filter) => {
460
+ this.patch({ filter });
461
+ };
462
+ setLoading = (isLoading) => {
463
+ this.patch({ isLoading });
464
+ };
465
+ get visibleTodos() {
466
+ const todos = this.state.todos;
467
+ switch (this.state.filter) {
468
+ case "active": return todos.filter((t) => !t.done);
469
+ case "completed": return todos.filter((t) => t.done);
470
+ case "all":
471
+ default: return todos;
472
+ }
473
+ }
474
+ get activeTodoCount() {
475
+ return this.state.todos.filter((t) => !t.done).length;
476
+ }
477
+ };
478
+
479
+ //#endregion
480
+ //#region src/core/Vertex.ts
481
+ /**
482
+ * Vertex is an event-driven state container (Bloc pattern)
483
+ *
484
+ * Includes its own simple event system since events are only needed
485
+ * for the Vertex pattern, not for the base StateContainer.
486
+ */
487
+ var Vertex = class extends StateContainer {
488
+ eventHandlers = /* @__PURE__ */ new Map();
489
+ isProcessing = false;
490
+ eventQueue = [];
491
+ /**
492
+ * Create a new Vertex
493
+ * @param initialState Initial state value
494
+ * @param config Configuration options
495
+ */
496
+ constructor(initialState, config) {
497
+ super(initialState, config);
498
+ }
499
+ /**
500
+ * Register an event handler
501
+ * Arrow function to maintain correct 'this' binding
502
+ */
503
+ on = (EventClass, handler) => {
504
+ const className = EventClass.name;
505
+ const registrations = this.eventHandlers.get(className) || [];
506
+ registrations.push({
507
+ eventClass: EventClass,
508
+ handler
509
+ });
510
+ this.eventHandlers.set(className, registrations);
511
+ };
512
+ /**
513
+ * Add an event to be processed
514
+ * Arrow function to maintain correct 'this' binding in React
515
+ */
516
+ add = (event) => {
517
+ this.processEvent(event);
518
+ };
519
+ /**
520
+ * Process an event (synchronously)
521
+ */
522
+ processEvent(event) {
523
+ if (this.isProcessing) {
524
+ this.eventQueue.push(event);
525
+ return;
526
+ }
527
+ this.isProcessing = true;
528
+ try {
529
+ this.handleEvent(event);
530
+ while (this.eventQueue.length > 0) {
531
+ const nextEvent = this.eventQueue.shift();
532
+ this.handleEvent(nextEvent);
533
+ }
534
+ } finally {
535
+ this.isProcessing = false;
536
+ }
537
+ }
538
+ /**
539
+ * Handle a single event (synchronously)
540
+ */
541
+ handleEvent(event) {
542
+ const className = event.constructor.name;
543
+ const registrations = this.eventHandlers.get(className);
544
+ if (!registrations || registrations.length === 0) {
545
+ if (this.debug) console.warn(`No handler registered for event: ${className}`);
546
+ return;
547
+ }
548
+ const emitFn = (state) => {
549
+ this.emit(state);
550
+ };
551
+ for (const registration of registrations) try {
552
+ registration.handler(event, emitFn);
553
+ } catch (error$1) {
554
+ if (this.debug) console.error(`Error handling event ${className}:`, error$1);
555
+ this.onEventError(event, error$1);
556
+ }
557
+ }
558
+ /**
559
+ * Hook for handling event processing errors
560
+ */
561
+ onEventError(event, error$1) {}
562
+ };
563
+ /**
564
+ * Example: Counter Events
565
+ */
566
+ var IncrementEvent = class {
567
+ type = "increment";
568
+ timestamp = Date.now();
569
+ constructor(amount = 1) {
570
+ this.amount = amount;
571
+ }
572
+ };
573
+ var DecrementEvent = class {
574
+ type = "decrement";
575
+ timestamp = Date.now();
576
+ constructor(amount = 1) {
577
+ this.amount = amount;
578
+ }
579
+ };
580
+ var ResetEvent = class {
581
+ type = "reset";
582
+ timestamp = Date.now();
583
+ };
584
+ /**
585
+ * Example: Counter Vertex
586
+ * Demonstrates proper typing and event handling
587
+ */
588
+ var CounterVertex = class extends Vertex {
589
+ constructor() {
590
+ super(0);
591
+ this.on(IncrementEvent, (event, emit) => {
592
+ emit(this.state + event.amount);
593
+ });
594
+ this.on(DecrementEvent, (event, emit) => {
595
+ emit(this.state - event.amount);
596
+ });
597
+ this.on(ResetEvent, (_, emit) => {
598
+ emit(0);
599
+ });
600
+ }
601
+ increment = (amount = 1) => {
602
+ this.add(new IncrementEvent(amount));
603
+ };
604
+ decrement = (amount = 1) => {
605
+ this.add(new DecrementEvent(amount));
606
+ };
607
+ reset = () => {
608
+ this.add(new ResetEvent());
609
+ };
610
+ };
611
+ var LoginEvent = class {
612
+ type = "login";
613
+ timestamp = Date.now();
614
+ constructor(email, password) {
615
+ this.email = email;
616
+ this.password = password;
617
+ }
618
+ };
619
+ var LogoutEvent = class {
620
+ type = "logout";
621
+ timestamp = Date.now();
622
+ };
623
+ var AuthVertex = class extends Vertex {
624
+ constructor() {
625
+ super({
626
+ isAuthenticated: false,
627
+ isLoading: false,
628
+ user: null,
629
+ error: null
630
+ });
631
+ this.on(LoginEvent, (event, emit) => {
632
+ emit({
633
+ ...this.state,
634
+ isLoading: true,
635
+ error: null
636
+ });
637
+ if (event.email === "user@example.com" && event.password === "password") emit({
638
+ isAuthenticated: true,
639
+ isLoading: false,
640
+ user: {
641
+ id: "123",
642
+ name: "Test User",
643
+ email: "user@example.com"
644
+ },
645
+ error: null
646
+ });
647
+ else emit({
648
+ isAuthenticated: false,
649
+ isLoading: false,
650
+ user: null,
651
+ error: "Invalid credentials"
652
+ });
653
+ });
654
+ this.on(LogoutEvent, (_, emit) => {
655
+ emit({
656
+ isAuthenticated: false,
657
+ isLoading: false,
658
+ user: null,
659
+ error: null
660
+ });
661
+ });
662
+ }
663
+ login = (email, password) => {
664
+ this.add(new LoginEvent(email, password));
665
+ };
666
+ logout = () => {
667
+ this.add(new LogoutEvent());
668
+ };
669
+ };
670
+
671
+ //#endregion
672
+ //#region src/tracking/proxy-tracker.ts
673
+ /**
674
+ * Functional proxy tracker for automatic dependency tracking
675
+ *
676
+ * This module provides a functional approach to proxy-based dependency tracking.
677
+ * Unlike the class-based ProxyTracker, this uses a state object pattern that's
678
+ * easier to integrate with functional programming patterns and framework hooks.
679
+ */
680
+ /**
681
+ * Array methods that should trigger tracking of the entire array
682
+ */
683
+ const ARRAY_METHODS = new Set([
684
+ "map",
685
+ "filter",
686
+ "forEach",
687
+ "find",
688
+ "some",
689
+ "every",
690
+ "reduce"
691
+ ]);
692
+ /**
693
+ * Check if a value can be proxied
694
+ *
695
+ * Returns true for plain objects and arrays only.
696
+ * Excludes built-in objects like Date, Map, Set, etc.
697
+ */
698
+ function isProxyable(value) {
699
+ if (typeof value !== "object" || value === null) return false;
700
+ const proto = Object.getPrototypeOf(value);
701
+ return proto === Object.prototype || proto === Array.prototype;
702
+ }
703
+ /**
704
+ * Create a new proxy tracker state
705
+ *
706
+ * @example
707
+ * const state = createProxyTrackerState<MyState>();
708
+ * startProxyTracking(state);
709
+ * const proxy = createProxyForTarget(state, myObject);
710
+ * // ... use proxy ...
711
+ * const paths = stopProxyTracking(state);
712
+ */
713
+ function createProxyTrackerState() {
714
+ return {
715
+ trackedPaths: /* @__PURE__ */ new Set(),
716
+ isTracking: false,
717
+ proxyCache: /* @__PURE__ */ new WeakMap(),
718
+ boundFunctionsCache: null,
719
+ lastProxiedState: null,
720
+ lastProxy: null,
721
+ maxDepth: 10
722
+ };
723
+ }
724
+ /**
725
+ * Start tracking property accesses
726
+ *
727
+ * Clears previous tracked paths and enables tracking mode.
728
+ */
729
+ function startProxyTracking(state) {
730
+ state.isTracking = true;
731
+ state.trackedPaths.clear();
732
+ }
733
+ /**
734
+ * Stop tracking and return the tracked paths
735
+ *
736
+ * Returns a new Set containing all tracked paths.
737
+ */
738
+ function stopProxyTracking(state) {
739
+ state.isTracking = false;
740
+ return new Set(state.trackedPaths);
741
+ }
742
+ /**
743
+ * Create a proxy for an array with property access tracking
744
+ *
745
+ * Tracks:
746
+ * - Array element access (arr[0])
747
+ * - Length access (arr.length)
748
+ * - Array method calls (arr.map, arr.filter, etc.)
749
+ */
750
+ function createArrayProxy(state, target, path, depth = 0) {
751
+ const proxy = new Proxy(target, { get: (arr, prop) => {
752
+ if (typeof prop === "symbol") return Reflect.get(arr, prop);
753
+ const value = Reflect.get(arr, prop);
754
+ if (typeof value === "function") {
755
+ if (ARRAY_METHODS.has(prop)) {
756
+ if (state.isTracking && path) state.trackedPaths.add(path);
757
+ }
758
+ if (!state.boundFunctionsCache) state.boundFunctionsCache = /* @__PURE__ */ new WeakMap();
759
+ const cached = state.boundFunctionsCache.get(value);
760
+ if (cached) return cached;
761
+ const bound = value.bind(arr);
762
+ state.boundFunctionsCache.set(value, bound);
763
+ return bound;
764
+ }
765
+ let fullPath;
766
+ if (prop === "length") fullPath = path ? `${path}.length` : "length";
767
+ else if (typeof prop === "string") {
768
+ const index = Number(prop);
769
+ if (!isNaN(index) && index >= 0) fullPath = path ? `${path}[${index}]` : `[${index}]`;
770
+ else fullPath = path ? `${path}.${prop}` : prop;
771
+ } else return value;
772
+ if (isProxyable(value)) return createProxyInternal(state, value, fullPath, depth + 1);
773
+ if (state.isTracking) state.trackedPaths.add(fullPath);
774
+ return value;
775
+ } });
776
+ state.proxyCache.set(target, proxy);
777
+ return proxy;
778
+ }
779
+ /**
780
+ * Create a proxy for an object with property access tracking
781
+ *
782
+ * This is the core proxy creation function that recursively creates proxies
783
+ * for nested objects and arrays.
784
+ *
785
+ * Tracks:
786
+ * - Property access (obj.prop)
787
+ * - Nested property access (obj.nested.prop)
788
+ * - 'in' operator usage ('prop' in obj)
789
+ * - Object.keys, Object.entries, etc.
790
+ */
791
+ function createProxyInternal(state, target, path = "", depth = 0) {
792
+ if (!state.isTracking || !isProxyable(target)) return target;
793
+ if (depth >= state.maxDepth) return target;
794
+ if (state.proxyCache.has(target)) return state.proxyCache.get(target);
795
+ if (Array.isArray(target)) return createArrayProxy(state, target, path, depth);
796
+ const proxy = new Proxy(target, {
797
+ get: (obj, prop) => {
798
+ if (typeof prop === "symbol") return Reflect.get(obj, prop);
799
+ const value = Reflect.get(obj, prop);
800
+ if (typeof value === "function") {
801
+ if (!state.boundFunctionsCache) state.boundFunctionsCache = /* @__PURE__ */ new WeakMap();
802
+ const cached = state.boundFunctionsCache.get(value);
803
+ if (cached) return cached;
804
+ const bound = value.bind(obj);
805
+ state.boundFunctionsCache.set(value, bound);
806
+ return bound;
807
+ }
808
+ const fullPath = path ? `${path}.${String(prop)}` : String(prop);
809
+ if (isProxyable(value)) return createProxyInternal(state, value, fullPath, depth + 1);
810
+ if (typeof prop === "string" && state.isTracking) {
811
+ if (!prop.startsWith("_") && !prop.startsWith("$$")) state.trackedPaths.add(fullPath);
812
+ }
813
+ return value;
814
+ },
815
+ has: (obj, prop) => {
816
+ if (typeof prop === "string" && state.isTracking) {
817
+ const fullPath = path ? `${path}.${prop}` : prop;
818
+ state.trackedPaths.add(fullPath);
819
+ }
820
+ return Reflect.has(obj, prop);
821
+ },
822
+ ownKeys: (obj) => {
823
+ if (state.isTracking && path) state.trackedPaths.add(path);
824
+ return Reflect.ownKeys(obj);
825
+ }
826
+ });
827
+ state.proxyCache.set(target, proxy);
828
+ return proxy;
829
+ }
830
+ /**
831
+ * Create a proxy for a target with caching
832
+ *
833
+ * If the target hasn't changed since the last call, returns the cached proxy.
834
+ * Otherwise, creates a new proxy and caches it.
835
+ *
836
+ * This is the main entry point for creating tracked proxies.
837
+ */
838
+ function createProxyForTarget(state, target) {
839
+ if (state.lastProxiedState === target && state.lastProxy) return state.lastProxy;
840
+ state.proxyCache = /* @__PURE__ */ new WeakMap();
841
+ state.boundFunctionsCache = null;
842
+ const proxy = createProxyInternal(state, target, "", 0);
843
+ state.lastProxiedState = target;
844
+ state.lastProxy = proxy;
845
+ return proxy;
846
+ }
847
+
848
+ //#endregion
849
+ //#region src/tracking/path-utils.ts
850
+ /**
851
+ * Path utilities for dependency tracking
852
+ *
853
+ * Provides utilities for parsing property paths and extracting values
854
+ * from nested objects using path strings.
855
+ */
856
+ /**
857
+ * Parse a property path string into an array of segments
858
+ *
859
+ * Handles both dot notation (a.b.c) and bracket notation (a[0].b)
860
+ *
861
+ * @example
862
+ * parsePath('user.name') // ['user', 'name']
863
+ * parsePath('items[0].name') // ['items', '0', 'name']
864
+ * parsePath('data.users[2].address.city') // ['data', 'users', '2', 'address', 'city']
865
+ */
866
+ function parsePath(path) {
867
+ const segments = [];
868
+ let current = "";
869
+ let i = 0;
870
+ while (i < path.length) {
871
+ const char = path[i];
872
+ if (char === ".") {
873
+ if (current) segments.push(current);
874
+ current = "";
875
+ } else if (char === "[") {
876
+ if (current) segments.push(current);
877
+ current = "";
878
+ i++;
879
+ while (i < path.length && path[i] !== "]") current += path[i++];
880
+ if (current) segments.push(current);
881
+ current = "";
882
+ } else current += char;
883
+ i++;
884
+ }
885
+ if (current) segments.push(current);
886
+ return segments;
887
+ }
888
+ /**
889
+ * Get a value from an object using a path of segments
890
+ *
891
+ * @example
892
+ * const obj = { user: { name: 'Alice', age: 30 } }
893
+ * getValueAtPath(obj, ['user', 'name']) // 'Alice'
894
+ * getValueAtPath(obj, ['user', 'age']) // 30
895
+ * getValueAtPath(obj, ['user', 'missing']) // undefined
896
+ */
897
+ function getValueAtPath(obj, segments) {
898
+ if (obj == null) return void 0;
899
+ let current = obj;
900
+ for (let i = 0; i < segments.length; i++) {
901
+ current = current[segments[i]];
902
+ if (current == null) return void 0;
903
+ }
904
+ return current;
905
+ }
906
+ /**
907
+ * Shallow equality comparison for arrays
908
+ *
909
+ * Compares two arrays element-by-element using Object.is
910
+ *
911
+ * @example
912
+ * shallowEqual([1, 2, 3], [1, 2, 3]) // true
913
+ * shallowEqual([1, 2, 3], [1, 2, 4]) // false
914
+ * shallowEqual([1, 2], [1, 2, 3]) // false
915
+ */
916
+ function shallowEqual(arr1, arr2) {
917
+ if (arr1.length !== arr2.length) return false;
918
+ for (let i = 0; i < arr1.length; i++) if (!Object.is(arr1[i], arr2[i])) return false;
919
+ return true;
920
+ }
921
+
922
+ //#endregion
923
+ //#region src/tracking/dependency-tracker.ts
924
+ /**
925
+ * How often to clean up unused paths from the cache
926
+ */
927
+ const CLEANUP_INTERVAL = 10;
928
+ /**
929
+ * Create a new tracker state
930
+ */
931
+ function createTrackerState() {
932
+ return {
933
+ proxyTrackerState: createProxyTrackerState(),
934
+ previousRenderPaths: /* @__PURE__ */ new Set(),
935
+ currentRenderPaths: /* @__PURE__ */ new Set(),
936
+ pathCache: /* @__PURE__ */ new Map(),
937
+ lastCheckedState: null,
938
+ lastCheckedValues: /* @__PURE__ */ new Map(),
939
+ cleanupCounter: 0
940
+ };
941
+ }
942
+ /**
943
+ * Start tracking property accesses
944
+ */
945
+ function startTracking(tracker) {
946
+ startProxyTracking(tracker.proxyTrackerState);
947
+ }
948
+ /**
949
+ * Create a proxy for the given state
950
+ */
951
+ function createProxy(tracker, state) {
952
+ return createProxyForTarget(tracker.proxyTrackerState, state);
953
+ }
954
+ /**
955
+ * Capture the paths that were tracked during a render
956
+ *
957
+ * This should be called after each render to record which paths were accessed.
958
+ * It also performs periodic cleanup of unused paths to prevent memory leaks.
959
+ */
960
+ function captureTrackedPaths(tracker, state) {
961
+ tracker.previousRenderPaths = tracker.currentRenderPaths;
962
+ tracker.currentRenderPaths = stopProxyTracking(tracker.proxyTrackerState);
963
+ if (tracker.previousRenderPaths.size === 0 && tracker.currentRenderPaths.size === 0) return;
964
+ const trackedPathsUnion = new Set(tracker.previousRenderPaths);
965
+ for (const path of tracker.currentRenderPaths) trackedPathsUnion.add(path);
966
+ const canReuseCache = tracker.lastCheckedState === state;
967
+ for (const path of trackedPathsUnion) if (!tracker.pathCache.has(path)) {
968
+ const segments = parsePath(path);
969
+ const value = canReuseCache && tracker.lastCheckedValues.has(path) ? tracker.lastCheckedValues.get(path) : getValueAtPath(state, segments);
970
+ tracker.pathCache.set(path, {
971
+ segments,
972
+ value
973
+ });
974
+ } else {
975
+ const info$1 = tracker.pathCache.get(path);
976
+ info$1.value = canReuseCache && tracker.lastCheckedValues.has(path) ? tracker.lastCheckedValues.get(path) : getValueAtPath(state, info$1.segments);
977
+ }
978
+ tracker.cleanupCounter++;
979
+ if (tracker.cleanupCounter >= CLEANUP_INTERVAL) {
980
+ tracker.cleanupCounter = 0;
981
+ for (const path of tracker.pathCache.keys()) if (!trackedPathsUnion.has(path)) tracker.pathCache.delete(path);
982
+ }
983
+ tracker.lastCheckedValues.clear();
984
+ }
985
+ /**
986
+ * Check if any tracked paths have changed
987
+ *
988
+ * This is called when state changes to determine if a re-render is needed.
989
+ * Returns true if any tracked path has a different value than before.
990
+ */
991
+ function hasChanges(tracker, state) {
992
+ if (tracker.pathCache.size === 0) return true;
993
+ tracker.lastCheckedValues.clear();
994
+ for (const [path, info$1] of tracker.pathCache.entries()) {
995
+ const currentValue = getValueAtPath(state, info$1.segments);
996
+ tracker.lastCheckedValues.set(path, currentValue);
997
+ if (!Object.is(currentValue, info$1.value)) {
998
+ tracker.lastCheckedState = state;
999
+ return true;
1000
+ }
1001
+ }
1002
+ tracker.lastCheckedState = state;
1003
+ return false;
1004
+ }
1005
+ /**
1006
+ * Check if tracker has any tracked data
1007
+ *
1008
+ * Returns true if there are any tracked paths or cached paths.
1009
+ */
1010
+ function hasTrackedData(tracker) {
1011
+ return tracker.proxyTrackerState.trackedPaths.size > 0 || tracker.pathCache.size > 0 || tracker.previousRenderPaths.size > 0;
1012
+ }
1013
+
1014
+ //#endregion
1015
+ //#region src/logging/Logger.ts
1016
+ let LogLevel = /* @__PURE__ */ function(LogLevel$1) {
1017
+ LogLevel$1[LogLevel$1["ERROR"] = 0] = "ERROR";
1018
+ LogLevel$1[LogLevel$1["WARN"] = 1] = "WARN";
1019
+ LogLevel$1[LogLevel$1["INFO"] = 2] = "INFO";
1020
+ LogLevel$1[LogLevel$1["DEBUG"] = 3] = "DEBUG";
1021
+ return LogLevel$1;
1022
+ }({});
1023
+ /**
1024
+ * Creates a logger instance with given configuration
1025
+ *
1026
+ * @param config - Logger configuration
1027
+ * @returns Logger instance with debug, info, warn, error, and configure methods
1028
+ *
1029
+ * @example
1030
+ * ```ts
1031
+ * const logger = createLogger({
1032
+ * enabled: true,
1033
+ * level: LogLevel.DEBUG,
1034
+ * output: (entry) => console.log(JSON.stringify(entry))
1035
+ * });
1036
+ * logger.debug('MyComponent', 'Rendering', { props: { foo: 'bar' } });
1037
+ * ```
1038
+ */
1039
+ function createLogger(config) {
1040
+ const shouldLog = (level) => {
1041
+ return config.enabled && config.level >= level;
1042
+ };
1043
+ const log = (level, context, message, data) => {
1044
+ try {
1045
+ const entry = {
1046
+ level,
1047
+ context,
1048
+ message,
1049
+ timestamp: Date.now(),
1050
+ ...data !== void 0 && { data: serialize(data) }
1051
+ };
1052
+ config.output(entry);
1053
+ } catch (e) {
1054
+ console.error("[BlacLogger] Error logging:", e);
1055
+ }
1056
+ };
1057
+ const serialize = (data) => {
1058
+ try {
1059
+ return JSON.parse(JSON.stringify(data));
1060
+ } catch {
1061
+ return String(data);
1062
+ }
1063
+ };
1064
+ return {
1065
+ debug: (context, message, data) => {
1066
+ if (shouldLog(LogLevel.DEBUG)) log("DEBUG", context, message, data);
1067
+ },
1068
+ info: (context, message, data) => {
1069
+ if (shouldLog(LogLevel.INFO)) log("INFO", context, message, data);
1070
+ },
1071
+ warn: (context, message, data) => {
1072
+ if (shouldLog(LogLevel.WARN)) log("WARN", context, message, data);
1073
+ },
1074
+ error: (context, message, data) => {
1075
+ if (shouldLog(LogLevel.ERROR)) log("ERROR", context, message, data);
1076
+ },
1077
+ configure: (opts) => {
1078
+ Object.assign(config, opts);
1079
+ }
1080
+ };
1081
+ }
1082
+ let currentConfig = {
1083
+ enabled: false,
1084
+ level: LogLevel.INFO,
1085
+ output: (entry) => console.log(JSON.stringify(entry))
1086
+ };
1087
+ let defaultLogger = createLogger(currentConfig);
1088
+ const debug = (context, message, data) => defaultLogger.debug(context, message, data);
1089
+ const info = (context, message, data) => defaultLogger.info(context, message, data);
1090
+ const warn = (context, message, data) => defaultLogger.warn(context, message, data);
1091
+ const error = (context, message, data) => defaultLogger.error(context, message, data);
1092
+ /**
1093
+ * Configuration function that recreates the default logger
1094
+ *
1095
+ * @param opts - Partial logger configuration
1096
+ *
1097
+ * @example
1098
+ * ```ts
1099
+ * configureLogger({ enabled: true, level: LogLevel.DEBUG });
1100
+ * ```
1101
+ */
1102
+ function configureLogger(opts) {
1103
+ currentConfig = {
1104
+ ...currentConfig,
1105
+ ...opts
1106
+ };
1107
+ defaultLogger = createLogger(currentConfig);
1108
+ }
1109
+
1110
+ //#endregion
1111
+ //#region src/proxy/ProxyTracker.ts
1112
+ /**
1113
+ * Check if a value is an object that can be proxied
1114
+ */
1115
+ function isProxyable$1(value) {
1116
+ return value !== null && typeof value === "object" && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof Map) && !(value instanceof Set) && !(value instanceof WeakMap) && !(value instanceof WeakSet) && !(value instanceof Promise);
1117
+ }
1118
+ /**
1119
+ * Tracks property access on state objects
1120
+ */
1121
+ var ProxyTracker = class {
1122
+ trackedPaths = /* @__PURE__ */ new Set();
1123
+ isTracking = false;
1124
+ proxyCache = /* @__PURE__ */ new WeakMap();
1125
+ maxDepth = 10;
1126
+ /**
1127
+ * Create a proxy that tracks property access
1128
+ */
1129
+ createProxy(target, path = "", depth = 0) {
1130
+ if (!this.isTracking || !isProxyable$1(target)) return target;
1131
+ if (depth >= this.maxDepth) return target;
1132
+ if (this.proxyCache.has(target)) return this.proxyCache.get(target);
1133
+ if (Array.isArray(target)) return this.createArrayProxy(target, path, depth);
1134
+ const proxy = new Proxy(target, {
1135
+ get: (obj, prop) => {
1136
+ const value = Reflect.get(obj, prop);
1137
+ if (typeof value === "function") return value.bind(obj);
1138
+ const fullPath = path ? `${path}.${String(prop)}` : String(prop);
1139
+ if (isProxyable$1(value)) return this.createProxy(value, fullPath, depth + 1);
1140
+ if (typeof prop === "string" && this.isTracking) {
1141
+ if (!prop.startsWith("_") && !prop.startsWith("$$")) {
1142
+ this.trackedPaths.add(fullPath);
1143
+ debug("ProxyTracker", "Tracked property access", {
1144
+ path: fullPath,
1145
+ valueType: typeof value
1146
+ });
1147
+ }
1148
+ }
1149
+ return value;
1150
+ },
1151
+ has: (obj, prop) => {
1152
+ if (typeof prop === "string" && this.isTracking) {
1153
+ const fullPath = path ? `${path}.${prop}` : prop;
1154
+ this.trackedPaths.add(fullPath);
1155
+ debug("ProxyTracker", "Tracked \"in\" operator access", { path: fullPath });
1156
+ }
1157
+ return Reflect.has(obj, prop);
1158
+ },
1159
+ ownKeys: (obj) => {
1160
+ if (this.isTracking && path) {
1161
+ this.trackedPaths.add(path);
1162
+ debug("ProxyTracker", "Tracked object keys iteration", { path });
1163
+ }
1164
+ return Reflect.ownKeys(obj);
1165
+ }
1166
+ });
1167
+ this.proxyCache.set(target, proxy);
1168
+ return proxy;
1169
+ }
1170
+ /**
1171
+ * Create a proxy for arrays with special handling
1172
+ */
1173
+ createArrayProxy(target, path, depth = 0) {
1174
+ const proxy = new Proxy(target, { get: (arr, prop) => {
1175
+ const value = Reflect.get(arr, prop);
1176
+ if (typeof value === "function") {
1177
+ if ([
1178
+ "map",
1179
+ "filter",
1180
+ "forEach",
1181
+ "find",
1182
+ "some",
1183
+ "every",
1184
+ "reduce"
1185
+ ].includes(String(prop))) {
1186
+ if (this.isTracking && path) {
1187
+ this.trackedPaths.add(path);
1188
+ debug("ProxyTracker", "Tracked array method access", {
1189
+ path,
1190
+ method: String(prop)
1191
+ });
1192
+ }
1193
+ }
1194
+ return value.bind(arr);
1195
+ }
1196
+ let fullPath;
1197
+ if (prop === "length") fullPath = path ? `${path}.length` : "length";
1198
+ else if (typeof prop === "string") {
1199
+ const index = Number(prop);
1200
+ if (!isNaN(index) && index >= 0) fullPath = path ? `${path}[${index}]` : `[${index}]`;
1201
+ else fullPath = path ? `${path}.${prop}` : prop;
1202
+ } else return value;
1203
+ if (isProxyable$1(value)) return this.createProxy(value, fullPath, depth + 1);
1204
+ if (this.isTracking) {
1205
+ this.trackedPaths.add(fullPath);
1206
+ debug("ProxyTracker", "Tracked array property access", {
1207
+ path: fullPath,
1208
+ valueType: typeof value
1209
+ });
1210
+ }
1211
+ return value;
1212
+ } });
1213
+ this.proxyCache.set(target, proxy);
1214
+ return proxy;
1215
+ }
1216
+ /**
1217
+ * Start tracking property access
1218
+ */
1219
+ startTracking() {
1220
+ this.isTracking = true;
1221
+ this.trackedPaths.clear();
1222
+ debug("ProxyTracker", "Started tracking");
1223
+ }
1224
+ /**
1225
+ * Stop tracking and return tracked paths
1226
+ */
1227
+ stopTracking() {
1228
+ this.isTracking = false;
1229
+ debug("ProxyTracker", "Stopped tracking", {
1230
+ pathCount: this.trackedPaths.size,
1231
+ paths: Array.from(this.trackedPaths)
1232
+ });
1233
+ return new Set(this.trackedPaths);
1234
+ }
1235
+ /**
1236
+ * Get currently tracked paths
1237
+ */
1238
+ getTrackedPaths() {
1239
+ return new Set(this.trackedPaths);
1240
+ }
1241
+ /**
1242
+ * Check if currently tracking
1243
+ */
1244
+ isCurrentlyTracking() {
1245
+ return this.isTracking;
1246
+ }
1247
+ /**
1248
+ * Clear proxy cache (useful for memory management)
1249
+ */
1250
+ clearCache() {
1251
+ this.proxyCache = /* @__PURE__ */ new WeakMap();
1252
+ }
1253
+ /**
1254
+ * Set maximum tracking depth
1255
+ */
1256
+ setMaxDepth(depth) {
1257
+ this.maxDepth = Math.max(1, depth);
1258
+ }
1259
+ /**
1260
+ * Add a path manually (useful for forcing dependencies)
1261
+ */
1262
+ addPath(path) {
1263
+ this.trackedPaths.add(path);
1264
+ }
1265
+ /**
1266
+ * Remove a path manually
1267
+ */
1268
+ removePath(path) {
1269
+ this.trackedPaths.delete(path);
1270
+ }
1271
+ /**
1272
+ * Clear all tracked paths
1273
+ */
1274
+ clearPaths() {
1275
+ this.trackedPaths.clear();
1276
+ }
1277
+ };
1278
+ /**
1279
+ * Global proxy tracker instance for convenience
1280
+ */
1281
+ const globalProxyTracker = new ProxyTracker();
1282
+ /**
1283
+ * Utility function to track property access in a callback
1284
+ */
1285
+ function trackAccess(state, callback) {
1286
+ const tracker = new ProxyTracker();
1287
+ tracker.startTracking();
1288
+ return {
1289
+ result: callback(tracker.createProxy(state)),
1290
+ trackedPaths: tracker.stopTracking()
1291
+ };
1292
+ }
1293
+
1294
+ //#endregion
1295
+ //#region src/constants.ts
1296
+ /**
1297
+ * Default configuration constants for BlaC
1298
+ *
1299
+ * Centralized location for all magic numbers and default values.
1300
+ */
1301
+ /**
1302
+ * Default configuration constants for BlaC
1303
+ */
1304
+ const BLAC_DEFAULTS = {
1305
+ CLEANUP_INTERVAL_MS: 3e4,
1306
+ WEAKREF_CLEANUP_INTERVAL_MS: 1e4,
1307
+ MAX_SUBSCRIPTIONS: 1e3,
1308
+ MAX_SUBSCRIPTIONS_HIGH_PERF: 1e4,
1309
+ PIPELINE_TIMEOUT_MS: 5e3,
1310
+ CLEANUP_INTERVAL_HIGH_PERF_MS: 5e3,
1311
+ MAX_PIPELINE_STAGES: 30
1312
+ };
1313
+
1314
+ //#endregion
1315
+ export { AuthVertex, BLAC_DEFAULTS, CounterCubit, CounterVertex, Cubit, DecrementEvent, IncrementEvent, LogLevel, LoginEvent, LogoutEvent, ProxyTracker, ResetEvent, StateContainer, StateContainerRegistry, TodoCubit, Vertex, __resetIdCounters, captureTrackedPaths, configureLogger, createArrayProxy, createIdGenerator, createLogger, createProxy, createProxyForTarget, createProxyInternal, createProxyTrackerState, createTrackerState, debug, error, generateId, generateSimpleId, getValueAtPath, globalProxyTracker, globalRegistry, hasChanges, hasTrackedData, info, isProxyable, parsePath, shallowEqual, startProxyTracking, startTracking, stopProxyTracking, trackAccess, warn };
38
1316
  //# sourceMappingURL=index.js.map