Skip to content

This project is a shortener of URL I have done in a interview for a job. Since the project was quite cool and interesting, I pushed it further and try to make a project the most complete as possible. The project has typescript, unit test, smoke test, e2e test, tyescript coverage, dockerization, documentation, sonar analyzis and a lot of other th...

Notifications You must be signed in to change notification settings

JustalK/SHORTENER

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SHORTENER

Goal

This project is a shortener of URL I have done in a interview for a job. Since the project was quite cool and interesting, I pushed it further and try to make a project the most complete as possible. The project has typescript, unit test, smoke test, e2e test, tyescript coverage, dockerization, documentation, sonar analyzis and a lot of other things...

For this project, I have used Nx to create the structure, React for the frontend, Express for the backend and cypress, jest for the testing. I have also used sonar, docker, docker-compose. For the database, I have used mongodb and mongoose as an ORM.

Plan of the presentation

I explain with all the details how I build the project and my way of working.

Development

Sharing interface between projects

Create a library at the root of the project using NX command:

$ nx generate @nrwl/js:library types

A path pointing to the lib will be added in tsconfig.base.json. Since the other tsconfig are extending the tsconfig base, the path will be available in each project.

Setting Swagger for api documentation

In order to be able to use swagger, we install the dependencies:

$ npm i swagger-jsdoc swagger-ui-express --save-dev

We then, set up the extensions in server.ts and put the options in the folder docs:

const specs = swaggerJsdoc(options);
this.#app.use(
     `/${ENVIRONMENT.API.VERSION}/docs`,
     swaggerUi.serve,
     swaggerUi.setup(specs)
);

And finally, we put the documentation of the api as close as possible as the api endpoints in routes.
The documentation can be consulted at: http://localhost:3333/v1/docs

0.png

Setting Jest for unit tests and coverage

Backend

In order to configure the test on the shortener-api, you need to add a target in the project.json of the shortener-api project:

    "test": {
      "executor": "@nx/jest:jest",
      "outputs": ["{workspaceRoot}/dist/apps/coverage-test-backend"],
      "options": {
        "jestConfig": "apps/shortener-api/jest.config.ts",
        "codeCoverage": true,
        "collectCoverageFrom": ["src/**/*.{ts,tsx}"],
        "coverageReporters": [
          "clover",
          "json",
          "lcov",
          "text-summary"
        ],
        "passWithNoTests": true
      }
    }

