Skip to content
This repository has been archived by the owner on Aug 4, 2023. It is now read-only.

Latest commit

 

History

History
525 lines (402 loc) · 18 KB

API.md

File metadata and controls

525 lines (402 loc) · 18 KB

One of the main reasons behind Swagger Tools initially was to provide an API around validating Swagger documents. One reason for this is that real validation of Swagger documents consists of two parts:

  • Structural validation using the provided (By Swagger) JSON Schema files
  • Semantic validation based on what is correct when it comes to the values in the document that cannot be handled via the structural validation

Seeing that everyone wants/needs this level of validation, why not create an API for everyone to use that handles all of this stuff?

At the time of starting this project, Swagger 2.0 was in its infancy and Swagger 1.2 was, and still is, the latest stable release. With that in mind, Swagger Tools was written initially to support Swagger 1.2 but recently has been updated to support the latest version of Swagger 2.0 as best as possible. As with any project, this project will be updated as upstream Swagger schemas/specifications change.

API

When you import Swagger Tools into your project (require('swagger-tools') for Node.js or SwaggerTools for the browser), an object is returned with the following property/properties:

  • initializeMiddleware: Function used to initialize the Swagger Connect middleware. (During this phase we validate your Swagger document(s)) This function is documented in the middleware documentation. (Node.js only)
  • specs: An object whose keys are the Swagger version (dots are converted to underscores) and the value is a Specification object

As of right now, since only Swagger versions 1.2 and 2.0 are supported, the specs object has the following properties:

  • v1: object (Pointer to the latest 1.x version which is 1.2 right now)
  • v1_2: object Swagger 1.2 support
  • v2: object (Pointer to the latest 2.x version which is 2.0 right now)
  • v2_0: object Swagger 2.0 support

All functions take an error-first callback where if any upstream error occurs not directly related to the API being called, this error will be passed as the first argument. An example of this is if you call Specification#validate and you have a JSON Reference to some path that cannot be resolved or if you call Specification#composeModel and the model or the document it is contained within fails validation.

The second argument, not always required so check the documentation below, will typically be the result of the API being called. So for Specification#validate, the response object would be the validation results. (The reason this is not sent back as the err argument is because validation results are not themselves an error and are the result of a successful API call.) Another example would be Specification#composeModel would return the composed JSON Schema for the model requested.

Specifications

Each version property in the specs object points to a Specification object. The Specification object provides the API that you will use with your Swagger documents to do things like validation.

Metadata Properties

Each Specification object has a few metadata properties that could are useful for both users and developers:

  • docsUrl: string This is a URL to the specification documentation for the corresponding Swagger version
  • primitives: string[] This is an array of primitive types for the corresponding Swagger version (This is typically only useful for tool authors and integrations)
  • schemas: object This is an object whose keys are the schema file name and the value is the JavaScript object representing the JSON Schema the file name corresponds with
  • schemasUrl: string This is a URL to the JSON Schema(s) for the corresponding Swagger version
  • validators: object This is an object whose keys are the schema file name and the value is the [JSON Schema Validator][jjve] for that particular schema file
  • version: This is the human readable name of the Swagger version (Example: 1.2)

Functions

The real API is provided by the functions made available on the Specification object. Due to the differences between Swagger versions 1.2 and 2.0, the functions listed below have different inputs and different outputs. These will be noted below.

#composeModel(aDOrSO, modelIdOrPtr, callback)

Arguments

  • aDOrSO: object The API Declaration or the Swagger Object (For Swagger 1.2, this should be the API Declaration object that defines the model. For Swagger 2.0, this is the Swagger object itself.)
  • modelIdOrRef: string The model id or the model's JSON Reference pointer string (For Swagger 1.2, this is the model id. For Swagger 2.0, this is the JSON Reference pointer string)
  • callback: function The error-first callback to call with the response or any upstream errors not related to invalid arguments

Returns

This function returns an object that represents the JSON Schema for the model id (Swagger 1.2) or the JSON Reference (Swagger 2.0). Here is a full example of this API in action:

Note: For Swagger 1.2, we only perform structural validation prior to composing the model.

Swagger 2.0

var spec = require('swagger-tools').specs.v2; // Using the latest Swagger 2.x specification
var swaggerObject = require('./samples/2.0/petstore.json'); // This assumes you're in the root of the swagger-tools

spec.composeModel(swaggerObject, '#/definitions/Pet', function (err, schema) {
  if (err) {
    throw err;
  }

  console.log(JSON.stringify(schema, null, '  '));
});

Swagger 1.2

var spec = require('swagger-tools').specs.v1; // Using the latest Swagger 1.x specification
var petJson = require('./samples/1.2/pet.json'); // This assumes you're in the root of the swagger-tools

spec.composeModel(petJson, 'Pet', function (err, schema) {
  if (err) {
    throw err;
  }

  console.log(JSON.stringify(schema, null, '  '));
});

These examples would output something like the following:

