@blastz/nico v0.25.0
Nico
This package is still in development.
Nico is a modern backend framework build on koa, it's inspired by sails. Ultimately nico is an effort to provide a more clear way to build api services.
Installation
npm install @blastz/nico
Hello Nico
import nico from '@blastz/nico';
// const nico = require('@blastz/nico').default
nico.init({
routes: {
'GET /users': {
controller: async (ctx) => {
return (ctx.body = []);
},
},
},
});
nico.start();
Router
Basic Router
Nico use routes
config to register routes, the basic usage like:
nico.init({
routes: {
'GET /users': {
// ...
},
},
});
This will register a route whose path is /users
and http method is Get
.
Nested Router
Nesetd router also supported:
nico.init({
routes: {
'/api/v3': {
'/users': {
GET: {
// ...
},
POST: {
// ...
},
'/:id': {
DELETE: {
// ...
},
},
},
},
},
});
This config will register three routes
GET /api/v3/users
POST /api/v3/users
DELETE /api/v3/users/:id
Body Parser
By default, body parser only works when request method is POST
, PUT
or PATCH
, change it by parsedMethods
config.
You need to manually enable body parser on specific route, otherwise it won't work.
nico.init({
routes: {
'/api/v3': {
'/users': {
POST: {
bodyParser: true,
// ...
},
},
},
},
});
By default It will only parse json
and form
types.
Multipart
To support multipart form data, you need to enable it.
nico.init({
//...
POST: {
bodyParser: {
multipartOpts: {
enable: true,
},
},
// ...
},
//...
});
You can pass formidable options directly in multipartOpts
like this:
nico.init({
//...
POST: {
bodyParser: {
multipartOpts: {
enable: true,
formidable: {
maxFileSize: 10 * 1024 * 1024,
},
},
},
// ...
},
//...
});
XML And Text
Same as multipart, you need to enable them by xmlOpts
and textOpts
configs.
More options
Check more options in config types.
Responses
Use responses to change response format.
nico.init({
routes: {
'GET /users': {
controller: (ctx) => {
return ctx.ok([]); // { data: [], message: 'execute success', success: true }
},
},
},
responses: {
ok: function ok(data, message = 'execute success', success = true) {
this.status = 200;
this.body = {
success,
data,
message,
};
},
},
});
Validate
Nico support validate params
, query
, body
and files
, It's recommend to use it with Joi.
nico.init({
routes: {
'POST /users': {
controller: (ctx) => {
ctx.logger.info(ctx.state.body.name); // validated value will be mounted at ctx.state
},
bodyParser: true, // enable body parser middleware
validate: {
body: Joi.object({
username: Joi.string().trim().required().min(1).max(50),
}),
},
},
},
});
NOTE
Above validate will allow body
to be undefined
, use Joi.object().requried()
to block it.
Nico will throw validate error by default, the error will be cached by global error handler.
You can add onError
, onBodyParserError
, onValidateError
in responses
config to change default behavior.
nico.init({
responses: {
onError: function onError(err) {
this.status = 200;
return (this.body = {
message: err.message,
success: false,
});
}, // change global error handle
onBodyParserError: function onBodyParserError(err) {
this.status = 200;
return (this.body = {
message: err.message,
success: false,
});
}, // change body parser error handle
onValidateError: function onValidateError(err) {
this.status = 200;
return (this.body = {
message: err.message,
success: false,
});
}, // change validate error handle
},
});
Static File Serve
Serve /assets
directory like this:
nico.init({
serve: {
root: path.resolve(process.cwd(), './assets'),
},
});
Change Route Path
nico.init({
serve: {
root: path.resolve(process.cwd(), './assets'),
route: '/static',
},
});
Get /assets/avatar.png
by route {{serverUrl}}/static/avatar.png
.
Serve Multiple Directories
Serve multiple directories also supported.
nico.init({
serve: [
{
root: path.resolve(process.cwd(), './assets'),
route: '/assets',
},
{
root: path.resolve(process.cwd(), './static'),
route: '/static',
},
],
});
More Options
Serve configs support koa-static options.
nico.init({
serve: {
opts, // from koa-static
},
});
Debug
nico has five log levels: fatal
, error
, warn
, info
, debug
and trace
.
Default console level is info
, file level is none
.
Logger
Check usage detail in @blastz/logger.
Change console level to trace:
import { logger, createConsoleTransport, LoggerLevel } from '@blastz/nico';
// Reset logger before nico init
logger.clear().add(createConsoleTransport({ level: LoggerLevel.Trace }));
nico.init({
// ...
});
Custom Middlewares
Nico use appMiddlewares
and routeMiddlewares
to store middleware informations, app middlewares will execute when nico.init()
is called,
route middlewares will execute when http request come.
The default appMiddleware
is ['error-handler', 'not-found-handler', 'global-cors', 'responses', 'serve', 'routes']
.
The default routeMiddleware
is ['debug', 'controller-cors', 'csp', 'xframes', 'policies', 'body-parser', 'validate', 'controller']
.
Change default middlewares:
nico.appMiddlewares = [
InnerAppMiddleware.ERROR_HANDLER,
InnerAppMiddleware.GLOBAL_CORS,
InnerAppMiddleware.ROUTES,
];
nico.routeMiddlewares = [InnerRouteMiddleware.CONTROLLER];
Define custom middlewares:
nico.useAppMiddleware(async (ctx, next) => {
await next();
ctx.set('custom', 'custom');
});
nico.useRouteMiddleware(async (ctx, next) => {
await next();
ctx.set('custom', 'custom');
}, InnerRouteMiddleware.DEBUG);
nico.init();
The second argument is the middleware name, above example shows custom middleware will execute after debug
middleware.
Custom middleware will be added to the middlewares after use middleware function, the name in the middlewares is the name of the function.
The default second argument of useAppMiddleware
is global-cors
and useRouteMiddleware
is controller-cors
.
If the second argument is null
or not found in middlewares, the custom middleware will be execute before all middlewares.
Graceful Shutdown
Nico will handle SIGINT
and SIGTERM
by default, you can add custom signal handler like this:
nico.useSignalHandler('SIGINT', () => {
closeDB();
});
Nico will automatically await all requests end and close the server, you only need to add some side effects.
The process will force exit after 10 seconds, you can change it in nico.config.advancedConfigs.forceExitTime
.
Cluster Mode
Nico support cluster mode internal, use nico.startCluster(port: number, instances?: number)
to start nico with cluster mode.
The default instances will be cpu numbers.
Plugins
- nico-build bundle project build on nico.
- nico-mongo (⚠️building) use mongo with nico.
- nico-redis (⚠️building) use ioredis with nico.
License
2 months ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago