@storve/core 1.0.1 → 1.0.3

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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +993 -26
  3. package/dist/adapters/indexedDB.cjs +0 -1
  4. package/dist/adapters/indexedDB.mjs +0 -1
  5. package/dist/adapters/localStorage.cjs +0 -1
  6. package/dist/adapters/localStorage.mjs +0 -1
  7. package/dist/adapters/memory.cjs +0 -1
  8. package/dist/adapters/memory.mjs +0 -1
  9. package/dist/adapters/sessionStorage.cjs +0 -1
  10. package/dist/adapters/sessionStorage.mjs +0 -1
  11. package/dist/async-entry.d.ts +0 -1
  12. package/dist/async.cjs +0 -1
  13. package/dist/async.d.ts +0 -1
  14. package/dist/async.mjs +0 -1
  15. package/dist/batch.d.ts +0 -1
  16. package/dist/compose.d.ts +0 -1
  17. package/dist/computed-entry.d.ts +0 -1
  18. package/dist/computed.cjs +0 -1
  19. package/dist/computed.d.ts +0 -1
  20. package/dist/computed.mjs +0 -1
  21. package/dist/devtools/history.d.ts +0 -1
  22. package/dist/devtools/index.d.ts +0 -1
  23. package/dist/devtools/redux-bridge.d.ts +0 -1
  24. package/dist/devtools/snapshots.d.ts +0 -1
  25. package/dist/devtools/withDevtools.d.ts +0 -1
  26. package/dist/devtools.cjs +0 -1
  27. package/dist/devtools.mjs +0 -1
  28. package/dist/extensions/noop.d.ts +0 -1
  29. package/dist/index.cjs +0 -1
  30. package/dist/index.d.ts +0 -1
  31. package/dist/index.mjs +0 -1
  32. package/dist/persist/adapters/indexedDB.d.ts +0 -1
  33. package/dist/persist/adapters/localStorage.d.ts +0 -1
  34. package/dist/persist/adapters/memory.d.ts +0 -1
  35. package/dist/persist/adapters/sessionStorage.d.ts +0 -1
  36. package/dist/persist/debounce.d.ts +0 -1
  37. package/dist/persist/hydrate.d.ts +0 -1
  38. package/dist/persist/index.d.ts +0 -1
  39. package/dist/persist/serialize.d.ts +0 -1
  40. package/dist/persist.cjs +0 -1
  41. package/dist/persist.mjs +0 -1
  42. package/dist/proxy.d.ts +0 -1
  43. package/dist/registry-qtr1UpFU.js +0 -1
  44. package/dist/registry-zaKZ1P-s.js +0 -1
  45. package/dist/registry.d.ts +0 -1
  46. package/dist/signals/createSignal.d.ts +0 -1
  47. package/dist/signals/index.d.ts +0 -1
  48. package/dist/signals/useSignal.d.ts +0 -1
  49. package/dist/signals.cjs +0 -1
  50. package/dist/signals.mjs +0 -1
  51. package/dist/store.d.ts +0 -1
  52. package/dist/sync/channel.d.ts +0 -1
  53. package/dist/sync/index.d.ts +0 -1
  54. package/dist/sync/protocol.d.ts +0 -1
  55. package/dist/sync/withSync.d.ts +0 -1
  56. package/dist/sync.cjs +0 -1
  57. package/dist/sync.mjs +0 -1
  58. package/dist/types.d.ts +0 -1
  59. package/package.json +9 -3
  60. package/CHANGELOG.md +0 -151
  61. package/benchmarks/run.ts +0 -102
  62. package/benchmarks/week2.md +0 -9
  63. package/benchmarks/week2.ts +0 -64
  64. package/benchmarks/week4.md +0 -13
  65. package/benchmarks/week4.ts +0 -178
  66. package/benchmarks/week5.md +0 -15
  67. package/benchmarks/week5.ts +0 -184
  68. package/coverage/coverage-summary.json +0 -31
  69. package/dist/adapters/indexedDB.cjs.map +0 -1
  70. package/dist/adapters/indexedDB.mjs.map +0 -1
  71. package/dist/adapters/localStorage.cjs.map +0 -1
  72. package/dist/adapters/localStorage.mjs.map +0 -1
  73. package/dist/adapters/memory.cjs.map +0 -1
  74. package/dist/adapters/memory.mjs.map +0 -1
  75. package/dist/adapters/sessionStorage.cjs.map +0 -1
  76. package/dist/adapters/sessionStorage.mjs.map +0 -1
  77. package/dist/async-entry.d.ts.map +0 -1
  78. package/dist/async.cjs.map +0 -1
  79. package/dist/async.d.ts.map +0 -1
  80. package/dist/async.mjs.map +0 -1
  81. package/dist/batch.d.ts.map +0 -1
  82. package/dist/compose.d.ts.map +0 -1
  83. package/dist/computed-entry.d.ts.map +0 -1
  84. package/dist/computed.cjs.map +0 -1
  85. package/dist/computed.d.ts.map +0 -1
  86. package/dist/computed.mjs.map +0 -1
  87. package/dist/devtools/history.d.ts.map +0 -1
  88. package/dist/devtools/index.d.ts.map +0 -1
  89. package/dist/devtools/redux-bridge.d.ts.map +0 -1
  90. package/dist/devtools/snapshots.d.ts.map +0 -1
  91. package/dist/devtools/withDevtools.d.ts.map +0 -1
  92. package/dist/devtools.cjs.map +0 -1
  93. package/dist/devtools.mjs.map +0 -1
  94. package/dist/extensions/noop.d.ts.map +0 -1
  95. package/dist/index.cjs.js +0 -118
  96. package/dist/index.cjs.js.map +0 -1
  97. package/dist/index.cjs.map +0 -1
  98. package/dist/index.d.ts.map +0 -1
  99. package/dist/index.esm.js +0 -116
  100. package/dist/index.esm.js.map +0 -1
  101. package/dist/index.mjs.map +0 -1
  102. package/dist/persist/adapters/indexedDB.d.ts.map +0 -1
  103. package/dist/persist/adapters/localStorage.d.ts.map +0 -1
  104. package/dist/persist/adapters/memory.d.ts.map +0 -1
  105. package/dist/persist/adapters/sessionStorage.d.ts.map +0 -1
  106. package/dist/persist/debounce.d.ts.map +0 -1
  107. package/dist/persist/hydrate.d.ts.map +0 -1
  108. package/dist/persist/index.d.ts.map +0 -1
  109. package/dist/persist/serialize.d.ts.map +0 -1
  110. package/dist/persist.cjs.map +0 -1
  111. package/dist/persist.mjs.map +0 -1
  112. package/dist/proxy.d.ts.map +0 -1
  113. package/dist/registry-D3X0HSbl.js +0 -26
  114. package/dist/registry-D3X0HSbl.js.map +0 -1
  115. package/dist/registry-RDjbeJdx.js +0 -29
  116. package/dist/registry-RDjbeJdx.js.map +0 -1
  117. package/dist/registry-qtr1UpFU.js.map +0 -1
  118. package/dist/registry-zaKZ1P-s.js.map +0 -1
  119. package/dist/registry.d.ts.map +0 -1
  120. package/dist/signals/createSignal.d.ts.map +0 -1
  121. package/dist/signals/index.d.ts.map +0 -1
  122. package/dist/signals/useSignal.d.ts.map +0 -1
  123. package/dist/signals.cjs.map +0 -1
  124. package/dist/signals.mjs.map +0 -1
  125. package/dist/stats.html +0 -4949
  126. package/dist/store.d.ts.map +0 -1
  127. package/dist/sync/channel.d.ts.map +0 -1
  128. package/dist/sync/index.d.ts.map +0 -1
  129. package/dist/sync/protocol.d.ts.map +0 -1
  130. package/dist/sync/withSync.d.ts.map +0 -1
  131. package/dist/sync.cjs.map +0 -1
  132. package/dist/sync.mjs.map +0 -1
  133. package/dist/types.d.ts.map +0 -1
  134. package/rollup.config.mjs +0 -44
  135. package/src/async-entry.ts +0 -6
  136. package/src/async.ts +0 -240
  137. package/src/batch.ts +0 -33
  138. package/src/compose.ts +0 -50
  139. package/src/computed-entry.ts +0 -6
  140. package/src/computed.ts +0 -187
  141. package/src/devtools/history.ts +0 -103
  142. package/src/devtools/index.ts +0 -5
  143. package/src/devtools/redux-bridge.ts +0 -70
  144. package/src/devtools/snapshots.ts +0 -54
  145. package/src/devtools/withDevtools.ts +0 -196
  146. package/src/extensions/noop.ts +0 -12
  147. package/src/index.ts +0 -4
  148. package/src/persist/adapters/indexedDB.ts +0 -114
  149. package/src/persist/adapters/localStorage.ts +0 -28
  150. package/src/persist/adapters/memory.ts +0 -26
  151. package/src/persist/adapters/sessionStorage.ts +0 -28
  152. package/src/persist/debounce.ts +0 -28
  153. package/src/persist/hydrate.ts +0 -60
  154. package/src/persist/index.ts +0 -141
  155. package/src/persist/serialize.ts +0 -60
  156. package/src/proxy.ts +0 -87
  157. package/src/registry.ts +0 -67
  158. package/src/signals/createSignal.ts +0 -81
  159. package/src/signals/index.ts +0 -20
  160. package/src/signals/useSignal.ts +0 -18
  161. package/src/store.ts +0 -250
  162. package/src/sync/channel.ts +0 -15
  163. package/src/sync/index.ts +0 -3
  164. package/src/sync/protocol.ts +0 -18
  165. package/src/sync/withSync.ts +0 -147
  166. package/src/types.ts +0 -159
  167. package/tests/async.test.ts +0 -1100
  168. package/tests/batch.test.ts +0 -41
  169. package/tests/compose.test.ts +0 -209
  170. package/tests/computed.test.ts +0 -867
  171. package/tests/devtools.test.ts +0 -1039
  172. package/tests/integration/persist.integration.test.ts +0 -258
  173. package/tests/integration/signals.integration.test.ts +0 -309
  174. package/tests/integration.test.ts +0 -278
  175. package/tests/persist/adapters/indexedDB.adapter.test.ts +0 -185
  176. package/tests/persist/adapters/localStorage.adapter.test.ts +0 -105
  177. package/tests/persist/adapters/memory.adapter.test.ts +0 -112
  178. package/tests/persist/adapters/sessionStorage.adapter.test.ts +0 -128
  179. package/tests/persist/debounce.test.ts +0 -121
  180. package/tests/persist/hydrate.test.ts +0 -120
  181. package/tests/persist/migrate.test.ts +0 -208
  182. package/tests/persist/persist.test.ts +0 -357
  183. package/tests/persist/serialize.test.ts +0 -128
  184. package/tests/proxy.test.ts +0 -473
  185. package/tests/registry.test.ts +0 -67
  186. package/tests/signals/derived.test.ts +0 -244
  187. package/tests/signals/inference.test.ts +0 -108
  188. package/tests/signals/signal.test.ts +0 -348
  189. package/tests/signals/useSignal.test.tsx +0 -275
  190. package/tests/store.test.ts +0 -482
  191. package/tests/stress.test.ts +0 -268
  192. package/tests/sync.test.ts +0 -576
  193. package/tests/types.test.ts +0 -32
  194. package/tests/v0.3.test.ts +0 -813
  195. package/tree-shake-test.js +0 -1
  196. package/tsconfig.json +0 -15
  197. package/vitest.config.ts +0 -22
  198. package/vitest_play.ts +0 -7
