Git Product home page Git Product logo

fastify-swagger's Introduction

@fastify/swagger

NPM version CI workflow js-standard-style

A Fastify plugin for serving Swagger (OpenAPI v2) or OpenAPI v3 schemas, which are automatically generated from your route schemas, or from an existing Swagger/OpenAPI schema.

If you are looking for a plugin to generate routes from an existing OpenAPI schema, check out fastify-openapi-glue.

Following plugins serve Swagger/OpenAPI front-ends based on the swagger definitions generated by this plugin:

See also the migration guide for migrating from @fastify/swagger version <= <=7.x to version >=8.x.

Install

npm i @fastify/swagger

Compatibility

Plugin version Fastify version
^7.0.0 ^4.0.0
^6.0.0 ^3.0.0
^3.0.0 ^2.0.0
^1.0.0 ^1.0.0

Please note that if a Fastify version is out of support, then so are the corresponding version(s) of this plugin in the table above. See Fastify's LTS policy for more details.

Usage

Add it to your project with register, pass it some options, call the swagger API, and you are done! Below an example of how to configure the OpenAPI v3 specification with Fastify Swagger:

const fastify = require('fastify')()

await fastify.register(require('@fastify/swagger'), {
  openapi: {
    openapi: '3.0.0',
    info: {
      title: 'Test swagger',
      description: 'Testing the Fastify swagger API',
      version: '0.1.0'
    },
    servers: [
      {
        url: 'http://localhost:3000',
        description: 'Development server'
      }
    ],
    tags: [
      { name: 'user', description: 'User related end-points' },
      { name: 'code', description: 'Code related end-points' }
    ],
    components: {
      securitySchemes: {
        apiKey: {
          type: 'apiKey',
          name: 'apiKey',
          in: 'header'
        }
      }
    },
    externalDocs: {
      url: 'https://swagger.io',
      description: 'Find more info here'
    }
  }
})

fastify.put('/some-route/:id', {
  schema: {
    description: 'post some data',
    tags: ['user', 'code'],
    summary: 'qwerty',
    security: [{ apiKey: [] }],
    params: {
      type: 'object',
      properties: {
        id: {
          type: 'string',
          description: 'user id'
        }
      }
    },
    body: {
      type: 'object',
      properties: {
        hello: { type: 'string' },
        obj: {
          type: 'object',
          properties: {
            some: { type: 'string' }
          }
        }
      }
    },
    response: {
      201: {
        description: 'Successful response',
        type: 'object',
        properties: {
          hello: { type: 'string' }
        }
      },
      default: {
        description: 'Default response',
        type: 'object',
        properties: {
          foo: { type: 'string' }
        }
      }
    }
  }
}, (req, reply) => { })

await fastify.ready()
fastify.swagger()

With @fastify/autoload

You need to register @fastify/swagger before registering routes.

const fastify = require('fastify')()
const fastify = fastify()
await fastify.register(require('@fastify/swagger'))
fastify.register(require("@fastify/autoload"), {
  dir: path.join(__dirname, 'routes')
})
await fastify.ready()
fastify.swagger()

API

Register options

Modes

@fastify/swagger supports two registration modes dynamic and static:

Dynamic

dynamic is the default mode, if you use @fastify/swagger this way API schemas will be auto-generated from route schemas:

// All of the below parameters are optional but are included for demonstration purposes
{
  // swagger 2.0 options
  swagger: {
    info: {
      title: String,
      description: String,
      version: String
    },
    externalDocs: Object,
    host: String,
    schemes: [ String ],
    consumes: [ String ],
    produces: [ String ],
    tags: [ Object ],
    securityDefinitions: Object
  },
  // openapi 3.0.3 options
  // openapi: {
  //   info: {
  //     title: String,
  //     description: String,
  //     version: String,
  //   },
  //   externalDocs: Object,
  //   servers: [ Object ],
  //   components: Object,
  //   security: [ Object ],
  //   tags: [ Object ]
  // }
}

All properties detailed in the Swagger (OpenAPI v2) and OpenAPI v3 specifications can be used. @fastify/swagger will generate API schemas that adhere to the Swagger specification by default. If provided an openapi option it will generate OpenAPI compliant API schemas instead.

Examples of using @fastify/swagger in dynamic mode:

Static

static mode must be configured explicitly. In this mode @fastify/swagger serves an already existing Swagger or OpenAPI schema that is passed to it in specification.path:

{
  mode: 'static',
  specification: {
    path: './examples/example-static-specification.yaml',
    postProcessor: function(swaggerObject) {
      return swaggerObject
    },
    baseDir: '/path/to/external/spec/files/location',
  },
}

The specification.postProcessor parameter is optional. It allows you to change your Swagger object on the fly (for example - based on the environment). It accepts swaggerObject - a JavaScript object that was parsed from your yaml or json file and should return a Swagger schema object.

specification.baseDir allows specifying the directory where all spec files that are included in the main one using $ref will be located. By default, this is the directory where the main spec file is located. Provided value should be an absolute path without trailing slash.

An example of using @fastify/swagger with static mode enabled can be found here.

Options

Option Default Description
hiddenTag X-HIDDEN Tag to control hiding of routes.
hideUntagged false If true remove routes without tags from resulting Swagger/OpenAPI schema file.
initOAuth {} Configuration options for Swagger UI initOAuth.
openapi {} OpenAPI configuration.
stripBasePath true Strips base path from routes in docs.
swagger {} Swagger configuration.
transform null Transform method for the route's schema and url. documentation.
transformObject null Transform method for the swagger or openapi object before it is rendered. documentation.
refResolver {} Option to manage the $refs of your application's schemas. Read the $ref documentation
exposeHeadRoutes false Include HEAD routes in the definitions

Transform

By passing a synchronous transform function you can modify the route's url and schema.

You may also access the openapiObject and swaggerObject

Some possible uses of this are:

  • add the hide flag on schema according to your own logic based on url & schema
  • altering the route url into something that's more suitable for the api spec
  • using different schemas such as Joi and transforming them to standard JSON schemas expected by this plugin
  • hiding routes based on version constraints

This option is available in dynamic mode only.

Examples of all the possible uses mentioned:

const convert = require('joi-to-json')

