express-jsdoc-swagger
express-jsdoc-swagger copied to clipboard
Swagger OpenAPI 3.x generator
express-jsdoc-swagger
With this library, you can document your express endpoints using swagger OpenAPI 3 Specification without writing YAML or JSON. You can write comments similar to jsdoc
on each endpoint, and the dependecy is going to create the swagger UI.
Table of Contents
- Prerequisites
- Installation
- Basic Usage
- Basic Examples
- Validator
- VSCode extension
Prerequisites
This library assumes you are using:
Installation
npm i express-jsdoc-swagger
Basic Usage
// index.js file
const express = require('express');
const expressJSDocSwagger = require('express-jsdoc-swagger');
const options = {
info: {
version: '1.0.0',
title: 'Albums store',
license: {
name: 'MIT',
},
},
security: {
BasicAuth: {
type: 'http',
scheme: 'basic',
},
},
// Base directory which we use to locate your JSDOC files
baseDir: __dirname,
// Glob pattern to find your jsdoc files (multiple patterns can be added in an array)
filesPattern: './**/*.js',
// URL where SwaggerUI will be rendered
swaggerUIPath: '/api-docs',
// Expose OpenAPI UI
exposeSwaggerUI: true,
// Expose Open API JSON Docs documentation in `apiDocsPath` path.
exposeApiDocs: false,
// Open API JSON Docs endpoint.
apiDocsPath: '/v3/api-docs',
// Set non-required fields as nullable by default
notRequiredAsNullable: false,
// You can customize your UI options.
// you can extend swagger-ui-express config. You can checkout an example of this
// in the `example/configuration/swaggerOptions.js`
swaggerUiOptions: {},
// multiple option in case you want more that one instance
multiple: true,
};
const app = express();
const PORT = 3000;
expressJSDocSwagger(app)(options);
/**
* GET /api/v1
* @summary This is the summary of the endpoint
* @return {object} 200 - success response
*/
app.get('/api/v1', (req, res) => res.json({
success: true,
}));
app.listen(PORT, () => console.log(`Example app listening at http://localhost:${PORT}`));
Basic Examples
- Basic configuration options.
const options = {
info: {
version: '1.0.0',
title: 'Albums store',
license: {
name: 'MIT',
},
},
security: {
BasicAuth: {
type: 'http',
scheme: 'basic',
},
},
baseDir: __dirname,
// Glob pattern to find your jsdoc files (multiple patterns can be added in an array)
filesPattern: './**/*.js',
};
- Components definition
/**
* A song type
* @typedef {object} Song
* @property {string} title.required - The title
* @property {string} artist - The artist
* @property {number} year - The year - double
*/
- Endpoint which returns a
Songs
model array in the response.
/**
* GET /api/v1/albums
* @summary This is the summary of the endpoint
* @tags album
* @return {array<Song>} 200 - success response - application/json
*/
app.get('/api/v1/albums', (req, res) => (
res.json([{
title: 'abum 1',
}])
));
- Endpoint PUT with body and path params which returns a
Songs
model array in the response.
/**
* PUT /api/v1/albums/{id}
* @summary Update album
* @tags album
* @param {string} name.path - name param description
* @param {Song} request.body.required - songs info
* @return {array<Song>} 200 - success response - application/json
*/
app.put('/api/v1/albums/:id', (req, res) => (
res.json([{
title: 'abum 1',
}])
));
- Basic endpoint definition with tags, params and basic authentication
/**
* GET /api/v1/album
* @summary This is the summary of the endpoint
* @security BasicAuth
* @tags album
* @param {string} name.query.required - name param description
* @return {object} 200 - success response - application/json
* @return {object} 400 - Bad request response
*/
app.get('/api/v1/album', (req, res) => (
res.json({
title: 'abum 1',
})
));
- Basic endpoint definition with code example for response body
/**
* GET /api/v1/albums
* @summary This is the summary of the endpoint
* @tags album
* @return {array<Song>} 200 - success response - application/json
* @example response - 200 - success response example
* [
* {
* "title": "Bury the light",
* "artist": "Casey Edwards ft. Victor Borba",
* "year": 2020
* }
* ]
*/
app.get('/api/v1/albums', (req, res) => (
res.json([{
title: 'track 1',
}])
));
You can find more examples here, or visit our documentation.
Validator
We developed a new package works as a validator of your API endpoints and the documentation you create with this package. This package is express-oas-validator.
Example
Install using the node package registry:
npm install --save express-oas-validator
We have to wait until we have the full swagger schema to initiate the validator.
// validator.js
const { init } = require('express-oas-validator');
const validators = instance => new Promise((resolve, reject) => {
instance.on('finish', (swaggerDef) => {
const { validateRequest, validateResponse } = init(swaggerDef);
resolve({ validateRequest, validateResponse });
});
instance.on('error', (error) => {
reject(error);
});
});
module.exports = validators;
You can check out this also in our example folder.
// index.js
const express = require('express');
const expressJSDocSwagger = require('express-jsdoc-swagger');
const validator = require('./validator');
const options = {
info: {
version: '1.0.0',
title: 'Albums store',
license: {
name: 'MIT',
},
},
filesPattern: './**.js',
baseDir: __dirname,
};
const app = express();
const instance = expressJSDocSwagger(app)(options);
const serverApp = async () => {
const { validateRequest, validateResponse } = await validator(instance);
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
/**
* A song
* @typedef {object} Song
* @property {string} title.required - The title
* @property {string} artist - The artist
* @property {integer} year - The year
*/
/**
* POST /api/v1/songs
* @param {Song} request.body.required - song info
* @return {object} 200 - song response
*/
app.post('/api/v1/songs', validateRequest(), (req, res) => res.send('You save a song!'));
/**
* POST /api/v1/name
* @param {string} request.body.required - name body description
* @return {object} 200 - song response
*/
app.post('/api/v1/name', (req, res, next) => {
try {
// Validate response
validateResponse('Error string', req);
return res.send('Hello World!');
} catch (error) {
return next(error);
}
});
/**
* GET /api/v1/authors
* @summary This is the summary or description of the endpoint
* @param {string} name.query.required - name param description - enum:type1,type2
* @param {array<string>} license.query - name param description
* @return {object} 200 - success response - application/json
*/
app.get('/api/v1/authors', validateRequest({ headers: false }), (req, res) => (
res.json([{
title: 'album 1',
}])
));
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
res.status(err.status).json(err);
});
return app;
};
const PORT = process.env.PORT || 4000;
serverApp()
.then(app =>
app.listen(PORT, () =>
console.log(`Listening PORT: ${PORT}`)
))
.catch((err) => {
console.error(err);
process.exit(1);
});
You can visit our documentation.
Contributors ✨
This project follows the all-contributors specification. Contributions of any kind welcome!