1.1.0 • Published 2 months ago

@sigiljs/pathfinder v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 months ago

Pathfinder HTTP Router

Pathfinder is a lightweight (~4.0kb), high‑performance HTTP router for Node.js and browsers, written in TypeScript. It delivers sub‑microsecond route resolution by combining O(1) lookups for static routes with a compact trie for parameterized paths.

An optional LRU cache accelerates repeated requests, and you can mount child routers under any base path using delegate or copy strategies — all with zero external dependencies.

import Pathfinder, { MountStrategy } from "@kurai-io/pathfinder"

const router = new Pathfinder()

router.register("GET", "/", () => ({ message: "Hello!" }))
router.register("GET", "/users/:id", ({ params }) => ({ id: params.id }))

const match = router.lookup("GET", "/users/42")
if (match) {
  const { handler, params } = match
  console.log(handler({ params })) // → { id: "42" }
}

// Mount another router under '/v2'
const v2 = new Pathfinder()
v2.register("GET", "/items", () => [1, 2, 3])
router.mount("/v2", v2, MountStrategy.Copy)

Mount Strategies

Delegate

Attaches a reference to a child Pathfinder at a single node in the trie. Incoming requests that match the mount prefix are forwarded (lookup) into the child router, preserving its own routing tables and cache. This uses minimal memory but incurs an extra function call per mount.

Copy

Walks through all routes of the child router via exportRoutes() and re-registers them under the parent’s trie with the mount prefix prepended. This yields faster lookups (no delegation overhead) but duplicates route entries and increases memory use.

Internal Principles

Static route table: a plain-object map from trimmed path strings to handlers for constant-time O(1) dispatch.

LRU Cache: recent lookup(pathRaw) results (handler + params) are cached in insertion order map; on cache hit, the entry is moved to the end. When capacity is exceeded, the oldest is evicted.

Trie traversal: if no static or cache hit, the router walks a prefix tree (children for static segments, single paramChild for dynamic segments) in one pass over the URL segments, collecting parameter values on the way. Mounted routers are invoked if encountered mid-traversal.

Benchmark Comparison

Following benchmarks where taken under Node v24.0.2, on an Apple MacBook Pro M4 Pro 14C and represents operations per second for each routing type and framework.

Benchmark is not an indicator that any framework is worse or better. Any framework that can perform >1M ops/s already fits most modern production projects, and you will hardly see a difference between 1M and 10M ops/s

Benchmarkpathfinderhono (node)koa-tree-routerfind-my-way
Short static174,821,861109,583,13869,474,23649,879,976
Static (same radix)175,252,326123,069,72829,058,94115,376,204
Dynamic158,388,86919,463,35314,016,8076,034,499
Mixed161,300,51021,616,37116,510,8557,738,542
Long static148,986,703123,865,98230,311,28916,897,184
Wildcard156,484,92835,454,29818,744,64910,537,618
All together8,946,4726,586,9993,484,4851,762,148

Original benchmark code by Tomas Della Vedova available at https://github.com/delvedor/router-benchmark

Note: this benchmark is not the same benchmark available in the benchmarks folder

License

You can copy and paste the MIT license summary from below.

MIT License

Copyright (c) 2022-2025 Kurai Foundation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
1.1.0

2 months ago

1.0.3

2 months ago