You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.5 KiB
106 lines
3.5 KiB
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<Route> = new Collection<Route>()
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|