import { IDestroyable } from "@implab/core-amd/interfaces"; export interface Sink { next: (value: T) => void; error: (e: unknown) => void; complete: () => void; } export type Consumer = Partial>; export type Producer = (sink: Sink) => (void | (() => void)); export interface Observable { on(sink: Partial>): IDestroyable; } const noop = () => {}; const sink = (consumer: Consumer) => { const { next = noop, error = noop, complete = noop } = consumer; let done = false; return { next: (value: T) => done && next(value), error: (e: unknown) => done && (done = true, error(e)), complete: () => done && (done = true, complete()) }; } export const observe = (producer: Producer) => ({ on: (consumer: Consumer) => ({ destroy: producer(sink(consumer)) ?? noop }) });