@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.
- package/package.json +5 -6
- package/src/device/infrastructure/repositories/LegacyDeviceIdRepository.ts +1 -1
- package/src/device/infrastructure/services/DeviceFeatureService.ts +1 -1
- package/src/exception/infrastructure/services/ExceptionLogger.ts +1 -1
- package/src/exception/infrastructure/storage/ExceptionStore.ts +1 -1
- package/src/exports/filesystem.ts +1 -0
- package/src/exports/storage.ts +1 -0
- package/src/filesystem/domain/constants/FileConstants.ts +20 -0
- package/src/filesystem/domain/entities/File.ts +20 -0
- package/src/filesystem/domain/types/FileTypes.ts +43 -0
- package/src/filesystem/domain/utils/FileUtils.ts +86 -0
- package/src/filesystem/index.ts +23 -0
- package/src/filesystem/infrastructure/services/FileSystemService.ts +45 -0
- package/src/filesystem/infrastructure/services/cache.service.ts +48 -0
- package/src/filesystem/infrastructure/services/directory.service.ts +66 -0
- package/src/filesystem/infrastructure/services/download.constants.ts +6 -0
- package/src/filesystem/infrastructure/services/download.service.ts +74 -0
- package/src/filesystem/infrastructure/services/download.types.ts +7 -0
- package/src/filesystem/infrastructure/services/encoding.service.ts +25 -0
- package/src/filesystem/infrastructure/services/file-info.service.ts +52 -0
- package/src/filesystem/infrastructure/services/file-manager.service.ts +81 -0
- package/src/filesystem/infrastructure/services/file-path.service.ts +22 -0
- package/src/filesystem/infrastructure/services/file-reader.service.ts +52 -0
- package/src/filesystem/infrastructure/services/file-writer.service.ts +32 -0
- package/src/filesystem/infrastructure/utils/blob.utils.ts +20 -0
- package/src/image/infrastructure/services/ImageStorageService.ts +1 -1
- package/src/index.ts +9 -0
- package/src/molecules/alerts/AlertStore.ts +1 -1
- package/src/molecules/calendar/infrastructure/storage/EventActions.ts +1 -1
- package/src/molecules/calendar/infrastructure/stores/storageAdapter.ts +1 -1
- package/src/offline/infrastructure/storage/OfflineStore.ts +1 -1
- package/src/onboarding/infrastructure/storage/OnboardingStore.ts +2 -2
- package/src/onboarding/infrastructure/storage/__tests__/OnboardingStore.test.ts +1 -1
- package/src/onboarding/infrastructure/storage/actions/answerActions.ts +1 -1
- package/src/onboarding/infrastructure/storage/actions/storageHelpers.ts +1 -1
- package/src/storage/README.md +185 -0
- package/src/storage/__tests__/integration.test.ts +391 -0
- package/src/storage/__tests__/mocks/asyncStorage.mock.ts +52 -0
- package/src/storage/__tests__/performance.test.tsx +352 -0
- package/src/storage/__tests__/setup.ts +63 -0
- package/src/storage/application/README.md +158 -0
- package/src/storage/application/ports/IStorageRepository.ts +61 -0
- package/src/storage/application/ports/README.md +127 -0
- package/src/storage/cache/README.md +154 -0
- package/src/storage/cache/__tests__/PerformanceAndMemory.test.ts +387 -0
- package/src/storage/cache/__tests__/setup.ts +19 -0
- package/src/storage/cache/domain/Cache.ts +146 -0
- package/src/storage/cache/domain/CacheManager.md +83 -0
- package/src/storage/cache/domain/CacheManager.ts +48 -0
- package/src/storage/cache/domain/CacheStatsTracker.md +169 -0
- package/src/storage/cache/domain/CacheStatsTracker.ts +49 -0
- package/src/storage/cache/domain/CachedValue.md +97 -0
- package/src/storage/cache/domain/ErrorHandler.md +99 -0
- package/src/storage/cache/domain/ErrorHandler.ts +42 -0
- package/src/storage/cache/domain/PatternMatcher.md +122 -0
- package/src/storage/cache/domain/PatternMatcher.ts +30 -0
- package/src/storage/cache/domain/README.md +118 -0
- package/src/storage/cache/domain/__tests__/Cache.test.ts +293 -0
- package/src/storage/cache/domain/__tests__/CacheManager.test.ts +276 -0
- package/src/storage/cache/domain/__tests__/ErrorHandler.test.ts +303 -0
- package/src/storage/cache/domain/__tests__/PatternMatcher.test.ts +261 -0
- package/src/storage/cache/domain/strategies/EvictionStrategy.ts +9 -0
- package/src/storage/cache/domain/strategies/FIFOStrategy.ts +12 -0
- package/src/storage/cache/domain/strategies/LFUStrategy.ts +22 -0
- package/src/storage/cache/domain/strategies/LRUStrategy.ts +22 -0
- package/src/storage/cache/domain/strategies/README.md +117 -0
- package/src/storage/cache/domain/strategies/TTLStrategy.ts +23 -0
- package/src/storage/cache/domain/strategies/__tests__/EvictionStrategies.test.ts +293 -0
- package/src/storage/cache/domain/types/Cache.ts +28 -0
- package/src/storage/cache/domain/types/README.md +107 -0
- package/src/storage/cache/index.ts +28 -0
- package/src/storage/cache/infrastructure/README.md +126 -0
- package/src/storage/cache/infrastructure/TTLCache.ts +103 -0
- package/src/storage/cache/infrastructure/__tests__/TTLCache.test.ts +303 -0
- package/src/storage/cache/presentation/README.md +123 -0
- package/src/storage/cache/presentation/__tests__/ReactHooks.test.ts +514 -0
- package/src/storage/cache/presentation/useCache.ts +76 -0
- package/src/storage/cache/presentation/useCachedValue.ts +88 -0
- package/src/storage/cache/types.d.ts +3 -0
- package/src/storage/domain/README.md +128 -0
- package/src/storage/domain/constants/CacheDefaults.ts +64 -0
- package/src/storage/domain/constants/README.md +105 -0
- package/src/storage/domain/entities/CachedValue.ts +86 -0
- package/src/storage/domain/entities/README.md +109 -0
- package/src/storage/domain/entities/StorageResult.ts +75 -0
- package/src/storage/domain/entities/__tests__/CachedValue.test.ts +149 -0
- package/src/storage/domain/entities/__tests__/StorageResult.test.ts +122 -0
- package/src/storage/domain/errors/README.md +126 -0
- package/src/storage/domain/errors/StorageError.ts +81 -0
- package/src/storage/domain/errors/__tests__/StorageError.test.ts +127 -0
- package/src/storage/domain/factories/README.md +138 -0
- package/src/storage/domain/factories/StoreFactory.ts +59 -0
- package/src/storage/domain/types/README.md +522 -0
- package/src/storage/domain/types/Store.ts +44 -0
- package/src/storage/domain/utils/CacheKeyGenerator.ts +66 -0
- package/src/storage/domain/utils/README.md +127 -0
- package/src/storage/domain/utils/__tests__/devUtils.test.ts +97 -0
- package/src/storage/domain/utils/devUtils.ts +37 -0
- package/src/storage/domain/value-objects/README.md +120 -0
- package/src/storage/domain/value-objects/StorageKey.ts +60 -0
- package/src/storage/index.ts +175 -0
- package/src/storage/infrastructure/README.md +165 -0
- package/src/storage/infrastructure/adapters/README.md +175 -0
- package/src/storage/infrastructure/adapters/StorageService.md +103 -0
- package/src/storage/infrastructure/adapters/StorageService.ts +49 -0
- package/src/storage/infrastructure/repositories/AsyncStorageRepository.ts +98 -0
- package/src/storage/infrastructure/repositories/BaseStorageOperations.ts +100 -0
- package/src/storage/infrastructure/repositories/BatchStorageOperations.ts +42 -0
- package/src/storage/infrastructure/repositories/README.md +121 -0
- package/src/storage/infrastructure/repositories/StringStorageOperations.ts +44 -0
- package/src/storage/infrastructure/repositories/__tests__/AsyncStorageRepository.test.ts +170 -0
- package/src/storage/infrastructure/repositories/__tests__/BaseStorageOperations.test.ts +201 -0
- package/src/storage/presentation/README.md +181 -0
- package/src/storage/presentation/hooks/CacheStorageOperations.ts +94 -0
- package/src/storage/presentation/hooks/README.md +128 -0
- package/src/storage/presentation/hooks/__tests__/usePersistentCache.test.ts +405 -0
- package/src/storage/presentation/hooks/__tests__/useStorage.test.ts +247 -0
- package/src/storage/presentation/hooks/__tests__/useStorageState.test.ts +293 -0
- package/src/storage/presentation/hooks/useCacheState.ts +53 -0
- package/src/storage/presentation/hooks/usePersistentCache.ts +154 -0
- package/src/storage/presentation/hooks/useStorage.ts +102 -0
- package/src/storage/presentation/hooks/useStorageState.ts +71 -0
- package/src/storage/presentation/hooks/useStore.ts +15 -0
- package/src/storage/types/README.md +103 -0
- package/src/theme/infrastructure/globalThemeStore.ts +1 -1
- package/src/theme/infrastructure/storage/ThemeStorage.ts +1 -1
- package/src/theme/infrastructure/stores/themeStore.ts +1 -1
- package/src/utilities/sharing/infrastructure/services/SharingService.ts +1 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Manager Service
|
|
3
|
+
* Single Responsibility: Manage file operations (delete, copy, move)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { File, Directory } from "expo-file-system";
|
|
7
|
+
import type { FileOperationResult } from "../../domain/entities/File";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Delete file or directory
|
|
11
|
+
*/
|
|
12
|
+
export async function deleteFile(uri: string): Promise<boolean> {
|
|
13
|
+
try {
|
|
14
|
+
// Try as file first
|
|
15
|
+
try {
|
|
16
|
+
const file = new File(uri);
|
|
17
|
+
if (file.exists) {
|
|
18
|
+
file.delete();
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
// Not a file, try as directory
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Try as directory
|
|
26
|
+
try {
|
|
27
|
+
const dir = new Directory(uri);
|
|
28
|
+
if (dir.exists) {
|
|
29
|
+
dir.delete();
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
// Not a directory either
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return false;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Copy file
|
|
44
|
+
*/
|
|
45
|
+
export async function copyFile(
|
|
46
|
+
sourceUri: string,
|
|
47
|
+
destinationUri: string,
|
|
48
|
+
): Promise<FileOperationResult> {
|
|
49
|
+
try {
|
|
50
|
+
const sourceFile = new File(sourceUri);
|
|
51
|
+
const destination = new File(destinationUri);
|
|
52
|
+
sourceFile.copy(destination);
|
|
53
|
+
return { success: true, uri: destinationUri };
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return {
|
|
56
|
+
success: false,
|
|
57
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Move file
|
|
64
|
+
*/
|
|
65
|
+
export async function moveFile(
|
|
66
|
+
sourceUri: string,
|
|
67
|
+
destinationUri: string,
|
|
68
|
+
): Promise<FileOperationResult> {
|
|
69
|
+
try {
|
|
70
|
+
const sourceFile = new File(sourceUri);
|
|
71
|
+
const destination = new File(destinationUri);
|
|
72
|
+
sourceFile.move(destination);
|
|
73
|
+
return { success: true, uri: destinationUri };
|
|
74
|
+
} catch (error) {
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Path Service
|
|
3
|
+
* Single Responsibility: Generate and manage file paths
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { DirectoryType } from "../../domain/entities/File";
|
|
7
|
+
import { getDirectoryPath } from "./directory.service";
|
|
8
|
+
import { FileUtils } from "../../domain/entities/File";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate unique file path in specified directory
|
|
12
|
+
*/
|
|
13
|
+
export function generateFilePath(
|
|
14
|
+
filename: string,
|
|
15
|
+
directory: DirectoryType = "documentDirectory",
|
|
16
|
+
): string {
|
|
17
|
+
const dirPath = getDirectoryPath(directory);
|
|
18
|
+
const uniqueFilename = FileUtils.generateUniqueFilename(filename);
|
|
19
|
+
return FileUtils.joinPaths(dirPath, uniqueFilename);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Reader Service
|
|
3
|
+
* Single Responsibility: Read files from device storage
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { File } from "expo-file-system";
|
|
7
|
+
import type { FileEncoding } from "../../domain/entities/File";
|
|
8
|
+
import { blobToBase64 } from "../utils/blob.utils";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Read file as string with encoding
|
|
12
|
+
*/
|
|
13
|
+
export async function readFile(
|
|
14
|
+
uri: string,
|
|
15
|
+
encoding: FileEncoding = "utf8",
|
|
16
|
+
): Promise<string | null> {
|
|
17
|
+
try {
|
|
18
|
+
// For file:// URLs, try fetch first (works in React Native)
|
|
19
|
+
if (uri.startsWith("file://")) {
|
|
20
|
+
try {
|
|
21
|
+
const response = await fetch(uri);
|
|
22
|
+
if (response.ok) {
|
|
23
|
+
if (encoding === "base64") {
|
|
24
|
+
const blob = await response.blob();
|
|
25
|
+
return await blobToBase64(blob);
|
|
26
|
+
}
|
|
27
|
+
return await response.text();
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
// Fall through to FileSystem API
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Use FileSystem API as fallback
|
|
35
|
+
const file = new File(uri);
|
|
36
|
+
if (encoding === "base64") {
|
|
37
|
+
const content = await file.base64();
|
|
38
|
+
return content;
|
|
39
|
+
}
|
|
40
|
+
const content = await file.text();
|
|
41
|
+
return content;
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Read file as base64 string
|
|
49
|
+
*/
|
|
50
|
+
export async function readFileAsBase64(uri: string): Promise<string | null> {
|
|
51
|
+
return readFile(uri, "base64");
|
|
52
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Writer Service
|
|
3
|
+
* Single Responsibility: Write files to device storage
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { File } from "expo-file-system";
|
|
7
|
+
import type { FileEncoding, FileOperationResult } from "../../domain/entities/File";
|
|
8
|
+
import { getEncodingType, type ExpoEncodingType } from "./encoding.service";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Write string to file
|
|
12
|
+
*/
|
|
13
|
+
export async function writeFile(
|
|
14
|
+
uri: string,
|
|
15
|
+
content: string,
|
|
16
|
+
encoding: FileEncoding = "utf8",
|
|
17
|
+
): Promise<FileOperationResult> {
|
|
18
|
+
try {
|
|
19
|
+
const encodingType = getEncodingType(encoding);
|
|
20
|
+
const file = new File(uri);
|
|
21
|
+
file.write(content, {
|
|
22
|
+
encoding: encodingType as ExpoEncodingType,
|
|
23
|
+
});
|
|
24
|
+
return { success: true, uri };
|
|
25
|
+
} catch (error) {
|
|
26
|
+
const writeError = error as Error;
|
|
27
|
+
return {
|
|
28
|
+
success: false,
|
|
29
|
+
error: writeError.message || "Unknown error",
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blob Utils
|
|
3
|
+
* Blob utility functions for file operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Convert blob to base64 string
|
|
8
|
+
*/
|
|
9
|
+
export function blobToBase64(blob: Blob): Promise<string> {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const reader = new FileReader();
|
|
12
|
+
reader.onloadend = () => {
|
|
13
|
+
const result = reader.result as string;
|
|
14
|
+
const base64 = result.includes(",") ? result.split(",")[1] ?? result : result;
|
|
15
|
+
resolve(base64);
|
|
16
|
+
};
|
|
17
|
+
reader.onerror = reject;
|
|
18
|
+
reader.readAsDataURL(blob);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles saving images to the device filesystem
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { FileSystemService } from '@
|
|
7
|
+
import { FileSystemService } from '@filesystem';
|
|
8
8
|
import { ImageValidator } from '../utils/ImageValidator';
|
|
9
9
|
import { ImageErrorHandler, IMAGE_ERROR_CODES } from '../utils/ImageErrorHandler';
|
|
10
10
|
|
package/src/index.ts
CHANGED
|
@@ -102,7 +102,16 @@ export * from './exports/variants';
|
|
|
102
102
|
// =============================================================================
|
|
103
103
|
export * from './exports/utilities';
|
|
104
104
|
|
|
105
|
+
// =============================================================================
|
|
106
|
+
// STORAGE EXPORTS
|
|
107
|
+
// =============================================================================
|
|
108
|
+
export * from './exports/storage';
|
|
109
|
+
|
|
105
110
|
// =============================================================================
|
|
106
111
|
// ONBOARDING EXPORTS
|
|
107
112
|
// =============================================================================
|
|
108
113
|
export * from './exports/onboarding';
|
|
114
|
+
// =============================================================================
|
|
115
|
+
// FILESYSTEM EXPORTS
|
|
116
|
+
// =============================================================================
|
|
117
|
+
export * from './exports/filesystem';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Event CRUD operations for calendar store
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { storageRepository, unwrap } from '@
|
|
6
|
+
import { storageRepository, unwrap } from '@storage';
|
|
7
7
|
import type { CalendarEvent, CreateCalendarEventRequest, UpdateCalendarEventRequest } from '../../domain/entities/CalendarEvent.entity';
|
|
8
8
|
import { generateId, STORAGE_KEY, hydrateEvents, handleStorageError, handleStorageSuccess } from './CalendarStore.utils';
|
|
9
9
|
import type { CalendarState } from './CalendarStore.types';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Converts AsyncStorageRepository to Zustand-compatible storage
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { storageRepository } from '@
|
|
6
|
+
import { storageRepository } from '@storage';
|
|
7
7
|
|
|
8
8
|
export const zustandStorage = {
|
|
9
9
|
getItem: async (name: string): Promise<string | null> => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Uses expo-network for universal network detection
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { createStore } from '@
|
|
7
|
+
import { createStore } from '@storage';
|
|
8
8
|
import type { NetworkState, OfflineState, OfflineActions } from '../../types';
|
|
9
9
|
|
|
10
10
|
const initialState: OfflineState = {
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* Onboarding Store
|
|
3
3
|
*
|
|
4
4
|
* Zustand store for managing onboarding completion state
|
|
5
|
-
* Uses @
|
|
5
|
+
* Uses @storage for persistence
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { useMemo } from "react";
|
|
9
|
-
import { createStore } from "@
|
|
9
|
+
import { createStore } from "@storage";
|
|
10
10
|
import type { OnboardingStoreState } from "./OnboardingStoreState";
|
|
11
11
|
import { initialOnboardingState } from "./OnboardingStoreState";
|
|
12
12
|
import { createOnboardingStoreActions } from "./OnboardingStoreActions";
|
|
@@ -6,7 +6,7 @@ import { renderHook, act } from '@testing-library/react-native';
|
|
|
6
6
|
import { useOnboardingStore, useOnboarding } from '../OnboardingStore';
|
|
7
7
|
|
|
8
8
|
// Mock storage repository
|
|
9
|
-
jest.mock('@
|
|
9
|
+
jest.mock('@storage', () => ({
|
|
10
10
|
storageRepository: {
|
|
11
11
|
getString: jest.fn(),
|
|
12
12
|
setString: jest.fn(),
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Single Responsibility: Save and update user answers
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { storageRepository } from "@
|
|
6
|
+
import { storageRepository } from "@storage";
|
|
7
7
|
import type { OnboardingUserData } from "../../../domain/entities/OnboardingUserData";
|
|
8
8
|
import type { OnboardingStoreState } from "../OnboardingStoreState";
|
|
9
9
|
import { USER_DATA_STORAGE_KEY, handleError, logSuccess } from "./storageHelpers";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Single Responsibility: Common storage operations and error handling
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { storageRepository, unwrap } from "@
|
|
6
|
+
import { storageRepository, unwrap } from "@storage";
|
|
7
7
|
import type { OnboardingUserData } from "../../../domain/entities/OnboardingUserData";
|
|
8
8
|
|
|
9
9
|
export const DEFAULT_STORAGE_KEY = "@onboarding:completed";
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Source Directory
|
|
2
|
+
|
|
3
|
+
Main source code for react-native-storage package following Domain-Driven Design principles.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Complete implementation of storage and caching solution with Clean Architecture. Located at `src/`.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
Clean Architecture with DDD principles:
|
|
12
|
+
- `application/` - Application layer (ports/interfaces)
|
|
13
|
+
- `cache/` - In-memory caching module
|
|
14
|
+
- `domain/` - Domain layer (business logic)
|
|
15
|
+
- `infrastructure/` - Infrastructure layer (implementations)
|
|
16
|
+
- `presentation/` - Presentation layer (React hooks)
|
|
17
|
+
- `types/` - Shared TypeScript types
|
|
18
|
+
|
|
19
|
+
## Strategies
|
|
20
|
+
|
|
21
|
+
### Layer Organization
|
|
22
|
+
- Use application layer for interfaces and ports
|
|
23
|
+
- Use domain layer for business logic and entities
|
|
24
|
+
- Use infrastructure layer for external service implementations
|
|
25
|
+
- Use presentation layer for React integration
|
|
26
|
+
- Use cache module for in-memory caching
|
|
27
|
+
|
|
28
|
+
### Dependency Flow
|
|
29
|
+
- Presentation depends on domain
|
|
30
|
+
- Domain depends on nothing (core)
|
|
31
|
+
- Infrastructure implements domain interfaces
|
|
32
|
+
- Application defines contracts between layers
|
|
33
|
+
|
|
34
|
+
### Module Separation
|
|
35
|
+
- Keep cache module independent and self-contained
|
|
36
|
+
- Enable cache usage without storage dependency
|
|
37
|
+
- Support standalone cache operations
|
|
38
|
+
- Maintain clean module boundaries
|
|
39
|
+
|
|
40
|
+
### Type Safety
|
|
41
|
+
- Use TypeScript for all modules
|
|
42
|
+
- Provide generic type parameters
|
|
43
|
+
- Enable type inference
|
|
44
|
+
- Support branded types for storage keys
|
|
45
|
+
|
|
46
|
+
## Restrictions
|
|
47
|
+
|
|
48
|
+
### Layer Dependencies
|
|
49
|
+
- DO NOT import infrastructure in domain layer
|
|
50
|
+
- DO NOT import presentation in domain layer
|
|
51
|
+
- DO NOT import application in infrastructure
|
|
52
|
+
- DO NOT create circular dependencies
|
|
53
|
+
|
|
54
|
+
### Module Boundaries
|
|
55
|
+
- DO NOT mix concerns across layers
|
|
56
|
+
- DO NOT bypass layer boundaries
|
|
57
|
+
- DO NOT expose implementation details
|
|
58
|
+
- DO NOT create tight coupling between modules
|
|
59
|
+
|
|
60
|
+
### Code Organization
|
|
61
|
+
- DO NOT place business logic in presentation
|
|
62
|
+
- DO NOT place UI code in domain
|
|
63
|
+
- DO NOT place external dependencies in domain
|
|
64
|
+
- DO NOT create god objects
|
|
65
|
+
|
|
66
|
+
### Architecture Compliance
|
|
67
|
+
- DO NOT violate dependency inversion principle
|
|
68
|
+
- DO NOT ignore layer responsibilities
|
|
69
|
+
- DO NOT create ambiguous module placement
|
|
70
|
+
- DO NOT mix abstraction levels
|
|
71
|
+
|
|
72
|
+
## Rules
|
|
73
|
+
|
|
74
|
+
### Application Layer
|
|
75
|
+
- MUST define IStorageRepository interface
|
|
76
|
+
- MUST provide ports for dependency inversion
|
|
77
|
+
- MUST not contain implementation details
|
|
78
|
+
- MUST be framework-agnostic
|
|
79
|
+
- MUST enable constructor injection
|
|
80
|
+
|
|
81
|
+
### Cache Module
|
|
82
|
+
- MUST provide domain entities (CacheManager, CachedValue)
|
|
83
|
+
- MUST provide infrastructure implementation (TTLCache)
|
|
84
|
+
- MUST provide presentation hooks (useCache, useCachedValue)
|
|
85
|
+
- MUST support multiple eviction strategies (LRU, LFU, FIFO, TTL)
|
|
86
|
+
- MUST be independent and self-contained
|
|
87
|
+
|
|
88
|
+
### Domain Layer
|
|
89
|
+
- MUST contain core business logic
|
|
90
|
+
- MUST define value objects (StorageKey)
|
|
91
|
+
- MUST define entities (CachedValue, Result)
|
|
92
|
+
- MUST provide factory functions (createStore)
|
|
93
|
+
- MUST define error types (StorageError hierarchy)
|
|
94
|
+
- MUST not depend on external frameworks
|
|
95
|
+
|
|
96
|
+
### Infrastructure Layer
|
|
97
|
+
- MUST implement IStorageRepository interface
|
|
98
|
+
- MUST provide StorageService adapter for Zustand
|
|
99
|
+
- MUST handle Result pattern for error handling
|
|
100
|
+
- MUST support AsyncStorage as primary backend
|
|
101
|
+
- MUST enable custom storage backends
|
|
102
|
+
|
|
103
|
+
### Presentation Layer
|
|
104
|
+
- MUST provide React hooks for storage
|
|
105
|
+
- MUST provide React hooks for cache
|
|
106
|
+
- MUST enable reactive state management
|
|
107
|
+
- MUST handle loading and error states
|
|
108
|
+
- MUST follow React hooks rules
|
|
109
|
+
|
|
110
|
+
### Types Module
|
|
111
|
+
- MUST provide shared TypeScript types
|
|
112
|
+
- MUST define StorageResult type
|
|
113
|
+
- MUST define DynamicStorageKey type
|
|
114
|
+
- MUST enable type-safe operations
|
|
115
|
+
- MUST be imported by all layers
|
|
116
|
+
|
|
117
|
+
### Export Structure
|
|
118
|
+
- MUST export from index.ts at root level
|
|
119
|
+
- MUST organize exports by module
|
|
120
|
+
- MUST provide TypeScript types
|
|
121
|
+
- MUST maintain backward compatibility
|
|
122
|
+
- MUST not export internal utilities
|
|
123
|
+
|
|
124
|
+
### File Organization
|
|
125
|
+
- MUST place files in appropriate layer
|
|
126
|
+
- MUST follow feature-based organization within layers
|
|
127
|
+
- MUST use descriptive file names
|
|
128
|
+
- MUST maintain consistent structure
|
|
129
|
+
- MUST enable easy navigation
|
|
130
|
+
|
|
131
|
+
### Testing Structure
|
|
132
|
+
- MUST place tests in __tests__ directories
|
|
133
|
+
- MUST mirror source structure
|
|
134
|
+
- MUST provide comprehensive coverage
|
|
135
|
+
- MUST enable isolated testing
|
|
136
|
+
- MUST not depend on external services
|
|
137
|
+
|
|
138
|
+
### Type Safety Requirements
|
|
139
|
+
- MUST use TypeScript for all files
|
|
140
|
+
- MUST provide generic type parameters
|
|
141
|
+
- MUST enable type inference
|
|
142
|
+
- MUST not use `any` type
|
|
143
|
+
- MUST enforce strict type checking
|
|
144
|
+
|
|
145
|
+
### Error Handling
|
|
146
|
+
- MUST use Result pattern for operations
|
|
147
|
+
- MUST preserve error context
|
|
148
|
+
- MUST provide hierarchical error types
|
|
149
|
+
- MUST not throw exceptions across layers
|
|
150
|
+
- MUST handle errors gracefully
|
|
151
|
+
|
|
152
|
+
### Documentation
|
|
153
|
+
- MUST provide README for each layer
|
|
154
|
+
- MUST document public APIs
|
|
155
|
+
- MUST specify file locations
|
|
156
|
+
- MUST explain architecture decisions
|
|
157
|
+
- MUST not include code examples in README files
|
|
158
|
+
|
|
159
|
+
### Naming Conventions
|
|
160
|
+
- MUST use camelCase for files and variables
|
|
161
|
+
- MUST use PascalCase for types and interfaces
|
|
162
|
+
- MUST use descriptive names
|
|
163
|
+
- MUST follow React hooks naming (use prefix)
|
|
164
|
+
- MUST maintain consistency across modules
|
|
165
|
+
|
|
166
|
+
### Performance Considerations
|
|
167
|
+
- MUST optimize for read-heavy or write-heavy patterns
|
|
168
|
+
- MUST minimize unnecessary re-renders
|
|
169
|
+
- MUST use memoization where appropriate
|
|
170
|
+
- MUST enable lazy loading
|
|
171
|
+
- MUST consider bundle size impact
|
|
172
|
+
|
|
173
|
+
### Security Requirements
|
|
174
|
+
- MUST not expose sensitive data in logs
|
|
175
|
+
- MUST use SecureStore for sensitive data
|
|
176
|
+
- MUST handle encryption for secure storage
|
|
177
|
+
- MUST validate input data
|
|
178
|
+
- MUST prevent injection attacks
|
|
179
|
+
|
|
180
|
+
### Best Practices Compliance
|
|
181
|
+
- MUST follow Single Responsibility Principle
|
|
182
|
+
- MUST follow Open/Closed Principle
|
|
183
|
+
- MUST follow Liskov Substitution Principle
|
|
184
|
+
- MUST follow Interface Segregation Principle
|
|
185
|
+
- MUST follow Dependency Inversion Principle
|