Once done, we also need to modify in ``jest.config.ts, the coverageDirectory` in order to move the lcov result in the dist directory in order to be able to access through the express server:

{
     "coverageDirectory": "../../dist/apps/coverage-test-backend",
}

Finally, in the express server, we add the route to serve our index as a static resource:

    this.#app.use(
      `/${ENVIRONMENT.API.VERSION}/test/backend`,
      express.static(__dirname + '/../coverage-test-backend/lcov-report')
    );

In order to generate the result, run the following command:

$ nx test shortener-api
# OR
$ npm run test-unit-backend

You can then access the result through the url: http://localhost:3333/v1/test/backend/

PS: Since we are using the "test" command, the environment variable is "test". The environment file need to be set in consequence.

0.png

PS2: If some test such as import let the server open, it's possible to force the exit and to make the test pass with this command

nx test shortener-api --detectOpenHandles --forceExit 
Frontend

For the react app, it's easier. Jest is already setup. However, we need to modify a bit the config in vite.config.mjs. In the section test, we can add the following:

    test: {
      coverage: {
        reportsDirectory: '../../dist/apps/coverage-test-frontend',
        enabled: true,
        provider: 'v8',
      },
    },

Once done, we can add the route to serve our index as a static resource:

    this.#app.use(
      `/${ENVIRONMENT.API.VERSION}/test/backend`,
      express.static(__dirname + '/../coverage-test-backend/lcov-report')
    );

In order to generate the result, run the following command:

$ nx test shortener
# OR
$ npm run test-unit-frotend

You can then access the result through the url: http://localhost:3333/v1/test/frontend/

Typescript

Backend

For checking my level of coverage of the typing, I am using the package typescript-coverage-report.
The coverage has been push till 100%. Everything has been typed properly.

$ npm i typescript-coverage-report --save-dev

To create the coverage page, simply run the following command:

$ npm run ts-coverage-backend

0.png

If you want more information, the report can be watch through the api once the previous command has been run at least once:

$ nx server shortener-api

You can then look the report at this URL: http://localhost:3333/v1/typescript/backend/

1.png

Absolute Path

Backend

In order to make absolute path possible, you need to config in the file tsconfig.json of each project the following properties:

    "baseUrl": ".",
    "paths": {
      "@controllers/*": [
        "./src/controllers/*"
      ],
    }
Frontend

For the frontend, it's exactly the same as for the backend with one difference.
The plugin vite-tsconfig-paths need to be install and configure in vite:

$ npm i -D vite-tsconfig-paths

Then in vite.config.mjs, just add the plugin:

    plugins: [
      tsconfigPaths(),
    ],

Then, it's possible to add the path using the following typo:

import Home from '@pages/Home/Home';

Organization

Organization of the project

.
├── .nx                               # Cache NX
├── apps                              # Contains all the apps of the project
     └── mongodb                      # The script for setting up the mongodb
     └── shortener                    # The react frontend
            └── locales               # The json file for i18n (multi language)
            └── src                   # The source file
                 └── app              # The app entrance file
                 └── assets           # The asset of the project
                 └── components       # The reusable component
                 └── interfaces       # The interface for typescript
                 └── pages            # The page for the project
                 └── services         # The services for calling the backend
                 └── styles           # The style of the frontend
     └── shortener-api                # The express backend
            └── src                   # The source file
                 └── controllers      # The controllers of the api
                 └── daos             # The data object validating the parameter of the entering request
                 └── docs             # The options for the swagger
                 └── interfaces       # The interface for typescript
                 └── libs             # The libs containing constant, logger and utils
                 └── models           # The model to save in the database
                 └── repositories     # The repository allowing operations to the db
                 └── routes           # The routes allowed by the api
                 └── services         # The services of the backend
     └── shortener-api-e2e            # The tests for the express backend (jest)
     └── shortener-e2e                # The tests for the react frontend (cypress)
├── env                               # Environment file
├── scenarios                         # The scenario for the load testing
├── seeding                           # Seed the database for the test
├── nginx                             # Contains the configuration for reverse proxy
├── node_modules                      # Contains all the dependencies of the two projects (monorepository)
├── .dockerignore                     # The file to ignore for docker
├── .eslintrc                         # The configuration for the linter
├── .prettierrc                       # The configuration for the prettier
├── docker-compose.yml                # File for managing the creation of container for docker
├── Dockerfile                        # Creation of container for our apps
├── nx.json                           # Setting of nx
├── package.json                      # Npm configuration file
├── package-lock.json                 # Npm locker version for module
├── tsconfig.base.json                # Shared configuration for typescript
├── vitest.workspace.json             # Shareed configuration if multiple frontend
├── LICENSE                           # Description of the license
└── README.md                         # Presentation for the project

Prerequisite

The project where the project will be running need to have the following too:

  • Node 20 or Volta
  • Npm 10 or higher
  • Docker
  • Docker Compose
  • nx
$ npm add --global nx@latest

Development

Without Docker

In dev mode, the user need to have at least mongoDB setup on his machine Before starting the development mode without docker

$ npm install

In the terminal, type the following command:

$ npm run dev
With Docker

Since the production mode compile the project at every restart and since the project is small. Without any installation needed, the user can the project using:

$ npm run up

In order to be the closest of possible of the production, modify the /etc/hosts with the following:

127.0.0.1 shortener.net mongodb server1

Production

In the terminal, type the following command:

$ npm run up

Limit

  • The project does not ensure the unicity of the short url. It means that if the short url unfortunaly has been generated with one already existing, the url will be replace through an update.

System

Ubuntu Version: Ubuntu 20.04.1 Node Version: v20.11.1 Npm Version: v10.5.0

The version are manage with Volta.

# Get the latest version of ubuntu
$ lsb_release -a

# Get the version of node
$ node -v

# Get the version of npm
$ npm -v

Errors

If your computer has not enough memory, in some case, the deamon of NX can fail to start or restart. In such case,
you can run the following command to clean up the project:

$ nx reset

About

This project is a shortener of URL I have done in a interview for a job. Since the project was quite cool and interesting, I pushed it further and try to make a project the most complete as possible. The project has typescript, unit test, smoke test, e2e test, tyescript coverage, dockerization, documentation, sonar analyzis and a lot of other th...

Topics

Resources

Stars

Watchers

Forks