项目作者: asad-mlbd

项目描述 :
Deno RESTful API project starter for oak framework
高级语言: TypeScript
项目地址: git://github.com/asad-mlbd/deno-api-starter-oak.git
创建时间: 2020-05-29T20:45:49Z
项目社区:https://github.com/asad-mlbd/deno-api-starter-oak

开源协议:

下载


Deno RESTful API using OAK

logo

This is a starter project to create Deno RESTful API using oak. oak is a middleware framework and router middleware for Deno, inspired by popular Node.js framework Koa and @koa/router.

This project covers

  • Swagger Open API doc
  • Docker container environment
  • JWT authentication
  • User authorization
  • Request validation
  • .env config management
  • Coding architecture with Router, Service & Repository layers
  • Application Error Handling
  • Request timing logging
  • Generic request logging

1) Setup
2) Migrations
3) Modules
4) Project Layout
5) How to add a new route
6) How to validate request body
7) How to use JWT authorization
8) How to add auth guards
9) Error handling
10) Contributing
11) Contributors
12) Roadmap

Setup

We can run the project with/ without Docker.

  • Pre-Requisite
    • For dockerized environment we need
      • docker,
      • docker-compose installed.
    • To run API server without Docker we need
      • MySQL server running &
      • Deno run time installed
  • Configuration
    • In application root, rename example env file env.example to .env.
    • An example env file contains MySQL credentials for the dockerized environment. For non-docker setup, update MySQL credentials here.
  • Run API

    • For Docker: Up docker-compose, this will create a docker container with the database with the given name in env.

      1. $ docker-compose up --build
    • For non-docker run API server with Deno run time

      1. $ deno run --allow-read --allow-net app.ts
  • API

Migrations

We use nessie to manage database migration.

  • In the application root, we have nessie.config.ts. Make sure to update this with the DB credentials.
  • Run the following command to run the migration. Migration should create necessary tables and dump the data.
    1. $ deno run --allow-net --allow-read --allow-write https://deno.land/x/nessie@v1.0.0-rc3/cli.ts migrate

With this, the user table would be created and the table would be seeded with fake data

  • Further, to add new migration, for example, to create new product table run
    1. deno run --allow-net --allow-read --allow-write https://deno.land/x/nessie@v1.0.0-rc3/cli.ts make create_product

Modules

Package Purpose
oak@v5.0.0"">oak@v5.0.0 Deno middleware framework
dotenv@v0.4.2"">dotenv@v0.4.2 Read env variables
mysql@2.2.0"">mysql@2.2.0 MySQL driver for Deno
nessie@v1.0.0-rc3"">nessie@v1.0.0-rc3 DB migration tool for Deno
validasaur@v0.7.0"">validasaur@v0.7.0 validation library
djwt@v0.9.0"">djwt@v0.9.0 JWT token encoding
bcrypt@v0.2.1"">bcrypt@v0.2.1 bcrypt encription lib

Project Layout

  1. .
  2. ├── .env (Make sure to create this file from given .env.example)
  3. ├── config/
  4. | |── config.ts (configuration object)
  5. ├── db/
  6. | |── migrations/
  7. | |── seeds/
  8. | ├── db.ts (DB connection object)
  9. ├── middlewares/
  10. ├── migrations/
  11. ├── services/
  12. ├── repositories/
  13. ├── helpers/
  14. ├── routes/
  15. |── types/
  16. |── types.ts (all types exported here)
  17. ├── app.ts (application server)
  18. ├── openapi.yml (Swagger open api definition)
  19. └── nessie.config.ts (DB configuration for nessie migration)

How to add a new route

  • Router hanlders are defined in routes folder. For each entity there should be separate routes file. For example user related CRUD router handlers are defined in user.routes.ts file.
  • All routes are bind with router handlers in routes.ts file.
  • To create CRUD for cat

    • Create file cat.routes.ts
    • Write router handler methods,
      ```
      //cat.routes.ts
      import as catService from “./../services/cat.service.ts”;
      /*
    • get list of cats
      */
      const getCats = [
      async (ctx: Context) => {

      1. const cats = await catService.getCats();
      2. ctx.response.body = cats;

      }
      ];

      //export route handler methods
      exports { getCats };
      ```

    • Then bind getCats route handler with router in routes.ts file -

      1. //routes.ts
      2. import * as catRoutes from "./cat.routes.ts";
      3. // ... router initialization codes
      4. router
      5. .get("/cats", ...catRoutes.getCats);

How to validate request body

  • Here we used validasaur@v0.7.0"">validasaur@v0.7.0 module for validating forms or request body. List of available rules can be found validasaur@v0.7.0/#available-rules">here
  • requestValidator middleware added to validate the request body.
    ```
    //auth.routes.ts
    import {
    required,
    isEmail,
    } from “validasaur@v0.7.0/src/rules.ts"">https://deno.land/x/validasaur@v0.7.0/src/rules.ts“;

import { requestValidator } from “./../middlewares/request-validator.middleware.ts”;

/**

  • request body schema
  • for cat create/update
  • */
    const catSchema = {
    name: [required],
    email: [required, isEmail],
    };

/**

  • create cat
    /
    const createCat = [
    /** request validation middleware
    /
    requestValidator({ bodyRules: catSchema }),
    /* router handler /
    async (ctx: Context) => {
    // … router handler code to create cat
    },
    ];
    ```

How to use JWT authorization

  • Here, We used JWT based authentication
  • Necessary JWT constants should be configured in .env (copy from .env.example).
    ```

    Access token validity in ms

    JWT_ACCESS_TOKEN_EXP=600000

Refresh token validity in ms

JWT_REFRESH_TOKEN_EXP=3600000

Secret secuirity string

JWT_TOKEN_SECRET=HEGbulKGDblAFYskBLml

  1. - Request header should contain JWT bearer token as `Authorization` key.
  2. - Middleware [JWTAuthMiddleware](./middlewares/jwt-auth.middleware.ts) used to parse the `Authorization` header and decode the payload as `ctx.user`.
  3. ## How to add auth guards
  4. - Auth guards are dependent on the `ctx.user` provided by [JWTAuthMiddleware](./middlewares/jwt-auth.middleware.ts) middleware.
  5. - To define different levels of authentication guard in different route handlers, middleware [userGuard](./middlewares/user-guard.middleware.ts) defined.
  6. - `userGuard` middleware optionally takes allowed user's roles as parameter. Otherwise, it will check only for the signed user.
  7. - Here is the example usage:-

//user.routes.ts

/**

  • get list of users
  • user with ADMIN role only can access
    */
    const getUsers = [
    userGuard(UserRole.ADMIN),
    async (ctx: Context) => {
    // … route handlers code
    },
    ];

/**

  • get signed user detail
  • any authenticated user can access
    */
    const getMe = [
    userGuard(),
    async (ctx: Context) => {
    // … route handlers code
    },
    ];
    ```

Error handling

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/asad-mlbd/deno-api-starter-oak.

Contributors

Roadmap

  • Open API integration
  • API Doc
  • Validation
  • JWT Auth
  • Unit Testing
  • Logger