Express + Typescript + Mongo – Part 1 – Getting Started
About a year ago, I wrote a series where I showed how to create a very simple “To Do” client and server application. The server was written in Java and used JEE and MySQL. I’d like to revisit this and rewrite the server piece using Express, TypeScript, and Mongo.
So, let’s get started!
If you don’t have it running already, go ahead and run the AngularJS To Do front-end.
The next thing you’ll need is an installation of NodeJS. Once you have that, create a new folder then run the npm init command.
Now, we’re going to add a few dependencies:
npm install --save express ts-node typescript cors body-parser npm install --save-dev @types/express @types/node nodemon
Create a new folder, called “src” at the root of the project, then add a new file: app.ts. This file is where we define our Express server and all of its endpoints and middleware.
Copy and paste the following code into that file:
import * as express from 'express'; import * as cors from 'cors'; import * as bodyparser from 'body-parser'; const app = express(); app.use(cors()); app.use(bodyparser.json()); // TODO - Add more middleware export { app }
Here, we’re just constructing a new Express server with CORS support and we’re also adding middleware that will convert all HTTP body data into JSON on our express request object for each of the routes we’ll be defining later.
Next, create another file, main.ts in the src folder as well. Add the following contents to it:
import { app } from './app'; import * as http from 'http'; const port = 8080; const server = http.createServer(app); server.listen(port); server.on('error', (err) => { console.error(err); }); server.on('listening', () => { console.info(`Listening on port ${port}`); });
This is our “entry point” file and will start our express server on port 8080. It will also print out some text once it’s started.
The next thing we need to do is modify our package.json file and add the following script:
"start": "nodemon -x ts-node src/main.ts"
This script will automatically restart the server if a file changes and will allow us to execute TypeScript files. We could get fancier but the default configuration is good enough for now.
If you run the server now — by invoking npm run start at the command-line — you’ll see it doesn’t really do much for the moment. Let’s change that by adding some logging for every request. To do this, we’ll need to create our own “middleware”.
Create a new file in the src folder called “request.logger.middleware.ts” with the following contents:
import * as express from 'express'; const requestLoggerMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => { console.info(`${req.method} ${req.originalUrl}`); const start = new Date().getTime(); res.on('finish', () => { const elapsed = new Date().getTime() - start; const msg = `${req.method} ${req.originalUrl} ${res.statusCode} ${elapsed}ms`; console.info(msg); }); next(); } export { requestLoggerMiddleware };
This will simply print the HTTP method and URL of the request when the request first comes in and when the response goes out. I’ve gotten into the habit of logging both of these as it helps you better identify the window in which a request has been handled by the server and any problems it may have encountered in between.
Open app.ts up again and import our new file by adding the following line near the top:
import { requestLoggerMiddleware } from './request.logger.middleware';
Now, we have to inject the middleware we just created by adding the following line towards the end (but before the export!):
app.use(requestLoggerMiddleware);
If you save those files, the server should pick up the changes automatically. Assuming it did, if you open your browser to http://localhost:8080/todo, you should see something like GET /todo 404 in the console window.
The last thing we’ll do in this article is define the endpoints we’ll be working with. In app.ts, paste the following code in near the end:
app.get('/todo', (req: express.Request, res: express.Response, next: express.NextFunction) => { res.status(200); res.json([{id: 1, description: 'Buy Bread'}]); }); app.post('/todo', (req: express.Request, res: express.Response, next: express.NextFunction) => { console.info(`${JSON.stringify(req.body)}`); res.status(200); res.end(); }); app.put('/todo/:id', (req: express.Request, res: express.Response, next: express.NextFunction) => { console.info(`${JSON.stringify(req.body)}`); console.info(`:id = ${req.params.id}`); res.status(200); res.end(); }); app.delete('/todo/:id', (req: express.Request, res: express.Response, next: express.NextFunction) => { console.info(`:id = ${req.params.id}`); res.status(200); res.end(); });
Here, we just re-defined the API we originally created in the JavaEE project. We’re also logging the data that we’ll need to complete these APIs in the next article. If you play around with the client application, you should be able to see logging for each of these endpoints.
That’s it for this part, in the next part, we’ll tie in Mongo.
Source code is available here: