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

@novice1/api-doc-generator

v0.2.6

Published

Quickly generate API Documentation.

Downloads

99

Readme

@novice1/api-doc-generator

Generate API documentation directly from application.

Installation

$ npm install @novice1/api-doc-generator

OpenAPI Specification

Reference.

OpenAPI Specification 3.0.3.

Default

By default it handles joi schemas.

Example:

import { 
  GenerateComponentsRule, 
  OpenAPI 
} from '@novice1/api-doc-generator';
import routing from '@novice1/routing';
import Joi from 'joi';

const openapi = new OpenAPI();

openapi
  .setTitle('api doc')
  .setHost('http://localhost:8000')
  .setConsumes(['application/json'])
  .setTags([
    {
      name: 'default',
      externalDocs: { description: 'Find more info here', url: 'https://swagger.io/specification/' }
    }
  ])
  .setGenerateComponentsRule(GenerateComponentsRule.ifUndefined)
  .setResponsesProperty('openapi')
  .setSecuritySchemes({
    basicAuth: {
      type: 'http',
      scheme: 'basic',
    }
  })
  .setDefaultSecurity([
    {
      basicAuth: []
    }
  ]);

const router = routing()
  .get({
    name: 'Main app',
    path: '/app',
    auth: true,
    tags: ['default'],
    parameters: {
      query: {
        version: Joi.number()
          .description('version number')
          .min(1)
          .max(3)
          .default(2)
          .example(2)
      },

      operationId: 'default-app',
      undoc: false, // set to `true` to not display the route in the documentation

      // override consumes
      consumes: ['application/json'],
      // override default security
      security: ['basicAuth'],
    },
    responses: {
      openapi: {
        default: {
          description: 'Version number',
          content: {
            'application/json': {
              schema: {
                type: 'number',
                example: 2
              }
            }
          }
        }
      }
    }
  }, function (req, res) {
    res.json(req.query.version)
  });

// add router metadata
openapi.add(router.getMeta());

// get OpenAPI Object (json)
const doc = openapi.result();

Postman Specification

Reference.

Postman Collection Format v2.1.0.

Default

By default it handles joi schemas.

Example:

import { 
  GenerateFoldersRule, 
  Postman 
} from '@novice1/api-doc-generator';
import routing from '@novice1/routing';
import Joi from 'joi';

const postman = new Postman();

postman
      .setName('api doc')
      .setHost('http://localhost:8000')
      .setConsumes(['multipart/form-data', 'application/json'])
      .setFolders([
        {
          name: 'default',
          description: 'A folder is just an ordered set of requests.',
          item: [],
        }
      ])
      .setGenerateFoldersRule(GenerateFoldersRule.siblings)
      .setResponsesProperty('postman')
      .setDefaultSecurity({
        type: 'basic',
        basic: []
      });

const router = routing()
  .get({
    name: 'Main app',
    path: '/app',
    auth: true,
    tags: ['default'], // folders
    parameters: {
      query: {
        version: Joi.number()
          .description('version number')
          .min(1)
          .max(3)
          .default(2)
          .example(2)
      },

      operationId: 'default-app',

      // override consumes
      consumes: ['application/json'],
      // override default security
      security: ['basic'],
    },
    responses: {
      postman: {
        // ...
      }
    }
  }, function (req, res) {
    res.json(req.query.version)
  });

// add router metadata
postman.add(router.getMeta());

// get Postman Collection (json)
const doc = postman.result();

Schema helpers

Default helper

Types

The default helper handles the following joi types: alternatives, any, array, boolean, date function, number, object, string, binary.

It also handles format methods like Joi.string().email(), Joi.string().url() and more.

In some cases you might have to precise the format in Joi.meta. For example Joi.string().meta({format: 'password'}), Joi.date().meta({format: 'datetime'}) or more.

Handled formats are:

  • boolean
  • object
  • array
  • number
  • string
  • date
  • date-time
  • datetime
  • float
  • double
  • integer
  • int32
  • int64
  • byte
  • binary
  • password
  • email
  • guid
  • uuid
  • uri
  • dataUri

Joi.meta

You can configure multiple elements in Joi.meta like a reference to a component. For example:

Joi.object()
  .keys({
    name: Joi.string().required(),
    petType: Joi.string().required()
  })
  .meta({ ref: '#/components/schemas/Pet' })

