Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/pateketrueke/abstract-nested-router
Minimal nested-routing impl!
https://github.com/pateketrueke/abstract-nested-router
Last synced: 10 days ago
JSON representation
Minimal nested-routing impl!
- Host: GitHub
- URL: https://github.com/pateketrueke/abstract-nested-router
- Owner: pateketrueke
- Created: 2019-05-24T19:54:05.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2022-06-26T17:49:28.000Z (over 2 years ago)
- Last Synced: 2024-10-29T11:24:31.534Z (about 2 months ago)
- Language: JavaScript
- Size: 781 KB
- Stars: 3
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Abstract Nested Router
> It _tries_ to capture all matching routes from its **root**.
>
> [![Build status](https://github.com/pateketrueke/abstract-nested-router/actions/workflows/ci.yml/badge.svg)](https://github.com/pateketrueke/abstract-nested-router/actions/workflows/ci.yml)
> [![NPM version](https://badge.fury.io/js/abstract-nested-router.svg)](http://badge.fury.io/js/abstract-nested-router)
> [![Coverage Status](https://codecov.io/github/pateketrueke/abstract-nested-router/coverage.svg?branch=master)](https://codecov.io/github/pateketrueke/abstract-nested-router)
> [![Known Vulnerabilities](https://snyk.io/test/npm/abstract-nested-router/badge.svg)](https://snyk.io/test/npm/abstract-nested-router)```js
import Router from 'abstract-nested-router';const r = new Router();
r.add('/', { key: 'Home' });
r.mount('/', () => {
r.add('/foo', { key: 'JustFoo' });
r.mount('/foo', () => {
r.add('/static', { key: 'StaticOne' });
r.mount('/nested', () => {
r.add('/', { key: 'NestedRoot' });
r.add('/:value', { key: 'NestedValue' });
});
r.add('/:bar', { key: 'AndNested' });
});
r.add('/baz', { key: 'Baz' });
r.add('/buzz', { key: 'Buzz' });
r.mount('/buzz', () => {
r.add('#test', { key: 'Anchor' });
r.add('#:quux', { key: 'Hashed' });
});
r.add('/*any', { key: 'Fallback' });
});
```## API
Available methods:
- `resolve(path, cb)` — Progressively finds and invoke callback with `(err, routes)` as input, useful for third-party integrations, e.g. [yrv](https://www.npmjs.com/package/yrv)
- `mount(path, cb)` — Allow to register routes under the same route
- `find(path[, retries])` — Look up routes by path, in case of failure try passing `retries` as true
- `add(path[, routeInfo])` — Register a single route by path, additional info will be returned on match
- `rm(path)` — Remove a single route by full-path, it will fail if given route is not registered!Options:
While `routeInfo` can include anything, but special keys are considered:
- `key` — Unique identity for any route handler
- `exact` — Tell if routing should match exactly or not
- `fallback` — Tell if the route should be used as last resort### Params
By default all segments are optional, e.g. `/a/:b/:c` matches with `/a`, `/a/x` and `/a/x/y` so you can say `:b` and `:c` are optional parameters.
More advanced cases would require fragments to be optional, e.g. `/:foo(-bar)` matches with `/x` and `/x-bar` because `-bar` is an optional fragment.
In the latter case `params.foo` will always be `x` regardless if `-bar` is appended, if you want to match `bar` then use `/:foo(-:suffix)` instead.
> _Splat_ parameters will consume the rest of the segments/fragments if they're present, e.g. `/x*y` captures anything that begins with `x` and stores it on `params.y` so it matches `/xy`, `/xabc`, `/x/y`, `/x/a/b/c` and so on.
Every parameter can hold simple regex-like patterns, e.g. `/:id<\d+>`
Supported patterns:
- `/:x` and `/*y` are optional segments and they cannot be empty
- `<...>` to hold regex-like patterns, `-$.` are escaped, `/` is forbidden
- `(...)` are used to mark fragments as optional, it translates to `(?:...)?`> Please avoid `/` inside `(...)` or `<...>` as they will fail loudly!
### Nesting
Consider the following examples:
```js
// 1. regular
r.add('/a');
r.add('/a/:b');
r.add('/a/:b/:c');// 2. nested
r.mount('/a', () => {
r.mount('/:b', () => {
r.add('/:c');
});
});// 3. concise
r.add('/a/:b/:c');
```In the former way (1) we're declaring each route-level by hand, however they can be expressed at once as that latter one (3) which is more concise.
The middle form (2) is a shortcut to produce concise routes.
So which one is the best? It depends on the context:
- Use concise routes to share the same `routeInfo` on all segments, it will be applied only if it's not yet defined on the route.
- Use nested routes to use shared paths, it's convenient for creating stacks of context while mounting routes, etc.
- Use regular routes to gain full control over its definition, this way each route can have its own separated context.> Routes are sorted and matched by priority and type, routes with splat params will be tried last. As more static and with less parameters the route will be matched sooner!