import { Actual, All, ConstructorType, DestroyableType, DestroyContainer, MaybeMessage, Message, MessageType, Of, } from "silentium"; import { RegexpMatched } from "../system"; export interface Route { pattern?: string; patternFlags?: string; condition?: (v: unknown) => boolean; message: ConstructorType<[], MaybeMessage>; } const isTrue = (v: unknown) => v === true; /** * Router component what will return template if url matches pattern * * @url https://silentium.pw/article/router/view */ export function Router( _url: MaybeMessage, routes: MaybeMessage[]>, $default: ConstructorType<[], MaybeMessage>, ): MessageType & DestroyableType { const $routes = Actual(routes); const $url = Actual(_url); return Message(function RouterImpl(r) { const dc = DestroyContainer(); const destructor = () => { dc.destroy(); }; All($routes, $url).then(function routerAllSub([routes, url]) { destructor(); const $matches = All( ...routes.map(function routerRoutesMap(r) { return r.pattern ? RegexpMatched( Of(r.pattern), Of(url), r.patternFlags ? Of(r.patternFlags) : undefined, ) : r?.condition?.(url); }), ); $matches.then(function routerMatchesSub(matches) { const index = matches.findIndex(isTrue); if (index === -1) { const instance = Actual($default()); dc.add(instance); instance.then(r); } if (index > -1) { const instance = Actual(routes[index].message()); dc.add(instance); instance.then(r); } }); }); return destructor; }); }