Repository files navigation

koa-joi-controllers

Controller decorators for Koa using koa-joi-router.

npm versionBuild Statuscodecov

Installation

npm install koa-joi-controllers

If you're using TypeScript, you should also install the type definitions for koa-joi-router:

npm install --save-dev @types/koa-joi-router

Usage

Create a controller class:

import{Get,Controller,KoaController}from'koa-joi-controllers';
@Controller('/v1')exportclassMyControllerextendsKoaController{
@Get('/hello')asynchello(ctx){ctx.body='Hello World';}}

Create a Koa app and configure the routes before running the server:

importKoafrom'koa';// import * as Koa from 'koa'; for TypeScript projectsimport{configureRoutes}from'koa-joi-controllers';constapp=newKoa();configureRoutes(app,[newMyController();],'/api');// optional prefix for all routesapp.listen(3000);// GET /api/v1/hello -> 'Hello World'

Overview

Defining controllers

You can create as many controllers as you want. Every controller needs to extend the KoaController class and have the @Controller decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.

@Controller('/koalas')exportclassKoalaControllerextendsKoaController{
@Get()asyncall(ctx){ctx.body=Koala.all();}
@Get('/:id')asyncfindById(ctx){ctx.body=Koala.findById(ctx.params.id);}}

HTTP method decorators

You can define a route with a @Method decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).

The method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports RegExp syntax.

You can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.

@Post() @Put()// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Get('/options') @Options('/options')// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Delete() @Head('/head')// throws exceptionasyncmyFunction(ctx){ctx.body='Failure';}

Request parameters

Request parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.