await fastify.register(require('@fastify/swagger'), {
  swagger: { ... },
  transform: ({ schema, url, route, swaggerObject }) => {
    const {
      params,
      body,
      querystring,
      headers,
      response,
      ...transformedSchema
    } = schema
    let transformedUrl = url

    // Transform the schema as you wish with your own custom logic.
    // In this example convert is from 'joi-to-json' lib and converts a Joi based schema to json schema
    if (params) transformedSchema.params = convert(params)
    if (body) transformedSchema.body = convert(body)
    if (querystring) transformedSchema.querystring = convert(querystring)
    if (headers) transformedSchema.headers = convert(headers)
    if (response) transformedSchema.response = convert(response)

    // can add the hide tag if needed
    if (url.startsWith('/internal')) transformedSchema.hide = true

    // can transform the url
    if (url.startsWith('/latest_version/endpoint')) transformedUrl = url.replace('latest_version', 'v3')

    // can add the hide tag for routes that do not match the swaggerObject version
    if (route?.constraints?.version !== swaggerObject.swagger) transformedSchema.hide = true

    return { schema: transformedSchema, url: transformedUrl }
  }
})

You can also attach the transform function on a specific endpoint:

fastify.get("/", {
  schema: { ... },
  config: {
    swaggerTransform: ({ schema, url, route, swaggerObject }) => { ... }
  }
})

If both a global and a local transform function is available for an endpoint, the endpoint-specific transform function will be used.

The local transform function can be useful if you:

  • want to add additional information to a specific endpoint
  • have an endpoint which requires different transformation from other endpoints
  • want to entirely ignore the global transform function for one endpoint

The endpoint-specific transform can be used to "disable" the global transform function by passing in false instead of a function.

Transform Object

By passing a synchronous transformObject function you can modify the resulting swaggerObject or openapiObject before it is rendered.

await fastify.register(require('@fastify/swagger'), {
  swagger: { ... },
  transformObject ({ swaggerObject }) => {
    swaggerObject.info.title = 'Transformed';
    return swaggerObject;
  }
})

Managing your $refs

When this plugin is configured as dynamic mode, it will resolve all $refs in your application's schemas. This process will create an new in-line schema that is going to reference itself.

This logic step is done to make sure that the generated documentation is valid, otherwise the Swagger UI will try to fetch the schemas from the server or the network and fail.

By default, this option will resolve all $refs renaming them to def-${counter}, but your view models keep the original $id naming thanks to the title parameter.

To customize this logic you can pass a refResolver option to the plugin:

