Управление интеграциями
Интеграции — это основная сущность приложения. Каждая интеграция представляет собой отдельную конфигурацию со своими credentials, secrets и handlers.
Обзор
Функциональность управления интеграциями включает:
- ✅ Просмотр списка всех интеграций
- ✅ Создание новых интеграций
- ✅ Редактирование интеграций
- ✅ Удаление интеграций
- ✅ Управление credentials
- ✅ Управление secrets
- ✅ Управление handlers
- ✅ Просмотр audit logs
Структура интеграции
interface IIntegration {
id: string; // UUID
name: string; // Название
createdAt: string; // Дата создания
updatedAt: string; // Дата обновления
}Страницы
Список интеграций
URL: /admin/integrations
Отображает таблицу всех интеграций с возможностью:
- Поиска по названию
- Сортировки
- Перехода к детальной странице
- Удаления интеграции
Компонент: IntegrationsListComponent
@Component({
selector: "app-integrations-list",
standalone: true,
imports: [MatTableModule, MatButtonModule, MatIconModule],
templateUrl: "./integrations-list.component.html"
})
export class IntegrationsListComponent implements OnInit {
private readonly integrationsService = inject(IntegrationsService);
integrations: IIntegration[] = [];
displayedColumns = ["name", "createdAt", "actions"];
ngOnInit() {
this.loadIntegrations();
}
loadIntegrations() {
this.integrationsService.getAll().subscribe((integrations) => {
this.integrations = integrations;
});
}
deleteIntegration(id: string) {
this.integrationsService.delete(id).subscribe(() => {
this.loadIntegrations();
});
}
}Создание интеграции
URL: /admin/integrations/new
Форма для создания новой интеграции.
Поля:
name— название интеграции (required)
Пример:
createIntegration() {
const data: ICreateIntegrationRequest = {
name: 'My New Integration'
};
this.integrationsService.create(data).subscribe(integration => {
this.router.navigate(['/admin/integrations', integration.id]);
});
}Детальная страница
URL: /admin/integrations/:id
Детальная информация об интеграции с вкладками:
- Handlers — обработчики событий (webhooks)
- Secrets — секреты и конфиденциальные данные
- D1 — управление таблицами базы данных
- KV — управление key-value хранилищем
- Agent — настройки AI агента (промпт, ElevenLabs, голосовой ассистент)
- Tests — тестовые сценарии для интеграции
- Chats — история чатов с AI агентом
В заголовке страницы также есть быстрые ссылки на внешние сервисы:
- Documentation — текстовая документация (
https://integ.docs.happ.tools/integrations/{name}) - API Docs — OpenAPI/Scalar документация (
{baseUrl}/{name}/docs) - SaaS Platform, ElevenLabs, Inngest, Cloudflare Worker/Logs/Settings, D1, KV, GitHub Actions
Credentials
Credentials — это публичные учетные данные (например, API keys, usernames).
Операции
Просмотр
this.credentialsService.getByIntegration(integrationId).subscribe((credentials) => {
console.log(credentials);
});Создание
const data: ICreateCredentialRequest = {
key: "API_KEY",
value: "your-api-key-here"
};
this.credentialsService.create(integrationId, data).subscribe((credential) => {
console.log("Created:", credential.id);
});Обновление
const data: IUpdateCredentialRequest = {
value: "new-api-key-value"
};
this.credentialsService.update(integrationId, credentialId, data).subscribe();Удаление
this.credentialsService.delete(integrationId, credentialId).subscribe();Пример использования
Credential для Telegram Bot:
{
key: 'BOT_TOKEN',
value: '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11'
}Secrets
Secrets — это конфиденциальные данные (например, webhook secrets, private keys).
Операции
API идентичен Credentials:
// Получить все секреты
this.secretsService.getByIntegration(integrationId);
// Создать секрет
this.secretsService.create(integrationId, {
key: "WEBHOOK_SECRET",
value: "secret-value"
});
// Обновить
this.secretsService.update(integrationId, secretId, {
value: "new-secret-value"
});
// Удалить
this.secretsService.delete(integrationId, secretId);Безопасность
Важно
Secrets хранятся в зашифрованном виде на backend'е. Frontend получает только зашифрованную версию.
Handlers
Handlers — это обработчики событий (webhooks).
Структура
interface IHandler {
id: string;
integrationId: string;
name: string; // Используется в URL
defaultArgs: Record<string, any>; // Дефолтные аргументы
createdAt: string;
updatedAt: string;
}Синхронизация Handlers из OpenAPI
Handlers можно автоматически синхронизировать из OpenAPI спецификации integ-core. В UI рядом с кнопкой создания handler'а есть кнопка синхронизации (иконка sync).
this.integrationsService.syncHandlers(integrationId, { integrationName: "sofa" }).subscribe((result) => {
console.log(`Created: ${result.created}, Updated: ${result.updated}`);
});Синхронизация:
- Делает запрос к
{baseUrl}/{integrationName}/openapi.json - Парсит OpenAPI spec и извлекает handlers из paths
- Создаёт новые или обновляет существующие handlers
Создание Handler
const data: ICreateHandlerRequest = {
name: "order-created",
defaultArgs: {
timeout: 5000,
retries: 3
}
};
this.handlersService.create(integrationId, data).subscribe((handler) => {
console.log("Handler URL:", `/webhook/${handler.name}`);
});Выполнение Handler
Тестирование handler'а напрямую из UI:
this.handlersService
.execute("order-created", "POST", {
body: {
orderId: "12345",
amount: 100
}
})
.subscribe((response) => {
console.log("Status:", response.statusCode);
console.log("Body:", response.body);
console.log("Timestamp:", response.timestamp);
});Webhook URL
Handler доступен по URL:
POST https://your-domain.com/webhook/{handler-name}Пример:
curl -X POST https://api.example.com/webhook/order-created \
-H "Content-Type: application/json" \
-d '{"orderId": "12345", "amount": 100}'Диалоги
Приложение использует Material Dialog для создания/редактирования:
Пример диалога создания Credential
@Component({
selector: "app-credential-create-dialog",
standalone: true,
imports: [MatDialogModule, ReactiveFormsModule],
template: `...`
})
export class CredentialCreateDialogComponent {
private readonly dialogRef = inject(MatDialogRef);
private readonly data = inject(MAT_DIALOG_DATA);
form = new FormGroup({
key: new FormControl("", Validators.required),
value: new FormControl("", Validators.required)
});
onSubmit() {
if (this.form.valid) {
this.dialogRef.close(this.form.value);
}
}
}Открытие диалога:
const dialogRef = this.dialog.open(CredentialCreateDialogComponent, {
width: "500px",
data: { integrationId }
});
dialogRef.afterClosed().subscribe((result) => {
if (result) {
this.credentialsService.create(integrationId, result).subscribe(() => {
this.loadCredentials();
});
}
});Audit Logs
Просмотр истории изменений интеграции.
this.auditService.getByIntegration(integrationId).subscribe((logs) => {
console.log(logs);
});API Endpoints
| Метод | Endpoint | Описание |
|---|---|---|
| GET | /integrations | Список интеграций |
| GET | /integrations/:id | Детали интеграции |
| POST | /integrations | Создать интеграцию |
| PUT | /integrations/:id | Обновить интеграцию |
| DELETE | /integrations/:id | Удалить интеграцию |
| POST | /integrations/:id/sync-handlers | Синхронизация handlers |
| GET | /integrations/:id/credentials | Список credentials |
| POST | /integrations/:id/credentials | Создать credential |
| PUT | /integrations/:id/credentials/:credId | Обновить credential |
| DELETE | /integrations/:id/credentials/:credId | Удалить credential |
| GET | /integrations/:id/secrets | Список secrets |
| POST | /integrations/:id/secrets | Создать secret |
| PUT | /integrations/:id/secrets/:secId | Обновить secret |
| DELETE | /integrations/:id/secrets/:secId | Удалить secret |
| GET | /integrations/:id/handlers | Список handlers |
| POST | /integrations/:id/handlers | Создать handler |
| PUT | /integrations/:id/handlers/:handlerId | Обновить handler |
| DELETE | /integrations/:id/handlers/:handlerId | Удалить handler |
Типичные сценарии
Создание полной интеграции
// 1. Создать интеграцию
const integration = await firstValueFrom(this.integrationsService.create({ name: "Telegram Bot" }));
// 2. Добавить credential
await firstValueFrom(
this.credentialsService.create(integration.id, {
key: "BOT_TOKEN",
value: "token-here"
})
);
// 3. Добавить secret
await firstValueFrom(
this.secretsService.create(integration.id, {
key: "WEBHOOK_SECRET",
value: "secret-here"
})
);
// 4. Создать handler
await firstValueFrom(
this.handlersService.create(integration.id, {
name: "message-received",
defaultArgs: { timeout: 5000 }
})
);Следующие шаги
- Access Tokens — токены для API
- Аутентификация — система авторизации
- API Reference — документация сервисов