@botonic/core
Version:
Build Chatbots using React
101 lines (93 loc) • 2.68 kB
text/typescript
import {
EMPTY_ACTION_PATH,
NOT_FOUND_PATH,
PATH_PAYLOAD_IDENTIFIER,
PATH_PAYLOAD_REGEXP,
} from '../constants'
import {
Action,
BotContext,
Input,
Params,
PathParams,
Route,
Routes,
} from '../models'
export class NoMatchingRouteError extends Error {
input: Input
constructor(input: Input) {
super(
`No route found for input '${JSON.stringify(
input
)}' and no ${NOT_FOUND_PATH} route defined`
)
this.input = input
}
}
export function isPathPayload(payload?: string): boolean {
if (!payload) return false
const isPathPayload = PATH_PAYLOAD_REGEXP.exec(payload)
return Boolean(isPathPayload)
}
export function getPathParamsFromPathPayload(payload?: string): PathParams {
const defaultPathParams = {
path: null,
params: {},
}
if (!payload) return defaultPathParams
if (!isPathPayload(payload)) return defaultPathParams
try {
const pathWithParams = payload.split(PATH_PAYLOAD_IDENTIFIER)[1]
if (!pathWithParams) {
throw `${PATH_PAYLOAD_IDENTIFIER} is empty`
}
const [path, params] = pathWithParams.split('?')
return { path: path ?? null, params: pathParamsToParams(params) }
} catch (e) {
console.error('Error getting path and params from input.payload:', e)
return defaultPathParams
}
}
export function pathParamsToParams(pathParams?: string): Params {
if (!pathParams) return {}
try {
const params = {}
const searchParams = new URLSearchParams(pathParams)
for (const [key, value] of searchParams) {
params[key] = value
}
return params
} catch (e) {
return {}
}
}
export function getEmptyAction(childRoutes?: Route[]): Action {
if (!childRoutes) return null
const emptyActionRoute = childRoutes.find(r => r.path === EMPTY_ACTION_PATH)
if (!emptyActionRoute) return null
return emptyActionRoute.action
}
export function getNotFoundAction(input: Input, routes: Route[]): Action {
const notFoundActionRoute = routes.find(r => r.path === NOT_FOUND_PATH)
if (!notFoundActionRoute) throw new NoMatchingRouteError(input)
return notFoundActionRoute.action
}
export async function getComputedRoutes(
routes: Routes,
botContext: BotContext
): Promise<Route[]> {
if (routes instanceof Function) {
return await getComputedRoutes(await routes(botContext), botContext)
}
for (const [key, route] of Object.entries(routes) as any) {
if (route.childRoutes && route.childRoutes instanceof Function) {
routes[key].childRoutes = await getComputedRoutes(
await route.childRoutes(botContext),
botContext
)
} else {
routes[key] = route
}
}
return routes
}