@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,352 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * Performance Tests
4
+ *
5
+ * Performance and memory leak tests
6
+ */
7
+
8
+ import { renderHook, act } from '@testing-library/react-hooks';
9
+ import { useStorage, useStorageState, usePersistentCache } from '../../index';
10
+ import { AsyncStorage } from '../mocks/asyncStorage.mock';
11
+ import { mockPerformance, trackMemoryUsage } from '../setup';
12
+
13
+ describe('Performance Tests', () => {
14
+ beforeEach(() => {
15
+ (AsyncStorage as any).__clear();
16
+ jest.clearAllMocks();
17
+ mockPerformance();
18
+ });
19
+
20
+ describe('Memory Leak Prevention', () => {
21
+ it('should not leak memory with multiple hook instances', () => {
22
+ const memoryTracker = trackMemoryUsage();
23
+
24
+ // Create many hook instances
25
+ const hooks = Array.from({ length: 100 }, (_, i) =>
26
+ renderHook(() => useStorage())
27
+ );
28
+
29
+ // Add listeners
30
+ hooks.forEach(hook => {
31
+ hook.current.getItem(`key-${i}`, 'default');
32
+ });
33
+
34
+ const listenerCount = memoryTracker.getListenerCount();
35
+ expect(listenerCount).toBeLessThan(50); // Should be much less than 100
36
+
37
+ // Cleanup
38
+ hooks.forEach(hook => hook.unmount());
39
+ memoryTracker.cleanup();
40
+ });
41
+
42
+ it('should cleanup on unmount', () => {
43
+ const memoryTracker = trackMemoryUsage();
44
+
45
+ const { result, unmount } = renderHook(() => useStorageState('test', 'default'));
46
+
47
+ // Add some async operations
48
+ const promise = result.current[1]('test-value');
49
+
50
+ // Unmount before promise resolves
51
+ unmount();
52
+
53
+ const listenerCount = memoryTracker.getListenerCount();
54
+ expect(listenerCount).toBe(0);
55
+
56
+ memoryTracker.cleanup();
57
+ return promise;
58
+ });
59
+
60
+ it('should not create multiple CacheStorageOperations instances', () => {
61
+ const { result: hook1 } = renderHook(() =>
62
+ usePersistentCache('key1')
63
+ );
64
+
65
+ const { result: hook2 } = renderHook(() =>
66
+ usePersistentCache('key2')
67
+ );
68
+
69
+ const { result: hook3 } = renderHook(() =>
70
+ usePersistentCache('key3')
71
+ );
72
+
73
+ // All should use the same instance (singleton pattern)
74
+ expect(hook1.current.setData).toBe(hook2.current.setData);
75
+ expect(hook2.current.setData).toBe(hook3.current.setData);
76
+ });
77
+ });
78
+
79
+ describe('Performance Benchmarks', () => {
80
+ it('should handle large datasets efficiently', async () => {
81
+ const { result: storageHook } = renderHook(() => useStorage());
82
+
83
+ // Create large dataset (10,000 items)
84
+ const largeData = Array.from({ length: 10000 }, (_, i) => ({
85
+ id: i,
86
+ name: `Item ${i}`,
87
+ description: `Description for item ${i}`,
88
+ metadata: {
89
+ created: Date.now(),
90
+ tags: [`tag${i % 10}`, `category${i % 5}`],
91
+ },
92
+ }));
93
+
94
+ const startTime = performance.now();
95
+
96
+ // Set large data
97
+ const setSuccess = await storageHook.current.setItem('large-data', largeData);
98
+ expect(setSuccess).toBe(true);
99
+
100
+ // Get large data
101
+ const retrievedData = await storageHook.current.getItem('large-data', []);
102
+ expect(retrievedData).toEqual(largeData);
103
+
104
+ const endTime = performance.now();
105
+ const duration = endTime - startTime;
106
+
107
+ // Should complete within reasonable time (less than 1 second)
108
+ expect(duration).toBeLessThan(1000);
109
+ });
110
+
111
+ it('should handle rapid operations efficiently', async () => {
112
+ const { result: storageHook } = renderHook(() => useStorage());
113
+
114
+ const iterations = 1000;
115
+ const startTime = performance.now();
116
+
117
+ // Rapid set/get operations
118
+ for (let i = 0; i < iterations; i++) {
119
+ const key = `rapid-key-${i}`;
120
+ const value = `rapid-value-${i}`;
121
+
122
+ await storageHook.current.setItem(key, value);
123
+ const retrieved = await storageHook.current.getItem(key, '');
124
+ expect(retrieved).toBe(value);
125
+ }
126
+
127
+ const endTime = performance.now();
128
+ const duration = endTime - startTime;
129
+ const avgTime = duration / iterations;
130
+
131
+ // Average operation should be fast (less than 1ms per operation)
132
+ expect(avgTime).toBeLessThan(1);
133
+ });
134
+
135
+ it('should handle concurrent operations efficiently', async () => {
136
+ const { result: storageHook } = renderHook(() => useStorage());
137
+
138
+ const concurrentOperations = 100;
139
+ const operations = Array.from({ length: concurrentOperations }, (_, i) =>
140
+ storageHook.current.setItem(`concurrent-key-${i}`, `concurrent-value-${i}`)
141
+ );
142
+
143
+ const startTime = performance.now();
144
+
145
+ // Execute all operations concurrently
146
+ const results = await Promise.all(operations);
147
+
148
+ const endTime = performance.now();
149
+ const duration = endTime - startTime;
150
+
151
+ // All operations should succeed
152
+ expect(results.every(success => success)).toBe(true);
153
+
154
+ // Concurrent operations should be faster than sequential
155
+ expect(duration).toBeLessThan(concurrentOperations * 10); // Less than 10ms per operation
156
+ });
157
+ });
158
+
159
+ describe('Cache Performance', () => {
160
+ it('should handle cache operations efficiently', async () => {
161
+ const { result: cacheHook } = renderHook(() =>
162
+ usePersistentCache('performance-cache')
163
+ );
164
+
165
+ const cacheOperations = 1000;
166
+ const startTime = performance.now();
167
+
168
+ // Rapid cache operations
169
+ for (let i = 0; i < cacheOperations; i++) {
170
+ const data = { id: i, value: `cache-value-${i}` };
171
+
172
+ await cacheHook.current.setData(data);
173
+ expect(cacheHook.current.data).toEqual(data);
174
+ }
175
+
176
+ const endTime = performance.now();
177
+ const duration = endTime - startTime;
178
+ const avgTime = duration / cacheOperations;
179
+
180
+ // Cache operations should be very fast
181
+ expect(avgTime).toBeLessThan(0.1); // Less than 0.1ms per operation
182
+ });
183
+
184
+ it('should handle TTL checks efficiently', async () => {
185
+ const { result: cacheHook } = renderHook(() =>
186
+ usePersistentCache('ttl-cache', { ttl: 60000 })
187
+ );
188
+
189
+ const data = { test: 'value' };
190
+ await cacheHook.current.setData(data);
191
+
192
+ const startTime = performance.now();
193
+
194
+ // Check TTL many times (should be cached)
195
+ for (let i = 0; i < 10000; i++) {
196
+ // Access isExpired property
197
+ const isExpired = cacheHook.current.isExpired;
198
+ expect(isExpired).toBe(false);
199
+ }
200
+
201
+ const endTime = performance.now();
202
+ const duration = endTime - startTime;
203
+
204
+ // TTL checks should be extremely fast
205
+ expect(duration).toBeLessThan(10); // Less than 10ms for 10,000 checks
206
+ });
207
+ });
208
+
209
+ describe('State Performance', () => {
210
+ it('should handle state updates efficiently', async () => {
211
+ const { result: stateHook, waitForNextUpdate } = renderHook(() =>
212
+ useStorageState('performance-state', 'initial')
213
+ );
214
+
215
+ await act(async () => {
216
+ await waitForNextUpdate();
217
+ });
218
+
219
+ const stateUpdates = 1000;
220
+ const startTime = performance.now();
221
+
222
+ // Rapid state updates
223
+ for (let i = 0; i < stateUpdates; i++) {
224
+ await act(async () => {
225
+ await stateHook.current[1](`update-${i}`);
226
+ });
227
+ expect(stateHook.current[0]).toBe(`update-${i}`);
228
+ }
229
+
230
+ const endTime = performance.now();
231
+ const duration = endTime - startTime;
232
+ const avgTime = duration / stateUpdates;
233
+
234
+ // State updates should be fast
235
+ expect(avgTime).toBeLessThan(1); // Less than 1ms per update
236
+ });
237
+
238
+ it('should not re-render unnecessarily', async () => {
239
+ let renderCount = 0;
240
+
241
+ const TestComponent = () => {
242
+ renderCount++;
243
+ const [state] = useStorageState('render-test', 'default');
244
+ return null; // Don't render anything
245
+ };
246
+
247
+ const { rerender } = renderHook(() => <TestComponent />);
248
+
249
+ const initialRenders = renderCount;
250
+
251
+ // Rerender with same props
252
+ rerender(<TestComponent />);
253
+
254
+ // Should not cause additional renders
255
+ expect(renderCount).toBe(initialRenders);
256
+ });
257
+ });
258
+
259
+ describe('Memory Usage', () => {
260
+ it('should maintain stable memory usage', async () => {
261
+ const { result: storageHook } = renderHook(() => useStorage());
262
+
263
+ const initialMemory = (performance as any).memory?.usedJSHeapSize || 0;
264
+
265
+ // Create and destroy many objects
266
+ for (let i = 0; i < 1000; i++) {
267
+ const largeObject = {
268
+ id: i,
269
+ data: new Array(1000).fill(`data-${i}`),
270
+ nested: {
271
+ level1: { level2: { level3: new Array(100).fill(`nested-${i}`) } },
272
+ },
273
+ };
274
+
275
+ await storageHook.current.setItem(`temp-${i}`, largeObject);
276
+ await storageHook.current.removeItem(`temp-${i}`);
277
+ }
278
+
279
+ // Force garbage collection if available
280
+ if (global.gc) {
281
+ global.gc();
282
+ }
283
+
284
+ const finalMemory = (performance as any).memory?.usedJSHeapSize || 0;
285
+ const memoryIncrease = finalMemory - initialMemory;
286
+
287
+ // Memory increase should be minimal
288
+ expect(memoryIncrease).toBeLessThan(1024 * 1024); // Less than 1MB increase
289
+ });
290
+
291
+ it('should cleanup event listeners', () => {
292
+ const memoryTracker = trackMemoryUsage();
293
+
294
+ // Create and destroy many hooks
295
+ for (let i = 0; i < 100; i++) {
296
+ const { unmount } = renderHook(() => useStorageState(`cleanup-${i}`, 'default'));
297
+ unmount();
298
+ }
299
+
300
+ const listenerCount = memoryTracker.getListenerCount();
301
+ expect(listenerCount).toBe(0);
302
+
303
+ memoryTracker.cleanup();
304
+ });
305
+ });
306
+
307
+ describe('Scalability Tests', () => {
308
+ it('should handle many keys efficiently', async () => {
309
+ const { result: storageHook } = renderHook(() => useStorage());
310
+
311
+ const keyCount = 10000;
312
+ const startTime = performance.now();
313
+
314
+ // Create many keys
315
+ for (let i = 0; i < keyCount; i++) {
316
+ await storageHook.current.setItem(`scale-key-${i}`, `scale-value-${i}`);
317
+ }
318
+
319
+ const endTime = performance.now();
320
+ const duration = endTime - startTime;
321
+
322
+ // Should handle many keys efficiently
323
+ expect(duration).toBeLessThan(keyCount * 0.1); // Less than 0.1ms per key
324
+
325
+ // Verify all keys exist
326
+ for (let i = 0; i < keyCount; i++) {
327
+ const exists = await storageHook.current.hasItem(`scale-key-${i}`);
328
+ expect(exists).toBe(true);
329
+ }
330
+ });
331
+
332
+ it('should handle large values efficiently', async () => {
333
+ const { result: storageHook } = renderHook(() => useStorage());
334
+
335
+ // Create very large value (1MB string)
336
+ const largeValue = 'x'.repeat(1024 * 1024);
337
+ const startTime = performance.now();
338
+
339
+ const setSuccess = await storageHook.current.setItem('large-value', largeValue);
340
+ expect(setSuccess).toBe(true);
341
+
342
+ const retrievedValue = await storageHook.current.getString('large-value', '');
343
+ expect(retrievedValue).toBe(largeValue);
344
+
345
+ const endTime = performance.now();
346
+ const duration = endTime - startTime;
347
+
348
+ // Large values should be handled efficiently
349
+ expect(duration).toBeLessThan(100); // Less than 100ms for 1MB
350
+ });
351
+ });
352
+ });
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Test Setup
3
+ *
4
+ * Global test configuration and mocks
5
+ */
6
+
7
+ import 'jest-environment-jsdom';
8
+
9
+ // Mock __DEV__ global
10
+ Object.defineProperty(globalThis, '__DEV__', {
11
+ value: true,
12
+ writable: true,
13
+ });
14
+
15
+ // Mock AsyncStorage
16
+ jest.mock('@react-native-async-storage/async-storage', () => ({
17
+ default: {
18
+ getItem: jest.fn(),
19
+ setItem: jest.fn(),
20
+ removeItem: jest.fn(),
21
+ clear: jest.fn(),
22
+ getAllKeys: jest.fn(),
23
+ multiGet: jest.fn(),
24
+ },
25
+ }));
26
+
27
+ // Mock console for __DEV__ checks
28
+ const originalConsole = { ...console };
29
+
30
+ beforeEach(() => {
31
+ jest.clearAllMocks();
32
+ });
33
+
34
+ afterEach(() => {
35
+ // Restore console after each test
36
+ Object.assign(console, originalConsole);
37
+ });
38
+
39
+ // Performance test utilities
40
+ export const mockPerformance = () => {
41
+ const mockPerformance = {
42
+ now: jest.fn(() => Date.now()),
43
+ mark: jest.fn(),
44
+ measure: jest.fn(),
45
+ };
46
+
47
+ globalThis.performance = mockPerformance as any;
48
+ return mockPerformance;
49
+ };
50
+
51
+ // Memory leak test utilities
52
+ export const trackMemoryUsage = () => {
53
+ const listeners = new Set<() => void>();
54
+
55
+ return {
56
+ addListener: (listener: () => void) => {
57
+ listeners.add(listener);
58
+ return () => listeners.delete(listener);
59
+ },
60
+ getListenerCount: () => listeners.size,
61
+ cleanup: () => listeners.clear(),
62
+ };
63
+ };
@@ -0,0 +1,158 @@
1
+ # Application Layer
2
+
3
+ Ports and interfaces for dependency inversion between domain and infrastructure layers.
4
+
5
+ ## Overview
6
+
7
+ Application layer containing interfaces (ports) for storage operations. Located at `src/application/`.
8
+
9
+ ## Directory Structure
10
+
11
+ - `ports/` - Repository interfaces defining storage contracts
12
+
13
+ ## Strategies
14
+
15
+ ### Dependency Inversion
16
+ - Use IStorageRepository interface for storage operations
17
+ - Define contracts in application layer
18
+ - Implement interfaces in infrastructure layer
19
+ - Enable dependency injection for testing
20
+
21
+ ### Port Definition
22
+ - Use IStorageRepository as primary storage interface
23
+ - Define all storage operations as methods
24
+ - Support Result pattern for error handling
25
+ - Enable generic type parameters for type safety
26
+
27
+ ### Use Case Pattern
28
+ - Create use cases for complex business logic
29
+ - Inject IStorageRepository through constructor
30
+ - Encapsulate business rules in use case methods
31
+ - Enable testing with mock implementations
32
+
33
+ ### Interface Segregation
34
+ - Define cohesive interfaces for specific purposes
35
+ - Support granular method dependencies
36
+ - Enable single responsibility principle
37
+ - Facilitate testing with focused mocks
38
+
39
+ ## Restrictions
40
+
41
+ ### Interface Definition
42
+ - DO NOT define implementation details in interfaces
43
+ - DO NOT create interfaces without clear purpose
44
+ - DO NOT mix different concerns in single interface
45
+ - DO NOT include framework-specific types
46
+
47
+ ### Dependency Injection
48
+ - DO NOT create concrete instances in use cases
49
+ - DO NOT use hardcoded dependencies
50
+ - DO NOT skip constructor injection
51
+ - DO NOT create circular dependencies
52
+
53
+ ### Use Case Implementation
54
+ - DO NOT implement business logic in components
55
+ - DO NOT mix storage operations with UI logic
56
+ - DO NOT create use cases without clear purpose
57
+ - DO NOT bypass error handling in use cases
58
+
59
+ ### Testing
60
+ - DO NOT test with real storage implementations
61
+ - DO NOT create complex mock implementations
62
+ - DO NOT share state between tests
63
+ - DO NOT forget to reset mocks between tests
64
+
65
+ ## Rules
66
+
67
+ ### IStorageRepository Interface
68
+ - MUST define getItem<T>(key, defaultValue): Promise<StorageResult<T>>
69
+ - MUST define setItem<T>(key, value): Promise<StorageResult<void>>
70
+ - MUST define getString(key, defaultValue): Promise<StorageResult<string>>
71
+ - MUST define setString(key, value): Promise<StorageResult<void>>
72
+ - MUST define removeItem(key): Promise<StorageResult<void>>
73
+ - MUST define hasItem(key): Promise<boolean>
74
+ - MUST define clearAll(): Promise<StorageResult<void>>
75
+
76
+ ### Interface Design
77
+ - MUST use generic type parameters for value operations
78
+ - MUST return Result type for all mutable operations
79
+ - MUST support type inference from parameters
80
+ - MUST be framework-agnostic
81
+ - MUST define contracts only (no implementation)
82
+
83
+ ### Method Signatures
84
+ - MUST accept key parameter for all operations
85
+ - MUST accept defaultValue parameter for get operations
86
+ - MUST accept value parameter for set operations
87
+ - MUST return Promise for all async operations
88
+ - MUST include StorageResult for typed results
89
+
90
+ ### Use Case Implementation
91
+ - MUST accept IStorageRepository in constructor
92
+ - MUST define single responsibility per use case
93
+ - MUST handle Result pattern in all operations
94
+ - MUST return domain types from use case methods
95
+ - MUST not expose storage implementation details
96
+
97
+ ### Constructor Injection
98
+ - MUST inject dependencies through constructor
99
+ - MUST store dependencies as private fields
100
+ - MUST use interface types for dependencies
101
+ - MUST enable dependency injection for testing
102
+ - MUST not create instances inside use cases
103
+
104
+ ### Error Handling
105
+ - MUST check result.success before accessing data
106
+ - MUST handle result.error appropriately
107
+ - MUST propagate errors to callers when needed
108
+ - MUST not throw exceptions from use cases
109
+ - MUST preserve error context
110
+
111
+ ### Testing Requirements
112
+ - MUST enable mocking of IStorageRepository
113
+ - MUST support test double implementations
114
+ - MUST isolate tests from real storage
115
+ - MUST clear state between test runs
116
+ - MUST not depend on external services
117
+
118
+ ### Mock Implementation
119
+ - MUST implement full IStorageRepository interface
120
+ - MUST return appropriate Result types
121
+ - MUST simulate storage behavior accurately
122
+ - MUST support async operations with Promise
123
+ - MUST be simple and predictable
124
+
125
+ ### Custom Repository Implementation
126
+ - MUST implement IStorageRepository interface
127
+ - MUST use Result pattern for all methods
128
+ - MUST handle errors appropriately
129
+ - MUST support generic type parameters
130
+ - MUST be compatible with existing code
131
+
132
+ ### Layer Separation
133
+ - MUST not depend on infrastructure implementations
134
+ - MUST not depend on presentation components
135
+ - MUST define contracts for domain use
136
+ - MUST enable layer independence
137
+ - MUST support testing at each layer
138
+
139
+ ### Export Rules
140
+ - MUST export IStorageRepository interface
141
+ - MUST export all port interfaces
142
+ - MUST not export implementations
143
+ - MUST provide TypeScript types
144
+ - MUST document interface contracts
145
+
146
+ ### Architecture Compliance
147
+ - MUST follow dependency inversion principle
148
+ - MUST depend on abstractions not concretions
149
+ - MUST enable independent layer evolution
150
+ - MUST support multiple implementations
151
+ - MUST maintain clear separation of concerns
152
+
153
+ ### Documentation
154
+ - MUST document all interface methods
155
+ - MUST specify method contracts clearly
156
+ - MUST provide usage guidance
157
+ - MUST explain Result pattern usage
158
+ - MUST not include implementation examples
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Storage Repository Interface (Port)
3
+ *
4
+ * Domain-Driven Design: Application port for storage operations
5
+ * Infrastructure layer implements this interface
6
+ */
7
+
8
+ import type { StorageResult } from '../../domain/entities/StorageResult';
9
+
10
+ /**
11
+ * Storage Repository Interface
12
+ * Defines contract for storage operations
13
+ */
14
+ export interface IStorageRepository {
15
+ /**
16
+ * Get item from storage with JSON parsing
17
+ */
18
+ getItem<T>(key: string, defaultValue: T): Promise<StorageResult<T>>;
19
+
20
+ /**
21
+ * Set item in storage with JSON serialization
22
+ */
23
+ setItem<T>(key: string, value: T): Promise<StorageResult<T>>;
24
+
25
+ /**
26
+ * Get string value (no JSON parsing)
27
+ */
28
+ getString(key: string, defaultValue: string): Promise<StorageResult<string>>;
29
+
30
+ /**
31
+ * Set string value (no JSON serialization)
32
+ */
33
+ setString(key: string, value: string): Promise<StorageResult<string>>;
34
+
35
+ /**
36
+ * Remove item from storage
37
+ */
38
+ removeItem(key: string): Promise<StorageResult<void>>;
39
+
40
+ /**
41
+ * Check if key exists in storage
42
+ */
43
+ hasItem(key: string): Promise<boolean>;
44
+
45
+ /**
46
+ * Clear all storage data
47
+ */
48
+ clearAll(): Promise<StorageResult<void>>;
49
+
50
+ /**
51
+ * Get multiple items at once
52
+ */
53
+ getMultiple(keys: string[]): Promise<StorageResult<Record<string, string | null>>>;
54
+
55
+ /**
56
+ * Get all keys from storage
57
+ */
58
+ getAllKeys(): Promise<StorageResult<string[]>>;
59
+
60
+
61
+ }