- Notifications
You must be signed in to change notification settings - Fork11
ysocorp/koa-smart
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
KoaSmart is a framework based onKoajs2, which allows you to develop RESTful APIs with :Class,Decorator,Params checker
A framework based onKoajs2 withDecorator,Params checker and abase of modules (cors,bodyparser,compress,I18n, etc... ) to allow you to develop a smart api easily
exportdefaultclassRouteUsersextendsRoute{// get route: http://localhost:3000/users/get/:id @Route.Get({path:'get/:id'})asyncget(ctx){constuser=awaitthis.models.users.findById(ctx.params.id);this.assert(user,404,'User not found');this.sendOk(ctx,user);}// post route: http://localhost:3000/users/add @Route.Post({accesses:[Route.accesses.public],bodyType:Types.object().keys({email:Types.string().required(),// return an 400 if the body doesn't contain email keyname:Types.string().uppercase(),// optional parameter}),})asyncadd(ctx){constbody=this.body(ctx);// or ctx.request.body// body can contain only an object with email and name fieldconstuser=awaitthis.models.user.create(body);this.sendCreated(ctx,user);}}
- What's in this framework ?
- Install
- Router with decorator
- Params checker of POST body
- Automatic documention generation
- Get Started
- Full example
- Add treatment on route
**This framework gives you the tools to use a set of modules: **
For routing
koajs 2as the main, underlying frameworkkcorsis used to handle cross-domain requestskoa2-ratelimitTo limit bruteforce requestskoa-helmethelps you secure your apikoa-bodyto parse request bodieskoa-compressto compress the responsekoa-i18nfor Internationalization (I18n)
momentParse, validate, manipulate, and display dates in javascript.jsonwebtokenan implementation ofJSON Web Tokens JWT💪
@Decoratorsto ensure a better project structure
npm install --save koa-smartOr use the boilerplate (koa-smart-boilerplate)
All routes have to extend theRoute class in order to be mount
Prefix of routes
If you have a route class with the name
RouteMyApi, all the routes inside said class will bepreceded by/my-api/How does it work ?
- the
Routeword is removed - uppercase letters are replaced with '-'. (essentially converting camelCase into camel-case)e.g.: this will add a get route =>http://localhost:3000/my-api/hello
exportdefaultclassRouteMyApiextendsRoute{ @Route.Get({})asynchello(ctx){this.sendOk(ctx,'hello');}}
- the
Change prefix of all routes in the class:http://localhost:3000/my-prefix/hello
@Route.Route({routeBase:'my-prefix',})exportdefaultclassRouteMyApiextendsRoute{ @Route.Get({})asynchello(ctx){this.sendOk(ctx,'hello');}}
Get routehttp://localhost:3000/my-api/hello
@Route.Get({})asynchello(ctx){this.sendOk(ctx,null,'hello');}
Change pathhttp://localhost:3000/my-api/myroute/15
@Route.Get({path:'/myroute/:id'})asynchello(ctx){this.sendOk(ctx,'hello'+ctx.params.id);}
Post routehttp://localhost:3000/my-api/user-post
@Route.Post({bodyType:Types.object().keys({// body to allow: all other params will be rejectedemail:Types.string().required(),// return an 400 if the body doesn't contain email keyname:Types.string().uppercase(),// optional parameter}),})asyncuserPost(ctx){constbody=this.body(ctx);// body can contain only an object with email and name fieldconstuser=awaitthis.models.user.create(body);this.sendCreated(ctx,user);}
Disable route
Disable all routes in a class
to disable all routes in a class you should add
disablein the content of your decorator class@Route.Route({disable:true,})exportdefaultclassRouteMyApiextendsRoute{// All routes in this class will not be mounted}
Disable a specific route
to disable a specific route you can add
disablein the content of your decorator@Route.Get({disable:true,// this route will not be mounted})asynchello(ctx){this.sendOk(ctx,null,'hello');}
Grant accesses
Koa smart allows grant permission to be handled in a simple and efficient manner.
Each function passed to
accesserswill be given thekoa context (ctx)as a parameter, and must return abooleanto express whether is grants access to the route or not.If at least one of the function given returns
true, access to the route will be granted.asyncfunctionisConnected(ctx){// TODO test if the user is connectedreturnctx.state.user;}asyncfunctionisUserPremium(ctx){// TODO test if the user is premiumreturnctx.state.user.isPremium;}asyncfunctionisAdmin(ctx){// TODO test if the user is a adminreturnctx.state.user.isAdmin;}
Of a Class
@Route.Route({accesses:[isConnected]})classRouteMiddlewaresextendsRoute{ @Route.Get({})asyncview(ctx,next){console.log('I can be call if the current client is connected');this.sendOk(ctx,null,'OK');}}
Of a specific route
@Route.Get({})asyncmyPublicRoute(ctx,next){console.log('I am a public route, I can be call by any one');this.sendOk(ctx,null,'OK');}@Route.Get({accesses:[isConnected]})asyncmyConnectedRoute(ctx,next){console.log('I can be call if the current client is connected');this.sendOk(ctx,null,'OK');}@Route.Get({accesses:[isUserPremium,isAdmin]})asyncmyPremiumRoute(ctx,next){console.log('I can be call if the current client is connected and premium or admin');this.sendOk(ctx,null,'OK');}
RateLimit : For more infos, see the
koa2-ratelimitmoduleConfigure
import{App}from'koa-smart';import{RateLimit,RateLimitStores}from'koa-smart/middlewares';constapp=newApp({port:3000});// Set Default Optionconststore=newRateLimitStores.Memory()ORnewRateLimitStores.Sequelize(sequelizeInstance)RateLimit.defaultOptions({message:'Too many requests, get out!',store:store,// By default it will create MemoryStore});// limit 100 accesses per min on your APIapp.addMiddlewares([// ...RateLimit.middleware({interval:{min:1},max:100}),// ...]);
RateLimit On Decorator
Single RateLimit
@Route.Get({// allow only 100 requests per day to /viewrateLimit:{interval:{day:1},max:100},})asyncview(ctx){this.sendOk(ctx,null,'hello');}
Multiple RateLimit
// Multiple RateLimit@Route.Get({rateLimit:[{interval:{day:1},max:100},// allow only 100 requests per day{interval:{min:2},max:40},// allow only 40 requests in 2 minutes],})asynchello(ctx){this.sendOk(ctx,null,'hello');}
Middlewares
Of a Class
@Route.Route({middlewares:[// Array of middlewaresasync(ctx,next)=>{console.log('I will be call before all route in this class');awaitnext();},],})classRouteMiddlewaresextendsRoute{ @Route.Get({})asyncview(ctx,next){console.log('I will be call after middlewares of class');this.sendOk(ctx,null,'hello');}}
Of a specific route
@Route.Get({middlewares:[// Array of middlewaresasync(ctx,next)=>{console.log('I will be call before the route but after middlewares of class');awaitnext();},],})asyncview(ctx,next){console.log('I will be call after middlewares of the class and route');this.sendOk(ctx,null,'hello');}
Params checker:See the doc of Types for more information
quick example
@Route.Post({// or Put, PatchbodyType:Types.object().keys({email:Types.string().regex(/\S+@\S+\.\S+/).required(),password:Types.string().min(8).required(),address:Types.object().keys({country:Types.string().required(),street:Types.string().required(),}).required(),}),})asyncuser(ctx){// this is the body manage by bodyTypeconstbodyParams=this.body(ctx);// this is the origin body passconstoriginBodyParams=this.body(ctx,true);}
quick example
@Route.Get({queryType:Types.object().keys({limit:Types.number().integer().required().default(10),offset:Types.number().integer().required().default(10),}),})asyncusers(ctx){// this can contain only limit and offsetconstqueryParams=this.queryParam(ctx);// this is the origin queryParams passconstoriginQueryParams=this.queryParam(ctx,true);}
Automatic documention generation:See the manual for more information
Get Started (quick-start boilerplate)
in order to get started quickly, look atthis boilerplate, or follow the instructions below:
import the app and your middlewares
import{join}from'path';// import the appimport{App}from'koa-smart';// import middlewares koa-smart give you OR othersimport{bodyParser,compress,cors,handleError,RateLimit, ...}from'koa-smart/middlewares';
create an app listening on port 3000
constmyApp=newApp({port:3000,});
add your middlewares
myApp.addMiddlewares([cors({credentials:true}),helmet(),bodyParser({multipart:true}),handleError(),RateLimit.middleware({interval:{min:1},max:100}), ...]);
add your routesmount a folder with a prefix (all file who extends from
Routewill be added and mounted)myApp.mountFolder(join(__dirname,'routes'),'/');
Start your app
myApp.start();
Basic one
import{join}from'path';// import the appimport{App}from'koa-smart';// import middlewares koa-smart give you OR othersimport{i18n,bodyParser,compress,cors,helmet,addDefaultBody,handleError,logger,RateLimit,}from'koa-smart/middlewares';constmyApp=newApp({port:3000,});myApp.addMiddlewares([cors({credentials:true}),helmet(),bodyParser({multipart:true}),i18n(myApp.app,{directory:join(__dirname,'locales'),locales:['en','fr'],modes:['query','subdomain','cookie','header','tld'],}),handleError(),logger(),addDefaultBody(),compress({}),RateLimit.middleware({interval:{min:1},max:100}),]);// mount a folder with an prefix (all file who extends from `Route` will be add and mount)myApp.mountFolder(join(__dirname,'routes'),'/');// start the appmyApp.start();
Other example who Extends class App
import{join}from'path';// import the appimport{App}from'koa-smart';// import middlewares koa-smart give you OR othersimport{i18n,bodyParser,compress,cors,helmet,addDefaultBody,handleError,logger,RateLimit,}from'koa-smart/middlewares';// create an class who extends from App classexportdefaultclassMyAppextendsApp{constructor(){super({port:3000});}asyncstart(){// add your Middlewaressuper.addMiddlewares([cors({credentials:true}),helmet(),bodyParser({multipart:true}),i18n(this.app,{directory:join(__dirname,'locales'),locales:['en','fr'],modes:['query','subdomain','cookie','header','tld'],}),handleError(),logger(),addDefaultBody(),compress({}),RateLimit.middleware({interval:{min:1},max:100}),]);// mount a folder with an prefix (all file who extends from `Route` will be add and mount)super.mountFolder(join(__dirname,'routes'));returnsuper.start();}}// start the appconstmyApp=newMyApp();myApp.start();
4.0.0 upgradeskoa2-ratelimit to version 1.0.0
This means koa2-ratelimit does not install sequelize, mongoose or redis anymore. If you use these packages, make sure you install them in your project.
MIT ©YSO Corp
About
A framework base on Koajs2 with Decorator, Params checker and a base of modules (cors, bodyparser, compress, I18n, etc…) to let you develop smart api easily
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors10
Uh oh!
There was an error while loading.Please reload this page.

