
Security News
Critical Security Vulnerability in React Server Components
React disclosed a CVSS 10.0 RCE in React Server Components and is advising users to upgrade affected packages and frameworks to patched versions now.
@ardentcode/omni-router
Advanced tools
Router library based on modern Navigation API
To install and build the router for production, please run following commands:
npm installnpm run buildFor development, you can use:
npm run watchThe library uses following browser features. If you want to use it in older browsers, you should include polyfills on your own. Server side already includes the polyfills.
Router is an entity that manages application routing. It allows you to register routes, that will be automatically handled.
Route is a representation of route that have name, path, params and optionally data.
It can be in handled state (when data is available) or not (when data is null).
Route declaration is description of how the routing should look like.
It describes followings fields: name, path (pattern) and handler.
Route handler is a function that is executed when route is being opened.
It receives params as argument and returns data, which is assigned to the route.
Handlers can also be lazy loaded.
Route processor is an object with optional listener methods, which can be executed on specific router actions.
There are 7 available listeners so far:
onGetRouteStart, onGetRouteEnd, onOpenRouteStart, onOpenRouteEnd, onOpenRouteSuccess, onOpenRouteError, onOpenRouteAbort
It's used for processing data returned in handlers, so that repetitive actions can be achieved for all specific routes.
You need to define two types:
interface RoutesMap {
home: HomeRouteParams;
post: PostRouteParams;
}
interface RoutesData extends HTMLRouteData, RedirectRouteData {
}
const router = createRouter<RoutesMap, RoutesData>();
To register route you only need to specify three properties: name, path and handler.
router.registerRoute({
name: 'home',
path: '/',
handler: async (params: HomeRouteParams) => {
return {
// ...
};
}
});
Route handler should only return data for further processing.
It shouldn't perform any visible action to the user.
Route parameters are passed as a first argument.
Object containing router and abort signal is passed as a second parameter.
async function homeRouteHandler(params: HomeRouteParams, info: RouteInfo): Promise<HTMLRouteData> {
const homeData = await homeApi.getData();
return {
html: {
content: renderHomePage(homeData)
}
};
}
You can find the route by its name or path:
homeRoute = router.getRouteByName('home');
homeRoute = router.getRouteByPath('/');
Now you can use it in anchors (route is automatically serialized to its path when used as string):
<a href={homeRoute.path}/>Home</a>
<a href={homeRoute}/>Home</a>
Remember that this way you get unhandled route (without data), because data is only available after opening the route.
You can open the route programmatically. You will get the handled route (with data).
await router.openRouteByName('home');
await router.openRouteByPath('/');
There are 3 types of parameters:
All parameters are strings. If you want to use them as numbers, remember to parse them firstly.
Named parameters are parameters that are defined in path pattern with ":" prefix:
interface PostsParams {
page: string;
}
router.registerRoute({
name: 'posts',
path: '/posts/:page',
handler: /* ... */
});
router.getRouteByName('posts', {page: '1'});
// {name: 'posts', path: '/posts/1', params: {page: '1'}}
Query parameters are additional parameters which are not defined in path pattern:
interface PostsParams {
page: string;
}
router.registerRoute({
name: 'posts',
path: '/posts',
handler: /* ... */
});
router.getRouteByName('posts', {page: '1'});
// {name: 'posts', path: '/posts?page=1', params: {page: '1'}}
Wildcard parameters are like named parameters, but instead of a name, they have just a number assigned (starting with 0):
interface PostsParams {
page: string;
}
router.registerRoute({
name: 'posts',
path: '/posts/*',
handler: /* ... */
});
router.getRouteByName('posts', {0: '1'});
// {name: 'posts', path: '/posts/1', params: {page: '1'}}
You can define a fallback page (404 not found) with wildcard, but you have to register it as the last one:
router.registerRoute({
name: 'not-found',
path: '/*',
handler: /* ... */
});
HTML processor injects HTML into specified elements.
By default, there is content property, which is injected into element with id rootId.
You can also define additional fragments, which you want to inject HTML into.
Please check the examples:
<body>
<header id="app-header"></header>
<main id="app-main"></main>
</body>
createHTMLRouteProcessor({
rootId: 'app-main',
fragmentsIds: {
header: 'app-header'
},
renderHTML: (html) => `<div class="wrapper>{html}</div>`,
renderError: (error) => `<div class="error">Error</div>`
})
async function homeRouteHandler(params: HomeRouteParams): Promise<HTMLRouteData> {
return {
html: {
content: `<p>Hello World!</p>`,
fragments: {
header: `Home`
}
}
};
}
Redirect processor opens new route with history mode replace, so previous page is not available in browser history.
createRedirectRouteProcessor()
async function firstPostRouteHandler(): Promise<RedirectRouteData> {
const firstPost = await postApi.getPosts({limit: 1})[0];
return {
redirect: {
path: '/post/' + firstPost.id
}
};
}
Meta processor sets page metadata like title, description, keywords, etc.
createMetaRouteProcessor({
modifier: (name, content) => {
if (name === 'title') {
return `${content} - MyApp`;
}
return content;
},
defaults: {
title: 'MyApp'
}
})
async function homeRouteHandler(params: HomeRouteParams): Promise<MetaRouteData> {
return {
meta: {
title: 'Home Page',
description: 'Home Page of MyApp'
}
};
}
You can create you own processors. There are 7 available methods so far:
onGetRouteStartonGetRouteEndonOpenRouteStartonOpenRouteEndonOpenRouteSuccessonOpenRouteErroronOpenRouteAbortinterface BodyClassRouteData {
bodyClass: string;
}
function createBodyClassRouteProcessor(): RouteProcessor<BodyClassRouteData> {
return {
onOpenRouteSuccess: async ({route}) => {
document.body.className = route.data.bodyClass ?? '';
}
};
}
async function homeRouteHandler(params: HomeRouteParams): Promise<BodyClassRouteData> {
return {
bodyClass: 'home'
};
}
FAQs
Router library based on modern navigation-api
We found that @ardentcode/omni-router demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 5 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
React disclosed a CVSS 10.0 RCE in React Server Components and is advising users to upgrade affected packages and frameworks to patched versions now.

Research
/Security News
We spotted a wave of auto-generated “elf-*” npm packages published every two minutes from new accounts, with simple malware variants and early takedowns underway.

Security News
TypeScript 6.0 will be the last JavaScript-based major release, as the project shifts to the TypeScript 7 native toolchain with major build speedups.