koa-rest-router
Most powerful, flexible and composable router for building enterprise RESTful APIs easily!
You might also be interested in gibon - a minimal & functional 600 bytes client-side router.
Highlighs
- production: ready for and used in
- composability: grouping multiple resources and multiple routers
- flexibility: overriding controller and request methods, plus custom prefixes
- compatibility: accepts both old and modern middlewares without deprecation messages
- powerful: multiple routers on same koa app - even can combine multiple routers
- light: not poluting your router instance and app - see
.loadMethods
- backward compatible: works on koa v1 - use
.legacyMiddleware
- maintainability: very small, beautiful, maintainable and commented codebase
- stability: strict semantic versioning and very well documented, based on koa-better-router
- open: love PRs for features, issues and recipes - Contribute a recipe? See the recipes of koa-better-router
Table of Contents
(TOC generated by verb using markdown-toc)
ProTip: Checkout koa-better-router API too to know what more methods comes with this.
Quickstart
This router uses koa-better-router, so you should review its API documentation to get more info how the things are working and what more methods are exposed.
Controller methods mapping
In addition this router allows you to override the controller methods which will be used in certain route path.
Defaults
Request method | Route path | Controller method |
---|---|---|
GET | /users |
index |
GET | /users/new |
new |
POST | /users |
create |
GET | /users/:user |
show |
GET | /users/:user/edit |
edit |
PUT | /users/:user |
update |
DELETE | /users/:user |
remove |
Example
let Router = let router = router let users = router console // => 7console // => Array Route Objects console // => 7console // => 1
Note: Multiple middlewares can be passed on each. Also combining old and modern koa middlewares, so both generator functions and normal functions.
Overriding controller methods
You easily can override the defaults by passing
options.map
object with key/value pairs where the key represents the original, and value is a string containing the wanted override.
Example
let router = let options = map: index: 'foo' new: 'bar' create: 'baz' show: 'qux' router
Overriding request methods
In some cases in guides the REST routes uses different request methods and that field is not clear enough. So every sane router should allow overriding such things, so we do it. By default for updating is used
PUT
, for deleting/removing isDELETE
. You can override this methods to usePOST
instead, so ...
Example
let router = let options = methods: put: 'POST' router
And you can combine both overriding variants, of course
Example
let router = let options = methods: put: 'POST' map: update: 'foobar' router
Install
Install with npm
$ npm i koa-rest-router --save
Usage
For more use-cases see the tests
let router = // or let Router = let apiRouter =
API
KoaRestRouter
Initialize
KoaRestRouter
with optionaloptions
, directly passed to koa-better-router and this package inherits it. So you have all methods and functionality from the awesome koa-better-router middleware.
Params
[options]
{Object}: passed directly to koa-better-router, in addition we have 2 more options here.[options.methods]
{Object}: override request methods to be used[options.map]
{Object}: override controller methods to be called
Example
let Router = let api = // - can have multiples middlewares// - can have both old and modern middlewares combinedapi console // 7console // 1 api console // 14console // 2 let Koa = // Koa v2let app = let basic = // prefix is `/` by defaultbasic appapp app
.createResource
Core method behind
.resource
for creating single resource with aname
, but without adding it tothis.routes
array. You can override any defaults - default request methods and default controller methods, just by passing respectivelyopts.methods
object andopts.map
object. It uses koa-better-router's.createRoute
under the hood.
Params
name
{String|Object}: name of the resource orctrl
ctrl
{Object}: controller object to be called on each endpoint, oropts
opts
{Object}: optional, merged with options from constructorreturns
{KoaRestRouter}this
: instance for chaining
Example
let router = prefix: '/api' // The server partlet body = let Koa = let app = // override request methodslet methods = put: 'POST' del: 'POST' // override controller methodslet map = index: 'list' show: 'read' remove: 'destroy' // notice the body should be invoked explicitly// with or without options object, no matterlet updateMiddlewares = { ctxbody = `This method by default is triggered with PUT requests only.` ctxbody = ` But now it is from POST request.` return } => { thisbody = ` Incoming data is` thisbody = ` ` next} // create actual resourcelet cats = router console// => array of "Route Objects" // router.routes array is emptyconsole // => [] // register the resourcerouter console // => 7console // => 7console // or router.routes// => array of "Route Objects" app app
.addResource
Simple method that is alias of
.addRoutes
and.addResources
, but for adding single resource. It can accepts only oneresource
object.
Params
resource
{Array}: array of route objects, known as "Resource Object"returns
{KoaRestRouter}this
: instance for chaining
Example
let Router = let api = prefix: '/' console // 0console // 0 api console // 1console // 7 console// array of route objects// => [// { prefix: '/', route: '/dragons', path: '/dragons', ... }// { prefix: '/', route: '/dragons/:dragon', path: '/dragons/:dragon', ... }// ... and 5 more routes// ]
.getResource
Get single resource by
name
. Special case is resource to the/
prefix. So pass/
asname
. See more on what are the "Route Objects" in the koa-better-router docs. What that method returns, I call "Resource Object" - array of "Route Objects"
Params
name
{String}: name of the resource, pluralreturns
{Array|Null}: if resource withname
not found `null, otherwise array of route objects - that array is known as Resource Object
Example
let api = prefix: '/api/v2' let frogs = apilet dragons = api console// array of route objects// => [// { prefix: '/api/v2', route: '/frogs', path: '/api/v2/frogs', ... }// { prefix: '/api/v2', route: '/frogs/:frog', path: '/api/v2/frogs/:frog', ... }// ... and 5 more routes// ] console // 2
.resource
Creates a resource using
.createResource
and adds the resource routes to thethis.routes
array, using.addResource
. This is not an alias! It is combination of two methods. Methods that are not defined in givenctrl
(controller) returns by default501 Not Implemented
. You can override any defaults - default request methods and default controller methods, just by passing respectivelyopts.methods
object andopts.map
object.
Params
name
{String|Object}: name of the resource orctrl
ctrl
{Object}: controller object to be called on each endpoint, oropts
opts
{Object}: optional, merged with options from constructorreturns
{KoaRestRouter}this
: instance for chaining
Example
let Router = let api = prefix: '/api/v3' let router = // on `/` prefix by default // All of the controller methods// can be remap-ed. using `opts.map`// try to pass `{ map: { index: 'home' } }` as options api // notice the `foo` methodrouter apiroutesrouterroutes // Wanna use only one router?let fooRouter = let Koa = let app = fooRouter consoleconsole // 14 app app
.addResources
Just an alias of koa-better-router's'
.addRoutes
method.
Params
...args
{Array}: any number of arguments (arrays of route objects)returns
{KoaRestRouter}this
: instance for chaining
.getResources
As we have
.getRoutes
method for gettingthis.routes
, so we have.getResources
for gettingthis.resources
array, too. Each.createResource
returns array of route objects with length of 7, so 7 routes. So if you call.createResource
two times thethis.resources
(what this method returns) will contain 2 arrays with 7 routes in each of them.
returns
{Array}: array of arrays of route objects
Example
let router = console // 0console // 0 console // 0console // 0 routerrouterrouter console // 15console // 15 console // 2console // 2
.groupResources
Powerful method for grouping couple of resources into one resource endpoint. For example you have
/cats
and/dogs
endpoints, but you wanna create/cats/:cat/dogs/:dog
endpoint, so you can do such things with that. You can group infinite number of resources. Useful methods that gives you what you should pass as arguments here are.createResource
,.createRoute
,.getResources
,.getResource
and.getRoutes
. Note: Be aware of that it replaces middlewares ofdest
with the middlewares of lastsrc
.
Params
dest
{Array}: array of "Route Objects" or "Resource Object" (both are arrays)src1
{Array}: array of "Route Objects" or "Resource Object" (both are arrays)src2
{Array}: array of "Route Objects" or "Resource Object" (both are arrays)returns
{Array}: new array with grouped resources
Example
let router = prefix: '/api/v3' let departments = routerlet companies = routerlet profiles = routerlet clients = routerlet users = routerlet cats = routerlet dogs = router // endpoint: /companies/:company/departments/:departmentlet one = router // endpoint: /profiles/:profile/clients/:client/cats/:catlet two = router // crazy? huh, AWESOME!// endpoint: /companies/:company/departments/:department/profiles/:profile/clients/:client/cats/:catlet foo = router // but actually just "register" `one` and `foo`// so you WON'T have `/profiles/:profile/clients/:client/cats/:cat`// endpoint in your APIrouter // Server partlet Koa = let app = app app
Related
- koa-bel: View engine for
koa
without any deps, built to be used… more | homepage - koa-better-body: Full-featured koa body parser! Support parsing text, buffer, json, json patch… more | homepage
- koa-better-ratelimit: Better, smaller, faster - koa middleware for limit request by ip… more | homepage
- koa-better-router: Stable and lovely router for koa, using path-match. Foundation for building… more | homepage
- koa-better-serve: Small, simple and correct serving of files, using koa-send - nothing… more | homepage
- koa-ip-filter: Middleware for koa that filters IPs against glob patterns, RegExp, string… more | homepage
- nanomatch: Fast, minimal glob matcher for node.js. Similar to micromatch, minimatch and… more | homepage
Contributing
Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.
Please read the contributing guidelines for advice on opening issues, pull requests, and coding standards.
If you need some help and can spent some cash, feel free to contact me at CodeMentor.io too.
In short: If you want to contribute to that project, please follow these things
- Please DO NOT edit README.md, CHANGELOG.md and .verb.md files. See "Building docs" section.
- Ensure anything is okey by installing the dependencies and run the tests. See "Running tests" section.
- Always use
npm run commit
to commit changes instead ofgit commit
, because it is interactive and user-friendly. It uses commitizen behind the scenes, which follows Conventional Changelog idealogy. - Do NOT bump the version in package.json. For that we use
npm run release
, which is standard-version and follows Conventional Changelog idealogy.
Thanks a lot! :)
Contributing Recipes
Recipes are just different use cases, written in form of README in human language. Showing some "Pro Tips" and tricks, answering common questions and so on. They look like tests, but in more readable and understandable way for humans - mostly for beginners that not reads or understand enough the README or API and tests.
- They are in form of folders in the root
recipes/
folder: for examplerecipes/[short-meaningful-recipe-name]/
. - In recipe folder should exist
README.md
file - In recipe folder there may have actual js files, too. And should be working.
- The examples from the recipe README.md should also exist as separate
.js
files. - Examples in recipe folder also should be working and actual.
It would be great if you follow these steps when you want to fix, update or create a recipes. 😎
- Title for recipe idea should start with
[recipe]
: for example[recipe] my awesome recipe
- Title for new recipe (PR) should also start with
[recipe]
. - Titles of Pull Requests or Issues for fixing/updating some existing recipes should start with
[recipe-fix]
.
It will help a lot, thanks in advance! 😋
Building docs
Documentation and that readme is generated using verb-generate-readme, which is a verb generator, so you need to install both of them and then run verb
command like that
$ npm install verbose/verb#dev verb-generate-readme --global && verb
Please don't edit the README directly. Any changes to the readme must be made in .verb.md.
Running tests
Clone repository and run the following in that cloned directory
$ npm install && npm test
Author
Charlike Mike Reagent
License
Copyright © 2016-2017, Charlike Mike Reagent. Released under the MIT license.
This file was generated by verb-generate-readme, v0.4.1, on February 14, 2017.
Project scaffolded using charlike cli.