import LifecycleUnit from '../lifecycle/Unit.ts' import {Unit} from '../lifecycle/decorators.ts' import Routes from './Routes.ts' import {RouterDefinition} from '../http/type/RouterDefinition.ts' import {Collection} from '../collection/Collection.ts' import {Route} from '../http/routing/Route.ts' import {SimpleRoute} from "../http/routing/SimpleRoute.ts"; import {ComplexRoute} from "../http/routing/ComplexRoute.ts"; import ActivatedRoute from "../http/routing/ActivatedRoute.ts"; export type RouteHandler = () => any export interface RouteDefinition { get?: RouteHandler, post?: RouteHandler, patch?: RouteHandler, delete?: RouteHandler, head?: RouteHandler, put?: RouteHandler, connect?: RouteHandler, options?: RouteHandler, trace?: RouteHandler, } const verbs = ['get', 'post', 'patch', 'delete', 'head', 'put', 'connect', 'options', 'trace'] @Unit() export default class Routing extends LifecycleUnit { protected definitions: { [key: string]: RouteDefinition } = {} protected instances: Collection = new Collection() constructor( protected readonly routes: Routes, ) { super() } public async up() { const route_groups = this.routes.all() for ( const route_group_name of route_groups ) { const route_group: RouterDefinition | undefined = this.routes.get(route_group_name) if ( !route_group ) continue const prefix = route_group.prefix || '/' for ( const verb of verbs ) { // @ts-ignore if ( route_group[verb] ) { // @ts-ignore const group = route_group[verb] for ( const key in group ) { if ( !group.hasOwnProperty(key) ) continue const handlers = Array.isArray(group[key]) ? group[key] : [group[key]] const base = this.resolve([prefix, key]) if ( !this.definitions[base] ) { this.definitions[base] = {} } // @ts-ignore this.definitions[base][verb] = this.build_handler(handlers) // TODO want to rework this this.instances.push(this.build_route(base)) } } } } } // TODO public build_handler(group: string[]): () => any { return () => {} } public resolve(parts: string[]): string { const cleaned = parts.map(part => { if ( part.startsWith('/') ) part = part.substr(1) if ( part.endsWith('/') ) part = part.slice(0, -1) return part }) let joined = cleaned.join('/') if ( joined.startsWith('/') ) joined = joined.substr(1) if ( joined.endsWith('/') ) joined = joined.slice(0, -1) return `/${joined}`.toLowerCase() } public build_route(base: string): Route { if ( !base.includes(':') && !base.includes('*') ) { return new SimpleRoute(base) } else { return new ComplexRoute(base) } // TODO deep-match route } public match(incoming: string): Route | undefined { return this.instances.firstWhere((route: Route) => route.match(incoming)) } public build(incoming: string): ActivatedRoute | undefined { const route: Route | undefined = this.match(incoming) if ( route ) { return new ActivatedRoute(incoming, route) } } }