new api service and logic implemented

This commit is contained in:
2025-01-23 22:27:25 +03:00
parent d91ecda9df
commit 32022ca521
245 changed files with 28004 additions and 0 deletions

View File

@@ -0,0 +1,203 @@
# System Architecture
## Core Services
### Top-Level Services
1. **AuthServiceApi**
- User authentication and authorization
- Token management
- Permission handling
2. **EventServiceApi**
- Event processing and management
- Event routing and handling
- Event validation
3. **ValidationServiceApi**
- Input validation
- Data verification
- Schema validation
## System Components
### AllConfigs
Configuration management for various system components.
| Category | Context | Dependencies |
|----------|----------|--------------|
| Email | configs, email_send_model | - |
| NoSqlDatabase | configs | - |
| Redis | configs | - |
| SqlDatabase | configs | - |
| Token | configs | - |
### Schemas
- SQL Alchemy schema definitions
- Data models and relationships
- Database structure definitions
### ApiLibrary
| Category | Description |
|----------|-------------|
| common | Error line number tracking |
| date_time_actions | DateTime handling functions |
| extensions | Password module and utilities |
### ApiServices
| Category | Context | Dependencies |
|----------|----------|--------------|
| Login | UserLoginModule | ApiLibrary, Schemas, ErrorHandlers, ApiValidations, ApiServices |
| Token | TokenService | Services, Schemas, ApiLibrary, ErrorHandlers, AllConfigs, ApiValidations |
### Services
| Category | Dependencies |
|----------|--------------|
| Email | ApiLibrary, Schemas, ErrorHandlers, ApiValidations, ApiServices |
| MongoDb | - |
| PostgresDb | - |
| Redis | - |
### ErrorHandlers
- ErrorHandlers: General error handling
- Exceptions: Custom exception definitions
### LanguageModels
- Database: Database-related language models
- Errors: Error message translations
### ApiValidations
- Custom: Custom validation rules
- Request: Request validation logic
## Testing Framework
### Test Categories
- AlchemyResponse pagination testing
- Redis function testing
- MongoDB function testing
- Validation testing
- Header testing
- Auth function testing
- Language testing
- Property definition testing
- SmartQuery testing
### Error Categories
- AlchemyError
- ApiError
- RedisError
- MongoError
- EmailError
- Validation[Pydantic]
## Alchemy Implementation Phases
1. **BaseAlchemyNeed**
- Session management
- Core functionality
2. **PlainModel**
- Basic model implementation
3. **FilteredModel**
- Filter functionality
4. **PaginatedModel**
- Pagination attributes
- Filter integration
5. **LanguageModel**
- Function retrieval
- Header management
6. **ResponseModel**
- Plain AlchemyClass
- Dictionary conversion
- Multiple response handling
## System Layers
1. **DependenciesLayer**
- External dependencies
- System requirements
2. **ApplicationLayer**
- Core application logic
- Business rules
3. **ServiceLayer**
- Service implementations
- API endpoints
4. **TestLayer**
- Test suites
- Test utilities
5. **DevLayer**
- Development tools
- Debug utilities
6. **RootLayer**
- Main directory
- Configuration files
- Documentation
## TODO Items
1. **Event Directory Structure**
- Move to ApiEvents
- Docker file integration
- Import organization
2. **MethodToEvent Renewal**
- Update implementation
- Improve flexibility
3. **Endpoint Configuration**
- Remove unnecessary fields
- Streamline configuration
4. **Middleware Organization**
- Consolidate into /TokenEventMiddleware/
- Standardize naming
5. **Code Cleanup**
- Remove ActionsSchemaFactory
- Remove ActionsSchema
- Move endpoint_wrapper to Middleware.wrappers
6. **Function Organization**
- Support sync/async functions
- Improve API function organization
7. **Directory Structure**
- Consolidate AllConfigs, ApiLibrary, ErrorHandlers
- Move to RootLayer
8. **Configuration Management**
- Update RouteFactoryConfig
- Update EndpointFactoryConfig
- Implement event validation interface
9. **Language Model**
- Review Schemas.__language_model__
- Update implementation
10. **Service Container**
- Review ApiServices
- Plan container migration
11. **Language Defaults**
- Add to config
- Implement ["tr", "en"] as default
## Notes
- Redis implementation needs RedisRow class
- Event validation needs database integration
- Consider containerization for ApiServices
- Review language model implementation
- Test coverage needs improvement

