Архитектура приложения
Integ Admin построен на Angular 20 с использованием современных подходов и best practices.
Общая архитектура
Приложение использует модульную архитектуру с четким разделением ответственности:
src/app/
├── core/ # Ядро приложения
├── admin/ # Админ секция
└── shared/ # Shared компонентыCore
Содержит основную функциональность приложения:
- Services — бизнес-логика и работа с API (25 сервисов)
- Guards — защита маршрутов (authGuard, noAuthGuard)
- Interceptors — обработка HTTP запросов (auth, error, loading)
- Interfaces — TypeScript типы и интерфейсы (26 интерфейсов)
- Routes — определение роутов с lazy loading
Admin
Содержит админскую часть приложения:
- Layout — общий layout с навигацией (sidenav, header)
- Pages — страницы функциональности (12 feature pages)
Shared
Содержит переиспользуемые компоненты:
- Components — 31 UI компонент (sidebar-list, data-table, monaco-editor-wrapper, fab-button, empty-state, page-header и др.)
- Pipes — date-format pipe
- Utils — утилиты
Роутинг
Приложение использует Angular Router с lazy loading:
export const CORE_ROUTES: Routes = [
{
path: 'auth',
children: [
{ path: 'login', loadComponent: ... },
{ path: 'register', loadComponent: ... }
]
},
{
path: 'admin',
canActivate: [authGuard],
loadComponent: ...,
children: [
{ path: 'dashboard', loadComponent: ... },
{ path: 'integrations', children: [
{ path: '', loadComponent: IntegrationsComponent },
{ path: ':id', loadComponent: IntegrationComponent, children: [
{ path: 'handlers', children: [{ path: ':handlerId', ... }] },
{ path: 'agent', ... },
{ path: 'secrets', ... },
{ path: 'd1', children: [{ path: ':tableName', ... }] },
{ path: 'kv', children: [{ path: ':keyName', ... }] },
{ path: 'tests', children: [{ path: ':scenarioId', ... }] },
{ path: 'chats', children: [{ path: ':chatId', ... }] }
]}
]},
{ path: 'testing', loadChildren: TESTING_ROUTES },
{ path: 'emulator', loadChildren: EMULATOR_ROUTES },
{ path: 'prompts', loadChildren: PROMPTS_ROUTES },
{ path: 'tools', children: [
{ path: 'base64', ... },
{ path: 'proxy', ... }
]},
{ path: 'd1', children: [{ path: ':tableName', ... }] },
{ path: 'kv', children: [
{ path: ':namespaceId', children: [{ path: ':keyName', ... }] }
]},
{ path: 'settings', children: [
{ path: 'account', ... },
{ path: 'access-tokens', ... }
]}
]
}
];Защита маршрутов
Используются два guard'а:
- authGuard — проверяет авторизацию для доступа к админ-панели
- noAuthGuard — редирект для авторизованных пользователей (login/register)
Страницы и функциональность
Dashboard (/admin/dashboard)
Стартовая страница с карточками интеграций и быстрым поиском.
Integrations (/admin/integrations)
Основной раздел. Каждая интеграция имеет табы:
- Handlers — обработчики вебхуков с тестированием
- Agent — промпт агента с Monaco editor
- Secrets — управление секретами интеграции
- D1 — таблицы базы данных с SQL консолью
- KV — ключи KV хранилища с Monaco editor
- Tests — тестовые сценарии
- Chats — история чатов
Standalone D1 (/admin/d1)
Браузер Cloudflare D1 баз данных. Адаптивный сайдбар: таблицы → строки.
Standalone KV (/admin/kv)
Браузер Cloudflare KV. Адаптивный сайдбар: namespaces → keys → key detail с Monaco editor.
Tools (/admin/tools)
Инструменты разработчика: Base64 encoder/decoder, HTTP proxy.
Emulator (/admin/emulator)
Эмулятор для тестирования обработчиков HTTP запросов.
Prompts (/admin/prompts)
Управление шаблонами промптов.
Testing (/admin/testing)
Массовое тестирование интеграций.
Settings (/admin/settings)
Настройки аккаунта и управление access tokens.
State Management
Приложение использует @ngneat/elf для управления состоянием:
import { createStore } from "@ngneat/elf";
import { withEntities } from "@ngneat/elf-entities";
const integrationsStore = createStore({ name: "integrations" }, withEntities<IIntegration>());HTTP Layer
Формат API Ответов
API использует два разных формата для разных типов эндпоинтов:
Auth эндпоинты (БЕЗ обёртки)
// POST /auth/sign-in
{ accessToken: string, refreshToken: string }
// GET /auth/me
{ id: string, email: string, firstName?: string, lastName?: string }Остальные эндпоинты (С обёрткой)
// GET /integrations
{ success: true, data: IIntegration[] }
// POST /integrations/:id/credentials
{ success: true, data: ICredential }API Service
Базовый сервис для работы с API. Автоматически извлекает data из обёртки:
@Injectable({ providedIn: "root" })
export class ApiService {
private readonly http = inject(HttpClient);
get<T>(url: string) {
return this.http.get<IApiWrapper<T>>(url).pipe(map((response) => response.data));
}
post<T>(url: string, data: unknown) {
return this.http.post<IApiWrapper<T>>(url, data).pipe(map((response) => response.data));
}
patch<T>(url: string, data: unknown) {
return this.http.patch<IApiWrapper<T>>(url, data).pipe(map((response) => response.data));
}
delete<T>(url: string) {
return this.http.delete<IApiWrapper<T>>(url).pipe(map((response) => response.data));
}
}Interceptors
Auth Interceptor
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = localStorage.getItem("access_token");
if (token) {
req = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
}
return next(req);
};Error Interceptor
Обрабатывает ошибки и выполняет logout при 401.
Loading Interceptor
Автоматически отслеживает состояние загрузки HTTP запросов для GlobalProgressBarComponent.
Ключевые паттерны
Adaptive Sidebar (Explorer Layout)
Страницы KV, D1, Handlers, Tests, Chats используют единый адаптивный сайдбар:
Namespaces mode → Keys mode (с кнопкой назад) → Key detail (router-outlet)SidebarListComponent— переиспользуемый компонент бокового менюshowItemMenu— включает dropdown с Edit/Delete#headerActions— слот для кнопки "назад"useRouting— автоматическая навигация по клику- Состояние отслеживается через
Router.events+NavigationEnd
BehaviorSubject Trigger Pattern
Для обновления данных после CRUD операций:
private readonly refreshData$ = new BehaviorSubject(true);
private readonly data$ = this.refreshData$.pipe(
switchMap(() => this.service.getData()),
catchError(() => of([])),
shareReplay(1)
);
readonly data = toSignal(this.data$, { initialValue: [] });Dialog + Toastr
this.dialogService
.onSuccess(FormDialogComponent, { data: {...} })
.pipe(
switchMap((result) => this.service.save(result)),
this.toastr.withToastr({ success: "Saved", error: "Error" }),
tap(() => this.refreshData$.next(true)),
untilDestroyed(this)
)
.subscribe();Аутентификация
- Пользователь вводит credentials
- Отправка запроса на
/auth/login - Получение JWT токена
- Сохранение токена в localStorage
- Перенаправление в админ-панель
Server-Side Rendering
- Protected routes (
/admin/**) →RenderMode.Client(без SSR) - Auth pages (
/auth/**) →RenderMode.Server(с SSR) - Сборка генерирует
dist/admin/browser+dist/admin/server
Интернационализация (i18n)
Используется @jsverse/transloco с тремя языками:
src/assets/i18n/uk.json— Українськаsrc/assets/i18n/en.json— Englishsrc/assets/i18n/ru.json— Русский
27 категорий переводов: agent, auth, chat, common, d1, dashboard, editor, emulator, handlers, integration, integrations, kv, nav, prompts, secrets, settings, testing, toasts, tools и др.
Следующие шаги
- Паттерны — архитектурные паттерны
- Правила кода — стандарты написания кода
- Стили — SCSS гайдлайны