Security News
38% of CISOs Fear Theyβre Not Moving Fast Enough on AI
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
@wbe/low-router
Advanced tools
LowRouter
is a lightweight (~=1.8Kb), low-level router implementation designed for use in nodejs, javascript or typescript applications. By default, LowRouter
has no link with the browser history, but this repository provide a createBrowserHistory
util ready to use. It also includes a createMatcher
function to convert a route path to a regular expression, but still open to use a custom one.
The examples of this repo are available on codesandbox:
npm i @wbe/low-router
import { LowRouter } from "@wbe/low-router"
const routes = [
{
path: "/",
name: "home",
action: () => "Hello home!",
},
{
path: "/admin",
name: "admin",
action: () => "Hello admin!",
children: [
{
path: "/config",
name: "config",
action: (context) => `Hello ${context.route.name}!`,
},
{
path: "/user/:id",
name: "user",
action: (context) => `Hello user! with id ${context.params.id}`,
},
],
},
]
const router = new LowRouter(routes)
The resolve
method allows you to match a given pathname or route object to a defined route and execute its associated action. It returns a Promise that resolves with the action result and route context.
router.resolve("/").then(({ response, context }) => {
// response: "Hello home!"
})
Or, with an object param:
router.resolve({ name: "user", params: { id: 123 } }).then(({ response, context }) => {
// response: "Hello user! with id 123"
})
The resolveSync
method is the same than resolve, but synchronously. It returns the action result and route context directly.
const { response, context } = router.resolveSync("/admin/config")
// response: "Hello home!"
Or, with an object param:
const { response, context } = router.resolveSync({ name: "user", params: { id: 123 } })
// response: "Hello user! with id 123"
The createUrl
method generates a URL based on a route name and optional parameters.
router.createUrl({ name: "config" })
// "/admin/config"
The dispose
method is used to clean up the router instance.
router.dispose()
Internal createBrowserHistory
provide a way to interact with the browser's history and listen to changes in the URL. You can integrate this functionality with the LowRouter
class to enable client-side routing with browser history support.
import { LowRouter, createBrowserHistory } from "@wbe/low-router"
const router = new LowRouter(routes, options)
const history = createBrowserHistory()
const unlisten = history.listen(async ({ location, action }) => {
const response = await router.resolve(location.pathname)
// Do something with the response...
})
// Push to the browser history will trigger the router resolve method
history.push("/foo")
history.push(router.createUrl({ name: "bar", params: { id: 123 } }))
// Stop listening to history changes
unlisten()
On the same way, you can use every history lib you want to handle history changes, and resolve the new pathname with the router, like remix-run/history.
The matcher
is the function used to convert a route path to a regular expression. By default, LowRouter
use an internal matcher function. this matcher is called when the resolve method is called. You shouldn't have to use this function directly, but it's interesting to understand how it works, specially if you need to use a custom one.
import { createMatcher } from "@wbe/low-router"
const matcher = createMatcher()
const [isMatch, routeParams, queryParams, hash] = matcher(
"/user/1?lang=fr&cat=foo#section-2",
"/user/:id"
)
// isMatch: true
// routeParams: { id: "1" }
// queryParams: { lang: "fr", cat: "foo" }
// hash: "section-2"
This returns values are returned by RouteContext
when the route match. For more information about the matcher full matcher API, read the createMatcher unit tests.
If the internal matcher doesn't respond as needed, it's possible to use a custom matcher function: like the original path-to-regexp package.
import { LowRouter, createMatcher } from "@wbe/low-router"
import { pathToRegexp } from "path-to-regexp"
const customPathToRegexpFn = (path: string): { keys: Record<string, string>[]; regexp: RegExp } => {
let keys = []
const regexp = pathToRegexp(path, keys)
return { keys, regexp }
}
const customMatcher = createMatcher(customPathToRegexpFn)
// ex: customMatcher("/about/:id", "/about/1")
// return: [true, { id: "1" }, {}, null]
// then, pass this customMatcher to the router options
// Now, the router will use this custom matcher with path-to-regexp to match routes
const router = new LowRouter(routes, { matcher: customMatcher })
This flexible custom matcher pattern as been created by molefrog on wouter π
@wbe/debug tool is used as dependency in this project. To enable debug logs, you can use the following commands:
Browser debug:
localStorage.debug = "low-router:*"
Node debug:
DEBUG=low-router:*
// LowRouter(routes: Route[], options?: Options)
const router = new LowRouter(routes, options)
// Resolve a pathname or a route object
// resolve(pathnameOrObject: string | { name: string; params?: RouteParams })
router.resolve(path)
router.resolve({ name: "", params: {} })
// Resolve synchronously
// resolveSync(pathnameOrObject: string | { name: string; params?: RouteParams })
router.resolveSync(path)
router.resolveSync({ name: "", params: {} })
// Create a URL based on a route name and optional parameters
// createUrl({ name: string; params?: RouteParams }): string
router.createUrl({ name: "", params: {} })
// Clean up the router instance
// dispose(): void
router.dispose()
const options: Options = {
// The base URL path for all routes.
// default: `/`.
base: "/",
// called when the router is initialized
// onInit: () => void
onInit: () => {},
// called when no matching route is found during resolution
// onError: () => void
onError: (context, error) => {},
// called after a route's action has been executed successfully
// onResolve: ({response: ActionResponse<A>, context: RouteContext<A, P>}) => void
onResolve: ({ response, context }) => {},
// called when the router is disposed of using the `dispose` method
// onDispose: () => void
onDispose: () => {},
// Custom function to convert a route path to a regular expression.
// Default: the internal `createMatcher()` fn
// matcher: Matcher
matcher: createMatcher(),
// give an id to the router instance, useful when you have multiple router instances
// and you want to identify them from debug logs
// id?: number | string
id: 1,
}
RouteContext
is the 1st level route object, passed to the route action function.
It contains all the information about the current context, plus the route object itself.
interface RouteContext {
// The current pathname
pathname: string
// The current path params
// (ex: /:foo/:bar)
params: RouteParams
// The current query params
// (ex: ?foo=bar&baz=qux)
query: QueryParams
// The current hash
// (ex: #foo)
hash: Hash
// the route base URL
base: string
// β the route object associated to this context
route: Route
// parent route context, useful when the current is a child route
parent: RouteContext | null
}
Route
is the route object definition passed to the LowRouter
constructor, define by the developer.
interface Route {
// The route path
// (ex: /foo/:bar)
path: string
// The route name, useful to get a route by name
name?: string
// The route action function is the main function of the route
// this function is called when the route is resolved
action?: (context: RouteContext) => Promise<any> | any
// The route children
children?: Route[]
// The route props can be any data you want to pass/associate to the route
props?: Record<string, any>
}
createBrowserHistory()
will return an object:
export interface HistoryAPI {
// associate a callback to the history change event
// return a function to stop listening
listen: (callback: ({ location, action }) => void) => () => void
// Push a new patname to the history
push: (pathname: string) => void
}
# clone repo
git clone {repo}
# install all dependencies
pnpm i
# run build watch
pnpm run build:watch
# run test watch
pnpm run test:watch
# run examples dev server
pnpm run dev
This project is inspired by the following projects:
FAQs
low-router πβ <img al
We found that @wbe/low-router demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.
Security News
Company News
Socket is joining TC54 to help develop standards for software supply chain security, contributing to the evolution of SBOMs, CycloneDX, and Package URL specifications.