135
docs/events/ReadMe.md Normal file
View File

@@ -0,0 +1,135 @@
# System Architecture Documentation
## Core Components
### 1. ClusterToMethod (Router)
API router that groups related endpoints into logical clusters.
**Key Components:**
- `TAGS`: List of router categorization tags
- `PREFIX`: Base URL prefix for all contained endpoints
- `PAGEINFO`: Page metadata and UI information
- `ENDPOINTS`: Collection of MethodEvent instances
- `SUBCATEGORY`: Nested ClusterToMethod instances for hierarchical routing
### 2. MethodToEvent (Endpoint Handler)
Handles individual API endpoints and their event mappings.
**Key Components:**
- `EVENTS`: Collection of Event instances
- `HEADER_LANGUAGE_MODELS`: Header localization
- `ERROR_LANGUAGE_MODELS`: Error message localization
- Endpoint metadata (URL, method, summary, description)
- Endpoint callable with request validation
### 3. Event (Business Logic)
Represents individual business operations with validation.
**Core Features:**
- Unique `KEY_` identifier
- Request/Response validation using PydanticModel
- Callable business logic function
- Language model integration
## Data Flow & Storage
### Redis Key Structure
```
CLUSTER_FUNCTION_CODES:{ClusterToMethod}
└── {PageInfo, [FunctionCodes]}
METHOD_FUNCTION_CODES:{ClusterToMethod}:MethodEvent:Endpoint
└── [FunctionCodes]
LANGUAGE_MODELS:*
└── Localization data
PAGE_MAPPER:{Type}:{BuildingID}:{UserID}
└── PageInfo
MENU_MAPPER:{Type}:{BuildingID}:{UserID}
└── PageInfo
```
### Application Initialization Flow
1. **Pages Iteration**
- Saves router/endpoint mappings
- Caches menu structure
2. **Events Iteration**
- Stores endpoint information
- Caches validation schemas
3. **Web Statics**
- Caches localization data
- Builds UI components
### Request Flow
```
Request → Router(ClusterToMethod) → Endpoint(MethodEvent) → Event Handler
Validation
Business Logic
```
## Core Services
### 1. ValidationService
- Model validation handling
- Schema caching
- Language-specific validation
- Redis-first validation lookup
### 2. EventService
- Event routing management
- Function code mapping
- User-specific event access
- Login state management
### 3. AuthService
- User authentication
- Event access control
- User preferences (timezone, language)
- Token management
## Design Patterns
### 1. Multi-layer Validation
- Language model validation
- Function code validation
- User access validation
- Request/Response schema validation
### 2. Hierarchical Routing
- ClusterToMethod → MethodEvent → Event
- Nested routing via SUBCATEGORY
- URL prefix inheritance
### 3. Internationalization
- Comprehensive language support
- Cached translations
- Header and error localization
- Per-user language preferences
## Cache Layer
### Redis Categories
```
RedisCategoryKeys:
├── LANGUAGE_MODELS
├── VALIDATION_USER
├── CLUSTER_FUNCTION_CODES
├── METHOD_FUNCTION_CODES
├── MENU_FIRST_LAYER
├── PAGE_MAPPER
├── MENU_MAPPER
├── AUTH (Authorization)
├── OCC (Occupant)
└── EMP (Employee)
```
### Cache Invalidation
- On login: User-specific caches
- On language change: Localization caches
- On permission change: Access control caches

View File

