Hello everyone , here I would like to introduce to you a series of articles on Using TypeScript to write security APIs with Node.js and Express. Within 5 articles, it may be incomplete and many errors. Hope you comment comments. I would like to thank.
Overview of posts
- Introduction and initial installation
- Create Modeling Data and Services
- Create Endpoints
- API security
- Rights management
I will turn out the posts.
In the first article Introduction and initial installation , I will guide how to install TypeScript in Node.js and Framework Express using Hot-Module Replacement of webpack.
I will take a specific example of making a website that relates to a restaurant’s menu. Thereby we will learn how to build a fully functional API using Node.js, Express and TypeScript , allowing the client to perform operations with data on resources (here is the restaurant menu). Using TypeScript with Node.js gives you access to optional static type checking along with powerful tools for large applications and the latest ECMAScript features.
In addition, we will learn how to define data models, create data services, and build modular endpoints. We can also use Auth0 to secure the API.
We will use the rule in the business to restrict API access:
- Anyone can read menu items.
- Only admin are allowed to CRUD items in that menu.
For simplicity, I will save the data right in RAM.
content
- Install the project with Node.js and Express
- Install the dependeccy
- Initializing TypeScript with Node.js
- Use env environment variable
- Create Node App with Express using TypeScript
- Set Up Hot-Module Replacement (HMR) for TypeScript with Webpack
1. Install the project with Node.js and Express
You create an arbitrary new directory to contain the project. I named typescript-secure-api
and cd into it
1 2 3 | mkdir typescript-secure-api cd typescript-secure-api |
Next, create a new Node.js project with the default package.json
file
1 2 | npm init -y |
2. Install the dependeccy
We need to require some dependencies to create a secure Express server with TypeScript.
1 2 | npm i express dotenv cors helmet |
- Express : No need to present much. A fast, compact, lightweight framework for Node.js.
- Dotenv : Dotenv is a Zero-dependency module, it loads environment variables from .env file into process.env.
- CORS: An Express middleware. You can refer here .
- Helmet : An Express middleware, securing applications by setting up different HTTP headers, helps minimize common attack vectors.
Install typescript as dependencies
1 2 | npm i -D typescript |
To use TypeScript effectively, you need to install the type definition for the above packages
1 2 | npm i -D @types/node @types/express @types/dotenv @types/cors @types/helmet |
When a package does not have build-in types, you can install the type definition via the @types npm namespace, which stores the TypeScript type definitions in the DefiniteTyped project. When packages are installed, types will automatically be included by the TypeScript compiler.
3. Initialize TypeScript with Node.js
To help the TypeScript compiler understand the project structure, create the tsconfig.json
file in the project folder with the following command
1 2 | npx tsc --init |
That’s all you need to configure this project with default values.
4. Use env environment variables
Instead of using hard-coded configuration variables in files, you can define all those variables in a file and import them into modules if needed. This file is named .env
:
1 2 | touch .env |
In the file, I define the PORT of the server:
1 2 | PORT=7000 |
By using the dotenv package, in any module I can use the local variable defined in the .env file
Note: The .env file may contain sensitive information such as API keys, etc. Therefore, you should add this file to .gitignore.
5. Create Node App with Express using TypeScript
For the project to be well structured, I will add an src
folder
1 2 | mkdir src |
In the src
folder I created a file named endtrypoint.ts
1 2 | touch src/endtrypoint.ts |
Below is the content of the endtrypoint.ts
file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * Required External Modules */ /** * App Variables */ /** * App Configuration */ /** * Server Activation */ /** * Webpack HMR Activation */ |
In each comment section, I will add the following content: Required External Modules
, add the previously installed dependencies and load the environment variables in the .env
file using the dotenv.config()
method
1 2 3 4 5 6 7 8 9 10 11 | /** * Required External Modules */ import * as dotenv from "dotenv"; import express from "express"; import cors from "cors"; import helmet from "helmet"; dotenv.config(); |
For App Variables
, check that the PORT environment variable has been loaded into process.env. If ok, pass its value (number format) and create an instance of Express. If not then exit.
1 2 3 4 5 6 7 8 9 10 11 12 | /** * App Variables */ if (!process.env.PORT) { process.exit(1); } const PORT: number = parseInt(process.env.PORT as string, 10); const app = express(); |
In the App Configuration
section, link the middleware functions in the packages that have been imported into the entry point module.
1 2 3 4 5 6 7 8 | /** * App Configuration */ app.use(helmet()); app.use(cors()); app.use(express.json()); |
helmet
is a collection of 14 small middleware functions that set HTTP Response Headers. The helmet()
does not include all of these middleware functions, but provides default values such as DNS Prefetch Control, Frameguard, Hide Powered-By, HSTS, IE No Open, Don’t Sniff Mimetype, and XSS Filter.
We allow CORS requests using the cors()
method. Then, parse the request as JSON using the express.json()
method, which identifies the request
object with the body
of the already parseed data. Part Server Activation
, create Express server
1 2 3 4 5 6 7 8 | /** * Server Activation */ const server = app.listen(PORT, () => { console.log(`Listening on port ${PORT}`); }); |
6. Set Up Hot-Module Replacement (HMR) for TypeScript with Webpack
The TypeScript compile process can increase boot time. However, if there are any changes in the sourcecode, you do not need to recompile the entire project. We can set up the Hot-Module Replacement webpack (HMR) to significantly reduce the restart time when making changes.
Install Webpack Dependencies for TypeScript
1 2 | npm i -D ts-loader webpack webpack-cli webpack-node-externals |
ts-loader
: Help preprocessing TypeScript files to bundle out Javascript files.webpack
: A bundle module, capable of transforming, bundling, or packaging any tresource or asset.webpack-cli
: module provides a set of commands to speed up the installation of a webpack project.webpack-node-externals
: easily exclude Node.js modules from the webpack bundle.
In the project directory create webpack.config.ts
file
1 2 | touch webpack.config.ts |
With the content below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | const webpack = require("webpack"); const path = require("path"); const nodeExternals = require("webpack-node-externals"); module.exports = { entry: ["webpack/hot/poll?100", "./src/endtrypoint.ts"], watch: true, target: "node", externals: [ nodeExternals({ whitelist: ["webpack/hot/poll?100"] }) ], module: { rules: [ { test: /.tsx?$/, use: "ts-loader", exclude: /node_modules/ } ] }, mode: "development", resolve: { extensions: [".tsx", ".ts", ".js"] }, plugins: [new webpack.HotModuleReplacementPlugin()], output: { path: path.join(__dirname, "dist"), filename: "endtrypoint.js" } }; |
There is a lot to be said in this webpack config file, but I only mention high-level tasks to understand:
- Locate the file entry in the project:
./src/endtrypoint.ts
. - Define the loader webpack needs to compile the source file:
ts-loader
for files ending with.ts
and.tsx
- Define the directory, where the webpack will store compiled source files: directory
dist
Enable Hot-Module Replacement in the Express application
To Enable Hot-Module Replacement (HMR) in the Express server, you need to update the file endtrypoint.ts
. In the file endtrypoint.ts
, at Webpack HMR Activation
1 2 3 4 5 6 7 8 9 | /** * Webpack HMR Activation */ if (module.hot) { module.hot.accept(); module.hot.dispose(() => server.close()); } |
Calm, keep reading below to see bug reports section red hot
.
Here, we notice that the Hot-Module Replacement has enabled via the HotModuleReplocationPlugin for the module defined in endtrypoint.ts
. If HMR is enabled, there will be module.hot
interface in the module, which can be used to perform module operations.
Use interface accept () method to accept updated modules and its dependencies. Then, the interface dispose () method is implemented when the last module is replaced. Delete or exit actions will erase all resources created, such as ending the Node.js application and exiting all existing connections.
Because the moduke
not defined anywhere in the file, the TypeScript compiler will throw an error: The hot
attribute has not been defined. To fix this, we will use ngxs
– an Angular state management library
ngxs
provides a [hmr-plugin](https://github.com/ngxs/store/blob/master/packages/hmr-plugin/src/symbols.ts)
, which is defined for the hotpack webpack module. Please update the Webpack HMR Activation
as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /** * Webpack HMR Activation */ type ModuleId = string | number; interface WebpackHotModule { hot?: { data: any; accept( dependencies: string[], callback?: (updatedDependencies: ModuleId[]) => void, ): void; accept(dependency: string, callback?: () => void): void; accept(errHandler?: (err: Error) => void): void; dispose(callback: (data: any) => void): void; }; } declare const module: WebpackHotModule; if (module.hot) { module.hot.accept(); module.hot.dispose(() => server.close()); } |
Run Node-Express and TypeScript servers
For HMR installation, you need to install 2 more scripts in package.json
file, that is start
and webpack
(note the endtrypoint.js file name)
1 2 3 4 5 6 | "main": "endtrypoint.js", "scripts": { "start": "node dist/endtrypoint", "webpack": "webpack --config webpack.config.ts" }, |
webpack
script will run and configure webpack.config.ts
and bundle the endtrypoint.js
file in directory dist
.
To run, we will open 2 terminal windows, one to call the webpack
1 2 | npm run webpack |
One to call start
1 2 | npm start |
In terminal run start
, display the message “Listening on port 7000” -> OK.
As such, I have finished part one of the Introduction and Initial Installation tutorial for the Series on Using TypeScript to write security APIs with Node.js and Express.
See you in the next posts.