Плагіни пропонують можливість додавати нові функції переважно через одну точку входу. Вони спілкуються один з одним за допомогою сигналів, які поширюються від батьківських плагінів до дочірніх. Оскільки плагіни можуть мати кілька дочірніх плагінів, ці сигнали передаються в тому порядку, в якому вони підключені (це може бути важливо під час включення плагінів, таких як rete-readonly-plugin
)
Наступний приклад коду демонструє створення двох скоупів: батьківського та дочірнього. Обидва скоупи логують сигнали.
import { Scope } from 'rete';
const parentScope = new Scope<number>('parent'); // number це продукуємий тип
const childScope = new Scope<string, [number]>('child'); // [number] це очікуваний тип батьківського ланцюга
parentScope.addPipe((context) => { // додати пайп до батьківської області
console.log('parent', context); // number
return context;
});
childScope.addPipe((context) => { // додати пайп до дочірньої області
console.log('child', context); // string | number
return context;
});
parentScope.use(childScope); // forward all signals to child scope
const returnedNumber = await parentScope.emit(1); // can emit number
const returnedString = await childScope.emit('a'); // can emit string
Майте на увазі, що порядок use
і addPipe
впливає на порядок виклику батьківського та дочірнього обробників.
Логи:
parent 1
child 1
child a
У деяких випадках сигнали можна змінювати або блокувати.
parentScope.addPipe((context) => {
return context * 2;
});
childScope.addPipe((context) => {
if (context === 'b') return // запобігання поширення 'b'
return context;
});
const doubledNumber = await parentScope.emit(1); // 2
const expectedString = await childScope.emit('a'); // 'a'
const expectedUndefined = await childScope.emit('b'); // undefined
Статична типізація використовується для гарантії того, що очікувані сигнали використовуваних плагінів сумісні з сигналами, створеними батьківським плагіном.
import { Scope } from 'rete';
const parentScope = new Scope<number>('parent');
const childScope = new Scope<string, [number | boolean]>('child');
parentScope.use(childScope); // Type 'boolean' is not assignable to type 'string | number'.ts(2345)
Дочірні плагіни можуть отримати доступ до екземпляра батьківського плагіна як для прямого доступу до його інтерфейсів, так і для продукування сигналів від імені батьківського плагіна
import { Scope } from 'rete';
class Root extends Scope<number> {
isRoot = true
}
class Root2 extends Scope<number> {
isRoot2 = true
}
const parentScope = new Root('parent');
const childScope = new Scope<string, [number]>('child');
parentScope.use(childScope);
const parent = childScope.parentScope(); // екземпляр Root, але Scope з точки зору TS
const root = childScope.parentScope<Root>(Root); // екземпляр Root
const wrongInstance = childScope.parentScope<Root2>(Root2); // викидає виняток