@iopa/router
Version:
Lightweight and fast router for IOPA applications
63 lines (50 loc) • 1.73 kB
text/typescript
/* eslint-disable @rushstack/security/no-unsafe-regexp */
import type { ParamMap, IRouterContext } from './node'
import { Node } from './node'
export type { ParamMap } from './node'
export type ReplacementMap = number[]
interface IInitOptions {
reverse: boolean
}
export class Trie {
public context: IRouterContext = { varIndex: 0 }
public root: Node
public constructor({ reverse }: IInitOptions = { reverse: false }) {
this.root = new Node({ reverse })
}
public insert(path: string, index: number): ParamMap {
const paramMap: ParamMap = []
/**
* - pattern (:label, :label{0-9]+}, ...)
* - /* wildcard
* - character
*/
const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.root.insert(tokens, index, paramMap, this.context)
return paramMap
}
public buildRegExp(): [RegExp, ReplacementMap, ReplacementMap] {
let regexp = this.root.buildRegExpStr()
let captureIndex = 0
const indexReplacementMap: ReplacementMap = []
const paramReplacementMap: ReplacementMap = []
regexp = regexp.replace(
/#(\d+)|@(\d+)|\.\*\$/g,
// eslint-disable-next-line @typescript-eslint/naming-convention
(_, handlerIndex, paramIndex) => {
if (typeof handlerIndex !== 'undefined') {
indexReplacementMap[++captureIndex] = Number(handlerIndex)
return '$()'
}
if (typeof paramIndex !== 'undefined') {
paramReplacementMap[Number(paramIndex)] = ++captureIndex
return ''
}
return ''
}
)
return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap]
}
}