Git Product home page Git Product logo

doctopus's Introduction

NPM version Build Status

codecov

doctopus

Nobody likes writing docs. So to make it better, we wrote doctopus; a fluent pluggable Swagger spec builder enabling docs to be built quickly and maintained automatically.

alt tag

The doctopus API provides heavy syntactic sugar over Swagger enabling re-use of common libraries and components for documentation composition.

When used in conjunction with sister libraries doctopus faciliates schema reuse for persistence, validation, and documentation reducing maintenance overhead and increasing consistency.

Overview

Way more documentation to come.

It is important to note that doctopus implements a mutable API enabling reuse of common variables and parameters to make documenting common routes easier. It is recommended to create a single instance per route file and clear params (doc.clearParams()) when they change.

Installation

$ npm install --save doctopus

Example Configuration

const app = require('express')();
const doctopus = require('doctopus');

const docs = new doctopus.DocBuilder();
const docFactory = new doctopus.Doc();

docs.set('title', 'My Express App');

docs.add('/swagger', docFactory.get()
    .group('Documentation')
    .description('Gets a Swagger Specification')
    .summary('Swagger')
    .onSuccess(200, {
        description: 'Swagger Spec',
        schema: Doc.object()
    })
    .build());

app.get('/swagger', (req, res) => res.send(docs.build()));
app.listen('3000');

Decorator API

import { 
    get, 
    route, 
    group, 
    param, 
    response, 
    Doc, 
    DocBuilder,
} from 'doctopus';

// set default for all controller methods
@group('Cats')
class CatCtrl {

    // http get request
    @get
    // set route
    @route('/cats/{id}')
    // override group of a specific method
    @group('Orders')
    public findOne(req, res) {
        res.send({});
    }

    @get
    @route('/cats')
    // add a param
    @param({
        in: 'query',
        type: 'string',
        name: 'name',  
    })
    // declare response
    @response({
        description: 'All Cats',
        schema: Doc.object(), // schema, see schema api
    })
    public findAll(req, res) {
        res.send([]);
    }
}

const docs = new DocBuilder();

// docBuilder instance will read the docs
docs.use(CatCtrl);

Advanced Usage

Doctopus was designed with automation and re-usability in mind. To leverage automatic doc generation, we recommend using two packages that we've found to be helpful.

  • joi-to-swagger - Joi Validation Object to Swagger Mapper
    • For API inputs, joi is an excellent validation framework which can help define sync endpoint validation and with doctopus, you can also define your documentation using the same schemas.
  • mongoose-to-swagger - Mongoose Model to Swagger Mapper
    • For API outputs, often times API endpoints simply return JSON representations of mongoose models. Doctopus allows you to simply reference the mongoose model (Doc.model('name')) and have the swagger schema automatically generated.

After you've registered your mongoose models...

const joi = require('joi');
const j2s = require('joi-to-swagger');
const m2s = require('mongoose-to-swagger');

// ...

const docs = new doctopus.DocBuilder();
const definitions = {
  // you can define custom definitions in line or reference from another file if you choose
  'Cat': {
      'id': 'Cat',
      'properties': {
          'name': {
              'type': 'string'
          }
      }
  }
};

// automatically register // namespace all mongoose models
for(const i in mongoose.models) {
    definitions[`mongoose|${i}`] = m2s(mongoose.models[i]);
}

const joiSchemas = {
    Cat: joi.object().keys({
      name: joi.string()
    })
};

Object.keys(joiSchemas).forEach(k => {
    definitions[`joi|${k}`] = j2s(joiSchemas[k]).swagger;
});

// enable Reflection in doctopus api (Doc.pick('RegisteredModel', 'Property')))
doctopus.Doc.setDefinitions(definitions);

// add definitions to swagger definitions
docs.addDefinitions(definitions);

Parameter Groups

const group = {
  accessToken: {
    name: 'accessToken',
    description: 'Client Token',
    in: 'query',
    required: false,
    type: 'string'
  },
  fields: {
    name: 'fields',
    description: 'Fields you want returned',
    in: 'query',
    required: false,
    type: 'string'
  }
};

doctopus.paramGroup('public', group);

// later
Doc.paramGroup('public');

Resources

Contributing

We look forward to seeing your contributions!

License

MIT © Ben Lugavere

doctopus's People

Contributors

alexander-alvarez avatar blugavere avatar dependabot[bot] avatar sadiqboxed avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

doctopus's Issues

generate openapi.yml instead of serving openapi

docs appear to be down, so apologies in advance if i miss something from there.

I really like the idea of annotations instead of bulky @Swagger comments (huge mess identing properly) from swagger-jsdoc.

However in our current setup, we are not serving openapi from nodejs, but as part of our static docs site with redoc. For this reason we had previously set up a ci job that is triggered at code changes, generate yml file and then export it to our privately hosted docs (gitlab pages).

I couldnt find a quick way to achieve the same without coding my own script, I'm I right? Any suggestion?

Furthermore, our current scenario entails a monorepo with different services (some exposing rest endpoints) and api-contracts packages. With swagger-jsdoc we have /** @swagger */ comments on each package which expose apis or define models. Then running it from the root of yarn workspace it basically parses any ts file from any package matching the glob rule. It there a way to achieve something like this with this cool project?

Not compatible with latest swagger types

when using this version

+    "@types/swagger-schema-official": "2.0.18",

below errors occur

lib/Doc.ts(129,7): error TS2322: Type 'IProperties' is not assignable to type '{ [propertyName: string]: Schema; }'.
  Index signatures are incompatible.
    Type 'IExtendedSchema' is not assignable to type 'Schema'.
      Types of property 'type' are incompatible.
        Type 'string | undefined' is not assignable to type '"string" | "number" | "boolean" | "object" | "integer" | "array" | undefined'.
          Type 'string' is not assignable to type '"string" | "number" | "boolean" | "object" | "integer" | "array" | undefined'.
lib/Doc.ts(151,7): error TS2322: Type '"file"' is not assignable to type '"string" | "number" | "boolean" | "object" | "integer" | "array" | undefined'.
lib/Doc.ts(211,7): error TS2322: Type '{ type: string; }' is not assignable to type 'Schema | Schema[] | undefined'.
  Type '{ type: string; }' is not assignable to type 'undefined'.
lib/Doc.ts(466,5): error TS2322: Type '{ description?: string | undefined; in: string; required: boolean; schema?: Schema | undefined; name: string; }' is not assignable to type 'Parameter'.
  Type '{ description?: string | undefined; in: string; required: boolean; schema?: Schema | undefined; name: string; }' is not assignable to type 'BodyParameter'.
    Type '{ description?: string | undefined; in: string; required: boolean; schema?: Schema | undefined; name: string; }' is not assignable to type 'BaseParameter'.
      Types of property 'in' are incompatible.
        Type 'string' is not assignable to type '"body" | "query" | "path" | "header" | "formData"'.
lib/Doc.ts(798,27): error TS2339: Property 'schema' does not exist on type 'Reference | Response'.
  Property 'schema' does not exist on type 'Reference'.
lib/interfaces.ts(50,18): error TS2430: Interface 'IExtendedSchema' incorrectly extends interface 'Schema'.
  Types of property 'type' are incompatible.
    Type 'string | undefined' is not assignable to type '"string" | "number" | "boolean" | "object" | "integer" | "array" | undefined'.
      Type 'string' is not assignable to type '"string" | "number" | "boolean" | "object" | "integer" | "array" | undefined'.
TypeScript: 6 semantic errors

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.