7.7 KiB
7.7 KiB
Architecture Guide for AI Agents
This document provides comprehensive architecture information to help AI assistants understand and work with this codebase effectively.
System Architecture
High-Level Overview
┌─────────────┐ HTTP/REST ┌─────────────┐
│ Frontend │ ◄─────────────────► │ Backend │
│ (React) │ │ (NestJS) │
└─────────────┘ └──────┬──────┘
│
│ Grammy API
▼
┌─────────────┐
│ Telegram │
│ Bot │
└─────────────┘
│
│ PostgreSQL
▼
┌─────────────┐
│ Database │
└─────────────┘
Backend Architecture (NestJS)
Module Structure
Each feature follows NestJS module pattern:
- Module: Registers providers, imports dependencies
- Controller: Handles HTTP requests/responses
- Service: Contains business logic
- Entity: TypeORM database model
- DTO: Data Transfer Objects for validation
Key Modules
AppModule (Root Module)
- Imports all feature modules
- Configures global modules (Config, Database)
- Entry point:
main.ts
DatabaseModule
- Configures TypeORM with PostgreSQL
- Registers all entities
- Handles migrations
AuthModule
- JWT-based authentication
- Login/Register endpoints
- Token verification
- Guards for route protection
AdminsModule
- Admin user CRUD operations
- Role management (superadmin/admin)
- Pagination, sorting, filtering support
BotModule
- Telegram bot integration via Grammy
- Command handlers
- Message sending utilities
CommonModule
- Shared utilities
- Custom decorators (pagination, filtering, sorting)
- Base entities
- Interceptors
Request Flow
HTTP Request
↓
Controller (validates DTO)
↓
Guard (AuthGuard - checks JWT)
↓
Service (business logic)
↓
Repository/TypeORM (database)
↓
Response Interceptor (formats response)
↓
HTTP Response
Response Format
All API responses follow this structure:
{
statusCode: number;
message: string;
data: T; // Actual response data
}
Pagination
- Query params:
page(1-indexed),size(default: 25) - Response includes
totalCountanditems[]
Sorting
- Query params:
sortBy(field name),sortOrder(asc/desc) - Controller specifies allowed fields:
@SortingParams(['id', 'created_at'])
Filtering
- Query param:
filters[]array - Format:
field:rule:value(e.g.,username:like:john) - Rules:
eq,neq,gt,gte,lt,lte,like,nlike,in,nin,isnull,isnotnull,between - Controller specifies allowed fields:
@FilteringParams(['username', 'role'])
Frontend Architecture (React)
Structure
src/
├── api/ # API client setup, helpers, DTOs
├── components/ # Reusable UI components
├── guards/ # Route guards (auth, guest)
├── hooks/ # Custom hooks (auth, API queries)
├── layouts/ # Page layouts (auth, dashboard)
├── pages/ # Page components
├── providers/ # Context providers
├── routes/ # React Router configuration
└── theme/ # Mantine theme customization
API Integration
- Uses Axios for HTTP requests
- React Query for data fetching/caching
- Zod schemas for runtime validation
- Custom hooks generated via
createGetQueryHook,createPostMutationHook, etc.
State Management
- React Query for server state
- Zustand for client state (if needed)
- Context API for auth state
Routing
- React Router v6
- Protected routes via guards
- Lazy loading for code splitting
Database Schema
Entities
Admin
id: number (PK, auto-increment)username: string (255)email: string (255)image: string | nullis_active: boolean (default: true)role: enum ('superadmin' | 'admin')created_at: Dateupdated_at: Date- Relations:
OneToOnewithPassword
Password
id: number (PK)admin_id: number (FK)hash: string (bcrypt hash)- Relations:
OneToOnewithAdmin
Abstract Entity
All entities extend AbstractEntity:
id: Primary keycreated_at: Creation timestampupdated_at: Update timestamp
Telegram Bot Integration
Grammy Framework
- Bot instance created in
BotService - Commands registered in
onModuleInit() - Context types from Grammy for type safety
Common Patterns
// Register command
this.bot.command('command', this.handler.bind(this));
// Send message
await this.bot.api.sendMessage(chatId, message, options);
// Keyboard
const keyboard = new Keyboard().text('Button').row();
Environment Variables
Backend
PORT: Server port (default: 4000)JWT_SECRET: Secret for JWT signingTELEGRAM_BOT_TOKEN: Telegram bot tokenDB_HOST: Database hostDB_PORT: Database port (default: 5432)DB_USERNAME: Database usernameDB_PASSWORD: Database passwordDB_NAME: Database nameNODE_ENV: Environment (development/production)
Frontend
API_URL: Backend API URLPORT: Dev server port (default: 3000)
Development Workflow
Adding a New Feature
-
Backend:
- Create entity:
back/src/feature/entities/feature.entity.ts - Create DTOs:
back/src/feature/dto/*.dto.ts - Create service:
back/src/feature/feature.service.ts - Create controller:
back/src/feature/feature.controller.ts - Create module:
back/src/feature/feature.module.ts - Register in
AppModule - Generate migration:
pnpm migration:generate --name=create-feature
- Create entity:
-
Frontend:
- Create Zod schemas:
front/src/api/dtos/feature.ts - Create API hooks:
front/src/hooks/api/feature.ts - Create page component:
front/src/pages/feature/ - Add route:
front/src/routes/index.tsx
- Create Zod schemas:
Testing
- Backend: Jest (unit + e2e)
- Frontend: Vitest + React Testing Library
Common Code Patterns
Backend Controller Example
@Controller('resource')
export class ResourceController {
constructor(private readonly service: ResourceService) {}
@UseGuards(AuthGuard)
@Get()
findChunk(
@PaginationParams() pagination: IPagination,
@SortingParams(['id', 'name']) sorting: ISorting,
@FilteringParams(['name', 'status']) filtering: IFiltering,
) {
return this.service.findChunk(pagination, sorting, filtering);
}
}
Frontend Hook Example
const useGetResource = createPaginationQueryHook({
endpoint: '/api/resource',
dataSchema: resourceSchema,
rQueryParams: { queryKey: ['getResource'] },
});
Important Conventions
- Naming: Use descriptive names, follow camelCase for variables, PascalCase for classes
- Error Handling: Use NestJS exceptions, handle in interceptors
- Validation: Always validate input with DTOs and class-validator
- Type Safety: Use TypeScript strictly, avoid
any - Comments: Add JSDoc for public APIs
- Security: Never expose secrets, validate all inputs, use guards