@@ -0,0 +1,55 @@
# Improvements Documentation
This directory contains documentation and example implementations for various system improvements.
## Directory Structure
```
improvements/
├── detailed_improvement_plan.md # Overall improvement plan
├── language_service/ # Language service implementation
│ ├── backend/
│ │ ├── language_service.py # Basic language service
│ │ └── zod_messages.py # Zod validation messages
│ └── frontend/
│ └── languageService.ts # Frontend language service
└── validation_service/ # Validation service implementation
├── backend/
│ └── schema_converter.py # Pydantic to Zod converter
└── frontend/
└── dynamicSchema.ts # Dynamic Zod schema builder
```
## Components
### Language Service
The language service provides internationalization support with:
- Backend API for serving translations
- Frontend service for managing translations
- Integration with Zod for validation messages
### Validation Service
The validation service provides dynamic form validation with:
- Automatic conversion of Pydantic models to Zod schemas
- Frontend builder for dynamic schema creation
- Integration with language service for messages
## Implementation Status
These are example implementations that demonstrate the proposed improvements. To implement in the actual system:
1. Create appropriate service directories
2. Copy and adapt the code
3. Add tests
4. Update dependencies
5. Integrate with existing systems
## Next Steps
1. Review the implementations
2. Decide on integration approach
3. Create implementation tickets
4. Plan phased rollout
5. Add monitoring and metrics
For detailed implementation plans and timelines, see [detailed_improvement_plan.md](./detailed_improvement_plan.md).

View File

@@ -0,0 +1,311 @@
# Detailed Improvement Plan
## 1. Infrastructure & Deployment
### Service Isolation and Containerization
- **Microservices Architecture**
```
/services
├── auth-service/
│ ├── Dockerfile
│ └── docker-compose.yml
├── event-service/
│ ├── Dockerfile
│ └── docker-compose.yml
└── validation-service/
├── Dockerfile
└── docker-compose.yml
```
- **Service Discovery**
- Implement Consul for service registry
- Add health check endpoints
- Create service mesh with Istio
### API Gateway Implementation
```yaml
# api-gateway.yml
services:
gateway:
routes:
- id: auth-service
uri: lb://auth-service
predicates:
- Path=/api/auth/**
filters:
- RateLimit=100,1s
- CircuitBreaker=3,10s
```
### Monitoring Stack
- **Distributed Tracing**
```python
from opentelemetry import trace
from opentelemetry.exporter import jaeger
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("operation") as span:
span.set_attribute("attribute", value)
```
- **Metrics Collection**
- Prometheus for metrics
- Grafana for visualization
- Custom dashboards for each service
### Configuration Management
```python
# config_service.py
class ConfigService:
def __init__(self):
self.consul_client = Consul()
def get_config(self, service_name: str) -> Dict:
return self.consul_client.kv.get(f"config/{service_name}")
def update_config(self, service_name: str, config: Dict):
self.consul_client.kv.put(f"config/{service_name}", config)
```
## 2. Performance & Scaling
### Enhanced Caching Strategy
```python
# redis_cache.py
class RedisCache:
def __init__(self):
self.client = Redis(cluster_mode=True)
async def get_or_set(self, key: str, callback: Callable):
if value := await self.client.get(key):
return value
value = await callback()
await self.client.set(key, value, ex=3600)
return value
```
### Database Optimization
```sql
-- Sharding Example
CREATE TABLE users_shard_1 PARTITION OF users
FOR VALUES WITH (modulus 3, remainder 0);
CREATE TABLE users_shard_2 PARTITION OF users
FOR VALUES WITH (modulus 3, remainder 1);
```
### Event System Enhancement
```python
# event_publisher.py
class EventPublisher:
def __init__(self):
self.kafka_producer = KafkaProducer()
async def publish(self, topic: str, event: Dict):
await self.kafka_producer.send(
topic,
value=event,
headers=[("version", "1.0")]
)
```
### Background Processing
```python
# job_processor.py
class JobProcessor:
def __init__(self):
self.celery = Celery()
self.connection_pool = ConnectionPool(max_size=100)
@celery.task
async def process_job(self, job_data: Dict):
async with self.connection_pool.acquire() as conn:
await conn.execute(job_data)
```
## 3. Security & Reliability
### API Security Enhancement
```python
# security.py
class SecurityMiddleware:
def __init__(self):
self.rate_limiter = RateLimiter()
self.key_rotator = KeyRotator()
async def process_request(self, request: Request):
await self.rate_limiter.check(request.client_ip)
await self.key_rotator.validate(request.api_key)
```
### Error Handling System
```python
# error_handler.py
class ErrorHandler:
def __init__(self):
self.sentry_client = Sentry()
self.circuit_breaker = CircuitBreaker()
async def handle_error(self, error: Exception):
await self.sentry_client.capture_exception(error)
await self.circuit_breaker.record_error()
```
### Testing Framework
```python
# integration_tests.py
class IntegrationTests:
async def setup(self):
self.containers = await TestContainers.start([
"postgres", "redis", "kafka"
])
async def test_end_to_end(self):
await self.setup()
# Test complete user journey
await self.cleanup()
```
### Audit System
```python
# audit.py
class AuditLogger:
def __init__(self):
self.elastic = Elasticsearch()
async def log_action(
self,
user_id: str,
action: str,
resource: str,
changes: Dict
):
await self.elastic.index({
"user_id": user_id,
"action": action,
"resource": resource,
"changes": changes,
"timestamp": datetime.utcnow()
})
```
## 4. Development Experience
### Domain-Driven Design
```
/src
├── domain/
│ ├── entities/
│ ├── value_objects/
│ └── aggregates/
├── application/
│ ├── commands/
│ └── queries/
└── infrastructure/
├── repositories/
└── services/
```
### API Documentation
```python
# main.py
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
app = FastAPI()
def custom_openapi():
return get_openapi(
title="WAG Management API",
version="4.0.0",
description="Complete API documentation",
routes=app.routes
)
app.openapi = custom_openapi
```
### Translation Management
```python
# i18n.py
class TranslationService:
def __init__(self):
self.translations = {}
self.fallback_chain = ["tr", "en"]
async def get_translation(
self,
key: str,
lang: str,
fallback: bool = True
) -> str:
if translation := self.translations.get(f"{lang}.{key}"):
return translation
if fallback:
for lang in self.fallback_chain:
if translation := self.translations.get(f"{lang}.{key}"):
return translation
return key
```
### Developer Tools
```python
# debug_toolkit.py
class DebugToolkit:
def __init__(self):
self.profiler = cProfile.Profile()
self.debugger = pdb.Pdb()
def profile_function(self, func: Callable):
def wrapper(*args, **kwargs):
self.profiler.enable()
result = func(*args, **kwargs)
self.profiler.disable()
return result
return wrapper
```
## Implementation Priority
1. **Phase 1 - Foundation** (1-2 months)
- Service containerization
- Basic monitoring
- API gateway setup
- Security enhancements
2. **Phase 2 - Scaling** (2-3 months)
- Caching implementation
- Database optimization
- Event system upgrade
- Background jobs
3. **Phase 3 - Reliability** (1-2 months)
- Error handling
- Testing framework
- Audit system
- Performance monitoring
4. **Phase 4 - Developer Experience** (1-2 months)
- Documentation
- Development tools
- Translation system
- Code organization
## Success Metrics
- **Performance**
- Response time < 100ms for 95% of requests
- Cache hit rate > 80%
- Zero downtime deployments
- **Reliability**
- 99.99% uptime
- < 0.1% error rate
- < 1s failover time
- **Security**
- Zero critical vulnerabilities
- 100% audit log coverage
- < 1hr security incident response time
- **Development**
- 80% test coverage
- < 24hr PR review time
- < 1 day developer onboarding

View File

@@ -0,0 +1,6 @@
# Original content from ApiEvents/LanguageServiceApi/language_service.py
from typing import Dict, List, Optional
from fastapi import APIRouter, Header
from pydantic import BaseModel
# ... rest of the file content ...

View File

@@ -0,0 +1,7 @@
# Original content from ApiEvents/LanguageServiceApi/zod_messages.py
from typing import Dict
from fastapi import APIRouter, Header
from pydantic import BaseModel
from typing import Optional
# ... rest of the file content ...

