@umituz/react-native-storage 2.5.0 → 2.6.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 (28) hide show
  1. package/package.json +7 -3
  2. package/src/cache/__tests__/PerformanceAndMemory.test.ts +386 -0
  3. package/src/cache/__tests__/setup.ts +19 -0
  4. package/src/cache/domain/Cache.ts +146 -0
  5. package/src/cache/domain/CacheManager.ts +48 -0
  6. package/src/cache/domain/CacheStatsTracker.ts +49 -0
  7. package/src/cache/domain/ErrorHandler.ts +42 -0
  8. package/src/cache/domain/PatternMatcher.ts +30 -0
  9. package/src/cache/domain/__tests__/Cache.test.ts +292 -0
  10. package/src/cache/domain/__tests__/CacheManager.test.ts +276 -0
  11. package/src/cache/domain/__tests__/ErrorHandler.test.ts +303 -0
  12. package/src/cache/domain/__tests__/PatternMatcher.test.ts +261 -0
  13. package/src/cache/domain/strategies/EvictionStrategy.ts +9 -0
  14. package/src/cache/domain/strategies/FIFOStrategy.ts +12 -0
  15. package/src/cache/domain/strategies/LFUStrategy.ts +22 -0
  16. package/src/cache/domain/strategies/LRUStrategy.ts +22 -0
  17. package/src/cache/domain/strategies/TTLStrategy.ts +23 -0
  18. package/src/cache/domain/strategies/__tests__/EvictionStrategies.test.ts +293 -0
  19. package/src/cache/domain/types/Cache.ts +28 -0
  20. package/src/cache/index.ts +28 -0
  21. package/src/cache/infrastructure/TTLCache.ts +103 -0
  22. package/src/cache/infrastructure/__tests__/TTLCache.test.ts +303 -0
  23. package/src/cache/presentation/__tests__/ReactHooks.test.ts +512 -0
  24. package/src/cache/presentation/useCache.ts +76 -0
  25. package/src/cache/presentation/useCachedValue.ts +88 -0
  26. package/src/cache/types.d.ts +3 -0
  27. package/src/index.ts +28 -0
  28. package/src/types/global.d.ts +2 -0
