import { Actual } from "base/Actual"; import { Source } from "base/Source"; import { All } from "components/All"; import { Destructured } from "components/Destructured"; import { Primitive } from "components/Primitive"; import { ConstructorType } from "types/ConstructorType"; import { ContextType } from "types/ContextType"; import { MaybeMessage } from "types/MessageType"; Context.transport = new Map>(); /** * The ability to call an external system through * sending a message in a standardized format * ContextType, the list of transport should be defined via * the Context.transport map object * * @url https://silentium.pw/article/context/view */ export function Context( name: MaybeMessage, params: MaybeMessage = {}, ) { const $msg = Destructured( All(Actual(name), Actual(params)), function contextMsgNormalize(name, params) { return { transport: name, params, result: undefined, error: undefined, } as ContextType; }, ); return Source( function contextMsgImpl(resolve, reject) { $msg.then(function contextMsgSub(message) { const transport = Context.transport.get(message.transport); if (transport === undefined) { throw new Error(`Context: unknown transport ${message.transport}`); } if (!message.result) { message.result = resolve; } if (!message.error) { message.error = reject; } try { transport(message); } catch (error) { reject(error); } }); }, function contextSrcImpl(value) { const msg = Primitive($msg).primitive(); if (msg === null) { throw new Error("Context: sourcing impossible message not existed"); } const transport = Context.transport.get(msg.transport); if (transport === undefined) { throw new Error(`Context: sourcing unknown transport ${msg.transport}`); } transport({ ...msg, value, }); }, ); }