{
  "title": "Composed #/definitions/Pet",
  "type": "object",
  "properties": {
    "category": {
      "type": "object",
      "properties": {
        "id": {
          "format": "int64",
          "type": "integer"
        },
        "name": {
          "type": "string"
        }
      }
    },
    "id": {
      "description": "unique identifier for the pet",
      "format": "int64",
      "maximum": 100,
      "minimum": 0,
      "type": "integer"
    },
    "name": {
      "type": "string"
    },
    "photoUrls": {
      "items": {
        "type": "string"
      },
      "type": "array"
    },
    "status": {
      "description": "pet status in the store",
      "enum": [
        "available",
        "pending",
        "sold"
      ],
      "type": "string"
    },
    "tags": {
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "type": "array"
    }
  },
  "required": [
    "id",
    "name"
  ]
}

As you can see, this JSON Schema is valid and it is fully resolved so that it is a standalone document.

#convert(resourceListing, apiDeclarations, skipValidation, callback)

Arguments

  • resourceListing: object The Resource Listing
  • apiDeclarations: [object[]] The array of API Declaration objects
  • skipValidation: [boolean=false] Whether or not to skip validation prior to conversion
  • callback: function The error-first callback to call with the response or any upstream errors not related to invalid arguments

Returns

This function returns an object that represents the converted Swagger 2.0 document.

Notes

Does not work with Swagger 2.0

Here is an example:

var resourceListing = require('./samples/1.2/resourceListing.json'); // This assumes you're in the root of the swagger-tools
var apiDeclarations = [
  require('./samples/1.2/pet.json'), // This assumes you're in the root of the swagger-tools
  require('./samples/1.2/store.json'), // This assumes you're in the root of the swagger-tools
  require('./samples/1.2/user.json') // This assumes you're in the root of the swagger-tools
];
var spec = require('swagger-tools').specs.v1; // Using the latest Swagger 1.x specification

try {
  spec.convert(resourceListing, apiDeclarations, function (err, converted) {
    if (err) {
      throw err;
    }

    console.log(JSON.stringify(converted, null, 2));
  });
} catch (err) {
  // Can be thrown if validation fails (Pass skipValidation of true if need be)
  throw err;
}
#resolve(document, ptr, callback)

Arguments

  • document: object The document to resolve or the document containing the reference to resolve
  • ptr: string The JSON Pointer or undefined to return the whole document
  • callback: function The error-first callback to call with the response or any upstream errors not related to invalid arguments

Returns

A fully resolved JSON Schema representation of the document or path within the document, or undefined if the document does not contain a path corresponding to the pointer

Notes

Does not work with Swagger 1.2 since those documents are not valid JSON Schema documents

Here is an example:

Swagger 2.0

var spec = require('swagger-tools').specs.v2; // Using the latest Swagger 2.x specification
var swaggerObject = require('./samples/2.0/petstore.json'); // This assumes you're in the root of the swagger-tools

spec.resolve(swaggerObject, function (err, result) {
  if (err) {
    throw err;
  }

  if (!result) {
    console.log('%s does not correspond with a path in the provided document', ptr);
  } else {
    console.log(JSON.stringify(result));
  }
});

This API could be confused with Specification#composeModel but this API does not work with Swagger 1.x and it can resolve any path within the document, not just models.

#validate(rLOrSO, apiDeclarations, callback)

Arguments

  • rLOrSO: object The Resource Listing or the Swagger Object (For Swagger 1.2, this should be the Resource Listing. For Swagger 2.0, this is the Swagger object itself.)
  • apiDeclarations: [object[]] The array of API Declaration objects (For Swagger 1.2 only)
  • callback: function The error-first callback to call with the response or any upstream errors not related to invalid arguments

Returns

undefined if the Swagger document(s) are valid or an object containing the validation errors and/or warnings. Below is a list of the object keys available on the response when it is not undefined:

  • apiDeclarations: (1.2 only) This is an array, per API Declaration, containing an object each with its own errors and warnings properties that each contain an array of error and warning objects respectively.
  • errors: For 1.2, this is an array of the global errors for the whole API. For 2.0, this is an array of all errors.
  • warnings: For 1.2, this is an array of the global warnings for the whole API. For 2.0, this is an array of all warnings.

Each error object itself has the following properties:

  • code: This is the error/warning code
  • message: This is the human readable message describing the error/warning
  • path: This is an array containing the path to the Swagger document property that failed validation
  • description: The description of the JSON Schema entry (Optional)

The Error object can also have an inner property with a list of nested errors where applicable.

Here is an example error:

{
  code: 'CYCLICAL_MODEL_INHERITANCE',
  message: 'Model has a circular inheritance: Baz -> Bar -> Baz',
  path: ['models', 'Baz', 'subTypes']
}

And here is an example of using the validate function:

Swagger 2.0

var spec = require('swagger-tools').specs.v2; // Using the latest Swagger 2.x specification
var swaggerObject = require('./samples/2.0/petstore.json'); // This assumes you're in the root of the swagger-tools

