Модульная структура
Приложение организовано по domain-driven принципам. Каждый модуль отвечает за отдельный аспект функциональности.
Архитектура: Два уровня API
Высокоуровневые API (Бизнес-логика)
├── /api/integrations -> Управление интеграциями + handlers
├── /api/auth -> Аутентификация (sign-up, sign-in, me)
├── /api/access-tokens -> Токены доступа
├── /api/testing -> Тестирование AI интеграций
└── /api/inngest -> URLs для Inngest dashboard
Низкоуровневые API (integ-core прокси)
├── /api/core/secrets -> Управление секретами (D1)
├── /api/core/cache -> Управление KV (группировка по интеграции)
├── /api/core/d1 -> Прямой доступ к D1 таблицам
└── /api/core/kv -> Прямой доступ к KV namespacesОбзор модулей
src/app/
├── core/ # Глобальные конфигурации
├── shared/ # Общие утилиты и модули
│ ├── constants/ # Глобальные константы
│ ├── decorators/ # Декораторы (Swagger, etc)
│ ├── dtos/ # Data Transfer Objects
│ ├── entities/ # Базовые сущности
│ ├── enums/ # Глобальные enum'ы
│ ├── guards/ # Общие guards
│ ├── interceptors/ # Общие interceptors
│ ├── interfaces/ # Общие интерфейсы
│ ├── modules/
│ │ ├── crypto/ # Шифрование (@Global)
│ │ ├── health/ # Health check endpoint
│ │ ├── logger/ # Логирование (@Global)
│ │ ├── mcp/ # Model Context Protocol
│ │ ├── swagger/ # Scalar конфигурация
│ │ └── types/ # Типы
│ └── utils/ # Утилиты
├── auth/ # JWT аутентификация
│ └── access-tokens/ # Токены доступа (M2M)
├── users/ # Управление пользователями
├── integrations/ # REST API для управления интеграциями
│ ├── handlers/ # Event handlers
│ └── prompts/ # Prompt templates
├── emulator/ # Эмулятор API запросов
│ ├── collections/ # Коллекции запросов
│ ├── saved-requests/# Сохраненные запросы
│ ├── proxy/ # Прокси для запросов
│ └── secrets/ # Секреты эмулятора
├── testing/ # Автоматизированное тестирование AI интеграций
│ └── chats/ # Тестовые чаты
└── third-parties/ # Внешние сервисы
├── inngest/ # Inngest event processing
└── integ-core/ # Cloudflare D1/KV/Cache/Secrets прокси
└── controllers/
├── cache.controller.ts # /api/core/cache
├── d1.controller.ts # /api/core/d1
├── kv.controller.ts # /api/core/kv
└── secrets.controller.ts # /api/core/secretsCore Module
Путь: src/app/core/
Глобальные конфигурации и bootstrapping приложения.
Структура
core/
├── configs/
│ └── typeorm.config.ts # TypeORM конфигурация
├── interceptors.ts # Глобальные interceptors
└── core.module.ts # МодульОтветственность
- Конфигурация TypeORM (подключение к PostgreSQL)
- Настройка глобальных interceptors
- Базовые настройки приложения
Shared Module
Путь: src/app/shared/
Переиспользуемые компоненты для всех модулей.
Структура
shared/
├── constants/ # Глобальные константы
│ └── index.ts
├── decorators/
│ └── swagger-auth.decorator.ts # Swagger декоратор
├── dtos/ # Data Transfer Objects
├── entities/
│ └── base.entity.ts # Базовая entity
├── enums/ # Глобальные enum'ы
│ └── index.ts
├── guards/
│ └── (index.ts) # Общие guards
├── interceptors/
│ └── (index.ts) # Общие interceptors
├── interfaces/
│ ├── base.interface.ts # IBase интерфейс
│ ├── d1.interface.ts # D1 Provider interface
│ └── kv.interface.ts # KV Provider interface
├── modules/
│ ├── crypto/ # Шифрование (@Global)
│ │ ├── crypto.module.ts
│ │ ├── services/
│ │ └── interfaces/
│ ├── health/ # Health check
│ │ ├── controllers/
│ │ └── health.module.ts
│ ├── logger/ # Логирование (@Global)
│ │ ├── services/
│ │ │ └── logger.service.ts
│ │ └── logger.module.ts
│ ├── mcp/ # Model Context Protocol
│ │ ├── controllers/
│ │ ├── dtos/
│ │ ├── interfaces/
│ │ ├── services/
│ │ ├── tools/
│ │ └── mcp.module.ts
│ ├── swagger/ # Swagger конфигурация
│ │ └── utils/
│ └── types/ # Типы
│ └── types.module.ts
└── utils/ # Утилиты
└── index.tsКлючевые компоненты
BaseEntity
Базовая сущность, от которой наследуются все остальные:
export abstract class BaseEntity implements IBase {
@PrimaryGeneratedColumn("uuid")
id: string;
@CreateDateColumn({ name: "created_at" })
createdAt: Date;
@UpdateDateColumn({ name: "updated_at" })
updatedAt: Date;
}Crypto Module (@Global)
Шифрование и хеширование данных. Используется для защиты credentials.
Logger Module (@Global)
Централизованный логирующий сервис для всего приложения.
Swagger Module
Централизованная конфигурация Swagger документации.
Auth Module
Путь: src/app/auth/
Аутентификация и авторизация пользователей.
Структура
auth/
├── controllers/
│ └── auth.controller.ts
├── dtos/
│ ├── login.dto.ts
│ └── register.dto.ts
├── guards/
│ └── jwt.guard.ts
├── middlewares/
│ ├── auth.middleware.ts
│ └── index.ts
├── services/
│ └── auth.service.ts
└── auth.module.tsОсновные эндпоинты
POST /api/auth/sign-up # Регистрация
POST /api/auth/sign-in # Вход
GET /api/auth/me # Профиль текущего пользователя
PATCH /api/auth/me # Обновление профиляJWT Strategy
- Пользователь отправляет credentials (email + password)
- Сервер проверяет и возвращает JWT токен
- Клиент отправляет токен в заголовке
Authorization: Bearer <token> - JWT Guard проверяет токен и добавляет пользователя в request
Users Module
Путь: src/app/users/
Управление пользователями приложения.
Структура
users/
├── entities/
│ └── user.entity.ts
├── interfaces/
│ └── user.interface.ts
├── services/
│ └── users.service.ts
└── users.module.tsUser Entity
@Entity("users")
export class UserEntity extends BaseEntity implements IUser {
@Column()
email: string;
@Column()
password: string;
@Column({ name: "verification_status" })
verificationStatus: string;
}Users Service
CRUD операции с пользователями:
findMany()- поиск множества пользователей с пагинациейfindOne()- поиск одного пользователяcreate()- создание пользователяupdate()- обновление пользователяdelete()- удаление пользователя
Access Tokens Module
Путь: src/app/auth/access-tokens/
Управление токенами доступа пользователей для аутентификации API запросов.
Структура
access-tokens/
├── controllers/
│ ├── access-token.controller.ts
│ └── index.ts
├── dtos/
│ ├── create-access-token.dto.ts
│ └── index.ts
├── entities/
│ ├── access-token.entity.ts
│ └── index.ts
├── services/
│ ├── access-token.service.ts
│ └── index.ts
└── access-tokens.module.tsОсновные эндпоинты
POST /api/access-tokens # Создать токен доступа
GET /api/access-tokens # Получить все токены пользователя
DELETE /api/access-tokens/:tokenId # Отозвать токенAccess Token Entity
@Entity("access_tokens")
export class AccessToken extends BaseEntity implements IAccessToken {
@Column()
userId: string;
@ManyToOne(() => UserEntity, { onDelete: "CASCADE" })
user: UserEntity;
@Column()
token: string;
@Column({ nullable: true })
name?: string;
@Column({ nullable: true })
expiresAt?: Date;
@Column({ nullable: true })
lastUsedAt?: Date;
}Access Token Service
Управление токенами:
create()- создание нового токена доступаfindByToken()- поиск по значению токенаfindAllByUserId()- получение всех токенов пользователяupdateLastUsed()- обновление времени последнего использованияrevoke()- отзыв токенаrevokeAll()- отзыв всех токенов пользователя
Integrations Module
Путь: src/app/integrations/
REST API для управления интеграциями и handlers. Для управления секретами используйте Secrets Module.
Структура
integrations/
├── controllers/
│ ├── integrations.controller.ts
│ └── index.ts
├── dtos/
│ ├── create-handler.dto.ts
│ ├── handler-response.dto.ts
│ └── index.ts
├── entities/
│ ├── integration.entity.ts
│ ├── integration-handler.entity.ts
│ └── index.ts
├── services/
│ ├── handlers.service.ts
│ ├── integrations.service.ts
│ └── index.ts
└── integrations.module.tsОсновные эндпоинты
GET /api/integrations # Список интеграций пользователя
POST /api/integrations # Создать интеграцию
GET /api/integrations/:id # Получить интеграцию
PATCH /api/integrations/:id # Обновить интеграцию
DELETE /api/integrations/:id # Удалить интеграцию
# Handlers API (прямые пути без вложенности)
GET /api/handlers?integrationId=xxx # Список handlers
GET /api/handlers/:id # Получить handler
POST /api/handlers # Создать handler (integrationId в body)
POST /api/handlers/:id/invoke # Вызвать handler
DELETE /api/handlers/:id # Удалить handlerEntities
IntegrationEntity
@Entity("integrations")
export class IntegrationEntity {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column()
name: string;
@Column({ name: "owner_id" })
ownerId: string;
@CreateDateColumn({ name: "created_at" })
createdAt: Date;
@UpdateDateColumn({ name: "updated_at" })
updatedAt: Date;
}IntegrationHandler
Определяет обработчики и их default arguments для интеграций.
Services
IntegrationsService
Управление интеграциями:
findByOwnerId()- интеграции пользователяfindById()- получить интеграцию по IDcreate()- создать новую интеграциюupdate()- обновить интеграциюdelete()- удалить интеграцию
HandlersService
Управление handlers (обработчики):
getHandlers()- получить все handlerscreate()- создать handlerfindOne()- получить handler по IDupdate()- обновить handlerdelete()- удалить handlerinvokeHandler()- вызвать handler с аргументами
Testing Module
Шлях: src/app/testing/
Автоматизоване тестування AI-агентів через LLM-діалоги з оцінкою якості. Один шлях виконання: TextDialogRunner (Tester LLM vs Agent LLM) → EvaluatorService (LLM-оцінка 0-100).
Архітектура
TestPersona (профіль дзвінка)
↓
TextDialogRunner (Tester LLM ↔ Agent LLM, до 10 реплік)
↓
EvaluatorService (LLM-оцінка: 5 критеріїв, 0-100 балів)
↓
TestResult (score, evaluation, transcript)- TestPersona — описує поведінку дзвінка (persona, goal, constraints, tags)
- TestRun — запуск набору персон проти агента інтеграції
- TestResult — результат кожної персони (score, evaluation, transcript)
- TestSchedule — cron-розклад автоматичних запусків
Структура
testing/
├── constants/
│ └── testing.constant.ts
├── controllers/
│ ├── test-personas.controller.ts # CRUD персон + AI-генерація
│ ├── test-runs.controller.ts # Запуски + Quick Test + Cancel + Delete
│ └── test-schedules.controller.ts # CRUD розкладів + Toggle
├── dtos/
│ ├── create-test-persona.dto.ts
│ ├── update-test-persona.dto.ts
│ ├── test-personas-query.dto.ts
│ ├── create-test-run.dto.ts
│ ├── test-runs-query.dto.ts
│ ├── create-test-schedule.dto.ts
│ ├── update-test-schedule.dto.ts
│ ├── test-schedules-query.dto.ts
│ ├── generate-personas.dto.ts
│ └── example-message.dto.ts
├── entities/
│ ├── test-persona.entity.ts # ManyToOne → Integration, User
│ ├── test-run.entity.ts # ManyToOne → Integration, User
│ ├── test-result.entity.ts # ManyToOne → TestRun, TestPersona
│ └── test-schedule.entity.ts # ManyToOne → Integration, User
├── enums/
│ └── test-status.enum.ts # TestStatusEnum, TestRunStatusEnum, TestRunTriggerEnum
├── interfaces/
│ ├── evaluate-params.interface.ts
│ ├── evaluation.interface.ts # IEvaluation, ICriteriaResult
│ ├── generate-suite.interface.ts
│ ├── runner.interface.ts # IRunnerContext, IRunnerResult
│ ├── test-execution-event.interface.ts
│ ├── test-persona.interface.ts # ITestPersona, IExampleMessage
│ ├── test-result.interface.ts
│ ├── test-run.interface.ts # ITestRun, ICreateTestRunParams, IExecuteRunParams
│ └── test-schedule.interface.ts
├── runners/
│ ├── base-runner.ts # buildTesterPrompt(persona)
│ └── text-dialog-runner.ts # run(agentPrompt, persona, context)
├── services/
│ ├── test-personas.service.ts # CRUD персон
│ ├── test-runs.service.ts # CRUD запусків + startRun + quickRun
│ ├── test-runner.service.ts # executeRun (promisePool, concurrency=3)
│ ├── test-execution.listener.ts # @OnEvent handler + AbortController
│ ├── test-schedules.service.ts # CRUD розкладів
│ ├── test-scheduler.service.ts # Cron-джоби (SchedulerRegistry)
│ ├── evaluator.service.ts # LLM-оцінка транскрипту
│ └── test-generator.service.ts # AI-генерація персон з agentPrompt
├── swagger/
│ └── testing-decorators.swagger.ts
├── chats/ # Інтерактивне тестування через чат
│ ├── controllers/
│ ├── entities/
│ ├── dtos/
│ └── services/
└── testing.module.tsОсновні ендпоінти
# Personas (Персони — профілі дзвінків)
GET /api/testing/personas # Список персон
POST /api/testing/personas # Створити персону
GET /api/testing/personas/:id # Отримати персону
PATCH /api/testing/personas/:id # Оновити персону
DELETE /api/testing/personas/:id # Видалити персону
POST /api/testing/personas/generate # AI-генерація персон
# Runs (Запуски тестів)
GET /api/testing/runs # Список запусків
POST /api/testing/runs # Запустити тести (personaIds?, scoreThreshold?)
POST /api/testing/runs/quick # Quick Test (автогенерація + запуск)
GET /api/testing/runs/:id # Отримати запуск
GET /api/testing/runs/:id/results # Детальні результати з транскриптами
POST /api/testing/runs/:id/cancel # Скасувати запуск
DELETE /api/testing/runs/:id # Видалити запуск
# Schedules (Розклади)
GET /api/testing/schedules # Список розкладів
POST /api/testing/schedules # Створити розклад
PATCH /api/testing/schedules/:id # Оновити розклад
DELETE /api/testing/schedules/:id # Видалити розклад
POST /api/testing/schedules/:id/toggle # Увімкнути/вимкнути
# Chats (Інтерактивне тестування)
POST /api/integrations/:id/chats # Створити чат
GET /api/integrations/:id/chats # Список чатів
GET /api/chats/:chatId # Отримати чат
DELETE /api/chats/:chatId # Видалити чат
GET /api/chats/:chatId/messages # Повідомлення
POST /api/chats/:chatId/messages # Надіслати повідомленняTestGeneratorService
AI-генерація персон з agentPrompt інтеграції через LlmService. Аналізує конфігурацію агента (name, prompt, language, tools, firstMessage) і генерує 5-8 різноманітних персон. Дедуплікація за іменем.
EvaluatorService
LLM-оцінка завершених діалогів. Критерії: Goal Achievement, Persona Handling, Tone & Professionalism, Information Accuracy, Conversation Flow. Повертає IEvaluation з загальним score (0-100) та breakdown по критеріях.
Залежності
- IntegrationsModule — зв'язок з інтеграціями (agentPrompt, ownership)
- LlmModule — LLM-провайдер (Groq/Claude) для діалогів та оцінки
- @nestjs/schedule — cron-розклади
MCP Module
Путь: src/app/shared/modules/mcp/
Model Context Protocol интеграция для AI взаимодействия с интеграциями.
Структура
shared/modules/mcp/
├── controllers/
│ └── mcp.controller.ts
├── interfaces/
│ └── mcp.interface.ts
├── services/
│ └── mcp.service.ts
├── tools/
│ ├── index.ts
│ └── integrations.tools.ts
└── mcp.module.tsНазначение
- Предоставление инструментов для AI моделей
- Интеграция с Model Context Protocol
- Tools для работы с интеграциями через IntegrationsService
Взаимодействие
MCP Module импортирует IntegrationsModule и предоставляет access к функциям управления интеграциями через MCP tools.
Health Module
Путь: src/app/shared/modules/health/
Health check endpoint для мониторинга приложения.
Структура
shared/modules/health/
├── controllers/
│ ├── health.controller.ts
│ └── index.ts
└── health.module.tsЭндпоинт
GET /health # Проверка здоровья приложенияДиаграмма взаимодействия модулей
graph TB
subgraph HighLevel [Высокоуровневые API]
Integrations["Integrations Module<br/>/api/integrations"]
Inngest["Inngest Module<br/>/api/inngest"]
Testing["Testing Module<br/>/api/testing"]
end
subgraph IntegCore [integ-core Прокси API]
Secrets["Secrets Module<br/>/api/core/secrets"]
Cache["Cache Module<br/>/api/core/cache"]
D1API["D1 Module<br/>/api/core/d1"]
KVAPI["KV Module<br/>/api/core/kv"]
end
subgraph Core_Auth [Core & Auth]
Auth["Auth Module"]
Users["Users Module"]
AccessTokens["Access Tokens Module"]
Core["Core Module"]
end
subgraph Shared_Global [Shared Global Modules]
Crypto["Crypto (@Global)"]
Logger["Logger (@Global)"]
end
subgraph Storage [Storage]
PostgreSQL["PostgreSQL<br/>TypeORM"]
D1["Cloudflare D1<br/>(integ-creds, integ-data)"]
KV["Cloudflare KV<br/>(CACHE)"]
end
subgraph ThirdParties [Third Parties]
CF["Cloudflare API"]
Inngest_Service["Inngest Service"]
Miniflare["Miniflare"]
LLM["LLM Provider (Groq/Claude)"]
end
Auth -->|JWT| Users
AccessTokens -->|userId| Users
Integrations -->|ownerId| Users
Integrations -->|Handlers| PostgreSQL
Inngest -->|URLs| Inngest_Service
Testing -->|integrationId| Integrations
Testing -->|Tester+Agent+Evaluator| LLM
Testing -->|Results| PostgreSQL
Secrets -->|Query| D1
Cache -->|KV ops| KV
D1API -->|Raw SQL| D1
KVAPI -->|Raw ops| KV
Secrets -->|Encrypt/Decrypt| Crypto
Integrations -->|Encrypt| Crypto
AccessTokens -->|Encrypt| Crypto
Secrets -->|Log| Logger
Integrations -->|Log| Logger
D1API -->|Log| Logger
KVAPI -->|Log| Logger
D1API -->|API calls| CF
KVAPI -->|API calls| CF
Core -->|Config| PostgreSQL
Core -->|Init| Crypto
Core -->|Init| Logger
style Crypto fill:#90EE90
style Logger fill:#90EE90
style Core fill:#FFB6C1
style HighLevel fill:#87CEEB
style LowLevel fill:#FFA500Глобальные модули
@Global() Модули
Эти модули доступны во всём приложении без дополнительных импортов:
- Crypto Module - Шифрование/дешифрование
- Logger Module - Логирование
Локальные модули
Эти модули импортируются только где они нужны:
- Health Module - Импортируется в AppModule
- Swagger Module - Используется через utils в main.ts
Принципы организации
Глобальность
Только критически важные модули должны быть глобальными:
// ✅ @Global() - Используется везде
@Global()
@Module({
providers: [LoggerService],
exports: [LoggerService]
})
export class LoggerModule {}
// ✅ @Global() - Нужен для шифрования данных
@Global()
@Module({
providers: [CryptoService],
exports: [CryptoService]
})
export class CryptoModule {}
// ❌ Не глобальный - импортируется явно
@Module({
imports: [HealthModule],
...
})
export class AppModule {}Принципы межмодульного взаимодействия
✅ Правильно
// Использование сервиса другого модуля
@Injectable()
export class IntegrationsService {
constructor(
private readonly _usersService: UsersService,
private readonly _gatewayService: GatewayService
) {}
async getIntegrations(userId: string) {
const user = await this._usersService.findOne({ where: { id: userId } });
if (!user) return null;
return this._gatewayService.listIntegrations();
}
}❌ Неправильно
// НИКОГДА не обращаемся к repository другого модуля напрямую!
@Injectable()
export class IntegrationsService {
constructor(
@InjectRepository(UserEntity)
private readonly _userRepo: Repository<UserEntity> // ❌ Плохо!
) {}
}Следующие шаги
- Бизнес-логика - Взаимодействие модулей
- Архитектурные паттерны - Паттерны проектирования
- API Guide - Работа с API