await fastify.register(require('@fastify/swagger'), {
  swagger: { ... },
  ...
  refResolver: {
    buildLocalReference (json, baseUri, fragment, i) {
      return json.$id || `my-fragment-${i}`
    }
  }
}

To deep down the buildLocalReference arguments, you may read the documentation.

Route options

It is possible to instruct @fastify/swagger to include specific HEAD routes in the definitions by adding exposeHeadRoute in the route config, like so:

  fastify.get('/with-head', {
    schema: {
      operationId: 'with-head',
      response: {
        200: {
          description: 'Expected Response',
          type: 'object',
          properties: {
            foo: { type: 'string' }
          }
        }
      }
    },
    config: {
      swagger: {
        exposeHeadRoute: true,
      }
    }
  }, () => {})

Response Options

Response description and response body description

description is a required field as per the Swagger specification. If it is not provided then the plugin will automatically generate one with the value 'Default Response'. If you supply a description it will be used for both the response and response body schema, for example:

fastify.get('/description', {
  schema: {
    response: {
      200: {
        description: 'response and schema description',
        type: 'string'
      }
    }
  }
}, () => {})

Generates this in a Swagger (OpenAPI v2) schema's paths:

{
  "/description": {
    "get": {
      "responses": {
        "200": {
          "description": "response and schema description",
          "schema": {
            "description": "response and schema description",
            "type": "string"
          }
        }
      }
    }
  }
}

And this in a OpenAPI v3 schema's paths:

{
  "/description": {
    "get": {
      "responses": {
        "200": {
          "description": "response and schema description",
          "content": {
            "application/json": {
              "schema": {
                "description": "response and schema description",
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}

If you want to provide different descriptions for the response and response body, use the x-response-description field alongside description:

fastify.get('/responseDescription', {
  schema: {
    response: {
      200: {
        'x-response-description': 'response description',
        description: 'schema description',
        type: 'string'
      }
    }
  }
}, () => {})

Status code 2xx

Fastify supports both the 2xx and 3xx status codes, however Swagger (OpenAPI v2) itself does not. @fastify/swagger transforms 2xx status codes into 200, but will omit it if a 200 status code has already been declared. OpenAPI v3 supports the 2xx syntax so is unaffected.

Example:

{
  response: {
    '2xx': {
      description: '2xx',
      type: 'object'
    }
  }
}

// will become
{
  response: {
    200: {
      schema: {
        description: '2xx',
        type: 'object'
      }
    }
  }
}

Response headers

You can decorate your own response headers by following the below example:

{
  response: {
    200: {
      type: 'object',
      headers: {
        'X-Foo': {
          type: 'string'
        }
      }
    }
  }
}

Note: You need to specify type property when you decorate the response headers, otherwise the schema will be modified by Fastify.

Different content types responses

Note: not supported by Swagger (OpenAPI v2), only OpenAPI v3 Different content types responses are supported by @fastify/swagger and @fastify. Please use content for the response otherwise Fastify itself will fail to compile the schema:

{
  response: {
    200: {
      description: 'Description and all status-code based properties are working',
      content: {
        'application/json': {
          schema: { 
            name: { type: 'string' }, 
            image: { type: 'string' }, 
            address: { type: 'string' } 
          }
        }, 
        'application/vnd.v1+json': {
          schema: { 
            fullName: { type: 'string' }, 
            phone: { type: 'string' } 
          }
        }
      }
    }
  }
}
Empty Body Responses

Empty body responses are supported by @fastify/swagger. Please specify type: 'null' for the response otherwise Fastify itself will fail to compile the schema:

{
  response: {
    204: {
      type: 'null',
      description: 'No Content'
    },
    503: {
      type: 'null',
      description: 'Service Unavailable'
    }
  }
}

OpenAPI Parameter Options

Note: OpenAPI's terminology differs from Fastify's. OpenAPI uses "parameter" to refer to parts of a request that in Fastify's validation documentation are called "querystring", "params", and "headers".

OpenAPI provides some options beyond those provided by the JSON schema specification for specifying the shape of parameters. A prime example of this is the collectionFormat option for specifying how to encode parameters that should be handled as arrays of values.

These encoding options only change how Swagger UI presents its documentation and how it generates curl commands when the Try it out button is clicked. Depending on which options you set in your schema, you may also need to change the default query string parser used by Fastify so that it produces a JavaScript object that will conform to the schema. As far as arrays are concerned, the default query string parser conforms to the collectionFormat: "multi" specification. If you were to select collectionFormat: "csv", you would have to replace the default query string parser with one that parses CSV parameter values into arrays. The same applies to the other parts of a request that OpenAPI calls "parameters" and which are not encoded as JSON in a request.

You can also apply different serialization style and explode as specified here.

@fastify/swagger supports these options as shown in this example:

// Need to add a collectionFormat keyword to ajv in fastify instance
const fastify = Fastify({
  ajv: {
    customOptions: {
      keywords: ['collectionFormat']
    }
  }
})

fastify.route({
  method: 'GET',
  url: '/',
  schema: {
    querystring: {
      type: 'object',
      required: ['fields'],
      additionalProperties: false,
      properties: {
        fields: {
          type: 'array',
          items: {
            type: 'string'
          },
          minItems: 1,
          //
          // Note that this is an OpenAPI version 2 configuration option. The
          // options changed in version 3.
          //
          // Put `collectionFormat` on the same property which you are defining
          // as an array of values. (i.e. `collectionFormat` should be a sibling
          // of the `type: "array"` specification.)
          collectionFormat: 'multi'
        }
      },
     // OpenAPI 3 serialization options
     explode: false,
     style: "deepObject"
    }
  },
  handler (request, reply) {
    reply.send(request.query.fields)
  }
})

There is a complete runnable example here.

Complex serialization in query and cookie, eg. JSON

Note: not supported by Swagger (OpenAPI v2), only OpenAPI v3

http://localhost/?filter={"foo":"baz","bar":"qux"}

IMPORTANT CAVEAT You will need to change the default query string parser used by Fastify so that it produces a JavaScript object that will conform to the schema. See example.

fastify.route({
  method: 'GET',
  url: '/',
  schema: {
    querystring: {
      type: 'object',
      required: ['filter'],
      additionalProperties: false,
      properties: {
        filter: {
          type: 'object',
          required: ['foo'],
          properties: {
            foo: { type: 'string' },
            bar: { type: 'string' }
          },
          'x-consume': 'application/json'
        }
      }
    }
  },
  handler (request, reply) {
    reply.send(request.query.filter)
  }
})

Will generate this in the OpenAPI v3 schema's paths:

{
  "/": {
    "get": {
      "parameters": [
        {
          "in": "query",
          "name": "filter",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "foo"
                ],
                "properties": {
                  "foo": {
                    "type": "string"
                  },
                  "bar": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      ]
    }
  }
}
Route parameters

Route parameters in Fastify are called params, these are values included in the URL of the requests, for example:

fastify.route({
  method: 'GET',
  url: '/:id',
  schema: {
    params: {
      type: 'object',
      properties: {
        id: {
          type: 'string',
          description: 'user id'
        }
      }
    }
  },
  handler (request, reply) {
    reply.send(request.params.id)
  }
})

Will generate this in the Swagger (OpenAPI v2) schema's paths:

{
  "/{id}": {
    "get": {
      "parameters": [
        {
          "type": "string",
          "description": "user id",
          "required": true,
          "in": "path",
          "name": "id"
        }
      ],
      "responses": {
        "200": {
          "description": "Default Response"
        }
      }
    }
  }
}

Will generate this in the OpenAPI v3 schema's paths:

{
  "/{id}": {
    "get": {
      "parameters": [
        {
          "schema": {
            "type": "string"
          },
          "in": "path",
          "name": "id",
          "required": true,
          "description": "user id"
        }
      ],
      "responses": {
        "200": {
          "description": "Default Response"
        }
      }
    }
  }
}

Whether params is not present in the schema, or a schema is not provided, parameters are automatically generated, for example:

fastify.route({
  method: 'POST',
  url: '/:id',
  handler (request, reply) {
    reply.send(request.params.id)
  }
})

Will generate this in the Swagger (OpenAPI v2) schema's paths:

{
  "/{id}": {
    "get": {
      "parameters": [
        {
          "type": "string",
          "required": true,
          "in": "path",
          "name": "id"
        }
      ],
      "responses": {
        "200": {
          "description": "Default Response"
        }
      }
    }
  }
}

Will generate this in the OpenAPI v3 schema's paths:

{
  "/{id}": {
    "get": {
      "parameters": [
        {
          "schema": {
            "type": "string"
          },
          "in": "path",
          "name": "id",
          "required": true
        }
      ],
      "responses": {
        "200": {
          "description": "Default Response"
        }
      }
    }
  }
}

Links

Note: not supported by Swagger (OpenAPI v2), only OpenAPI v3

OpenAPI v3 Links are added by adding a links property to the top-level options of a route. See:

fastify.get('/user/:id', {
  schema: {
    params: {
      type: 'object',
      properties: {
        id: {
          type: 'string',
          description: 'the user identifier, as userId'
        }
      },
      required: ['id']
    },
    response: {
      200: {
        type: 'object',
        properties: {
          uuid: {
            type: 'string',
            format: 'uuid'
          }
        }
      }
    }
  },
  links: {
    // The status code must match the one in the response
    200: {
      address: {
        // See the OpenAPI documentation
        operationId: 'getUserAddress',
        parameters: {
          id: '$request.path.id'
        }
      }
    }
  }
}, () => {})

fastify.get('/user/:id/address', {
  schema: {
    operationId: 'getUserAddress',
    params: {
      type: 'object',
      properties: {
        id: {
          type: 'string',
          description: 'the user identifier, as userId'
        }
      },
      required: ['id']
    },
    response: {
      200: {
        type: 'string'
      }
    }
  }
}, () => {})

Hide a route

There are two ways to hide a route from the Swagger UI:

  • Pass { hide: true } to the schema object inside the route declaration.
  • Use the tag declared in hiddenTag options property inside the route declaration. Default is X-HIDDEN.

Swagger function options

Registering @fastify/swagger decorates the fastify instance with fastify.swagger(), which returns a JSON object representing the API. If { yaml: true } is passed to fastify.swagger() it will return a YAML string.

Integration

You can integrate this plugin with @fastify/helmet with some little work.

@fastify/helmet options example:

.register(helmet, instance => {
  return {
    contentSecurityPolicy: {
      directives: {
        ...helmet.contentSecurityPolicy.getDefaultDirectives(),
        "form-action": ["'self'"],
        "img-src": ["'self'", "data:", "validator.swagger.io"],
        "script-src": ["'self'"].concat(instance.swaggerCSP.script),
        "style-src": ["'self'", "https:"].concat(
          instance.swaggerCSP.style
        ),
      }
    }
  }
})

Add examples to the schema

Note: OpenAPI and JSON Schema have different examples field formats.

Array with examples from JSON Schema converted to OpenAPI example or examples field automatically with generated names (example1, example2...):

fastify.route({
  method: 'POST',
  url: '/',
  schema: {
    querystring: {
      type: 'object',
      required: ['filter'],
      properties: {
        filter: {
          type: 'object',
          required: ['foo'],
          properties: {
            foo: { type: 'string' },
            bar: { type: 'string' }
          },
          examples: [
            { foo: 'bar', bar: 'baz' },
            { foo: 'foo', bar: 'bar' }
          ]
        }
      },
      examples: [
        { filter: { foo: 'bar', bar: 'baz' } }
      ]
    }
  },
  handler (request, reply) {
    reply.send(request.query.filter)
  }
})

Will generate this in the OpenAPI v3 schema's path:

"/": {
  "post": {
    "requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "required": ["filter"],
            "properties": {
              "filter": {
                "type": "object",
                "required": ["foo"],
                "properties": {
                  "foo": { "type": "string" },
                  "bar": { "type": "string" }
                },
                "example": { "foo": "bar", "bar": "baz" }
              }
            }
          },
          "examples": {
            "example1": {
              "value": { "filter": { "foo": "bar", "bar": "baz" } }
            },
            "example2": {
              "value": { "filter": { "foo": "foo", "bar": "bar" } }
            }
          }
        }
      },
      "required": true
    },
    "responses": { "200": { "description": "Default Response" } }
  }
}

If you want to set your own names or add descriptions to the examples of schemas, you can use x-examples field to set examples in OpenAPI format:

// Need to add a new allowed keyword to ajv in fastify instance
const fastify = Fastify({
  ajv: {
    plugins: [
      function (ajv) {
        ajv.addKeyword({ keyword: 'x-examples' })
      }
    ]
  }
})

fastify.route({
  method: 'POST',
  url: '/feed-animals',
  schema: {
    body: {
      type: 'object',
      required: ['animals'],
      properties: {
        animals: {
          type: 'array',
          items: {
            type: 'string'
          },
          minItems: 1,
        }
      },
      "x-examples": {
        Cats: {
          summary: "Feed cats",
          description: 
            "A longer **description** of the options with cats",
          value: { 
            animals: ["Tom", "Garfield", "Felix"] 
          }
        },
        Dogs: {
          summary: "Feed dogs",
          value: { 
            animals: ["Spike", "Odie", "Snoopy"] 
          }
        }
      }
    }
  },
  handler (request, reply) {
    reply.send(request.body.animals)
  }
})

$id and $ref usage

Development

In order to start development run:

npm i
npm run prepare

So that swagger-ui static folder will be generated for you.

How it works under the hood

@fastify/static serves swagger-ui static files, then calls /docs/json to get the Swagger file and render it.

How to work with $refs

The /docs/json endpoint in dynamic mode produces a single swagger.json file resolving all your

Acknowledgements

This project is kindly sponsored by:

License

Licensed under MIT.

fastify-swagger's People

Contributors

alexanderniebuhr avatar allevo avatar briceruzand avatar cemremengu avatar climba03003 avatar darkgl0w avatar delvedor avatar dependabot-preview[bot] avatar dependabot[bot] avatar dwickern avatar eomm avatar fdawgs avatar greenkeeper[bot] avatar joaopedrocampos avatar jsumners avatar kibertoad avatar kromol avatar leandroandrade avatar mcollina avatar pavelpolyakov avatar pgaubatz avatar rafaismyname avatar samzilverberg avatar scriptjs avatar serayaeryn avatar skellla avatar thomasthiebaud avatar uzlopak avatar woh avatar zekth 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  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  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  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

fastify-swagger's Issues

Cannot find module 'fastify-swagger'

fastify-swagger module not published the latest version

module.js:538
    throw err;
    ^

Error: Cannot find module 'fastify-swagger'
    at Function.Module._resolveFilename (module.js:536:15)
    at Function.Module._load (module.js:466:25)
    at Module.require (module.js:579:17)
    at require (internal/module.js:11:18)

Project:
screen shot 2017-11-10 at 2 06 03 pm

As above screenshot is shown, I can only see one file package.json after installing fastify-swagger.

Is this project well maintained?

HTTP/2 Support

Fastify currently has experimental HTTP/2 support.

Is it possible to use fastify-swagger with http/2? But since I'm using Typescript, my project won't compile because the fastify-swagger types require a HTTP Server, instead of HTTP2

handling of ajv pattern properties

Hello!
i think this ticket is not a real issue , but might be a missing feature from ajv/swagger.
According to ajv spec we can set dynamic key in properties with the patternProperties.
In fastify it works like charms for validation but not for the swagger gen part.
here is a example :
schema :

 "response": {
      "200": {
       " description":
          "if uplink need acknowledgement (ack=true), set the reponse the configuration for the device (downlink)",
        "type": "object",
        "patternProperties": {
          "^([0-9]|[A-Z])*$": {
            "type": "object",
            "properties": {
              "downlinkData": {
                "type": "string",
                "description": "the encoded hexadecimal configuration"
              }
            }
          }
        },
        "additionalProperties": false
      },

the swagger output:

{
  "responses": {
    "200": {
      "schema": {
        "description": "if uplink need acknowledgement (ack=true), set the reponse the configuration for the device (downlink)",
        "type": "object",
        "patternProperties": {
          "^([0-9]|[A-Z])*$": {
            "type": "object",
            "properties": {
              "downlinkData": {
                "type": "string",
                "description": "the encoded hexadecimal configuration"
              }
            }
          }
        },
        "additionalProperties": false
      },
      "description": "if uplink need acknowledgement (ack=true), set the reponse the configuration for the device (downlink)"
    }
  }
}

So we clearly see that the swagger schema holds a patternProperties wich is not descriped in the swagger spec v3. https://swagger.io/docs/specification/data-models/dictionaries/

thanks for your time.
Olivier

Corrupt file attachments

We encountered an issue where a file download triggered via the Content-Disposition header will result in a link to download the file, but the file will be corrupt. A similiar issue is also documented in following swagger-ui issue:

swagger-api/swagger-ui#4638

In our case we want to download a tar-file. So the content-type of the response is application/gzip. We want to add the download-endpoint to the swagger-documentation but if we do that the downloaded file is corrupt.

In the swagger-api/swagger-ui#4638 Issue the solution is to upgrade to Swagger UI 3. Is there a workaround in fastify-swagger?

Remove dynamic requirements

I use webpack on the server side. ES 6 expects static imports and emits the following warnings. In general, I believe it is bad practice to include dynamic requirements in a module - even while a dynamic import is being considered in ES.

I have replaced my project path with '/path/to/project' in the traces below:

WARNING in /path/to/project/index.js
47:15-60 Critical dependency: the request of a dependency is an expression
 @ ./node_modules/fastify-swagger/index.js
 @ ./es6/lib/app/index.js
 @ ./es6/index.js

I'll send a PR for this.

Multiple docs in project

Hi,
I need to make different docs for different routes in my application. I have 2 "root" routes, for example:

fastify.register(require('./routes/one'), {
  prefix: '/one'
})

fastify.register(require('./routes/two'), {
  prefix: '/two'
})

And want two documentations for subroutes of /one and /two.
Is there any way to make it now? Or maybe add something like subroutesOf: '/one' parameter to plugin options to filter routes needed for each documentation?
Thanks for your time.

Plugin not working with JOI

Here is schema example for route:

import * as Joi from 'joi';

export const PING_CREATE_VALIDATOR = {
    schema: {
        body: Joi.object({
            example: Joi.string().required(),
        }).required(),
    },
    schemaCompiler: (schema: any) => (data: any) => Joi.validate(data, schema),
};

Error:

TypeError: Cannot read property 'description' of null
    at Object.keys.forEach.p (node_modules/fastify-swagger/index.js:217:34)
    at Array.forEach (native)
    at getPathParams (node_modules/fastify-swagger/index.js:212:23)
    at Object.swagger (node_modules/fastify-swagger/index.js:121:11)
    at fastify.ready (src/app.ts:49:20)
    at Object._encapsulateThreeParam (node_modules/avvio/boot.js:345:7)
    at Boot.callWithCbOrNextTick (node_modules/avvio/boot.js:300:5)
    at Object.push (node_modules/fastq/queue.js:88:14)
    at Boot.ready (node_modules/avvio/boot.js:255:18)
    at Object.server.(anonymous function) [as ready] (node_modules/avvio/boot.js:46:21)

Returned specs does not contain definitions

Hi,

I would like to convert the spec I get from const spec = fastify.swagger() into a typescript d.ts.

I tryied many libraries, but none could do the trick. Then I realised that there was no definitions property in the outputed spec. I can see the paths, but no definition.

Is there any setting to output it?

Declare an empty response for 204

For 204 response (empty response), Swagger allows for its description by not specifying a content https://swagger.io/docs/specification/describing-responses/.

However, for fastify-swagger, I haven't found a way to do that yet. If I do:

{
  schema: {
    response: {
      204: {
        description: 'Successfully deleted item'
      }
    }
  }
}

I get the following stacktrace:

Uncaught Exception Error: undefined unsupported
    at build (/Users/tri/project/node_modules/fast-json-stringify/index.js:80:13)
    at getValidatorForStatusCodeSchema (/Users/tri/project/node_modules/fastify/lib/validation.js:12:10)
    at /Users/tri/project/node_modules/fastify/lib/validation.js:18:21
    at Array.reduce (<anonymous>)
    at getResponseSchema (/Users/tri/project/node_modules/fastify/lib/validation.js:17:22)
    at build (/Users/tri/project/node_modules/fastify/lib/validation.js:44:28)

Wrong redirect

v0.10.1 - There stil seems to be a bug when using routePrefix: '/' even after this fix (#65) from @allevo. It redirects the browser to index.html instead of http://domain/index.html

fastify.ready() with fastify-cli

Hello everyone.
I'm using fastify-cli to run my project, and don't know where to add the configuration:

fastify.ready(err => {
  if (err) throw err
  fastify.swagger()
})

Thanks!

Not support JSON schema items properties object

{
  type: "object",
  required: ["message", "errors"]
  properties: {
    message: {
      type: "string"
    },
    errors: {
      type: "array",
      items: [
        {
          type: "object",
          properties: {
            field: {
              type: "string"
            },
            error: {
              type: "string"
            },
            type: {
              type: "string"
            }
          }
        }
      ]
    }
  }
}

image

Authorize UI does appear to work when configured

I don't seem to be able to configure authorization properly to gain the authorize UI button in the docs as in the petstore reference implementation you see in the image below:

screen shot 2018-01-04 at 10 51 25 pm

I have attempted by setting headers ie.

  headers: {
    type: 'object',
    properties: {
      'x-api-token': {
        type: 'string',
        description: 'optional api token'
      },
      'x-api-version': {
        type: 'string',
        description: 'optional api version'
      }
    }
  },

and

  headers: {
    type: 'object',
    properties: {
      authorization: {
        type: 'string',
        description: 'api token'
      }
    },
    required: ['authorization']
  },

from what I was able to read from the tests.

I have also tried adding securityDefinitions within the swagger object. These are normally attached to a security object for scope ie.

"security": [{
  "api_key": []
}]

Add a transform method for schema

Hello I would like to suggest an extra option to add a transform method in the plugin options for dynamic mode.
Use case : using Joi validation library we need to convert Joi schema back into a JSON schema only for Swagger documentation generation. With a transform method it would be easy to convert it with a third-party library.

Support passing swagger definition in static mode

Currently, in static mode, there is no way to pass a content of the file directly. You need to pass the path to the file instead.

Current behavior

mode: 'static',
specification: {
    path: './examples/example-static-specification.yaml'
},

New feature request

mode: 'static',
specification: {
    doc: {
        ...real swagger document... (content of the specification file)
    }
},

Why?

We use fastify-swagger to provide a fastify integration with NestJS (and Swagger module exposed by @nestjs/swagger). Unluckily, we cannot fully support this platform since there is no way to pass swagger definition's object directly (you always have to pass a path to the file in static mode). Would it be a big deal to provide such possibility in the future?

Support openapi 3.0 for dynamic configuration

Seems underlying module swagger-parser already supports new openapi v3 specifications. So I think it would be good if this module will support it as well.

The main idea just to make https://github.com/fastify/fastify-swagger/blob/master/dynamic.js#L59 configurable through options.

However it will also require to refactor some things like securityDefinitions, because in 3.0 they moved to other sections of config file.

I'm not sure that fastify schemas are compatible with openapi v3 specs.

Fastify-Swagger introduction to a TYPESCRIPT proj doen't allow swagger details

While importing fastify-swagger into a fastify (ts) based project, when we are defining the schema of any method, we are restricted because of the RouteSchema defined in the fastify.d.ts.
For Swagger we need to expand this to include other properties like documenation,tags,summary,security.
Creating a pull reques to acheive this.

file upload schema error 400

Hi, when i define the schema consumer in endpoint /upload to 'multipart/form-data' for uploading file i dont know wich is the schema structure body for passing the base64 string or the file that i need to upload.

If y define the schema:

schema: {
      description: 'Upload file',
      tags: ['Info'],
      consumes: [ 'multipart/form-data' ],
      summary: 'Upload the file to the server',
      body: {
        type: 'object',
        properties: {
          file: {type: 'string'}
        }
      },
      response: {
        200: {
          description: 'Succesful response',
          type: 'boolean'
        }
      }
    }

when i send the post get the error:

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "body should be object"
}

I fetch in the dynamic.js code looking for the solution but i dont get with it.

Can you help me?

PD: Im sorry if this is not the place for this kind of issues.

Thx

An in-range update of fastify is breaking the build 🚨

☝️ Greenkeeper’s updated Terms of Service will come into effect on April 6th, 2018.

Version 1.2.1 of fastify was just published.

Branch Build failing 🚨
Dependency fastify
Current Version 1.2.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

fastify is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Release Notes v1.2.1

Fixes

  • Run onSend hooks when an encapsulated handler invokes the notFound handler - #870
  • Updated default 404 message - #870

Docs

  • Fix typo in getting started documentation #869
  • Fix broken links - #866
Commits

The new version differs by 4 commits.

  • 2d8ac88 Bumped v1.2.1
  • cc2f9c9 Run onSend hooks when an encapsulated handler invokes the notFound handler (#870)
  • b010287 Fix typo in getting started documentation (#869)
  • 8491872 [docs] Fix broken links (#866)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Deprecated route

Hi!, i have a deprecated route in schema and defined like deprecated: true but not showing in the ui the route with the style like line-through.

This is an issue or im not defining the schema correctly?

Thx!

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! 🎊

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml

If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didn’t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected πŸ€–


FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Problems with `ignoreTrailingSlash` fastify option

Hello, just taking the dynamic example and changing the fastify construction:

const fastify = require('fastify')({
  ignoreTrailingSlash: true
})

makes the url sample documentation url http://localhost:3000/documentation redirect to http://localhost:3000/documentation/documentation

Seems related to the routes redirect. But I am really not sure where the real cause and true good fix is... in this plugin, fastify or find-my-way... I can't really find where the original redirect happens in fastify or find-my-way that seems to be cause by ignoreTrailingSlash option.

I would think ideally if we could know the options of fastify instance we could just ignore the setup of redirect route. But I can't seem to find a nice way of knowing if that option is turned on as it or the original options do not seem to be exposed? I would be willing to do a PR with some guidance on the best approach where the fix is.

I also checked this with code in #56 and it still exhibits this issue.

image

Thanks.

fastify is not iterable

Versions

name version
node 8.9.0
fastify 0.40.0
fastify-swagger 0.3.1

Error

TypeError: fastify is not iterable
    at Function.swagger (/codes/node_modules/fastify-swagger/index.js:70:22)
    at fastify.ready (/codes/server.js:44:11)
    at Function._encapsulateThreeParam (/codes/node_modules/avvio/boot.js:332:7)
    at Boot.callWithCbOrNextTick (/codes/node_modules/avvio/boot.js:287:5)
    at release (/codes/node_modules/fastq/queue.js:127:16)
    at Object.resume (/codes/node_modules/fastq/queue.js:61:7)
    at Boot.Plugin.loadPlugin.call (/codes/node_modules/avvio/boot.js:141:20)
    at toLoad.finish (/codes/node_modules/avvio/plugin.js:108:7)
    at done (/codes/node_modules/avvio/plugin.js:66:5)
    at check (/codes/node_modules/avvio/plugin.js:77:7)

Script

const fastify = require('fastify')({
  logger: {
    level: 'info',
  },
});
const fastifySwagger = require('fastify-swagger');

const routes = require('./app/controller');

fastify.register(fastifySwagger, {
  swagger: {
    info: {
      title: 'insurance-agent-favor/backend',
      version: '0.1.0',
    },
    host: 'localhost',
    schemes: ['http'],
    consumes: ['application/json'],
    produces: ['application/json'],
  },
  exposeRoute: true,
});
fastify.register(routes);

const start = async () => {
  try {
    await fastify.listen(3000);
    fastify.swagger();
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};
start();

Else

It is ok with [email protected]

Undefined description in path parameters will cause yaml dump crash

As the title described, if I didn't add description field in parameters in schema when I access /documentation/yaml will cause crash, and the expection is:

YAMLException: unacceptable kind of an object to dump [object Undefined]

Specifically in line 146 in index.js

const swaggerString = yaml.safeDump(swaggerObject)

Since the yaml feature is bundled with documentation routes feature no matter if user need it or not, so this will lead to potential risk.

Actually js-yaml has an option for ignoring invalid value when dumps, see safedump docs
Simply change to this:

const swaggerString = yaml.safeDump(swaggerObject, { skipInvalid: true })

This may hide the exception, but at least it will not crash.

An in-range update of tap is breaking the build 🚨

The devDependency tap was updated from 12.1.1 to 12.1.2.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

tap is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Commits

The new version differs by 7 commits.

  • cf8a2e1 12.1.2
  • 04d27df Add attributes file
  • 3620c76 Remove some tests of things that can't be done in v11+
  • f61181a Run snapshots in -J mode, remove an extraneous test
  • 699b179 (synonym) added 'identical' to same to create symmetry to 'equivalent' synonym on equal
  • fe466f5 test: don't break when running in buffered mode
  • f1979a9 typo in usage.txt

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Params with separator breaking docs

I'm trying to do a route like the one specified in the Fastify docs with two params between a single set of slashes using the dash separator:

fastify.get('/example/near/:lat-:lng/radius/:r', (request, reply) => {}))

My specific route is pretty close to this: '/transform_point/:lat-:lng/:srid'. This end point works fine. The Swagger docs, however, seem to break on the separator. The path ends up looking like this:

path

The schema populates the test form correctly with the route inputs, but after hitting execute it doesn't populate the lng and lat route parameters, seemingly treating that portion of the route as a static string.

curl

My schema parameters look like this:

params: {
    lat: {
      type: 'number',
      description: 'x coordinate'
    },
    lng: {
      type: 'number',
      description: 'y coordinate'
    },
    srid: {
      type: 'integer',
      description: 'SRID of the coordinate'
    }
  },

Am I doing something wrong, or are two params between a set of slashes unsupported? Am I better off making it a single parameter and regex-ing a [number][separator][number] validation?

Many thanks!

generate fastify code from swagger definition ?

Hi,

Since fastify already uses JSON-schema I thought it might be an idea to try to generate fastify code from a swagger doc so one can use a Design-First approach as well.
Either using swagger codegen, a fastify specific tool or fully dynamically by using JSON path queries on a swagger definition (using a fastify plugin ?)

Has anybody already tried this ?

Swagger codegen currently only generates Express code for NodeJS

Kind regards,
Hans

Rename repository to fastify-openapi

Swagger 2 was made OpenAPI 2 quite some time ago. Swagger is the brand name of SmartBear Software. In the spirit of the move to the open standard, the previous Swagger 2 specification became the OpenAPI 2 specification. Version 3 of the OpenAPI specification is still undergoing review.

I am recommending the repository name be changed to fastify-openapi to reflect the direction of the standard and to stop using SmartBear's proprietary branding.

This will require a few small changes since the higher level object is referred to as swagger at the moment.

How to add Dynamic Querystring Parameters ?

Hello
I'm trying to achieve the same goal than this : https://stackoverflow.com/questions/49582559/how-to-document-dynamic-query-parameter-names-in-openapi-swagger
basically trying to mix on the doc some known querystrings params with not known that can be used by the api behind dynamically :

GET api/v1/users?knownParam1=value1&knownParam2=value2...&dynamicParam1=...&foo=bar

I tryied the object type with the additionalProperties flag :

  querystring: {
    knownParam1: { type: 'string', description: 'String - bla bla ' },
    knownParam2:{ type: 'string', description: 'String - bla bla ' },
    params : {
      'type': 'object',
      'properties': {
        unknownParam1: { type: 'string' },
        unknownParam2: { type: 'string' }
      },
      'additionalProperties': true,
    },

But the end result still have a "params" parameter rather than listing the examples

I try really to mix known api query params and unknowparams, the free form object seems to fit my need for the unknowns but I don't know how to make that key dynamic to let the user generate the additional ones exactly as in the SOF thread
image

If Someone has any idea,
thanks

External $ref does not work

Description
It doesn't work if $ref is pointing to the definition in another file. External references are supported by swagger

This code does not work:
$ref: './resources.yaml#/resources/User'

Expected result
It should load definition from external files

Actual result
It fails when it tries to load the file (GET /documentation/path-to-file). Server responds with 404 since it's not aware about any other files except of main swagger file that is passed to the plugin.

Swagger expose "/documentation/*" endpoint

Hi, i have an issue that i dont know if to others happend but in swagger is loading the /documentation/* endpoint, i resolve if i ask in the fastify-swagger plugin by the condition in dynamic:

if (route.path === 'documentation/*' || route.schema && route.schema.hide)

but i dont know if is the correct way because maybe someone just resolvered.

This is the json that swagger generates with only one endpoint:

{
   "swagger":"2.0",
   "info":{
      "version":"1.0.0",
      "title":"API Documentation",
      "description":"API Endpoints Documentation"
   },
   "schemes":[
      "https",
      "http"
   ],
   "consumes":[
      "application/json"
   ],
   "produces":[
      "application/json"
   ],
   "paths":{
      "/documentation/*":{
         "get":{
            "responses":{
               "200":{
                  "description":"Default Response"
               }
            }
         }
      },
      "/v1/keep-alive":{
         "get":{
            "summary":"Obtain the status of the API",
            "description":"Get the status of the API",
            "tags":[
               "Info"
            ],
            "responses":{
               "200":{
                  "schema":{
                     "description":"Succesful response",
                     "type":"string"
                  },
                  "description":"Succesful response"
               },
               "400":{
                  "schema":{
                     "description":"Not Found response",
                     "type":"string"
                  },
                  "description":"Not Found response"
               },
               "500":{
                  "schema":{
                     "description":"Error response",
                     "type":"object",
                     "properties":{
                        "error":{
                           "type":"string"
                        },
                        "message":{
                           "type":"string"
                        },
                        "statusCode":{
                           "type":"number"
                        }
                     }
                  },
                  "description":"Error response"
               }
            }
         }
      }
   }
}

and this is my config:

{
   "swagger":{
      "info":{
         "version":"1.0.0",
         "title":"API Documentation",
         "description":"API Endpoints Documentation"
      },
      "schemes":[
         "http"
      ],
      "consumes":[
         "application/json"
      ],
      "produces":[
         "application/json"
      ]
   },
   "exposeRoute":true
}

Unable to generate the /documentation Swagger URI

Hi Team,
I am testing this plugin with Fastify 1.0.0-rc-2 and even after lot of attempts unable to get the swagger UI up. The JSON representation shows that the default URL /documentation is not a part of swagger configuration that is being returned.

{"swagger":"2.0","info":{"title":"Test swagger","description":"testing the fastify swagger api","version":"0.1.0"},"host":"localhost","schemes":["http"],"consumes":["application/json"],"produces":["application/json"],"paths":{"/":{"get":{"responses":{"200":{"description":"Default Response"}}}},"/error":{"get":{"responses":{"200":{"description":"Default Response"}}}},"/some-route/{id}":{"put":{"summary":"qwerty","description":"post some data","tags":["user","code"],"parameters":[{"name":"body","in":"body","schema":{"type":"object","properties":{"hello":{"type":"string"},"obj":{"type":"object","properties":{"some":{"type":"string"}}}}}},{"name":"id","in":"path","required":true,"description":"user id","type":"string"}],"responses":{"201":{"schema":{"description":"Successful response","type":"object","properties":{"hello":{"type":"string"}}},"description":"Successful response"}}}},"/ram":{"get":{"responses":{"200":{"description":"Default Response"}}}}}}

This is what I am getting. All the source code is available at https://github.com/panbhatt/Fastify-api-boilerplate ( in master branch ). Please HELP.

[Suggestion] Change swagger url

Hi,

Are you guys open for a PR that will customize the url so let's say I want to change the url from documentation to docs?

Let me know what you guys think.

Cheers.

An in-range update of swagger-parser is breaking the build 🚨

Version 5.0.4 of swagger-parser was just published.

Branch Build failing 🚨
Dependency swagger-parser
Current Version 5.0.2
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

swagger-parser is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Commits

The new version differs by 8 commits.

  • 5870803 release v5.0.4
  • 9331095 updated dependencies
  • 33a665c fixed a line of code that didn't work on some older web browsers (IE11)
  • e58c457 Merge pull request #92 from marcelstoer/feat/dup-operationId
  • 4e6ed4b Add check for duplicate operation ids
  • f8113cf release v5.0.3
  • 91640e9 updated dependencies
  • 8c62e51 Modified the sample URL to use HTTPS instead of HTTP

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

'Error: plugin must be a function' while using Jest coverage reporting

I've been stuck debugging this issue all day. I think I've finally figure out the source of the issue and it looks like it has something to do with Jest coverage generator, fastify-swagger, and avvio.

On this PR: MatterhornDev/matterhorn#25
A user has added fastify-swagger to a basic fastify server.

I'm using Jest for testing. npm run test works as expected. Everything is green.

Running npm run test:ci or npm run coverage (which both execute jest --coverage in some fashion) everything fails and blows up.

I found this issue: swagger-api/swagger-node#560 (comment) which mentions that the swagger doc generator doesn't exactly play nicely with Jest. I added "collectCoverageFrom": [ "src" ] to my jest.config.json in order to force the coverage reporter to only look at my actual source code. This resolved a really nasty (barely useful) error message and has now left me with the following:

πŸ‘» matterhorn (panbhatt-fastify_swagger_implementation %)β–· npm run test -- --coverage --coverageReporters=lcov

> [email protected] test /Users/ethanarrowood/Documents/GitHub/matterhorn
> jest --config jest.config.json "--coverage" "--coverageReporters=lcov"

/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:178
    throw new Error('plugin must be a function')
    ^

Error: plugin must be a function
    at Boot.Object.<anonymous>.Boot.use (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:178:11)
    at Object.server.(anonymous function) [as register] (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio
/boot.js:30:14)
    at Object.<anonymous>.module.exports [as dynamic] (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastify-swagger/dynamic.js:35:13)
    at fastifySwagger (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastify-swagger/index.js:18:13)
    at Plugin.Object.<anonymous>.Plugin.exec (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:84:17)
    at Boot.loadPlugin (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:168:10)
    at Task.release (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastq/queue.js:127:16)
    at worked (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastq/queue.js:169:10)
    at toLoad.finish (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:171:7)
    at done (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:129:5)
    at check (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:140:7)
    at processTicksAndRejections (internal/process/next_tick.js:74:9)
 PASS  tests/index.test.ts
/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:178
    throw new Error('plugin must be a function')
    ^

Error: plugin must be a function
    at Boot.Object.<anonymous>.Boot.use (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:178:11)
    at Object.server.(anonymous function) [as register] (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio
/boot.js:30:14)
    at Object.<anonymous>.module.exports [as dynamic] (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastify-swagger/dynamic.js:35:13)
    at fastifySwagger (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastify-swagger/index.js:18:13)
    at Plugin.Object.<anonymous>.Plugin.exec (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:84:17)
    at Boot.loadPlugin (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:168:10)
    at Task.release (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastq/queue.js:127:16)
    at worked (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastq/queue.js:169:10)
    at toLoad.finish (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:171:7)
    at done (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:129:5)
    at check (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:140:7)
    at processTicksAndRejections (internal/process/next_tick.js:74:9)
/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:178
    throw new Error('plugin must be a function')
    ^

Error: plugin must be a function
    at Boot.Object.<anonymous>.Boot.use (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:178:11)
    at Object.server.(anonymous function) [as register] (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:30:14)
    at Object.<anonymous>.module.exports [as dynamic] (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastify-swagger/dynamic.js:35:13)
    at fastifySwagger (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastify-swagger/index.js:18:13)
    at Plugin.Object.<anonymous>.Plugin.exec (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:84:17)
    at Boot.loadPlugin (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:168:10)
    at Task.release (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastq/queue.js:127:16)
    at worked (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastq/queue.js:169:10)
    at toLoad.finish (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:171:7)
    at done (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:129:5)
    at check (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:140:7)
    at processTicksAndRejections (internal/process/next_tick.js:74:9)
/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:178
    throw new Error('plugin must be a function')
    ^

Error: plugin must be a function
    at Boot.Object.<anonymous>.Boot.use (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:178:11)
    at Object.server.(anonymous function) [as register] (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/boot.js:30:14)
    at Object.<anonymous>.module.exports [as dynamic] (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastify-swagger/dynamic.js:35:13)
    at fastifySwagger (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastify-swagger/index.js:18:13)
    at Plugin.Object.<anonymous>.Plugin.exec (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:84:17)
    at Boot.loadPlugin (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:168:10)
    at Task.release (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastq/queue.js:127:16)
    at worked (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/fastq/queue.js:169:10)
    at toLoad.finish (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:171:7)
    at done (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:129:5)
    at check (/Users/ethanarrowood/Documents/GitHub/matterhorn/node_modules/avvio/plugin.js:140:7)
    at processTicksAndRejections (internal/process/next_tick.js:74:9)
 FAIL  tests/plugins.test.ts
  ● Test suite failed to run

    Call retries were exceeded

      at ChildProcessWorker.initialize (node_modules/jest-worker/build/workers/ChildProcessWorker.js:177:21)

Test Suites: 1 failed, 1 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        7.605s
Ran all test suites.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test: `jest --config jest.config.json "--coverage" "--coverageReporters=lcov"`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/ethanarrowood/.npm/_logs/2019-03-12T01_47_07_774Z-debug.log

I'm now going to try and dig into these error messages, but I thought I'd post this issue in case someone could spot the mistake or propose a solution faster than I can.

FWIW, coverage works fine on the master branch (where there is no fastify-swagger installed).

Some other areas I have debunked:

  • It is not caused by the directory structure or import structure of my src/ contents
  • As far as I can tell everything has been updated (and works as expected on master)

Declare 204 with type null

When I declare the scheme as below

response: {
        204: {
          description: 'Succesful response',
        },
      },

I get the following stacktrace:

Error: undefined unsupported
    at build (/Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/fast-json-stringify/index.js:94:13)
    at getValidatorForStatusCodeSchema (/Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/fastify/lib/validation.js:13:10)
    at /Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/fastify/lib/validation.js:19:21
    at Array.reduce (<anonymous>)
    at getResponseSchema (/Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/fastify/lib/validation.js:18:22)
    at build (/Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/fastify/lib/validation.js:58:31)
    at afterRouteAdded (/Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/fastify/fastify.js:607:9)
    at Object._encapsulateThreeParam (/Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/avvio/boot.js:387:7)
    at Boot.callWithCbOrNextTick (/Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/avvio/boot.js:311:5)
    at Boot._after (/Users/guilherme.gregio/Documents/easynvest/easynvest.preferencies/node_modules/avvio/boot.js:215:26)

When I try use type: 'null'

response: {
        204: {
          type: 'null',
          description: 'Succesful response',
        },
      },

But the result is "Unknown Type: null" in model's section on swagger doc

Add support for different response content types

Swagger supports different content types in the response like this:

/health:
  get:
    responses:
      '200':
        description: Successful response
        content:
          text/plain:
            schema:
              type: string
              enum: ['UP','DOWN']

Currently it is not possible to define a response like this with fastify-swagger.

Support `tags` and `externalDocs` in dynamic mode

As per OpenAPI 2.0 specification, you are missing 2 top-level fields described here https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields:

  • tags
  • externalDocs

Because you are reconstructing swaggerObject from opts.swagger in dynamic.js even if those fields are given, they are stripped in the output.

I'm filing this issue because I found that tags was missing, but there may be more fields that are lacking deeper down, I didn't check.

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.