This package has been deprecated

Author message:

package deprecated

@leeruniek/blocks

0.5.7 • Public • Published

blocks

Node.js API framework. You have a request and need to produce a response.

Request-Response cycle


Features

Validate input - ajv

Pass request data (headers, body, query parameters, URL parameters) through custom JSON Schemas defined for each route. Make sure no unwanted data gets in, de-clutter the route logic and make the API behave more consistent.
If validation fails, an automatic 409 Conflict response will be sent to the client.

Check permissions

Simple function outside of main route logic.
If it returns false, an automatic 403 Forbidden response will be sent to the client.

Async support

Route actions, middleware and plugins have async/await support.

Query string parsing - qs

Parsed data will be available on the request.ctx object.

Cross-origin resource sharing

Using cors

Install

npm install @leeruniek/blocks

Basic example

src/index.js

const http = require("http")
const path = require("path")
const { block } = require("@leeruniek/blocks")

block({
  // settings: {
  //   METRICS: true,
  //   METRICS_NAMESPACE: "blocks",
  //   METRICS_WITH_DEFAULT: false,
  //   PORT: 8080,
  //   MICRO_VERSION: pkg.version,
  //   ENV: "development",
  //   CORS_ORIGIN: null,
  //   CORS_METHODS: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
  // },

  // where plugins and routes are
  folders: path.resolve("./src"),

  // RegExp to match plugin files 
  // plugins: /\.plugins\.js$/,

  // RegExp to match routes files 
  // routes: /\.routes\.js$/,
}).then(({ Plugins: { Config }, middlewarePipeline }) =>
  http
    .createServer(middlewarePipeline)
    .listen(Config.get("PORT"), "localhost", () => {
      console.log(`### Started server on port ${Config.get("PORT")}`)
    })
)

Routes

Default routes

Status check

GET: /ping

{
  "ping": "pong",
  "aliveFor": {
    "days": 2, "hours": 1, "minutes": 47, "seconds": 46
  },
  "version": "0.5.6", // package.json version 
}

Prometheus data

GET: /metrics If server started with METRICS: true.

Add route

src/something.route.js

module.exports = {
  method: "GET",
  path: "/something",

  // Data is valid then continue to permissionn check, otherwise return 409
  schema: require("./something.schema"),

  // Is allowed then continue to action, otherwise return 403
  isAllowed: (/* plugins */) => async ({ method, ctx }) => {
    console.log(`${method}:${ctx.pathname} - isAllowed`)

    return true
  },

  // Returned value will be set in `res` body 
  action: (/* plugins */) => async (/* req */) => {
    return {
      message: "This is something else!"
    }
  },
}

src/something.schema.js

module.exports = {
  type: "object",
  properties: {
    headers: {
      type: "object",
    },

    params: {
      type: "object",
      additionalProperties: false,
    },

    query: {
      type: "object",
      additionalProperties: false,
    },

    body: {
      type: "object",
      additionalProperties: false,
    },
  },
}

See ajv and JSON Schema docs for more on data validation.

Plugins

Default plugins

Config

Getter over the settings object when instantiating blocks. Accessible in route's isAllowed and action methods and when defining custom middleware.

While you can use process.env to access CI variables globally, use this opportunity to write a few words about each.

src/index.js

blocks({
  settings: {
    // (CI) Key to verify incoming json-web-tokens. See `jwt.middle.js` for details.
    JWT_SECRET: process.env.JWT_SECRET ?? "CHANGE ME!"
    ...
  },
  ...
})

src/middleware/req__jwt.js

module.exports = ({ Config }) => (req, res, next) => {
  ...
  jwt.verify(req.headers.authorization, Config.get("JWT_SECRET"))
  ...
}

Add plugin

A plugin consists of a constructor function and a list of other plugins that is dependent on.

Whatever the create function returns will be considered as the plugin's content and is what will be exposed to the routes, middleware and other plugins.

src/plugins/database.plugin.js

const Sequelize = require("sequelize")

module.exports = {
  // Array of plugins to wait for before running `create`
  depend: ["Config"],

  /** 
   * Constructor function, whatever returns will be considered as the plugin's
   * content and is what will be exposed to the routes, middleware and other 
   * plugins.
   *
   * @param  {Object}  props  Initial settings object passed to the `blocks`
   *                          constructor
   *
   * @returns  {any|Promise<any>}  Plugin content. Will resolve before continuing.
   */
  create: (/* props */) => Config => {
    console.log("Checking DB connection")
    
    // Database connection, model loading etc
    ...
    return {
      Todos: ...,
      Comments: ...,
    }
  }
}

Develop

git clone git@github.com:leeruniek/blocks.git && \
  cd blocks && \
  npm run setup

# run tests (any `*.test.js`) once
npm test

# watch `src` folder for changes and run test automatically
npm run tdd

Changelog

History of all changes in CHANGELOG.md

0.6 - March 2019

Add

  • Diagrams and words describing how things work

Readme

Keywords

none

Package Sidebar

Install

npm i @leeruniek/blocks

Weekly Downloads

17

Version

0.5.7

License

BSD-3-Clause

Unpacked Size

50 kB

Total Files

34

Last publish

Collaborators

  • igpejic
  • tomasleeruniek
  • whois42