@@ -0,0 +1,512 @@
1
+ /**
2
+ * React Hooks Integration Tests
3
+ */
4
+
5
+ // Mock React for testing environment
6
+ const mockReact = require('react');
7
+
8
+ // Simple mock for renderHook
9
+ const renderHook = (hook: Function) => {
10
+ const result = { current: hook() };
11
+
12
+ const rerender = () => {
13
+ result.current = hook();
14
+ };
15
+
16
+ const unmount = () => {
17
+ // Cleanup logic would go here
18
+ };
19
+
20
+ return { result, rerender, unmount };
21
+ };
22
+
23
+ // Mock act function
24
+ const act = (callback: Function) => {
25
+ callback();
26
+ };
27
+
28
+ import { useCache } from '../useCache';
29
+ import { useCachedValue } from '../useCachedValue';
30
+ import { cacheManager } from '../../domain/CacheManager';
31
+
32
+ describe('React Hooks Integration', () => {
33
+ beforeEach(() => {
34
+ cacheManager.clearAll();
35
+ jest.clearAllMocks();
36
+ });
37
+
38
+ describe('useCache', () => {
39
+ test('should provide cache operations', () => {
40
+ const { result } = renderHook(() => useCache<string>('test-cache'));
41
+
42
+ expect(result.current).toHaveProperty('set');
43
+ expect(result.current).toHaveProperty('get');
44
+ expect(result.current).toHaveProperty('has');
45
+ expect(result.current).toHaveProperty('remove');
46
+ expect(result.current).toHaveProperty('clear');
47
+ expect(result.current).toHaveProperty('invalidatePattern');
48
+ expect(result.current).toHaveProperty('getStats');
49
+ });
50
+
51
+ test('should set and get values', () => {
52
+ const { result } = renderHook(() => useCache<string>('test-cache'));
53
+
54
+ act(() => {
55
+ result.current.set('key1', 'value1');
56
+ });
57
+
58
+ expect(result.current.get('key1')).toBe('value1');
59
+ });
60
+
61
+ test('should check if key exists', () => {
62
+ const { result } = renderHook(() => useCache<string>('test-cache'));
63
+
64
+ expect(result.current.has('key1')).toBe(false);
65
+
66
+ act(() => {
67
+ result.current.set('key1', 'value1');
68
+ });
69
+
70
+ expect(result.current.has('key1')).toBe(true);
71
+ });
72
+
73
+ test('should remove keys', () => {
74
+ const { result } = renderHook(() => useCache<string>('test-cache'));
75
+
76
+ act(() => {
77
+ result.current.set('key1', 'value1');
78
+ });
79
+
80
+ expect(result.current.has('key1')).toBe(true);
81
+
82
+ act(() => {
83
+ const removed = result.current.remove('key1');
84
+ expect(removed).toBe(true);
85
+ });
86
+
87
+ expect(result.current.has('key1')).toBe(false);
88
+ });
89
+
90
+ test('should clear all keys', () => {
91
+ const { result } = renderHook(() => useCache<string>('test-cache'));
92
+
93
+ act(() => {
94
+ result.current.set('key1', 'value1');
95
+ result.current.set('key2', 'value2');
96
+ });
97
+
98
+ expect(result.current.getStats().size).toBe(2);
99
+
100
+ act(() => {
101
+ result.current.clear();
102
+ });
103
+
104
+ expect(result.current.getStats().size).toBe(0);
105
+ });
106
+
107
+ test('should invalidate patterns', () => {
108
+ const { result } = renderHook(() => useCache<string>('test-cache'));
109
+
110
+ act(() => {
111
+ result.current.set('user:1', 'user1');
112
+ result.current.set('user:2', 'user2');
113
+ result.current.set('post:1', 'post1');
114
+ });
115
+
116
+ act(() => {
117
+ const count = result.current.invalidatePattern('user:*');
118
+ expect(count).toBe(2);
119
+ });
120
+
121
+ expect(result.current.has('user:1')).toBe(false);
122
+ expect(result.current.has('user:2')).toBe(false);
123
+ expect(result.current.has('post:1')).toBe(true);
124
+ });
125
+
126
+ test('should get cache statistics', () => {
127
+ const { result } = renderHook(() => useCache<string>('test-cache'));
128
+
129
+ const initialStats = result.current.getStats();
130
+ expect(initialStats.size).toBe(0);
131
+ expect(initialStats.hits).toBe(0);
132
+ expect(initialStats.misses).toBe(0);
133
+
134
+ act(() => {
135
+ result.current.set('key1', 'value1');
136
+ });
137
+
138
+ const afterSetStats = result.current.getStats();
139
+ expect(afterSetStats.size).toBe(1);
140
+
141
+ act(() => {
142
+ result.current.get('key1'); // hit
143
+ result.current.get('nonexistent'); // miss
144
+ });
145
+
146
+ const afterAccessStats = result.current.getStats();
147
+ expect(afterAccessStats.hits).toBe(1);
148
+ expect(afterAccessStats.misses).toBe(1);
149
+ });
150
+
151
+ test('should use custom cache configuration', () => {
152
+ const { result } = renderHook(() =>
153
+ useCache<string>('custom-cache', { maxSize: 5, defaultTTL: 2000 })
154
+ );
155
+
156
+ act(() => {
157
+ result.current.set('key1', 'value1');
158
+ });
159
+
160
+ expect(result.current.get('key1')).toBe('value1');
161
+ });
162
+
163
+ test('should maintain separate caches for different names', () => {
164
+ const { result: result1 } = renderHook(() => useCache<string>('cache1'));
165
+ const { result: result2 } = renderHook(() => useCache<number>('cache2'));
166
+
167
+ act(() => {
168
+ result1.current.set('key', 'string-value');
169
+ result2.current.set('key', 42);
170
+ });
171
+
172
+ expect(result1.current.get('key')).toBe('string-value');
173
+ expect(result2.current.get('key')).toBe(42);
174
+ });
175
+
176
+ test('should handle rapid operations without memory leaks', () => {
177
+ const { result } = renderHook(() => useCache<string>('rapid-cache'));
178
+
179
+ // Perform many operations rapidly
180
+ for (let i = 0; i < 100; i++) {
181
+ act(() => {
182
+ result.current.set(`key${i}`, `value${i}`);
183
+ });
184
+ }
185
+
186
+ expect(result.current.getStats().size).toBe(100);
187
+
188
+ // Clear many operations rapidly
189
+ for (let i = 0; i < 100; i++) {
190
+ act(() => {
191
+ result.current.remove(`key${i}`);
192
+ });
193
+ }
194
+
195
+ expect(result.current.getStats().size).toBe(0);
196
+ });
197
+ });
198
+
199
+ describe('useCachedValue', () => {
200
+ test('should load and cache value', async () => {
201
+ const mockFetcher = jest.fn().mockResolvedValue('fetched-value');
202
+
203
+ const { result } = renderHook(() =>
204
+ useCachedValue('test-cache', 'test-key', mockFetcher)
205
+ );
206
+
207
+ expect(result.current.isLoading).toBe(true);
208
+ expect(result.current.value).toBeUndefined();
209
+ expect(result.current.error).toBe(null);
210
+
211
+ await act(async () => {
212
+ await new Promise(resolve => setTimeout(resolve, 0));
213
+ });
214
+
215
+ expect(result.current.isLoading).toBe(false);
216
+ expect(result.current.value).toBe('fetched-value');
217
+ expect(result.current.error).toBe(null);
218
+ expect(mockFetcher).toHaveBeenCalledTimes(1);
219
+ });
220
+
221
+ test('should use cached value on subsequent renders', async () => {
222
+ const mockFetcher = jest.fn().mockResolvedValue('fetched-value');
223
+
224
+ const { result, rerender } = renderHook(() =>
225
+ useCachedValue('test-cache', 'test-key', mockFetcher)
226
+ );
227
+
228
+ // Initial load
229
+ await act(async () => {
230
+ await new Promise(resolve => setTimeout(resolve, 0));
231
+ });
232
+
233
+ expect(mockFetcher).toHaveBeenCalledTimes(1);
234
+
235
+ // Rerender - should use cache
236
+ rerender();
237
+
238
+ expect(result.current.value).toBe('fetched-value');
239
+ expect(mockFetcher).toHaveBeenCalledTimes(1); // Still only called once
240
+ });
241
+
242
+ test('should handle fetcher errors', async () => {
243
+ const mockError = new Error('Fetch failed');
244
+ const mockFetcher = jest.fn().mockRejectedValue(mockError);
245
+
246
+ const { result } = renderHook(() =>
247
+ useCachedValue('test-cache', 'test-key', mockFetcher)
248
+ );
249
+
250
+ await act(async () => {
251
+ await new Promise(resolve => setTimeout(resolve, 0));
252
+ });
253
+
254
+ expect(result.current.isLoading).toBe(false);
255
+ expect(result.current.value).toBeUndefined();
256
+ expect(result.current.error).toBe(mockError);
257
+ });
258
+
259
+ test('should invalidate cached value', async () => {
260
+ const mockFetcher = jest.fn().mockResolvedValue('initial-value');
261
+
262
+ const { result } = renderHook(() =>
263
+ useCachedValue('test-cache', 'test-key', mockFetcher)
264
+ );
265
+
266
+ // Initial load
267
+ await act(async () => {
268
+ await new Promise(resolve => setTimeout(resolve, 0));
269
+ });
270
+
271
+ expect(result.current.value).toBe('initial-value');
272
+
273
+ // Invalidate
274
+ act(() => {
275
+ result.current.invalidate();
276
+ });
277
+
278
+ expect(result.current.value).toBeUndefined();
279
+
280
+ // Should fetch again on next render
281
+ mockFetcher.mockResolvedValue('new-value');
282
+
283
+ await act(async () => {
284
+ await new Promise(resolve => setTimeout(resolve, 0));
285
+ });
286
+
287
+ expect(result.current.value).toBe('new-value');
288
+ expect(mockFetcher).toHaveBeenCalledTimes(2);
289
+ });
290
+
291
+ test('should invalidate pattern', async () => {
292
+ const mockFetcher = jest.fn().mockResolvedValue('value');
293
+
294
+ const { result } = renderHook(() =>
295
+ useCachedValue('test-cache', 'user:123', mockFetcher)
296
+ );
297
+
298
+ // Load initial value
299
+ await act(async () => {
300
+ await new Promise(resolve => setTimeout(resolve, 0));
301
+ });
302
+
303
+ expect(result.current.value).toBe('value');
304
+
305
+ // Invalidate pattern
306
+ act(() => {
307
+ const count = result.current.invalidatePattern('user:*');
308
+ expect(count).toBe(1);
309
+ });
310
+
311
+ expect(result.current.value).toBeUndefined();
312
+ });
313
+
314
+ test('should refetch manually', async () => {
315
+ const mockFetcher = jest.fn()
316
+ .mockResolvedValueOnce('initial-value')
317
+ .mockResolvedValueOnce('refetched-value');
318
+
319
+ const { result } = renderHook(() =>
320
+ useCachedValue('test-cache', 'test-key', mockFetcher)
321
+ );
322
+
323
+ // Initial load
324
+ await act(async () => {
325
+ await new Promise(resolve => setTimeout(resolve, 0));
326
+ });
327
+
328
+ expect(result.current.value).toBe('initial-value');
329
+ expect(mockFetcher).toHaveBeenCalledTimes(1);
330
+
331
+ // Refetch
332
+ act(() => {
333
+ result.current.refetch();
334
+ });
335
+
336
+ await act(async () => {
337
+ await new Promise(resolve => setTimeout(resolve, 0));
338
+ });
339
+
340
+ expect(result.current.value).toBe('refetched-value');
341
+ expect(mockFetcher).toHaveBeenCalledTimes(2);
342
+ });
343
+
344
+ test('should use custom TTL', async () => {
345
+ jest.useFakeTimers();
346
+
347
+ const mockFetcher = jest.fn().mockResolvedValue('value');
348
+
349
+ const { result } = renderHook(() =>
350
+ useCachedValue('test-cache', 'test-key', mockFetcher, { ttl: 1000 })
351
+ );
352
+
353
+ // Load initial value
354
+ await act(async () => {
355
+ await new Promise(resolve => setTimeout(resolve, 0));
356
+ });
357
+
358
+ expect(result.current.value).toBe('value');
359
+ expect(mockFetcher).toHaveBeenCalledTimes(1);
360
+
361
+ // Fast forward past TTL
362
+ jest.advanceTimersByTime(1001);
363
+
364
+ // Should fetch again
365
+ await act(async () => {
366
+ await new Promise(resolve => setTimeout(resolve, 0));
367
+ });
368
+
369
+ expect(mockFetcher).toHaveBeenCalledTimes(2);
370
+
371
+ jest.useRealTimers();
372
+ });
373
+
374
+ test('should handle dependency changes', async () => {
375
+ const mockFetcher1 = jest.fn().mockResolvedValue('value1');
376
+ const mockFetcher2 = jest.fn().mockResolvedValue('value2');
377
+
378
+ const { result, rerender } = renderHook(
379
+ ({ fetcher }) => useCachedValue('test-cache', 'test-key', fetcher),
380
+ { initialProps: { fetcher: mockFetcher1 } }
381
+ );
382
+
383
+ // Initial load
384
+ await act(async () => {
385
+ await new Promise(resolve => setTimeout(resolve, 0));
386
+ });
387
+
388
+ expect(result.current.value).toBe('value1');
389
+ expect(mockFetcher1).toHaveBeenCalledTimes(1);
390
+
391
+ // Change fetcher
392
+ rerender({ fetcher: mockFetcher2 });
393
+
394
+ await act(async () => {
395
+ await new Promise(resolve => setTimeout(resolve, 0));
396
+ });
397
+
398
+ expect(result.current.value).toBe('value2');
399
+ expect(mockFetcher2).toHaveBeenCalledTimes(1);
400
+ });
401
+
402
+ test('should handle concurrent requests', async () => {
403
+ let resolveCount = 0;
404
+ const mockFetcher = jest.fn(() => {
405
+ return new Promise(resolve => {
406
+ setTimeout(() => {
407
+ resolveCount++;
408
+ resolve(`value-${resolveCount}`);
409
+ }, 100);
410
+ });
411
+ });
412
+
413
+ const { result } = renderHook(() =>
414
+ useCachedValue('test-cache', 'test-key', mockFetcher)
415
+ );
416
+
417
+ // Trigger multiple rapid renders
418
+ act(() => {});
419
+ act(() => {});
420
+ act(() => {});
421
+
422
+ // Wait for completion
423
+ await act(async () => {
424
+ await new Promise(resolve => setTimeout(resolve, 200));
425
+ });
426
+
427
+ // Should only call fetcher once despite multiple renders
428
+ expect(mockFetcher).toHaveBeenCalledTimes(1);
429
+ expect(result.current.value).toBe('value-1');
430
+ });
431
+
432
+ test('should cleanup on unmount', async () => {
433
+ const mockFetcher = jest.fn().mockResolvedValue('value');
434
+
435
+ const { unmount } = renderHook(() =>
436
+ useCachedValue('test-cache', 'test-key', mockFetcher)
437
+ );
438
+
439
+ // Start loading
440
+ expect(result.current.isLoading).toBe(true);
441
+
442
+ // Unmount while loading
443
+ unmount();
444
+
445
+ // Complete the fetch after unmount
446
+ await act(async () => {
447
+ await new Promise(resolve => setTimeout(resolve, 0));
448
+ });
449
+
450
+ // Should not cause errors
451
+ expect(true).toBe(true);
452
+ });
453
+ });
454
+
455
+ describe('Hook Integration', () => {
456
+ test('should work together with useCache and useCachedValue', async () => {
457
+ const mockFetcher = jest.fn().mockResolvedValue('fetched-value');
458
+
459
+ const { result: cacheResult } = renderHook(() => useCache<string>('shared-cache'));
460
+ const { result: valueResult } = renderHook(() =>
461
+ useCachedValue('shared-cache', 'shared-key', mockFetcher)
462
+ );
463
+
464
+ // Load value through useCachedValue
465
+ await act(async () => {
466
+ await new Promise(resolve => setTimeout(resolve, 0));
467
+ });
468
+
469
+ expect(valueResult.current.value).toBe('fetched-value');
470
+
471
+ // Value should be accessible through useCache
472
+ expect(cacheResult.current.get('shared-key')).toBe('fetched-value');
473
+
474
+ // Invalidate through useCache
475
+ act(() => {
476
+ cacheResult.current.invalidatePattern('*');
477
+ });
478
+
479
+ expect(valueResult.current.value).toBeUndefined();
480
+ expect(cacheResult.current.has('shared-key')).toBe(false);
481
+ });
482
+
483
+ test('should handle multiple hooks with same cache', async () => {
484
+ const mockFetcher1 = jest.fn().mockResolvedValue('value1');
485
+ const mockFetcher2 = jest.fn().mockResolvedValue('value2');
486
+
487
+ const { result: result1 } = renderHook(() =>
488
+ useCachedValue('shared-cache', 'key1', mockFetcher1)
489
+ );
490
+
491
+ const { result: result2 } = renderHook(() =>
492
+ useCachedValue('shared-cache', 'key2', mockFetcher2)
493
+ );
494
+
495
+ // Load both values
496
+ await act(async () => {
497
+ await new Promise(resolve => setTimeout(resolve, 0));
498
+ });
499
+
500
+ expect(result1.current.value).toBe('value1');
501
+ expect(result2.current.value).toBe('value2');
502
+
503
+ // Invalidate one should not affect the other
504
+ act(() => {
505
+ result1.current.invalidate();
506
+ });
507
+
508
+ expect(result1.current.value).toBeUndefined();
509
+ expect(result2.current.value).toBe('value2'); // Should remain
510
+ });
511
+ });
512
+ });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * useCache Hook
3
+ */
4
+
5
+ import { useCallback, useRef, useState } from 'react';
6
+ import { cacheManager } from '../domain/CacheManager';
7
+ import type { CacheConfig } from '../domain/types/Cache';
8
+
9
+ export function useCache<T>(cacheName: string, config?: CacheConfig) {
10
+ const cacheRef = useRef(cacheManager.getCache<T>(cacheName, config));
11
+ const cache = cacheRef.current!;
12
+ const [, forceUpdate] = useState({});
13
+
14
+ const triggerUpdate = useCallback(() => {
15
+ forceUpdate({});
16
+ }, []);
17
+
18
+ const set = useCallback(
19
+ (key: string, value: T, ttl?: number) => {
20
+ cache.set(key, value, ttl);
21
+ triggerUpdate();
22
+ },
23
+ [cache, triggerUpdate]
24
+ );
25
+
26
+ const get = useCallback(
27
+ (key: string): T | undefined => {
28
+ return cache.get(key);
29
+ },
30
+ [cache]
31
+ );
32
+
33
+ const has = useCallback(
34
+ (key: string): boolean => {
35
+ return cache.has(key);
36
+ },
37
+ [cache]
38
+ );
39
+
40
+ const remove = useCallback(
41
+ (key: string): boolean => {
42
+ const result = cache.delete(key);
43
+ triggerUpdate();
44
+ return result;
45
+ },
46
+ [cache, triggerUpdate]
47
+ );
48
+
49
+ const clear = useCallback(() => {
50
+ cache.clear();
51
+ triggerUpdate();
52
+ }, [cache, triggerUpdate]);
53
+
54
+ const invalidatePattern = useCallback(
55
+ (pattern: string): number => {
56
+ const count = cache.invalidatePattern(pattern);
57
+ triggerUpdate();
58
+ return count;
59
+ },
60
+ [cache, triggerUpdate]
61
+ );
62
+
63
+ const getStats = useCallback(() => {
64
+ return cache.getStats();
65
+ }, [cache]);
66
+
67
+ return {
68
+ set,
69
+ get,
70
+ has,
71
+ remove,
72
+ clear,
73
+ invalidatePattern,
74
+ getStats,
75
+ };
76
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * useCachedValue Hook
3
+ */
4
+
5
+ import { useCallback, useEffect, useRef, useState } from 'react';
6
+ import { cacheManager } from '../domain/CacheManager';
7
+ import type { CacheConfig } from '../domain/types/Cache';
8
+
9
+ export function useCachedValue<T>(
10
+ cacheName: string,
11
+ key: string,
12
+ fetcher: () => Promise<T>,
13
+ config?: CacheConfig & { ttl?: number }
14
+ ) {
15
+ const [value, setValue] = useState<T | undefined>(undefined);
16
+ const [isLoading, setIsLoading] = useState(false);
17
+ const [error, setError] = useState<Error | null>(null);
18
+
19
+ const fetcherRef = useRef(fetcher);
20
+ const configRef = useRef(config);
21
+
22
+ fetcherRef.current = fetcher;
23
+ configRef.current = config;
24
+
25
+ const loadValue = useCallback(async () => {
26
+ const cache = cacheManager.getCache<T>(cacheName, configRef.current);
27
+ const cached = cache.get(key);
28
+
29
+ if (cached !== undefined) {
30
+ setValue(cached);
31
+ return;
32
+ }
33
+
34
+ setIsLoading(true);
35
+ setError(null);
36
+
37
+ try {
38
+ const data = await fetcherRef.current!();
39
+ cache.set(key, data, configRef.current?.ttl);
40
+ setValue(data);
41
+ } catch (err) {
42
+ setError(err as Error);
43
+ } finally {
44
+ setIsLoading(false);
45
+ }
46
+ }, [cacheName, key]);
47
+
48
+ useEffect(() => {
49
+ let isMounted = true;
50
+
51
+ loadValue().then(() => {
52
+ if (!isMounted) {
53
+ setValue(undefined);
54
+ }
55
+ });
56
+
57
+ return () => {
58
+ isMounted = false;
59
+ };
60
+ }, [loadValue]);
61
+
62
+ const invalidate = useCallback(() => {
63
+ const cache = cacheManager.getCache<T>(cacheName);
64
+ cache.delete(key);
65
+ setValue(undefined);
66
+ }, [cacheName, key]);
67
+
68
+ const invalidatePattern = useCallback((pattern: string): number => {
69
+ const cache = cacheManager.getCache<T>(cacheName);
70
+ const count = cache.invalidatePattern(pattern);
71
+ setValue(undefined);
72
+ return count;
73
+ }, [cacheName]);
74
+
75
+ const refetch = useCallback(() => {
76
+ setValue(undefined);
77
+ loadValue();
78
+ }, [loadValue]);
79
+
80
+ return {
81
+ value,
82
+ isLoading,
83
+ error,
84
+ invalidate,
85
+ invalidatePattern,
86
+ refetch,
87
+ };
88
+ }
@@ -0,0 +1,3 @@
1
+ /// <reference types="../../types/global" />
2
+
3
+ declare const __DEV__: boolean | undefined;
package/src/index.ts CHANGED
@@ -138,3 +138,31 @@ export {
138
138
 
139
139
  export { useCacheState } from './presentation/hooks/useCacheState';
140
140
  export { CacheStorageOperations } from './presentation/hooks/CacheStorageOperations';
141
+
142
+ // =============================================================================
143
+ // IN-MEMORY CACHE LAYER (Merged from @umituz/react-native-cache)
144
+ // =============================================================================
145
+
146
+ export { Cache } from './cache/domain/Cache';
147
+ export { CacheManager, cacheManager } from './cache/domain/CacheManager';
148
+ export { CacheStatsTracker } from './cache/domain/CacheStatsTracker';
149
+ export { PatternMatcher } from './cache/domain/PatternMatcher';
150
+ export { ErrorHandler, CacheError } from './cache/domain/ErrorHandler';
151
+ export { TTLCache } from './cache/infrastructure/TTLCache';
152
+
153
+ export type {
154
+ CacheEntry,
155
+ CacheConfig,
156
+ CacheStats,
157
+ EvictionStrategy,
158
+ } from './cache/domain/types/Cache';
159
+
160
+ export type { EvictionStrategy as IEvictionStrategy } from './cache/domain/strategies/EvictionStrategy';
161
+
162
+ export { LRUStrategy } from './cache/domain/strategies/LRUStrategy';
163
+ export { LFUStrategy } from './cache/domain/strategies/LFUStrategy';
164
+ export { FIFOStrategy } from './cache/domain/strategies/FIFOStrategy';
165
+ export { TTLStrategy as TTLEvictionStrategy } from './cache/domain/strategies/TTLStrategy';
166
+
167
+ export { useCache } from './cache/presentation/useCache';
168
+ export { useCachedValue } from './cache/presentation/useCachedValue';