
Security News
Open Source Maintainers Feeling the Weight of the EU’s Cyber Resilience Act
The EU Cyber Resilience Act is prompting compliance requests that open source maintainers may not be obligated or equipped to handle.
express-openapi-generator
Advanced tools
An Express plugin that can parse an app and generate a OpenApiv3 document.
This package analyzes an Express app project, generating OpenApi v3 documentation. The optional middleware attaches additional documentation to routes and provides optional request validation.
This project takes a minimalist, un-opinionated approach with only a single dependency, express-route-parser, a dependency free package developed and maintained by me.
npm i express-openapi-generator
You can use this package to generate quick and dirty valid open api specs for every route on your project.
API Documentation: TS Docs
Warning: OpenApi does not support exotic route matching, such as /p(ab)th
, /p*ath/
, or optional path parameters /:name?
. If these are in your project the generated document won't follow the OpenApi v3 spec. It may still work, since the route parser can handle these special routes, but plugins like swagger ui may fail.
import express, { Request, Response } from 'express'
import { DocumentBuilder } from 'express-openapi-generator'
const app = express();
const router = express.Router();
// This initializes and creates our document builder interface
const documentBuilder = DocumentBuilder.initializeDocument({
openapi: '3.0.1',
info: {
title: 'A example document',
version: '1',
},
paths: {}, // You don't need to include any path objects, those will be generated later
});
app.use(express.json())
app.use('/api/v1', router);
router.get('/user/:id', (req: Request, res: Response) => {
res.json({ id: '1', name: 'John Smith' });
});
router.post('/user', (req: Request, res: Response) => {
const save = req.body;
res.json(save);
});
// Generates our full open api document
documentBuilder.generatePathsObject(app);
// The final document can be retrieved with the build() method. A new deep copy is created each time.
console.log(documentBuilder.build());
Output
const exampleDocumentOutput = {
openapi: '3.0.1',
info: { title: 'A example document', version: '1' },
paths: {
'/api/v1/user': {
post: {
responses: {
default: { description: 'Responses object not provided for this route' },
},
},
},
'/api/v1/user/{id}': {
get: {
responses: {
default: { description: 'Responses object not provided for this route' },
},
parameters: [{
in: 'path',
name: 'id',
required: true,
schema: {
type: 'string',
},
}],
},
},
},
};
import express, { Request, Response } from 'express';
import { OpenAPIV3 } from 'openapi-types';
import { DocumentBuilder, PathMiddleware, ResponseBuilder, OperationBuilder } from '../index';
const app = express();
const router = express.Router();
// This initializes and creates our document builder interface
const documentBuilder = DocumentBuilder.initializeDocument({
openapi: '3.0.1',
info: {
title: 'A example document',
version: '1',
},
paths: {}, // You don't need to include any path objects, those will be generated later
});
const userSchema: OpenAPIV3.SchemaObject = {
title: 'A user object',
type: 'object',
properties: {
id: { type: 'integer' },
name: { type: 'string' },
},
};
documentBuilder.schema('user', { component: userSchema });
app.use(express.json())
app.use('/api/v1', router);
// Create our open api operation object following OpenApiv3 specification
const createUserOperation: OpenAPIV3.OperationObject = {
operationId: 'createUser',
tags: ['users'],
responses: {
'200': {
description: 'Create a User',
content: {
'application/json': {
schema: documentBuilder.schema('user'),
},
},
},
},
requestBody: { content: { 'application/json': { schema: documentBuilder.schema('user') } } }
};
// Attach our middleware
router.post(
'/user',
PathMiddleware.path('createUser', { operationObject: createUserOperation }),
(req: Request, res: Response): void => {
const save = req.body;
res.json(save);
},
);
// ** As an alternative to passing the full operation object **
// ** there are some builder classes provided, with more planned **
// Setup re-usable defaults for our ResponseBuilder object,
// useful if your application sends mostly json
ResponseBuilder.defaults({ mimeType: 'application/json' });
// Build our open api operation object for this route, using the builder method
const getUserOperation: OpenAPIV3.OperationObject = OperationBuilder.new({
'200': ResponseBuilder.new('Get user by id')
.schema(documentBuilder.schema('user') as OpenAPIV3.ReferenceObject)
.build(),
})
.operationId('getUsers')
.tags(['users'])
.build();
// Attach our operation object to the route with the path middleware
router.get(
'/user/:id',
PathMiddleware.path('getUser', { operationObject: getUserOperation }),
(req: Request, res: Response) => {
res.json({ id: '1', name: 'John Smith' });
},
);
// Generates our full open api document
documentBuilder.generatePathsObject(app);
// The final document can be retrieved with the .build() method. . A new deep copy is created each time.
console.log(documentBuilder.build());
Output
const exampleOutputSchema = {
openapi: '3.0.1',
info: { title: 'An example document', version: '1' },
paths: {
'/api/v1/user': {
post: {
operationId: 'createUser',
tags: ['users'],
requestBody: {
content: {
'application/json': {
schema: { $ref: '#/components/schemas/user' },
},
},
},
responses: {
'200': {
description: 'Create a User',
content: {
'application/json': { schema: { $ref: '#/components/schemas/user' } },
},
},
},
},
},
'/api/v1/user/{id}': {
get: {
responses: {
'200': {
description: 'Get user by id',
content: {
'application/json': { schema: { $ref: '#/components/schemas/user' } },
},
},
},
parameters: [{
in: 'path',
name: 'id',
required: true,
schema: {
type: 'string',
},
}],
operationId: 'getUser',
tags: ['users'],
},
},
},
components: {
schemas: {
user: {
title: 'A user object',
type: 'object',
properties: { id: { type: 'integer' }, name: { type: 'string' } },
},
},
},
};
This is a incomplete code snippet, with just the changes needed from the prior example to work.
// ... prior imports here
import Ajv from 'ajv';
import addFormats from 'ajv-formats'
// .... previous example here .... ///
documentBuilder.generatePathsObject(app); // generate open api doc
const ajv = new Ajv({ coerceTypes: true }) // choose any Ajv options
// For example, included coerceTypes: true and it will convert the path params, headers, query and body into the correct types.
addFormats(ajv); // Apply any desired ajv plugins
// Build and provide the document and ajv client to the validation middlewares
PathMiddleware.initializeValidation(documentBuilder.build(), ajv);
Both DocumentBuilder and PathMiddleware use singleton patterns. This allows you to initialize the underlying objects and then import the classes in other modules directly from express-openapi-generator package. This allows the required state to be maintained throughout the project.
These packages may integrate well into this eco-system/philosophy of documentation/validation generated from code. This package has no direct affiliation with any of these packages.
See the TS Docs
Inspired by @wesleytodd/express-openapi. This project seeks to use the same philosophy of documentation from code, but provide a less opinionated interface, improved features and support more complex Express app router structures.
FAQs
An Express plugin that can parse an app and generate a OpenApiv3 document.
The npm package express-openapi-generator receives a total of 152 weekly downloads. As such, express-openapi-generator popularity was classified as not popular.
We found that express-openapi-generator demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The EU Cyber Resilience Act is prompting compliance requests that open source maintainers may not be obligated or equipped to handle.
Security News
Crates.io adds Trusted Publishing support, enabling secure GitHub Actions-based crate releases without long-lived API tokens.
Research
/Security News
Undocumented protestware found in 28 npm packages disrupts UI for Russian-language users visiting Russian and Belarusian domains.