Skip to main content
Version: 4.0.0

OpenAPI integration

Preface

The Mocks Server main distribution includes the openapi plugin preinstalled. It enables to automatically create Mocks Server routes and collections from OpenAPI documents.

module.exports = [
{
basePath: "/api", // basePath to add to the url of every created route
document: { // OpenAPI document
$ref: "../fixtures/openapi.json"
}
}
];

How does it work

OpenAPI versions 3.0 and 3.1 are supported.

Routes and variants are created using the response examples found in the OpenAPI document's paths property, or using status codes when the response has no content. Basically, it creates a different route variant from:

  • Each different example found on each paths[path][method].responses[code].content[media-type].examples[example-id] property.
  • Each different status code without content found on each paths[path][method].responses[code] property.

Collections are created using the first variant found on each OpenAPI route. They can also extend from other collections.

info

Read the OpenAPI conversion section for further info about the required OpenAPI structure for creating routes.

Usage

The plugin can be used to create routes in two different ways:

  • Usage through files. It searches for files in the /mocks/openapi folder and it automatically converts the exported plugin's OpenAPI definitions into routes and loads them.
  • Programmatic usage. It provides JavaScript functions to create routes and collections from OpenAPI definitions. The returned routes and collections should be loaded manually. The function could be used to export routes in a file in the mocks/routes folder, or to load routes programmatically, for example.
tip

OpenAPI conversion supports JSON refs, so, routes can be created from complete or partial OpenAPI documents hosted on remote servers, defined in separated JSON files, etc. Check out the Recipes section for examples.

OpenAPI definitions

Each OpenAPI document from which to generate routes has to be provided using an object with next properties:

  • basePath (String): Path to be added to the url of every route created from the OpenAPI document.
  • document (Object): OpenAPI document. Read OpenAPI conversion for further details.
  • collection (Object): Optional. Allows to create a collection with the first variant of each route generated from the OpenAPI document. When not provided, no collection will be created for this particular document routes (but the routes will still be added to the plugin's default collection).
    • id (String): ID for the collection.
    • from (String): Collection ID from which the collection will extend.
  • refs (Object): Optional. Options for resolving possible $refs in the OpenAPI document. The json-refs library is used behind the scenes to resolve refs, so any of its options is supported here.
    • location (String): The location of the document being processed. It will be used to locate relative references found within the document being resolved. If this value is relative, it will be calculated from process.cwd().
    • subDocPath (String): The JSON Pointer or array of path segments to the sub document location to search from.
    • ...any other json-refs option.

Usage through files

The plugin automatically searches for files in the /mocks/openapi folder. Each file must export an array of OpenAPI definitions, or a function exporting an array of OpenAPI definitions.

info

The plugin can be used to create routes from multiple OpenAPI documents. So, it expects an array of OpenAPI definitions in every file. You can export multiple OpenAPI definitions in one or multiple files. Check out Recipes for examples.

project-root/
├── mocks/
│ ├── openapi/ <- DEFINE OPENAPIS HERE
│ │ └── definitions.js
│ └── collections.js
└── mocks.config.js
tip

The plugin takes advantage of the files loaders API provided by Mocks Server. So, OpenAPI definitions files can also be defined using JSON, Yaml, JavaScript, TypeScript, etc. And any custom Babel configuration will be also applied to these files. Read the organizing files guide for further info.

Examples

module.exports = [
{
basePath: "/testing-api", // basePath to add to the url of every created route
collection: {
id: "testing-api", // Id for the collection generated with all routes created from the OpenAPI document
from: "base" // Id of the collection to extend from
},
document: { // OpenAPI document
openapi: "3.1.0",
info: {
version: "1.0.0",
title: "Testing API",
description: "OpenAPI document to create routes",
},
paths: {
//... OpenAPI document paths
}
}
}
];
tip

OpenAPI conversion supports JSON refs, so, routes can be created from complete or partial OpenAPI documents hosted on remote servers, defined in separated JSON files, etc. Check out the Recipes section for examples.

Configuring refs

When OpenAPI definitions are exported from files in the /mocks/openapi folder, relative refs in the OpenAPI document by default will be resolved from the file path. This default value can be changed using the refs.location option.

module.exports = [
{
basePath: "/testing-api",
document: {
$ref: "../documents/openapi.json"
}
}
];

OpenAPI conversion

Routes

Routes are created using the paths and methods found in the document paths property. It creates a different route from:

  • Each different path and method found on each paths[path][method] property.

Route ID

The route ID is assigned following the next criteria, from higher to lower priority:

  • The value of the x-mocks-server-route-id property in the path method, when defined.
  • The value of the operationId property in the path method, when defined.
  • A combination of the method and path ([method]-[path]), applying next replacements:
    • Path separators (/) are replaced by -
    • Path templates characters are removed ({ or })
Example
{
"openapi": "3.1.0",
"info": {
"title": "Foo API",
//...
},
"paths": {
"/users": {
// ROUTE "getUsers"
"get": {
"x-mocks-server-route-id": "getUsers"
//...
},
// ROUTE "createUser"
"post": {
"operationId": "createUser"
//...
}
},
"/users/{id}": {
// ROUTE "get-users-id"
"get": {
//...
}
}
}
}

Variants

Variants of each route are created using the examples found on each different response code content media type. It creates a different variant from:

  • Each different example found on each paths[path][method].responses[code].content[media-type].examples[example-id] property.
  • Each different status code without content found on each paths[path][method].responses[code] property.

Variant type

The created variants will have different types depending on the method responses properties:

  • json when the response code content media type contains application/json. The example value must be an object, otherwise the route won't pass the validation.
  • text when the response code content media type contains text/. The example value must be a string, otherwise the route won't pass the validation.
  • status when the the response code does not have a content property

Variant ID

The variant ID is assigned following the next criteria, from higher to lower priority:

  • The value of the x-mocks-server-variant-id property in the example, when defined.
  • A combination of the code, variant type and example id ([code]-[variant type]-[example id]) when the response code has content
  • A combination of the code and variant type ([code]-[variant type]) when the response code has no content
Example
{
"openapi": "3.1.0",
"info": {
"title": "Foo API",
//...
},
"paths": {
"/users": {
// ROUTE "get-users"
"get": {
"responses": {
"200": {
"content": {
"application/json": {
"examples": {
// VARIANT "all-users-json"
"all-users": {
"x-mocks-server-variant-id": "all-users-json",
"value": [
{
"name": "John Doe"
},
{
"name": "Jane Doe"
}
]
},
// VARIANT "200-json-no-users"
"no-users": {
"value": []
}
}
},
"text/plain": {
"examples": {
// VARIANT "200-text-all-users"
"all-users": {
"value": "John Doe, Jane Doe"
},
// VARIANT "200-text-no-users"
"no-users": {
"value": ""
}
}
}
}
}
}
},
// ROUTE "post-users"
"post": {
"responses": {
// VARIANT "200-status"
"200": {
//...
}
}
}
}
}
}

Variant headers

All headers defined in the OpenAPI headers response code will be added to all of the variants created for that response status code.

Example
{
"openapi": "3.1.0",
"info": {
"title": "Foo API",
//...
},
"paths": {
"/users": {
// ROUTE "get-users"
"get": {
"responses": {
"200": {
"headers": {
"foo-header-1": "foo-value-1",
"foo-header-2": "foo-value-2"
},
"content": {
"application/json": {
"examples": {
// VARIANT "200-json-all-users" will have headers "foo-header-1" and "foo-header-2"
"all-users": {
//...
},
// VARIANT "200-json-no-users" will have headers "foo-header-1" and "foo-header-2"
"no-users": {
//...
}
}
},
"text/plain": {
"examples": {
// VARIANT "200-text-all-users" will have headers "foo-header-1" and "foo-header-2"
"all-users": {
//...
},
// VARIANT "200-text-no-users" will have headers "foo-header-1" and "foo-header-2"
"no-users": {
//...
}
}
}
}
}
}
}
}
}
}

Document collection

The plugin's OpenAPI definitions collection options allows to automatically create a collection containing all routes generated from each OpenAPI document.

The first variant found on each route will be the selected one when the collection is created, but you can change it afterwards defining custom route variants through any of the available APIs or integration tools.

Example

Two collections will be created in the next example. Each one will contain only the routes in the base collection and the routes from each correspondent OpenAPI document:

module.exports = [
{
basePath: "/api-1",
collection: {
id: "api-1",
from: "base"
},
document: { // OpenAPI document
$ref: "../fixtures/api-1.json"
}
},
{
basePath: "/api-1",
collection: {
id: "api-2",
from: "base"
},
document: { // OpenAPI document
$ref: "../fixtures/api-2.json"
}
}
];

All documents collection

The plugin supports to create routes from multiple OpenAPI documents. A different collection can be created from each different document, but the plugin also allows to create a collection containing all routes from all OpenAPI documents loaded. So, all routes from all OpenAPI documents can be available at the same time in the API mock.

By default, it creates a collection with "openapi" id, containing all routes from all documents, but you can use the plugin options to change the collection name and the collection to extend from. The creation of this default collection can also be disabled setting the plugins.openapi.collection.id option to null.

Example

Only one collection will be created in the next example. It will contain all routes in the "base" collection and in both OpenAPI documents:

module.exports = [
{
basePath: "/api-1",
document: { // OpenAPI document
$ref: "../fixtures/api-1.json"
}
},
{
basePath: "/api-1",
document: { // OpenAPI document
$ref: "../fixtures/api-2.json"
}
}
];

Configuration

Here are described the plugin's options. Take into account that these options only have effect when it is the plugin who loads the OpenAPI definitions in the /mocks/openapi folder. When used programmatically, these options have no effect.

You can use the next Mocks Server configuration properties to change the plugin's options:

  • plugins.openapi.collection.id (String | Null): Id for the collection to be created with all routes from all OpenAPI documents. Default is "openapi". When it is set to null, no collection will be created.
  • plugins.openapi.collection.from (String): When provided, the created collection will extend from this one.

Programmatic usage

The plugin also exports a function allowing to create routes manually from OpenAPI definitions. Created routes should be loaded manually using any of the Mocks Server available methods.

caution

Note that you'll have to create the collections by your own when getting routes programmatically.

API

The plugin exports next methods:

  • openApiRoutes(openAPIdefinition[, options]): (Async Function): Resolves with an array of routes generated from the provided OpenAPI definition. Rejects with error if it is not possible to resolve OpenAPI document refs or there is any other error trying to convert it.
    • openAPIdefinition (Object): OpenAPI definition
    • options (Object): Optional Object containing any of next properties:
      • defaultLocation (String): Set this location as refs.location option in the OpenAPI definition. It is ignored if the OpenAPI definition contains a refs.location property.
      • logger (Object): Mocks Server Logger instance. If received, the function will log details during the conversion process using it.
      • alerts (Object): Mocks Server Alerts instance. If received, the function will create alerts using this object when any error is produced while trying to convert the OpenAPI document instead of throwing an error.
caution

When the OpenAPI document contain relative refs, they will be resolved from the process.cwd() path by default. Use the refs.location option in the OpenAPI definitions, or the defaultLocation option in the methods in order to change it.

Examples

const path = require("path");

const { createServer } = require("@mocks-server/main");
const { openApiRoutes } = require("@mocks-server/plugin-openapi");

const openApiDocument = require("../openapi.json");

const core = createServer();

core.start().then(async () => {
const routes = await openApiRoutes({
basePath: "/foo-api",
document: openApiDocument,
refs: {
// Define next option only if the document contains relative refs
location: path.resolve(__dirname, "..", "openapi.json"),
}
});

// Load routes
const { loadRoutes } = core.mock.createLoaders();
loadRoutes(routes);
});

Recipes

Remote OpenAPI document

Using JSON refs, an OpenAPI document hosted on a remote server can be used to create mock routes. Simply define the document as a ref to the url of the remote document:

module.exports = [
{
basePath: "/openapi", // basePath to add to the url of every created route
document: { // OpenAPI document
$ref: "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/api-with-examples.json"
}
}
];

OpenAPI JSON file document

Using JSON refs, a JSON OpenAPI document located in the file system can be used to create mock routes. Simply define the document as a ref to the path of the document:

module.exports = [
{
basePath: "/openapi", // basePath to add to the url of every created route
document: { // OpenAPI document
$ref: "../fixtures/api-with-examples.json"
}
}
];
caution

When using relative refs, remember to configure properly the location option.

Multiple OpenAPI documents

The plugin allows to create routes from multiple API documents. Each file in the /mocks/openapi folder can export multiple definitions. Using the collection option, you'll be able to have all routes available at the same time, or to switch between one API and another.

The next example:

  • Creates routes from remote OpenAPI document in the /api-1 path, and a collection named api-1 only with that routes.
  • Creates routes from local OpenAPI document in the /api-2 path, and a collection named api-2 only with that routes.
  • Load routes defined "manually" in the routes folder, and a collection named base only with that routes.
  • Configures this plugin to create a collection using routes from all OpenAPI documents, extending from the base collection.
module.exports = [
{
basePath: "/api-2", // basePath to add to the url of every created route
collection: {
id: "api-2",
},
document: { // OpenAPI document
$ref: "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/api-with-examples.json"
}
},
{
basePath: "/api-3", // basePath to add to the url of every created route
collection: {
id: "api-3",
},
document: { // OpenAPI document
$ref: "../documents/openapi.json"
}
}
];

So, there will be 4 collections in the server:

  • base: Only routes defined "manually" are available (/api-1/users)
  • api-2: Only routes created from remote OpenAPI document are available (/api-2/*)
  • api-3: Only routes created from local OpenAPI document are available (/api-3/*)
  • all-routes: All routes are available (/api-1/users, /api-2/*, /api-3/*)