@tscircuit/routematch
v1.0.1
Published
TypeScript route matcher with Next.js-style dynamic routes
Maintainers
Readme
@tscircuit/routematch
A TypeScript route matcher with Next.js-style dynamic routes
Features
- Next.js-style dynamic routes (
[id],[...slug],[[optional]]) - Server-side and client-side compatible
- TypeScript support with full type safety
- Zero dependencies
- High performance route matching with priority sorting
- URL decoding support
- Comprehensive test coverage
Installation
bun install @tscircuit/routematchQuick Start
import createRouteMatcher from '@tscircuit/routematch'
const routeMatcher = createRouteMatcher([
'/health',
'/api/users/[id]',
'/api/posts/[...slug]',
'/blog/[[...path]]'
])
// Match routes
const result = routeMatcher('/api/users/123')
// { matchedRoute: '/api/users/[id]', routeParams: { id: '123' } }
const catchAll = routeMatcher('/api/posts/2023/hello-world')
// { matchedRoute: '/api/posts/[...slug]', routeParams: { slug: ['2023', 'hello-world'] } }Route Patterns
Static Routes
'/about'
'/api/health'Dynamic Routes
'/users/[id]' // matches /users/123
'/posts/[slug]' // matches /posts/hello-worldCatch-all Routes
'/api/[...path]' // matches /api/v1/users/123
'/docs/[...slug]' // matches /docs/getting-started/installationOptional Routes
'/blog/[[...slug]]' // matches /blog and /blog/category/postAPI Reference
createRouteMatcher(routes: string[])
Creates a route matcher function from an array of route patterns.
Parameters:
routes: Array of route pattern strings
Returns: A matcher function that takes a path and returns a match result or null
Example:
const matcher = createRouteMatcher(['/api/[id]', '/health'])
const result = matcher('/api/123') // { matchedRoute: '/api/[id]', routeParams: { id: '123' } }isValidRoute(route: string): boolean
Validates if a route pattern is syntactically correct.
isValidRoute('/api/[id]') // true
isValidRoute('/api/[...slug]') // truegetRouteParameters(route: string): string[]
Extracts parameter names from a route pattern.
getRouteParameters('/api/[id]/posts/[slug]') // ['id', 'slug']
getRouteParameters('/docs/[...path]') // ['path']Route Priority
Routes are matched in priority order:
- Exact matches (highest priority)
- Fewer parameters (higher priority)
- Catch-all routes (lowest priority)
const matcher = createRouteMatcher([
'/api/[id]/[action]', // Lower priority (2 params)
'/api/[id]/edit', // Higher priority (1 param + exact)
'/api/users' // Highest priority (exact match)
])Development
Build
bun run buildTest
bun testDevelopment with Hot Reload
bun --hot lib/index.tsExamples
Basic Web Server
import { serve } from 'bun'
import createRouteMatcher from '@tscircuit/routematch'
const routeMatcher = createRouteMatcher([
'/',
'/api/users/[id]',
'/api/posts/[...slug]'
])
serve({
port: 3000,
fetch(request) {
const url = new URL(request.url)
const match = routeMatcher(url.pathname)
if (!match) {
return new Response('Not Found', { status: 404 })
}
return new Response(JSON.stringify(match))
}
})Express-like Router
import createRouteMatcher from '@tscircuit/routematch'
const routes = {
'/': () => 'Home',
'/users/[id]': ({ id }) => `User: ${id}`,
'/posts/[...slug]': ({ slug }) => `Post: ${slug.join('/')}`
}
const routeMatcher = createRouteMatcher(Object.keys(routes))
function handleRequest(path: string) {
const match = routeMatcher(path)
if (match) {
const handler = routes[match.matchedRoute]
return handler(match.routeParams)
}
return 'Not Found'
}License
MIT
