1.2.8 • Published yesterday
@anchorlib/router
Licence
MIT
Version
1.2.8
Deps
0
Size
108 kB
Vulns
0
Weekly
0
@anchorlib/router
A type-safe, reactive router for JavaScript and TypeScript applications. Part of the Anchor library ecosystem.
Features
- Type-Safe Routing - Full TypeScript support with automatic type inference for route parameters and query strings
- Nested Routes - Build hierarchical route structures with parent-child relationships
- Route Guards - Protect routes with authentication and authorization checks
- Data Providers - Load data asynchronously when routes activate
- Smart Caching - LRU cache for URL matching with time-based expiration for provider data
- Reactive - Integrates with
@anchorlib/corefor reactive state management - Preloading - Prefetch route data before navigation for instant transitions
- Redirects - Declarative redirect handling with guard integration
Installation
npm install @anchorlib/router
# or
bun add @anchorlib/router
Quick Start
import { createRouter, redirect } from '@anchorlib/router';
// Create a router instance
const router = createRouter({ baseUrl: 'https://example.com' });
// Define routes
const homeRoute = router.route('/');
const usersRoute = router.route('/users');
const userRoute = usersRoute.route('/:id');
// Add guards for authentication
userRoute.guard(async ({ params }) => {
if (!await isAuthenticated()) {
throw redirect(loginRoute);
}
});
// Add data providers
userRoute.provide('user', async ({ params }) => {
return await fetchUser(params.id);
});
// Activate a route
await router.activate('/users/123');
// Access active route data
console.log(router.data.user);
console.log(router.params.id); // '123'
console.log(router.path); // 'users/:id'
API Reference
Router
The main router class for managing routes and navigation.
import { Router, createRouter } from '@anchorlib/router';
// Create via constructor
const router = new Router({
baseUrl: 'https://example.com',
cacheSize: 100,
maxAge: 60000
});
// Or use the factory function
const router = createRouter({ baseUrl: 'https://example.com' });
Router Methods
| Method | Description |
|---|---|
route(path, options?) |
Creates a new route at the given path |
find(url) |
Finds a matching route for the given URL |
activate(url) |
Activates the route matching the URL |
deactivate() |
Deactivates all currently active routes |
preload(url) |
Preloads route data without activating |
Router Properties
| Property | Description |
|---|---|
activeRoute |
The currently active route |
activeContext |
Shared context with params, query, and data |
activeSegments |
Array of active route segments |
path |
The active route's path |
data |
The active route's loaded data |
query |
The active route's query parameters |
params |
The active route's path parameters |
Route
Represents a single route with guards, providers, and nested routes.
// Create nested routes
const usersRoute = router.route('/users');
const userRoute = usersRoute.route('/:id');
const postsRoute = userRoute.route('/posts');
// Index routes
const indexRoute = usersRoute.route('/'); // Matches '/users' exactly
Route Methods
| Method | Description |
|---|---|
route(path, options?) |
Creates a child route |
guard(handler) |
Adds a navigation guard |
provide(name, provider, options?) |
Adds a data provider |
url(params?, query?) |
Generates a URL for this route |
preload(context) |
Preloads route data |
authenticate(context) |
Runs all guards |
Route Properties
| Property | Description |
|---|---|
active |
Whether the route is currently active |
data |
Loaded data for this route |
params |
Route parameters (when active) |
query |
Query parameters (when active) |
path |
Full path including parent paths |
name |
Route segment name |
type |
Route type (static, dynamic, wildcard) |
Route Types
Routes are automatically classified by their path pattern:
import { ROUTE_TYPE } from '@anchorlib/router';
// Static route - fixed path
router.route('/users'); // type: ROUTE_TYPE.STATIC
// Dynamic route - parameterized
router.route('/:id'); // type: ROUTE_TYPE.DYNAMIC
// Wildcard route - catches all remaining segments
router.route('/*'); // type: ROUTE_TYPE.WILDCARD
Guards
Guards protect routes from unauthorized access. Throw a Redirect or Error to block navigation.
import { redirect } from '@anchorlib/router';
route.guard(async ({ params, query }) => {
// Check authentication
if (!await isAuthenticated()) {
throw redirect(loginRoute, { returnTo: router.activeRoute?.path });
}
// Check authorization
if (!hasPermission(params.id)) {
throw new Error('Access denied');
}
});
Data Providers
Providers load data when routes activate. Data is available in the active context.
// Simple provider
route.provide('user', async ({ params }) => {
return await fetchUser(params.id);
});
// With caching and retry options
route.provide('posts', async ({ params }) => {
return await fetchPosts(params.id);
}, {
maxAge: 30000, // Cache for 30 seconds
retries: 3, // Retry 3 times on failure
retryDelay: 1000 // Wait 1s between retries
});
Redirects
Create redirects to navigate programmatically or from guards.
import { redirect, redirectUrl, setRedirectHandler } from '@anchorlib/router';
// Create a redirect
const r = redirect(loginRoute, { returnTo: '/dashboard' });
// Get the redirect URL
const url = redirectUrl(r); // '/login?returnTo=/dashboard'
// Set up redirect handling
setRedirectHandler((redirect) => {
window.location.href = redirectUrl(redirect);
});
// Use in guards
route.guard(async () => {
if (!isAuthenticated()) {
throw redirect(loginRoute);
}
});
Caching
The router includes two caching mechanisms:
- URL Cache - LRU cache for matched routes (configurable size)
- Provider Cache - Time-based expiration for provider data
const router = createRouter({
cacheSize: 100, // Max 100 URLs cached
maxAge: 60000 // Provider data cached for 60s
});
Type Inference
The router provides full type inference for parameters:
// Path params are automatically typed
const userRoute = usersRoute.route('/:id');
// params: { id: string }
const postRoute = userRoute.route('/posts/:postId');
// params: { id: string, postId: string }
// Query params can be typed in the path
const searchRoute = router.route('/search?q(string)&page(number)');
// query: { q?: string, page?: number }
// Provider data is accumulated
userRoute.provide('user', async ({ params }) => {
return { name: 'John', email: 'john@example.com' };
});
// data: { user: { name: string, email: string } }
Scripts
| Script | Description |
|---|---|
dev |
Start development mode with watch |
build |
Build for production |
test |
Run tests with Vitest |
test:preview |
Run tests and preview coverage |
format |
Format code with Biome |
License
MIT