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