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

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 (157) 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 +624 -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 +67 -0
  19. package/dist/adapter/BlacAdapter.d.ts.map +1 -0
  20. package/dist/adapter/BlacAdapter.js +263 -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/{src/index.ts → dist/index.d.ts} +1 -10
  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 +33 -0
  92. package/dist/testing.d.ts.map +1 -0
  93. package/dist/testing.js +68 -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 +19 -6
  120. package/src/Blac.ts +0 -802
  121. package/src/Bloc.ts +0 -180
  122. package/src/BlocBase.ts +0 -398
  123. package/src/Cubit.ts +0 -68
  124. package/src/__tests__/Blac.config.test.ts +0 -79
  125. package/src/__tests__/Bloc.event.test.ts +0 -394
  126. package/src/__tests__/BlocBase.subscription.test.ts +0 -349
  127. package/src/__tests__/Cubit.test.ts +0 -462
  128. package/src/__tests__/memory-leaks.test.ts +0 -383
  129. package/src/__tests__/plugins.test.ts +0 -464
  130. package/src/adapter/BlacAdapter.ts +0 -467
  131. package/src/adapter/ProxyFactory.ts +0 -249
  132. package/src/adapter/__tests__/BlacAdapter.test.ts +0 -555
  133. package/src/adapter/__tests__/ProxyFactory.test.ts +0 -655
  134. package/src/errors/BlacError.ts +0 -69
  135. package/src/errors/ErrorManager.ts +0 -101
  136. package/src/errors/handleError.ts +0 -114
  137. package/src/errors/index.ts +0 -13
  138. package/src/lifecycle/BlocLifecycle.ts +0 -156
  139. package/src/lifecycle/index.ts +0 -1
  140. package/src/plugins/BlocPluginRegistry.ts +0 -240
  141. package/src/plugins/SystemPluginRegistry.ts +0 -242
  142. package/src/plugins/__tests__/BlocPluginRegistry.test.ts +0 -450
  143. package/src/plugins/__tests__/SystemPluginRegistry.test.ts +0 -404
  144. package/src/plugins/types.ts +0 -129
  145. package/src/subscription/README.md +0 -132
  146. package/src/subscription/SubscriptionManager.ts +0 -395
  147. package/src/subscription/__tests__/SubscriptionManager.test.ts +0 -355
  148. package/src/subscription/types.ts +0 -90
  149. package/src/testing.ts +0 -246
  150. package/src/utils/BatchingManager.ts +0 -59
  151. package/src/utils/RerenderLogger.ts +0 -265
  152. package/src/utils/__tests__/generateInstanceId.test.ts +0 -104
  153. package/src/utils/__tests__/shallowEqual.test.ts +0 -171
  154. package/src/utils/__tests__/uuid.test.ts +0 -144
  155. package/src/utils/generateInstanceId.ts +0 -54
  156. package/src/utils/shallowEqual.ts +0 -40
  157. package/src/utils/uuid.ts +0 -22
