@blac/core 2.0.10 → 2.0.12

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 (203) hide show
  1. package/README.md +59 -83
  2. package/dist/Cubit-9jal5zdZ.cjs +390 -0
  3. package/dist/Cubit-9jal5zdZ.cjs.map +1 -0
  4. package/dist/Cubit-BAUPiUF7.cjs +307 -0
  5. package/dist/Cubit-BAUPiUF7.cjs.map +1 -0
  6. package/dist/Cubit-BOgUZva7.js +284 -0
  7. package/dist/Cubit-BOgUZva7.js.map +1 -0
  8. package/dist/Cubit-BTznt8zg.js +370 -0
  9. package/dist/Cubit-BTznt8zg.js.map +1 -0
  10. package/dist/Cubit-CZaf_fp4.cjs +367 -292
  11. package/dist/Cubit-C_dUEUdd.cjs +307 -0
  12. package/dist/Cubit-C_dUEUdd.cjs.map +1 -0
  13. package/dist/Cubit-D2vQ6nMb.js +284 -0
  14. package/dist/Cubit-D2vQ6nMb.js.map +1 -0
  15. package/dist/Cubit-D7jOZCoZ.js +284 -0
  16. package/dist/Cubit-D7jOZCoZ.js.map +1 -0
  17. package/dist/Cubit-DP5DXPUK.js +284 -0
  18. package/dist/Cubit-DP5DXPUK.js.map +1 -0
  19. package/dist/Cubit-DbnhTUaZ.cjs +307 -0
  20. package/dist/Cubit-DbnhTUaZ.cjs.map +1 -0
  21. package/dist/Cubit-Dw_kFBgc.js +372 -0
  22. package/dist/Cubit-Dw_kFBgc.js.map +1 -0
  23. package/dist/Cubit-KiXZCubP.cjs +392 -0
  24. package/dist/Cubit-KiXZCubP.cjs.map +1 -0
  25. package/dist/Cubit-Ksj7G4uR.js +284 -0
  26. package/dist/Cubit-Ksj7G4uR.js.map +1 -0
  27. package/dist/Cubit-MkjbpcPf.cjs +307 -0
  28. package/dist/Cubit-MkjbpcPf.cjs.map +1 -0
  29. package/dist/Cubit-PMTXxI_u.js +350 -272
  30. package/dist/Cubit-kU5_4jgC.cjs +307 -0
  31. package/dist/Cubit-kU5_4jgC.cjs.map +1 -0
  32. package/dist/StateContainerRegistry-BhcnG0DF.js +602 -0
  33. package/dist/StateContainerRegistry-BhcnG0DF.js.map +1 -0
  34. package/dist/StateContainerRegistry-BsMIpllP.cjs +612 -560
  35. package/dist/StateContainerRegistry-Ck2-XmT_.js +567 -0
  36. package/dist/StateContainerRegistry-Ck2-XmT_.js.map +1 -0
  37. package/dist/StateContainerRegistry-DC4N73O6.js +609 -0
  38. package/dist/StateContainerRegistry-DC4N73O6.js.map +1 -0
  39. package/dist/StateContainerRegistry-DOkDGng-.js +586 -526
  40. package/dist/StateContainerRegistry-DOuGI-l5.js +622 -0
  41. package/dist/StateContainerRegistry-DOuGI-l5.js.map +1 -0
  42. package/dist/StateContainerRegistry-DT66lr3I.cjs +643 -0
  43. package/dist/StateContainerRegistry-DT66lr3I.cjs.map +1 -0
  44. package/dist/StateContainerRegistry-Yph6UCA_.js +610 -0
  45. package/dist/StateContainerRegistry-Yph6UCA_.js.map +1 -0
  46. package/dist/StateContainerRegistry-mseeTqSA.cjs +663 -0
  47. package/dist/StateContainerRegistry-mseeTqSA.cjs.map +1 -0
  48. package/dist/StateContainerRegistry-pRNxHNFD.cjs +650 -0
  49. package/dist/StateContainerRegistry-pRNxHNFD.cjs.map +1 -0
  50. package/dist/StateContainerRegistry-vXMWtG7J.cjs +608 -0
  51. package/dist/StateContainerRegistry-vXMWtG7J.cjs.map +1 -0
  52. package/dist/StateContainerRegistry-v_prqMcI.cjs +651 -0
  53. package/dist/StateContainerRegistry-v_prqMcI.cjs.map +1 -0
  54. package/dist/branded-BSeA_mZO.cjs +18 -0
  55. package/dist/branded-BSeA_mZO.cjs.map +1 -0
  56. package/dist/branded-DwtzSsg0.js +13 -0
  57. package/dist/branded-DwtzSsg0.js.map +1 -0
  58. package/dist/config-BKoaAlmb.js +16 -0
  59. package/dist/config-BKoaAlmb.js.map +1 -0
  60. package/dist/config-CCUhIYIF.js +16 -0
  61. package/dist/config-CCUhIYIF.js.map +1 -0
  62. package/dist/config-CR_Bz7RD.js +16 -0
  63. package/dist/config-CR_Bz7RD.js.map +1 -0
  64. package/dist/config-CTOa-yPN.cjs +32 -0
  65. package/dist/config-CTOa-yPN.cjs.map +1 -0
  66. package/dist/config-D3jisfdj.cjs +32 -0
  67. package/dist/config-D3jisfdj.cjs.map +1 -0
  68. package/dist/config-D4GifZQ4.js +16 -0
  69. package/dist/config-D4GifZQ4.js.map +1 -0
  70. package/dist/config-DDrSQGpQ.cjs +32 -0
  71. package/dist/config-DDrSQGpQ.cjs.map +1 -0
  72. package/dist/config-DLzmy2rZ.cjs +20 -20
  73. package/dist/config-DMNZ2YLV.cjs +32 -0
  74. package/dist/config-DMNZ2YLV.cjs.map +1 -0
  75. package/dist/config-DokTzpr8.cjs +32 -0
  76. package/dist/config-DokTzpr8.cjs.map +1 -0
  77. package/dist/config-DslYBm4Z.js +16 -0
  78. package/dist/config-DslYBm4Z.js.map +1 -0
  79. package/dist/config-XQua95Xz.js +5 -5
  80. package/dist/core/StateContainer.d.ts +1 -1
  81. package/dist/core/StateContainerRegistry.d.ts +29 -17
  82. package/dist/debug.cjs +4 -3
  83. package/dist/debug.d.cts +5 -6
  84. package/dist/debug.d.ts +5 -6
  85. package/dist/debug.js +4 -4
  86. package/dist/ensure-9VEq5H0L.js +9 -0
  87. package/dist/ensure-9VEq5H0L.js.map +1 -0
  88. package/dist/ensure-BNDfTzqg.cjs +14 -0
  89. package/dist/ensure-BNDfTzqg.cjs.map +1 -0
  90. package/dist/ensure-BVCnjU7r.js +289 -0
  91. package/dist/ensure-BVCnjU7r.js.map +1 -0
  92. package/dist/ensure-BbzGXjep.cjs +14 -0
  93. package/dist/ensure-BbzGXjep.cjs.map +1 -0
  94. package/dist/ensure-C5I1xp2C.js +3 -3
  95. package/dist/ensure-CJZL7bcA.cjs +318 -0
  96. package/dist/ensure-CJZL7bcA.cjs.map +1 -0
  97. package/dist/ensure-CSHYjIeH.cjs +8 -8
  98. package/dist/ensure-CU-B1ywv.js +9 -0
  99. package/dist/ensure-CU-B1ywv.js.map +1 -0
  100. package/dist/ensure-D63lEMUK.cjs +14 -0
  101. package/dist/ensure-D63lEMUK.cjs.map +1 -0
  102. package/dist/ensure-DamKOP6q.cjs +14 -0
  103. package/dist/ensure-DamKOP6q.cjs.map +1 -0
  104. package/dist/ensure-Def-EBWG.js +9 -0
  105. package/dist/ensure-Def-EBWG.js.map +1 -0
  106. package/dist/ensure-Sb92MCXu.js +9 -0
  107. package/dist/ensure-Sb92MCXu.js.map +1 -0
  108. package/dist/ensure-n80crSlX.js +9 -0
  109. package/dist/ensure-n80crSlX.js.map +1 -0
  110. package/dist/ensure-vS71MV4q.cjs +14 -0
  111. package/dist/ensure-vS71MV4q.cjs.map +1 -0
  112. package/dist/index.cjs +12 -10
  113. package/dist/index.cjs.map +1 -1
  114. package/dist/index.d.cts +1 -1
  115. package/dist/index.d.ts +1 -1
  116. package/dist/index.js +12 -11
  117. package/dist/index.js.map +1 -1
  118. package/dist/management-Bg652agq.js +32 -0
  119. package/dist/management-Bg652agq.js.map +1 -0
  120. package/dist/management-C-wBdpho.js +18 -10
  121. package/dist/management-CU_V3LIP.js +32 -0
  122. package/dist/management-CU_V3LIP.js.map +1 -0
  123. package/dist/management-CaqiyNzB.js +32 -0
  124. package/dist/management-CaqiyNzB.js.map +1 -0
  125. package/dist/management-Cin-JvYe.js +32 -0
  126. package/dist/management-Cin-JvYe.js.map +1 -0
  127. package/dist/management-ClaXym0F.cjs +79 -0
  128. package/dist/management-ClaXym0F.cjs.map +1 -0
  129. package/dist/management-Dag9u4t6.cjs +79 -0
  130. package/dist/management-Dag9u4t6.cjs.map +1 -0
  131. package/dist/management-DbMRdDBo.cjs +79 -0
  132. package/dist/management-DbMRdDBo.cjs.map +1 -0
  133. package/dist/management-ZU2YzOkr.js +29 -0
  134. package/dist/management-ZU2YzOkr.js.map +1 -0
  135. package/dist/management-baPDwA9n.cjs +79 -0
  136. package/dist/management-baPDwA9n.cjs.map +1 -0
  137. package/dist/management-jQGCvZNN.cjs +70 -0
  138. package/dist/management-jQGCvZNN.cjs.map +1 -0
  139. package/dist/management-xoZ7w3bI.cjs +44 -44
  140. package/dist/plugin/BlacPlugin.d.ts +15 -0
  141. package/dist/plugins.cjs +1 -1
  142. package/dist/plugins.js +1 -1
  143. package/dist/registry/acquire.d.ts +1 -1
  144. package/dist/registry/index.d.ts +1 -1
  145. package/dist/registry/queries.d.ts +1 -0
  146. package/dist/registry/release.d.ts +1 -1
  147. package/dist/resolve-dependencies-BA3u06uC.js +643 -561
  148. package/dist/resolve-dependencies-BFZQq60Y.cjs +774 -0
  149. package/dist/resolve-dependencies-BFZQq60Y.cjs.map +1 -0
  150. package/dist/resolve-dependencies-BGafS3Ww.js +649 -0
  151. package/dist/resolve-dependencies-BGafS3Ww.js.map +1 -0
  152. package/dist/resolve-dependencies-BHd34gS3.cjs +774 -0
  153. package/dist/resolve-dependencies-BHd34gS3.cjs.map +1 -0
  154. package/dist/resolve-dependencies-BT6TU2HF.cjs +724 -666
  155. package/dist/resolve-dependencies-BiWkW2eS.js +649 -0
  156. package/dist/resolve-dependencies-BiWkW2eS.js.map +1 -0
  157. package/dist/resolve-dependencies-CTzV1txG.js +649 -0
  158. package/dist/resolve-dependencies-CTzV1txG.js.map +1 -0
  159. package/dist/resolve-dependencies-D0vTzZgs.js +649 -0
  160. package/dist/resolve-dependencies-D0vTzZgs.js.map +1 -0
  161. package/dist/resolve-dependencies-D2WnZMF-.cjs +774 -0
  162. package/dist/resolve-dependencies-D2WnZMF-.cjs.map +1 -0
  163. package/dist/resolve-dependencies-DSQNXvnV.cjs +774 -0
  164. package/dist/resolve-dependencies-DSQNXvnV.cjs.map +1 -0
  165. package/dist/resolve-dependencies-DcUUva2P.cjs +774 -0
  166. package/dist/resolve-dependencies-DcUUva2P.cjs.map +1 -0
  167. package/dist/resolve-dependencies-f-QUqYiL.js +649 -0
  168. package/dist/resolve-dependencies-f-QUqYiL.js.map +1 -0
  169. package/dist/testing.cjs +5 -5
  170. package/dist/testing.cjs.map +1 -1
  171. package/dist/testing.js +5 -5
  172. package/dist/testing.js.map +1 -1
  173. package/dist/tracked-B77j2g9M.js +177 -0
  174. package/dist/tracked-B77j2g9M.js.map +1 -0
  175. package/dist/tracked-BDVi2LKM.cjs +206 -0
  176. package/dist/tracked-BDVi2LKM.cjs.map +1 -0
  177. package/dist/tracked-BH-gX4T1.cjs +206 -0
  178. package/dist/tracked-BH-gX4T1.cjs.map +1 -0
  179. package/dist/tracked-BTHok3Dl.cjs +206 -0
  180. package/dist/tracked-BTHok3Dl.cjs.map +1 -0
  181. package/dist/tracked-CoAlC8fs.js +177 -0
  182. package/dist/tracked-CoAlC8fs.js.map +1 -0
  183. package/dist/tracked-DBn-bs_G.js +177 -0
  184. package/dist/tracked-DBn-bs_G.js.map +1 -0
  185. package/dist/tracked-DCfBaYjL.cjs +196 -175
  186. package/dist/tracked-DKduNLgI.js +171 -151
  187. package/dist/tracked-DMBTDF0P.js +177 -0
  188. package/dist/tracked-DMBTDF0P.js.map +1 -0
  189. package/dist/tracked-Dcu6EATB.js +177 -0
  190. package/dist/tracked-Dcu6EATB.js.map +1 -0
  191. package/dist/tracked-GvAJQVAI.cjs +240 -0
  192. package/dist/tracked-GvAJQVAI.cjs.map +1 -0
  193. package/dist/tracked-WF6aXuAo.js +199 -0
  194. package/dist/tracked-WF6aXuAo.js.map +1 -0
  195. package/dist/tracked-d_sQWU3c.cjs +206 -0
  196. package/dist/tracked-d_sQWU3c.cjs.map +1 -0
  197. package/dist/tracked-n9TMK-30.cjs +206 -0
  198. package/dist/tracked-n9TMK-30.cjs.map +1 -0
  199. package/dist/tracking.cjs +1 -1
  200. package/dist/tracking.js +1 -1
  201. package/dist/watch-entry.cjs +1 -1
  202. package/dist/watch-entry.js +1 -1
  203. package/package.json +1 -1
package/README.md CHANGED
@@ -1,76 +1,68 @@
1
1
  # @blac/core
2
2
 
3
- Core state management primitives for BlaC: state containers, registry, plugins, and tracking utilities.
3
+ Core state management primitives for BlaC — state containers, registry, plugins, and tracking utilities.
4
4
 
5
- **[Full documentation](https://jsnanigans.github.io/blac/guide/introduction)**
5
+ **[Documentation](https://blac-docs.pages.dev/guide/introduction)** · **[npm](https://www.npmjs.com/package/@blac/core)**
6
6
 
7
7
  ## Installation
8
8
 
9
9
  ```bash
10
- npm install @blac/core
11
- # or
12
10
  pnpm add @blac/core
13
- # or
14
- yarn add @blac/core
15
11
  ```
16
12
 
17
- ## Core Concepts
13
+ ## State Containers
18
14
 
19
- ### StateContainer
15
+ ### Cubit
20
16
 
21
- `StateContainer` is the abstract base class. It provides state storage, subscriptions, lifecycle events, and registry integration.
17
+ The primary building block. Extends `StateContainer` with public `emit`, `update`, and `patch` methods.
22
18
 
23
19
  ```ts
24
- import { StateContainer } from '@blac/core';
20
+ import { Cubit } from '@blac/core';
25
21
 
26
- class CounterContainer extends StateContainer<{ count: number }> {
22
+ class CounterCubit extends Cubit<{ count: number }> {
27
23
  constructor() {
28
24
  super({ count: 0 });
29
25
  }
30
26
 
31
- increment() {
32
- this.update((state) => ({ count: state.count + 1 }));
33
- }
27
+ increment = () => this.emit({ count: this.state.count + 1 });
28
+ decrement = () => this.update((s) => ({ count: s.count - 1 }));
29
+ reset = () => this.patch({ count: 0 });
34
30
  }
35
31
  ```
36
32
 
37
- Key public API:
38
-
39
- - `state` (readonly)
40
- - `subscribe(listener)` -> `unsubscribe`
41
- - `dispose()`
42
- - `isDisposed`, `name`, `debug`, `instanceId`, `createdAt`, `lastUpdateTimestamp`
33
+ - `emit(newState)` — replace the entire state
34
+ - `update(fn)` — derive new state from current
35
+ - `patch(partial)` — shallow merge (object state only)
43
36
 
44
- Protected API for subclasses:
45
-
46
- - `emit(newState)`
47
- - `update(fn)`
48
- - `onSystemEvent(event, handler)` for `stateChanged` and `dispose`
49
- - `depend(BlocClass, instanceKey?)` for cross-bloc dependencies
50
-
51
- ### Cubit
37
+ ### StateContainer
52
38
 
53
- `Cubit` extends `StateContainer` with public mutation methods.
39
+ Abstract base class. Use this when you want `emit`/`update` to be protected (not callable from outside).
54
40
 
55
41
  ```ts
56
- import { Cubit } from '@blac/core';
42
+ import { StateContainer } from '@blac/core';
57
43
 
58
- class CounterCubit extends Cubit<{ count: number }> {
44
+ class AuthContainer extends StateContainer<{ token: string | null }> {
59
45
  constructor() {
60
- super({ count: 0 });
46
+ super({ token: null });
61
47
  }
62
48
 
63
- increment = () => this.emit({ count: this.state.count + 1 });
64
- decrement = () => this.update((state) => ({ count: state.count - 1 }));
65
- reset = () => this.patch({ count: 0 });
49
+ login(token: string) {
50
+ this.emit({ token });
51
+ }
52
+
53
+ logout() {
54
+ this.emit({ token: null });
55
+ }
66
56
  }
67
57
  ```
68
58
 
69
- `patch()` performs a shallow merge for object state and is only available when `S extends object`.
59
+ **Public API:** `state`, `subscribe(listener)`, `dispose()`, `isDisposed`, `name`, `instanceId`, `createdAt`, `lastUpdateTimestamp`
70
60
 
71
- ## Registry API
61
+ **Protected API:** `emit(state)`, `update(fn)`, `onSystemEvent(event, handler)`, `depend(BlocClass, instanceKey?)`
72
62
 
73
- The registry manages instance lifecycles and ref counting.
63
+ ## Registry
64
+
65
+ Manages instance lifecycles and ref counting.
74
66
 
75
67
  ```ts
76
68
  import {
@@ -81,32 +73,17 @@ import {
81
73
  release,
82
74
  hasInstance,
83
75
  getRefCount,
84
- getAll,
85
- forEach,
86
- clear,
87
- clearAll,
88
76
  } from '@blac/core';
89
77
 
90
- const counter = acquire(CounterCubit); // increments ref count
91
-
92
- const shared = ensure(CounterCubit); // no ref count increment
93
- const existing = borrow(CounterCubit); // no create, no ref count
94
- const maybe = borrowSafe(CounterCubit); // { error, instance }
78
+ const counter = acquire(CounterCubit); // create or reuse, increment ref count
79
+ const shared = ensure(CounterCubit); // create or reuse, no ref count change
80
+ const existing = borrow(CounterCubit); // get existing, throws if missing
81
+ const maybe = borrowSafe(CounterCubit); // get existing, returns { error, instance }
95
82
 
96
- release(CounterCubit); // decrements ref count, auto-dispose at 0 unless keepAlive
97
-
98
- if (hasInstance(CounterCubit)) {
99
- console.log(getRefCount(CounterCubit));
100
- }
101
-
102
- forEach(CounterCubit, (inst) => console.log(inst.state));
103
- clear(CounterCubit);
104
- clearAll();
83
+ release(CounterCubit); // decrement ref count, auto-dispose at 0 (unless keepAlive)
105
84
  ```
106
85
 
107
- ## Decorators
108
-
109
- Configure container behavior with `@blac`.
86
+ ## Configuration
110
87
 
111
88
  ```ts
112
89
  import { Cubit, blac } from '@blac/core';
@@ -118,29 +95,27 @@ class AuthCubit extends Cubit<AuthState> {}
118
95
  class InternalCubit extends Cubit<State> {}
119
96
  ```
120
97
 
121
- `BlacOptions` is a union type, so only one option can be specified at a time.
98
+ ## Watch
122
99
 
123
- ## Watch and Tracking
124
-
125
- ### watch
100
+ Observe state changes outside of a UI framework.
126
101
 
127
102
  ```ts
128
103
  import { watch, instance } from '@blac/core';
129
104
 
130
105
  const stop = watch(CounterCubit, (counter) => {
131
106
  console.log(counter.state.count);
132
-
133
- if (counter.state.count >= 10) {
134
- return watch.STOP; // stop from inside the callback
135
- }
107
+ if (counter.state.count >= 10) return watch.STOP;
136
108
  });
137
109
 
138
- const stopSpecific = watch(instance(CounterCubit, 'counter-1'), (counter) => {
139
- console.log(counter.state.count);
110
+ // Watch a specific named instance
111
+ const stop2 = watch(instance(CounterCubit, 'counter-1'), (c) => {
112
+ console.log(c.state.count);
140
113
  });
141
114
  ```
142
115
 
143
- ### tracked
116
+ ## Tracked
117
+
118
+ Run a function and capture which blocs/state it accessed.
144
119
 
145
120
  ```ts
146
121
  import { tracked } from '@blac/core';
@@ -156,27 +131,28 @@ const { result, dependencies } = tracked(() => {
156
131
  ```ts
157
132
  import { getPluginManager, type BlacPlugin } from '@blac/core';
158
133
 
159
- const loggingPlugin: BlacPlugin = {
160
- name: 'logging',
134
+ const myPlugin: BlacPlugin = {
135
+ name: 'my-plugin',
161
136
  version: '1.0.0',
162
- onStateChanged(instance, previousState, currentState, callstack) {
163
- console.log(instance.constructor.name, previousState, currentState);
164
- if (callstack) console.log(callstack);
137
+ onStateChanged(instance, previousState, currentState) {
138
+ console.log(instance.constructor.name, previousState, '→', currentState);
165
139
  },
166
140
  };
167
141
 
168
- getPluginManager().install(loggingPlugin, {
169
- enabled: true,
170
- environment: 'development',
171
- });
142
+ getPluginManager().install(myPlugin, { environment: 'development' });
172
143
  ```
173
144
 
174
145
  ## Subpath Exports
175
146
 
176
- - `@blac/core/watch` -> `watch`, `instance`, `tracked` utilities
177
- - `@blac/core/tracking` -> dependency tracking utilities for framework adapters
178
- - `@blac/core/plugins` -> plugin system exports
179
- - `@blac/core/debug` -> advanced registry introspection helpers
147
+ | Export | Contents |
148
+ | --------------------- | ------------------------------------------------------ |
149
+ | `@blac/core` | All core classes, registry, decorators, watch, tracked |
150
+ | `@blac/core/watch` | `watch`, `instance`, `tracked` |
151
+ | `@blac/core/tracking` | Dependency tracking internals for framework adapters |
152
+ | `@blac/core/plugins` | Plugin system types and utilities |
153
+ | `@blac/core/debug` | Registry introspection helpers |
154
+ | `@blac/core/testing` | Test utilities |
155
+ | `@blac/core/types` | Type-only exports |
180
156
 
181
157
  ## License
182
158
 
@@ -0,0 +1,390 @@
1
+ const require_StateContainerRegistry = require('./StateContainerRegistry-vXMWtG7J.cjs');
2
+ const require_config = require('./config-D3jisfdj.cjs');
3
+ //#region src/utils/idGenerator.ts
4
+ /**
5
+ * Generate simple ID with timestamp and random (no counter tracking)
6
+ *
7
+ * Format: `${prefix}:${timestamp}_${random}`
8
+ *
9
+ * @param prefix - Prefix for the ID
10
+ * @returns Branded ID string
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const id = generateSimpleId('CounterBloc');
15
+ * // Returns: "CounterBloc:1698765432100_a3k9d7f2q"
16
+ * ```
17
+ */
18
+ function generateSimpleId(prefix, affix) {
19
+ if (affix) return `${prefix}:${affix}`;
20
+ return `${prefix}:${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
21
+ }
22
+ //#endregion
23
+ //#region src/core/symbols.ts
24
+ const EMIT = Symbol('blac.emit');
25
+ const UPDATE = Symbol('blac.update');
26
+ //#endregion
27
+ //#region src/core/StateContainer.ts
28
+ const EMPTY_DEPS = /* @__PURE__ */ new Map();
29
+ var StateContainer = class StateContainer {
30
+ static {
31
+ this.__excludeFromDevTools = false;
32
+ }
33
+ static {
34
+ this.enableStackTrace = true;
35
+ }
36
+ get dependencies() {
37
+ return this._dependencies ?? EMPTY_DEPS;
38
+ }
39
+ depend(Type, instanceKey) {
40
+ if (!this._dependencies) this._dependencies = /* @__PURE__ */ new Map();
41
+ this._dependencies.set(
42
+ Type,
43
+ instanceKey ??
44
+ require_StateContainerRegistry.BLAC_DEFAULTS.DEFAULT_INSTANCE_KEY,
45
+ );
46
+ return () => require_config.getRegistry().ensure(Type, instanceKey);
47
+ }
48
+ constructor(initialState) {
49
+ this._listeners = /* @__PURE__ */ new Set();
50
+ this._disposed = false;
51
+ this._hydrationStatus = 'idle';
52
+ this._changedWhileHydrating = false;
53
+ this._hydrationPromise = null;
54
+ this._hydrationPromiseSettled = false;
55
+ this._config = {};
56
+ this._systemEventHandlers = /* @__PURE__ */ new Map();
57
+ this._dependencies = null;
58
+ this.name = this.constructor.name;
59
+ this.debug = false;
60
+ this.instanceId = generateSimpleId(this.constructor.name, 'main');
61
+ this.createdAt = Date.now();
62
+ this.lastUpdateTimestamp = Date.now();
63
+ this.createdFrom = '';
64
+ this.onSystemEvent = (event, handler) => {
65
+ let handlers = this._systemEventHandlers.get(event);
66
+ if (!handlers) {
67
+ handlers = /* @__PURE__ */ new Set();
68
+ this._systemEventHandlers.set(event, handlers);
69
+ }
70
+ handlers.add(handler);
71
+ return () => {
72
+ handlers?.delete(handler);
73
+ };
74
+ };
75
+ this._state = initialState;
76
+ }
77
+ initConfig(config) {
78
+ this._config = { ...config };
79
+ this.name = this._config.name || this.constructor.name;
80
+ this.debug = this._config.debug ?? false;
81
+ this.instanceId = generateSimpleId(
82
+ this.constructor.name,
83
+ this._config.instanceId,
84
+ );
85
+ this.createdFrom = this.captureStackTrace();
86
+ require_config.getRegistry().emit('created', this);
87
+ }
88
+ get state() {
89
+ return this._state;
90
+ }
91
+ get isDisposed() {
92
+ return this._disposed;
93
+ }
94
+ get hydrationStatus() {
95
+ return this._hydrationStatus;
96
+ }
97
+ get hydrationError() {
98
+ return this._hydrationError;
99
+ }
100
+ get isHydrated() {
101
+ return this._hydrationStatus === 'hydrated';
102
+ }
103
+ get changedWhileHydrating() {
104
+ return this._changedWhileHydrating;
105
+ }
106
+ subscribe(listener) {
107
+ if (this._disposed)
108
+ throw new Error(`Cannot subscribe to disposed container ${this.name}`);
109
+ this._listeners.add(listener);
110
+ return () => this._listeners.delete(listener);
111
+ }
112
+ dispose() {
113
+ if (this._disposed) return;
114
+ if (this.debug) console.log(`[${this.name}] Disposing...`);
115
+ this._disposed = true;
116
+ if (this._hydrationStatus === 'hydrating')
117
+ this.failHydration(
118
+ /* @__PURE__ */ new Error(
119
+ `Hydration cancelled because ${this.name} was disposed`,
120
+ ),
121
+ );
122
+ this.emitSystemEvent('dispose', void 0);
123
+ this._listeners.clear();
124
+ this._systemEventHandlers.clear();
125
+ require_config.getRegistry().emit('disposed', this);
126
+ if (this.debug) console.log(`[${this.name}] Disposed successfully`);
127
+ }
128
+ [EMIT](newState) {
129
+ this.applyState(newState, 'default');
130
+ }
131
+ [UPDATE](updater) {
132
+ if (this._disposed)
133
+ throw new Error(
134
+ `Cannot update state from disposed container ${this.name}`,
135
+ );
136
+ this[EMIT](updater(this._state));
137
+ }
138
+ beginHydration() {
139
+ if (this._disposed)
140
+ throw new Error(
141
+ `Cannot begin hydration for disposed container ${this.name}`,
142
+ );
143
+ this._changedWhileHydrating = false;
144
+ this._hydrationError = void 0;
145
+ this._hydrationPromise = null;
146
+ this._resolveHydrationPromise = void 0;
147
+ this._rejectHydrationPromise = void 0;
148
+ this._hydrationPromiseSettled = false;
149
+ this.ensureHydrationPromise();
150
+ this.setHydrationStatus('hydrating');
151
+ }
152
+ applyHydratedState(newState) {
153
+ if (this._disposed) return false;
154
+ if (this._hydrationStatus !== 'hydrating' || this._changedWhileHydrating)
155
+ return false;
156
+ this.applyState(newState, 'hydration');
157
+ return true;
158
+ }
159
+ finishHydration() {
160
+ if (this._hydrationStatus !== 'hydrating') {
161
+ if (this._hydrationStatus === 'hydrated') return;
162
+ if (this._hydrationStatus === 'error') this.ensureHydrationPromise();
163
+ }
164
+ this.setHydrationStatus('hydrated');
165
+ this.resolveHydration();
166
+ }
167
+ failHydration(error) {
168
+ const err =
169
+ error instanceof Error
170
+ ? error
171
+ : /* @__PURE__ */ new Error(`Hydration failed: ${String(error)}`);
172
+ this._hydrationError = err;
173
+ this.setHydrationStatus('error', err);
174
+ this.rejectHydration(err);
175
+ }
176
+ waitForHydration() {
177
+ if (
178
+ this._hydrationStatus === 'idle' ||
179
+ this._hydrationStatus === 'hydrated'
180
+ )
181
+ return Promise.resolve();
182
+ if (this._hydrationStatus === 'error')
183
+ return Promise.reject(
184
+ this._hydrationError ??
185
+ /* @__PURE__ */ new Error(
186
+ `Hydration failed for container ${this.name}`,
187
+ ),
188
+ );
189
+ return this.ensureHydrationPromise();
190
+ }
191
+ captureStackTrace() {
192
+ if (
193
+ !StateContainer.enableStackTrace ||
194
+ (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production')
195
+ )
196
+ return '';
197
+ try {
198
+ const relevantLines = (/* @__PURE__ */ new Error().stack || '')
199
+ .split('\n')
200
+ .slice(1);
201
+ const formattedLines = [];
202
+ for (const line of relevantLines) {
203
+ if (!line.trim()) continue;
204
+ if (
205
+ line.includes('StateContainer.emit') ||
206
+ line.includes('StateContainer.update') ||
207
+ line.includes('StateContainer.captureStackTrace') ||
208
+ line.includes('[blac.emit]') ||
209
+ line.includes('[blac.update]') ||
210
+ line.includes('Cubit.patch') ||
211
+ line.includes('/blac-core/dist/') ||
212
+ line.includes('@blac/core/')
213
+ )
214
+ continue;
215
+ if (
216
+ line.includes('node_modules') ||
217
+ line.includes('react-dom') ||
218
+ line.includes('react_jsx') ||
219
+ line.includes('.vite/deps') ||
220
+ line.includes('executeDispatch') ||
221
+ line.includes('runWithFiber') ||
222
+ line.includes('invokeGuarded') ||
223
+ line.includes('callCallback') ||
224
+ line.includes('processDispatchQueue') ||
225
+ line.includes('dispatchEvent') ||
226
+ line.includes('batchedUpdates')
227
+ )
228
+ continue;
229
+ const formatted = this.formatStackLine(line);
230
+ if (formatted) formattedLines.push(formatted);
231
+ }
232
+ return formattedLines.join('\n');
233
+ } catch {
234
+ return '';
235
+ }
236
+ }
237
+ formatStackLine(line) {
238
+ const match = line.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
239
+ if (!match) {
240
+ const simpleMatch = line.match(/at\s+(.+?):(\d+):(\d+)/);
241
+ if (simpleMatch) {
242
+ const [, url, lineNum, col] = simpleMatch;
243
+ return ` at ${this.cleanFilePath(url)}:${lineNum}:${col}`;
244
+ }
245
+ return null;
246
+ }
247
+ const [, functionName, url, lineNum, col] = match;
248
+ return ` at ${functionName} (${this.cleanFilePath(url)}:${lineNum}:${col})`;
249
+ }
250
+ cleanFilePath(url) {
251
+ let path = url
252
+ .replace(/http:\/\/localhost:\d+\/@fs/, '')
253
+ .replace(/http:\/\/localhost:\d+\//, '')
254
+ .replace(/\?t=\d+/, '')
255
+ .replace(/\?v=[a-f0-9]+/, '');
256
+ const projectMatch = path.match(/\/Projects\/blac\/(.+)/);
257
+ if (projectMatch) path = projectMatch[1];
258
+ const segments = path.split('/');
259
+ if (segments.length > 3) path = segments.slice(-3).join('/');
260
+ return path;
261
+ }
262
+ applyState(newState, source) {
263
+ if (this._disposed)
264
+ throw new Error(`Cannot emit state from disposed container ${this.name}`);
265
+ if (this._state === newState) return;
266
+ if (this._hydrationStatus === 'hydrating' && source !== 'hydration')
267
+ this._changedWhileHydrating = true;
268
+ const previousState = this._state;
269
+ this._state = newState;
270
+ this.emitSystemEvent('stateChanged', {
271
+ state: newState,
272
+ previousState,
273
+ });
274
+ const listeners = Array.from(this._listeners);
275
+ for (const listener of listeners)
276
+ try {
277
+ listener(newState);
278
+ } catch (error) {
279
+ console.error(`[${this.name}] Error in listener:`, error);
280
+ }
281
+ const stackTrace = this.captureStackTrace();
282
+ require_config
283
+ .getRegistry()
284
+ .emit('stateChanged', this, previousState, newState, stackTrace);
285
+ this.lastUpdateTimestamp = Date.now();
286
+ }
287
+ setHydrationStatus(status, error) {
288
+ const previousStatus = this._hydrationStatus;
289
+ this._hydrationStatus = status;
290
+ this._hydrationError = error;
291
+ this.emitSystemEvent('hydrationChanged', {
292
+ status,
293
+ previousStatus,
294
+ error,
295
+ changedWhileHydrating: this._changedWhileHydrating,
296
+ });
297
+ }
298
+ ensureHydrationPromise() {
299
+ if (!this._hydrationPromise || this._hydrationPromiseSettled) {
300
+ this._hydrationPromiseSettled = false;
301
+ this._hydrationPromise = new Promise((resolve, reject) => {
302
+ this._resolveHydrationPromise = () => {
303
+ if (this._hydrationPromiseSettled) return;
304
+ this._hydrationPromiseSettled = true;
305
+ resolve();
306
+ };
307
+ this._rejectHydrationPromise = (error) => {
308
+ if (this._hydrationPromiseSettled) return;
309
+ this._hydrationPromiseSettled = true;
310
+ reject(error);
311
+ };
312
+ });
313
+ this._hydrationPromise.catch(() => {});
314
+ }
315
+ return this._hydrationPromise;
316
+ }
317
+ resolveHydration() {
318
+ this._resolveHydrationPromise?.();
319
+ }
320
+ rejectHydration(error) {
321
+ this.ensureHydrationPromise();
322
+ this._rejectHydrationPromise?.(error);
323
+ }
324
+ emitSystemEvent(event, payload) {
325
+ const handlers = this._systemEventHandlers.get(event);
326
+ if (!handlers) return;
327
+ for (const handler of handlers)
328
+ try {
329
+ handler(payload);
330
+ } catch (error) {
331
+ console.error(`[${this.name}] Error in system event handler:`, error);
332
+ }
333
+ }
334
+ };
335
+ //#endregion
336
+ //#region src/core/Cubit.ts
337
+ var Cubit = class extends StateContainer {
338
+ constructor(initialState) {
339
+ super(initialState);
340
+ this.patch = (partial) => {
341
+ if (typeof this.state !== 'object' || this.state === null)
342
+ throw new Error('patch() is only available for object state types');
343
+ const current = this.state;
344
+ let hasChanges = false;
345
+ for (const key in partial)
346
+ if (!Object.is(current[key], partial[key])) {
347
+ hasChanges = true;
348
+ break;
349
+ }
350
+ if (hasChanges)
351
+ this.update((c) => ({
352
+ ...c,
353
+ ...partial,
354
+ }));
355
+ };
356
+ }
357
+ emit(newState) {
358
+ this[EMIT](newState);
359
+ }
360
+ update(updater) {
361
+ this[UPDATE](updater);
362
+ }
363
+ };
364
+ //#endregion
365
+ Object.defineProperty(exports, 'Cubit', {
366
+ enumerable: true,
367
+ get: function () {
368
+ return Cubit;
369
+ },
370
+ });
371
+ Object.defineProperty(exports, 'EMIT', {
372
+ enumerable: true,
373
+ get: function () {
374
+ return EMIT;
375
+ },
376
+ });
377
+ Object.defineProperty(exports, 'StateContainer', {
378
+ enumerable: true,
379
+ get: function () {
380
+ return StateContainer;
381
+ },
382
+ });
383
+ Object.defineProperty(exports, 'UPDATE', {
384
+ enumerable: true,
385
+ get: function () {
386
+ return UPDATE;
387
+ },
388
+ });
389
+
390
+ //# sourceMappingURL=Cubit-9jal5zdZ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cubit-9jal5zdZ.cjs","names":["BLAC_DEFAULTS","getRegistry"],"sources":["../src/utils/idGenerator.ts","../src/core/symbols.ts","../src/core/StateContainer.ts","../src/core/Cubit.ts"],"sourcesContent":["/**\n * Centralized ID Generation\n *\n * Provides consistent, collision-resistant ID generation for all BlaC subsystems.\n * Uses timestamp + counter + random suffix for uniqueness.\n */\n\n// Global counter map for ID generation\nconst globalCounters = new Map<string, number>();\n\n/**\n * Creates an ID generator with isolated counter state\n *\n * @param prefix - Prefix for generated IDs\n * @returns Object with next(), nextSimple(), and reset() methods\n *\n * @example\n * ```ts\n * const generator = createIdGenerator('sub');\n * const id1 = generator.next(); // \"sub:1698765432100_1_a3k9d7f2q\"\n * const id2 = generator.next(); // \"sub:1698765432101_2_b4n8e9g3r\"\n * ```\n */\nexport function createIdGenerator(prefix: string) {\n let counter = 0;\n return {\n next: () =>\n `${prefix}:${Date.now()}_${++counter}_${Math.random().toString(36).substring(2, 11)}`,\n nextSimple: () => `${prefix}:${++counter}`,\n reset: () => {\n counter = 0;\n },\n };\n}\n\n/**\n * Generate ID with timestamp, counter, and random suffix (tree-shakeable)\n *\n * Format: `${prefix}:${timestamp}_${counter}_${random}`\n *\n * @param prefix - Prefix for the ID (e.g., 'sub', 'consumer', 'stage')\n * @returns Branded ID string\n *\n * @example\n * const id = generateId('sub');\n * // Returns: \"sub:1698765432100_1_a3k9d7f2q\"\n */\nexport function generateId(prefix: string): string {\n const counter = (globalCounters.get(prefix) ?? 0) + 1;\n globalCounters.set(prefix, counter);\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 11);\n return `${prefix}:${timestamp}_${counter}_${random}`;\n}\n\n/**\n * Generate simple ID with timestamp and random (no counter tracking)\n *\n * Format: `${prefix}:${timestamp}_${random}`\n *\n * @param prefix - Prefix for the ID\n * @returns Branded ID string\n *\n * @example\n * ```ts\n * const id = generateSimpleId('CounterBloc');\n * // Returns: \"CounterBloc:1698765432100_a3k9d7f2q\"\n * ```\n */\nexport function generateSimpleId(prefix: string, affix?: string): string {\n if (affix) {\n return `${prefix}:${affix}`;\n }\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 11);\n return `${prefix}:${timestamp}_${random}`;\n}\n\n/**\n * Reset all counters for testing purposes\n * @internal\n */\nexport function __resetIdCounters(): void {\n globalCounters.clear();\n}\n","export const EMIT = Symbol('blac.emit');\nexport const UPDATE = Symbol('blac.update');\n","import { generateSimpleId } from '../utils/idGenerator';\nimport { BLAC_DEFAULTS } from '../constants';\nimport { getRegistry } from '../registry/config';\nimport type { StateContainerConstructor } from '../types/utilities';\nimport { EMIT, UPDATE } from './symbols';\n\nexport interface StateContainerConfig {\n name?: string;\n debug?: boolean;\n instanceId?: string;\n}\n\nexport type HydrationStatus = 'idle' | 'hydrating' | 'hydrated' | 'error';\n\ntype StateListener<S> = (state: S) => void;\n\nexport type SystemEvent = 'stateChanged' | 'dispose' | 'hydrationChanged';\n\nexport interface SystemEventPayloads<S> {\n stateChanged: { state: S; previousState: S };\n dispose: void;\n hydrationChanged: {\n status: HydrationStatus;\n previousStatus: HydrationStatus;\n error?: Error;\n changedWhileHydrating: boolean;\n };\n}\n\ntype SystemEventHandler<S, E extends SystemEvent> = (\n payload: SystemEventPayloads<S>[E],\n) => void;\n\nconst EMPTY_DEPS: ReadonlyMap<any, any> = new Map();\n\nexport abstract class StateContainer<S extends object = any> {\n static __excludeFromDevTools = false;\n static enableStackTrace = true;\n\n private _state: S;\n private readonly _listeners = new Set<StateListener<S>>();\n private _disposed = false;\n private _hydrationStatus: HydrationStatus = 'idle';\n private _hydrationError?: Error;\n private _changedWhileHydrating = false;\n private _hydrationPromise: Promise<void> | null = null;\n private _resolveHydrationPromise?: () => void;\n private _rejectHydrationPromise?: (error: Error) => void;\n private _hydrationPromiseSettled = false;\n private _config: StateContainerConfig = {};\n private readonly _systemEventHandlers = new Map<\n SystemEvent,\n Set<SystemEventHandler<S, any>>\n >();\n private _dependencies: Map<StateContainerConstructor, string> | null = null;\n\n name: string = this.constructor.name;\n debug: boolean = false;\n instanceId: string = generateSimpleId(this.constructor.name, 'main');\n createdAt: number = Date.now();\n lastUpdateTimestamp: number = Date.now();\n createdFrom: string = '';\n\n get dependencies(): ReadonlyMap<StateContainerConstructor, string> {\n return this._dependencies ?? EMPTY_DEPS;\n }\n\n protected depend<T extends StateContainerConstructor>(\n Type: T,\n instanceKey?: string,\n ): () => InstanceType<T> {\n if (!this._dependencies) {\n this._dependencies = new Map();\n }\n this._dependencies.set(\n Type,\n instanceKey ?? BLAC_DEFAULTS.DEFAULT_INSTANCE_KEY,\n );\n return () => getRegistry().ensure(Type, instanceKey);\n }\n\n constructor(initialState: S) {\n this._state = initialState;\n }\n\n initConfig(config: StateContainerConfig): void {\n this._config = { ...config };\n this.name = this._config.name || this.constructor.name;\n this.debug = this._config.debug ?? false;\n this.instanceId = generateSimpleId(\n this.constructor.name,\n this._config.instanceId,\n );\n this.createdFrom = this.captureStackTrace();\n getRegistry().emit('created', this);\n }\n\n get state(): Readonly<S> {\n return this._state;\n }\n\n get isDisposed(): boolean {\n return this._disposed;\n }\n\n get hydrationStatus(): HydrationStatus {\n return this._hydrationStatus;\n }\n\n get hydrationError(): Error | undefined {\n return this._hydrationError;\n }\n\n get isHydrated(): boolean {\n return this._hydrationStatus === 'hydrated';\n }\n\n get changedWhileHydrating(): boolean {\n return this._changedWhileHydrating;\n }\n\n subscribe(listener: StateListener<S>): () => void {\n if (this._disposed) {\n throw new Error(`Cannot subscribe to disposed container ${this.name}`);\n }\n this._listeners.add(listener);\n return () => this._listeners.delete(listener);\n }\n\n dispose(): void {\n if (this._disposed) return;\n\n if (this.debug) {\n console.log(`[${this.name}] Disposing...`);\n }\n\n this._disposed = true;\n\n if (this._hydrationStatus === 'hydrating') {\n this.failHydration(\n new Error(`Hydration cancelled because ${this.name} was disposed`),\n );\n }\n\n this.emitSystemEvent('dispose', undefined as void);\n\n this._listeners.clear();\n this._systemEventHandlers.clear();\n\n getRegistry().emit('disposed', this);\n\n if (this.debug) {\n console.log(`[${this.name}] Disposed successfully`);\n }\n }\n\n protected [EMIT](newState: S): void {\n this.applyState(newState, 'default');\n }\n\n protected [UPDATE](updater: (current: S) => S): void {\n if (this._disposed) {\n throw new Error(\n `Cannot update state from disposed container ${this.name}`,\n );\n }\n this[EMIT](updater(this._state));\n }\n\n beginHydration(): void {\n if (this._disposed) {\n throw new Error(\n `Cannot begin hydration for disposed container ${this.name}`,\n );\n }\n\n this._changedWhileHydrating = false;\n this._hydrationError = undefined;\n this._hydrationPromise = null;\n this._resolveHydrationPromise = undefined;\n this._rejectHydrationPromise = undefined;\n this._hydrationPromiseSettled = false;\n void this.ensureHydrationPromise();\n this.setHydrationStatus('hydrating');\n }\n\n applyHydratedState(newState: S): boolean {\n if (this._disposed) {\n return false;\n }\n\n if (this._hydrationStatus !== 'hydrating' || this._changedWhileHydrating) {\n return false;\n }\n\n this.applyState(newState, 'hydration');\n return true;\n }\n\n finishHydration(): void {\n if (this._hydrationStatus !== 'hydrating') {\n if (this._hydrationStatus === 'hydrated') {\n return;\n }\n if (this._hydrationStatus === 'error') {\n void this.ensureHydrationPromise();\n }\n }\n\n this.setHydrationStatus('hydrated');\n this.resolveHydration();\n }\n\n failHydration(error: Error): void {\n const err =\n error instanceof Error\n ? error\n : new Error(`Hydration failed: ${String(error)}`);\n\n this._hydrationError = err;\n this.setHydrationStatus('error', err);\n this.rejectHydration(err);\n }\n\n waitForHydration(): Promise<void> {\n if (\n this._hydrationStatus === 'idle' ||\n this._hydrationStatus === 'hydrated'\n ) {\n return Promise.resolve();\n }\n\n if (this._hydrationStatus === 'error') {\n return Promise.reject(\n this._hydrationError ??\n new Error(`Hydration failed for container ${this.name}`),\n );\n }\n\n return this.ensureHydrationPromise();\n }\n\n private captureStackTrace(): string {\n if (\n !StateContainer.enableStackTrace ||\n (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production')\n ) {\n return '';\n }\n\n try {\n const error = new Error();\n const stack = error.stack || '';\n const lines = stack.split('\\n');\n const relevantLines = lines.slice(1);\n const formattedLines: string[] = [];\n\n for (const line of relevantLines) {\n if (!line.trim()) continue;\n\n if (\n line.includes('StateContainer.emit') ||\n line.includes('StateContainer.update') ||\n line.includes('StateContainer.captureStackTrace') ||\n line.includes('[blac.emit]') ||\n line.includes('[blac.update]') ||\n line.includes('Cubit.patch') ||\n line.includes('/blac-core/dist/') ||\n line.includes('@blac/core/')\n ) {\n continue;\n }\n\n if (\n line.includes('node_modules') ||\n line.includes('react-dom') ||\n line.includes('react_jsx') ||\n line.includes('.vite/deps') ||\n line.includes('executeDispatch') ||\n line.includes('runWithFiber') ||\n line.includes('invokeGuarded') ||\n line.includes('callCallback') ||\n line.includes('processDispatchQueue') ||\n line.includes('dispatchEvent') ||\n line.includes('batchedUpdates')\n ) {\n continue;\n }\n\n const formatted = this.formatStackLine(line);\n if (formatted) {\n formattedLines.push(formatted);\n }\n }\n\n return formattedLines.join('\\n');\n } catch {\n return '';\n }\n }\n\n private formatStackLine(line: string): string | null {\n const match = line.match(/at\\s+(.+?)\\s+\\((.+?):(\\d+):(\\d+)\\)/);\n if (!match) {\n const simpleMatch = line.match(/at\\s+(.+?):(\\d+):(\\d+)/);\n if (simpleMatch) {\n const [, url, lineNum, col] = simpleMatch;\n const cleanPath = this.cleanFilePath(url);\n return ` at ${cleanPath}:${lineNum}:${col}`;\n }\n return null;\n }\n\n const [, functionName, url, lineNum, col] = match;\n const cleanPath = this.cleanFilePath(url);\n\n return ` at ${functionName} (${cleanPath}:${lineNum}:${col})`;\n }\n\n private cleanFilePath(url: string): string {\n let path = url\n .replace(/http:\\/\\/localhost:\\d+\\/@fs/, '')\n .replace(/http:\\/\\/localhost:\\d+\\//, '')\n .replace(/\\?t=\\d+/, '')\n .replace(/\\?v=[a-f0-9]+/, '');\n\n const projectMatch = path.match(/\\/Projects\\/blac\\/(.+)/);\n if (projectMatch) {\n path = projectMatch[1];\n }\n\n const segments = path.split('/');\n if (segments.length > 3) {\n path = segments.slice(-3).join('/');\n }\n\n return path;\n }\n\n private applyState(newState: S, source: 'default' | 'hydration'): void {\n if (this._disposed) {\n throw new Error(`Cannot emit state from disposed container ${this.name}`);\n }\n\n if (this._state === newState) return;\n\n if (this._hydrationStatus === 'hydrating' && source !== 'hydration') {\n this._changedWhileHydrating = true;\n }\n\n const previousState = this._state;\n this._state = newState;\n\n this.emitSystemEvent('stateChanged', {\n state: newState,\n previousState,\n });\n\n const listeners = Array.from(this._listeners);\n for (const listener of listeners) {\n try {\n listener(newState);\n } catch (error) {\n console.error(`[${this.name}] Error in listener:`, error);\n }\n }\n\n const stackTrace = this.captureStackTrace();\n\n getRegistry().emit(\n 'stateChanged',\n this,\n previousState,\n newState,\n stackTrace,\n );\n this.lastUpdateTimestamp = Date.now();\n }\n\n private setHydrationStatus(status: HydrationStatus, error?: Error): void {\n const previousStatus = this._hydrationStatus;\n this._hydrationStatus = status;\n this._hydrationError = error;\n\n this.emitSystemEvent('hydrationChanged', {\n status,\n previousStatus,\n error,\n changedWhileHydrating: this._changedWhileHydrating,\n });\n }\n\n private ensureHydrationPromise(): Promise<void> {\n if (!this._hydrationPromise || this._hydrationPromiseSettled) {\n this._hydrationPromiseSettled = false;\n this._hydrationPromise = new Promise<void>((resolve, reject) => {\n this._resolveHydrationPromise = () => {\n if (this._hydrationPromiseSettled) return;\n this._hydrationPromiseSettled = true;\n resolve();\n };\n this._rejectHydrationPromise = (error: Error) => {\n if (this._hydrationPromiseSettled) return;\n this._hydrationPromiseSettled = true;\n reject(error);\n };\n });\n this._hydrationPromise.catch(() => {});\n }\n\n return this._hydrationPromise;\n }\n\n private resolveHydration(): void {\n this._resolveHydrationPromise?.();\n }\n\n private rejectHydration(error: Error): void {\n void this.ensureHydrationPromise();\n this._rejectHydrationPromise?.(error);\n }\n\n protected onSystemEvent = <E extends SystemEvent>(\n event: E,\n handler: SystemEventHandler<S, E>,\n ): (() => void) => {\n let handlers = this._systemEventHandlers.get(event);\n if (!handlers) {\n handlers = new Set();\n this._systemEventHandlers.set(event, handlers);\n }\n handlers.add(handler as SystemEventHandler<S, any>);\n\n return () => {\n handlers?.delete(handler as SystemEventHandler<S, any>);\n };\n };\n\n private emitSystemEvent<E extends SystemEvent>(\n event: E,\n payload: SystemEventPayloads<S>[E],\n ): void {\n const handlers = this._systemEventHandlers.get(event);\n if (!handlers) return;\n\n for (const handler of handlers) {\n try {\n handler(payload);\n } catch (error) {\n console.error(`[${this.name}] Error in system event handler:`, error);\n }\n }\n }\n}\n","import { StateContainer } from './StateContainer';\nimport { EMIT, UPDATE } from './symbols';\n\nexport abstract class Cubit<S extends object = any> extends StateContainer<S> {\n constructor(initialState: S) {\n super(initialState);\n }\n\n public emit(newState: S): void {\n this[EMIT](newState);\n }\n\n public update(updater: (current: S) => S): void {\n this[UPDATE](updater);\n }\n\n public patch = ((partial: S extends object ? Partial<S> : never): void => {\n if (typeof this.state !== 'object' || this.state === null) {\n throw new Error('patch() is only available for object state types');\n }\n const current = this.state;\n let hasChanges = false;\n for (const key in partial) {\n if (!Object.is((current as any)[key], (partial as any)[key])) {\n hasChanges = true;\n break;\n }\n }\n if (hasChanges) {\n this.update((c) => ({ ...c, ...partial }) as S);\n }\n }) as S extends object ? (partial: Partial<S>) => void : never;\n}\n"],"mappings":"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"}