@Get('/users/:userId/koalas/:koalaId')asyncfindById(ctx){constuserId=ctx.params.userId;constkoalaId=ctx.params.koalaId;// do something...}

Request body

A request's body can be found in ctx.request.body, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the @Json, @Form or @Multipart decorators.

@Post('/koalas')
@Json()asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

Alternatively, you can use the @Validate decorator.

@Post('/koalas')
@Validate({type: 'json',// can also be 'form' or 'multipart'failure: 403// status code if validation fails})asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

If the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the failure value set in the @Validate decorator.

Joi validation

The @Validate decorator can enforce Joi validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the continueOnError (default: false) field to true.

import{Post,Validate,Validator}from'koa-joi-controllers';
@Post('/koalas')
@Validate({type: 'json',body: {name: Validator.Joi.string().max(40),email: Validator.Joi.string().lowercase().email(),password: Validator.Joi.string().max(40),_csrf: Validator.Joi.string().token()},continueOnError: true// ctx.invalid is set to true if validation fails})asynccreateKoala(ctx){if(!ctx.invalid){Koala.create(ctx.request.body);}else{console.log('Validation failed!');}}

Named route parameter middleware

You can define middleware for named route parameters. This is useful for auto-loading or validation.

@Param('id')asyncparam(id,ctx,next){ctx.koala=Koala.findById(id);awaitnext();}
@Get('/:id')asyncfindById(ctx){ctx.body=ctx.koala;// ctx.koala was set by the @Param('id') middlewarectx.status=ctx.koala ? 200 : 404;}

Multiple middleware support

You can use the @Pre and @Chain decorators to add additional middleware to a specific route. The Pre middleware is called first, followed by the Chain middleware (can be multiple).

@Get('/chain')
@Pre(async(ctx,next)=>{ctx.body=[0];awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(1);awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(2);awaitnext();},async(ctx,next)=>{ctx.body.push(3);awaitnext();})asyncchain(ctx){ctx.body.push(4);}// GET /chain -> [0, 1, 2, 3, 4]

Adding metadata

You can store metadata about a route. This isn't used but is stored along with all other route data.

@Get('/hello')
@Meta({info: 'Hello World example',other: {data: 42}})asynchello(ctx){ctx.body='Hello World';}

Adding routes via the router

If you're looking for functionality that is not available with the current decorators, but is possible with koa-joi-router, you can achieve this by extending the router() method in your controller class.

@Controller()exportclassMyControllerextendsKoaController{router(){letrouter=super.router();// returns router with all routes defined with decorators// add all your routes hererouter.route({path: '/hello',method: 'get',handler: asyncfunction(ctx){ctx.body='Hello World';}});returnrouter;// router must be returned}}

Using with JavaScript

In order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary babel dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators

Create a .babelrc file in your project root:

{
"presets": [["@babel/preset-env", {"targets": {"node": true}}]],
"plugins": [["@babel/plugin-proposal-decorators", {"legacy": true}]]
}

Run with:

npx babel-node app.js

License

MIT

About

Controller decorators for Koa using koa-joi-router

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

koa-joi-controllers

Controller decorators for Koa using koa-joi-router.

npm versionBuild Statuscodecov

Installation

npm install koa-joi-controllers

If you're using TypeScript, you should also install the type definitions for koa-joi-router:

npm install --save-dev @types/koa-joi-router

Usage

Create a controller class:

import{Get,Controller,KoaController}from'koa-joi-controllers';
@Controller('/v1')exportclassMyControllerextendsKoaController{
@Get('/hello')asynchello(ctx){ctx.body='Hello World';}}

Create a Koa app and configure the routes before running the server:

importKoafrom'koa';// import * as Koa from 'koa'; for TypeScript projectsimport{configureRoutes}from'koa-joi-controllers';constapp=newKoa();configureRoutes(app,[newMyController();],'/api');// optional prefix for all routesapp.listen(3000);// GET /api/v1/hello -> 'Hello World'

Overview

Defining controllers

You can create as many controllers as you want. Every controller needs to extend the KoaController class and have the @Controller decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.

@Controller('/koalas')exportclassKoalaControllerextendsKoaController{
@Get()asyncall(ctx){ctx.body=Koala.all();}
@Get('/:id')asyncfindById(ctx){ctx.body=Koala.findById(ctx.params.id);}}

HTTP method decorators

You can define a route with a @Method decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).

The method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports RegExp syntax.

You can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.

@Post() @Put()// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Get('/options') @Options('/options')// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Delete() @Head('/head')// throws exceptionasyncmyFunction(ctx){ctx.body='Failure';}

Request parameters

Request parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.

@Get('/users/:userId/koalas/:koalaId')asyncfindById(ctx){constuserId=ctx.params.userId;constkoalaId=ctx.params.koalaId;// do something...}

Request body

A request's body can be found in ctx.request.body, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the @Json, @Form or @Multipart decorators.

@Post('/koalas')
@Json()asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

Alternatively, you can use the @Validate decorator.

@Post('/koalas')
@Validate({type: 'json',// can also be 'form' or 'multipart'failure: 403// status code if validation fails})asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

If the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the failure value set in the @Validate decorator.

Joi validation

The @Validate decorator can enforce Joi validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the continueOnError (default: false) field to true.

import{Post,Validate,Validator}from'koa-joi-controllers';
@Post('/koalas')
@Validate({type: 'json',body: {name: Validator.Joi.string().max(40),email: Validator.Joi.string().lowercase().email(),password: Validator.Joi.string().max(40),_csrf: Validator.Joi.string().token()},continueOnError: true// ctx.invalid is set to true if validation fails})asynccreateKoala(ctx){if(!ctx.invalid){Koala.create(ctx.request.body);}else{console.log('Validation failed!');}}

Named route parameter middleware

You can define middleware for named route parameters. This is useful for auto-loading or validation.

@Param('id')asyncparam(id,ctx,next){ctx.koala=Koala.findById(id);awaitnext();}
@Get('/:id')asyncfindById(ctx){ctx.body=ctx.koala;// ctx.koala was set by the @Param('id') middlewarectx.status=ctx.koala ? 200 : 404;}

Multiple middleware support

You can use the @Pre and @Chain decorators to add additional middleware to a specific route. The Pre middleware is called first, followed by the Chain middleware (can be multiple).

@Get('/chain')
@Pre(async(ctx,next)=>{ctx.body=[0];awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(1);awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(2);awaitnext();},async(ctx,next)=>{ctx.body.push(3);awaitnext();})asyncchain(ctx){ctx.body.push(4);}// GET /chain -> [0, 1, 2, 3, 4]

Adding metadata

You can store metadata about a route. This isn't used but is stored along with all other route data.

@Get('/hello')
@Meta({info: 'Hello World example',other: {data: 42}})asynchello(ctx){ctx.body='Hello World';}

Adding routes via the router

If you're looking for functionality that is not available with the current decorators, but is possible with koa-joi-router, you can achieve this by extending the router() method in your controller class.

@Controller()exportclassMyControllerextendsKoaController{router(){letrouter=super.router();// returns router with all routes defined with decorators// add all your routes hererouter.route({path: '/hello',method: 'get',handler: asyncfunction(ctx){ctx.body='Hello World';}});returnrouter;// router must be returned}}

Using with JavaScript

In order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary babel dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators

Create a .babelrc file in your project root:

{
"presets": [["@babel/preset-env", {"targets": {"node": true}}]],
"plugins": [["@babel/plugin-proposal-decorators", {"legacy": true}]]
}

Run with:

npx babel-node app.js

License

MIT

About

Controller decorators for Koa using koa-joi-router

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

koa-joi-controllers

Controller decorators for Koa using koa-joi-router.

npm versionBuild Statuscodecov

Installation

npm install koa-joi-controllers

If you're using TypeScript, you should also install the type definitions for koa-joi-router:

npm install --save-dev @types/koa-joi-router

Usage

Create a controller class:

import{Get,Controller,KoaController}from'koa-joi-controllers';
@Controller('/v1')exportclassMyControllerextendsKoaController{
@Get('/hello')asynchello(ctx){ctx.body='Hello World';}}

Create a Koa app and configure the routes before running the server:

importKoafrom'koa';// import * as Koa from 'koa'; for TypeScript projectsimport{configureRoutes}from'koa-joi-controllers';constapp=newKoa();configureRoutes(app,[newMyController();],'/api');// optional prefix for all routesapp.listen(3000);// GET /api/v1/hello -> 'Hello World'

Overview

Defining controllers

You can create as many controllers as you want. Every controller needs to extend the KoaController class and have the @Controller decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.

@Controller('/koalas')exportclassKoalaControllerextendsKoaController{
@Get()asyncall(ctx){ctx.body=Koala.all();}
@Get('/:id')asyncfindById(ctx){ctx.body=Koala.findById(ctx.params.id);}}

HTTP method decorators

You can define a route with a @Method decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).

The method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports RegExp syntax.

You can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.

@Post() @Put()// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Get('/options') @Options('/options')// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Delete() @Head('/head')// throws exceptionasyncmyFunction(ctx){ctx.body='Failure';}

Request parameters

Request parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.

@Get('/users/:userId/koalas/:koalaId')asyncfindById(ctx){constuserId=ctx.params.userId;constkoalaId=ctx.params.koalaId;// do something...}

Request body

A request's body can be found in ctx.request.body, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the @Json, @Form or @Multipart decorators.

@Post('/koalas')
@Json()asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

Alternatively, you can use the @Validate decorator.

@Post('/koalas')
@Validate({type: 'json',// can also be 'form' or 'multipart'failure: 403// status code if validation fails})asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

If the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the failure value set in the @Validate decorator.

Joi validation

The @Validate decorator can enforce Joi validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the continueOnError (default: false) field to true.

import{Post,Validate,Validator}from'koa-joi-controllers';
@Post('/koalas')
@Validate({type: 'json',body: {name: Validator.Joi.string().max(40),email: Validator.Joi.string().lowercase().email(),password: Validator.Joi.string().max(40),_csrf: Validator.Joi.string().token()},continueOnError: true// ctx.invalid is set to true if validation fails})asynccreateKoala(ctx){if(!ctx.invalid){Koala.create(ctx.request.body);}else{console.log('Validation failed!');}}

Named route parameter middleware

You can define middleware for named route parameters. This is useful for auto-loading or validation.

@Param('id')asyncparam(id,ctx,next){ctx.koala=Koala.findById(id);awaitnext();}
@Get('/:id')asyncfindById(ctx){ctx.body=ctx.koala;// ctx.koala was set by the @Param('id') middlewarectx.status=ctx.koala ? 200 : 404;}

Multiple middleware support

You can use the @Pre and @Chain decorators to add additional middleware to a specific route. The Pre middleware is called first, followed by the Chain middleware (can be multiple).

@Get('/chain')
@Pre(async(ctx,next)=>{ctx.body=[0];awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(1);awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(2);awaitnext();},async(ctx,next)=>{ctx.body.push(3);awaitnext();})asyncchain(ctx){ctx.body.push(4);}// GET /chain -> [0, 1, 2, 3, 4]

Adding metadata

You can store metadata about a route. This isn't used but is stored along with all other route data.

@Get('/hello')
@Meta({info: 'Hello World example',other: {data: 42}})asynchello(ctx){ctx.body='Hello World';}

Adding routes via the router

If you're looking for functionality that is not available with the current decorators, but is possible with koa-joi-router, you can achieve this by extending the router() method in your controller class.

@Controller()exportclassMyControllerextendsKoaController{router(){letrouter=super.router();// returns router with all routes defined with decorators// add all your routes hererouter.route({path: '/hello',method: 'get',handler: asyncfunction(ctx){ctx.body='Hello World';}});returnrouter;// router must be returned}}

Using with JavaScript

In order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary babel dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators

Create a .babelrc file in your project root:

{
"presets": [["@babel/preset-env", {"targets": {"node": true}}]],
"plugins": [["@babel/plugin-proposal-decorators", {"legacy": true}]]
}

Run with:

npx babel-node app.js

License

MIT

About

Controller decorators for Koa using koa-joi-router

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

koa-joi-controllers

Controller decorators for Koa using koa-joi-router.

npm versionBuild Statuscodecov

Installation

npm install koa-joi-controllers

If you're using TypeScript, you should also install the type definitions for koa-joi-router:

npm install --save-dev @types/koa-joi-router

Usage

Create a controller class:

import{Get,Controller,KoaController}from'koa-joi-controllers';
@Controller('/v1')exportclassMyControllerextendsKoaController{
@Get('/hello')asynchello(ctx){ctx.body='Hello World';}}

Create a Koa app and configure the routes before running the server:

importKoafrom'koa';// import * as Koa from 'koa'; for TypeScript projectsimport{configureRoutes}from'koa-joi-controllers';constapp=newKoa();configureRoutes(app,[newMyController();],'/api');// optional prefix for all routesapp.listen(3000);// GET /api/v1/hello -> 'Hello World'

Overview

Defining controllers

You can create as many controllers as you want. Every controller needs to extend the KoaController class and have the @Controller decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.

@Controller('/koalas')exportclassKoalaControllerextendsKoaController{
@Get()asyncall(ctx){ctx.body=Koala.all();}
@Get('/:id')asyncfindById(ctx){ctx.body=Koala.findById(ctx.params.id);}}

HTTP method decorators

You can define a route with a @Method decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).

The method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports RegExp syntax.

You can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.

@Post() @Put()// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Get('/options') @Options('/options')// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Delete() @Head('/head')// throws exceptionasyncmyFunction(ctx){ctx.body='Failure';}

Request parameters

Request parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.

@Get('/users/:userId/koalas/:koalaId')asyncfindById(ctx){constuserId=ctx.params.userId;constkoalaId=ctx.params.koalaId;// do something...}

Request body

A request's body can be found in ctx.request.body, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the @Json, @Form or @Multipart decorators.

@Post('/koalas')
@Json()asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

Alternatively, you can use the @Validate decorator.

@Post('/koalas')
@Validate({type: 'json',// can also be 'form' or 'multipart'failure: 403// status code if validation fails})asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

If the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the failure value set in the @Validate decorator.

Joi validation

The @Validate decorator can enforce Joi validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the continueOnError (default: false) field to true.

import{Post,Validate,Validator}from'koa-joi-controllers';
@Post('/koalas')
@Validate({type: 'json',body: {name: Validator.Joi.string().max(40),email: Validator.Joi.string().lowercase().email(),password: Validator.Joi.string().max(40),_csrf: Validator.Joi.string().token()},continueOnError: true// ctx.invalid is set to true if validation fails})asynccreateKoala(ctx){if(!ctx.invalid){Koala.create(ctx.request.body);}else{console.log('Validation failed!');}}

Named route parameter middleware

You can define middleware for named route parameters. This is useful for auto-loading or validation.

@Param('id')asyncparam(id,ctx,next){ctx.koala=Koala.findById(id);awaitnext();}
@Get('/:id')asyncfindById(ctx){ctx.body=ctx.koala;// ctx.koala was set by the @Param('id') middlewarectx.status=ctx.koala ? 200 : 404;}

Multiple middleware support

You can use the @Pre and @Chain decorators to add additional middleware to a specific route. The Pre middleware is called first, followed by the Chain middleware (can be multiple).

@Get('/chain')
@Pre(async(ctx,next)=>{ctx.body=[0];awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(1);awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(2);awaitnext();},async(ctx,next)=>{ctx.body.push(3);awaitnext();})asyncchain(ctx){ctx.body.push(4);}// GET /chain -> [0, 1, 2, 3, 4]

Adding metadata

You can store metadata about a route. This isn't used but is stored along with all other route data.

@Get('/hello')
@Meta({info: 'Hello World example',other: {data: 42}})asynchello(ctx){ctx.body='Hello World';}

Adding routes via the router

If you're looking for functionality that is not available with the current decorators, but is possible with koa-joi-router, you can achieve this by extending the router() method in your controller class.

@Controller()exportclassMyControllerextendsKoaController{router(){letrouter=super.router();// returns router with all routes defined with decorators// add all your routes hererouter.route({path: '/hello',method: 'get',handler: asyncfunction(ctx){ctx.body='Hello World';}});returnrouter;// router must be returned}}

Using with JavaScript

In order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary babel dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators

Create a .babelrc file in your project root:

{
"presets": [["@babel/preset-env", {"targets": {"node": true}}]],
"plugins": [["@babel/plugin-proposal-decorators", {"legacy": true}]]
}

Run with:

npx babel-node app.js

License

MIT

About

Controller decorators for Koa using koa-joi-router

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

koa-joi-controllers

Controller decorators for Koa using koa-joi-router.

npm versionBuild Statuscodecov

Installation

npm install koa-joi-controllers

If you're using TypeScript, you should also install the type definitions for koa-joi-router:

npm install --save-dev @types/koa-joi-router

Usage

Create a controller class:

import{Get,Controller,KoaController}from'koa-joi-controllers';
@Controller('/v1')exportclassMyControllerextendsKoaController{
@Get('/hello')asynchello(ctx){ctx.body='Hello World';}}

Create a Koa app and configure the routes before running the server:

importKoafrom'koa';// import * as Koa from 'koa'; for TypeScript projectsimport{configureRoutes}from'koa-joi-controllers';constapp=newKoa();configureRoutes(app,[newMyController();],'/api');// optional prefix for all routesapp.listen(3000);// GET /api/v1/hello -> 'Hello World'

Overview

Defining controllers

You can create as many controllers as you want. Every controller needs to extend the KoaController class and have the @Controller decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.

@Controller('/koalas')exportclassKoalaControllerextendsKoaController{
@Get()asyncall(ctx){ctx.body=Koala.all();}
@Get('/:id')asyncfindById(ctx){ctx.body=Koala.findById(ctx.params.id);}}

HTTP method decorators

You can define a route with a @Method decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).

The method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports RegExp syntax.

You can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.

@Post() @Put()// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Get('/options') @Options('/options')// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Delete() @Head('/head')// throws exceptionasyncmyFunction(ctx){ctx.body='Failure';}

Request parameters

Request parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.

@Get('/users/:userId/koalas/:koalaId')asyncfindById(ctx){constuserId=ctx.params.userId;constkoalaId=ctx.params.koalaId;// do something...}

Request body

A request's body can be found in ctx.request.body, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the @Json, @Form or @Multipart decorators.

@Post('/koalas')
@Json()asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

Alternatively, you can use the @Validate decorator.

@Post('/koalas')
@Validate({type: 'json',// can also be 'form' or 'multipart'failure: 403// status code if validation fails})asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

If the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the failure value set in the @Validate decorator.

Joi validation

The @Validate decorator can enforce Joi validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the continueOnError (default: false) field to true.

import{Post,Validate,Validator}from'koa-joi-controllers';
@Post('/koalas')
@Validate({type: 'json',body: {name: Validator.Joi.string().max(40),email: Validator.Joi.string().lowercase().email(),password: Validator.Joi.string().max(40),_csrf: Validator.Joi.string().token()},continueOnError: true// ctx.invalid is set to true if validation fails})asynccreateKoala(ctx){if(!ctx.invalid){Koala.create(ctx.request.body);}else{console.log('Validation failed!');}}

Named route parameter middleware

You can define middleware for named route parameters. This is useful for auto-loading or validation.

@Param('id')asyncparam(id,ctx,next){ctx.koala=Koala.findById(id);awaitnext();}
@Get('/:id')asyncfindById(ctx){ctx.body=ctx.koala;// ctx.koala was set by the @Param('id') middlewarectx.status=ctx.koala ? 200 : 404;}

Multiple middleware support

You can use the @Pre and @Chain decorators to add additional middleware to a specific route. The Pre middleware is called first, followed by the Chain middleware (can be multiple).

@Get('/chain')
@Pre(async(ctx,next)=>{ctx.body=[0];awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(1);awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(2);awaitnext();},async(ctx,next)=>{ctx.body.push(3);awaitnext();})asyncchain(ctx){ctx.body.push(4);}// GET /chain -> [0, 1, 2, 3, 4]

Adding metadata

You can store metadata about a route. This isn't used but is stored along with all other route data.

@Get('/hello')
@Meta({info: 'Hello World example',other: {data: 42}})asynchello(ctx){ctx.body='Hello World';}

Adding routes via the router

If you're looking for functionality that is not available with the current decorators, but is possible with koa-joi-router, you can achieve this by extending the router() method in your controller class.

@Controller()exportclassMyControllerextendsKoaController{router(){letrouter=super.router();// returns router with all routes defined with decorators// add all your routes hererouter.route({path: '/hello',method: 'get',handler: asyncfunction(ctx){ctx.body='Hello World';}});returnrouter;// router must be returned}}

Using with JavaScript

In order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary babel dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators

Create a .babelrc file in your project root:

{
"presets": [["@babel/preset-env", {"targets": {"node": true}}]],
"plugins": [["@babel/plugin-proposal-decorators", {"legacy": true}]]
}

Run with:

npx babel-node app.js

License

MIT

About

Controller decorators for Koa using koa-joi-router

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

koa-joi-controllers

Controller decorators for Koa using koa-joi-router.

npm versionBuild Statuscodecov

Installation

npm install koa-joi-controllers

If you're using TypeScript, you should also install the type definitions for koa-joi-router:

npm install --save-dev @types/koa-joi-router

Usage

Create a controller class:

import{Get,Controller,KoaController}from'koa-joi-controllers';
@Controller('/v1')exportclassMyControllerextendsKoaController{
@Get('/hello')asynchello(ctx){ctx.body='Hello World';}}

Create a Koa app and configure the routes before running the server:

importKoafrom'koa';// import * as Koa from 'koa'; for TypeScript projectsimport{configureRoutes}from'koa-joi-controllers';constapp=newKoa();configureRoutes(app,[newMyController();],'/api');// optional prefix for all routesapp.listen(3000);// GET /api/v1/hello -> 'Hello World'

Overview

Defining controllers

You can create as many controllers as you want. Every controller needs to extend the KoaController class and have the @Controller decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.

@Controller('/koalas')exportclassKoalaControllerextendsKoaController{
@Get()asyncall(ctx){ctx.body=Koala.all();}
@Get('/:id')asyncfindById(ctx){ctx.body=Koala.findById(ctx.params.id);}}

HTTP method decorators

You can define a route with a @Method decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).

The method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports RegExp syntax.

You can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.

@Post() @Put()// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Get('/options') @Options('/options')// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Delete() @Head('/head')// throws exceptionasyncmyFunction(ctx){ctx.body='Failure';}

Request parameters

Request parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.

@Get('/users/:userId/koalas/:koalaId')asyncfindById(ctx){constuserId=ctx.params.userId;constkoalaId=ctx.params.koalaId;// do something...}

Request body

A request's body can be found in ctx.request.body, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the @Json, @Form or @Multipart decorators.

@Post('/koalas')
@Json()asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

Alternatively, you can use the @Validate decorator.

@Post('/koalas')
@Validate({type: 'json',// can also be 'form' or 'multipart'failure: 403// status code if validation fails})asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

If the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the failure value set in the @Validate decorator.

Joi validation

The @Validate decorator can enforce Joi validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the continueOnError (default: false) field to true.

import{Post,Validate,Validator}from'koa-joi-controllers';
@Post('/koalas')
@Validate({type: 'json',body: {name: Validator.Joi.string().max(40),email: Validator.Joi.string().lowercase().email(),password: Validator.Joi.string().max(40),_csrf: Validator.Joi.string().token()},continueOnError: true// ctx.invalid is set to true if validation fails})asynccreateKoala(ctx){if(!ctx.invalid){Koala.create(ctx.request.body);}else{console.log('Validation failed!');}}

Named route parameter middleware

You can define middleware for named route parameters. This is useful for auto-loading or validation.

@Param('id')asyncparam(id,ctx,next){ctx.koala=Koala.findById(id);awaitnext();}
@Get('/:id')asyncfindById(ctx){ctx.body=ctx.koala;// ctx.koala was set by the @Param('id') middlewarectx.status=ctx.koala ? 200 : 404;}

Multiple middleware support

You can use the @Pre and @Chain decorators to add additional middleware to a specific route. The Pre middleware is called first, followed by the Chain middleware (can be multiple).

@Get('/chain')
@Pre(async(ctx,next)=>{ctx.body=[0];awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(1);awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(2);awaitnext();},async(ctx,next)=>{ctx.body.push(3);awaitnext();})asyncchain(ctx){ctx.body.push(4);}// GET /chain -> [0, 1, 2, 3, 4]

Adding metadata

You can store metadata about a route. This isn't used but is stored along with all other route data.

@Get('/hello')
@Meta({info: 'Hello World example',other: {data: 42}})asynchello(ctx){ctx.body='Hello World';}

Adding routes via the router

If you're looking for functionality that is not available with the current decorators, but is possible with koa-joi-router, you can achieve this by extending the router() method in your controller class.

@Controller()exportclassMyControllerextendsKoaController{router(){letrouter=super.router();// returns router with all routes defined with decorators// add all your routes hererouter.route({path: '/hello',method: 'get',handler: asyncfunction(ctx){ctx.body='Hello World';}});returnrouter;// router must be returned}}

Using with JavaScript

In order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary babel dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators

Create a .babelrc file in your project root:

{
"presets": [["@babel/preset-env", {"targets": {"node": true}}]],
"plugins": [["@babel/plugin-proposal-decorators", {"legacy": true}]]
}

Run with:

npx babel-node app.js

License

MIT

About

Controller decorators for Koa using koa-joi-router

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

koa-joi-controllers

Controller decorators for Koa using koa-joi-router.

npm versionBuild Statuscodecov

Installation

npm install koa-joi-controllers

If you're using TypeScript, you should also install the type definitions for koa-joi-router:

npm install --save-dev @types/koa-joi-router

Usage

Create a controller class:

import{Get,Controller,KoaController}from'koa-joi-controllers';
@Controller('/v1')exportclassMyControllerextendsKoaController{
@Get('/hello')asynchello(ctx){ctx.body='Hello World';}}

Create a Koa app and configure the routes before running the server:

importKoafrom'koa';// import * as Koa from 'koa'; for TypeScript projectsimport{configureRoutes}from'koa-joi-controllers';constapp=newKoa();configureRoutes(app,[newMyController();],'/api');// optional prefix for all routesapp.listen(3000);// GET /api/v1/hello -> 'Hello World'

Overview

Defining controllers

You can create as many controllers as you want. Every controller needs to extend the KoaController class and have the @Controller decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.

@Controller('/koalas')exportclassKoalaControllerextendsKoaController{
@Get()asyncall(ctx){ctx.body=Koala.all();}
@Get('/:id')asyncfindById(ctx){ctx.body=Koala.findById(ctx.params.id);}}

HTTP method decorators

You can define a route with a @Method decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).

The method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports RegExp syntax.

You can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.

@Post() @Put()// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Get('/options') @Options('/options')// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Delete() @Head('/head')// throws exceptionasyncmyFunction(ctx){ctx.body='Failure';}

Request parameters

Request parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.

@Get('/users/:userId/koalas/:koalaId')asyncfindById(ctx){constuserId=ctx.params.userId;constkoalaId=ctx.params.koalaId;// do something...}

Request body

A request's body can be found in ctx.request.body, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the @Json, @Form or @Multipart decorators.

@Post('/koalas')
@Json()asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

Alternatively, you can use the @Validate decorator.

@Post('/koalas')
@Validate({type: 'json',// can also be 'form' or 'multipart'failure: 403// status code if validation fails})asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

If the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the failure value set in the @Validate decorator.

Joi validation

The @Validate decorator can enforce Joi validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the continueOnError (default: false) field to true.

import{Post,Validate,Validator}from'koa-joi-controllers';
@Post('/koalas')
@Validate({type: 'json',body: {name: Validator.Joi.string().max(40),email: Validator.Joi.string().lowercase().email(),password: Validator.Joi.string().max(40),_csrf: Validator.Joi.string().token()},continueOnError: true// ctx.invalid is set to true if validation fails})asynccreateKoala(ctx){if(!ctx.invalid){Koala.create(ctx.request.body);}else{console.log('Validation failed!');}}

Named route parameter middleware

You can define middleware for named route parameters. This is useful for auto-loading or validation.

@Param('id')asyncparam(id,ctx,next){ctx.koala=Koala.findById(id);awaitnext();}
@Get('/:id')asyncfindById(ctx){ctx.body=ctx.koala;// ctx.koala was set by the @Param('id') middlewarectx.status=ctx.koala ? 200 : 404;}

Multiple middleware support

You can use the @Pre and @Chain decorators to add additional middleware to a specific route. The Pre middleware is called first, followed by the Chain middleware (can be multiple).

@Get('/chain')
@Pre(async(ctx,next)=>{ctx.body=[0];awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(1);awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(2);awaitnext();},async(ctx,next)=>{ctx.body.push(3);awaitnext();})asyncchain(ctx){ctx.body.push(4);}// GET /chain -> [0, 1, 2, 3, 4]

Adding metadata

You can store metadata about a route. This isn't used but is stored along with all other route data.

@Get('/hello')
@Meta({info: 'Hello World example',other: {data: 42}})asynchello(ctx){ctx.body='Hello World';}

Adding routes via the router

If you're looking for functionality that is not available with the current decorators, but is possible with koa-joi-router, you can achieve this by extending the router() method in your controller class.

@Controller()exportclassMyControllerextendsKoaController{router(){letrouter=super.router();// returns router with all routes defined with decorators// add all your routes hererouter.route({path: '/hello',method: 'get',handler: asyncfunction(ctx){ctx.body='Hello World';}});returnrouter;// router must be returned}}

Using with JavaScript

In order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary babel dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators

Create a .babelrc file in your project root:

{
"presets": [["@babel/preset-env", {"targets": {"node": true}}]],
"plugins": [["@babel/plugin-proposal-decorators", {"legacy": true}]]
}

Run with:

npx babel-node app.js

License

MIT

About

Controller decorators for Koa using koa-joi-router

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

koa-joi-controllers

Controller decorators for Koa using koa-joi-router.

npm versionBuild Statuscodecov

Installation

npm install koa-joi-controllers

If you're using TypeScript, you should also install the type definitions for koa-joi-router:

npm install --save-dev @types/koa-joi-router

Usage

Create a controller class:

import{Get,Controller,KoaController}from'koa-joi-controllers';
@Controller('/v1')exportclassMyControllerextendsKoaController{
@Get('/hello')asynchello(ctx){ctx.body='Hello World';}}

Create a Koa app and configure the routes before running the server:

importKoafrom'koa';// import * as Koa from 'koa'; for TypeScript projectsimport{configureRoutes}from'koa-joi-controllers';constapp=newKoa();configureRoutes(app,[newMyController();],'/api');// optional prefix for all routesapp.listen(3000);// GET /api/v1/hello -> 'Hello World'

Overview

Defining controllers

You can create as many controllers as you want. Every controller needs to extend the KoaController class and have the @Controller decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.

@Controller('/koalas')exportclassKoalaControllerextendsKoaController{
@Get()asyncall(ctx){ctx.body=Koala.all();}
@Get('/:id')asyncfindById(ctx){ctx.body=Koala.findById(ctx.params.id);}}

HTTP method decorators

You can define a route with a @Method decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).

The method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports RegExp syntax.

You can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.

@Post() @Put()// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Get('/options') @Options('/options')// allowedasyncmyFunction(ctx){ctx.body='Success';}
@Delete() @Head('/head')// throws exceptionasyncmyFunction(ctx){ctx.body='Failure';}

Request parameters

Request parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.

@Get('/users/:userId/koalas/:koalaId')asyncfindById(ctx){constuserId=ctx.params.userId;constkoalaId=ctx.params.koalaId;// do something...}

Request body

A request's body can be found in ctx.request.body, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the @Json, @Form or @Multipart decorators.

@Post('/koalas')
@Json()asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

Alternatively, you can use the @Validate decorator.

@Post('/koalas')
@Validate({type: 'json',// can also be 'form' or 'multipart'failure: 403// status code if validation fails})asynccreateKoala(ctx){constbody=ctx.request.body;// incoming JSON data is in ctx.request.bodyctx.body=Koala.create(body);}

If the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the failure value set in the @Validate decorator.

Joi validation

The @Validate decorator can enforce Joi validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the continueOnError (default: false) field to true.

import{Post,Validate,Validator}from'koa-joi-controllers';
@Post('/koalas')
@Validate({type: 'json',body: {name: Validator.Joi.string().max(40),email: Validator.Joi.string().lowercase().email(),password: Validator.Joi.string().max(40),_csrf: Validator.Joi.string().token()},continueOnError: true// ctx.invalid is set to true if validation fails})asynccreateKoala(ctx){if(!ctx.invalid){Koala.create(ctx.request.body);}else{console.log('Validation failed!');}}

Named route parameter middleware

You can define middleware for named route parameters. This is useful for auto-loading or validation.

@Param('id')asyncparam(id,ctx,next){ctx.koala=Koala.findById(id);awaitnext();}
@Get('/:id')asyncfindById(ctx){ctx.body=ctx.koala;// ctx.koala was set by the @Param('id') middlewarectx.status=ctx.koala ? 200 : 404;}

Multiple middleware support

You can use the @Pre and @Chain decorators to add additional middleware to a specific route. The Pre middleware is called first, followed by the Chain middleware (can be multiple).

@Get('/chain')
@Pre(async(ctx,next)=>{ctx.body=[0];awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(1);awaitnext();})
@Chain(async(ctx,next)=>{ctx.body.push(2);awaitnext();},async(ctx,next)=>{ctx.body.push(3);awaitnext();})asyncchain(ctx){ctx.body.push(4);}// GET /chain -> [0, 1, 2, 3, 4]

Adding metadata

You can store metadata about a route. This isn't used but is stored along with all other route data.

@Get('/hello')
@Meta({info: 'Hello World example',other: {data: 42}})asynchello(ctx){ctx.body='Hello World';}

Adding routes via the router

If you're looking for functionality that is not available with the current decorators, but is possible with koa-joi-router, you can achieve this by extending the router() method in your controller class.

@Controller()exportclassMyControllerextendsKoaController{router(){letrouter=super.router();// returns router with all routes defined with decorators// add all your routes hererouter.route({path: '/hello',method: 'get',handler: asyncfunction(ctx){ctx.body='Hello World';}});returnrouter;// router must be returned}}

Using with JavaScript

In order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary babel dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators

Create a .babelrc file in your project root:

{
"presets": [["@babel/preset-env", {"targets": {"node": true}}]],
"plugins": [["@babel/plugin-proposal-decorators", {"legacy": true}]]
}

Run with:

npx babel-node app.js

License

MIT

About

Controller decorators for Koa using koa-joi-router

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages