Our first official release is out!!
Today I’m thrilled to announce the first official release of nodevader, a nodeJS boilerplate to get your backend API started in few minutes.
If you’re already a user of express framework, will be at home.
Icon by Filipe Carvalho
Why nodevader
Nodevader boilerplate helps developers to increase productivity and reduce time to get things done thanks to it’s minimalist concept. The main goal here is to define patterns for basic concepts for an uncoupled backend API and good practices for development.
Reasons to use it
It’s based on express framework 4.x, which is the most nodejs framework used in this galaxy. It works on node version v10.x.
Now take a look at the main features we have for now:
- NPM as the package manager. Take a look here
- Express framework as the core
- Serving with Nodemon or PM2
- Eslint Standard JS pattern for code standards
- Knex query builder and some utils methods on utils/database.js (mysql and postgres support)
- Run migrations using docker-compose using boxfuse/flyway image
- Mustache template transpiler
- i18n take a look
- Moment for date and time
- Mocha & Chai for testing
- Winston for logs
- Axios Http Request
- JWT standard for Authentication
- Firebase Storage bucket and Firestore database
- Send emails using SMTP lib Nodemailer and html templates with mustache
- Express config with Cors enabled, cookie and body parser, helmet headers
- Docker-compose and dockerfile attached running migrations e starting database and nodejs
Deeper look at some features
Let’s get deep into some examples of use.
Serving the app
You may serve for
# development (Nodemon)
npm run dev
or
# production (PM2)
npm run prd
Config and enviroment
Main configurations of the app are defined on src/config/index.js
file. Some config are using dotenv package which get config from .env file on app’s root.
There’s a .env.example in app’s root with config samples. You can rename it to .env to get started.
Good practice: Keep app’s config (used in any ambient) centered in this file and enviroment variables in .env
file.
const appConfig = {
server: {
port: process.env.HTTP_PORT || 3000
},
cors: {
origin: '*',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
preflightContinue: false,
optionsSuccessStatus: 204
},
template: {
showCompiled: true,
...
Style guide
JavaScript style guide, linter, and formatter from Standard JS. Consistent code. Catch style issues & programmer errors early.
ES lint config is defined in /.eslintrc.json
file.
Express config
There’s some pre-defined config for express to make it more complete. We have cors enabled, cookie and body parser and helmet headers.
Template transpiler
If you need a template transpiler, use Mustache. We have some utilities to make it easier to deal with templates. Take a look:
const mustacheUtils = require('./utils/mustache')
const params = {
id: 1
}
mustacheUtils.getTemplateSQL(dir + filename, params).then(query => {
console.log(query)
}).catch(error => reject(error))
And a template sample:
select
id,
name
from
user
where
1 = 1
{{#id}}
and id = :id
{{/id}}
Internacionalization
Use this i18n package to deal with internacionalization. Take a look at the use case with the utility we build on top of i18n:
const i18nUtils = require('./utils/i18n')
console.log(i18nUtils.translate('Hello'))
You can find the json definitions in src/config/i18n-locales/
folder. There you have files for each language.
{
"Hello": "Hello World!",
"system_error": "Hillston, we have a problem.",
...
}
Logs
For better logging, use Winston package. And… here you have a sample from our utility.
const loggerUtils = require('./utils/logger')
loggerUtils.error('Error!!')
loggerUtils.info('Error!!')
Logs will be written in /logs
on root folder of repository.
Http requests
For better support and performance, we recommend to use Axios package for Http Request.
const loggerUtils = require('./utils/httpRequest')
const params = {
url: 'https://i.imgur.com/lljnHdR.mp4'
}
// do a request
httpRequestUtils.get(params).then((response) => {
console.log(response)
}).catch((error) => console.log(error))
Authentication and Authorization
We choose JWT package to secure our application by default.
To get started, you’ll need to add a privateKey to your /src/config/index.js
file. Then you
To manage authenticated routes, go to /src/routes/index.js
file which contains authMiddleware file.
JWT methods are implemented at /src/utils/jwt.js
file.
Before using it, you have to create a method to login your user so you can finally use generate token.
const jwtUtil = require('./utils/jwt')
// create your custom `login` method
login().then(userData => {
// return user data you want to store inside token
jwtUtil.generateAuthToken(userData).then(responseToken => {
// here you get user token
console.log(responseToken)
}).catch(error => console.log(error))
})
Database
We’re using Knex package to manage database connectors and be our database persistence layer. It has query builder built in and we wrote some utilities on utils/database.js
.
These utilities have support for mysql
and postgres
at this time. You can extend support via knex to oracle, sqlite and other.
Here some methods implemented over the builder.
const databaseUtils = require('./utils/database')
const params = {
id: 2
}
// executing a query
// from a file located in [src/templates/sql]
// transpiled by mustache
databaseUtils.namedQuery('getUser', params).then(response => {
console.log(response)
}).catch(err => console.log(err))
const fields = {
name: 'Fulano de tal',
email: 'fulano@detal.com'
}
const fields = [
'name',
'email'
]
// insert data into a table
databaseUtils.basicInsert('user', data, fields).then(response => {
console.log(response)
}).catch(err => console.log(res, err))
Database migrations runner
You can run migrations using docker-compose. We have boxfuse/flyway image configured.
Once you start the containers, flyway container will look for migrations folder and run migrations.
# get containers up
docker-compose up
Migrations file are stored at /docker/migrations
folder.
Firebase utils
In addiction to demonstrate a sample of good practices implementing a utilities module and deal with a NoSQL database and CDN file storage, we built this firebase module based in firebase Storage bucket and Firestore database packages.
Take a look at these two use cases bellow:
const firebaseUtils = require('./utils/firebase')
const fileUtils = require('./utils/file')
const collection = 'myFirstCollection'
const data = {
message: 'Hello World!!'
}
const document = 'myDocument'
// create or update a document from a collection
firebaseUtils.createOrUpdateDocument(collection, data, document).then((response) => {
console.log(response)
}).catch((error) => console.log(error))
// upload a file
sampleRest.get('/upload', fileUtils.multer.single('file'), (req, res) => {
const file = req.file
if (file) {
firebaseUtils.uploadFile(file).then((urlFile) => {
console.log(urlFile)
}).catch((error) => console.log(error))
}
})
Send emails easily using SMTP package Nodemailer and html templates with mustache.
Take a look at this sample using our utility.
const smtpUtils = require('./utils/smtp')
const emailData = {
to: ['friend1@nodevader.com', 'friend2@nodevader.com'],
subject: 'Hello ✔✔✔',
template: 'helloWorld', // this file is located on [src/templates/smtp] folder
templateContainer: 'container',
params: {
name: 'Fulano'
}
}
smtpUtils.sendMail(emailData).then((response) => {
console.log(response)
}).catch((error) => {
console.log(error)
})
Utity tests
It’s a good practice to have unity tests of your app. We choose Mocha & Chai for our testing universe.
We need to have some sample cases described in repository. Theres an issue open with a list of good samples to do. Feel free to contribute.
Take a look how is that easy to implement a unity test using chai:
const chai = require('chai')
const someService = require('../api/someService/service')
const expect = chai.expect
describe('Some service tests', () => {
it('Should return a list of one single item', () => {
expect(someService.getData).to.have.lengthOf(1)
})
})
There’s one more thing
Feel free to fork or contribute to nodevader!! You’re very welcome! There’s some issues to run in backlog and you can always open new ones.
We’ll keep you updated of new releases.
Thanks for reading!
Nodevader team.