In this post, I would like to talk about the open source work at e.GO Mobile.

Many projects, which are not open source themselves, such as many of our in-house projects, are based on this type of software.

Examples for this are:

Therefore, it is consistent for the company to also dedicate itself to this topic: on the one hand, to become more well-known and to emphasize its role as a software-driven company … on the other hand, to receive feedback on the code.

Today, I would like to introduce 2 projects that are used in many of our projects:

For this, I have set up a small GitHub repository that shows how to set up a small backend project with:

Backend

I have built the backend in Node.js using our own module @egomobile/http-server, which is officially available on NPM.

The API is very similar to Express.js and supports the most important things, such as:

  • routing with parameters
  • middlewares

With just a few lines of code, you can build an HTTP server that, unlike Express, does not have all the overhead.

To do this, you first need to install the module in your project:

npm install @egomobile/http-server --save

The following “Hello, world!” example shows that there are not many differences to Express:

import { createServer } from "@egomobile/http-server"
// npm i cors && npm i -D @types/cors
import cors from "cors"

const app = createServer()

app.get(
    "/",
    [cors()], // use common middlewares, like `cors`
    async (request, response) => {
        // request: https://egomobile.github.io/node-http-server/interfaces/IHttpRequest.html
        // response: https://egomobile.github.io/node-http-server/interfaces/IHttpResponse.html
        
        response.write("Hello, world!")
        // a `response.end()` call is not needed anymore
    }
)

await app.listen(8080)
console.log("Server now runs on port", app.port)

What we now have is a HTTP server, with a GET endpoint for the route http://localhost:8080/.

PostgreSQL connection

For the connection to a PostgreSQL database, we use 2 self-written modules, which can also be found on NPM:

These provide, just like the HTTP module, a simple and fast API without much overhead and incompatible features, as is the case with TypeORM, for example.

These can be installed again using tools such as NPM or Yarn:

npm install @egomobile/orm --save
npm install @egomobile/orm-pg --save

Both provide us with functions to establish connections to databases, create migration scripts, and map data to simple class objects.

The file /src/databases/postgres/index.ts should demonstrate how we configure our projects for this purpose:

import {
    createWithPostgres,
    registerBigIntAsNumber
} from "@egomobile/orm-pg";
import pg from "pg"

// bigint e.g. is returned as string, so we can keep sure to have a number here
registerBigIntAsNumber({
    "pgModule": pg
})

// in this folder we organize the POCOs
import getDefaultEntityConfiguration from "./entities/default"

// `createWithPostgres` is a factory function that creates
// a new PostgreSQL connection with specific configuration
// organized by connection names
export const withPostgres = createWithPostgres({
    "default": {
        "client": () => {
            // this is the default and lets
            // `pg` module load the connection settings from
            // following environment variables:
            //
            // - PGDATABASE
            // - PGHOST
            // - PGPASSWORD
            // - PGPORT
            // - PGSSLMODE
            // - PGUSER
            // - PORT

            return {};
        },
        "clientClass": pg.Client,
        "entities": getDefaultEntityConfiguration,
        "noDbNull": true
    }
})

Migrations

In case we need to update the database structure, we simply call the script migration:create, which creates a new migration script in the /database/migrations/scripts folder for us:

npm run migration:create MyNewMigration

An implementation could later look like this, for example:

import type { MigrationAction } from "@egomobile/orm-pg";

const logTable = "logs";

/**
 * Function to UP-grade the database.
 */
export const up: MigrationAction = async (adapter, context, debug) => {
    // adapter => https://egomobile.github.io/node-orm-pg/classes/PostgreSQLDataAdapter.html
    // context => https://egomobile.github.io/node-orm/interfaces/IDataContext.html
    // debug => https://egomobile.github.io/node-orm-pg/modules.html#DebugAction

    await adapter.query(`
CREATE TABLE public.${logTable}
(
    "id" bigserial NOT NULL,
    "uuid" uuid DEFAULT uuid_in(md5(random()::text || random()::text)::cstring) NOT NULL,
    "message" json,
    "time" timestamp with time zone DEFAULT now() NOT NULL,
    "type" smallint
)
WITH (
    OIDS = FALSE
);
`);
};

/**
 * Function to DOWN-grade the database.
 */
export const down: MigrationAction = async (adapter, context, debug) => {
    // adapter => https://egomobile.github.io/node-orm-pg/classes/PostgreSQLDataAdapter.html
    // context => https://egomobile.github.io/node-orm/interfaces/IDataContext.html
    // debug => https://egomobile.github.io/node-orm-pg/modules.html#DebugAction

    await adapter.query(`DROP TABLE public.${logTable};`);
};

In the NPM start script, all migrations that still need to be executed are called every time the server is booting.

Start the demo project

Before you can start the demo project, you have to install Docker with docker-compose.

After this, run

docker-compose up

from the repositorie’s root directory inside a “terminal” and use tools like Postman or REST Client for Visual Studio Code to access the endpoints as defined in /src/handlers folder.

Conclusion & outlook

As you can see, it is easy to setup a stable, fast and powerful API and database support with relatively few lines of code.

We at e.GO only need a little time and are not dependent on external developers for such critical modules.

Have fun trying it out! 🎉

P.S.: In an upcoming post I will write about our controller framework we use, which is also part of @egomobile/http-server