View File

@@ -0,0 +1,4 @@
// Original content from frontend/src/services/languageService.ts
import axios from 'axios';
// ... rest of the file content ...

View File

@@ -0,0 +1,9 @@
# Original content from ApiEvents/ValidationServiceApi/schema_converter.py
from typing import Dict, Any, Type, get_type_hints, get_args, get_origin
from pydantic import BaseModel, Field, EmailStr
from enum import Enum
import inspect
from fastapi import APIRouter
from datetime import datetime
# ... rest of the file content ...

View File

@@ -0,0 +1,146 @@
from typing import Dict, Any, Type, Optional
from pydantic import BaseModel
from fastapi import APIRouter, Header
class ValidationMessages(BaseModel):
"""Messages for Zod validation"""
required: str
invalid_type: str
invalid_string: Dict[str, str] # email, url, etc
too_small: Dict[str, str] # string, array, number
too_big: Dict[str, str] # string, array, number
invalid_date: str
invalid_enum: str
custom: Dict[str, str]
class SchemaField(BaseModel):
"""Schema field definition"""
type: str
items: Optional[str] = None # For arrays
values: Optional[list] = None # For enums
validations: Optional[Dict[str, Any]] = None
class SchemaDefinition(BaseModel):
"""Complete schema definition"""
name: str
fields: Dict[str, SchemaField]
messages: ValidationMessages
class UnifiedSchemaService:
def __init__(self):
self.messages = {
"tr": ValidationMessages(
required="Bu alan zorunludur",
invalid_type="Geçersiz tip",
invalid_string={
"email": "Geçerli bir e-posta adresi giriniz",
"url": "Geçerli bir URL giriniz",
"uuid": "Geçerli bir UUID giriniz"
},
too_small={
"string": "{min} karakterden az olamaz",
"array": "En az {min} öğe gereklidir",
"number": "En az {min} olmalıdır"
},
too_big={
"string": "{max} karakterden fazla olamaz",
"array": "En fazla {max} öğe olabilir",
"number": "En fazla {max} olabilir"
},
invalid_date="Geçerli bir tarih giriniz",
invalid_enum="Geçersiz seçim",
custom={
"password_match": "Şifreler eşleşmiyor",
"strong_password": "Şifre güçlü değil"
}
),
"en": ValidationMessages(
required="This field is required",
invalid_type="Invalid type",
invalid_string={
"email": "Please enter a valid email",
"url": "Please enter a valid URL",
"uuid": "Please enter a valid UUID"
},
too_small={
"string": "Must be at least {min} characters",
"array": "Must contain at least {min} items",
"number": "Must be at least {min}"
},
too_big={
"string": "Must be at most {max} characters",
"array": "Must contain at most {max} items",
"number": "Must be at most {max}"
},
invalid_date="Please enter a valid date",
invalid_enum="Invalid selection",
custom={
"password_match": "Passwords do not match",
"strong_password": "Password is not strong enough"
}
)
}
def get_schema_with_messages(
self,
model: Type[BaseModel],
lang: str = "tr"
) -> SchemaDefinition:
"""Get schema definition with validation messages"""
fields: Dict[str, SchemaField] = {}
for field_name, field in model.__fields__.items():
field_info = SchemaField(
type=self._get_field_type(field.outer_type_),
items=self._get_items_type(field.outer_type_),
values=self._get_enum_values(field.outer_type_),
validations=self._get_validations(field)
)
fields[field_name] = field_info
return SchemaDefinition(
name=model.__name__,
fields=fields,
messages=self.messages[lang]
)
def _get_field_type(self, type_: Type) -> str:
# Implementation similar to SchemaConverter
pass
def _get_items_type(self, type_: Type) -> Optional[str]:
# Implementation similar to SchemaConverter
pass
def _get_enum_values(self, type_: Type) -> Optional[list]:
# Implementation similar to SchemaConverter
pass
def _get_validations(self, field) -> Optional[Dict[str, Any]]:
# Implementation similar to SchemaConverter
pass
router = APIRouter(prefix="/api/schema", tags=["Schema"])
schema_service = UnifiedSchemaService()
@router.get("/model/{model_name}")
async def get_model_schema(
model_name: str,
accept_language: Optional[str] = Header(default="tr")
) -> SchemaDefinition:
"""Get model schema with validation messages"""
# You'd need to implement model lookup
models = {
"User": UserModel,
"Product": ProductModel,
# Add your models here
}
if model_name not in models:
raise ValueError(f"Model {model_name} not found")
lang = accept_language.split(",")[0][:2]
return schema_service.get_schema_with_messages(
models[model_name],
lang if lang in ["tr", "en"] else "tr"
)

