Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V3 spec checks #198

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"--nolazy"
],
"env": {
"NODE_ENV": "development"
"NODE_ENV": "development",
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
},
"console": "internalConsole",
"sourceMaps": false,
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ Features
- Tested on **[over 1,500 real-world APIs](https://apis.guru/browse-apis/)** from Google, Microsoft, Facebook, Spotify, etc.
- Supports [circular references](https://apitools.dev/swagger-parser/docs/#circular-refs), nested references, back-references, and cross-references
- Maintains object reference equality — `$ref` pointers to the same value always resolve to the same object instance

- Checks for inconsistencies in Swagger v2.0 and OpenAPI v3.0 specs:
- path parameter mis-matches
- required field mis-matches
- arrays without item definition


Related Projects
Expand Down
7 changes: 6 additions & 1 deletion lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,10 @@ declare class SwaggerParser {

// eslint-disable-next-line no-redeclare
declare namespace SwaggerParser {

/* eslint-disable @typescript-eslint/no-explicit-any */
export type ApiCallback = (err: Error | null, api?: OpenAPI.Document) => any;
export type $RefsCallback = (err: Error | null, $refs?: $Refs) => any;
/* eslint-enable */

/**
* See https://apitools.dev/swagger-parser/docs/options.html
Expand Down Expand Up @@ -323,6 +324,7 @@ declare namespace SwaggerParser {
*/
read(
file: FileInfo,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
callback?: (error: Error | null, data: string | null) => any
): string | Buffer | Promise<string | Buffer>;
}
Expand Down Expand Up @@ -407,6 +409,7 @@ declare namespace SwaggerParser {
*
* @param types (optional) Optionally only return values from certain locations ("file", "http", etc.)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public values(...types: string[]): { [url: string]: any }

/**
Expand All @@ -425,6 +428,7 @@ declare namespace SwaggerParser {
*
* @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public get($ref: string): any

/**
Expand All @@ -433,6 +437,7 @@ declare namespace SwaggerParser {
* @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash
* @param value The value to assign. Can be anything (object, string, number, etc.)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public set($ref: string, value: any): void
}

Expand Down
18 changes: 7 additions & 11 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const validateSchema = require("./validators/schema");
const validateSpec = require("./validators/spec");
const normalizeArgs = require("@apidevtools/json-schema-ref-parser/lib/normalize-args");
const util = require("./util");
const Options = require("./options");
const ParserOptions = require("./options");
const maybe = require("call-me-maybe");
const { ono } = require("@jsdevtools/ono");
const $RefParser = require("@apidevtools/json-schema-ref-parser");
Expand Down Expand Up @@ -54,7 +54,7 @@ Object.defineProperty(SwaggerParser.prototype, "api", {
*/
SwaggerParser.prototype.parse = async function (path, api, options, callback) {
let args = normalizeArgs(arguments);
args.options = new Options(args.options);
args.options = new ParserOptions(args.options);

try {
let schema = await $RefParser.prototype.parse.call(this, args.path, args.schema, args.options);
Expand Down Expand Up @@ -150,7 +150,7 @@ SwaggerParser.validate = function (path, api, options, callback) {
SwaggerParser.prototype.validate = async function (path, api, options, callback) {
let me = this;
let args = normalizeArgs(arguments);
args.options = new Options(args.options);
args.options = new ParserOptions(args.options);

// ZSchema doesn't support circular objects, so don't dereference circular $refs yet
// (see https://github.com/zaggino/z-schema/issues/137)
Expand Down Expand Up @@ -182,8 +182,8 @@ SwaggerParser.prototype.validate = async function (path, api, options, callback)
}

if (args.options.validate.spec) {
// Validate the API against the Swagger spec
validateSpec(me.api);
// Validate the API against the Swagger spec; hand in $refs.circular meta-data from the SwaggerParser
validateSpec(me.api, me.$refs.circular);
}

return maybe(args.callback, Promise.resolve(me.schema));
Expand All @@ -193,9 +193,5 @@ SwaggerParser.prototype.validate = async function (path, api, options, callback)
}
};

/**
* The Swagger object
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object
*
* @typedef {{swagger: string, info: {}, paths: {}}} SwaggerObject
*/
// Only the one export; don't try to export the @typedef of SwaggerOrOpenAPIObject
module.exports = SwaggerParser;
19 changes: 15 additions & 4 deletions lib/validators/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,23 @@ const AjvDraft4 = require("ajv-draft-04");
const Ajv = require("ajv/dist/2020");
const { openapi } = require("@apidevtools/openapi-schemas");

/**
* The Swagger v2.0 or OpenAPI v3.0.x object - it could be either (but not both)
*
* cf.
* - https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object
* - https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.2.md#oasObject
*
* @typedef {{swagger: string, info: {}, paths: {},
* openapi:string, }} SwaggerOrOpenAPIObject
*/

module.exports = validateSchema;

/**
* Validates the given Swagger API against the Swagger 2.0 or OpenAPI 3.0 and 3.1 schemas.
*
* @param {SwaggerObject} api
* @param {SwaggerOrOpenAPIObject} api Either a Swagger or OpenAPI object - determined by presence of swagger, or openapi fields
*/
function validateSchema (api) {
let ajv;
Expand Down Expand Up @@ -59,8 +70,8 @@ function validateSchema (api) {
/**
* Determines which version of Ajv to load and prepares it for use.
*
* @param {bool} draft04
* @returns {Ajv}
* @param {boolean} draft04 Are we initialising for JsonSchemaDraft04?
* @returns {Ajv} The initialized Ajv environment
*/
function initializeAjv (draft04 = true) {
const opts = {
Expand All @@ -81,7 +92,7 @@ function initializeAjv (draft04 = true) {
*
* @param {object[]} errors - The Ajv errors
* @param {string} [indent] - The whitespace used to indent the error message
* @returns {string}
* @returns {string} - Formatted error message string
*/
function formatAjvError (errors, indent) {
indent = indent || " ";
Expand Down
Loading