Skip to content

Архитектура приложения

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:

typescript
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 для управления состоянием:

typescript
import { createStore } from "@ngneat/elf";
import { withEntities } from "@ngneat/elf-entities";

const integrationsStore = createStore({ name: "integrations" }, withEntities<IIntegration>());

HTTP Layer

Формат API Ответов

API использует два разных формата для разных типов эндпоинтов:

Auth эндпоинты (БЕЗ обёртки)

typescript
// POST /auth/sign-in
{ accessToken: string, refreshToken: string }

// GET /auth/me
{ id: string, email: string, firstName?: string, lastName?: string }

Остальные эндпоинты (С обёрткой)

typescript
// GET /integrations
{ success: true, data: IIntegration[] }

// POST /integrations/:id/credentials
{ success: true, data: ICredential }

API Service

Базовый сервис для работы с API. Автоматически извлекает data из обёртки:

typescript
@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

typescript
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 операций:

typescript
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

typescript
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();

Аутентификация

  1. Пользователь вводит credentials
  2. Отправка запроса на /auth/login
  3. Получение JWT токена
  4. Сохранение токена в localStorage
  5. Перенаправление в админ-панель

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 — English
  • src/assets/i18n/ru.json — Русский

27 категорий переводов: agent, auth, chat, common, d1, dashboard, editor, emulator, handlers, integration, integrations, kv, nav, prompts, secrets, settings, testing, toasts, tools и др.

Следующие шаги

Integ Admin Documentation