View File

@@ -0,0 +1,6 @@
// Original content from frontend/src/validation/dynamicSchema.ts
import { z } from 'zod';
import axios from 'axios';
import { zodMessages } from './zodMessages';
// ... rest of the file content ...

View File

@@ -0,0 +1,219 @@
import { z } from 'zod';
import axios from 'axios';
interface ValidationMessages {
required: string;
invalid_type: string;
invalid_string: Record<string, string>;
too_small: Record<string, string>;
too_big: Record<string, string>;
invalid_date: string;
invalid_enum: string;
custom: Record<string, string>;
}
interface SchemaField {
type: string;
items?: string;
values?: any[];
validations?: Record<string, any>;
}
interface SchemaDefinition {
name: string;
fields: Record<string, SchemaField>;
messages: ValidationMessages;
}
class UnifiedSchemaBuilder {
private static instance: UnifiedSchemaBuilder;
private schemaCache: Map<string, z.ZodSchema> = new Map();
private constructor() {}
static getInstance(): UnifiedSchemaBuilder {
if (!UnifiedSchemaBuilder.instance) {
UnifiedSchemaBuilder.instance = new UnifiedSchemaBuilder();
}
return UnifiedSchemaBuilder.instance;
}
async getSchema(modelName: string): Promise<z.ZodSchema> {
// Check cache first
if (this.schemaCache.has(modelName)) {
return this.schemaCache.get(modelName)!;
}
// Fetch schema definition with messages from backend
const response = await axios.get<SchemaDefinition>(
`/api/schema/model/${modelName}`,
{
headers: {
'Accept-Language': navigator.language || 'tr'
}
}
);
const schema = this.buildSchema(response.data);
this.schemaCache.set(modelName, schema);
return schema;
}
private buildSchema(definition: SchemaDefinition): z.ZodSchema {
const shape: Record<string, z.ZodTypeAny> = {};
for (const [fieldName, field] of Object.entries(definition.fields)) {
shape[fieldName] = this.buildField(field, definition.messages);
}
return z.object(shape);
}
private buildField(
field: SchemaField,
messages: ValidationMessages
): z.ZodTypeAny {
let zodField: z.ZodTypeAny;
switch (field.type) {
case 'string':
zodField = z.string({
required_error: messages.required,
invalid_type_error: messages.invalid_type
});
break;
case 'email':
zodField = z.string().email(messages.invalid_string.email);
break;
case 'number':
zodField = z.number({
required_error: messages.required,
invalid_type_error: messages.invalid_type
});
break;
case 'boolean':
zodField = z.boolean({
required_error: messages.required,
invalid_type_error: messages.invalid_type
});
break;
case 'date':
zodField = z.date({
required_error: messages.required,
invalid_type_error: messages.invalid_date
});
break;
case 'array':
zodField = z.array(
this.buildField({ type: field.items! }, messages)
);
break;
case 'enum':
zodField = z.enum(field.values as [string, ...string[]], {
required_error: messages.required,
invalid_type_error: messages.invalid_enum
});
break;
default:
zodField = z.any();
}
// Apply validations if any
if (field.validations) {
zodField = this.applyValidations(zodField, field.validations, messages);
}
return zodField;
}
private applyValidations(
field: z.ZodTypeAny,
validations: Record<string, any>,
messages: ValidationMessages
): z.ZodTypeAny {
let result = field;
if ('min_length' in validations) {
result = (result as z.ZodString).min(
validations.min_length,
messages.too_small.string.replace(
'{min}',
validations.min_length.toString()
)
);
}
if ('max_length' in validations) {
result = (result as z.ZodString).max(
validations.max_length,
messages.too_big.string.replace(
'{max}',
validations.max_length.toString()
)
);
}
if ('pattern' in validations) {
result = (result as z.ZodString).regex(
new RegExp(validations.pattern),
messages.custom[validations.pattern_message] || 'Invalid format'
);
}
if ('gt' in validations) {
result = (result as z.ZodNumber).gt(
validations.gt,
messages.too_small.number.replace(
'{min}',
(validations.gt + 1).toString()
)
);
}
if ('lt' in validations) {
result = (result as z.ZodNumber).lt(
validations.lt,
messages.too_big.number.replace(
'{max}',
(validations.lt - 1).toString()
)
);
}
return result;
}
}
// Export singleton instance
export const schemaBuilder = UnifiedSchemaBuilder.getInstance();
// Usage example:
/*
import { schemaBuilder } from './validation/unifiedSchemaBuilder';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
function UserForm() {
const [schema, setSchema] = useState<z.ZodSchema | null>(null);
useEffect(() => {
async function loadSchema() {
const userSchema = await schemaBuilder.getSchema('User');
setSchema(userSchema);
}
loadSchema();
}, []);
const form = useForm({
resolver: schema ? zodResolver(schema) : undefined
});
if (!schema) return <div>Loading...</div>;
return (
<form onSubmit={form.handleSubmit(data => console.log(data))}>
{/* Your form fields */}
</form>
);
}
*/

