β‘ Mango is a server template which makes it easy to build backend powered by NodeJS, Express, typeorm, typedi and routing-controllers. It minimises the setup time and makes your development cycle faster by using TypeScript. If you were looking for a server template with useful things, Mango is for you π€
Features β’ How to use β’ Structure β’ Changelog β’ Credits
- TypeScript
- TypeScript compiles to clean, simple JavaScript code which runs on any browser, in Node.js, or in any JavaScript engine that supports ECMAScript 3 (or newer).
- TypeORM
- Mango uses TypeORM to map models to your database manager, everything is typed and easier to mantain.
- TypeDI
- Mango uses Typedi for dependencies injection
- routing-controllers
- Every controller has it's own file, you declare your routes with annotations and they get registered on server start.
- JWT middleware (there's a refresh token flow, no need to use 2 tokens!)
- Resource activation protection, if a user doesn't own a resource he won't be able to modify it
- Logging, uses winston, everything gets logged to a file.
- User CRUD and also profile picture upload with multer
- dotEnv variables
- pm2 ready
And many other features
To clone and run this server template, you'll need Git and NodeJS MySQL is also needed (or change the database driver in database.ts file, check TypeORM documentation for a how-to)
# Clone this repository
$ git clone https://github.com/MrARC/Mango
# Go into the repository
$ cd Mango/server
# Install dependencies
$ npm install
# Create .env file
$ cp .example.env .env
# Run the server
$ npm run dev
You may want to use a standard response for all your API calls, you can import the ApiResponse object from handlers/api_response.handler
and create a new instance of it
example:
const response = new ApiResponse(response)
.withData({msg: 'hello'}).withStatusCode(HTTP_STATUS_CODE.OK).build();
A request can have the following properties
Method | Description | Note |
---|---|---|
.withData(object) |
Anything you want | |
.withStatusCode(HTTP_STATUS_CODE) |
HTTP Status code (see HTTP_STATUS_CODE class) | Defaults to 200 |
.build() |
Finish building request | Required to finish building request |
Adding a new module it's easy with plop, just open your console shell, execute:
npm add:module
and follow the steps β
Adding authorization to a route it's easy, just use the @Authorized annotation and add a roles property (can be an array of roles or a single role (or null if you only want to verify if there's a valid JWT token in request), but there's a weight system in place so users with high role can use routes that are for lower roles)
@Post()
// use only @Authorized() if you want to verify only jwt token
@Authorized(RoleType.USER)
public async blabla(@Res() response: Response, @Body({ required: true }) user: User): Promise<Response> {
...
}
I made a sequence diagram to try to explain this process:
Basically there's only one JWT token you will store in the client (web, mobile app, whatever), this JWT token is short-lived (it has a life span of only a few minutes, 15 minutes in production mode), all requests made in that span of time will be passed if the JWT is valid. If the JWT token is expired, Mango will check if is not older than 1 week and will try to update the old token in database and issue a new JWT token with the new parameters, otherwise it will throw a ForbiddenError with a 403 status code. The new JWT token will be present in the server response inside a custom header parameter (X-Auth-Token), this parameter will hold your new JWT token for the new requests.
You will have to implement some logic on your frontend or mobile app to replace the stored JWT token if the header X-Auth-Token is present in the server response, Mango will refuse to update any already updated JWT token and will throw a UnauthorizedError with a 401 status code.
.
βββ docs
β βββ mango.png
β βββ plop.gif
βββ LICENSE
βββ README.md
βββ server
βββ ecosystem.config.js
βββ .editorconfig
βββ .example.env
βββ nodemon.json
βββ package.json
βββ package-lock.json
βββ plopfile.js
βββ plop-templates
β βββ controller.hbs
β βββ repository.hbs
β βββ service.hbs
βββ public
β βββ index.html
βββ src
β βββ api
β β βββ auth
β β β βββ auth.controller.ts
β β β βββ jwt.service.ts
β β β βββ token.model.ts
β β β βββ token.repository.ts
β β βββ common
β β β βββ CUD.ts
β β β βββ CUID.ts
β β βββ health
β β β βββ health.controller.ts
β β β βββ health.service.ts
β β βββ index
β β β βββ index.controller.ts
β β βββ me
β β β βββ me.controller.ts
β β βββ users
β β βββ user.model.ts
β β βββ user_profile_picture.model.ts
β β βββ user.repository.ts
β β βββ user_role.model.ts
β β βββ users.controller.ts
β β βββ user.service.ts
β βββ app.ts
β βββ database
β β βββ database.ts
β β βββ redis.ts
β βββ handlers
β β βββ api_error.handler.ts
β β βββ api_response.handler.ts
β βββ helpers
β β βββ authorization_checker.helper.ts
β β βββ current_user_checker.helper.ts
β βββ logger
β β βββ logger.service.ts
β βββ middleware
β β βββ error.middleware.ts
β β βββ http_logging.middleware.ts
β β βββ not_found.middleware.ts
β βββ utils
β β βββ json.utils.ts
β β βββ upload.utils.ts
β βββ www.ts
βββ tests
β βββ src
β β βββ controllers
β β β βββ index.controller.spec.ts
β β βββ setup.ts
β βββ tsconfig.json
βββ tsconfig.json
βββ tslint.json
- Add JWT token refresh
- Better authorization token flow
- Better project structure
- Better readme
- Create a config file
- Add docker support
- Add GraphQL?
- Add unit test and integration tests (help wanted)
- 0.1 - First release
- 0.1.1 - Refactored authorization function, moved JWT middleware to auth function
- 0.1.2 - Refactored logging system, now it supports context for file, changed the way repositories are created (uses typedi injection), added current user checker, added some validation to me controller, tokens are now deleted when user changes his password or email. Refactored profile upload methods.
- 0.1.3 - Better project structure
- 0.1.4 - Better project structure again, removed graphics magick dependence and replaced it with sharp
- 0.1.5 - Fixed bug with refresh token flow, user would have to make request again to be found by user controller, improved logging
- 0.1.6 - Decoupled database from main server start, fixed load order error with repository injectors in routing-controllers helpers, indented with 2 spaces instead of 4, improved logging, fixed user profile update method