@platform/cell.tmpl
Version:
Template generator for the system
72 lines (59 loc) • 1.81 kB
text/typescript
import { filter, takeUntil } from 'rxjs/operators';
import { rx, slug, t } from './common';
type Id = string;
/**
* Event API.
*/
export function BusEvents(args: {
instance: { bus: t.EventBus<any>; id: Id };
filter?: (e: t.MyEvent) => boolean;
dispose$?: t.Observable<any>;
}): t.MyEvents {
const { dispose, dispose$ } = rx.disposable(args.dispose$);
const bus = rx.busAsType<t.MyEvent>(args.instance.bus);
const instance = args.instance.id;
const is = BusEvents.is;
const $ = bus.$.pipe(
takeUntil(dispose$),
filter((e) => is.instance(e, instance)),
filter((e) => args.filter?.(e) ?? true),
);
/**
* Base information about the module.
*/
const info: t.MyEvents['info'] = {
req$: rx.payload<t.MyInfoReqEvent>($, 'my.namespace/info:req'),
res$: rx.payload<t.MyInfoResEvent>($, 'my.namespace/info:res'),
async get(options = {}) {
const { timeout = 3000 } = options;
const tx = slug();
const op = 'info';
const res$ = info.res$.pipe(filter((e) => e.tx === tx));
const first = rx.asPromise.first<t.MyInfoResEvent>(res$, { op, timeout });
bus.fire({
type: 'my.namespace/info:req',
payload: { tx, instance },
});
const res = await first;
if (res.payload) return res.payload;
const error = res.error?.message ?? 'Failed';
return { tx, instance, error };
},
};
return {
instance: { bus: rx.bus.instance(bus), id: instance },
$,
dispose,
dispose$,
is,
info,
};
}
/**
* Event matching.
*/
const matcher = (startsWith: string) => (input: any) => rx.isEvent(input, { startsWith });
BusEvents.is = {
base: matcher('my.namespace/'),
instance: (e: t.Event, instance: Id) => BusEvents.is.base(e) && e.payload?.instance === instance,
};