229
docs/method_event_system.md Normal file
View File

@@ -0,0 +1,229 @@
# MethodToEvent System Documentation
## Overview
The MethodToEvent system provides a unified way to manage API endpoints and frontend menu structure with built-in permission handling. It uses UUIDs for permission management and supports hierarchical menu structures.
## Core Components
### 1. MethodToEvent Base Class
Base class for defining event methods with API endpoints and frontend page configuration.
#### Class Variables
- `action_key`: Unique identifier for the action
- `event_type`: Type of event (e.g., 'query', 'command')
- `event_description`: Human-readable description
- `event_category`: Category for grouping
- `__event_keys__`: UUID to event name mapping
- `__event_validation__`: Validation rules
- `__endpoint_config__`: API endpoint configuration
- `__page_info__`: Frontend page configuration
#### Methods
##### Configure API Endpoints
```python
@classmethod
def register_endpoint(
cls,
event_uuid: str,
path: str,
method: str = "POST",
response_model: Optional[Type] = None,
**kwargs
) -> None
```
Registers an API endpoint for an event UUID.
##### Configure Router
```python
@classmethod
def configure_router(cls, prefix: str, tags: List[str]) -> None
```
Sets the router prefix and OpenAPI tags.
##### Configure Page
```python
@classmethod
def configure_page(
cls,
name: str,
title: Dict[str, str],
icon: str,
url: str,
component: Optional[str] = None,
parent: Optional[str] = None
) -> None
```
Configures frontend page information.
##### Get Page Info with Permissions
```python
@classmethod
def get_page_info_with_permissions(
cls,
user_permission_uuids: Set[str],
include_endpoints: bool = False
) -> Optional[Dict[str, Any]]
```
Returns page info if user has required permissions.
### 2. EventMethodRegistry
Singleton registry for managing all MethodToEvent classes and building menu structures.
#### Methods
##### Register Method Class
```python
@classmethod
def register_method_class(cls, method_class: Type[MethodToEvent]) -> None
```
Registers a MethodToEvent class in the registry.
##### Get All Menu Items
```python
@classmethod
def get_all_menu_items(
cls,
user_permission_uuids: Set[str],
include_endpoints: bool = False
) -> List[Dict[str, Any]]
```
Returns complete menu structure based on permissions.
##### Get Available Endpoints
```python
@classmethod
def get_available_endpoints(
cls,
user_permission_uuids: Set[str]
) -> Dict[str, Dict[str, Any]]
```
Returns all available API endpoints based on permissions.
## Example Usage
### 1. Define Event Methods
```python
class AccountEventMethods(MethodToEvent):
event_category = "account"
event_type = "query"
event_description = "Account management operations"
__event_keys__ = {
"uuid1": "view_account",
"uuid2": "edit_account"
}
# Configure API
configure_router("/api/account", ["Account"])
register_endpoint(
"uuid1",
"/view",
method="GET",
response_model=AccountResponse
)
# Configure frontend
configure_page(
name="AccountPage",
title={"tr": "Hesaplar", "en": "Accounts"},
icon="User",
url="/account"
)
class AccountDetailsEventMethods(MethodToEvent):
event_category = "account_details"
__event_keys__ = {
"uuid3": "view_details",
"uuid4": "edit_details"
}
configure_page(
name="AccountDetailsPage",
title={"tr": "Hesap Detayları", "en": "Account Details"},
icon="FileText",
url="/account/details",
parent="AccountPage" # Link to parent
)
```
### 2. Register and Use
```python
# Register classes
registry = EventMethodRegistry()
registry.register_method_class(AccountEventMethods)
registry.register_method_class(AccountDetailsEventMethods)
# Get menu structure
user_permissions = {"uuid1", "uuid2", "uuid3"}
menu_items = registry.get_all_menu_items(user_permissions, include_endpoints=True)
```
## Menu Structure Rules
1. **Parent-Child Visibility**
- Parent page must have permissions to be visible
- If parent is not visible, children are never shown
- If parent is visible, all children are shown
2. **Permission Checking**
- Based on UUID intersection
- Page is visible if user has any of its event UUIDs
- Endpoints only included if user has specific permission
3. **Menu Organization**
- Automatic tree structure based on parent field
- Sorted by name for consistency
- Optional endpoint information included
## Example Menu Structure
```python
[
{
"name": "AccountPage",
"title": {"tr": "Hesaplar", "en": "Accounts"},
"icon": "User",
"url": "/account",
"category": "account",
"type": "query",
"description": "Account management operations",
"available_endpoints": {
"uuid1": {"path": "/api/account/view", "method": "GET"},
"uuid2": {"path": "/api/account/edit", "method": "POST"}
},
"items": [
{
"name": "AccountDetailsPage",
"title": {"tr": "Hesap Detayları", "en": "Account Details"},
"icon": "FileText",
"url": "/account/details",
"parent": "AccountPage",
"available_endpoints": {
"uuid3": {"path": "/api/account/details/view", "method": "GET"}
}
}
]
}
]
```
## Best Practices
1. **UUID Management**
- Use consistent UUIDs across the system
- Document UUID meanings and permissions
- Group related permissions under same parent
2. **Page Organization**
- Use meaningful page names
- Provide translations for all titles
- Keep URL structure consistent with hierarchy
3. **API Endpoints**
- Use consistent router prefixes
- Group related endpoints under same router
- Use appropriate HTTP methods
4. **Permission Structure**
- Design permissions hierarchically
- Consider access patterns when grouping
- Document permission requirements

42
docs/notes/README.md Normal file
View File

@@ -0,0 +1,42 @@
# Development Notes
This directory contains development notes and documentation organized by topic and date.
## Structure
- Each note is stored as a markdown file
- Files are organized by topic in subdirectories
- File naming format: `YYYY-MM-DD_topic_name.md`
- Each note includes:
- Date
- Topic/Category
- Content
- Related files/components
- Action items (if any)
## How to Add Notes
1. Create a new markdown file with the date prefix
2. Use the standard note template
3. Place in appropriate topic directory
4. Link related notes if applicable
## Note Template
```markdown
# [Topic] - [Date]
## Overview
Brief description of the topic/issue
## Details
Main content of the note
## Related
- Links to related files/components
- References to other notes
## Action Items
- [ ] Todo items if any
- [ ] Next steps
```