@@ -1,268 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
- import { createStore } from '../src/store';
3
-
4
- describe('4.1 Volume & Scale', () => {
5
- it.each([
6
- ['100', 100],
7
- ['1000', 1000],
8
- ['10000', 10000]
9
- ])('Store with %s keys — all update correctly', (_, count) => {
10
- const initial = Array.from({ length: count as number }).reduce((acc: Record<string, number>, _, i) => { acc[`k${i}`] = 0; return acc; }, {});
11
- const store = createStore(initial);
12
- store.setState({ k1: 1, k99: 1 } as unknown as Partial<typeof initial>);
13
- expect(store.getState().k1).toBe(1);
14
- });
15
-
16
- it('Store with 100 nested objects — all tracked correctly', () => {
17
- const initial = Array.from({ length: 100 }).reduce((acc: Record<string, { val: number }>, _, i) => { acc[`k${i}`] = { val: 0 }; return acc; }, {});
18
- const store = createStore(initial);
19
- const l = vi.fn();
20
- store.subscribe(l);
21
- store.setState({ k50: { val: 1 } } as unknown as Partial<typeof initial>);
22
- expect(l).toHaveBeenCalled();
23
- });
24
-
25
- it.each([
26
- [1000],
27
- [10000]
28
- ])('Store with array of %i items — push notifies correctly', (count) => {
29
- const arr = Array.from({ length: count }).map((_, i) => i);
30
- const store = createStore({ arr });
31
- const l = vi.fn();
32
- store.subscribe(l);
33
- store.setState(s => ({ arr: [...s.arr, 99] }));
34
- expect(l).toHaveBeenCalledTimes(1);
35
- expect(store.getState().arr.length).toBe(count + 1);
36
- });
37
-
38
- it.each([
39
- [1000],
40
- [10000]
41
- ])('%i sequential setState calls — final state is correct, no memory leak', (count) => {
42
- const store = createStore({ val: 0 });
43
- for (let i = 1; i <= count; i++) {
44
- store.setState({ val: i });
45
- }
46
- expect(store.getState().val).toBe(count);
47
- });
48
-
49
- it.each([
50
- [1000]
51
- ])('%i subscribers — all notified correctly', (count) => {
52
- const store = createStore({ a: 1 });
53
- const listeners = Array.from({ length: count }).map(() => vi.fn());
54
- listeners.forEach(l => store.subscribe(l));
55
- store.setState({ a: 2 });
56
- expect(listeners[0]).toHaveBeenCalledTimes(1);
57
- expect(listeners[count - 1]).toHaveBeenCalledTimes(1);
58
- });
59
-
60
- it.each([
61
- [1000],
62
- [10000]
63
- ])('%i subscribe + unsubscribe cycles — no memory leak', (count) => {
64
- const store = createStore({ a: 1 });
65
- const l = vi.fn();
66
- for (let i = 0; i < count; i++) {
67
- const u = store.subscribe(l);
68
- u();
69
- }
70
- expect((store as Record<string, { size?: number }>).listeners?.size || 0).toBe(0);
71
- });
72
- });
73
-
74
- describe('4.2 Performance Assertions', () => {
75
- it('createStore() completes in under 1ms', () => {
76
- const start = performance.now();
77
- createStore({ a: 1 });
78
- expect(performance.now() - start).toBeLessThan(10); // generous for CI
79
- });
80
-
81
- it('getState() completes in under 0.1ms (average over 100k calls)', () => {
82
- const store = createStore({ a: 1 });
83
- const start = performance.now();
84
- for (let i = 0; i < 100000; i++) store.getState();
85
- const duration = performance.now() - start;
86
- expect(duration / 100000).toBeLessThan(0.1);
87
- });
88
-
89
- it('setState() + notify (100 subs) completes in under 1ms', () => {
90
- const store = createStore({ a: 1 });
91
- for (let i = 0; i < 100; i++) store.subscribe(() => { });
92
- const start = performance.now();
93
- store.setState({ a: 2 });
94
- expect(performance.now() - start).toBeLessThan(15);
95
- });
96
-
97
- it('Nested read (3 levels) completes in under 0.1ms (average over 100k)', () => {
98
- const store = createStore({ a: { b: { c: 1 } } });
99
- const start = performance.now();
100
- for (let i = 0; i < 100000; i++) {
101
- void store.getState().a.b.c;
102
- }
103
- const duration = performance.now() - start;
104
- expect(duration / 100000).toBeLessThan(0.1);
105
- });
106
-
107
- it('Subscribe + unsubscribe cycle under 0.1ms (average over 100k)', () => {
108
- const store = createStore({ a: 1 });
109
- const start = performance.now();
110
- for (let i = 0; i < 100000; i++) {
111
- const u = store.subscribe(() => { });
112
- u();
113
- }
114
- const duration = performance.now() - start;
115
- expect(duration / 100000).toBeLessThan(0.1);
116
- });
117
-
118
- it('Store with 1000 keys — setState under 5ms', () => {
119
- const initial = Array.from({ length: 1000 }).reduce((acc: Record<string, number>, _, i) => { acc[`k${i}`] = 0; return acc; }, {});
120
- const store = createStore(initial);
121
- const start = performance.now();
122
- store.setState({ k500: 1 } as unknown as Partial<typeof initial>);
123
- expect(performance.now() - start).toBeLessThan(100);
124
- });
125
-
126
- it('1000 subscribers notified — under 10ms total', () => {
127
- const store = createStore({ a: 1 });
128
- for (let i = 0; i < 1000; i++) store.subscribe(() => { });
129
- const start = performance.now();
130
- store.setState({ a: 2 });
131
- expect(performance.now() - start).toBeLessThan(50);
132
- });
133
- });
134
-
135
- describe('4.3 Memory Safety', () => {
136
- it('No memory leak after 10000 subscribe/unsubscribe cycles', () => {
137
- const store = createStore({ a: 1 });
138
- for (let i = 0; i < 10000; i++) {
139
- store.subscribe(() => { })();
140
- }
141
- expect((store as Record<string, { size?: number }>).listeners?.size || 0).toBe(0);
142
- });
143
-
144
- it('No memory leak after 10000 setState calls', () => {
145
- const store = createStore({ a: 1 });
146
- for (let i = 0; i < 10000; i++) {
147
- store.setState({ a: i });
148
- }
149
- expect(store.getState().a).toBe(9999);
150
- });
151
-
152
- it('Unsubscribed listeners are garbage collectable (WeakRef test)', async () => {
153
- const store = createStore({ a: 1 });
154
- let l: (() => void) | null = () => { };
155
- const u = store.subscribe(l);
156
- u();
157
- l = null;
158
- expect((store as Record<string, { size?: number }>).listeners?.size || 0).toBe(0);
159
- });
160
-
161
- it('Removed nested objects are garbage collectable', () => {
162
- const store = createStore({ a: { b: 1 } });
163
- store.setState({ a: { c: 2 } } as unknown as Partial<{ a: { b: number } }>);
164
- expect(((store.getState() as Record<string, Record<string, number>>).a).b).toBeUndefined();
165
- });
166
-
167
- it('Creating and discarding 1000 stores leaves no leak', () => {
168
- for (let i = 0; i < 1000; i++) {
169
- createStore({ a: i });
170
- }
171
- expect(true).toBe(true);
172
- });
173
- });
174
-
175
- describe('4.4 Concurrency & Edge Cases', () => {
176
- it('setState called inside a listener — does not cause infinite loop', () => {
177
- const store = createStore({ a: 1 });
178
- let calls = 0;
179
- store.subscribe(() => {
180
- calls++;
181
- if (calls < 2) store.setState({ a: 3 });
182
- });
183
- store.setState({ a: 2 });
184
- expect(calls).toBe(2);
185
- expect(store.getState().a).toBe(3);
186
- });
187
-
188
- it('setState called inside a listener — subsequent listeners see new state', () => {
189
- const store = createStore({ a: 1 });
190
- store.subscribe(() => {
191
- if (store.getState().a === 2) {
192
- store.setState({ a: 3 });
193
- }
194
- });
195
- const l2 = vi.fn();
196
- store.subscribe(l2);
197
- store.setState({ a: 2 });
198
- expect(l2).toHaveBeenCalled();
199
- });
200
-
201
- it('subscribe called inside a listener — safe', () => {
202
- const store = createStore({ a: 1 });
203
- const l2 = vi.fn();
204
- let added = false;
205
- store.subscribe(() => {
206
- if (!added) { store.subscribe(l2); added = true; }
207
- });
208
- store.setState({ a: 2 });
209
- expect(true).toBe(true);
210
- });
211
-
212
- it('unsubscribe called inside a listener — safe', () => {
213
- const store = createStore({ a: 1 });
214
- const l1 = vi.fn(() => {
215
- unsub();
216
- });
217
- const unsub = store.subscribe(l1);
218
- expect(unsub).toBeDefined();
219
- store.setState({ a: 2 });
220
- store.setState({ a: 3 });
221
- expect(l1).toHaveBeenCalledTimes(1);
222
- });
223
-
224
- it('getState called inside a listener — returns correct state', () => {
225
- const store = createStore({ a: 1 });
226
- let stateInListener;
227
- store.subscribe(() => {
228
- stateInListener = store.getState().a;
229
- });
230
- store.setState({ a: 2 });
231
- expect(stateInListener).toBe(2);
232
- });
233
-
234
- it('Rapid sequential setState (1000 in tight loop) — final state correct', () => {
235
- const store = createStore({ val: 0 });
236
- for (let i = 1; i <= 1000; i++) store.setState({ val: i });
237
- expect(store.getState().val).toBe(1000);
238
- });
239
-
240
- it('setState with circular reference object — throws clear error or handles gracefully', () => {
241
- const store = createStore({ obj: {} as Record<string, unknown> });
242
- const a: Record<string, unknown> = {};
243
- const b: Record<string, unknown> = { a };
244
- a.b = b;
245
- expect(() => {
246
- store.setState({ obj: a });
247
- }).not.toThrow();
248
- });
249
-
250
- it('setState with frozen object — handles gracefully', () => {
251
- const store = createStore({ obj: {} });
252
- const frozen = Object.freeze({ a: 1 });
253
- expect(() => store.setState({ obj: frozen })).not.toThrow();
254
- });
255
-
256
- it('setState with sealed object — handles gracefully', () => {
257
- const store = createStore({ obj: {} });
258
- const sealed = Object.seal({ a: 1 });
259
- expect(() => store.setState({ obj: sealed })).not.toThrow();
260
- });
261
-
262
- it('Very deeply nested object (50 levels) — no stack overflow', () => {
263
- let deep: Record<string, unknown> | { val: number } = { val: 1 };
264
- for (let i = 0; i < 50; i++) deep = { child: deep };
265
- const store = createStore({ deep });
266
- expect(() => store.setState({ deep })).not.toThrow();
267
- });
268
- });