spec.validate(swaggerObject, function (err, result) {
  if (err) {
    throw err;
  }

  if (typeof result !== 'undefined') {
    if (result.errors.length > 0) {
      console.log('The Swagger document is invalid...');

      console.log('');

      console.log('Errors');
      console.log('------');

      result.errors.forEach(function (err) {
        console.log('#/' + err.path.join('/') + ': ' + err.message);
      });

      console.log('');
    }

    if (result.warnings.length > 0) {
      console.log('Warnings');
      console.log('--------');

      result.warnings.forEach(function (warn) {
        console.log('#/' + warn.path.join('/') + ': ' + warn.message);
      });
    }

    if (result.errors.length > 0) {
      process.exit(1);
    }
  } else {
    console.log('Swagger document is valid');
  }
});

Swagger 1.2

'use strict';

var spec = require('swagger-tools').specs.v1; // Using the latest Swagger 1.x specification
var resourceListing = require('./samples/1.2/resourceListing.json'); // This assumes you're in the root of the swagger-tools
var apiDeclarations = [
  require('./samples/1.2/pet.json'), // This assumes you're in the root of the swagger-tools
  require('./samples/1.2/store.json'), // This assumes you're in the root of the swagger-tools
  require('./samples/1.2/user.json') // This assumes you're in the root of the swagger-tools
];

spec.validate(resourceListing, apiDeclarations, function (err, result) {
  var errorCount = 0;

  if (typeof result !== 'undefined') {
    console.log('The server could not start due to invalid Swagger document...');

    console.log('');

    if (result.errors.length > 0) {
      errorCount += result.errors.length;

      console.log('Errors');
      console.log('------');

      result.errors.forEach(function (err) {
        console.log('#/' + err.path.join('/') + ': ' + err.message);
      });

      console.log('');
    }

    if (result.warnings.length > 0) {
      console.log('Warnings');
      console.log('--------');

      result.warnings.forEach(function (warn) {
        console.log('#/' + warn.path.join('/') + ': ' + warn.message);
      });

      console.log('');
    }

    if (result.apiDeclarations) {
      result.apiDeclarations.forEach(function (adResult, index) {
        var errorHeader = 'API Declaration (' + apiDeclarations[index].resourcePath + ') Errors';
        var warningHeader = 'API (' + apiDeclarations[index].resourcePath + ') Warnings';

        if (adResult.errors.length > 0) {
          errorCount += adResult.errors.length;

          console.log(errorHeader);
          console.log(new Array(errorHeader.length + 1).join('-'));

          adResult.errors.forEach(function (err) {
            console.log('#/' + err.path.join('/') + ': ' + err.message);
          });

          console.log('');
        }

        if (adResult.warnings.length > 0) {
          console.log(warningHeader);
          console.log(new Array(warningHeader.length + 1).join('-'));

          adResult.warnings.forEach(function (warn) {
            console.log('#/' + warn.path.join('/') + ': ' + warn.message);
          });

          console.log('');
        }
      });
    }

    if (errorCount > 0) {
      process.exit(1);
    }
  } else {
    console.log('Swagger document is valid');
  }
});
#validateModel(aDOrSO, modelIdOrRef, data, callback)

Arguments

  • aDOrSO: object The API Declaration or the Swagger Object (For Swagger 1.2, this should be the API Declaration object that defines the model. For Swagger 2.0, this is the Swagger object itself.)
  • modelIdOrRef: string The model id or the model's JSON Reference pointer string (For Swagger 1.2, this is the model id. For Swagger 2.0, this is the JSON Reference pointer string)
  • data: object|array The object representing the model to be validated
  • callback: function The error-first callback to call with the response or any upstream errors not related to invalid arguments

Returns

undefined if the Swagger document(s) are valid or an object containing the validation errors. The error object is structured identically to that of the #validate method.

Note: For Swagger 1.2, we only perform structural validation prior to composing the model.

Here is a full example of this API in action:

Swagger 2.0

var spec = require('swagger-tools').specs.v2; // Using the latest Swagger 2.x specification
var swaggerObject = require('./samples/2.0/petstore.json'); // This assumes you're in the root of the swagger-tools

spec.validateModel(swaggerObject, '#/definitions/Pet', {
  id: 1,
  name: 'Some Pet Name'
}, function (err, result) {
  if (result) {
    console.log('Swagger model failed validation:');

    console.log('Errors');
    console.log('------');

    result.errors.forEach(function (err) {
      console.log('#/' + err.path.join('/') + ': ' + err.message);
    });

    // Since this is schema validation, warnings shouldn't be populated
  } else {
    console.log('Swagger model is valid');
  }
});

Swagger 1.2

var spec = require('swagger-tools').specs.v1; // Using the latest Swagger 1.x specification
var petJson = require('./samples/1.2/pet.json'); // This assumes you're in the root of the swagger-tools

spec.validateModel(petJson, 'Pet', {
  id: 1,
  name: 'Some Pet Name'
}, function (err, result) {
  if (result) {
    console.log('Swagger model failed validation:');

    console.log('Errors');
    console.log('------');

    result.errors.forEach(function (err) {
      console.log('#/' + err.path.join('/') + ': ' + err.message);
    });

    // Since this is schema validation, warnings shouldn't be populated
  } else {
    console.log('Swagger model is valid');
  }
});