2022-09-12 11:49:18 +00:00
|
|
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
|
|
import type { Router, Result } from '../../router.ts'
|
|
|
|
import { UnsupportedPathError } from '../../router.ts'
|
|
|
|
|
|
|
|
export class SmartRouter<T> implements Router<T> {
|
2023-05-17 15:05:28 +00:00
|
|
|
name: string = 'SmartRouter'
|
2022-09-12 11:49:18 +00:00
|
|
|
routers: Router<T>[] = []
|
|
|
|
routes?: [string, string, T][] = []
|
|
|
|
|
|
|
|
constructor(init: Pick<SmartRouter<T>, 'routers'>) {
|
|
|
|
Object.assign(this, init)
|
|
|
|
}
|
|
|
|
|
|
|
|
add(method: string, path: string, handler: T) {
|
|
|
|
if (!this.routes) {
|
|
|
|
throw new Error('Can not add a route since the matcher is already built.')
|
|
|
|
}
|
|
|
|
|
|
|
|
this.routes.push([method, path, handler])
|
|
|
|
}
|
|
|
|
|
2023-10-15 23:39:37 +00:00
|
|
|
match(method: string, path: string): Result<T> {
|
2022-09-12 11:49:18 +00:00
|
|
|
if (!this.routes) {
|
|
|
|
throw new Error('Fatal error')
|
|
|
|
}
|
|
|
|
|
|
|
|
const { routers, routes } = this
|
|
|
|
const len = routers.length
|
|
|
|
let i = 0
|
|
|
|
let res
|
|
|
|
for (; i < len; i++) {
|
|
|
|
const router = routers[i]
|
|
|
|
try {
|
|
|
|
routes.forEach((args) => {
|
|
|
|
router.add(...args)
|
|
|
|
})
|
|
|
|
res = router.match(method, path)
|
|
|
|
} catch (e) {
|
|
|
|
if (e instanceof UnsupportedPathError) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
throw e
|
|
|
|
}
|
|
|
|
|
|
|
|
this.match = router.match.bind(router)
|
|
|
|
this.routers = [router]
|
|
|
|
this.routes = undefined
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i === len) {
|
|
|
|
// not found
|
|
|
|
throw new Error('Fatal error')
|
|
|
|
}
|
|
|
|
|
2023-05-17 15:05:28 +00:00
|
|
|
// e.g. "SmartRouter + RegExpRouter"
|
|
|
|
this.name = `SmartRouter + ${this.activeRouter.name}`
|
|
|
|
|
2023-10-15 23:39:37 +00:00
|
|
|
return res as Result<T>
|
2022-09-12 11:49:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get activeRouter() {
|
|
|
|
if (this.routes || this.routers.length !== 1) {
|
|
|
|
throw new Error('No active router has been determined yet.')
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.routers[0]
|
|
|
|
}
|
|
|
|
}
|