Dökümanlar oluşturuldu
This commit is contained in:
448
doc/architecture-overview.md
Normal file
448
doc/architecture-overview.md
Normal file
@@ -0,0 +1,448 @@
|
||||
# Architecture Overview & Design Patterns
|
||||
|
||||
## System Architecture
|
||||
|
||||
### High-Level Architecture
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Browser │ │ Backend │ │ External │
|
||||
│ (Frontend) │ │ Services │ │ Services │
|
||||
│ │ │ │ │ │
|
||||
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
|
||||
│ │ React App │◄┼────┼──│ Express API │◄┼────┼──│ GLM-4.6 API │ │
|
||||
│ │ (Vite) │ │ │ │ (EPUB Gen) │ │ │ │ (Translation)│ │
|
||||
│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ ┌─────────────┐ │ │ │ │ ┌─────────────┐ │
|
||||
│ │ Supabase │◄┼────────────────────┼────┼──│ Supabase │ │
|
||||
│ │ Auth │ │ │ │ │ Database │ │
|
||||
│ └─────────────┘ │ │ │ └─────────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌─────────────┐ │ │ │ │
|
||||
│ │ Tesseract │ │ │ │ │
|
||||
│ │ OCR Engine │ │ │ │ │
|
||||
│ └─────────────┘ │ │ │ │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
### Component Architecture
|
||||
|
||||
#### Frontend Layer Architecture
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Presentation Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
|
||||
│ │ Header │ │ Stepper │ │ Main Content │ │
|
||||
│ │ Component │ │ Component │ │ (Router Outlet) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Application Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
|
||||
│ │ Router │ │ State │ │ Utility │ │
|
||||
│ │ Management │ │ Management │ │ Services │ │
|
||||
│ │(React Router)│ │ (Zustand) │ │ (API, Auth, Utils) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Data Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
|
||||
│ │ Browser │ │ Local │ │ External │ │
|
||||
│ │ Storage │ │ Storage │ │ APIs │ │
|
||||
│ │ (Blobs, URLs)│ │ (localStorage)│ │ (Supabase, Backend) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Design Patterns
|
||||
|
||||
### 1. State Management Pattern (Zustand)
|
||||
```javascript
|
||||
// Centralized Store Pattern
|
||||
const useAppStore = create((set, get) => ({
|
||||
// State
|
||||
uploadedImages: [],
|
||||
cropConfig: {},
|
||||
ocrText: '',
|
||||
|
||||
// Actions
|
||||
setUploadedImages: (images) => set({ uploadedImages: images }),
|
||||
resetFromStep: (step) => set((state) => {
|
||||
// Clean, atomic state updates
|
||||
const newState = {};
|
||||
// Reset logic based on step
|
||||
return newState;
|
||||
}),
|
||||
}));
|
||||
|
||||
// Usage in components
|
||||
const uploadedImages = useAppStore(state => state.uploadedImages);
|
||||
const setUploadedImages = useAppStore(state => state.setUploadedImages);
|
||||
```
|
||||
|
||||
### 2. Component Composition Pattern
|
||||
```javascript
|
||||
// Wizard Step Composition
|
||||
const WizardStep = ({ children, title, onNext, onPrev }) => {
|
||||
return (
|
||||
<Box>
|
||||
<Typography variant="h6">{title}</Typography>
|
||||
{children}
|
||||
<StepActions onNext={onNext} onPrev={onPrev} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
// Specific step implementation
|
||||
const UploadStep = () => {
|
||||
return (
|
||||
<WizardStep title="Upload Images">
|
||||
<DropzoneUpload />
|
||||
<ImagePreview />
|
||||
</WizardStep>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Service Layer Pattern
|
||||
```javascript
|
||||
// API Service Abstraction
|
||||
export const epubService = {
|
||||
generate: async (text, metadata) => {
|
||||
const response = await fetch(`${API_BASE_URL}/generate-epub`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ text, meta: metadata }),
|
||||
});
|
||||
return response.json();
|
||||
},
|
||||
};
|
||||
|
||||
// Authentication Service
|
||||
export const authService = {
|
||||
login: async (credentials) => {
|
||||
// Authentication logic
|
||||
},
|
||||
logout: async () => {
|
||||
// Logout logic
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 4. Observer Pattern (Authentication)
|
||||
```javascript
|
||||
// Supabase Auth Observer
|
||||
useEffect(() => {
|
||||
const { data: subscription } = supabaseClient.auth.onAuthStateChange(
|
||||
(event, session) => {
|
||||
if (event === 'SIGNED_IN') {
|
||||
// Handle sign in
|
||||
exchangeGoogleSession(session);
|
||||
} else if (event === 'SIGNED_OUT') {
|
||||
// Handle sign out
|
||||
clearAuthSession();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return () => subscription.subscription.unsubscribe();
|
||||
}, []);
|
||||
```
|
||||
|
||||
### 5. Strategy Pattern (OCR Processing)
|
||||
```javascript
|
||||
// OCR Language Strategy
|
||||
const ocrLanguageStrategy = {
|
||||
primary: 'tur',
|
||||
fallback: 'eng',
|
||||
detect: async (imageData) => {
|
||||
try {
|
||||
const result = await worker.recognize(imageData, 'tur');
|
||||
return result.data.text;
|
||||
} catch (error) {
|
||||
// Fallback to English
|
||||
return await worker.recognize(imageData, 'eng');
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Data Flow Architecture
|
||||
|
||||
### Unidirectional Data Flow
|
||||
```
|
||||
User Action → Component Event → State Update → Re-render → New UI
|
||||
|
||||
Example:
|
||||
1. User uploads files
|
||||
2. Dropzone component triggers onDrop
|
||||
3. useAppStore.setUploadedImages() called
|
||||
4. State updated in Zustand store
|
||||
5. Components subscribed to state re-render
|
||||
6. New UI shows uploaded images
|
||||
```
|
||||
|
||||
### Async Data Handling
|
||||
```javascript
|
||||
// Async Action Pattern
|
||||
const handleOcrProcessing = async () => {
|
||||
try {
|
||||
setTranslationStatus('processing');
|
||||
setTranslationProgress(0);
|
||||
|
||||
const processedText = await processOcrImages(
|
||||
croppedImages,
|
||||
(progress) => setTranslationProgress(progress)
|
||||
);
|
||||
|
||||
setOcrText(processedText);
|
||||
setTranslationStatus('completed');
|
||||
} catch (error) {
|
||||
setTranslationError(error.message);
|
||||
setTranslationStatus('error');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Component Architecture
|
||||
|
||||
### Hierarchy Structure
|
||||
```
|
||||
App (Root Component)
|
||||
├── Header (Authentication & Navigation)
|
||||
├── Stepper (Wizard Progress)
|
||||
├── Main Content (Router Outlet)
|
||||
│ ├── UploadStep
|
||||
│ ├── CropStep
|
||||
│ ├── BulkCropStep
|
||||
│ ├── OcrStep
|
||||
│ ├── TranslationStep
|
||||
│ ├── EpubStep
|
||||
│ ├── DownloadStep
|
||||
│ └── Auth Pages
|
||||
└── Error Handling (Snackbar)
|
||||
```
|
||||
|
||||
### Smart vs Dumb Components
|
||||
```javascript
|
||||
// Smart Component (Stateful)
|
||||
const OcrStep = () => {
|
||||
const { croppedImages, ocrText, setOcrText } = useAppStore();
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
|
||||
const handleOcrStart = async () => {
|
||||
setIsProcessing(true);
|
||||
// OCR processing logic
|
||||
setOcrText(resultText);
|
||||
setIsProcessing(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<OcrProcessing
|
||||
images={croppedImages}
|
||||
onStart={handleOcrStart}
|
||||
isProcessing={isProcessing}
|
||||
result={ocrText}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
// Dumb Component (Presentational)
|
||||
const OcrProcessing = ({ images, onStart, isProcessing, result }) => {
|
||||
return (
|
||||
<Box>
|
||||
<Button onClick={onStart} disabled={isProcessing}>
|
||||
Start OCR
|
||||
</Button>
|
||||
{isProcessing && <ProgressIndicator />}
|
||||
{result && <TextResult text={result} />}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### Authentication Flow
|
||||
```
|
||||
User Login Attempt
|
||||
↓
|
||||
Supabase Auth Service
|
||||
↓
|
||||
JWT Token Generation
|
||||
↓
|
||||
Token Storage (localStorage)
|
||||
↓
|
||||
Authenticated API Requests
|
||||
↓
|
||||
Token Validation & Refresh
|
||||
```
|
||||
|
||||
### Data Security Measures
|
||||
```javascript
|
||||
// Secure API Requests
|
||||
const secureApiCall = async (endpoint, data) => {
|
||||
const token = useAppStore.getState().authToken;
|
||||
|
||||
return await fetch(endpoint, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
};
|
||||
|
||||
// Data Sanitization
|
||||
const sanitizeInput = (input) => {
|
||||
return input
|
||||
.trim()
|
||||
.replace(/[<>]/g, '') // Remove potential HTML
|
||||
.substring(0, MAX_LENGTH); // Length limit
|
||||
};
|
||||
```
|
||||
|
||||
## Performance Architecture
|
||||
|
||||
### Lazy Loading Pattern
|
||||
```javascript
|
||||
// Code Splitting
|
||||
const UploadStep = lazy(() => import('./components/UploadStep'));
|
||||
const CropStep = lazy(() => import('./components/CropStep'));
|
||||
|
||||
// Asset Lazy Loading
|
||||
const loadTesseractAssets = async () => {
|
||||
const worker = await createWorker('tur', 1, {
|
||||
workerPath: '/tesseract/worker.min.js',
|
||||
corePath: '/tesseract/tesseract-core-simd-lstm.wasm.js',
|
||||
langPath: '/tesseract/',
|
||||
});
|
||||
return worker;
|
||||
};
|
||||
```
|
||||
|
||||
### Memory Management Pattern
|
||||
```javascript
|
||||
// Resource Cleanup
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
// Cleanup on unmount
|
||||
if (generatedEpub?.url) {
|
||||
URL.revokeObjectURL(generatedEpub.url);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Batch Processing Control
|
||||
const processImagesInBatches = async (images, batchSize = 5) => {
|
||||
for (let i = 0; i < images.length; i += batchSize) {
|
||||
const batch = images.slice(i, i + batchSize);
|
||||
await processBatch(batch);
|
||||
|
||||
// Allow UI to breathe
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Error Handling Architecture
|
||||
|
||||
### Error Boundary Pattern
|
||||
```javascript
|
||||
const ErrorBoundary = ({ children }) => {
|
||||
const [hasError, setHasError] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const handleError = (error, errorInfo) => {
|
||||
setHasError(true);
|
||||
setError(error);
|
||||
// Log error to service
|
||||
logError(error, errorInfo);
|
||||
};
|
||||
|
||||
if (hasError) {
|
||||
return <ErrorFallback error={error} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<ErrorBoundary onError={handleError}>
|
||||
{children}
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Global Error Handling
|
||||
```javascript
|
||||
// Global Error Store
|
||||
const useErrorStore = create((set) => ({
|
||||
error: null,
|
||||
setError: (message) => set({ error: message }),
|
||||
clearError: () => set({ error: null }),
|
||||
}));
|
||||
|
||||
// Error Display Component
|
||||
const ErrorDisplay = () => {
|
||||
const error = useAppStore(state => state.error);
|
||||
const clearError = useAppStore(state => state.clearError);
|
||||
|
||||
return (
|
||||
<Snackbar open={!!error} autoHideDuration={6000} onClose={clearError}>
|
||||
<Alert severity="error" onClose={clearError}>
|
||||
{error}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Testing Architecture
|
||||
|
||||
### Component Testing Strategy
|
||||
```
|
||||
Unit Tests:
|
||||
├── Utility functions (fileUtils, ocrUtils)
|
||||
├── Service layer functions
|
||||
└── Custom hooks
|
||||
|
||||
Integration Tests:
|
||||
├── Component interactions
|
||||
├── State management flow
|
||||
└── API service integration
|
||||
|
||||
E2E Tests:
|
||||
├── Complete user workflows
|
||||
├── Authentication flows
|
||||
└── File processing pipelines
|
||||
```
|
||||
|
||||
## Deployment Architecture
|
||||
|
||||
### Build Process
|
||||
```
|
||||
Development:
|
||||
├── Vite dev server
|
||||
├── Hot module replacement
|
||||
├── Source maps
|
||||
└── Fast refresh
|
||||
|
||||
Production:
|
||||
├── Code optimization
|
||||
├── Asset bundling
|
||||
├── Tree shaking
|
||||
└── Compression
|
||||
```
|
||||
|
||||
### Container Strategy
|
||||
```dockerfile
|
||||
# Multi-stage Docker build
|
||||
FROM node:18-alpine AS builder
|
||||
# Build stage
|
||||
|
||||
FROM nginx:alpine AS production
|
||||
# Production stage with static files
|
||||
```
|
||||
|
||||
This architecture provides a robust, scalable foundation for the imgPub application with clear separation of concerns, maintainable code structure, and optimized performance characteristics.
|
||||
Reference in New Issue
Block a user