api-bxcore
v3.0.52
Published
API-bxcore is a minimalistic and flexible framework that provides an extensive set of functions for building REST APIs on Node.js.
Readme
Module Rest-API
API-bxcore is a minimalistic and flexible framework that provides an extensive set of functions for building REST APIs on Node.js.
It has at its disposal numerous utility methods and middleware handlers, for creating a reliable professional server quickly and easily.
This module provides a web panel for viewing, testing and analyzing API methods.
Install module
npm i api-bxcoreQuick start
const express = require('express');
const app = express();
const RestAPI = require('api-bxcore');
const restapi = new RestAPI({}, {
auth_user: (user) => {
return new Promise(resolve => {
if (user.session.auth && user.session.user_id)
resolve({status: true, user_id: user.session.user_id});
else
resolve({status: false})
});
},
auth_admin: (user) => {
return new Promise(resolve => {
if (user.session.auth && user.session.user_id&& user.session.admin ===1)
resolve({status: true, user_id: user.session.user_id});
else
resolve({status: false})
});
}
});
app.use('/api/v1', restapi.expressRouter);- need to describe the basic principles of operation
- describe what the auth_user auth_admin functions are
- describe how a configuration file is created
- describe what api express router is
- describe configuration file what each parameter means in it
Request parameters checksum for restAPI authorization
let param = {...__GET, ...__POST};
const checksumParams = crypto.createHash('sha256')
.update(JSON.stringify(param))
.digest('hex');
API Types and validate
String:
/**
* @param {string} options.regexp - STRING REGEXP (optional)
*/
API.types.STRING(lenght,options)Number:
/**
* ┌──────────────── fixed (3)
* 13.556 ───────── length (5)
* @param {string} options.regexp - STRING REGEXP (optional)
*/
API.types.FLOAT(length,fixed,options) //float number
API.types.INTEGER(length,options) // integerDate:
/**
* @param {number} options.zone_utc - Convert to ZONE (example 0 = UTC) (optional)
*/
API.types.DATE(options)Enum:
API.types.ENUM(...values)
// example API.types.ENUM('active','pending','deleted') Boolean:
API.types.BOOLEAN()Object:
API.types.OBJECT()Array:
API.types.ARRAY()FILE: (validator soon)
API.types.FILE()Own type
You can also create your own type.
for this you need to add the file to the PROJECT_ROOT/api_plugins folder
Example
// PROJECT_ROOT/api_plugins/object-id-type.js
const mongoose = require('mongoose');
module.exports = (API) => {
class _ObjectId {
constructor(len, options) {
this.name = 'ObjectID';
}
valid(v) {
if (!v || v === '' || typeof v !== 'string' || !mongoose.Types.ObjectId.isValid(v))
return {
success: false,
error: 'Value is not ObjectId'
};
return {success: true, value: v};
}
}
API.types.ObjectId = () => {
return new _ObjectId();
};
};
//Example use type
API.types.ObjectId()API File example
./api/GROUP_PATH/API_file.js
module.exports = (API, redis) => {
// method api/v1/GROUP_PATH/API_file/test
API.register('test', async (user, param) => {
return {ok:1};
}, {
title: 'Test API',
level: 0,// 0 public,1 user,2 admin,3 server
description: 'This method for test and learn api. =)',
group: "Testing API",
param: {
test:{
type: API.types.STRING(10),
error_code:12345678,
title: 'example param',
required: true
}
},
response: [{
name: 'data.example',
type: "string",
title: 'example res',
default: '1'
}]
});
};Each register must contain a function with return Promise - it's important that each method returns a promise as a result of execution How is the method name generated? api/v1/ + path to file with method + (1st parameter from register if it's a string) thus we get api/v1/folder1/folder2/file/test
Error handling
Errors have a strict structure - all API responses return a response in JSON format:
Example error response:
{
"success": false,
"error": {
"apiError": true,
"message": "Page not found",
"errorType": "api",
"object": {
},
"level": 0,
"errorCode": 4041543664702404,
"stack": "Object.API.register [as fn] (./path/api/file.js:444:52)"
},
"latency_ms": 4,
"requestId": "1543748408108-wirUSou"
}Often we need to describe our own errors in methods so that our client understands what went wrong. The API has a built-in convenient and flexible error creation system:
Generating errors in methods:
You just need to use this code in your method: (the method will immediately return Promise.reject)
return API.error.response("Error message example",55511111)
this method will work in most cases - it takes 3 parameters (message,errorcode,params) - parameters are not required but if your method should return something additionally you can use it.
More flexible way to describe errors:
return Promise.reject(
API.error.create("Error message example",'api',{},10,55511111,500)
)This method takes parameters type and error level, as well as statusCode with which the request will be returned parameters of this method (message, type, params, level, errorCode, statusCode) Be careful as this method does not return reject in itself - it only creates the needed object for its return - API you need to return its response in Promise.reject()
Each method has documentation in which
title - method title
level - method access level
0 - public method, authorization not required 1 - user method, before calling the auth_user function will be called which should return status: true if user is authorized and can also return additionally user_id so that the method has the parameter auth.user.user_id 2 - Admin method similar to user method auth_admin verification function 3 - Server method can only be called on server (for example in other methods) API.call($method,$user,$params,'server')description - method description (details, warnings and other information about the method)
group - method group (category to which the method belongs for documentation to conveniently format documentation)
hide - don't show this method in the list (documentation) (secret method) (optional)
param - parameters
paramName: { type: API.types.STRING(10), // parameter type error_code:12345678, // error code if parameter comes invalid title: 'example param', // description required: true // required } // parameters can also be an array paramArray: [{ type: API.types.STRING(10), // parameter type error_code:12345678, // error code if parameter comes invalid title: 'example param', // description required: true // required }] // in this case each array element will be checked for type compliance and if required is set then the array must have at least one element // parameter can also be an array with objects in this case the entire array with needed objects will be checked paramArray: [{param1:{type...},param2:{type...}}response - array that describes what the method will return
based on this documentation all parameters will be validated and access levels before the parameter itself is called if a syntax error occurs in the method, the method will return code 500 with error indication
After starting the application, the ./api/ and ./config/ folder will be created.
./api/- directory with API./config/api_config.json- configuration file
configuration file is created on first run - proper configuration affects API operation all parameters have logical names - you can familiarize yourself with it independently
Plugins (./api_plugins)
DDOS/Flood protect
How to use:
const ddosKey = 'protect-1'; // key for count req const floodSign = await API.plugin.ddos.lockApi(auth.ddosKey, blockForSec); await API.plugin.ddos.checkLockApi(auth.ddosKey, floodSign, delayMS);
Param types ObjectId
How to use:
param:{ newsId: { type: API.types.ObjectId(), // ... } }
Quick param pagination API.method
// in source validator let page = API.plugin.pageAPI.get(param.page, param.limit, {maxLimit: 100, defaultLimit: 20, maxPage: 2000}); // in meta block param: { ...API.plugin.pageAPI.docsParams(API), } //...
