@blac/core 2.0.0-rc-14 → 2.0.0-rc.0

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 (162) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/Blac.d.ts +246 -0
  3. package/dist/Blac.d.ts.map +1 -0
  4. package/dist/Blac.js +625 -0
  5. package/dist/Blac.js.map +1 -0
  6. package/dist/Bloc.d.ts +41 -0
  7. package/dist/Bloc.d.ts.map +1 -0
  8. package/dist/Bloc.js +140 -0
  9. package/dist/Bloc.js.map +1 -0
  10. package/dist/BlocBase.d.ts +110 -0
  11. package/dist/BlocBase.d.ts.map +1 -0
  12. package/dist/BlocBase.js +287 -0
  13. package/dist/BlocBase.js.map +1 -0
  14. package/dist/Cubit.d.ts +25 -0
  15. package/dist/Cubit.d.ts.map +1 -0
  16. package/dist/Cubit.js +64 -0
  17. package/dist/Cubit.js.map +1 -0
  18. package/dist/adapter/BlacAdapter.d.ts +71 -0
  19. package/dist/adapter/BlacAdapter.d.ts.map +1 -0
  20. package/dist/adapter/BlacAdapter.js +373 -0
  21. package/dist/adapter/BlacAdapter.js.map +1 -0
  22. package/dist/adapter/ProxyFactory.d.ts +50 -0
  23. package/dist/adapter/ProxyFactory.d.ts.map +1 -0
  24. package/dist/adapter/ProxyFactory.js +150 -0
  25. package/dist/adapter/ProxyFactory.js.map +1 -0
  26. package/{src/adapter/index.ts → dist/adapter/index.d.ts} +1 -0
  27. package/dist/adapter/index.d.ts.map +1 -0
  28. package/dist/adapter/index.js +19 -0
  29. package/dist/adapter/index.js.map +1 -0
  30. package/dist/errors/BlacError.d.ts +38 -0
  31. package/dist/errors/BlacError.d.ts.map +1 -0
  32. package/dist/errors/BlacError.js +55 -0
  33. package/dist/errors/BlacError.js.map +1 -0
  34. package/dist/errors/ErrorManager.d.ts +39 -0
  35. package/dist/errors/ErrorManager.d.ts.map +1 -0
  36. package/dist/errors/ErrorManager.js +91 -0
  37. package/dist/errors/ErrorManager.js.map +1 -0
  38. package/dist/errors/handleError.d.ts +24 -0
  39. package/dist/errors/handleError.d.ts.map +1 -0
  40. package/dist/errors/handleError.js +62 -0
  41. package/dist/errors/handleError.js.map +1 -0
  42. package/dist/errors/index.d.ts +5 -0
  43. package/dist/errors/index.d.ts.map +1 -0
  44. package/dist/errors/index.js +13 -0
  45. package/dist/errors/index.js.map +1 -0
  46. package/{src/events.ts → dist/events.d.ts} +4 -2
  47. package/dist/events.d.ts.map +1 -0
  48. package/dist/events.js +17 -0
  49. package/dist/events.js.map +1 -0
  50. package/dist/index.cjs +38 -0
  51. package/dist/index.d.ts +17 -1303
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +38 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/lifecycle/BlocLifecycle.d.ts +51 -0
  56. package/dist/lifecycle/BlocLifecycle.d.ts.map +1 -0
  57. package/dist/lifecycle/BlocLifecycle.js +123 -0
  58. package/dist/lifecycle/BlocLifecycle.js.map +1 -0
  59. package/dist/lifecycle/index.d.ts +2 -0
  60. package/dist/lifecycle/index.d.ts.map +1 -0
  61. package/dist/lifecycle/index.js +18 -0
  62. package/dist/lifecycle/index.js.map +1 -0
  63. package/dist/plugins/BlocPluginRegistry.d.ts +58 -0
  64. package/dist/plugins/BlocPluginRegistry.d.ts.map +1 -0
  65. package/dist/plugins/BlocPluginRegistry.js +201 -0
  66. package/dist/plugins/BlocPluginRegistry.js.map +1 -0
  67. package/dist/plugins/SystemPluginRegistry.d.ts +79 -0
  68. package/dist/plugins/SystemPluginRegistry.d.ts.map +1 -0
  69. package/dist/plugins/SystemPluginRegistry.js +184 -0
  70. package/dist/plugins/SystemPluginRegistry.js.map +1 -0
  71. package/{src/plugins/index.ts → dist/plugins/index.d.ts} +1 -5
  72. package/dist/plugins/index.d.ts.map +1 -0
  73. package/dist/plugins/index.js +26 -0
  74. package/dist/plugins/index.js.map +1 -0
  75. package/dist/plugins/types.d.ts +103 -0
  76. package/dist/plugins/types.d.ts.map +1 -0
  77. package/dist/plugins/types.js +3 -0
  78. package/dist/plugins/types.js.map +1 -0
  79. package/dist/subscription/SubscriptionManager.d.ts +67 -0
  80. package/dist/subscription/SubscriptionManager.d.ts.map +1 -0
  81. package/dist/subscription/SubscriptionManager.js +317 -0
  82. package/dist/subscription/SubscriptionManager.js.map +1 -0
  83. package/{src/subscription/index.ts → dist/subscription/index.d.ts} +1 -0
  84. package/dist/subscription/index.d.ts.map +1 -0
  85. package/dist/subscription/index.js +19 -0
  86. package/dist/subscription/index.js.map +1 -0
  87. package/dist/subscription/types.d.ts +65 -0
  88. package/dist/subscription/types.d.ts.map +1 -0
  89. package/dist/subscription/types.js +3 -0
  90. package/dist/subscription/types.js.map +1 -0
  91. package/dist/testing.d.ts +85 -0
  92. package/dist/testing.d.ts.map +1 -0
  93. package/dist/testing.js +186 -0
  94. package/dist/testing.js.map +1 -0
  95. package/{src/types.ts → dist/types.d.ts} +11 -28
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +3 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/utils/BatchingManager.d.ts +28 -0
  100. package/dist/utils/BatchingManager.d.ts.map +1 -0
  101. package/dist/utils/BatchingManager.js +48 -0
  102. package/dist/utils/BatchingManager.js.map +1 -0
  103. package/dist/utils/RerenderLogger.d.ts +60 -0
  104. package/dist/utils/RerenderLogger.d.ts.map +1 -0
  105. package/dist/utils/RerenderLogger.js +205 -0
  106. package/dist/utils/RerenderLogger.js.map +1 -0
  107. package/dist/utils/generateInstanceId.d.ts +11 -0
  108. package/dist/utils/generateInstanceId.d.ts.map +1 -0
  109. package/dist/utils/generateInstanceId.js +50 -0
  110. package/dist/utils/generateInstanceId.js.map +1 -0
  111. package/dist/utils/shallowEqual.d.ts +9 -0
  112. package/dist/utils/shallowEqual.d.ts.map +1 -0
  113. package/dist/utils/shallowEqual.js +35 -0
  114. package/dist/utils/shallowEqual.js.map +1 -0
  115. package/dist/utils/uuid.d.ts +10 -0
  116. package/dist/utils/uuid.d.ts.map +1 -0
  117. package/dist/utils/uuid.js +24 -0
  118. package/dist/utils/uuid.js.map +1 -0
  119. package/package.json +17 -10
  120. package/dist/index.cjs.js +0 -11
  121. package/dist/index.cjs.js.map +0 -1
  122. package/dist/index.es.js +0 -2275
  123. package/dist/index.es.js.map +0 -1
  124. package/src/Blac.ts +0 -802
  125. package/src/Bloc.ts +0 -180
  126. package/src/BlocBase.ts +0 -398
  127. package/src/Cubit.ts +0 -68
  128. package/src/__tests__/Blac.config.test.ts +0 -79
  129. package/src/__tests__/Bloc.event.test.ts +0 -394
  130. package/src/__tests__/BlocBase.subscription.test.ts +0 -349
  131. package/src/__tests__/Cubit.test.ts +0 -462
  132. package/src/__tests__/memory-leaks.test.ts +0 -383
  133. package/src/__tests__/plugins.test.ts +0 -464
  134. package/src/adapter/BlacAdapter.ts +0 -467
  135. package/src/adapter/ProxyFactory.ts +0 -249
  136. package/src/adapter/__tests__/BlacAdapter.test.ts +0 -555
  137. package/src/adapter/__tests__/ProxyFactory.test.ts +0 -655
  138. package/src/errors/BlacError.ts +0 -69
  139. package/src/errors/ErrorManager.ts +0 -101
  140. package/src/errors/handleError.ts +0 -114
  141. package/src/errors/index.ts +0 -13
  142. package/src/index.ts +0 -26
  143. package/src/lifecycle/BlocLifecycle.ts +0 -156
  144. package/src/lifecycle/index.ts +0 -1
  145. package/src/plugins/BlocPluginRegistry.ts +0 -240
  146. package/src/plugins/SystemPluginRegistry.ts +0 -242
  147. package/src/plugins/__tests__/BlocPluginRegistry.test.ts +0 -450
  148. package/src/plugins/__tests__/SystemPluginRegistry.test.ts +0 -404
  149. package/src/plugins/types.ts +0 -129
  150. package/src/subscription/README.md +0 -132
  151. package/src/subscription/SubscriptionManager.ts +0 -395
  152. package/src/subscription/__tests__/SubscriptionManager.test.ts +0 -355
  153. package/src/subscription/types.ts +0 -90
  154. package/src/testing.ts +0 -246
  155. package/src/utils/BatchingManager.ts +0 -59
  156. package/src/utils/RerenderLogger.ts +0 -265
  157. package/src/utils/__tests__/generateInstanceId.test.ts +0 -104
  158. package/src/utils/__tests__/shallowEqual.test.ts +0 -171
  159. package/src/utils/__tests__/uuid.test.ts +0 -144
  160. package/src/utils/generateInstanceId.ts +0 -54
  161. package/src/utils/shallowEqual.ts +0 -40
  162. package/src/utils/uuid.ts +0 -22
@@ -1,383 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import { Blac } from '../Blac';
3
- import { Cubit } from '../Cubit';
4
- import { Bloc } from '../Bloc';
5
- import { BlacAdapter } from '../adapter/BlacAdapter';
6
-
7
- // Helper to force garbage collection if available
8
- const forceGC = () => {
9
- if ((global as any).gc) {
10
- (global as any).gc();
11
- }
12
- };
13
-
14
- // Helper to wait for WeakRef cleanup
15
- const waitForCleanup = async (checkFn: () => boolean, maxWait = 1000) => {
16
- const start = Date.now();
17
- while (Date.now() - start < maxWait) {
18
- forceGC();
19
- await new Promise((resolve) => setTimeout(resolve, 10));
20
- if (checkFn()) return true;
21
- }
22
- return false;
23
- };
24
-
25
- // Test state class
26
- class TestState {
27
- constructor(public value: number) {}
28
- }
29
-
30
- // Test Cubit
31
- class TestCubit extends Cubit<TestState> {
32
- constructor() {
33
- super(new TestState(0));
34
- }
35
-
36
- increment = () => {
37
- this.emit(new TestState(this.state.value + 1));
38
- };
39
- }
40
-
41
- // Test event
42
- class IncrementEvent {
43
- constructor(public amount: number) {}
44
- }
45
-
46
- // Test Bloc
47
- class TestBloc extends Bloc<TestState, IncrementEvent> {
48
- constructor() {
49
- super(new TestState(0));
50
- this.on(IncrementEvent, this.handleIncrement);
51
- }
52
-
53
- handleIncrement = (
54
- event: IncrementEvent,
55
- emit: (state: TestState) => void,
56
- ) => {
57
- emit(new TestState(this.state.value + event.amount));
58
- };
59
- }
60
-
61
- describe('Memory Leak Tests', () => {
62
- let blac: Blac;
63
-
64
- beforeEach(() => {
65
- blac = Blac.getInstance();
66
- Blac.enableLog = false; // Disable logging for tests
67
- vi.useFakeTimers();
68
- });
69
-
70
- afterEach(() => {
71
- vi.useRealTimers();
72
- Blac.resetInstance();
73
- });
74
-
75
- describe('WeakRef Cleanup', () => {
76
- it('should support component WeakRefs for automatic cleanup', async () => {
77
- const cubit = blac.getBloc(TestCubit);
78
- let component: any = { id: 'test-component' };
79
- const weakRef = new WeakRef(component);
80
-
81
- // Subscribe with component reference
82
- const unsubscribe = cubit.subscribeComponent(weakRef, () => {});
83
- expect(cubit.subscriptionCount).toBe(1);
84
-
85
- // Verify the subscription works
86
- const callback = vi.fn();
87
- cubit.subscribeComponent(weakRef, callback);
88
- cubit.increment();
89
- expect(callback).toHaveBeenCalled();
90
-
91
- // Clean up
92
- unsubscribe();
93
- });
94
-
95
- it('should handle multiple subscriptions with weak references', async () => {
96
- const cubit = blac.getBloc(TestCubit);
97
- const component1 = { id: 'component-1' };
98
- const component2 = { id: 'component-2' };
99
- const component3 = { id: 'component-3' };
100
-
101
- // Add subscriptions with weak refs
102
- const unsub1 = cubit.subscribeComponent(
103
- new WeakRef(component1),
104
- () => {},
105
- );
106
- const unsub2 = cubit.subscribeComponent(
107
- new WeakRef(component2),
108
- () => {},
109
- );
110
- const unsub3 = cubit.subscribeComponent(
111
- new WeakRef(component3),
112
- () => {},
113
- );
114
-
115
- expect(cubit.subscriptionCount).toBe(3);
116
-
117
- // Remove some subscriptions
118
- unsub1();
119
- unsub2();
120
-
121
- expect(cubit.subscriptionCount).toBe(1);
122
-
123
- // Clean up remaining
124
- unsub3();
125
- expect(cubit.subscriptionCount).toBe(0);
126
- });
127
- });
128
-
129
- describe('Bloc Instance Disposal', () => {
130
- it('should dispose non-keepAlive blocs when no consumers remain', async () => {
131
- const cubit = blac.getBloc(TestCubit);
132
- const adapter = new BlacAdapter(
133
- { blocConstructor: TestCubit, componentRef: { current: {} } },
134
- {},
135
- );
136
-
137
- // Subscribe and unsubscribe
138
- adapter.mount();
139
- const unsubscribe = adapter.createSubscription({ onChange: () => {} });
140
- expect(cubit.subscriptionCount).toBe(1);
141
-
142
- unsubscribe();
143
- adapter.unmount();
144
-
145
- // Wait for disposal
146
- await vi.runAllTimersAsync();
147
-
148
- // Bloc should be disposed
149
- expect(cubit.isDisposed).toBe(true);
150
- });
151
-
152
- it('should not dispose keepAlive blocs when no consumers remain', async () => {
153
- class KeepAliveCubit extends TestCubit {
154
- static keepAlive = true;
155
- }
156
-
157
- const cubit = blac.getBloc(KeepAliveCubit);
158
- const adapter = new BlacAdapter(
159
- { blocConstructor: KeepAliveCubit, componentRef: { current: {} } },
160
- {},
161
- );
162
-
163
- // Subscribe and unsubscribe
164
- adapter.mount();
165
- const unsubscribe = adapter.createSubscription({ onChange: () => {} });
166
- expect(cubit.subscriptionCount).toBe(1);
167
-
168
- unsubscribe();
169
-
170
- // Wait for potential disposal
171
- await vi.runAllTimersAsync();
172
-
173
- // Bloc should still be active
174
- expect(cubit.isDisposed).toBe(false);
175
- });
176
- });
177
-
178
- describe('Memory Pressure Scenarios', () => {
179
- it('should handle rapid subscription addition/removal without leaks', async () => {
180
- const cubit = blac.getBloc(TestCubit);
181
- const unsubscribes: (() => void)[] = [];
182
-
183
- // Add many subscriptions
184
- for (let i = 0; i < 1000; i++) {
185
- const unsub = cubit.subscribe(() => {});
186
- unsubscribes.push(unsub);
187
- }
188
-
189
- expect(cubit.subscriptionCount).toBe(1000);
190
-
191
- // Remove half the subscriptions
192
- for (let i = 0; i < 500; i++) {
193
- unsubscribes[i]();
194
- }
195
-
196
- expect(cubit.subscriptionCount).toBe(500);
197
-
198
- // Remove remaining subscriptions
199
- for (let i = 500; i < 1000; i++) {
200
- unsubscribes[i]();
201
- }
202
-
203
- expect(cubit.subscriptionCount).toBe(0);
204
- });
205
-
206
- it('should handle concurrent bloc creation and disposal', async () => {
207
- const adapters: BlacAdapter<typeof TestBloc>[] = [];
208
- const unsubscribes: (() => void)[] = [];
209
-
210
- // Create many blocs through adapters
211
- for (let i = 0; i < 100; i++) {
212
- const adapter = new BlacAdapter(
213
- { blocConstructor: TestBloc, componentRef: { current: {} } },
214
- { instanceId: `test-bloc-${i}` },
215
- );
216
- adapters.push(adapter);
217
- adapter.mount();
218
- const unsub = adapter.createSubscription({ onChange: () => {} });
219
- unsubscribes.push(unsub);
220
- }
221
-
222
- // Unsubscribe all and unmount
223
- unsubscribes.forEach((unsub) => unsub());
224
- adapters.forEach((adapter) => adapter.unmount());
225
-
226
- // Wait for disposal
227
- await vi.runAllTimersAsync();
228
-
229
- // All blocs should be disposed
230
- for (const adapter of adapters) {
231
- expect(adapter.blocInstance.isDisposed).toBe(true);
232
- }
233
- });
234
- });
235
-
236
- describe('Proxy and Cache Cleanup', () => {
237
- it('should not leak memory through proxy caches', async () => {
238
- const { ProxyFactory } = await import('../adapter/ProxyFactory');
239
- const { createStateProxy, getStats, resetStats } = ProxyFactory;
240
- const stats = getStats();
241
- const initialProxyCount = stats.stateProxiesCreated || 0;
242
-
243
- // Create many proxied states
244
- for (let i = 0; i < 100; i++) {
245
- const cubit = new TestCubit();
246
- const proxy = createStateProxy({
247
- target: cubit.state,
248
- consumerRef: { current: {} },
249
- consumerTracker: {
250
- trackAccess: () => {},
251
- } as any,
252
- });
253
- // Access properties to trigger proxy creation
254
- const _ = proxy.value;
255
- }
256
-
257
- // Proxies should have been created
258
- const newStats = getStats();
259
- expect(newStats.stateProxiesCreated || 0).toBeGreaterThan(
260
- initialProxyCount,
261
- );
262
-
263
- // Clear stats
264
- resetStats();
265
- const clearedStats = getStats();
266
- expect(clearedStats.stateProxiesCreated || 0).toBe(0);
267
- });
268
- });
269
-
270
- describe('Event Queue Memory Management', () => {
271
- it('should not accumulate events in queue indefinitely', async () => {
272
- const bloc = blac.getBloc(TestBloc);
273
-
274
- // Add many events rapidly
275
- for (let i = 0; i < 1000; i++) {
276
- bloc.add(new IncrementEvent(1));
277
- }
278
-
279
- // Wait for processing
280
- await vi.runAllTimersAsync();
281
-
282
- // Queue should be empty after processing
283
- expect((bloc as any)._eventQueue.length).toBe(0);
284
- });
285
-
286
- it('should handle disposal during event processing', async () => {
287
- const bloc = blac.getBloc(TestBloc);
288
- const adapter = new BlacAdapter(
289
- { blocConstructor: TestBloc, componentRef: { current: {} } },
290
- {},
291
- );
292
-
293
- // Subscribe
294
- adapter.mount();
295
- const unsubscribe = adapter.createSubscription({ onChange: () => {} });
296
-
297
- // Add events and immediately dispose
298
- for (let i = 0; i < 10; i++) {
299
- bloc.add(new IncrementEvent(1));
300
- }
301
-
302
- unsubscribe();
303
- adapter.unmount();
304
-
305
- // Wait for disposal
306
- await vi.runAllTimersAsync();
307
-
308
- // Bloc should be disposed and queue cleared
309
- expect(bloc.isDisposed).toBe(true);
310
- expect((bloc as any)._eventQueue.length).toBe(0);
311
- });
312
- });
313
-
314
- describe('Disposal State Transitions', () => {
315
- it('should handle concurrent disposal requests safely', async () => {
316
- const cubit = blac.getBloc(TestCubit);
317
- const adapter = new BlacAdapter(
318
- { blocConstructor: TestCubit, componentRef: { current: {} } },
319
- {},
320
- );
321
-
322
- // Add multiple consumers
323
- adapter.mount();
324
- const unsub1 = adapter.createSubscription({ onChange: () => {} });
325
- const adapter2 = new BlacAdapter(
326
- { blocConstructor: TestCubit, componentRef: { current: {} } },
327
- {},
328
- );
329
- adapter2.mount();
330
- const unsub2 = adapter2.createSubscription({ onChange: () => {} });
331
-
332
- // Remove consumers concurrently
333
- await Promise.all([
334
- (async () => {
335
- unsub1();
336
- adapter.unmount();
337
- })(),
338
- (async () => {
339
- unsub2();
340
- adapter2.unmount();
341
- })(),
342
- ]);
343
-
344
- // Wait for disposal
345
- await vi.runAllTimersAsync();
346
-
347
- // Should be disposed exactly once
348
- expect(cubit.isDisposed).toBe(true);
349
- });
350
-
351
- it('should prevent state updates after disposal', async () => {
352
- const cubit = blac.getBloc(TestCubit);
353
- const adapter = new BlacAdapter(
354
- { blocConstructor: TestCubit, componentRef: { current: {} } },
355
- {},
356
- );
357
-
358
- // Subscribe and start disposal
359
- adapter.mount();
360
- const unsub = adapter.createSubscription({ onChange: () => {} });
361
- unsub();
362
- adapter.unmount();
363
-
364
- // Wait for disposal to complete
365
- await vi.runAllTimersAsync();
366
-
367
- expect(cubit.isDisposed).toBe(true);
368
-
369
- // Try to update state after disposal
370
- const callback = vi.fn();
371
- const unsubscribe = cubit.subscribe(callback);
372
-
373
- // State should not change
374
- const initialState = cubit.state;
375
- cubit.increment();
376
-
377
- // State should remain unchanged
378
- expect(cubit.state).toBe(initialState);
379
- expect(callback).not.toHaveBeenCalled();
380
- unsubscribe();
381
- });
382
- });
383
- });