TypeScript and Node.js - basic project setup and structure

Emilia Tyl bio photo By Emilia Tyl Comment

It’s time to introduce the first part of my project – a microservice for downloading weather data from a weather API provider. In this post I will explain my setup and provide steps for running my project if anyone would like to play with it. The folder structure may be a little bit overkill, because I’ve recently created a much more complicated solution at work, which requires for example dealing with different environments (testing/staging/production). I didn’t want to just leave one or two scripts since I kind of like the way I have it organized, so I stick to it. I noticed that there are many beginner developers taking part in GetNoticed! contest, some of them even having their first touch with programming, so I will try to explain everything that may be confusing. So do not frown with compassion when I’ll write about something obvious for you. ;)

Why TypeScript?

Source code is written in TypeScript, which is then transpiled to JavaScript. Why am I using TS instead of JS? Well, I’ve already written two backend services in JavaScript and have it running on production, but I really do not like how my code is organized there. I know that ES6 and ES7 (new versions of JavaScript that introduce classes and so on) are more appealing than vanilla JS, especially for someone with C# roots, but somehow I still feel this is all artificial, since there is no real control over types. And I like being controlled. TypeScript is – optionally - statically typed (static vs dynamic & strong vs weak), supports type inference (concluding the variable type by its declaration – “var”) and my bellowed Visual Studio Code is getting more and more efficient in analyzing code and showing hints.

Since it is transpiled to JavaScript, I didn’t have to make any changes to the process of deployment that I had created at work and I also works with all of the JS packages. Community has created a typings package for almost every one of them, so we can have them typed too. That’s also really helpful when using such packages as lodash, when we have to constantly search for some methods and its usage. Well, at least I have, since lodash/underscore and Linq left me with a complete mindfuck when it comes to naming a method for example sorting things.

Transpile/compile

I mentioned earlier that TypeScript is transpiled to JavaScript. You may ask, how is it different from compiling? Well, the difference lies in a definition. We say that language A gets compiled to language B, when they operate on different levels of abstraction. For example, when we compile a C# app, we get the IL instructions, which operate on much lower level. Similarly, C get compiled to machine code and Java to Java bytecode. On the other hand, when language gets transpiled, it’s usually a matter of different syntax.

Running my project

I’m sorry Linux and OSX fans, but I’m using Windows, so it’ll work only on Windows for now. As far as I’m concerned the difference can be in defining chained commands in the npm scripts (start and setup).

If you want to play around with my microservice project, you need to do following steps:

1. Download the Node.js from here

I like Windows installer as it also install the Node Package Manager (npm) and adds both node and npm to PATH, which makes it possible to use them from command line from any directory.

2. Clone the repository

In the command line run: git clone https://github.com/Harriet92/AmbientWeather.git

3. Navigate to the ApiServer directory
4. Open a command line there (if you’re not already using it)

If you have the directory opened you can click right button when holding shift and select “Open in command line” option.

5. Type “npm run setup”

This will do several things:

• install npm packages – both the ones used in the source code and also the ones that are needed for example for downloading typings packages or running buil scripts (gulp). The script knows which packages it should download thanks to the package.json file.

• install typings packages – accordingly to the typings.json file.

6. Type “npm start”

It will also do several things:

• “compile” (we all now know that it’s in fact transpiling) the project and save the result under the “dist” directory. For compiling I use gulp. Again, it’s a bit of overkill for now, since in fact we only need to invoke the “tsc” – Type Script Compiler.

• run the program by invoking “node ./dist/index.js” command. Index.js is our “Main” file.

If there are no errors in the console, the server is probably working. :)

You can check this by navigating to your browser and typing “localhost:4000/healthCheck”. You should see the “Server running” text.

Dive inside the source code

At the moment of writing this post, there is nothing more in the repo than basic configuration. So lets see what had to happen to display that message for us.

1

Configuring constants

Right now I will only use the Test configuration, but eventually the right one would be chosen depending on the NODE_ENV variable. It can contain such information as our app port, db connection string or logs directory. More secure solution would be for example reading the DB config from the environment variable. In case of a hacker attack, if someone somehow got file reading privileges, he or she would get to know the db connection credentials. In this file we’re defining the configs, in the next one we’re injecting the one that is used right now.

The next file is just an enum for environments. The next one, GlobalParameters will contain information about the NOVE_ENV variable or for example information about the OS that the server is running on (eg. for setting up logs).

Configuring middlewares

Middlewares are programs that catch the request, do something with it and pass it forward. I’m using Express as a web application framework, so setting them up is really easy. Right now I’m only using body-parser, to get my requests translated to json. Thanks to that, when I get my request parameter in handlers, it already has a neat “body” property that I can easily read. The MiddlewareBase file is also a place where I set up the base, common routes, as for now only the health check route (which is very important btw, for setting up downtime alarms, for example using NewRelic). The CommonRoutes and HealthCheckRoute files contain detailed routes tree setup.

import * as express from "express";
import * as bodyParser from "body-parser";

import CommonRoutes from "./../routes/CommonRoutes";

export default class MiddlewaresBase {

    static get configuration() {
        let app = express();
        app.use(bodyParser.urlencoded({
            extended: true
        }));
        app.use(bodyParser.json());
        app.use(new CommonRoutes().routes);

        return app;
    }
}
Object.seal(MiddlewaresBase);
Running the app

Last, but not least – our Main file. It just runs Node.js app.

/// <reference path="../typings/index.d.ts" />


import * as express from "express";
import Middlewares from "./common/config/middlewares/MiddlewaresBase";
import Constants from "./common/config/constants/Constants";


let app = express();
let port = Constants.PORT;

app.set("port", port);
app.use(Middlewares.configuration);

app.listen(port, () => {
    console.log("Node app is running at localhost:" + port);
});

You probably noticed this line of code

/// <reference path="../typings/index.d.ts" />

It has to be added at the begging of every file for the TypeScript to know where to look for typings definitions. If you have some strange error messages, saying that some package is not installed when in fact they are, there is a possibility you forgot about that. :)

That’s it for now. There are many crucial things missing right now – for example logs set up or data access, but I want to have my thermometer up and running as soon as I can. The next step will be downloading weather data from API and storing it in the Redis database.

And as always - like my fan page or follow me on Twitter to get notified when future posts appear. (。◕‿◕。)

comments powered by Disqus