If the reference is local (#), it could automatically generate the component depending on the rule you set (see OpenAPI.setGenerateComponentsRule).

List of elements you can configure in Joi.meta:

  • additionalProperties
  • allowReserved
  • deprecated
  • discriminator
  • examples
  • explode
  • encoding
  • format
  • ref
  • style
  • xml

The possible value for each of them is defined in the OpenAPI Specification.

Custom helper

You can create your own helper to handle another schema than joi. The helper

Example:

import { OpenAPI, Postman } from '@novice1/api-doc-generator';
import { 
  CustomOpenAPIHelperClass,
  CustomPostmanHelperClass
} from './custom';

const openapi = new OpenAPI(CustomOpenAPIHelperClass);

const postman = new Postman(CustomPostmanHelperClass);

Utils

As the format differs between specifications, some classes can help you generate the documentation following multiple specifications.

Auth

Classes:

Example:

import {
  OpenAPI,
  Postman,
  BearerUtil
} from '@novice1/api-doc-generator';
import routing from '@novice1/routing';

// security scheme
const bearerAuth = new BearerUtil('bearerName');

// add it to OpenAPI security schemes
const openapi = new OpenAPI();
openapi.addSecuritySchemes(bearerAuth);

// add it to Postman global authentication
const postman = new Postman();
postman.setAuth(bearerAuth);

// router
const router = routing()
  .get({
    path: '/something',
    auth: true,
    parameters: {
      // add security requirements for this route
      security: bearerAuth
    }
  }, function (req, res) {
    // ...
  });

Context

You can wrap the instance with a context to define a scope depending on the route. You do that with ContextAuthUtil.

Example:

import routing from '@novice1/routing';
import {
  OpenAPI, 
  Postman,
  ContextAuthUtil,
  OAuth2Util,
  GrantType
} from '@novice1/api-doc-generator';

// OAuth2 specifications
const oauth2 = new OAuth2Util('oAuth2AuthCode');
oauth2
  .setDescription('For more information, see https://api.slack.com/docs/oauth')
  .setGrantType(GrantType.authorizationCode)
  .setAuthUrl('https://slack.com/oauth/authorize')
  .setAccessTokenUrl('https://slack.com/api/oauth.access')
  .setScopes({
    'users:read': 'Read user information',
    'users:write': 'Modify user information',
    'im:read': 'Read messages',
    'im:write': 'Write messages',
    'im:history': 'Access the message archive',
    'search:read': 'Search messages, files, and so on'
  });
 
// add it to OpenAPI security schemes
const openapi = new OpenAPI();
openapi.addSecuritySchemes(oauth2);

// add it to Postman global authentication
const postman = new Postman();
postman.setAuth(oauth2);

// router
const router = routing()
  .get({
    path: '/messages',
    auth: true,
    parameters: {
      // add security requirements for this route
      security: new ContextAuthUtil(
        oauth2,
        // OAuth2 scopes for this route
        ['im:read']
      )
    }
  }, function (req, res) {
    // ...
  });

Group

You can group security schemes at your convenience with GroupAuthUtil and GroupContextAuthUtil.

Exemple:

import {
  OpenAPI,
  Postman,
  BasicAuthUtil,
  BearerUtil,
  GroupAuthUtil,
  GroupContextAuthUtil
} from '@novice1/api-doc-generator';

const basicAuth = new BasicAuthUtil('basicAuthName');
const bearerAuth = new BearerUtil('bearerName');

const groupAuth = new GroupAuthUtil([
  basicAuth,
  bearerAuth
]);

// add it to OpenAPI security schemes
const openapi = new OpenAPI();
openapi.addSecuritySchemes(groupAuth);

// add it to Postman global authentication
const postman = new Postman();
postman.setAuth(groupAuth);

const router = routing()
  .get({
    path: '/something',
    auth: true,
    parameters: {
      // add security requirements for this route
      security: new GroupContextAuthUtil([
        basicAuth,
        bearerAuth,
      ])
    }
  }, function (req, res) {
    // ...
  });

Responses

Classes:

Example:

import {
  ResponseUtil,
  GroupResponseUtil
} from '@novice1/api-doc-generator';

const generalError = new ResponseUtil('GeneralError');
generalError
  .setDescription('General Error')
  .addMediaType('application/json', {
    schema: {
      $ref: '#/components/schemas/GeneralError'
    }
  })
  .setCode(500);

const illegalInput = new ResponseUtil('IllegalInput');
illegalInput
  .setDescription('Illegal input for operation.')
  .setCode(400);

const responses = new GroupResponseUtil([
  generalError,
  illegalInput
]);

openapi.setResponses(responses);
// or 
openapi.addResponse(responses);
// or
openapi
  .addResponse(generalError)
  .addResponse(illegalInput);

// router
const router = routing()
  .post({
    path: '/something',
    auth: true,
    parameters: {
      body: {
        something: Joi.string().max(14)
      },
      responses
    }
  }, function (req, res) {
    // ...
  });

Context

You can wrap the instance with a context if you want to define default, code, ref and/or links depending on the route. You do that with ContextResponseUtil.

Example:

const generalError = new ResponseUtil('GeneralError');
generalError
  .setDescription('General Error')
  .addMediaType('application/json', {
    schema: {
      $ref: '#/components/schemas/GeneralError'
    }
  });

const illegalInput = new ResponseUtil('IllegalInput');
illegalInput
  .setDescription('Illegal input for operation.');

// router
const router = routing()
  .get({
    path: '/something',
    auth: true,
    parameters: {
      responses: new GroupResponseUtil([
        (new ContextResponseUtil(generalError))
          .setCode(500).setDefault(),
        (new ContextResponseUtil(illegalInput))
          .setCode(400)
      ])
    }
  }, function (req, res) {
    // ...
  });

References