- Generalization of CRUD API (No need to define CRUD api for every collection just define schema and permissions)
- File upload and download to filesystem or database
- Commom API using dispatch and actions
- Uses yarn
- No transpilers, just vanilla javascript with ES2017 latest features like Async/Await
- Express + MongoDB (Mongoose)
- CORS enabled and uses helmet to set some HTTP headers for security
- Load environment variables from .env files with dotenv
- Consistent coding styles with editorconfig
- Gzip compression with compression
- Linting with eslint
- Code coverage with istanbul and coveralls
- Git hooks with husky
- Logging with morgan
- Authentication and Authorization with passport
- Rate limiting with express-rate-limit
- API documentation generation with apidoc
- Clone the repo and make it yours:
git clone https://github.com/rameshbansal/node-boilerplate.git node-api
cd node-api
rm -rf .git
- Install dependencies:
npm install
- Set environment variables:
cp .env.example .env
yarn dev
yarn start
Developer just have to create an roles config file with permissions and by defining the mongo schema of collection he will get basic CRUD API
const ROLES = require('./roles');
const grantList =
{
[ROLES.SUPERADMIN]: {
User: {
read_any: {
filter: {},
allowedFields: ['*'],
deniedFields: ['password'],
},
read_own: {
filter: { _id: '=currentUser' },
allowedFields: ['*'],
deniedFields: ['services', 'password'],
},
},
Customer: {
read_any: {
filter: { },
allowedFields: ['*'],
deniedFields: ['email'],
},
read_own: {
filter: { _id: '=currentUser.customer' },
allowedFields: ['*'],
deniedFields: ['email'],
},
create_own: {
setter: { user: '=currentUser._id' },
allowedFields: ['*'],
deniedFields: ['user'],
},
remove_any: {
filter: {},
},
remove_own: {
filter: { user: '=currentUser._id' },
allowedFields: ['*'],
},
update_any: {
filter: {},
allowedFields: ['*'],
deniedFields: ['address.country.name'],
$pop: {
allowedFields: ['*'],
},
$pull: {
allowedFields: ['location', 'grades'],
},
$unset: {
allowedFields: ['address.city'],
},
},
update_own: {
filter: { user: '=currentUser._id' },
allowedFields: ['*'],
deniedFields: ['address.country.name'],
$pop: {
allowedFields: ['*'],
},
$pull: {
allowedFields: ['location', 'grades'],
},
$unset: {
allowedFields: ['address.city'],
},
},
},
},
[ROLES.CUSTOMER]: {
User: {
read_any: {
filter: { _id: { $ne: '=currentUser' } },
allowedFields: ['*'],
deniedFields: ['password', 'role'],
},
read_own: {
filter: {},
allowedFields: ['*'],
deniedFields: ['password', 'role', 'services'],
},
},
}
};
module.exports = grantList;
update
{
"variables": {"setter":{"$set": {"name": "ramesh17"}}},
"query": "mutation($setter: JSON){CustomerUpdateOwn(filter:{_id: \"5d5778bddba2222371172036\"},setter: $setter) { _id email name age }}"
}
Remove
{
"query": "mutation{CustomerRemoveOwn(filter:{_id: \"5d578804de1c752f987a2a20\"})}"
}
insert
{
"query": "mutation{CustomerCreate(name: \"ramesh\", email: \"ramesh.bansal+16@daffodilsw.com\",grades: [35]) { _id email}}"
}
query
{
"variables": {"filter": {"email": {"$in": ["ramesh.bansal@daffodilsw.com","ramesh.bansal+1211@daffodilsw.com"]}}},
"query": "query($filter: JSON){UserAny(filter: $filter, perPage : 10, page: 1, sort: {_id: 1}) { _id createdAt email name customer{_id age} role picture resetPasswordToken emailVerified emailVerificationCode services{ google { url } } }}"
}
Developer just have to declare config for file upload in vars file
fileUpload: {
type: 'local', // local or S3 or db
buckets: {
public: { permissions: { write: 'ANY', read: 'ANY' } },
app: { permissions: { write: ['SUPERADMIN'], read: ['SUPERADMIN', 'CUSTOMER'] } },
authBucket: { permissions: { write: ['CUSTOMER'], read: ['SUPERADMIN', 'CUSTOMER'] } },
},
},
Roles and permission will also work file upload and download
Developer just have to define actions and actions can be called as API
Example action file
const Joi = require('joi');
module.exports = {
/**
* @api {all} v1/dispatch/testing Dispatch Example
* @apiDescription this is example dispatch api for developers at server side
* @apiVersion 1.0.0
* @apiName Testing
* @apiGroup Dispatch
* @apiPermission public or private or role based
*
* @apiHeader {String} Authorization User's access token required for public or role based api
*
* @apiParam {String} Email Email of the tester
* @apiParam {String} name Name of the tester
* @apiParam {String} role Role of the tester
*
* @apiSuccess (Done 200) {Object} response response object
*
* @apiError (Bad Request 400) ValidationError Some parameters may contain invalid values
* @apiError (Unauthorized 401) Unauthorized Only authenticated users
* @apiError (Forbidden 403) Forbidden You are not allowed to access this API
*/
testing: {
public: true,
roles: ['SUPERADMIN'],
joi: {
email: Joi.string().email().required(),
name: Joi.string().max(128),
role: Joi.string().valid(['CUSTOMER', 'ADMIN', 'SUPERADMIN']),
},
dispatch: async ({
params, user, getModel, dispatch,
}) => {
const Users = await getModel('User').get({ filter: { email: params.email } });
return { users: Users };
},
},
};
using public and roles keys you can apply auth and permissions. using joi key you can validate the incoming fields in request params,body and query.
# lint code with ESLint
yarn lint
# try to fix ESLint errors
yarn lint:fix
# lint and watch for changes
yarn lint:watch
# show logs in production
pm2 logs
# generate and open api documentation
yarn docs
Change configuration in .env
file