A Node.js library for integrating OpenAPI specifications into an application. With @superhero/oas, you can define, validate, and route API operations using OpenAPI's structured standard.
OBS! This is an early release of this component.
- Builds API routes from OpenAPI specifications.
- Validate request parameters, bodies, and responses using OpenAPI schemas.
- Supports OpenAPI components for modular and reusable specifications.
- Middlewares for handling parameters, request bodies, and responses.
Install via npm:
npm install @superhero/oas
For detailed information about how to define an OpenAPI Specification, refer to the OpenAPI Specification Documentation.
Set up and bootstrap the @superhero/oas
library with your specification:
import HttpServer from '@superhero/http-server';
import Locator from '@superhero/locator';
import OAS from '@superhero/oas';
import Router from '@superhero/router';
// Instantiate the service locator
const locator = new Locator();
// Instantiate the router
const router = new Router(locator);
// Instantiate the server
const server = new HttpServer(router);
// Instantiate the OAS instance
const oas = new OAS(router)
// Register the route dispatcher service
locator.set('hello-dispatcher', {
dispatch: (request, session) => {
session.view.body.message = 'Hello, World!';
},
});
// Bootstrap and start the server
await server.bootstrap();
await server.listen(3000);
// Routes
const specification = {
paths: {
'/example': {
get: {
operationId: 'hello-dispatcher',
responses: { 200: { description: 'Hello World' } },
},
},
},
};
oas.bootstrap(specification)
The library automatically adds middleware for validating request parameters, request bodies, and responses as defined in the specification.
For example:
const specification = {
paths: {
'/example': {
post: {
operationId: 'example',
requestBody: {
required: true,
content: {
'application/json': {
schema: {
type: 'object',
properties: {
name: { type: 'string', minLength: 1 },
age: { type: 'integer', minimum: 0 },
},
required: ['name'],
},
},
},
},
responses: {
201: { description: 'Created' },
400: { description: 'Validation Error' },
},
},
},
},
};
oas.bootstrap(specification);
This will ensure:
- Request parameters are validated.
- Request bodies are checked against the defined schema.
- Responses are validated according to the specification.
- A dispatcher called
example
will dispatch the request.
Map the operationId
from your specification to a dispatcher:
locate.set('example-reader', {
dispatch: (request, session) => {
session.view.body = { message: `Fetched data for ID: ${request.param.id}` };
},
});
locate.set('example-writer', {
dispatch: (request, session) => {
session.view.body = { message: `Created data for ${request.body.name}` };
},
});
The library throws descriptive errors (will be improved on in comming versions) for invalid specifications or operations.
The test suite uses Node.js's built-in testing module.
To run the tests, execute:
npm test
▶ @superhero/oas/schemas
▶ Supported attributes
▶ type:boolean
✔ nullable enum (3.35678ms)
✔ throws if invalid enum type (0.300923ms)
✔ casts strings that can be interpreted as a boolean value to boolean (0.325861ms)
✔ throws if invalid (0.270627ms)
✔ type:boolean (6.104481ms)
▶ type:integer
✔ nullable enum (0.455196ms)
✔ minimum (0.190364ms)
✔ maximum (0.276653ms)
✔ exclusiveMinimum (0.311391ms)
✔ exclusiveMaximum (0.678551ms)
✔ multipleOf (0.457454ms)
✔ format int32 (0.319436ms)
✔ format int64 (0.357137ms)
✔ throws if invalid format (0.152509ms)
✔ throws if invalid enum type (0.134188ms)
✔ throws if a decimal (0.217675ms)
✔ type:integer (5.643484ms)
▶ type:number
✔ nullable enum (0.549315ms)
✔ format float (0.21403ms)
✔ format double (0.186924ms)
✔ throws if invalid enum type (0.221865ms)
✔ casts strings that can be interpreted as a number value to number (0.107354ms)
✔ type:number (2.023555ms)
▶ type:string
✔ nullable enum (1.457643ms)
✔ minLength (0.20732ms)
✔ maxLength (0.154873ms)
✔ pattern (0.303383ms)
✔ format date (1.632527ms)
✔ format time (0.389043ms)
✔ format datetime (0.413008ms)
✔ format base64 (0.432533ms)
✔ format email (0.23688ms)
✔ format ipv4 (1.006419ms)
✔ format ipv6 (6.590692ms)
✔ url (0.494795ms)
✔ format uuid (0.340933ms)
✔ throws if invalid enum type (0.139166ms)
✔ type:string (15.599415ms)
▶ type:null
✔ throws if not null (0.296927ms)
✔ throws if value is null and type is not null (0.210403ms)
✔ type:null (0.874171ms)
✔ type:undefined (0.140063ms)
▶ type:array
✔ throws if invalid type (0.359969ms)
✔ items (1.020706ms)
✔ additionalItems (0.21037ms)
✔ minItems (0.248753ms)
✔ maxItems (0.329635ms)
✔ uniqueItems (0.890805ms)
✔ enum (0.259908ms)
✔ throws if invalid enum type (0.304887ms)
✔ nullable enum (0.764214ms)
✔ nullable items (0.265034ms)
✔ nullable enum items (0.169632ms)
✔ type:array (6.446302ms)
▶ type:object
✔ throws if invalid type (0.282162ms)
✔ additionalProperties (0.33254ms)
✔ minProperties (0.22744ms)
✔ maxProperties (0.203384ms)
✔ propertyNames pattern (0.313919ms)
✔ nullable (0.111406ms)
✔ enum (0.243711ms)
✔ nullable enum (0.304399ms)
✔ throws if invalid enum type (0.132201ms)
✔ type:object (3.92496ms)
✔ type:invalid throws (0.146378ms)
▶ readOnly
✔ when is reading (0.130151ms)
✔ when is writing (0.166433ms)
✔ readOnly (0.514571ms)
▶ writeOnly
✔ when is reading (0.19847ms)
✔ when is writing (0.111985ms)
✔ writeOnly (0.519254ms)
▶ default
✔ when no value (0.122471ms)
✔ when value (0.109269ms)
✔ default (0.423953ms)
▶ if/then/else
✔ then (0.116916ms)
✔ else (0.202285ms)
✔ throws if invalid (0.391854ms)
✔ if/then/else (1.17015ms)
✔ not (0.250797ms)
▶ allOf
✔ result only what is expected (0.181802ms)
✔ throws if all are not valid (0.168471ms)
✔ allOf (1.106621ms)
▶ anyOf
✔ conforms to valid schema (0.147225ms)
✔ throws if none is valid (0.170714ms)
✔ anyOf (0.547187ms)
▶ oneOf
✔ conforms to valid schema (0.157463ms)
✔ throws if none is valid (0.12812ms)
✔ throws if more than one is valid (0.129512ms)
✔ oneOf (0.726333ms)
✔ const (0.305981ms)
✔ deep const (1.424227ms)
✔ throws on invalid $ref (0.605318ms)
✔ throws on invalid schema (0.147341ms)
✔ Supported attributes (49.751109ms)
✔ @superhero/oas/schemas (50.297111ms)
▶ @superhero/oas
✔ Can set a simple specification (79.360931ms)
✔ Can add middleware for requestBody content (10.793273ms)
✔ Can add middleware for parameters (8.350745ms)
▶ Specification with reference to components
✔ GET method using default parameter (31.754399ms)
✔ GET method not using required parameter (6.148027ms)
✔ GET method using path parameter (5.035696ms)
✔ GET method using query parameter (5.464326ms)
✔ GET method using header parameter (4.530933ms)
✔ POST method using request body (4.042791ms)
✔ Specification with reference to components (72.699754ms)
✔ Throws error for invalid paths type in specification (8.362196ms)
✔ Throws error for missing response (4.73213ms)
✔ Throws error for missing operationId in operation (7.265388ms)
✔ Throws error for missing responses in operation (7.791663ms)
✔ Throws error for missing response code (7.583666ms)
✔ Throws error for unsupported content type in requestBody (7.55338ms)
✔ Throws error for invalid parameters type (5.039937ms)
✔ @superhero/oas (222.477838ms)
tests 110
suites 3
pass 110
-----------------------------------------------------------------------------------------------------
file | line % | branch % | funcs % | uncovered lines
-----------------------------------------------------------------------------------------------------
components | | | |
abstraction.js | 76.10 | 72.00 | 100.00 | 42-48 63-68 71-76 89-93 100-104 111-115 140-143
headers.js | 69.14 | 64.29 | 66.67 | 30-33 37-38 43-46 53-54 63-66 70-75 78-80
parameters.js | 70.43 | 77.78 | 100.00 | 65-69 98-101 128-132 142-164 167-184
request-bodies.js | 78.38 | 65.00 | 100.00 | 50-55 58-61 70-73 90-94 105-109
responses.js | 86.26 | 80.00 | 100.00 | 40-44 67-71 88-91 116-119
schemas.js | 100.00 | 98.00 | 100.00 |
schemas.test.js | 100.00 | 100.00 | 100.00 |
index.js | 93.24 | 86.36 | 100.00 | 112-115 118-123
index.test.js | 100.00 | 100.00 | 96.55 |
middleware | | | |
parameters.js | 90.91 | 88.89 | 100.00 | 39-42
request-bodies.js | 100.00 | 100.00 | 100.00 |
responses.js | 100.00 | 100.00 | 100.00 |
-----------------------------------------------------------------------------------------------------
all files | 94.81 | 94.28 | 99.26 |
-----------------------------------------------------------------------------------------------------
This project is licensed under the MIT License.
Feel free to submit issues or pull requests for improvements or additional features.