UNPKG

@beignet/core

Version:

Core framework primitives for Beignet

65 lines (56 loc) 1.61 kB
import { parsePathTemplate } from "../contracts/index.js"; export type CompiledPath = { keys: string[]; pattern: RegExp; segments: ReturnType<typeof parsePathTemplate>["segments"]; normalizedPath: string; shapeKey: string; }; export class PathDecodeError extends Error { constructor() { super("Malformed URL path"); this.name = "PathDecodeError"; } } export function compilePath(path: string): CompiledPath { const parsed = parsePathTemplate(path); const regexParts = parsed.segments.map((segment) => segment.kind === "dynamic" ? "([^/]+)" : segment.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), ); const pattern = new RegExp(`^/${regexParts.join("/")}$`); return { ...parsed, pattern }; } export function decodeMatchedParams( keys: string[], match: RegExpExecArray, ): Record<string, string> { const params: Record<string, string> = {}; try { keys.forEach((key, index) => { params[key] = decodeURIComponent(match[index + 1]); }); } catch (error) { if (error instanceof URIError) { throw new PathDecodeError(); } throw error; } return params; } export function compareRouteSpecificity( a: CompiledPath, b: CompiledPath, ): number { const maxLength = Math.max(a.segments.length, b.segments.length); for (let index = 0; index < maxLength; index++) { const aSegment = a.segments[index]; const bSegment = b.segments[index]; if (!aSegment) return 1; if (!bSegment) return -1; if (aSegment.kind === bSegment.kind) continue; return aSegment.kind === "static" ? -1 : 1; } return 0; }