npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

http-doc

v0.0.11

Published

Creates your HTTP routes with ACL, data filtering and automatic documentation.

Downloads

4

Readme

Coverage Badge Last build

http-doc

Creates your HTTP routes with ACL, data filtering and automatic documentation.

Features

  • Documentation on routes or controllers
  • Automatic OpenAPI documentation generator
  • Access control management
  • Plugin system to handle additional HTTP frameworks

Installation

Install http-doc with npm

npm install http-doc --save

or with yarn

yarn add http-doc

API instanciation

import { Api, collection } from 'http-doc'

const api = new Api({
  // options, see Api Options section
})

// Register routes
collection(
  'Users',
  router => {
    router.get('/', UserController.list, {
      // options, see Route Options section
    })
  },
  {
    title: 'Users',
    description: 'Managing users',
    prefix: '/users'
  }
)

// Apply configuration to your HTTP framework
api.setup()

Api Options

| Parameter | Type | Description | | :-------------------- | :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | app | object | HTTP framework instance | | documentationPath | string | Documentation display path (Default: /swagger.json) | | documentationAccess | function | Function used to restrict access to the documentation configuration file. (default: request => true) | | driver | class | Provides plugin to use for HTTP framework interaction. | | getUserAccess | string/array/function | List of user access list. Can be a single string, or a function returning a string or an array of strings. | | monitor | boolean | Monitor all API calls (count, time metrics). Creates a set of monitoring API endpoints (See Monitoring section). (default: false) | | monitorAccess | function | Function used to restrict access to the monitoring API. (default: request => true) | | prefix | string | Prefix for all routes | | schemasFolder | string | Path to folder containing all OpenAPI Schemas (default: schemas) |

Route Options

| Parameter | Type | Description | | :------------------------------ | :---------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | title | string | Endpoint name in documentation. | | description | string | Endpoint description in documentation. | | access | string/array/function | List of user access requirements. Can be a string, a function or an array of string or functions. Functions will return a boolean. | | accepts | string/array/object | Restricts input with provided OpenAPI Schema. Can be a string (file path to schema), an object (OpenAPI schema), or an array of strings (file path to schema) or objects (direct schema or conditional object : {schema: String, handler: Function, description: String}). Validated schemas will be merged. | | returns | object | List of possible returned data, by HTTP code. | | returns.{code} | object | Object describing returned data. | | returns.{code}.schema | string | OpenAPI Schema path, relative to schemasFolder Api configuration field. | | returns.{code}.description | string | Description of returned data. | | parameters.{name} | object | Object describing parameter. | | parameters.{name}.schema | string | OpenAPI Schema path, relative to schemasFolder Api configuration field. | | parameters.{name}.description | string | Description of parameter. |

Access Control Lists

ACL is based on custom strings, like admin, users:list, per example. You define which permissions a user have, and he'll be able to access only routes with correct permissions.

Example

import { Api, collection } from 'http-doc'

const api = new Api({
  getUserAccess: request => {
    // Logged in user :
    /* {
      permissions: ['users:list', 'users:create']
    } */
    return request.user.permissions
  }
})

controller('Users', router => {
  router.get('/', listController, {
    access: 'users:list' // Will have access to this endpoint
  })
  router.post('/', createController, {
    access: ['admin', 'users:create'] // Will have access to this endpoint, because one of the requirements is fulfilled
  })
  router.put('/:id', updateController, {
    access: [
      'admin',
      'users:edit',
      request => request.params.id === request.user.id
    ] // Will not have access to this endpoint if he tries to edit another user
  })
})

OpenAPI Schemas

Input data and returned data filtering works with OpenAPI Schemas, stored where you want on your project folder in JSON format. References are relative to the provided schemas folder when initializing API.

Example :

{
  "type": "object",
  "required": ["name"],
  "properties": {
    "name": {
      "type": "string"
    },
    "address": {
      "$ref": "Address"
    },
    "age": {
      "type": "integer",
      "minimum": 0
    }
  }
}

More info on OpenAPI Schemas here.

Handled string formats :

  • date
  • date-time
  • byte (or base64)
  • email
  • uuid
  • objectid
  • uri

Unsupported features :

  • allOf
  • anyOf
  • oneOf
  • not

Parameters

With parameters route configuration parameter, you can describe and filter parameters located in query, path, headers or cookies.

Example

import { collection } from 'http-doc'

controller('Users', router => {
  router.get('/', listController, {
    parameters: {
      page: { schema: 'params/Page', description: 'Page' },
      limit: { schema: 'params/Limit', description: 'Limit' }
    }
  })
})

Input data filtering

You can filter input data with accepts configuration field on routes.

Example

import { collection } from 'http-doc'
import UserGetFilter from '../UserGetFilter.json'

controller('Users', router => {
  router.get('/', listController, {
    accepts: 'UserListFilters'
  })
  router.get('/:id', listController, {
    accepts: UserGetFilter
  })
  router.post('/', createController, {
    accepts: [
      'UserCreate',
      {
        schema: 'UserCreateAdmin',
        handler: request => !!request.user?.admin,
        description: 'If user is admin'
      }
    ]
  })
})

Returned data filtering

With returns route configuration parameter, you can automatically filter data returned by your controller according to an OpenAPI Schema, accordingly to the returned HTTP code.

Example

import { collection } from 'http-doc'
import UserGetFilter from '../UserGetFilter.json'

controller('Users', router => {
  router.get('/', listController, {
    returns: {
      200: { schema: 'UserLite', description: 'User data' },
      403: { schema: 'Error', description: 'Not authorized' },
      500: { schema: 'Error', description: 'Unknown error' }
    }
  })
  router.get('/:id', listController, {
    returns: {
      200: { schema: 'User', description: 'User data' },
      403: { schema: 'Error', description: 'Not authorized' },
      500: { schema: 'Error', description: 'Unknown error' }
    }
  })
  router.post('/', createController, {
    returns: {
      201: { schema: 'User', description: 'User data' },
      400: { schema: 'Error', description: 'Bad input data' },
      403: { schema: 'Error', description: 'Not authorized' },
      500: { schema: 'Error', description: 'Unknown error' }
    }
  })
})

Decorators

Decorators are provided to configure your routes, directly from the controllers :

import {
  title,
  description,
  access,
  accepts,
  returns,
  parameter
} from 'http-doc'

export default class UsersController {
  @title('Login')
  @description('Logs in a user')
  @access(true)
  @accepts('Login')
  @parameter('source', 'Source', 'Accepted auth source')
  @returns(200, 'UserJwt', 'Authorized JWT token')
  @returns(403, 'Error', 'Invalid credentials')
  @returns(500, 'Error', 'System error')
  static async login (request, reply, routeConf) {
    // Handling login
    return { loggedIn: true }
  }
}

You need to add babel configuration to handle ES6 decorators (experimental for now):

{
  "plugins": [["@babel/plugin-proposal-decorators", { "version": "2022-03" }]]
}

Authors