Another ExpressJS API tutorial for 2021, part 12 — Logs with Winston!
Here is our last article on how to built an ExpressJS API with Typescript. We are going to add longs with Winston to make our API more robust!

Hi there, if it is your first time arriving here we are creating a series on how to build an API using ExpressJS and Typescript. The first article can be found here.
Just as a quick overview, here is the series of articles that we are writing:
- Create your hello world ExpressJS API (Yes… we always need to start with a hello world)
- Configure our hello world application to use Typescript (TS is cool, believe me ;) )
- Create our first CRUD API endpoints for an user (Everyone wants a registered user in their applications, no?)
- Create and configure your controllers (We will talk about it after)
- Create and configure your services (What the h. is that?)
- Middleware’s! (Yes, we need and use it everyday)
- End to end testings!
- Configuring a secure way to manage user permissions via API
- Putting all together into a Docker container
- Configuring a simple MongoDB to connect to our application
- Configuring permission level to the application
- Add logs with Winston! — We are here now ;)
Congratulations to reach here! 12 articles is quite a lot but fore sure they have all what you need to start building your own API with ExpressJS and Typescript! In this final article we are going to add Winston logs. To get started, let’s first make sure that we have the last updated branch in this link.
Now, let’s update our package.json as the following:
{
"name": "expressjs-api-tutorial",
"version": "0.0.1",
"description": "Tutorial of how to create a REST API using ExpressJS",
"main": "dist/app.js",
"scripts": {
"tsc": "tsc",
"dev-debug": "nodemon --watch . --ext ts --exec \"npm run tsc\"",
"start": "npm run tsc && node ./dist/app.js",
"test-dev": "nodemon --watch . --ext ts --exec \"mocha -r ts-node/register test/**/*.test.ts\"",
"dev": "nodemon --watch . --ext ts --exec \"docker-compose build && docker-compose up\"",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/makinhs/expressjs-api-tutorial.git"
},
"keywords": [
"REST",
"API",
"ExpressJS",
"NodeJS"
],
"author": "Marcos Silva",
"license": "ISC",
"bugs": {
"url": "https://github.com/makinhs/expressjs-api-tutorial/issues"
},
"homepage": "https://github.com/makinhs/expressjs-api-tutorial#readme",
"dependencies": {
"argon2-pass": "^1.0.2",
"express": "^4.17.1",
"express-winston": "^4.0.2",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.8.11",
"short-uuid": "^3.1.1",
"winston": "^3.2.1"
},
"devDependencies": {
"@types/chai": "^4.2.8",
"@types/express": "^4.17.2",
"@types/mocha": "^7.0.1",
"@types/mongoose": "^5.7.0",
"@types/node": "^13.5.2",
"@types/supertest": "^2.0.8",
"chai": "^4.2.0",
"mocha": "^7.0.1",
"nodemon": "^2.0.2",
"source-map-support": "^0.5.16",
"supertest": "^4.0.2",
"ts-node": "^8.6.2",
"tslint": "^6.0.0",
"typescript": "^3.7.5"
}
}Now run npm install and we will have all needed dependencies.
We will easily add the log configuration at the app/app.ts file as the following:
import express from 'express';
import * as http from 'http';
import * as bodyparser from 'body-parser';import {CommonRoutesConfig} from './common/common.routes.config';
import {UsersRoutes} from './users/users.routes.config';
import {AuthRoutes} from './auth/auth.routes.config'import * as winston from 'winston';
import * as expressWinston from 'express-winston';const app: express.Application = express();
const server: http.Server = http.createServer(app);
const port = 3000;
const routes: any = [];app.use(bodyparser.json({limit: '5mb'}));let index = expressWinston.requestWhitelist.indexOf('headers');
if (index !== -1) expressWinston.requestWhitelist.splice(index, 1);app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'GET,HEAD,PUT,PATCH,POST,DELETE');
res.header('Access-Control-Expose-Headers', 'Content-Length');
res.header('Access-Control-Allow-Headers', req.header('Access-Control-Request-Headers'));
if (req.method === 'OPTIONS') {
return res.status(200).send();
} else {
return next();
}
});app.use(expressWinston.logger({
transports: [
new winston.transports.Console()
],
format: winston.format.combine(
winston.format.colorize(),
winston.format.json()
)
}));// routes definition should be placed here
routes.push(new UsersRoutes(app));
routes.push(new AuthRoutes(app));app.use(expressWinston.errorLogger({
transports: [
new winston.transports.Console()
],
format: winston.format.combine(
winston.format.colorize(),
winston.format.json()
)
}));app.get('/', (req: express.Request, res: express.Response) => {
res.status(200).send(`Server running at port ${port}`)
});server.listen(port, () => {
console.log(`Server running at port ${port}`);
routes.forEach((route: CommonRoutesConfig) => {
console.log(`Routes configured for ${route.getName()}`);
});
});export default app;And that’s it, we need only to run npm run dev and we will see that we have more the logs module working now. What you will want to do with it now will depends only on you, either to save it in a noSQL database or to use it into an elastic search.
In this last article we demonstrated how to easily add a nice way to configure and use logs with Winston. At the end of this series of articles on how to create an ExpressJS API with Typescript you are expected to:
- Create separated modules to have a better code maintenance;
- Manage Auth and Permission Levels;
- Create as many routes as you wish;
- Add new resources;
- Manage the logs from who are using your API;
- Manage your database with MongoDB;
Thanks for reading all of my 12 articles and have fun coding!
tips:
- don’t forget to use a nice app to test your API such as Postman or Insomnia
- I know you still didn’t… Read the ExpressJS documentation!
- Learn Docker, start at their Documentation!
- Learn Mongoose, start also at their Documentation!
- Complete project is here! (Includes even the non existing articles yet)
What’s next? Give a try to NestJS with my new articles series!
