@umituz/react-native-design-system 2.8.7 → 2.8.8

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 (128) hide show
  1. package/package.json +5 -6
  2. package/src/device/infrastructure/repositories/LegacyDeviceIdRepository.ts +1 -1
  3. package/src/device/infrastructure/services/DeviceFeatureService.ts +1 -1
  4. package/src/exception/infrastructure/services/ExceptionLogger.ts +1 -1
  5. package/src/exception/infrastructure/storage/ExceptionStore.ts +1 -1
  6. package/src/exports/filesystem.ts +1 -0
  7. package/src/exports/storage.ts +1 -0
  8. package/src/filesystem/domain/constants/FileConstants.ts +20 -0
  9. package/src/filesystem/domain/entities/File.ts +20 -0
  10. package/src/filesystem/domain/types/FileTypes.ts +43 -0
  11. package/src/filesystem/domain/utils/FileUtils.ts +86 -0
  12. package/src/filesystem/index.ts +23 -0
  13. package/src/filesystem/infrastructure/services/FileSystemService.ts +45 -0
  14. package/src/filesystem/infrastructure/services/cache.service.ts +48 -0
  15. package/src/filesystem/infrastructure/services/directory.service.ts +66 -0
  16. package/src/filesystem/infrastructure/services/download.constants.ts +6 -0
  17. package/src/filesystem/infrastructure/services/download.service.ts +74 -0
  18. package/src/filesystem/infrastructure/services/download.types.ts +7 -0
  19. package/src/filesystem/infrastructure/services/encoding.service.ts +25 -0
  20. package/src/filesystem/infrastructure/services/file-info.service.ts +52 -0
  21. package/src/filesystem/infrastructure/services/file-manager.service.ts +81 -0
  22. package/src/filesystem/infrastructure/services/file-path.service.ts +22 -0
  23. package/src/filesystem/infrastructure/services/file-reader.service.ts +52 -0
  24. package/src/filesystem/infrastructure/services/file-writer.service.ts +32 -0
  25. package/src/filesystem/infrastructure/utils/blob.utils.ts +20 -0
  26. package/src/image/infrastructure/services/ImageStorageService.ts +1 -1
  27. package/src/index.ts +9 -0
  28. package/src/molecules/alerts/AlertStore.ts +1 -1
  29. package/src/molecules/calendar/infrastructure/storage/EventActions.ts +1 -1
  30. package/src/molecules/calendar/infrastructure/stores/storageAdapter.ts +1 -1
  31. package/src/offline/infrastructure/storage/OfflineStore.ts +1 -1
  32. package/src/onboarding/infrastructure/storage/OnboardingStore.ts +2 -2
  33. package/src/onboarding/infrastructure/storage/__tests__/OnboardingStore.test.ts +1 -1
  34. package/src/onboarding/infrastructure/storage/actions/answerActions.ts +1 -1
  35. package/src/onboarding/infrastructure/storage/actions/storageHelpers.ts +1 -1
  36. package/src/storage/README.md +185 -0
  37. package/src/storage/__tests__/integration.test.ts +391 -0
  38. package/src/storage/__tests__/mocks/asyncStorage.mock.ts +52 -0
  39. package/src/storage/__tests__/performance.test.tsx +352 -0
  40. package/src/storage/__tests__/setup.ts +63 -0
  41. package/src/storage/application/README.md +158 -0
  42. package/src/storage/application/ports/IStorageRepository.ts +61 -0
  43. package/src/storage/application/ports/README.md +127 -0
  44. package/src/storage/cache/README.md +154 -0
  45. package/src/storage/cache/__tests__/PerformanceAndMemory.test.ts +387 -0
  46. package/src/storage/cache/__tests__/setup.ts +19 -0
  47. package/src/storage/cache/domain/Cache.ts +146 -0
  48. package/src/storage/cache/domain/CacheManager.md +83 -0
  49. package/src/storage/cache/domain/CacheManager.ts +48 -0
  50. package/src/storage/cache/domain/CacheStatsTracker.md +169 -0
  51. package/src/storage/cache/domain/CacheStatsTracker.ts +49 -0
  52. package/src/storage/cache/domain/CachedValue.md +97 -0
  53. package/src/storage/cache/domain/ErrorHandler.md +99 -0
  54. package/src/storage/cache/domain/ErrorHandler.ts +42 -0
  55. package/src/storage/cache/domain/PatternMatcher.md +122 -0
  56. package/src/storage/cache/domain/PatternMatcher.ts +30 -0
  57. package/src/storage/cache/domain/README.md +118 -0
  58. package/src/storage/cache/domain/__tests__/Cache.test.ts +293 -0
  59. package/src/storage/cache/domain/__tests__/CacheManager.test.ts +276 -0
  60. package/src/storage/cache/domain/__tests__/ErrorHandler.test.ts +303 -0
  61. package/src/storage/cache/domain/__tests__/PatternMatcher.test.ts +261 -0
  62. package/src/storage/cache/domain/strategies/EvictionStrategy.ts +9 -0
  63. package/src/storage/cache/domain/strategies/FIFOStrategy.ts +12 -0
  64. package/src/storage/cache/domain/strategies/LFUStrategy.ts +22 -0
  65. package/src/storage/cache/domain/strategies/LRUStrategy.ts +22 -0
  66. package/src/storage/cache/domain/strategies/README.md +117 -0
  67. package/src/storage/cache/domain/strategies/TTLStrategy.ts +23 -0
  68. package/src/storage/cache/domain/strategies/__tests__/EvictionStrategies.test.ts +293 -0
  69. package/src/storage/cache/domain/types/Cache.ts +28 -0
  70. package/src/storage/cache/domain/types/README.md +107 -0
  71. package/src/storage/cache/index.ts +28 -0
  72. package/src/storage/cache/infrastructure/README.md +126 -0
  73. package/src/storage/cache/infrastructure/TTLCache.ts +103 -0
  74. package/src/storage/cache/infrastructure/__tests__/TTLCache.test.ts +303 -0
  75. package/src/storage/cache/presentation/README.md +123 -0
  76. package/src/storage/cache/presentation/__tests__/ReactHooks.test.ts +514 -0
  77. package/src/storage/cache/presentation/useCache.ts +76 -0
  78. package/src/storage/cache/presentation/useCachedValue.ts +88 -0
  79. package/src/storage/cache/types.d.ts +3 -0
  80. package/src/storage/domain/README.md +128 -0
  81. package/src/storage/domain/constants/CacheDefaults.ts +64 -0
  82. package/src/storage/domain/constants/README.md +105 -0
  83. package/src/storage/domain/entities/CachedValue.ts +86 -0
  84. package/src/storage/domain/entities/README.md +109 -0
  85. package/src/storage/domain/entities/StorageResult.ts +75 -0
  86. package/src/storage/domain/entities/__tests__/CachedValue.test.ts +149 -0
  87. package/src/storage/domain/entities/__tests__/StorageResult.test.ts +122 -0
  88. package/src/storage/domain/errors/README.md +126 -0
  89. package/src/storage/domain/errors/StorageError.ts +81 -0
  90. package/src/storage/domain/errors/__tests__/StorageError.test.ts +127 -0
  91. package/src/storage/domain/factories/README.md +138 -0
  92. package/src/storage/domain/factories/StoreFactory.ts +59 -0
  93. package/src/storage/domain/types/README.md +522 -0
  94. package/src/storage/domain/types/Store.ts +44 -0
  95. package/src/storage/domain/utils/CacheKeyGenerator.ts +66 -0
  96. package/src/storage/domain/utils/README.md +127 -0
  97. package/src/storage/domain/utils/__tests__/devUtils.test.ts +97 -0
  98. package/src/storage/domain/utils/devUtils.ts +37 -0
  99. package/src/storage/domain/value-objects/README.md +120 -0
  100. package/src/storage/domain/value-objects/StorageKey.ts +60 -0
  101. package/src/storage/index.ts +175 -0
  102. package/src/storage/infrastructure/README.md +165 -0
  103. package/src/storage/infrastructure/adapters/README.md +175 -0
  104. package/src/storage/infrastructure/adapters/StorageService.md +103 -0
  105. package/src/storage/infrastructure/adapters/StorageService.ts +49 -0
  106. package/src/storage/infrastructure/repositories/AsyncStorageRepository.ts +98 -0
  107. package/src/storage/infrastructure/repositories/BaseStorageOperations.ts +100 -0
  108. package/src/storage/infrastructure/repositories/BatchStorageOperations.ts +42 -0
  109. package/src/storage/infrastructure/repositories/README.md +121 -0
  110. package/src/storage/infrastructure/repositories/StringStorageOperations.ts +44 -0
  111. package/src/storage/infrastructure/repositories/__tests__/AsyncStorageRepository.test.ts +170 -0
  112. package/src/storage/infrastructure/repositories/__tests__/BaseStorageOperations.test.ts +201 -0
  113. package/src/storage/presentation/README.md +181 -0
  114. package/src/storage/presentation/hooks/CacheStorageOperations.ts +94 -0
  115. package/src/storage/presentation/hooks/README.md +128 -0
  116. package/src/storage/presentation/hooks/__tests__/usePersistentCache.test.ts +405 -0
  117. package/src/storage/presentation/hooks/__tests__/useStorage.test.ts +247 -0
  118. package/src/storage/presentation/hooks/__tests__/useStorageState.test.ts +293 -0
  119. package/src/storage/presentation/hooks/useCacheState.ts +53 -0
  120. package/src/storage/presentation/hooks/usePersistentCache.ts +154 -0
  121. package/src/storage/presentation/hooks/useStorage.ts +102 -0
  122. package/src/storage/presentation/hooks/useStorageState.ts +71 -0
  123. package/src/storage/presentation/hooks/useStore.ts +15 -0
  124. package/src/storage/types/README.md +103 -0
  125. package/src/theme/infrastructure/globalThemeStore.ts +1 -1
  126. package/src/theme/infrastructure/storage/ThemeStorage.ts +1 -1
  127. package/src/theme/infrastructure/stores/themeStore.ts +1 -1
  128. package/src/utilities/sharing/infrastructure/services/SharingService.ts +1 -1
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Eviction Strategies Tests
3
+ */
4
+
5
+ import { LRUStrategy } from '../LRUStrategy';
6
+ import { LFUStrategy } from '../LFUStrategy';
7
+ import { FIFOStrategy } from '../FIFOStrategy';
8
+ import { TTLStrategy } from '../TTLStrategy';
9
+ import type { CacheEntry } from '../../types/Cache';
10
+
11
+ describe('Eviction Strategies', () => {
12
+ const createMockEntries = (): Map<string, CacheEntry<string>> => {
13
+ const entries = new Map<string, CacheEntry<string>>();
14
+ const now = Date.now();
15
+
16
+ entries.set('key1', {
17
+ value: 'value1',
18
+ timestamp: now - 1000,
19
+ ttl: 5000,
20
+ accessCount: 5,
21
+ lastAccess: now - 500,
22
+ });
23
+
24
+ entries.set('key2', {
25
+ value: 'value2',
26
+ timestamp: now - 2000,
27
+ ttl: 5000,
28
+ accessCount: 3,
29
+ lastAccess: now - 100,
30
+ });
31
+
32
+ entries.set('key3', {
33
+ value: 'value3',
34
+ timestamp: now - 3000,
35
+ ttl: 5000,
36
+ accessCount: 10,
37
+ lastAccess: now - 1500,
38
+ });
39
+
40
+ return entries;
41
+ };
42
+
43
+ describe('LRUStrategy', () => {
44
+ let strategy: LRUStrategy<string>;
45
+
46
+ beforeEach(() => {
47
+ strategy = new LRUStrategy<string>();
48
+ });
49
+
50
+ test('should evict least recently used key', () => {
51
+ const entries = createMockEntries();
52
+ const keyToEvict = strategy.findKeyToEvict(entries);
53
+
54
+ // key3 has the oldest lastAccess time
55
+ expect(keyToEvict).toBe('key3');
56
+ });
57
+
58
+ test('should return undefined for empty entries', () => {
59
+ const entries = new Map<string, CacheEntry<string>>();
60
+ const keyToEvict = strategy.findKeyToEvict(entries);
61
+
62
+ expect(keyToEvict).toBeUndefined();
63
+ });
64
+
65
+ test('should handle single entry', () => {
66
+ const entries = new Map<string, CacheEntry<string>>();
67
+ entries.set('key1', {
68
+ value: 'value1',
69
+ timestamp: Date.now(),
70
+ ttl: 5000,
71
+ accessCount: 1,
72
+ lastAccess: Date.now(),
73
+ });
74
+
75
+ const keyToEvict = strategy.findKeyToEvict(entries);
76
+ expect(keyToEvict).toBe('key1');
77
+ });
78
+ });
79
+
80
+ describe('LFUStrategy', () => {
81
+ let strategy: LFUStrategy<string>;
82
+
83
+ beforeEach(() => {
84
+ strategy = new LFUStrategy<string>();
85
+ });
86
+
87
+ test('should evict least frequently used key', () => {
88
+ const entries = createMockEntries();
89
+ const keyToEvict = strategy.findKeyToEvict(entries);
90
+
91
+ // key2 has the lowest access count (3)
92
+ expect(keyToEvict).toBe('key2');
93
+ });
94
+
95
+ test('should return undefined for empty entries', () => {
96
+ const entries = new Map<string, CacheEntry<string>>();
97
+ const keyToEvict = strategy.findKeyToEvict(entries);
98
+
99
+ expect(keyToEvict).toBeUndefined();
100
+ });
101
+
102
+ test('should handle ties by choosing first encountered', () => {
103
+ const entries = new Map<string, CacheEntry<string>>();
104
+ const now = Date.now();
105
+
106
+ entries.set('key1', {
107
+ value: 'value1',
108
+ timestamp: now,
109
+ ttl: 5000,
110
+ accessCount: 2,
111
+ lastAccess: now,
112
+ });
113
+
114
+ entries.set('key2', {
115
+ value: 'value2',
116
+ timestamp: now,
117
+ ttl: 5000,
118
+ accessCount: 2,
119
+ lastAccess: now,
120
+ });
121
+
122
+ const keyToEvict = strategy.findKeyToEvict(entries);
123
+ // Should return the first key with lowest count
124
+ expect(keyToEvict).toBe('key1');
125
+ });
126
+ });
127
+
128
+ describe('FIFOStrategy', () => {
129
+ let strategy: FIFOStrategy<string>;
130
+
131
+ beforeEach(() => {
132
+ strategy = new FIFOStrategy<string>();
133
+ });
134
+
135
+ test('should evict first inserted key', () => {
136
+ const entries = createMockEntries();
137
+ const keyToEvict = strategy.findKeyToEvict(entries);
138
+
139
+ // Map preserves insertion order, so first key should be evicted
140
+ expect(keyToEvict).toBe('key1');
141
+ });
142
+
143
+ test('should return undefined for empty entries', () => {
144
+ const entries = new Map<string, CacheEntry<string>>();
145
+ const keyToEvict = strategy.findKeyToEvict(entries);
146
+
147
+ expect(keyToEvict).toBeUndefined();
148
+ });
149
+
150
+ test('should handle single entry', () => {
151
+ const entries = new Map<string, CacheEntry<string>>();
152
+ entries.set('onlyKey', {
153
+ value: 'value',
154
+ timestamp: Date.now(),
155
+ ttl: 5000,
156
+ accessCount: 1,
157
+ lastAccess: Date.now(),
158
+ });
159
+
160
+ const keyToEvict = strategy.findKeyToEvict(entries);
161
+ expect(keyToEvict).toBe('onlyKey');
162
+ });
163
+ });
164
+
165
+ describe('TTLStrategy', () => {
166
+ let strategy: TTLStrategy<string>;
167
+
168
+ beforeEach(() => {
169
+ strategy = new TTLStrategy<string>();
170
+ });
171
+
172
+ test('should evict key with nearest expiry', () => {
173
+ const now = Date.now();
174
+ const entries = new Map<string, CacheEntry<string>>();
175
+
176
+ entries.set('key1', {
177
+ value: 'value1',
178
+ timestamp: now - 1000,
179
+ ttl: 2000, // Expires at now + 1000
180
+ accessCount: 1,
181
+ lastAccess: now,
182
+ });
183
+
184
+ entries.set('key2', {
185
+ value: 'value2',
186
+ timestamp: now - 500,
187
+ ttl: 1000, // Expires at now + 500
188
+ accessCount: 1,
189
+ lastAccess: now,
190
+ });
191
+
192
+ entries.set('key3', {
193
+ value: 'value3',
194
+ timestamp: now - 2000,
195
+ ttl: 3000, // Expires at now + 1000
196
+ accessCount: 1,
197
+ lastAccess: now,
198
+ });
199
+
200
+ const keyToEvict = strategy.findKeyToEvict(entries);
201
+
202
+ // key2 expires soonest (now + 500)
203
+ expect(keyToEvict).toBe('key2');
204
+ });
205
+
206
+ test('should return undefined for empty entries', () => {
207
+ const entries = new Map<string, CacheEntry<string>>();
208
+ const keyToEvict = strategy.findKeyToEvict(entries);
209
+
210
+ expect(keyToEvict).toBeUndefined();
211
+ });
212
+
213
+ test('should handle already expired entries', () => {
214
+ const now = Date.now();
215
+ const entries = new Map<string, CacheEntry<string>>();
216
+
217
+ entries.set('key1', {
218
+ value: 'value1',
219
+ timestamp: now - 2000,
220
+ ttl: 1000, // Already expired
221
+ accessCount: 1,
222
+ lastAccess: now,
223
+ });
224
+
225
+ entries.set('key2', {
226
+ value: 'value2',
227
+ timestamp: now - 1000,
228
+ ttl: 2000, // Expires at now + 1000
229
+ accessCount: 1,
230
+ lastAccess: now,
231
+ });
232
+
233
+ const keyToEvict = strategy.findKeyToEvict(entries);
234
+
235
+ // key1 is already expired, should be evicted first
236
+ expect(keyToEvict).toBe('key1');
237
+ });
238
+
239
+ test('should handle ties by choosing first encountered', () => {
240
+ const now = Date.now();
241
+ const entries = new Map<string, CacheEntry<string>>();
242
+
243
+ entries.set('key1', {
244
+ value: 'value1',
245
+ timestamp: now - 1000,
246
+ ttl: 2000, // Both expire at now + 1000
247
+ accessCount: 1,
248
+ lastAccess: now,
249
+ });
250
+
251
+ entries.set('key2', {
252
+ value: 'value2',
253
+ timestamp: now - 1000,
254
+ ttl: 2000, // Both expire at now + 1000
255
+ accessCount: 1,
256
+ lastAccess: now,
257
+ });
258
+
259
+ const keyToEvict = strategy.findKeyToEvict(entries);
260
+
261
+ // Should return the first key with nearest expiry
262
+ expect(keyToEvict).toBe('key1');
263
+ });
264
+ });
265
+
266
+ describe('Strategy Integration', () => {
267
+ test('all strategies should handle different data types', () => {
268
+ const numberStrategy = new LRUStrategy<number>();
269
+ const objectStrategy = new LRUStrategy<{ id: string }>();
270
+
271
+ const numberEntries = new Map<string, CacheEntry<number>>();
272
+ numberEntries.set('num1', {
273
+ value: 42,
274
+ timestamp: Date.now(),
275
+ ttl: 5000,
276
+ accessCount: 1,
277
+ lastAccess: Date.now(),
278
+ });
279
+
280
+ const objectEntries = new Map<string, CacheEntry<{ id: string }>>();
281
+ objectEntries.set('obj1', {
282
+ value: { id: 'test' },
283
+ timestamp: Date.now(),
284
+ ttl: 5000,
285
+ accessCount: 1,
286
+ lastAccess: Date.now(),
287
+ });
288
+
289
+ expect(numberStrategy.findKeyToEvict(numberEntries)).toBe('num1');
290
+ expect(objectStrategy.findKeyToEvict(objectEntries)).toBe('obj1');
291
+ });
292
+ });
293
+ });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Cache Types
3
+ */
4
+
5
+ export interface CacheEntry<T> {
6
+ value: T;
7
+ timestamp: number;
8
+ ttl: number;
9
+ accessCount: number;
10
+ lastAccess: number;
11
+ }
12
+
13
+ export interface CacheConfig {
14
+ maxSize?: number;
15
+ defaultTTL?: number;
16
+ onEvict?: (key: string, entry: CacheEntry<unknown>) => void;
17
+ onExpire?: (key: string, entry: CacheEntry<unknown>) => void;
18
+ }
19
+
20
+ export interface CacheStats {
21
+ size: number;
22
+ hits: number;
23
+ misses: number;
24
+ evictions: number;
25
+ expirations: number;
26
+ }
27
+
28
+ export type EvictionStrategy = 'lru' | 'lfu' | 'fifo' | 'ttl';
@@ -0,0 +1,107 @@
1
+ # Cache Domain Types
2
+
3
+ TypeScript interfaces and types for cache system.
4
+
5
+ ## Overview
6
+
7
+ TypeScript type definitions for cache entries, configuration, statistics, and eviction strategies. Located at `src/cache/domain/types/`.
8
+
9
+ ## Strategies
10
+
11
+ ### Cache Entry Definition
12
+ - Define CacheEntry with value, timestamp, TTL, and access tracking
13
+ - Include metadata for eviction strategies
14
+ - Support generic type parameter for cached values
15
+ - Track access patterns for statistics
16
+
17
+ ### Cache Configuration
18
+ - Provide optional configuration parameters
19
+ - Set sensible defaults (maxSize: 100, TTL: 5 minutes)
20
+ - Support lifecycle callbacks (onEvict, onExpire)
21
+ - Allow strategy selection
22
+
23
+ ### Statistics Tracking
24
+ - Track hits, misses, evictions, expirations
25
+ - Calculate hit rate automatically
26
+ - Provide snapshot of cache state
27
+ - Support performance monitoring
28
+
29
+ ### Type Safety
30
+ - Use generic type parameter for cached values
31
+ - Enforce type consistency across operations
32
+ - Provide type inference for cache creation
33
+ - Support nested type structures
34
+
35
+ ## Restrictions
36
+
37
+ ### Type Definitions
38
+ - DO NOT use optional properties for required fields
39
+ - DO NOT mix different data types in same cache without generic
40
+ - DO NOT create circular type dependencies
41
+ - DO NOT omit timestamp or TTL from entries
42
+
43
+ ### Configuration
44
+ - DO NOT allow unlimited cache sizes (must have maxSize)
45
+ - DO NOT set zero or negative TTL as default
46
+ - DO NOT make callbacks required (use optional)
47
+ - DO NOT ignore validation in configuration
48
+
49
+ ### Statistics
50
+ - DO NOT calculate statistics on every access (expensive)
51
+ - DO NOT track unnecessary metrics
52
+ - DO NOT use floating-point for hit rate (use decimal)
53
+ - DO NOT expose internal tracking fields
54
+
55
+ ## Rules
56
+
57
+ ### CacheEntry Interface
58
+ - MUST include value field of generic type T
59
+ - MUST include timestamp (creation time in milliseconds)
60
+ - MUST include ttl (time to live in milliseconds)
61
+ - MUST include accessCount (for LFU strategy)
62
+ - MUST include lastAccess (for LRU strategy)
63
+
64
+ ### CacheConfig Interface
65
+ - MUST provide maxSize with default value of 100
66
+ - MUST provide defaultTTL with default value of 300000 (5 minutes)
67
+ - MUST provide optional onEvict callback
68
+ - MUST provide optional onExpire callback
69
+ - MUST validate configuration values
70
+
71
+ ### CacheStats Interface
72
+ - MUST include size (current entry count)
73
+ - MUST include hits (cache hit count)
74
+ - MUST include misses (cache miss count)
75
+ - MUST include evictions (evicted entry count)
76
+ - MUST include expirations (expired entry count)
77
+ - MUST include hitRate (calculated as hits / (hits + misses))
78
+
79
+ ### Eviction Strategy Type
80
+ - MUST be union of literal types ('lru' | 'lfu' | 'fifo' | 'ttl')
81
+ - MUST support custom strategies
82
+ - MUST be case-sensitive
83
+ - MUST be documented
84
+
85
+ ### Generic Type Parameters
86
+ - MUST use T for cached value type
87
+ - MUST provide type inference
88
+ - MUST support nested types
89
+ - MUST enforce type safety
90
+
91
+ ### Type Guards
92
+ - MUST provide isCacheEntry guard
93
+ - MUST validate all required fields
94
+ - MUST check types of all fields
95
+ - MUST handle edge cases
96
+
97
+ ### Statistics Calculation
98
+ - MUST calculate hitRate as decimal (0-1)
99
+ - MUST update statistics on every operation
100
+ - MUST provide accurate counts
101
+ - MUST not expose internal calculation methods
102
+
103
+ ### Export Rules
104
+ - MUST export all public types
105
+ - MUST use `type` keyword for type-only exports
106
+ - MUST maintain backward compatibility
107
+ - MUST document type changes
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @umituz/react-native-cache
3
+ * In-memory caching utilities for React Native
4
+ */
5
+
6
+ export { Cache } from './domain/Cache';
7
+ export { CacheManager, cacheManager } from './domain/CacheManager';
8
+ export { CacheStatsTracker } from './domain/CacheStatsTracker';
9
+ export { PatternMatcher } from './domain/PatternMatcher';
10
+ export { ErrorHandler, CacheError } from './domain/ErrorHandler';
11
+ export { TTLCache } from './infrastructure/TTLCache';
12
+
13
+ export type {
14
+ CacheEntry,
15
+ CacheConfig,
16
+ CacheStats,
17
+ EvictionStrategy,
18
+ } from './domain/types/Cache';
19
+
20
+ export type { EvictionStrategy as IEvictionStrategy } from './domain/strategies/EvictionStrategy';
21
+
22
+ export { LRUStrategy } from './domain/strategies/LRUStrategy';
23
+ export { LFUStrategy } from './domain/strategies/LFUStrategy';
24
+ export { FIFOStrategy } from './domain/strategies/FIFOStrategy';
25
+ export { TTLStrategy as TTLEvictionStrategy } from './domain/strategies/TTLStrategy';
26
+
27
+ export { useCache } from './presentation/useCache';
28
+ export { useCachedValue } from './presentation/useCachedValue';
@@ -0,0 +1,126 @@
1
+ # Cache Infrastructure
2
+
3
+ Implementation details and concrete implementations of cache domain logic.
4
+
5
+ ## Overview
6
+
7
+ Infrastructure layer for cache system, providing TTLCache implementation with actual storage and eviction logic. Located at `src/cache/infrastructure/`.
8
+
9
+ ## Strategies
10
+
11
+ ### Cache Implementation
12
+ - Use Map data structure for O(1) operations
13
+ - Implement TTL-based expiration checking
14
+ - Support eviction strategies from domain layer
15
+ - Provide thread-safe operations
16
+
17
+ ### Storage Management
18
+ - Track cache size limits
19
+ - Implement automatic eviction when full
20
+ - Clean up expired entries periodically
21
+ - Support manual cache clearing
22
+
23
+ ### Performance Optimization
24
+ - Minimize memory overhead per entry
25
+ - Use efficient data structures
26
+ - Implement lazy expiration checking
27
+ - Cache frequently accessed metadata
28
+
29
+ ### Integration with Domain
30
+ - Implement interfaces defined in domain layer
31
+ - Use domain types for type safety
32
+ - Follow domain-level strategies and rules
33
+ - Export clean API to presentation layer
34
+
35
+ ## Restrictions
36
+
37
+ ### Implementation
38
+ - DO NOT expose internal storage directly
39
+ - DO NOT bypass eviction strategies
40
+ - DO NOT allow cache size to exceed limit
41
+ - DO NOT store non-serializable data
42
+
43
+ ### Performance
44
+ - DO NOT perform expensive operations on every access
45
+ - DO NOT use blocking operations
46
+ - DO NOT allocate memory unnecessarily
47
+ - DO NOT iterate entire cache for single operations
48
+
49
+ ### Expiration
50
+ - DO NOT ignore expired entries on access
51
+ - DO NOT auto-clean without explicit trigger
52
+ - DO NOT use inconsistent time sources
53
+ - DO NOT rely solely on TTL for memory management
54
+
55
+ ## Rules
56
+
57
+ ### TTLCache Implementation
58
+ - MUST implement Cache interface from domain
59
+ - MUST enforce maxSize limit
60
+ - MUST check expiration on get operations
61
+ - MUST trigger eviction when full
62
+ - MUST provide accurate statistics
63
+
64
+ ### Entry Storage
65
+ - MUST use Map<string, CacheEntry<T>> for storage
66
+ - MUST include all required metadata
67
+ - MUST update timestamps on access
68
+ - MUST validate entry structure
69
+
70
+ ### Expiration Handling
71
+ - MUST check (timestamp + ttl) < Date.now()
72
+ - MUST return undefined for expired entries
73
+ - MUST remove expired entries from storage
74
+ - MUST track expiration statistics
75
+
76
+ ### Eviction Execution
77
+ - MUST call strategy.findKeyToEvict() when full
78
+ - MUST remove selected entry from storage
79
+ - MUST trigger onEvict callback if provided
80
+ - MUST update eviction statistics
81
+
82
+ ### Statistics Tracking
83
+ - MUST increment hits on successful get
84
+ - MUST increment misses on failed get
85
+ - MUST increment evictions on eviction
86
+ - MUST increment expirations on expiration
87
+ - MUST calculate hitRate correctly
88
+
89
+ ### Public Methods
90
+ - MUST implement set(key, value, ttl?)
91
+ - MUST implement get(key) -> T | undefined
92
+ - MUST implement has(key) -> boolean
93
+ - MUST implement delete(key) -> boolean
94
+ - MUST implement clear()
95
+ - MUST implement getStats()
96
+
97
+ ### Configuration Validation
98
+ - MUST validate maxSize > 0
99
+ - MUST validate defaultTTL > 0
100
+ - MUST provide default values
101
+ - MUST reject invalid configuration
102
+
103
+ ### Lifecycle Callbacks
104
+ - MUST call onEvict(entry) when entry evicted
105
+ - MUST call onExpire(entry) when entry expired
106
+ - MUST pass key and entry to callbacks
107
+ - MUST handle callback errors gracefully
108
+
109
+ ### Type Safety
110
+ - MUST use generic type parameter T
111
+ - MUST enforce type consistency
112
+ - MUST provide type inference
113
+ - MUST validate input types where possible
114
+
115
+ ### Thread Safety
116
+ - MUST handle concurrent access appropriately
117
+ - MUST not corrupt cache state
118
+ - MUST provide atomic operations
119
+ - MUST handle race conditions
120
+
121
+ ### Testing Requirements
122
+ - MUST test all eviction strategies
123
+ - MUST test expiration logic
124
+ - MUST test statistics accuracy
125
+ - MUST test edge cases (empty, full, expired)
126
+ - MUST measure performance
@@ -0,0 +1,103 @@
1
+ /**
2
+ * TTL Cache
3
+ * Time-to-live cache with automatic cleanup
4
+ */
5
+
6
+ import { Cache } from '../domain/Cache';
7
+ import type { CacheConfig } from '../domain/types/Cache';
8
+
9
+ export class TTLCache<T = unknown> extends Cache<T> {
10
+ private cleanupInterval: ReturnType<typeof setInterval> | null = null;
11
+ private isDestroyed = false;
12
+ private readonly cleanupIntervalMs: number;
13
+
14
+ constructor(config: CacheConfig & { cleanupIntervalMs?: number } = {}) {
15
+ super(config);
16
+
17
+ this.cleanupIntervalMs = config.cleanupIntervalMs || 60000;
18
+ this.startCleanup();
19
+ }
20
+
21
+ private startCleanup(): void {
22
+ if (this.isDestroyed) return;
23
+
24
+ this.cleanupInterval = setInterval(() => {
25
+ if (!this.isDestroyed) {
26
+ this.cleanup();
27
+ }
28
+ }, this.cleanupIntervalMs);
29
+ }
30
+
31
+ private cleanup(): void {
32
+ if (this.isDestroyed) return;
33
+
34
+ const keys = this.keys();
35
+ let cleanedCount = 0;
36
+ const now = Date.now();
37
+
38
+ for (const key of keys) {
39
+ const entry = (this as any).store.get(key);
40
+ if (entry && (now - entry.timestamp) > entry.ttl) {
41
+ (this as any).store.delete(key);
42
+ cleanedCount++;
43
+ }
44
+ }
45
+
46
+ if (cleanedCount > 0) {
47
+ (this as any).statsTracker.updateSize((this as any).store.size);
48
+ (this as any).statsTracker.recordExpiration();
49
+
50
+ if (typeof __DEV__ !== 'undefined' && __DEV__) {
51
+ console.log(`TTLCache: Cleaned up ${cleanedCount} expired entries`);
52
+ }
53
+ }
54
+ }
55
+
56
+ destroy(): void {
57
+ if (this.isDestroyed) return;
58
+
59
+ this.isDestroyed = true;
60
+
61
+ if (this.cleanupInterval) {
62
+ clearInterval(this.cleanupInterval);
63
+ this.cleanupInterval = null;
64
+ }
65
+
66
+ this.clear();
67
+ }
68
+
69
+ override set(key: string, value: T, ttl?: number): void {
70
+ if (this.isDestroyed) {
71
+ if (typeof __DEV__ !== 'undefined' && __DEV__) {
72
+ console.warn('TTLCache: Attempted to set value on destroyed cache');
73
+ }
74
+ return;
75
+ }
76
+ super.set(key, value, ttl);
77
+ }
78
+
79
+ override get(key: string): T | undefined {
80
+ if (this.isDestroyed) {
81
+ if (typeof __DEV__ !== 'undefined' && __DEV__) {
82
+ console.warn('TTLCache: Attempted to get value from destroyed cache');
83
+ }
84
+ return undefined;
85
+ }
86
+ return super.get(key);
87
+ }
88
+
89
+ override has(key: string): boolean {
90
+ if (this.isDestroyed) return false;
91
+ return super.has(key);
92
+ }
93
+
94
+ override delete(key: string): boolean {
95
+ if (this.isDestroyed) return false;
96
+ return super.delete(key);
97
+ }
98
+
99
+ override clear(): void {
100
+ if (this.isDestroyed) return;
101
+ super.clear();
102
+ }
103
+ }