@blac/core 2.0.0-rc.10 → 2.0.0-rc.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -38,10 +38,8 @@ function createIdGenerator(prefix) {
38
38
  * @returns Branded ID string
39
39
  *
40
40
  * @example
41
- * ```ts
42
41
  * const id = generateId('sub');
43
42
  * // Returns: "sub:1698765432100_1_a3k9d7f2q"
44
- * ```
45
43
  */
46
44
  function generateId(prefix) {
47
45
  const counter = (globalCounters.get(prefix) ?? 0) + 1;
@@ -96,12 +94,32 @@ function isIsolatedKey(key) {
96
94
 
97
95
  //#endregion
98
96
  //#region src/plugin/PluginManager.ts
97
+ /**
98
+ * Manages plugin lifecycle for the BlaC state management system.
99
+ * Plugins receive notifications about state container lifecycle events.
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * const manager = createPluginManager(registry);
104
+ * manager.install(myPlugin, { environment: 'development' });
105
+ * ```
106
+ */
99
107
  var PluginManager = class {
108
+ /**
109
+ * Create a new PluginManager
110
+ * @param registry - The StateContainerRegistry to monitor for lifecycle events
111
+ */
100
112
  constructor(registry) {
101
113
  this.plugins = /* @__PURE__ */ new Map();
102
114
  this.registry = registry;
103
115
  this.setupLifecycleHooks();
104
116
  }
117
+ /**
118
+ * Install a plugin with optional configuration
119
+ * @param plugin - The plugin to install
120
+ * @param config - Optional plugin configuration
121
+ * @throws Error if plugin is already installed
122
+ */
105
123
  install(plugin, config = {}) {
106
124
  const effectiveConfig = {
107
125
  enabled: true,
@@ -128,6 +146,11 @@ var PluginManager = class {
128
146
  }
129
147
  console.log(`[BlaC] Plugin "${plugin.name}" v${plugin.version} installed`);
130
148
  }
149
+ /**
150
+ * Uninstall a plugin by name
151
+ * @param pluginName - The name of the plugin to uninstall
152
+ * @throws Error if plugin is not installed
153
+ */
131
154
  uninstall(pluginName) {
132
155
  const installed = this.plugins.get(pluginName);
133
156
  if (!installed) throw new Error(`Plugin "${pluginName}" is not installed`);
@@ -139,15 +162,32 @@ var PluginManager = class {
139
162
  this.plugins.delete(pluginName);
140
163
  console.log(`[BlaC] Plugin "${pluginName}" uninstalled`);
141
164
  }
165
+ /**
166
+ * Get an installed plugin by name
167
+ * @param pluginName - The name of the plugin to retrieve
168
+ * @returns The plugin instance or undefined if not found
169
+ */
142
170
  getPlugin(pluginName) {
143
171
  return this.plugins.get(pluginName)?.plugin;
144
172
  }
173
+ /**
174
+ * Get all installed plugins
175
+ * @returns Array of all installed plugins
176
+ */
145
177
  getAllPlugins() {
146
178
  return Array.from(this.plugins.values()).map((p) => p.plugin);
147
179
  }
180
+ /**
181
+ * Check if a plugin is installed
182
+ * @param pluginName - The name of the plugin to check
183
+ * @returns true if the plugin is installed
184
+ */
148
185
  hasPlugin(pluginName) {
149
186
  return this.plugins.has(pluginName);
150
187
  }
188
+ /**
189
+ * Uninstall all plugins
190
+ */
151
191
  clear() {
152
192
  for (const name of this.plugins.keys()) this.uninstall(name);
153
193
  }
@@ -294,9 +334,15 @@ const getterExecutionContext = {
294
334
  visitedBlocs: /* @__PURE__ */ new Set()
295
335
  };
296
336
  const MAX_GETTER_DEPTH = BLAC_DEFAULTS.MAX_GETTER_DEPTH;
337
+ /**
338
+ * @internal
339
+ */
297
340
  function getGetterExecutionContext() {
298
341
  return getterExecutionContext;
299
342
  }
343
+ /**
344
+ * @internal
345
+ */
300
346
  function getDescriptor(obj, prop) {
301
347
  const constructor = obj.constructor;
302
348
  let constructorCache = descriptorCache.get(constructor);
@@ -315,9 +361,15 @@ function getDescriptor(obj, prop) {
315
361
  constructorCache.set(prop, descriptor);
316
362
  return descriptor;
317
363
  }
364
+ /**
365
+ * @internal
366
+ */
318
367
  function isGetter(obj, prop) {
319
368
  return getDescriptor(obj, prop)?.get !== void 0;
320
369
  }
370
+ /**
371
+ * @internal
372
+ */
321
373
  function createGetterTracker() {
322
374
  return {
323
375
  trackedValues: /* @__PURE__ */ new Map(),
@@ -329,19 +381,34 @@ function createGetterTracker() {
329
381
  externalDependencies: /* @__PURE__ */ new Set()
330
382
  };
331
383
  }
384
+ /**
385
+ * @internal
386
+ */
332
387
  function setActiveTracker(bloc, tracker) {
333
388
  activeTrackerMap.set(bloc, tracker);
334
389
  }
390
+ /**
391
+ * @internal
392
+ */
335
393
  function clearActiveTracker(bloc) {
336
394
  activeTrackerMap.delete(bloc);
337
395
  }
396
+ /**
397
+ * @internal
398
+ */
338
399
  function getActiveTracker(bloc) {
339
400
  return activeTrackerMap.get(bloc);
340
401
  }
402
+ /**
403
+ * @internal
404
+ */
341
405
  function commitTrackedGetters(tracker) {
342
406
  if (tracker.currentlyAccessing.size > 0) tracker.trackedGetters = new Set(tracker.currentlyAccessing);
343
407
  tracker.currentlyAccessing.clear();
344
408
  }
409
+ /**
410
+ * @internal
411
+ */
345
412
  function createBlocProxy(bloc) {
346
413
  const cached = blocProxyCache.get(bloc);
347
414
  if (cached) return cached;
@@ -391,6 +458,9 @@ function createBlocProxy(bloc) {
391
458
  blocProxyCache.set(bloc, proxy);
392
459
  return proxy;
393
460
  }
461
+ /**
462
+ * @internal
463
+ */
394
464
  function hasGetterChanges(bloc, tracker) {
395
465
  if (!tracker || tracker.trackedGetters.size === 0) return false;
396
466
  tracker.renderCache.clear();
@@ -413,12 +483,21 @@ function hasGetterChanges(bloc, tracker) {
413
483
  tracker.cacheValid = true;
414
484
  return hasAnyChange;
415
485
  }
486
+ /**
487
+ * @internal
488
+ */
416
489
  function invalidateRenderCache(tracker) {
417
490
  tracker.cacheValid = false;
418
491
  }
492
+ /**
493
+ * @internal
494
+ */
419
495
  function clearExternalDependencies(tracker) {
420
496
  tracker.externalDependencies.clear();
421
497
  }
498
+ /**
499
+ * @internal
500
+ */
422
501
  function resetGetterTracker(tracker) {
423
502
  tracker.trackedValues.clear();
424
503
  tracker.currentlyAccessing.clear();
@@ -470,6 +549,19 @@ function isExcludedFromDevTools(Type) {
470
549
 
471
550
  //#endregion
472
551
  //#region src/core/StateContainerRegistry.ts
552
+ /**
553
+ * Central registry for managing StateContainer instances.
554
+ * Handles instance lifecycle, ref counting, and lifecycle event emission.
555
+ *
556
+ * @example
557
+ * ```ts
558
+ * const registry = new StateContainerRegistry();
559
+ * const instance = registry.resolve(MyBloc);
560
+ * registry.on('stateChanged', (container, prev, next) => {
561
+ * console.log('State changed:', prev, '->', next);
562
+ * });
563
+ * ```
564
+ */
473
565
  var StateContainerRegistry = class {
474
566
  constructor() {
475
567
  this.instancesByConstructor = /* @__PURE__ */ new WeakMap();
@@ -477,9 +569,19 @@ var StateContainerRegistry = class {
477
569
  this.typeConfigs = /* @__PURE__ */ new Map();
478
570
  this.listeners = /* @__PURE__ */ new Map();
479
571
  }
572
+ /**
573
+ * Register a type for lifecycle event tracking
574
+ * @param constructor - The StateContainer class constructor
575
+ */
480
576
  registerType(constructor) {
481
577
  this.types.add(constructor);
482
578
  }
579
+ /**
580
+ * Register a StateContainer class with configuration
581
+ * @param constructor - The StateContainer class constructor
582
+ * @param isolated - Whether instances should be isolated (component-scoped)
583
+ * @throws Error if type is already registered
584
+ */
483
585
  register(constructor, isolated = false) {
484
586
  const className = constructor.name;
485
587
  if (!isolated && isIsolatedClass(constructor)) isolated = true;
@@ -732,6 +834,26 @@ function getPluginManager() {
732
834
 
733
835
  //#endregion
734
836
  //#region src/core/StateContainer.ts
837
+ /**
838
+ * Abstract base class for all state containers in BlaC.
839
+ * Provides lifecycle management, subscription handling, ref counting,
840
+ * and integration with the global registry.
841
+ *
842
+ * @template S - State type managed by this container
843
+ * @template P - Props type passed to the container (optional)
844
+ *
845
+ * @example
846
+ * ```ts
847
+ * class CounterBloc extends StateContainer<number> {
848
+ * constructor() {
849
+ * super(0);
850
+ * }
851
+ * increment() {
852
+ * this.emit(this.state + 1);
853
+ * }
854
+ * }
855
+ * ```
856
+ */
735
857
  var StateContainer = class StateContainer {
736
858
  static {
737
859
  this.__excludeFromDevTools = false;
@@ -739,52 +861,124 @@ var StateContainer = class StateContainer {
739
861
  static {
740
862
  this._registry = globalRegistry;
741
863
  }
864
+ /**
865
+ * Get the global StateContainerRegistry
866
+ * @returns The registry managing all state container instances
867
+ */
742
868
  static getRegistry() {
743
869
  return StateContainer._registry;
744
870
  }
871
+ /**
872
+ * Replace the global registry (clears existing instances)
873
+ * @param registry - The new registry to use
874
+ */
745
875
  static setRegistry(registry) {
746
876
  StateContainer._registry.clearAll();
747
877
  StateContainer._registry = registry;
748
878
  }
879
+ /**
880
+ * Register this class with the global registry
881
+ * @param isolated - Whether instances should be isolated (component-scoped)
882
+ */
749
883
  static register(isolated = false) {
750
884
  StateContainer._registry.register(this, isolated);
751
885
  }
886
+ /**
887
+ * Resolve an instance with ref counting (ownership semantics).
888
+ * Creates a new instance if one doesn't exist, or returns existing and increments ref count.
889
+ * @param instanceKey - Optional instance key (defaults to 'default')
890
+ * @param constructorArgs - Arguments to pass to constructor if creating new instance
891
+ * @returns The state container instance
892
+ */
752
893
  static resolve(instanceKey, constructorArgs) {
753
894
  return StateContainer._registry.resolve(this, instanceKey, constructorArgs);
754
895
  }
896
+ /**
897
+ * Get an existing instance without incrementing ref count (borrowing semantics).
898
+ * @param instanceKey - Optional instance key (defaults to 'default')
899
+ * @returns The state container instance
900
+ * @throws Error if instance doesn't exist
901
+ */
755
902
  static get(instanceKey) {
756
903
  return StateContainer._registry.get(this, instanceKey);
757
904
  }
905
+ /**
906
+ * Safely get an existing instance with error handling.
907
+ * @param instanceKey - Optional instance key (defaults to 'default')
908
+ * @returns Discriminated union with either the instance or an error
909
+ */
758
910
  static getSafe(instanceKey) {
759
911
  return StateContainer._registry.getSafe(this, instanceKey);
760
912
  }
913
+ /**
914
+ * Connect to an instance for bloc-to-bloc communication (borrowing semantics).
915
+ * Gets or creates instance without incrementing ref count.
916
+ * @param instanceKey - Optional instance key (defaults to 'default')
917
+ * @param constructorArgs - Arguments to pass to constructor if creating new instance
918
+ * @returns The state container instance
919
+ */
761
920
  static connect(instanceKey, constructorArgs) {
762
921
  return StateContainer._registry.connect(this, instanceKey, constructorArgs);
763
922
  }
923
+ /**
924
+ * Release a reference to an instance.
925
+ * Decrements ref count and disposes when it reaches 0 (unless keepAlive).
926
+ * @param instanceKey - Optional instance key (defaults to 'default')
927
+ * @param forceDispose - Force immediate disposal regardless of ref count
928
+ */
764
929
  static release(instanceKey, forceDispose = false) {
765
930
  StateContainer._registry.release(this, instanceKey, forceDispose);
766
931
  }
932
+ /**
933
+ * Get all instances of this class
934
+ * @returns Array of all instances
935
+ */
767
936
  static getAll() {
768
937
  return StateContainer._registry.getAll(this);
769
938
  }
939
+ /**
940
+ * Iterate over all instances of this class
941
+ * @param callback - Function to call for each instance
942
+ */
770
943
  static forEach(callback) {
771
944
  StateContainer._registry.forEach(this, callback);
772
945
  }
946
+ /**
947
+ * Clear all instances of this class (disposes them)
948
+ */
773
949
  static clear() {
774
950
  StateContainer._registry.clear(this);
775
951
  }
952
+ /**
953
+ * Clear all instances from all registered types
954
+ */
776
955
  static clearAllInstances() {
777
956
  StateContainer._registry.clearAll();
778
957
  }
958
+ /**
959
+ * Get registry statistics for debugging
960
+ * @returns Object with registeredTypes, totalInstances, and typeBreakdown
961
+ */
779
962
  static getStats() {
780
963
  return StateContainer._registry.getStats();
781
964
  }
965
+ /**
966
+ * Get reference count for an instance
967
+ * @param instanceKey - Optional instance key (defaults to 'default')
968
+ * @returns Current ref count (0 if instance doesn't exist)
969
+ */
782
970
  static getRefCount(instanceKey) {
783
971
  return StateContainer._registry.getRefCount(this, instanceKey);
784
972
  }
973
+ /**
974
+ * Check if an instance exists
975
+ * @param instanceKey - Optional instance key (defaults to 'default')
976
+ * @returns true if instance exists
977
+ */
785
978
  static hasInstance(instanceKey) {
786
979
  return StateContainer._registry.hasInstance(this, instanceKey);
787
980
  }
981
+ /** Current props value passed to this container */
788
982
  get props() {
789
983
  return this._props;
790
984
  }
@@ -812,6 +1006,11 @@ var StateContainer = class StateContainer {
812
1006
  };
813
1007
  this._state = initialState;
814
1008
  }
1009
+ /**
1010
+ * Initialize configuration for this instance.
1011
+ * Called by the registry after construction.
1012
+ * @param config - Configuration options
1013
+ */
815
1014
  initConfig(config) {
816
1015
  this.config = { ...config };
817
1016
  this.name = this.config.name || this.constructor.name;
@@ -819,17 +1018,28 @@ var StateContainer = class StateContainer {
819
1018
  this.instanceId = generateSimpleId(this.constructor.name, this.config.instanceId);
820
1019
  StateContainer._registry.emit("created", this);
821
1020
  }
1021
+ /** Current state value */
822
1022
  get state() {
823
1023
  return this._state;
824
1024
  }
1025
+ /** Whether this instance has been disposed */
825
1026
  get isDisposed() {
826
1027
  return this._disposed;
827
1028
  }
1029
+ /**
1030
+ * Subscribe to state changes
1031
+ * @param listener - Function called when state changes
1032
+ * @returns Unsubscribe function
1033
+ */
828
1034
  subscribe(listener) {
829
1035
  if (this._disposed) throw new Error(`Cannot subscribe to disposed container ${this.name}`);
830
1036
  this.listeners.add(listener);
831
1037
  return () => this.listeners.delete(listener);
832
1038
  }
1039
+ /**
1040
+ * Dispose this instance and clean up resources.
1041
+ * Clears all listeners and emits the 'dispose' system event.
1042
+ */
833
1043
  dispose() {
834
1044
  if (this._disposed) return;
835
1045
  if (this.debug) console.log(`[${this.name}] Disposing...`);
@@ -840,6 +1050,11 @@ var StateContainer = class StateContainer {
840
1050
  StateContainer._registry.emit("disposed", this);
841
1051
  if (this.debug) console.log(`[${this.name}] Disposed successfully`);
842
1052
  }
1053
+ /**
1054
+ * Emit a new state value and notify all listeners.
1055
+ * @param newState - The new state value
1056
+ * @protected
1057
+ */
843
1058
  emit(newState) {
844
1059
  if (this._disposed) throw new Error(`Cannot emit state from disposed container ${this.name}`);
845
1060
  if (this._state === newState) return;
@@ -899,6 +1114,11 @@ var StateContainer = class StateContainer {
899
1114
  if (segments.length > 3) path = segments.slice(-3).join("/");
900
1115
  return path;
901
1116
  }
1117
+ /**
1118
+ * Update state using a transform function.
1119
+ * @param updater - Function that receives current state and returns new state
1120
+ * @protected
1121
+ */
902
1122
  update(updater) {
903
1123
  if (this._disposed) throw new Error(`Cannot update state from disposed container ${this.name}`);
904
1124
  this.emit(updater(this._state));
@@ -912,6 +1132,11 @@ var StateContainer = class StateContainer {
912
1132
  console.error(`[${this.name}] Error in system event handler:`, error$1);
913
1133
  }
914
1134
  }
1135
+ /**
1136
+ * Update the props for this container.
1137
+ * Emits the 'propsUpdated' system event.
1138
+ * @param newProps - The new props value
1139
+ */
915
1140
  updateProps(newProps) {
916
1141
  if (this._disposed) throw new Error(`Cannot update props on disposed container ${this.name}`);
917
1142
  const previousProps = this._props;
@@ -929,6 +1154,13 @@ var StateContainer = class StateContainer {
929
1154
 
930
1155
  //#endregion
931
1156
  //#region src/core/Cubit.ts
1157
+ /**
1158
+ * Simple state container with direct state emission.
1159
+ * Extends StateContainer with public methods for emitting and updating state.
1160
+ *
1161
+ * @template S - State type
1162
+ * @template P - Props type (optional)
1163
+ */
932
1164
  var Cubit = class extends StateContainer {
933
1165
  constructor(initialState) {
934
1166
  super(initialState);
@@ -940,89 +1172,32 @@ var Cubit = class extends StateContainer {
940
1172
  }));
941
1173
  });
942
1174
  }
1175
+ /**
1176
+ * Replace state with a new value and notify all listeners
1177
+ * @param newState - The new state value
1178
+ */
943
1179
  emit(newState) {
944
1180
  super["emit"](newState);
945
1181
  }
1182
+ /**
1183
+ * Transform current state using an updater function and emit the new state
1184
+ * @param updater - Function that receives current state and returns new state
1185
+ */
946
1186
  update(updater) {
947
1187
  super["update"](updater);
948
1188
  }
949
1189
  };
950
- var CounterCubit = class extends Cubit {
951
- constructor() {
952
- super(0);
953
- this.increment = () => {
954
- this.emit(this.state + 1);
955
- };
956
- this.decrement = () => {
957
- this.emit(this.state - 1);
958
- };
959
- this.reset = () => {
960
- this.emit(0);
961
- };
962
- this.addAmount = (amount) => {
963
- this.emit(this.state + amount);
964
- };
965
- }
966
- };
967
- var TodoCubit = class extends Cubit {
968
- static {
969
- this.keepAlive = true;
970
- }
971
- constructor() {
972
- super({
973
- todos: [],
974
- filter: "all",
975
- isLoading: false
976
- });
977
- this.nextId = 0;
978
- this.addTodo = (text) => {
979
- this.update((state) => ({
980
- ...state,
981
- todos: [...state.todos, {
982
- id: `todo-${Date.now()}-${this.nextId++}`,
983
- text,
984
- done: false
985
- }]
986
- }));
987
- };
988
- this.toggleTodo = (id) => {
989
- this.update((state) => ({
990
- ...state,
991
- todos: state.todos.map((todo) => todo.id === id ? {
992
- ...todo,
993
- done: !todo.done
994
- } : todo)
995
- }));
996
- };
997
- this.removeTodo = (id) => {
998
- this.update((state) => ({
999
- ...state,
1000
- todos: state.todos.filter((todo) => todo.id !== id)
1001
- }));
1002
- };
1003
- this.setFilter = (filter) => {
1004
- this.patch({ filter });
1005
- };
1006
- this.setLoading = (isLoading) => {
1007
- this.patch({ isLoading });
1008
- };
1009
- }
1010
- get visibleTodos() {
1011
- const todos = this.state.todos;
1012
- switch (this.state.filter) {
1013
- case "active": return todos.filter((t) => !t.done);
1014
- case "completed": return todos.filter((t) => t.done);
1015
- case "all":
1016
- default: return todos;
1017
- }
1018
- }
1019
- get activeTodoCount() {
1020
- return this.state.todos.filter((t) => !t.done).length;
1021
- }
1022
- };
1023
1190
 
1024
1191
  //#endregion
1025
1192
  //#region src/core/Vertex.ts
1193
+ /**
1194
+ * Event-driven state container that processes events to update state.
1195
+ * Use with event handlers registered via the on() method.
1196
+ *
1197
+ * @template S - State type
1198
+ * @template E - Event type (extends BaseEvent)
1199
+ * @template P - Props type (optional)
1200
+ */
1026
1201
  var Vertex = class extends StateContainer {
1027
1202
  constructor(initialState) {
1028
1203
  super(initialState);
@@ -1076,122 +1251,22 @@ var Vertex = class extends StateContainer {
1076
1251
  this.onEventError(event, error$1);
1077
1252
  }
1078
1253
  }
1254
+ /**
1255
+ * Handle errors that occur during event processing.
1256
+ * Override this method to implement custom error handling.
1257
+ * @param _event - The event that caused the error
1258
+ * @param _error - The error that occurred
1259
+ */
1079
1260
  onEventError(_event, _error) {}
1080
1261
  };
1081
- /**
1082
- * Example: Counter Events
1083
- */
1084
- var IncrementEvent = class {
1085
- constructor(amount = 1) {
1086
- this.amount = amount;
1087
- this.type = "increment";
1088
- this.timestamp = Date.now();
1089
- }
1090
- };
1091
- var DecrementEvent = class {
1092
- constructor(amount = 1) {
1093
- this.amount = amount;
1094
- this.type = "decrement";
1095
- this.timestamp = Date.now();
1096
- }
1097
- };
1098
- var ResetEvent = class {
1099
- constructor() {
1100
- this.type = "reset";
1101
- this.timestamp = Date.now();
1102
- }
1103
- };
1104
- /**
1105
- * Example: Counter Vertex
1106
- * Demonstrates proper typing and event handling
1107
- */
1108
- var CounterVertex = class extends Vertex {
1109
- constructor() {
1110
- super(0);
1111
- this.increment = (amount = 1) => {
1112
- this.add(new IncrementEvent(amount));
1113
- };
1114
- this.decrement = (amount = 1) => {
1115
- this.add(new DecrementEvent(amount));
1116
- };
1117
- this.reset = () => {
1118
- this.add(new ResetEvent());
1119
- };
1120
- this.on(IncrementEvent, (event, emit) => {
1121
- emit(this.state + event.amount);
1122
- });
1123
- this.on(DecrementEvent, (event, emit) => {
1124
- emit(this.state - event.amount);
1125
- });
1126
- this.on(ResetEvent, (_, emit) => {
1127
- emit(0);
1128
- });
1129
- }
1130
- };
1131
- var LoginEvent = class {
1132
- constructor(email, password) {
1133
- this.email = email;
1134
- this.password = password;
1135
- this.type = "login";
1136
- this.timestamp = Date.now();
1137
- }
1138
- };
1139
- var LogoutEvent = class {
1140
- constructor() {
1141
- this.type = "logout";
1142
- this.timestamp = Date.now();
1143
- }
1144
- };
1145
- var AuthVertex = class extends Vertex {
1146
- constructor() {
1147
- super({
1148
- isAuthenticated: false,
1149
- isLoading: false,
1150
- user: null,
1151
- error: null
1152
- });
1153
- this.login = (email, password) => {
1154
- this.add(new LoginEvent(email, password));
1155
- };
1156
- this.logout = () => {
1157
- this.add(new LogoutEvent());
1158
- };
1159
- this.on(LoginEvent, (event, emit) => {
1160
- emit({
1161
- ...this.state,
1162
- isLoading: true,
1163
- error: null
1164
- });
1165
- if (event.email === "user@example.com" && event.password === "password") emit({
1166
- isAuthenticated: true,
1167
- isLoading: false,
1168
- user: {
1169
- id: "123",
1170
- name: "Test User",
1171
- email: "user@example.com"
1172
- },
1173
- error: null
1174
- });
1175
- else emit({
1176
- isAuthenticated: false,
1177
- isLoading: false,
1178
- user: null,
1179
- error: "Invalid credentials"
1180
- });
1181
- });
1182
- this.on(LogoutEvent, (_, emit) => {
1183
- emit({
1184
- isAuthenticated: false,
1185
- isLoading: false,
1186
- user: null,
1187
- error: null
1188
- });
1189
- });
1190
- }
1191
- };
1192
1262
 
1193
1263
  //#endregion
1194
1264
  //#region src/plugin/BlacPlugin.ts
1265
+ /**
1266
+ * Type guard to check if a plugin has a required onInstall hook
1267
+ * @param plugin - The plugin to check
1268
+ * @returns true if the plugin implements BlacPluginWithInit
1269
+ */
1195
1270
  function hasInitHook(plugin) {
1196
1271
  return typeof plugin.onInstall === "function";
1197
1272
  }
@@ -1204,12 +1279,16 @@ function hasInitHook(plugin) {
1204
1279
  * This module provides a functional approach to proxy-based dependency tracking.
1205
1280
  * Unlike the class-based ProxyTracker, this uses a state object pattern that's
1206
1281
  * easier to integrate with functional programming patterns and framework hooks.
1282
+ *
1283
+ * @internal
1207
1284
  */
1208
1285
  /**
1209
1286
  * Check if a value can be proxied
1210
1287
  *
1211
1288
  * Returns true for plain objects and arrays only.
1212
1289
  * Excludes built-in objects like Date, Map, Set, etc.
1290
+ *
1291
+ * @internal
1213
1292
  */
1214
1293
  function isProxyable(value) {
1215
1294
  if (typeof value !== "object" || value === null) return false;
@@ -1225,6 +1304,8 @@ function isProxyable(value) {
1225
1304
  * const proxy = createProxyForTarget(state, myObject);
1226
1305
  * // ... use proxy ...
1227
1306
  * const paths = stopProxyTracking(state);
1307
+ *
1308
+ * @internal
1228
1309
  */
1229
1310
  function createProxyTrackerState() {
1230
1311
  return {
@@ -1241,6 +1322,8 @@ function createProxyTrackerState() {
1241
1322
  * Start tracking property accesses
1242
1323
  *
1243
1324
  * Clears previous tracked paths and enables tracking mode.
1325
+ *
1326
+ * @internal
1244
1327
  */
1245
1328
  function startProxyTracking(state) {
1246
1329
  state.isTracking = true;
@@ -1250,6 +1333,8 @@ function startProxyTracking(state) {
1250
1333
  * Stop tracking and return the tracked paths
1251
1334
  *
1252
1335
  * Returns a new Set containing all tracked paths.
1336
+ *
1337
+ * @internal
1253
1338
  */
1254
1339
  function stopProxyTracking(state) {
1255
1340
  state.isTracking = false;
@@ -1262,6 +1347,8 @@ function stopProxyTracking(state) {
1262
1347
  * - Array element access (arr[0])
1263
1348
  * - Length access (arr.length)
1264
1349
  * - Array method calls (arr.map, arr.filter, etc.)
1350
+ *
1351
+ * @internal
1265
1352
  */
1266
1353
  function createArrayProxy(state, target, path, depth = 0) {
1267
1354
  const proxy = new Proxy(target, { get: (arr, prop) => {
@@ -1306,6 +1393,8 @@ function createArrayProxy(state, target, path, depth = 0) {
1306
1393
  * - Nested property access (obj.nested.prop)
1307
1394
  * - 'in' operator usage ('prop' in obj)
1308
1395
  * - Object.keys, Object.entries, etc.
1396
+ *
1397
+ * @internal
1309
1398
  */
1310
1399
  function createProxyInternal(state, target, path = "", depth = 0) {
1311
1400
  if (!state.isTracking || !isProxyable(target)) return target;
@@ -1353,6 +1442,8 @@ function createProxyInternal(state, target, path = "", depth = 0) {
1353
1442
  * Otherwise, creates a new proxy and caches it.
1354
1443
  *
1355
1444
  * This is the main entry point for creating tracked proxies.
1445
+ *
1446
+ * @internal
1356
1447
  */
1357
1448
  function createProxyForTarget(state, target) {
1358
1449
  if (state.lastProxiedState === target && state.lastProxy) return state.lastProxy;
@@ -1371,16 +1462,22 @@ function createProxyForTarget(state, target) {
1371
1462
  *
1372
1463
  * Provides utilities for parsing property paths and extracting values
1373
1464
  * from nested objects using path strings.
1465
+ *
1466
+ * @internal
1374
1467
  */
1375
1468
  /**
1376
1469
  * Parse a property path string into an array of segments
1377
1470
  *
1471
+ * @internal
1472
+ *
1378
1473
  * Handles both dot notation (a.b.c) and bracket notation (a[0].b)
1379
1474
  *
1380
1475
  * @example
1476
+ * ```ts
1381
1477
  * parsePath('user.name') // ['user', 'name']
1382
1478
  * parsePath('items[0].name') // ['items', '0', 'name']
1383
1479
  * parsePath('data.users[2].address.city') // ['data', 'users', '2', 'address', 'city']
1480
+ * ```
1384
1481
  */
1385
1482
  function parsePath(path) {
1386
1483
  const segments = [];
@@ -1408,10 +1505,14 @@ function parsePath(path) {
1408
1505
  * Get a value from an object using a path of segments
1409
1506
  *
1410
1507
  * @example
1508
+ * ```ts
1411
1509
  * const obj = { user: { name: 'Alice', age: 30 } }
1412
1510
  * getValueAtPath(obj, ['user', 'name']) // 'Alice'
1413
1511
  * getValueAtPath(obj, ['user', 'age']) // 30
1414
1512
  * getValueAtPath(obj, ['user', 'missing']) // undefined
1513
+ * ```
1514
+ *
1515
+ * @internal
1415
1516
  */
1416
1517
  function getValueAtPath(obj, segments) {
1417
1518
  if (obj == null) return void 0;
@@ -1428,9 +1529,13 @@ function getValueAtPath(obj, segments) {
1428
1529
  * Compares two arrays element-by-element using Object.is
1429
1530
  *
1430
1531
  * @example
1532
+ * ```ts
1431
1533
  * shallowEqual([1, 2, 3], [1, 2, 3]) // true
1432
1534
  * shallowEqual([1, 2, 3], [1, 2, 4]) // false
1433
1535
  * shallowEqual([1, 2], [1, 2, 3]) // false
1536
+ * ```
1537
+ *
1538
+ * @internal
1434
1539
  */
1435
1540
  function shallowEqual(arr1, arr2) {
1436
1541
  if (arr1.length !== arr2.length) return false;
@@ -1458,6 +1563,9 @@ function getArrayParentPath(path) {
1458
1563
  if (arrayIndexMatch) return arrayIndexMatch[1];
1459
1564
  return null;
1460
1565
  }
1566
+ /**
1567
+ * @internal
1568
+ */
1461
1569
  function optimizeTrackedPaths(paths) {
1462
1570
  if (paths.size === 0) return /* @__PURE__ */ new Set();
1463
1571
  if (paths.size === 1) return new Set(paths);
@@ -1479,6 +1587,9 @@ function optimizeTrackedPaths(paths) {
1479
1587
  for (const arrayParent of arrayParents) optimized.add(arrayParent);
1480
1588
  return optimized;
1481
1589
  }
1590
+ /**
1591
+ * @internal
1592
+ */
1482
1593
  function createTrackerState() {
1483
1594
  return {
1484
1595
  proxyTrackerState: createProxyTrackerState(),
@@ -1489,12 +1600,21 @@ function createTrackerState() {
1489
1600
  lastCheckedValues: /* @__PURE__ */ new Map()
1490
1601
  };
1491
1602
  }
1603
+ /**
1604
+ * @internal
1605
+ */
1492
1606
  function startTracking(tracker) {
1493
1607
  startProxyTracking(tracker.proxyTrackerState);
1494
1608
  }
1609
+ /**
1610
+ * @internal
1611
+ */
1495
1612
  function createProxy(tracker, state) {
1496
1613
  return createProxyForTarget(tracker.proxyTrackerState, state);
1497
1614
  }
1615
+ /**
1616
+ * @internal
1617
+ */
1498
1618
  function captureTrackedPaths(tracker, state) {
1499
1619
  tracker.previousRenderPaths = tracker.currentRenderPaths;
1500
1620
  tracker.currentRenderPaths = optimizeTrackedPaths(stopProxyTracking(tracker.proxyTrackerState));
@@ -1515,6 +1635,9 @@ function captureTrackedPaths(tracker, state) {
1515
1635
  }
1516
1636
  tracker.lastCheckedValues.clear();
1517
1637
  }
1638
+ /**
1639
+ * @internal
1640
+ */
1518
1641
  function hasChanges(tracker, state) {
1519
1642
  if (tracker.pathCache.size === 0) return true;
1520
1643
  tracker.lastCheckedValues.clear();
@@ -1529,12 +1652,20 @@ function hasChanges(tracker, state) {
1529
1652
  tracker.lastCheckedState = state;
1530
1653
  return false;
1531
1654
  }
1655
+ /**
1656
+ * @internal
1657
+ */
1532
1658
  function hasTrackedData(tracker) {
1533
1659
  return tracker.proxyTrackerState.trackedPaths.size > 0 || tracker.pathCache.size > 0 || tracker.previousRenderPaths.size > 0;
1534
1660
  }
1535
1661
 
1536
1662
  //#endregion
1537
1663
  //#region src/adapter/framework-adapter.ts
1664
+ /**
1665
+ * Manages subscriptions to external bloc dependencies for getter tracking.
1666
+ * When a getter accesses another bloc's state, this manager ensures
1667
+ * re-renders occur when those external dependencies change.
1668
+ */
1538
1669
  var ExternalDependencyManager = class {
1539
1670
  constructor() {
1540
1671
  this.subscriptions = [];
@@ -1545,6 +1676,14 @@ var ExternalDependencyManager = class {
1545
1676
  for (const dep of newDeps) if (!oldDeps.has(dep)) return false;
1546
1677
  return true;
1547
1678
  }
1679
+ /**
1680
+ * Update subscriptions to external bloc dependencies.
1681
+ * Creates subscriptions to blocs accessed via getters.
1682
+ * @param getterTracker - The getter tracker state with external dependencies
1683
+ * @param rawInstance - The primary bloc instance (excluded from subscriptions)
1684
+ * @param onGetterChange - Callback to invoke when external dependency changes
1685
+ * @returns true if subscriptions were updated, false if unchanged
1686
+ */
1548
1687
  updateSubscriptions(getterTracker, rawInstance, onGetterChange) {
1549
1688
  if (!getterTracker?.externalDependencies) return false;
1550
1689
  const currentDeps = getterTracker.externalDependencies;
@@ -1565,11 +1704,21 @@ var ExternalDependencyManager = class {
1565
1704
  clearExternalDependencies(getterTracker);
1566
1705
  return true;
1567
1706
  }
1707
+ /**
1708
+ * Clean up all active subscriptions
1709
+ */
1568
1710
  cleanup() {
1569
1711
  this.subscriptions.forEach((unsub) => unsub());
1570
1712
  this.subscriptions = [];
1571
1713
  }
1572
1714
  };
1715
+ /**
1716
+ * Create a subscribe function for auto-tracking mode.
1717
+ * Only triggers callback when tracked properties change.
1718
+ * @param instance - The state container instance
1719
+ * @param adapterState - The adapter state for tracking
1720
+ * @returns Subscribe function for use with useSyncExternalStore
1721
+ */
1573
1722
  function createAutoTrackSubscribe(instance, adapterState) {
1574
1723
  return (callback) => {
1575
1724
  return instance.subscribe(() => {
@@ -1588,6 +1737,14 @@ function createAutoTrackSubscribe(instance, adapterState) {
1588
1737
  });
1589
1738
  };
1590
1739
  }
1740
+ /**
1741
+ * Create a subscribe function for manual dependency tracking mode.
1742
+ * Only triggers callback when dependencies array changes.
1743
+ * @param instance - The state container instance
1744
+ * @param adapterState - The adapter state for caching
1745
+ * @param config - Configuration with dependencies function
1746
+ * @returns Subscribe function for use with useSyncExternalStore
1747
+ */
1591
1748
  function createManualDepsSubscribe(instance, adapterState, config) {
1592
1749
  return (callback) => {
1593
1750
  return instance.subscribe(() => {
@@ -1599,9 +1756,22 @@ function createManualDepsSubscribe(instance, adapterState, config) {
1599
1756
  });
1600
1757
  };
1601
1758
  }
1759
+ /**
1760
+ * Create a subscribe function for no-tracking mode.
1761
+ * Triggers callback on every state change.
1762
+ * @param instance - The state container instance
1763
+ * @returns Subscribe function for use with useSyncExternalStore
1764
+ */
1602
1765
  function createNoTrackSubscribe(instance) {
1603
1766
  return (callback) => instance.subscribe(callback);
1604
1767
  }
1768
+ /**
1769
+ * Create a snapshot function for auto-tracking mode.
1770
+ * Returns a proxied state that tracks property access.
1771
+ * @param instance - The state container instance
1772
+ * @param adapterState - The adapter state for tracking
1773
+ * @returns Snapshot function for use with useSyncExternalStore
1774
+ */
1605
1775
  function createAutoTrackSnapshot(instance, adapterState) {
1606
1776
  return () => {
1607
1777
  const tracker = adapterState.tracker || (adapterState.tracker = createTrackerState());
@@ -1616,15 +1786,35 @@ function createAutoTrackSnapshot(instance, adapterState) {
1616
1786
  return createProxy(tracker, instance.state);
1617
1787
  };
1618
1788
  }
1789
+ /**
1790
+ * Create a snapshot function for manual dependency tracking mode.
1791
+ * Caches dependencies for comparison on next render.
1792
+ * @param instance - The state container instance
1793
+ * @param adapterState - The adapter state for caching
1794
+ * @param config - Configuration with dependencies function
1795
+ * @returns Snapshot function for use with useSyncExternalStore
1796
+ */
1619
1797
  function createManualDepsSnapshot(instance, adapterState, config) {
1620
1798
  return () => {
1621
1799
  adapterState.manualDepsCache = config.dependencies(instance.state, instance);
1622
1800
  return instance.state;
1623
1801
  };
1624
1802
  }
1803
+ /**
1804
+ * Create a snapshot function for no-tracking mode.
1805
+ * Returns the raw state directly.
1806
+ * @param instance - The state container instance
1807
+ * @returns Snapshot function for use with useSyncExternalStore
1808
+ */
1625
1809
  function createNoTrackSnapshot(instance) {
1626
1810
  return () => instance.state;
1627
1811
  }
1812
+ /**
1813
+ * Initialize adapter state for auto-tracking mode.
1814
+ * Creates getter tracker and proxied bloc instance.
1815
+ * @param instance - The state container instance
1816
+ * @returns Initialized adapter state
1817
+ */
1628
1818
  function initAutoTrackState(instance) {
1629
1819
  return {
1630
1820
  tracker: null,
@@ -1633,6 +1823,12 @@ function initAutoTrackState(instance) {
1633
1823
  proxiedBloc: createBlocProxy(instance)
1634
1824
  };
1635
1825
  }
1826
+ /**
1827
+ * Initialize adapter state for manual dependency tracking mode.
1828
+ * No proxy is created; bloc is used directly.
1829
+ * @param instance - The state container instance
1830
+ * @returns Initialized adapter state
1831
+ */
1636
1832
  function initManualDepsState(instance) {
1637
1833
  return {
1638
1834
  tracker: null,
@@ -1641,6 +1837,12 @@ function initManualDepsState(instance) {
1641
1837
  proxiedBloc: instance
1642
1838
  };
1643
1839
  }
1840
+ /**
1841
+ * Initialize adapter state for no-tracking mode.
1842
+ * No tracking or proxy is created.
1843
+ * @param instance - The state container instance
1844
+ * @returns Initialized adapter state
1845
+ */
1644
1846
  function initNoTrackState(instance) {
1645
1847
  return {
1646
1848
  tracker: null,
@@ -1649,6 +1851,12 @@ function initNoTrackState(instance) {
1649
1851
  proxiedBloc: instance
1650
1852
  };
1651
1853
  }
1854
+ /**
1855
+ * Disable getter tracking after render phase completes.
1856
+ * Clears the active tracker to prevent tracking outside of render.
1857
+ * @param adapterState - The adapter state
1858
+ * @param rawInstance - The raw bloc instance
1859
+ */
1652
1860
  function disableGetterTracking(adapterState, rawInstance) {
1653
1861
  if (adapterState.getterTracker) {
1654
1862
  adapterState.getterTracker.isTracking = false;
@@ -1658,10 +1866,17 @@ function disableGetterTracking(adapterState, rawInstance) {
1658
1866
 
1659
1867
  //#endregion
1660
1868
  //#region src/logging/Logger.ts
1869
+ /**
1870
+ * Log severity levels (lower number = higher severity)
1871
+ */
1661
1872
  let LogLevel = /* @__PURE__ */ function(LogLevel$1) {
1873
+ /** Critical errors that may cause application failure */
1662
1874
  LogLevel$1[LogLevel$1["ERROR"] = 0] = "ERROR";
1875
+ /** Warning conditions that should be addressed */
1663
1876
  LogLevel$1[LogLevel$1["WARN"] = 1] = "WARN";
1877
+ /** Informational messages about application state */
1664
1878
  LogLevel$1[LogLevel$1["INFO"] = 2] = "INFO";
1879
+ /** Detailed debugging information */
1665
1880
  LogLevel$1[LogLevel$1["DEBUG"] = 3] = "DEBUG";
1666
1881
  return LogLevel$1;
1667
1882
  }({});
@@ -1730,9 +1945,33 @@ let currentConfig = {
1730
1945
  output: (entry) => console.log(JSON.stringify(entry))
1731
1946
  };
1732
1947
  let defaultLogger = createLogger(currentConfig);
1948
+ /**
1949
+ * Log a debug message (tree-shakeable export)
1950
+ * @param context - Context identifier (module or component name)
1951
+ * @param message - Log message
1952
+ * @param data - Optional structured data
1953
+ */
1733
1954
  const debug = (context, message, data) => defaultLogger.debug(context, message, data);
1955
+ /**
1956
+ * Log an info message (tree-shakeable export)
1957
+ * @param context - Context identifier (module or component name)
1958
+ * @param message - Log message
1959
+ * @param data - Optional structured data
1960
+ */
1734
1961
  const info = (context, message, data) => defaultLogger.info(context, message, data);
1962
+ /**
1963
+ * Log a warning message (tree-shakeable export)
1964
+ * @param context - Context identifier (module or component name)
1965
+ * @param message - Log message
1966
+ * @param data - Optional structured data
1967
+ */
1735
1968
  const warn = (context, message, data) => defaultLogger.warn(context, message, data);
1969
+ /**
1970
+ * Log an error message (tree-shakeable export)
1971
+ * @param context - Context identifier (module or component name)
1972
+ * @param message - Log message
1973
+ * @param data - Optional structured data
1974
+ */
1736
1975
  const error = (context, message, data) => defaultLogger.error(context, message, data);
1737
1976
  /**
1738
1977
  * Configuration function that recreates the default logger
@@ -1758,7 +1997,7 @@ function configureLogger(opts) {
1758
1997
  * Decorator to configure StateContainer classes.
1759
1998
  *
1760
1999
  * @example Decorator syntax (requires experimentalDecorators or TC39 decorators)
1761
- * ```typescript
2000
+ * ```ts
1762
2001
  * @blac({ isolated: true })
1763
2002
  * class FormBloc extends Cubit<FormState> {}
1764
2003
  *
@@ -1770,7 +2009,7 @@ function configureLogger(opts) {
1770
2009
  * ```
1771
2010
  *
1772
2011
  * @example Function syntax (no decorator support needed)
1773
- * ```typescript
2012
+ * ```ts
1774
2013
  * const FormBloc = blac({ isolated: true })(
1775
2014
  * class extends Cubit<FormState> {}
1776
2015
  * );
@@ -1786,5 +2025,5 @@ function blac(options) {
1786
2025
  }
1787
2026
 
1788
2027
  //#endregion
1789
- export { AuthVertex, BLAC_DEFAULTS, BLAC_ERROR_PREFIX, BLAC_ID_PATTERNS, BLAC_STATIC_PROPS, CounterCubit, CounterVertex, Cubit, DecrementEvent, ExternalDependencyManager, IncrementEvent, LogLevel, LoginEvent, LogoutEvent, PluginManager, ResetEvent, StateContainer, StateContainerRegistry, TodoCubit, Vertex, __resetIdCounters, blac, captureTrackedPaths, clearActiveTracker, clearExternalDependencies, commitTrackedGetters, configureLogger, createArrayProxy, createAutoTrackSnapshot, createAutoTrackSubscribe, createBlocProxy, createGetterTracker, createIdGenerator, createLogger, createManualDepsSnapshot, createManualDepsSubscribe, createNoTrackSnapshot, createNoTrackSubscribe, createPluginManager, createProxy, createProxyForTarget, createProxyInternal, createProxyTrackerState, createTrackerState, debug, disableGetterTracking, error, generateId, generateIsolatedKey, generateSimpleId, getActiveTracker, getDescriptor, getGetterExecutionContext, getPluginManager, getStaticProp, getValueAtPath, globalRegistry, hasChanges, hasGetterChanges, hasInitHook, hasTrackedData, info, initAutoTrackState, initManualDepsState, initNoTrackState, invalidateRenderCache, isExcludedFromDevTools, isGetter, isIsolatedClass, isIsolatedKey, isKeepAliveClass, isProxyable, parsePath, resetGetterTracker, setActiveTracker, shallowEqual, startProxyTracking, startTracking, stopProxyTracking, warn };
2028
+ export { BLAC_DEFAULTS, BLAC_ERROR_PREFIX, BLAC_ID_PATTERNS, BLAC_STATIC_PROPS, Cubit, ExternalDependencyManager, LogLevel, PluginManager, StateContainer, StateContainerRegistry, Vertex, __resetIdCounters, blac, captureTrackedPaths, clearActiveTracker, clearExternalDependencies, commitTrackedGetters, configureLogger, createArrayProxy, createAutoTrackSnapshot, createAutoTrackSubscribe, createBlocProxy, createGetterTracker, createIdGenerator, createLogger, createManualDepsSnapshot, createManualDepsSubscribe, createNoTrackSnapshot, createNoTrackSubscribe, createPluginManager, createProxy, createProxyForTarget, createProxyInternal, createProxyTrackerState, createTrackerState, debug, disableGetterTracking, error, generateId, generateIsolatedKey, generateSimpleId, getActiveTracker, getDescriptor, getGetterExecutionContext, getPluginManager, getStaticProp, getValueAtPath, globalRegistry, hasChanges, hasGetterChanges, hasInitHook, hasTrackedData, info, initAutoTrackState, initManualDepsState, initNoTrackState, invalidateRenderCache, isExcludedFromDevTools, isGetter, isIsolatedClass, isIsolatedKey, isKeepAliveClass, isProxyable, parsePath, resetGetterTracker, setActiveTracker, shallowEqual, startProxyTracking, startTracking, stopProxyTracking, warn };
1790
2029
  //# sourceMappingURL=index.js.map