{"_id":"@ardentcode/omni-router","_rev":"7-f1951006062b380e4b98c1347eaa8b15","name":"@ardentcode/omni-router","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@ardentcode/omni-router","version":"0.1.0","author":{"url":"https://ardentcode.com/","name":"ArdentCode","email":"ardentcode@ardentcode.com"},"license":"CC0-1.0","_id":"@ardentcode/omni-router@0.1.0","maintainers":[{"name":"andrzeem90","email":"emil.andrzejewski@gmail.com"},{"name":"lukjaki","email":"l.jakimow@gmail.com"},{"name":"majo44","email":"majo44@gmail.com"},{"name":"krzysztof-cislo","email":"krzysztof.cislo@gmail.com"},{"name":"ownelek","email":"ownelek@protonmail.com"}],"homepage":"https://github.com/ardentcode/omni-router/blob/main/packages/omni-router/README.md","bugs":{"url":"https://github.com/ardentcode/omni-router/issues"},"dist":{"shasum":"d0fe7adcbb447e0cdb3dde7794c2f63bbdaef322","tarball":"https://registry.npmjs.org/@ardentcode/omni-router/-/omni-router-0.1.0.tgz","fileCount":45,"integrity":"sha512-rfYD9cesUXf1vbE1yR3XENlXz0SottE/NLqOKQXN8/9FuKmkdN6GBsLfvADG5Yb6FbEQuBTzb5dNbKbnWaHHlQ==","signatures":[{"sig":"MEYCIQDKGQ8kaqvgfo6AT28QHYWpY3s52tijcS4FL4r+QDMOkQIhAIhJ2N2rEQ/BqFoSWcvKBieBKaUzAGKP7T/RXMMZjwUa","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":75548,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjUqdCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq0YhAAjbf6gXpqQ4U60/sVAXb1eavLeF/M7w6qEAPNCXoJqcOeJ39Z\r\nWAMvBD1+G646PuLqqHo2hdD8P89AZUXJ8Qqdas0XwNOaKeAJfCzwkzLyBv64\r\n03j8PvJyt1DbeK8thi6r92O7MmXty1WbCPNaTCKeUAzhG1y6hUbtTvXQBTdT\r\nX48mm8YMNFNEN44t1mxJG5r+hi+OWvFMZGr9xZonmxyxQuobA8alwfqb2tAP\r\n+4mXoIbsYkAvp2+lbiu3w/nwkbm4+eut6KsBdgPQI/mapArKUE4qxTSeJIl6\r\nFpMRe5w7YO30Q+Li7LkSVHFO+cIavrTkJBVfqC/iZyMZ7Dw5/Nx3FwgByymZ\r\n9WX59NDVLQ4qYhG9vFzKmM1jIS4l2AfoIs9sTPHXRmu6n/ms/DTpViLTkuZa\r\n6Brm3Z0Gj36KHSxu86HoH6MtTzCnh7s1fsexFRS8OJ4Yidc48mySQNaD5KtR\r\nRPfdZqlJuRpFuVNLDnULU+8lxbGovk25SQS+kNsI6CuyKcg1i6DLVcU2n4V1\r\n0GizkTga39T5BK4zzE35EPZrqnfcHG44i+e6PDpFE2NPfnUP+1CmWtTpUP0N\r\nxzuRruU+oVYJ/ma9GWFGMInUl3uefsXOyEtvEhBLjeLewB1EBeWMrOjpEH9L\r\nJm3Vbt5lhiA+sTI5lJqq+a7qdfczl+qyXUk=\r\n=ILr6\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"transform":{"^.+\\.(ts|tsx)$":"ts-jest"},"setupFiles":["<rootDir>/src/polyfills.ts"],"moduleFileExtensions":["js","ts","tsx"]},"main":"dist/index.server.js","types":"dist/types/index.server.d.ts","browser":"dist/index.client.js","gitHead":"0490e93970ab0a8a7fb4d95436d0cb7b54b9398b","scripts":{"test":"jest","build":"node node_modules/webpack/bin/webpack.js --progress --mode=production","clean":"rimraf ./dist","watch":"node node_modules/webpack/bin/webpack.js --progress --mode=development --watch","test:coverage":"jest --coverage"},"_npmUser":{"name":"andrzeem90","email":"emil.andrzejewski@gmail.com"},"repository":{"url":"git+https://github.com/ardentcode/omni-router.git","type":"git"},"_npmVersion":"8.5.4","description":"Router library based on modern navigation-api","directories":{},"_nodeVersion":"16.14.1","dependencies":{"abort-controller":"^3.0.0","urlpattern-polyfill":"^6.0.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.1.2","rimraf":"^3.0.2","ts-jest":"^29.0.3","webpack":"^5.74.0","ts-loader":"^9.4.1","typescript":"^4.8.3","@types/jest":"^29.1.1","webpack-cli":"^4.10.0","@types/react":"^18.0.21","@types/react-dom":"^18.0.6"},"_npmOperationalInternal":{"tmp":"tmp/omni-router_0.1.0_1666361154487_0.31744752302691026","host":"s3://npm-registry-packages"}},"0.1.1":{"name":"@ardentcode/omni-router","version":"0.1.1","author":{"url":"https://ardentcode.com/","name":"ArdentCode","email":"ardentcode@ardentcode.com"},"license":"CC0-1.0","_id":"@ardentcode/omni-router@0.1.1","maintainers":[{"name":"andrzeem90","email":"emil.andrzejewski@gmail.com"},{"name":"lukjaki","email":"l.jakimow@gmail.com"},{"name":"majo44","email":"majo44@gmail.com"},{"name":"krzysztof-cislo","email":"krzysztof.cislo@gmail.com"},{"name":"ownelek","email":"ownelek@protonmail.com"}],"homepage":"https://github.com/ardentcode/omni-router/tree/main/packages/omni-router","bugs":{"url":"https://github.com/ardentcode/omni-router/issues"},"dist":{"shasum":"34d0e283f193907fdea276fc80dd56aba1032a1a","tarball":"https://registry.npmjs.org/@ardentcode/omni-router/-/omni-router-0.1.1.tgz","fileCount":45,"integrity":"sha512-EhqUEo47pU54dPaenwqNgwQtHu1A9bZHiT7G5dE6sphDbpWwgEDIvQC0fzwBn8aA9nspgigcDtyGoIVRwO2FXA==","signatures":[{"sig":"MEUCIFlFm2r4xYWOO0XE0RHi8VD45zp8jR8x/N2nIwZEmjxVAiEAurMBG4BELDrcx2j3yil6u9nx/MC0ETEU5V6oaHqsbz0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":75538,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjUqoeACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrnBw//Xn4wfrG2h2i/fOj4F27fsE5SAw8s3VVNfjdzLxv59uj623qz\r\n4X3SJpcl9tbciCKNp0/GIYlwEWs8U4ltSmIgN57ASJFRV0/jWCcx1hQLzkDb\r\nC7wjAqGIXoB0dqpBED69gOGd3wwy+AZv4fw0cerDcPCDH4uw8HdZWqSFj8jr\r\nqbGCA3TcCbBUCp/oMhaXpARCRryWuPCwvVcukLtHVAPU7l+xHoFz+3PC+Eei\r\ngbM8NcCsvAGSiTT28y0rp7J6xX2gsiSm/6wmvNKV2RCXK4gM1eQUVSspFkt+\r\nhBWFFHXUw8SBN5wzYf3X6jsnOcRxodIWj80jJciBPKiIgKGKaSy0GPdsaQco\r\nx34y0HPCWYuicwBjEWR4tJXpqOFm1eJJLYPJRMgkju1fWQv+2gIZaj8mE4uG\r\n1TK/OqdSPT8VDu+nEma0GPFdFiPRikAaY1eq6Ne5zkmamq4GOnNw2vDqo63W\r\ncoyAfZ6FYCz4Ua5PXF315Qw8Ew/VVVgQBzg2RxDNQZpmojuxgqJZW36GlhVH\r\n9gKB1KxNh6HRjdLcs1fDZKUPsSfP0tEzJG679f4rQ1dViu+2rsfj49FZaxX9\r\nXj73wafiqx1Ew+4MXLVpuQ8wvit1ddAXNjVEuPgxY2VDd7zhnXA/n1eBiVFY\r\n7cmefgX10M7cs8Fu0joxmyVYw137uE7DvnA=\r\n=eu8Z\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"transform":{"^.+\\.(ts|tsx)$":"ts-jest"},"setupFiles":["<rootDir>/src/polyfills.ts"],"moduleFileExtensions":["js","ts","tsx"]},"main":"dist/index.server.js","types":"dist/types/index.server.d.ts","browser":"dist/index.client.js","gitHead":"e9e0c32cc4d98a9243f6b0a1b0ed7561735e196d","scripts":{"test":"jest","build":"node node_modules/webpack/bin/webpack.js --progress --mode=production","clean":"rimraf ./dist","watch":"node node_modules/webpack/bin/webpack.js --progress --mode=development --watch","test:coverage":"jest --coverage"},"_npmUser":{"name":"andrzeem90","email":"emil.andrzejewski@gmail.com"},"repository":{"url":"git+https://github.com/ardentcode/omni-router.git","type":"git"},"_npmVersion":"8.5.4","description":"Router library based on modern navigation-api","directories":{},"_nodeVersion":"16.14.1","dependencies":{"abort-controller":"^3.0.0","urlpattern-polyfill":"^6.0.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.1.2","rimraf":"^3.0.2","ts-jest":"^29.0.3","webpack":"^5.74.0","ts-loader":"^9.4.1","typescript":"^4.8.3","@types/jest":"^29.1.1","webpack-cli":"^4.10.0","@types/react":"^18.0.21","@types/react-dom":"^18.0.6"},"_npmOperationalInternal":{"tmp":"tmp/omni-router_0.1.1_1666361886206_0.6396028578885364","host":"s3://npm-registry-packages"}}},"time":{"created":"2022-10-21T14:05:54.438Z","modified":"2026-05-21T09:28:33.248Z","0.1.0":"2022-10-21T14:05:54.690Z","0.1.1":"2022-10-21T14:18:06.392Z"},"bugs":{"url":"https://github.com/ardentcode/omni-router/issues"},"author":{"url":"https://ardentcode.com/","name":"ArdentCode","email":"ardentcode@ardentcode.com"},"license":"CC0-1.0","homepage":"https://github.com/ardentcode/omni-router/tree/main/packages/omni-router","repository":{"url":"git+https://github.com/ardentcode/omni-router.git","type":"git"},"description":"Router library based on modern navigation-api","maintainers":[],"readme":"# Omni Router\r\n\r\nRouter library based on modern [Navigation API](https://github.com/WICG/navigation-api)\r\n\r\n## Build & Development\r\n\r\nTo install and build the router for production, please run following commands:\r\n\r\n- `npm install`\r\n- `npm run build`\r\n\r\nFor development, you can use:\r\n\r\n- `npm run watch`\r\n\r\n## Features\r\n\r\n- uses modern [Navigation API](https://github.com/WICG/navigation-api)\r\n- dependency free (except polyfills for server side)\r\n- framework independent\r\n- server side rendering\r\n- redirections\r\n- navigation aborting\r\n- error handling\r\n- link resolutions\r\n\r\nThe library uses following browser features.\r\nIf you want to use it in older browsers, you should include polyfills on your own.\r\nServer side already includes the polyfills.\r\n- [Navigation API](https://chromestatus.com/feature/6232287446302720)\r\n- [Abort Controller](https://chromestatus.com/feature/5631483679080448)\r\n- [URL Pattern](https://chromestatus.com/feature/5731920199548928)\r\n\r\n## Concepts\r\n\r\n### Router\r\n\r\nRouter is an entity that manages application routing.\r\nIt allows you to register routes, that will be automatically handled.\r\n\r\n### Route\r\n\r\nRoute is a representation of route that have `name`, `path`, `params` and optionally `data`.\r\nIt can be in handled state (when `data` is available) or not (when `data` is null).\r\n\r\n### Route Declaration\r\n\r\nRoute declaration is description of how the routing should look like.\r\nIt describes followings fields: `name`, `path` (pattern) and `handler`.\r\n\r\n### Route Handler\r\n\r\nRoute handler is a function that is executed when route is being opened.\r\nIt receives `params` as argument and returns `data`, which is assigned to the route.\r\nHandlers can also be lazy loaded.\r\n\r\n### Route Processor\r\n\r\nRoute processor is an object with optional listener methods, which can be executed on specific router actions.\r\nThere are 7 available listeners so far:\r\n`onGetRouteStart`, `onGetRouteEnd`, `onOpenRouteStart`, `onOpenRouteEnd`, `onOpenRouteSuccess`, `onOpenRouteError`, `onOpenRouteAbort`\r\nIt's used for processing data returned in handlers, so that repetitive actions can be achieved for all specific routes.\r\n\r\n## Guides\r\n\r\n### Creating router\r\n\r\nYou need to define two types:\r\n\r\n- map with all your routes, where keys represent route names and values represent their parameters\r\n- structure of possible route data (returned by handler)\r\n\r\n```typescript\r\ninterface RoutesMap {\r\n    home: HomeRouteParams;\r\n    post: PostRouteParams;\r\n}\r\n\r\ninterface RoutesData extends HTMLRouteData, RedirectRouteData {\r\n\r\n}\r\n\r\nconst router = createRouter<RoutesMap, RoutesData>();\r\n```\r\n\r\n### Registering routes\r\n\r\nTo register route you only need to specify three properties: `name`, `path` and `handler`.\r\n\r\n```typescript\r\nrouter.registerRoute({\r\n    name: 'home',\r\n    path: '/',\r\n    handler: async (params: HomeRouteParams) => {\r\n        return {\r\n            // ...\r\n        };\r\n    }\r\n});\r\n```\r\n\r\n### Creating handler\r\n\r\nRoute handler should only return `data` for further processing.\r\nIt shouldn't perform any visible action to the user.\r\nRoute parameters are passed as a first argument.\r\nObject containing router and abort signal is passed as a second parameter.\r\n\r\n```typescript\r\nasync function homeRouteHandler(params: HomeRouteParams, info: RouteInfo): Promise<HTMLRouteData> {\r\n    const homeData = await homeApi.getData();\r\n    return {\r\n        html: {\r\n            content: renderHomePage(homeData)\r\n        }\r\n    };\r\n}\r\n```\r\n\r\n### Finding the route\r\n\r\nYou can find the route by its name or path:\r\n\r\n```typescript\r\nhomeRoute = router.getRouteByName('home');\r\nhomeRoute = router.getRouteByPath('/');\r\n```\r\n\r\nNow you can use it in anchors (route is automatically serialized to its path when used as string):\r\n\r\n```html\r\n<a href={homeRoute.path}/>Home</a>\r\n<a href={homeRoute}/>Home</a>\r\n```\r\n\r\nRemember that this way you get unhandled route (without `data`), because `data` is only available after opening the route.\r\n\r\n### Opening the route\r\n\r\nYou can open the route programmatically. You will get the handled route (with `data`).\r\n\r\n```typescript\r\nawait router.openRouteByName('home');\r\nawait router.openRouteByPath('/');\r\n```\r\n\r\n### Parameters\r\n\r\nThere are 3 types of parameters:\r\n\r\n- named parameters\r\n- query parameters\r\n- wildcard parameters\r\n\r\nAll parameters are strings. If you want to use them as numbers, remember to parse them firstly.\r\n\r\nNamed parameters are parameters that are defined in path pattern with \":\" prefix:\r\n\r\n```typescript\r\ninterface PostsParams {\r\n    page: string;\r\n}\r\n\r\nrouter.registerRoute({\r\n    name: 'posts',\r\n    path: '/posts/:page',\r\n    handler: /* ... */\r\n});\r\n\r\nrouter.getRouteByName('posts', {page: '1'});\r\n// {name: 'posts', path: '/posts/1', params: {page: '1'}}\r\n```\r\n\r\nQuery parameters are additional parameters which are not defined in path pattern:\r\n\r\n```typescript\r\ninterface PostsParams {\r\n    page: string;\r\n}\r\n\r\nrouter.registerRoute({\r\n    name: 'posts',\r\n    path: '/posts',\r\n    handler: /* ... */\r\n});\r\n\r\nrouter.getRouteByName('posts', {page: '1'});\r\n// {name: 'posts', path: '/posts?page=1', params: {page: '1'}}\r\n```\r\n\r\nWildcard parameters are like named parameters, but instead of a name, they have just a number assigned (starting with 0):\r\n\r\n```typescript\r\ninterface PostsParams {\r\n    page: string;\r\n}\r\n\r\nrouter.registerRoute({\r\n    name: 'posts',\r\n    path: '/posts/*',\r\n    handler: /* ... */\r\n});\r\n\r\nrouter.getRouteByName('posts', {0: '1'});\r\n// {name: 'posts', path: '/posts/1', params: {page: '1'}}\r\n```\r\n\r\nYou can define a fallback page (404 not found) with wildcard, but you have to register it as the last one:\r\n\r\n```typescript\r\nrouter.registerRoute({\r\n    name: 'not-found',\r\n    path: '/*',\r\n    handler: /* ... */\r\n});\r\n```\r\n\r\n### HTML processor\r\n\r\nHTML processor injects HTML into specified elements.\r\nBy default, there is `content` property, which is injected into element with id `rootId`.\r\nYou can also define additional fragments, which you want to inject HTML into.\r\nPlease check the examples:\r\n\r\n```html\r\n\r\n<body>\r\n    <header id=\"app-header\"></header>\r\n    <main id=\"app-main\"></main>\r\n</body>\r\n```\r\n\r\n```typescript\r\ncreateHTMLRouteProcessor({\r\n    rootId: 'app-main',\r\n    fragmentsIds: {\r\n        header: 'app-header'\r\n    },\r\n    renderHTML: (html) => `<div class=\"wrapper>{html}</div>`,\r\n    renderError: (error) => `<div class=\"error\">Error</div>`\r\n})\r\n```\r\n\r\n```typescript\r\nasync function homeRouteHandler(params: HomeRouteParams): Promise<HTMLRouteData> {\r\n    return {\r\n        html: {\r\n            content: `<p>Hello World!</p>`,\r\n            fragments: {\r\n                header: `Home`\r\n            }\r\n        }\r\n    };\r\n}\r\n```\r\n\r\n### Redirect processor\r\n\r\nRedirect processor opens new route with history mode `replace`, so previous page is not available in browser history.\r\n\r\n```typescript\r\ncreateRedirectRouteProcessor()\r\n```\r\n\r\n```typescript\r\nasync function firstPostRouteHandler(): Promise<RedirectRouteData> {\r\n    const firstPost = await postApi.getPosts({limit: 1})[0];\r\n    return {\r\n        redirect: {\r\n            path: '/post/' + firstPost.id\r\n        }\r\n    };\r\n}\r\n```\r\n\r\n### Meta processor\r\n\r\nMeta processor sets page metadata like title, description, keywords, etc.\r\n\r\n```typescript\r\ncreateMetaRouteProcessor({\r\n    modifier: (name, content) => {\r\n        if (name === 'title') {\r\n            return `${content} - MyApp`;\r\n        }\r\n        return content;\r\n    },\r\n    defaults: {\r\n        title: 'MyApp'\r\n    }\r\n})\r\n```\r\n\r\n```typescript\r\nasync function homeRouteHandler(params: HomeRouteParams): Promise<MetaRouteData> {\r\n    return {\r\n        meta: {\r\n            title: 'Home Page',\r\n            description: 'Home Page of MyApp'\r\n        }\r\n    };\r\n}\r\n```\r\n\r\n### Custom processor\r\n\r\nYou can create you own processors. There are 7 available methods so far:\r\n\r\n- `onGetRouteStart`\r\n- `onGetRouteEnd`\r\n- `onOpenRouteStart`\r\n- `onOpenRouteEnd`\r\n- `onOpenRouteSuccess`\r\n- `onOpenRouteError`\r\n- `onOpenRouteAbort`\r\n\r\n```typescript\r\ninterface BodyClassRouteData {\r\n    bodyClass: string;\r\n}\r\n\r\nfunction createBodyClassRouteProcessor(): RouteProcessor<BodyClassRouteData> {\r\n    return {\r\n        onOpenRouteSuccess: async ({route}) => {\r\n            document.body.className = route.data.bodyClass ?? '';\r\n        }\r\n    };\r\n}\r\n```\r\n\r\n```typescript\r\nasync function homeRouteHandler(params: HomeRouteParams): Promise<BodyClassRouteData> {\r\n    return {\r\n        bodyClass: 'home'\r\n    };\r\n}\r\n```\r\n","readmeFilename":"README.md"}