import { IPathMatcher } from '../path-matcher/interfaces'; import { IRoute } from './interfaces'; import { CancellablePromise, ICancellablePromise, IReadonlyList, TAbortStrategy } from '@lifaon/observables'; import { ICreateRouteResolverOptionsResolveCallbackReturnedValue, IRouteOptions, IRouteResolveCallbackNormalizedOptions, IRouteResolveCallbackOptions, IRouteResolveIncomingCallbackOptions, TRouteExecCallback } from './types'; import { IRouteInternal, IRoutePrivate, ROUTE_PRIVATE } from './privates'; import { ConstructRoute } from './constructor'; import { IResolvableTree } from '../resolvable-tree/interfaces'; import { ResolvableTree } from '../resolvable-tree/implementation'; import { IResolvableTreeOptions, TResolvableTreeResolveCallback } from '../resolvable-tree/types'; import { CreateResolvableTreeResolver, ICreateResolvableTreeResolverOptions } from '../resolvable-tree/functions'; import { IPathMatcherResult } from '../path-matcher/types'; import { $super } from '../../misc/instance/snippets'; /** CONSTRUCTOR FUNCTIONS **/ export function CreateRouteResolver(): TResolvableTreeResolveCallback { return CreateResolvableTreeResolver({ resolve( this: IRoute, options: IRouteResolveIncomingCallbackOptions ): ICancellablePromise, TStrategy> { type TCPReturn = ICreateRouteResolverOptionsResolveCallbackReturnedValue; const instance: IRoute = this; const privates: IRoutePrivate = (instance as IRouteInternal)[ROUTE_PRIVATE]; const normalizedOptions: IRouteResolveCallbackNormalizedOptions = options; const path: IPathMatcherResult | null = privates.pathMatcher.exec(normalizedOptions.path); if (path === null) { return CancellablePromise.resolve({ resolved: false }, normalizedOptions); } else { return (privates.resolve.call(instance, normalizedOptions) as ICancellablePromise) .then((resolved: boolean): TCPReturn => { const childrenOptions: IRouteResolveCallbackOptions | undefined = resolved ? ({ ...normalizedOptions, path: path.remaining, }) : void 0; const resolvePathOptions: IRouteResolveCallbackOptions | undefined = childrenOptions; return { resolved, childrenOptions, resolvePathOptions, }; }); } }, resolvePath( this: IRoute, options: IRouteResolveIncomingCallbackOptions, path: IRoute[] ): ICancellablePromise { const instance: IRoute = this; return CancellablePromise.try(() => { const isFinalRoute: boolean = ( (options.path === '') && (instance.exec !== null) ); if (path.length === 0) { // no children or no children resolved if (isFinalRoute) { return [instance]; } else { return []; } } else { return [instance].concat(path); } }, options); } } as ICreateResolvableTreeResolverOptions); } const ROUTE_RESOLVER = CreateRouteResolver(); /** METHODS **/ /* GETTERS/SETTERS */ export function RouteGetPathMatcher(instance: IRoute): IPathMatcher { return (instance as IRouteInternal)[ROUTE_PRIVATE].pathMatcher; } export function RouteGetExec(instance: IRoute): TRouteExecCallback | null { return (instance as IRouteInternal)[ROUTE_PRIVATE].exec; } /** CLASS **/ export class Route extends ResolvableTree implements IRoute { constructor(path: string, options: IRouteOptions = {}) { const _options: IResolvableTreeOptions = { ...options, resolve: ROUTE_RESOLVER, }; super(_options); ConstructRoute(this, path, options); } get children(): IReadonlyList { return $super(this, ResolvableTree).get('children'); // return super.children as IReadonlyList; } get pathMatcher(): IPathMatcher { return RouteGetPathMatcher(this); } get exec(): TRouteExecCallback | null { return RouteGetExec(this); } resolve(options: IRouteResolveCallbackOptions): ICancellablePromise { return super.resolve(options); } }