Skip to content

Latest commit

 

History

History
210 lines (136 loc) · 9.94 KB

README.md

File metadata and controls

210 lines (136 loc) · 9.94 KB

Full-Stack Generator - Express & React

This is a starter project using OpenAPI specifications to bind a NodeJs Express backend and a React frontend, using an `API-first approach - For a quick start, please consult the Cheat Sheet.


Roadmap & Features

Status Item info
Codebase TypeScript & Best Practices
Backend NodeJS, Express
React UI MUI, Chakra, AntD
Authentication OAuth
ORM TypeORM
Authorization Roles: Admins, Common Users
User Profiles Profile information + Image
- Common Users: Edit their profiles
- Admins: Edit all profiles
Background tasks Start, Cancel, Check Status, GET LOGS
Deployment Docker
CI/CD Render Deployment Platform
Unitary Tests -

Technology Stack

Installation Prerequisites

  • NodeJs is the platform that runs the Backend and builds the Frontend
    • NPM is the most popular package manager for the NodeJs ecosystem; to make use of the workspace monorepo architecture this project is built on, make sure you have at least version 7 of NPM installed
  • Java JRE is needed by the OpenAPI generator; if you don't want to install Java, you can still use the generator, via the Docker image:
docker run --rm \
  -v ${PWD}:/local openapitools/openapi-generator-cli generate \
  -i /local/api-bundle.yaml \
  -g typescript-fetch \
  -o /local/packages/generated
  --additional-properties=typescriptThreePlus=true,withInterfaces=true

then compile using:

tsc --project tsconfig.openapi.json 

Backend

  • Express is the most popular NodeJs web framework; the following commonly used plugins have been included:
    • helmet is a utility for setting HTTP headers
    • morgan is a logging utility
    • cors is a utility for configuring cross origin request security
    • express-openapi-validator is a utility for validating API requests against the OpenAPI specification
  • TypeORM is an ORM that supports the DataMapper pattern, which makes is more attractive in combination with the "API first" approach
  • Express JWT and JWKS-RSA are two utilities for verifying a JWT token authenticity, in an OAuth2 / OpenID connect context

Frontend

Both Backend and Frontend use Typescript.


Project anatomy

The project consists of 3 major components:

  • the OpenAPI specification
  • the Backend
  • the Frontend

The OpenAPI specification

This is found in the spec folder.

The up-to-date OpenAPI specification can be found here.

To improve maintainability, the spec is not provided as a single file, but broken into smaller pieces (read more about this here).

To assemble the API bundle, run this in the project root folder:

npm run generate:spec

This will combine all the smaller files into a single api-bundle.yaml. This file is in .gitignore, because we want to always have a single "source of truth" published.

To generate Typescript code from the OpenAPI spec, run the following command in the project root folder:

npm run generate:api

This will create a folder called generated in packages/frontend, based on the typescript-fetch generator. Note that this folder is also present in .gitignore, because the intention is to create it every time, during the CI/CD cycles.

The generated code will include:

  • Models
  • API Interfaces
  • API Client implementation using the Fetch API

The Frontend will use these directly.

The Backend will use them as follows:

  • The TypeORM Entity classes will implement the OpenAPI Models
  • The Services can implement the API interfaces (not possible yet due to this bug)

This will allow both the Frontend and the Backend to fail fast as soon as the API specification is changed.


Note

Upgrade OpenAPI generator version in openapitools.json when this bug gets resolved.


The Backend

The application setup, with the various middleware, the routes, as well as error handling, can be found in index.ts.

The ORM section, including Entities, Repositories and Migrations, can be found in data.

The controllers are in controller.

There's also a middleware folder, which contains any custom middleware you need to add (currently it only contains the Authorization middleware that verifies the Access Token received cryptographically).

The Backend configuration is in the .env file.

This seed is configured with a SQLite persistence.


The Frontend

In addition to the standard CRA output, the Frontend is organized as follows:

Each feature has a folder inside the features folder; each feature folder should contain a React component (.tsx), a Redux slice, with the actions, reducers and side effects, and a test file.

Note that Redux is only necessary for "smart" components, that hold and manipulate a state. "Dumb" components, like nav don't need it.

Don't forget to add your Redux slice in the store to make it functional.

The Frontend also provides a ui folder, that contains the components drawn using the three UI alternatives.

To select one of them, use the corresponding script, in the packages/frontend folder:

npm run select-ui:mui
npm run select-ui:chakra
npm run select-ui:bootstrap
npm run select-ui:antd

This will effectively replace the necessary components, as well as the theme, with the ones from the selected UI.

Feel free to clean this folder once you have decided upon a UI provider (don't forget to also cleanup the package.json, removing unnecessary dependencies).

The Frontend configuration is in the .env file.


Authentication

A special note for the authentication flow: this project uses the Authentication Code flow with PKCE verification. The implementation is in authService.ts and the routes can be protected using the GuardedRoute.tsx wrapper component.

The project is configured with a demo Auth0 client.

Modify the backend .env and frontend .env to contain your IDP configuration.

Here are a few major providers of OpenID Connect / OAuth2 platforms (IDPs):

For the Authentication Code flow, you'll need the following items:

  • the issuer uri, which is a URL provided by the IDP for your tenant
  • the client id, which is an id associated with a certain application where the user performs the authentication (i.e. on the same tenant, you can connect multiple applications and users can authenticate for any of these applications with the same credentials / SSO)
  • the audience, which is the id associated with a certain application that receives and verifies the Access Tokens (i.e. your backend in this case)
  • the scopes, i.e. the privileges you can assign to various users (e.g. write_access, admin_access, etc.)
  • the jwks uri, which is a public resource associated with your tenant, containing the JSON Web Keys (public keys) that can be used to verify the signatures on your JWTs;

Note that all OpenID providers have a .well-known path containing many of the information you require, once you are onboarded (e.g. https://node-seed.eu.auth0.com/.well-known/openid-configuration)

If you want to test the solution locally, you can also use Keycloak, the most popular open source IDP - for example using their Docker guide.



Full-Stack Generator - Express & React, free starter provided by AppSeed