@@ -1,462 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { Cubit } from '../Cubit';
3
- import { Blac } from '../Blac';
4
-
5
- // Test Cubit implementations
6
- class CounterCubit extends Cubit<number> {
7
- constructor(initialValue = 0) {
8
- super(initialValue);
9
- }
10
-
11
- increment = () => this.emit(this.state + 1);
12
- decrement = () => this.emit(this.state - 1);
13
- set = (value: number) => this.emit(value);
14
- }
15
-
16
- interface UserState {
17
- name: string;
18
- age: number;
19
- email: string;
20
- preferences?: {
21
- theme: string;
22
- notifications: boolean;
23
- };
24
- }
25
-
26
- class UserCubit extends Cubit<UserState> {
27
- constructor() {
28
- super({
29
- name: 'John Doe',
30
- age: 30,
31
- email: 'john@example.com',
32
- });
33
- }
34
-
35
- updateName = (name: string) => {
36
- this.patch({ name });
37
- };
38
-
39
- updateMultiple = (updates: Partial<UserState>) => {
40
- this.patch(updates);
41
- };
42
-
43
- setPreferences = (theme: string, notifications: boolean) => {
44
- this.patch({
45
- preferences: { theme, notifications },
46
- });
47
- };
48
- }
49
-
50
- class PrimitiveCubit extends Cubit<string> {
51
- constructor() {
52
- super('initial');
53
- }
54
-
55
- update = (value: string) => this.emit(value);
56
- }
57
-
58
- describe('Cubit State Emissions', () => {
59
- let blacInstance: Blac;
60
-
61
- beforeEach(() => {
62
- blacInstance = new Blac({ __unsafe_ignore_singleton: true });
63
- Blac.enableLog = false;
64
- vi.clearAllMocks();
65
- });
66
-
67
- describe('Basic emit() functionality', () => {
68
- it('should emit new state and notify observers', () => {
69
- const cubit = new CounterCubit();
70
- const observer = vi.fn();
71
-
72
- cubit.subscribe(observer);
73
-
74
- cubit.increment();
75
-
76
- expect(observer).toHaveBeenCalledWith(1);
77
- expect(cubit.state).toBe(1);
78
- });
79
-
80
- it('should not emit when new state is identical (Object.is comparison)', () => {
81
- const cubit = new CounterCubit(5);
82
- const observer = vi.fn();
83
-
84
- cubit.subscribe(observer);
85
-
86
- // Try to emit same value
87
- cubit.set(5);
88
-
89
- expect(observer).not.toHaveBeenCalled();
90
- expect(cubit.state).toBe(5);
91
- });
92
-
93
- it('should handle NaN correctly with Object.is', () => {
94
- const cubit = new CounterCubit(NaN);
95
- const observer = vi.fn();
96
-
97
- cubit.subscribe(observer);
98
-
99
- // NaN === NaN is false, but Object.is(NaN, NaN) is true
100
- cubit.set(NaN);
101
-
102
- expect(observer).not.toHaveBeenCalled();
103
- });
104
-
105
- it('should distinguish between +0 and -0', () => {
106
- const cubit = new CounterCubit(0);
107
- const observer = vi.fn();
108
-
109
- cubit.subscribe(observer);
110
-
111
- // Object.is can distinguish +0 and -0
112
- cubit.set(-0);
113
-
114
- expect(observer).toHaveBeenCalledWith(-0);
115
- });
116
-
117
- it('should emit multiple state changes sequentially', () => {
118
- const cubit = new CounterCubit();
119
- const observer = vi.fn();
120
-
121
- cubit.subscribe(observer);
122
-
123
- cubit.increment();
124
- cubit.increment();
125
- cubit.decrement();
126
-
127
- expect(observer).toHaveBeenCalledTimes(3);
128
- expect(observer).toHaveBeenNthCalledWith(1, 1);
129
- expect(observer).toHaveBeenNthCalledWith(2, 2);
130
- expect(observer).toHaveBeenNthCalledWith(3, 1);
131
- expect(cubit.state).toBe(1);
132
- });
133
- });
134
-
135
- describe('patch() functionality for object states', () => {
136
- it('should partially update object state', () => {
137
- const cubit = new UserCubit();
138
- const observer = vi.fn();
139
-
140
- cubit.subscribe(observer);
141
-
142
- cubit.updateName('Jane Doe');
143
-
144
- expect(observer).toHaveBeenCalledWith({
145
- name: 'Jane Doe',
146
- age: 30,
147
- email: 'john@example.com',
148
- });
149
- expect(cubit.state.name).toBe('Jane Doe');
150
- expect(cubit.state.age).toBe(30); // Unchanged
151
- });
152
-
153
- it('should update multiple properties at once', () => {
154
- const cubit = new UserCubit();
155
- const observer = vi.fn();
156
-
157
- cubit.subscribe(observer);
158
-
159
- cubit.updateMultiple({ name: 'Jane Smith', age: 25 });
160
-
161
- expect(observer).toHaveBeenCalledTimes(1);
162
- expect(cubit.state).toEqual({
163
- name: 'Jane Smith',
164
- age: 25,
165
- email: 'john@example.com',
166
- });
167
- });
168
-
169
- it('should not emit when patched values are identical', () => {
170
- const cubit = new UserCubit();
171
- const observer = vi.fn();
172
-
173
- cubit.subscribe(observer);
174
-
175
- // Patch with same values
176
- cubit.patch({ name: 'John Doe', age: 30 });
177
-
178
- expect(observer).not.toHaveBeenCalled();
179
- });
180
-
181
- it('should emit when at least one patched value differs', () => {
182
- const cubit = new UserCubit();
183
- const observer = vi.fn();
184
-
185
- cubit.subscribe(observer);
186
-
187
- // One value different
188
- cubit.patch({ name: 'John Doe', age: 31 });
189
-
190
- expect(observer).toHaveBeenCalledTimes(1);
191
- expect(cubit.state.age).toBe(31);
192
- });
193
-
194
- it('should handle nested object updates', () => {
195
- const cubit = new UserCubit();
196
- const observer = vi.fn();
197
-
198
- cubit.subscribe(observer);
199
-
200
- cubit.setPreferences('dark', true);
201
-
202
- expect(observer).toHaveBeenCalledTimes(1);
203
- expect(cubit.state.preferences).toEqual({
204
- theme: 'dark',
205
- notifications: true,
206
- });
207
- });
208
-
209
- it('should handle patch with ignoreChangeCheck flag', () => {
210
- const cubit = new UserCubit();
211
- const observer = vi.fn();
212
-
213
- cubit.subscribe(observer);
214
-
215
- // Force emit even with same values
216
- cubit.patch({ name: 'John Doe' }, true);
217
-
218
- expect(observer).toHaveBeenCalledTimes(1);
219
- });
220
-
221
- it('should warn when patch is called on non-object state', () => {
222
- const cubit = new PrimitiveCubit();
223
- const warnSpy = vi.spyOn(Blac, 'warn').mockImplementation(() => {});
224
-
225
- cubit.patch('new value' as any);
226
-
227
- expect(warnSpy).toHaveBeenCalledWith(
228
- expect.stringContaining(
229
- 'Cubit.patch: was called on a cubit where the state is not an object',
230
- ),
231
- );
232
- expect(cubit.state).toBe('initial'); // State unchanged
233
- });
234
-
235
- it('should handle null state gracefully', () => {
236
- class NullStateCubit extends Cubit<null> {
237
- constructor() {
238
- super(null);
239
- }
240
- }
241
-
242
- const cubit = new NullStateCubit();
243
- const warnSpy = vi.spyOn(Blac, 'warn').mockImplementation(() => {});
244
-
245
- cubit.patch({} as any);
246
-
247
- expect(warnSpy).toHaveBeenCalled();
248
- expect(cubit.state).toBe(null);
249
- });
250
- });
251
-
252
- describe('State change detection edge cases', () => {
253
- it('should detect changes in array states', () => {
254
- class ArrayCubit extends Cubit<number[]> {
255
- constructor() {
256
- super([1, 2, 3]);
257
- }
258
-
259
- add = (num: number) => {
260
- this.emit([...this.state, num]);
261
- };
262
-
263
- updateIndex = (index: number, value: number) => {
264
- const newArray = [...this.state];
265
- newArray[index] = value;
266
- this.emit(newArray);
267
- };
268
- }
269
-
270
- const cubit = new ArrayCubit();
271
- const observer = vi.fn();
272
-
273
- cubit.subscribe(observer);
274
-
275
- // New array reference should trigger update
276
- cubit.add(4);
277
- expect(observer).toHaveBeenCalledTimes(1);
278
- expect(cubit.state).toEqual([1, 2, 3, 4]);
279
-
280
- // Same array reference should not trigger
281
- observer.mockClear();
282
- const currentState = cubit.state;
283
- cubit.emit(currentState);
284
- expect(observer).not.toHaveBeenCalled();
285
- });
286
-
287
- it('should handle undefined and null transitions', () => {
288
- class NullableCubit extends Cubit<string | null | undefined> {
289
- constructor() {
290
- super('initial');
291
- }
292
-
293
- setNull = () => this.emit(null);
294
- setUndefined = () => this.emit(undefined);
295
- setString = (s: string) => this.emit(s);
296
- }
297
-
298
- const cubit = new NullableCubit();
299
- const observer = vi.fn();
300
-
301
- cubit.subscribe(observer);
302
-
303
- // null and undefined are different according to Object.is
304
- expect(Object.is(null, undefined)).toBe(false);
305
-
306
- cubit.setNull();
307
- expect(observer).toHaveBeenCalledWith(null);
308
- expect(cubit.state).toBe(null);
309
-
310
- observer.mockClear();
311
-
312
- // NOTE: There's a limitation in BlocBase._pushState that prevents undefined states
313
- // It has a validation: if (newState === undefined) return;
314
- // So undefined cannot be emitted as a state
315
- cubit.setUndefined();
316
-
317
- // State should remain null since undefined is rejected
318
- expect(observer).not.toHaveBeenCalled();
319
- expect(cubit.state).toBe(null);
320
-
321
- observer.mockClear();
322
- cubit.setString('value');
323
- expect(observer).toHaveBeenCalledWith('value');
324
- expect(cubit.state).toBe('value');
325
- });
326
-
327
- it('should handle complex object comparisons', () => {
328
- interface ComplexState {
329
- data: { id: number; values: number[] };
330
- metadata: Map<string, any>;
331
- }
332
-
333
- class ComplexCubit extends Cubit<ComplexState> {
334
- constructor() {
335
- super({
336
- data: { id: 1, values: [1, 2, 3] },
337
- metadata: new Map([['key', 'value']]),
338
- });
339
- }
340
-
341
- updateData = (data: ComplexState['data']) => {
342
- this.patch({ data });
343
- };
344
- }
345
-
346
- const cubit = new ComplexCubit();
347
- const observer = vi.fn();
348
-
349
- cubit.subscribe(observer);
350
-
351
- // Different object reference with same values
352
- cubit.updateData({ id: 1, values: [1, 2, 3] });
353
-
354
- // Should emit because object reference is different
355
- expect(observer).toHaveBeenCalledTimes(1);
356
- });
357
- });
358
-
359
- describe('Integration with BlocBase', () => {
360
- it('should properly inherit from BlocBase', () => {
361
- const cubit = new CounterCubit();
362
-
363
- // Should have BlocBase properties and methods
364
- expect(cubit.state).toBe(0);
365
- expect(cubit._subscriptionManager).toBeDefined();
366
- expect(typeof cubit.subscribe).toBe('function');
367
- });
368
-
369
- it('should work with state batching', () => {
370
- const cubit = new CounterCubit();
371
- const observer = vi.fn();
372
-
373
- cubit.subscribe(observer);
374
-
375
- cubit._batchUpdates(() => {
376
- cubit.increment(); // 0 -> 1
377
- cubit.increment(); // 1 -> 2
378
- cubit.increment(); // 2 -> 3
379
- });
380
-
381
- // Should only notify once with final state
382
- // The oldState in the batch notification is from the last update (2 -> 3)
383
- expect(observer).toHaveBeenCalledTimes(1);
384
- expect(observer).toHaveBeenCalledWith(3);
385
- expect(cubit.state).toBe(3);
386
- });
387
-
388
- it('should maintain state history correctly', () => {
389
- const cubit = new CounterCubit();
390
-
391
- cubit.increment();
392
- // Old state tracking was removed in new model
393
- expect(cubit.state).toBe(1);
394
-
395
- cubit.increment();
396
- expect(cubit.state).toBe(2);
397
- });
398
- });
399
-
400
- describe('Memory and Performance', () => {
401
- it('should not leak memory with rapid emissions', () => {
402
- const cubit = new CounterCubit();
403
- const observer = vi.fn();
404
-
405
- cubit.subscribe(observer);
406
-
407
- // Rapid emissions
408
- for (let i = 0; i < 1000; i++) {
409
- cubit.increment();
410
- }
411
-
412
- expect(cubit.state).toBe(1000);
413
- expect(observer).toHaveBeenCalledTimes(1000);
414
-
415
- // Check final state
416
- expect(cubit.state).toBe(1000);
417
- });
418
-
419
- it('should handle concurrent patch operations', () => {
420
- const cubit = new UserCubit();
421
- const observer = vi.fn();
422
-
423
- cubit.subscribe(observer);
424
-
425
- // Multiple patches in quick succession
426
- cubit.patch({ name: 'Name1' });
427
- cubit.patch({ age: 25 });
428
- cubit.patch({ email: 'new@example.com' });
429
-
430
- expect(observer).toHaveBeenCalledTimes(3);
431
- expect(cubit.state).toEqual({
432
- name: 'Name1',
433
- age: 25,
434
- email: 'new@example.com',
435
- });
436
- });
437
- });
438
-
439
- describe('Type Safety', () => {
440
- it('should maintain type safety with emit', () => {
441
- const cubit = new CounterCubit();
442
-
443
- // TypeScript should enforce number type
444
- cubit.emit(42);
445
- expect(cubit.state).toBe(42);
446
-
447
- // Test that emit only accepts numbers
448
- // cubit.emit('not a number'); // This would be a type error
449
- });
450
-
451
- it('should maintain type safety with patch', () => {
452
- const cubit = new UserCubit();
453
-
454
- // Valid patch
455
- cubit.patch({ name: 'New Name' });
456
-
457
- // Test that patch only accepts valid properties and types
458
- // cubit.patch({ invalidProp: 'value' }); // This would be a type error
459
- // cubit.patch({ age: 'not a number' }); // This would be a type error
460
- });
461
- });
462
- });