docs: add inter-plugin communication (RPC + discovery) docs to README
This commit is contained in:
parent
d9c87aef0a
commit
11e1827031
144
README.md
144
README.md
|
|
@ -19,6 +19,7 @@ SDK для створення плагінів ERP-платформи. Міст
|
|||
- [Інтерфейси](#інтерфейси)
|
||||
- [Attribute Access Control (ABAC)](#attribute-access-control-abac)
|
||||
- [Події та RabbitMQ](#події-та-rabbitmq)
|
||||
- [Міжплагінна комунікація](#міжплагінна-комунікація)
|
||||
- [CLI — create-erp-plugin](#cli--create-erp-plugin)
|
||||
- [Експорт SDK](#експорт-sdk)
|
||||
|
||||
|
|
@ -64,24 +65,32 @@ npx create-erp-plugin my-plugin --port 3007
|
|||
|
||||
```
|
||||
┌───────────────────┐ HTTP/REST ┌──────────────┐
|
||||
│ Plugin (BE) │ ◄──────────────────► │ Core (BE) │
|
||||
│ Plugin A (BE) │ ◄──────────────────► │ Core (BE) │
|
||||
│ CoreService │ RabbitMQ │ Port 3001 │
|
||||
│ AttributeAccess │ ◄──────────────────► │ │
|
||||
└────────┬──────────┘ └──────────────┘
|
||||
│
|
||||
Module Federation
|
||||
│
|
||||
┌────────▼──────────┐
|
||||
│ Plugin (FE) │
|
||||
│ React + Vite │
|
||||
│ host/UIKit │
|
||||
└───────────────────┘
|
||||
└────────┬──────────┘ └──────────┬───┘
|
||||
│ ┌───────────────────────▲ │
|
||||
│ Plugin→Plugin│ HTTP RPC Proxy │ │
|
||||
│ v1.3.0 │ │ │
|
||||
│ ┌──────┴───────┐ │ │
|
||||
│ │ Plugin B (BE)│ │ │
|
||||
│ │ callPlugin │───────────────┘ │
|
||||
│ └──────────────┘ │
|
||||
│ │
|
||||
Module Federation Module Fed.
|
||||
│ │
|
||||
┌────────▼──────────┐ ┌──────────▼───┐
|
||||
│ Plugin A (FE) │ │ Plugin B(FE)│
|
||||
│ React + Vite │ │ React + Vite│
|
||||
│ host/UIKit │ │ host/UIKit │
|
||||
└───────────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
**Комунікація:**
|
||||
1. **HTTP (REST)** — `CoreService.fetchCore()` для запитів до ядра
|
||||
2. **RabbitMQ (асинхронно)** — `CoreService.emit()` для подій, `@EventPattern()` для отримання
|
||||
3. **Module Federation** — фронтенд плагіна монтується як remote module всередині host-застосунку
|
||||
3. **Plugin→Plugin RPC** (v1.3.0+) — `CoreService.callPluginApi()` для виклику API іншого плагіна через core-proxy
|
||||
4. **Module Federation** — фронтенд плагіна монтується як remote module всередині host-застосунку
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -152,6 +161,40 @@ await coreService.sendNotification({
|
|||
});
|
||||
```
|
||||
|
||||
#### `callPluginApi<T>(pluginId, path, body?)`
|
||||
|
||||
Викликати API іншого плагіна через core RPC-проксі. Запит проксується ядром на `backendUrl` цільового плагіна методом POST. JWT-токен автоматично прокидyється.
|
||||
|
||||
```typescript
|
||||
// Викликати ендпоінт плагіна notifications
|
||||
const result = await coreService.callPluginApi('notifications', 'stats', { period: 'week' });
|
||||
|
||||
// Викликати з вкладеним шляхом
|
||||
const user = await coreService.callPluginApi('user-management', 'users/42');
|
||||
```
|
||||
|
||||
#### `discoverPlugins()`
|
||||
|
||||
Отримати список усіх зареєстрованих плагінів з їхніми можливостями. Повертає масив маніфестів з полями: `id`, `name`, `label`, `icon`, `routePath`, `backendUrl`, `events`, `objectTypes`, `permissions`, `roles`, `database`, `menu`, `headerActions`.
|
||||
|
||||
```typescript
|
||||
const plugins = await coreService.discoverPlugins();
|
||||
|
||||
// Знайти плагін за id
|
||||
const notifPlugin = plugins.find(p => p.id === 'notifications');
|
||||
console.log(notifPlugin.backendUrl); // http://notifications:3008
|
||||
|
||||
// Знайти всі плагіни, що оголосили певну подію
|
||||
const listeners = plugins.filter(p =>
|
||||
p.events?.some(e => e.name === 'core.user.created')
|
||||
);
|
||||
|
||||
// Знайти плагіни, що працюють з певним типом об'єктів
|
||||
const dealPlugins = plugins.filter(p =>
|
||||
p.objectTypes?.includes('deal')
|
||||
);
|
||||
```
|
||||
|
||||
#### `getDbName()`
|
||||
|
||||
Отримати назву БД (після `setupDatabase`).
|
||||
|
|
@ -552,6 +595,83 @@ async handle(@Payload() data: any) {
|
|||
|
||||
---
|
||||
|
||||
## Міжплагінна комунікація
|
||||
|
||||
До версії 1.3.0 плагіни могли спілкуватись тільки через ядро (HTTP до core + RabbitMQ broadcast). Починаючи з v1.3.0 додано підтримку прямого плагін→плагін зв'язку через HTTP RPC проксі.
|
||||
|
||||
### Архітектура
|
||||
|
||||
```
|
||||
Plugin A Core Backend Plugin B
|
||||
| | |
|
||||
|-- discoverPlugins() ----------->| |
|
||||
|<-- [{ id:'notifications', ... }]| |
|
||||
| | |
|
||||
|-- callPluginApi('notifications', | |
|
||||
| 'stats', { period:'week' })-->| |
|
||||
| |-- POST /stats -------------->|
|
||||
| |<-- { sent: 42 } ------------|
|
||||
|<-- { sent: 42 } ----------------| |
|
||||
```
|
||||
|
||||
Всі запити проходять через Core, який:
|
||||
1. **Перевіряє JWT** (як і будь-який захищений ендпоінт)
|
||||
2. **Визначає `backendUrl`** цільового плагіна з реєстру
|
||||
3. **Проксує POST-запит** з автентифікацією та тілом
|
||||
|
||||
### Discover — дізнатись які плагіни доступні
|
||||
|
||||
```typescript
|
||||
const plugins = await coreService.discoverPlugins();
|
||||
```
|
||||
|
||||
Кожен плагін має:
|
||||
- `id`, `name`, `label`, `backendUrl` — адреса для RPC
|
||||
- `events: { name, description }[]` — які події оголошує
|
||||
- `objectTypes: string[]` — з якими об'єктами працює
|
||||
- `permissions`, `roles` — права доступу
|
||||
|
||||
### RPC — викликати API іншого плагіна
|
||||
|
||||
```typescript
|
||||
const stats = await coreService.callPluginApi('notifications', 'stats');
|
||||
const user = await coreService.callPluginApi('user-management', 'users/42');
|
||||
const result = await coreService.callPluginApi('global-store', 'store/set', {
|
||||
key: 'my-key',
|
||||
value: { foo: 'bar' },
|
||||
});
|
||||
```
|
||||
|
||||
**Обмеження:**
|
||||
- Тільки POST-метод (ядро проксує POST на `backendUrl` цільового плагіна). Для GET-ендпоінтів цільового плагіна — використовуйте `@Post()` контролер з потрібною логікою.
|
||||
- Потребує JWT-токена (як і будь-який захищений API). Токен автоматично прокидyється з контексту запиту.
|
||||
- Якщо плагін не зареєстрований або не має `backendUrl` — повертається 404.
|
||||
|
||||
### Типовий сценарій використання
|
||||
|
||||
```typescript
|
||||
// В сервісі плагіна A
|
||||
async function notifyAndLog() {
|
||||
// 1. Discovery — знайти потрібний плагін
|
||||
const plugins = await this.coreService.discoverPlugins();
|
||||
const notifPlugin = plugins.find(p => p.events?.some(e => e.name === 'notification.send'));
|
||||
|
||||
// 2. RPC — викликати API плагіна B
|
||||
if (notifPlugin) {
|
||||
await this.coreService.callPluginApi('notifications', 'send', {
|
||||
userId: 1,
|
||||
title: 'Event occurred',
|
||||
message: 'Plugin A triggered a notification',
|
||||
});
|
||||
}
|
||||
|
||||
// 3. Або викликати будь-який кастомний ендпоінт
|
||||
const status = await this.coreService.callPluginApi('audit-logs', 'stats/daily');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CLI — create-erp-plugin
|
||||
|
||||
Генерація нового плагіна:
|
||||
|
|
@ -612,7 +732,7 @@ my-plugin/
|
|||
|
||||
```
|
||||
@erp/plugin-sdk
|
||||
├── CoreService # Головний сервіс (fetchCore, emit, register, ...)
|
||||
├── CoreService # Головний сервіс (fetchCore, emit, register, callPluginApi, discoverPlugins, ...)
|
||||
├── CoreClientService # RabbitMQ RPC клієнт
|
||||
├── AttributeAccessService # ABAC — керування атрибутами та перевірка доступу
|
||||
├── getRabbitMQOptions() # NestJS Microservice options
|
||||
|
|
|
|||
Loading…
Reference in New Issue