Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@seriousme/openapi-schema-validator

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@seriousme/openapi-schema-validator - npm Package Compare versions

Comparing version 2.1.0 to 2.1.1

.github/workflows/npm-publish.yml

12

bin/validate-api-cli.js

@@ -9,14 +9,14 @@ #!/usr/bin/env node

if (!filename) {
console.log(`
console.log(`
usage: ${argv[1]} <file>
where <file> contains a yaml or json openApi specification.
`);
exit(1);
exit(1);
}
validator.validate(filename).then((result) => {
console.log(JSON.stringify(result, null, 2));
if (!result.valid) {
exit(1);
}
console.log(JSON.stringify(result, null, "\t"));
if (!result.valid) {
exit(1);
}
});

@@ -6,2 +6,11 @@ # Changelog

## [v2.1.1] 13-09-2023
### Changed
- chore: added Biome for formatting and linting
- chore: removed tap
- chore: removed node-fetch
- Updated dependencies
- ajv ^8.11.0 → ^8.12.0
- c8 ^7.12.0 → ^8.0.1
## [v2.1.0] 14-10-2022

@@ -8,0 +17,0 @@ ### Changed

@@ -1,14 +0,14 @@

import {Options, ErrorObject} from "ajv"
import { ErrorObject, Options } from "ajv";
export class Validator {
static supportedVersions: Set<string>;
constructor(ajvOptions?: Options);
resolveRefs(opts?: {
specification?: object
}): object;
validate(schema: object | string): Promise<{
valid: boolean;
errors?: ErrorObject[];
}>;
specification: object;
version: string;
static supportedVersions: Set<string>;
constructor(ajvOptions?: Options);
resolveRefs(opts?: {
specification?: object;
}): object;
validate(schema: object | string): Promise<{
valid: boolean;
errors?: ErrorObject[];
}>;
specification: object;
version: string;
}

@@ -1,8 +0,8 @@

import { fileURLToPath, URL } from "url";
import { readFileSync } from "fs";
import { URL, fileURLToPath } from "url";
import Ajv04 from "ajv-draft-04";
import addFormats from "ajv-formats";
import Ajv2020 from "ajv/dist/2020.js";
import addFormats from "ajv-formats";
import { readFile } from "fs/promises";
import { JSON_SCHEMA, load } from "js-yaml";
import { readFileSync } from "fs";
import { readFile } from "fs/promises";
import { resolve } from "./resolve.js";

@@ -12,4 +12,4 @@

const ajvVersions = {
"http://json-schema.org/draft-04/schema#": Ajv04,
"https://json-schema.org/draft/2020-12/schema": Ajv2020,
"http://json-schema.org/draft-04/schema#": Ajv04,
"https://json-schema.org/draft/2020-12/schema": Ajv2020,
};

@@ -19,123 +19,130 @@ const inlinedRefs = "x-inlined-refs";

function localFile(fileName) {
return fileURLToPath(new URL(fileName, import.meta.url));
return fileURLToPath(new URL(fileName, import.meta.url));
}
function importJSON(file) {
return JSON.parse(readFileSync(localFile(file)));
return JSON.parse(readFileSync(localFile(file)));
}
function getOpenApiVersion(specification) {
for (const version of openApiVersions) {
const prop = specification[version == "2.0" ? "swagger" : "openapi"];
if (typeof prop === "string" && prop.startsWith(version)) {
return version;
}
}
return undefined;
for (const version of openApiVersions) {
const specificationType = version === "2.0" ? "swagger" : "openapi";
const prop = specification[specificationType];
if (typeof prop === "string" && prop.startsWith(version)) {
return {
version,
specificationType,
specificationVersion: prop,
};
}
}
return {
version: undefined,
specificationType: undefined,
specificationVersion: undefined,
};
}
async function getSpecFromData(data) {
const yamlOpts = { schema: JSON_SCHEMA };
if (typeof data === "object") {
return data;
}
if (typeof data === "string") {
if (data.match(/\n/)) {
try {
return load(data, yamlOpts);
} catch (_) {
return undefined;
}
}
try {
const fileData = await readFile(data, "utf-8");
return load(fileData, yamlOpts);
} catch (_) {
return undefined;
}
}
return undefined;
const yamlOpts = { schema: JSON_SCHEMA };
if (typeof data === "object") {
return data;
}
if (typeof data === "string") {
if (data.match(/\n/)) {
try {
return load(data, yamlOpts);
} catch (_) {
return undefined;
}
}
try {
const fileData = await readFile(data, "utf-8");
return load(fileData, yamlOpts);
} catch (_) {
return undefined;
}
}
return undefined;
}
export class Validator {
constructor(ajvOptions = {}) {
// AJV is a bit too strict in its strict validation of openAPI schemas
// so switch strict mode and validateFormats off
if (ajvOptions.strict !== "log") {
ajvOptions.strict = false;
}
this.ajvOptions = ajvOptions;
this.ajvValidators = {};
this.externalRefs = {};
return this;
}
constructor(ajvOptions = {}) {
// AJV is a bit too strict in its strict validation of openAPI schemas
// so switch strict mode and validateFormats off
if (ajvOptions.strict !== "log") {
ajvOptions.strict = false;
}
this.ajvOptions = ajvOptions;
this.ajvValidators = {};
this.externalRefs = {};
}
static supportedVersions = openApiVersions;
static supportedVersions = openApiVersions;
resolveRefs(opts = {}) {
return resolve(this.specification || opts.specification);
}
resolveRefs(opts = {}) {
return resolve(this.specification || opts.specification);
}
async addSpecRef(data, uri) {
const spec = await getSpecFromData(data);
if (spec === undefined) {
throw new Error("Cannot find JSON, YAML or filename in data");
}
if (uri === undefined) {
if (spec['$id'] === undefined) {
throw new Error("uri parameter or $id attribute must be present");
}
uri = spec['$id'];
}
async addSpecRef(data, uri) {
const spec = await getSpecFromData(data);
if (spec === undefined) {
throw new Error("Cannot find JSON, YAML or filename in data");
}
if (typeof uri !== "string") {
throw new Error("uri parameter or $id attribute must be a string");
}
spec["$id"] = uri;
this.externalRefs[uri] = spec;
}
const newUri = uri || spec["$id"];
if (typeof newUri !== "string") {
throw new Error("uri parameter or $id attribute must be a string");
}
async validate(data) {
const specification = await getSpecFromData(data);
this.specification = specification;
if (specification === undefined || specification === null) {
return {
valid: false,
errors: "Cannot find JSON, YAML or filename in data",
};
}
if (Object.keys(this.externalRefs).length > 0) {
specification[inlinedRefs] = this.externalRefs;
}
const version = getOpenApiVersion(specification);
this.version = version;
if (!version) {
return {
valid: false,
errors:
"Cannot find supported swagger/openapi version in specification, version must be a string.",
};
}
const validate = this.getAjvValidator(version);
const result = {
valid: validate(specification),
};
if (validate.errors) {
result.errors = validate.errors;
}
return result;
}
spec["$id"] = newUri;
this.externalRefs[newUri] = spec;
}
getAjvValidator(version) {
if (!this.ajvValidators[version]) {
const schema = importJSON(`./schemas/v${version}/schema.json`);
const schemaVersion = schema.$schema;
const AjvClass = ajvVersions[schemaVersion];
const ajv = new AjvClass(this.ajvOptions);
addFormats(ajv);
ajv.addFormat("media-range", true); // used in 3.1
this.ajvValidators[version] = ajv.compile(schema);
}
return this.ajvValidators[version];
}
}
async validate(data) {
const specification = await getSpecFromData(data);
this.specification = specification;
if (specification === undefined || specification === null) {
return {
valid: false,
errors: "Cannot find JSON, YAML or filename in data",
};
}
if (Object.keys(this.externalRefs).length > 0) {
specification[inlinedRefs] = this.externalRefs;
}
const { version, specificationType, specificationVersion } =
getOpenApiVersion(specification);
this.version = version;
this.specificationVersion = specificationVersion;
this.specificationType = specificationType;
if (!version) {
return {
valid: false,
errors:
"Cannot find supported swagger/openapi version in specification, version must be a string.",
};
}
const validate = this.getAjvValidator(version);
const result = {
valid: validate(specification),
};
if (validate.errors) {
result.errors = validate.errors;
}
return result;
}
getAjvValidator(version) {
if (!this.ajvValidators[version]) {
const schema = importJSON(`./schemas/v${version}/schema.json`);
const schemaVersion = schema.$schema;
const AjvClass = ajvVersions[schemaVersion];
const ajv = new AjvClass(this.ajvOptions);
addFormats(ajv);
ajv.addFormat("media-range", true); // used in 3.1
this.ajvValidators[version] = ajv.compile(schema);
}
return this.ajvValidators[version];
}
}
MIT License
Copyright (c) 2016-2022 Hans Klunder
Copyright (c) 2016-2023 Hans Klunder

@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

{
"name": "@seriousme/openapi-schema-validator",
"version": "2.1.0",
"version": "2.1.1",
"description": "Validate OpenApi specifications against their JSON schema",

@@ -11,3 +11,3 @@ "main": "index.js",

"dependencies": {
"ajv": "^8.11.0",
"ajv": "^8.12.0",
"ajv-draft-04": "^1.0.0",

@@ -18,8 +18,10 @@ "ajv-formats": "^2.1.1",

"scripts": {
"test": "c8 tap test/test-*.js",
"test": "c8 node --test test/test-*.js",
"format": "biome format --write .",
"lint": "biome ci .",
"posttest": "c8 check-coverage --lines 100 --functions 100 --branches 100",
"covtest": "c8 --reporter=lcov npm test",
"cloneOas": "rm -rf OpenAPI-Specification && git clone --branch 'gh-pages' --single-branch https://github.com/OAI/OpenAPI-Specification.git",
"checkOasVersions": "tap --no-coverage test/check-versions.js",
"checkOasVersionsSnapshot": "tap --no-coverage --snapshot test/check-versions.js",
"checkOasVersions": "node test/check-versions.js",
"checkOasVersionsSnapshot": "node test/check-versions.js --updateSnapshot",
"preconvert31": "npm run cloneOas",

@@ -38,5 +40,4 @@ "convert31": "node test/convert-3.1.js ",

"devDependencies": {
"c8": "^7.12.0",
"node-fetch": "^3.2.10",
"tap": "^16.3.0"
"@biomejs/biome": "^1.1.2",
"c8": "^8.0.1"
},

@@ -43,0 +44,0 @@ "directories": {

@@ -5,3 +5,2 @@ # OpenAPI schema validator

[![Coverage Status](https://coveralls.io/repos/github/seriousme/openapi-schema-validator/badge.svg?branch=master)](https://coveralls.io/github/seriousme/openapi-schema-validator?branch=master)
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/seriousme/openapi-schema-validator.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/seriousme/openapi-schema-validator/context:javascript)
[![NPM version](https://img.shields.io/npm/v/@seriousme/openapi-schema-validator.svg)](https://www.npmjs.com/package/seriousme/openapi-schema-validator)

@@ -8,0 +7,0 @@ ![npm](https://img.shields.io/npm/dm/@seriousme/openapi-schema-validator)

function escapeJsonPointer(str) {
return str.replace(/~/g, "~0").replace(/\//g, "~1");
return str.replace(/~/g, "~0").replace(/\//g, "~1");
}
function unescapeJsonPointer(str) {
return str.replace(/~1/g, "/").replace(/~0/g, "~");
return str.replace(/~1/g, "/").replace(/~0/g, "~");
}

@@ -12,134 +12,135 @@

const pointerWords = new Set([
"$ref",
"$id",
"$anchor",
"$dynamicRef",
"$dynamicAnchor",
"$schema",
"$ref",
"$id",
"$anchor",
"$dynamicRef",
"$dynamicAnchor",
"$schema",
]);
function resolveUri(uri, anchors) {
const [prefix, path] = uri.split("#", 2);
const hashPresent = !!path;
const err = new Error(`Can't resolve ${uri}, only internal refs are supported.`);
const [prefix, path] = uri.split("#", 2);
const hashPresent = !!path;
const err = new Error(
`Can't resolve ${uri}, only internal refs are supported.`,
);
if (hashPresent && (path[0] !== '/')) {
if (anchors[uri]) {
return anchors[uri];
}
throw err;
}
if (hashPresent && path[0] !== "/") {
if (anchors[uri]) {
return anchors[uri];
}
throw err;
}
if (!anchors[prefix]) {
throw err;
}
if (!anchors[prefix]) {
throw err;
}
if (!hashPresent) {
return anchors[prefix];
}
if (!hashPresent) {
return anchors[prefix];
}
const paths = path.split("/").slice(1);
try {
const result = paths.reduce(
(o, n) => o[unescapeJsonPointer(n)],
anchors[prefix]
);
if (result === undefined) {
throw "";
}
return result;
} catch (_) {
throw err;
}
const paths = path.split("/").slice(1);
try {
const result = paths.reduce(
(o, n) => o[unescapeJsonPointer(n)],
anchors[prefix],
);
if (result === undefined) {
throw "";
}
return result;
} catch (_) {
throw err;
}
}
export function resolve(tree) {
if (!isObject(tree)) {
return undefined;
}
let treeObj = tree;
if (!isObject(treeObj)) {
return undefined;
}
const pointers = {};
pointerWords.forEach((word) => (pointers[word] = []));
const pointers = {};
for (const word of pointerWords) {
pointers[word] = [];
}
function applyRef(path, target) {
let root = tree;
const paths = path.split("/").slice(1);
const prop = paths.pop();
paths.forEach(p => root = root[unescapeJsonPointer(p)]);
if (typeof prop !== 'undefined') {
root[unescapeJsonPointer(prop)] = target;
}
else {
tree = target;
}
}
function applyRef(path, target) {
let root = treeObj;
const paths = path.split("/").slice(1);
const prop = paths.pop();
for (const p of paths) {
root = root[unescapeJsonPointer(p)];
}
if (typeof prop !== "undefined") {
root[unescapeJsonPointer(prop)] = target;
} else {
treeObj = target;
}
}
function parse(obj, path, id) {
if (!isObject(obj)) {
return;
}
if (obj.$id) {
id = obj.$id;
}
for (const prop in obj) {
if (pointerWords.has(prop)) {
pointers[prop].push({ ref: obj[prop], obj, prop, path, id });
delete obj[prop];
}
parse(obj[prop], `${path}/${escapeJsonPointer(prop)}`, id);
}
}
// find all refs
parse(tree, "#", "");
function parse(obj, path, id) {
if (!isObject(obj)) {
return;
}
const objId = obj.$id || id;
for (const prop in obj) {
if (pointerWords.has(prop)) {
pointers[prop].push({ ref: obj[prop], obj, prop, path, id: objId });
obj[prop] = undefined;
}
parse(obj[prop], `${path}/${escapeJsonPointer(prop)}`, objId);
}
}
// find all refs
parse(treeObj, "#", "");
// resolve them
const anchors = { "": tree };
const dynamicAnchors = {};
// resolve them
const anchors = { "": treeObj };
const dynamicAnchors = {};
pointers.$id.forEach((item) => {
const { ref, obj, path } = item;
if (anchors[ref]) {
throw new Error(`$id : '${ref}' defined more than once at ${path}`);
}
anchors[ref] = obj;
});
pointers.$id.forEach((item) => {
const { ref, obj, path } = item;
if (anchors[ref]) {
throw new Error(`$id : '${ref}' defined more than once at ${path}`);
}
anchors[ref] = obj;
});
pointers.$anchor.forEach((item) => {
const { ref, obj, path, id } = item;
const fullRef = `${id}#${ref}`;
if (anchors[fullRef]) {
throw new Error(`$anchor : '${ref}' defined more than once at '${path}'`);
}
anchors[fullRef] = obj;
});
pointers.$anchor.forEach((item) => {
const { ref, obj, path, id } = item;
const fullRef = `${id}#${ref}`;
if (anchors[fullRef]) {
throw new Error(`$anchor : '${ref}' defined more than once at '${path}'`);
}
anchors[fullRef] = obj;
});
pointers.$dynamicAnchor.forEach((item) => {
const { ref, obj, path } = item;
if (dynamicAnchors[`#${ref}`]) {
throw new Error(
`$dynamicAnchor : '${ref}' defined more than once at '${path}'`
);
}
dynamicAnchors[`#${ref}`] = obj;
});
pointers.$dynamicAnchor.forEach((item) => {
const { ref, obj, path } = item;
if (dynamicAnchors[`#${ref}`]) {
throw new Error(
`$dynamicAnchor : '${ref}' defined more than once at '${path}'`,
);
}
dynamicAnchors[`#${ref}`] = obj;
});
pointers.$ref.forEach((item) => {
const { ref, id, path } = item;
const decodedRef = decodeURIComponent(ref);
const fullRef = decodedRef[0] !== "#" ? decodedRef : `${id}${decodedRef}`;
applyRef(path, resolveUri(fullRef, anchors));
});
pointers.$ref.forEach((item) => {
const { ref, id, path } = item;
const decodedRef = decodeURIComponent(ref);
const fullRef = decodedRef[0] !== "#" ? decodedRef : `${id}${decodedRef}`;
applyRef(path, resolveUri(fullRef, anchors));
});
pointers.$dynamicRef.forEach((item) => {
const { ref, path } = item;
if (!dynamicAnchors[ref]) {
throw new Error(`Can't resolve $dynamicAnchor : '${ref}'`);
}
applyRef(path, dynamicAnchors[ref]);
});
pointers.$dynamicRef.forEach((item) => {
const { ref, path } = item;
if (!dynamicAnchors[ref]) {
throw new Error(`Can't resolve $dynamicAnchor : '${ref}'`);
}
applyRef(path, dynamicAnchors[ref]);
});
return tree;
}
return treeObj;
}
{
"$id": "https://spec.openapis.org/oas/3.1/schema/2022-10-07",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "The description of OpenAPI v3.1.x documents without schema validation, as defined by https://spec.openapis.org/oas/v3.1.0",
"type": "object",
"properties": {
"openapi": {
"type": "string",
"pattern": "^3\\.1\\.\\d+(-.+)?$"
},
"info": {
"$ref": "#/$defs/info"
},
"jsonSchemaDialect": {
"type": "string",
"format": "uri",
"default": "https://spec.openapis.org/oas/3.1/dialect/base"
},
"servers": {
"type": "array",
"items": {
"$ref": "#/$defs/server"
},
"default": [
{
"url": "/"
}
]
},
"paths": {
"$ref": "#/$defs/paths"
},
"webhooks": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/path-item-or-reference"
}
},
"components": {
"$ref": "#/$defs/components"
},
"security": {
"type": "array",
"items": {
"$ref": "#/$defs/security-requirement"
}
},
"tags": {
"type": "array",
"items": {
"$ref": "#/$defs/tag"
}
},
"externalDocs": {
"$ref": "#/$defs/external-documentation"
}
},
"required": [
"openapi",
"info"
],
"anyOf": [
{
"required": [
"paths"
]
},
{
"required": [
"components"
]
},
{
"required": [
"webhooks"
]
}
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false,
"$defs": {
"info": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#info-object",
"type": "object",
"properties": {
"title": {
"type": "string"
},
"summary": {
"type": "string"
},
"description": {
"type": "string"
},
"termsOfService": {
"type": "string",
"format": "uri"
},
"contact": {
"$ref": "#/$defs/contact"
},
"license": {
"$ref": "#/$defs/license"
},
"version": {
"type": "string"
}
},
"required": [
"title",
"version"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"contact": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#contact-object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"url": {
"type": "string",
"format": "uri"
},
"email": {
"type": "string",
"format": "email"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"license": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#license-object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"identifier": {
"type": "string"
},
"url": {
"type": "string",
"format": "uri"
}
},
"required": [
"name"
],
"dependentSchemas": {
"identifier": {
"not": {
"required": [
"url"
]
}
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"server": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#server-object",
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri-reference"
},
"description": {
"type": "string"
},
"variables": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/server-variable"
}
}
},
"required": [
"url"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"server-variable": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#server-variable-object",
"type": "object",
"properties": {
"enum": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
},
"default": {
"type": "string"
},
"description": {
"type": "string"
}
},
"required": [
"default"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"components": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#components-object",
"type": "object",
"properties": {
"schemas": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/schema"
}
},
"responses": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/response-or-reference"
}
},
"parameters": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/parameter-or-reference"
}
},
"examples": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/example-or-reference"
}
},
"requestBodies": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/request-body-or-reference"
}
},
"headers": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/header-or-reference"
}
},
"securitySchemes": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/security-scheme-or-reference"
}
},
"links": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/link-or-reference"
}
},
"callbacks": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/callbacks-or-reference"
}
},
"pathItems": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/path-item-or-reference"
}
}
},
"patternProperties": {
"^(schemas|responses|parameters|examples|requestBodies|headers|securitySchemes|links|callbacks|pathItems)$": {
"$comment": "Enumerating all of the property names in the regex above is necessary for unevaluatedProperties to work as expected",
"propertyNames": {
"pattern": "^[a-zA-Z0-9._-]+$"
}
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"paths": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#paths-object",
"type": "object",
"patternProperties": {
"^/": {
"$ref": "#/$defs/path-item"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"path-item": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#path-item-object",
"type": "object",
"properties": {
"summary": {
"type": "string"
},
"description": {
"type": "string"
},
"servers": {
"type": "array",
"items": {
"$ref": "#/$defs/server"
}
},
"parameters": {
"type": "array",
"items": {
"$ref": "#/$defs/parameter-or-reference"
}
},
"get": {
"$ref": "#/$defs/operation"
},
"put": {
"$ref": "#/$defs/operation"
},
"post": {
"$ref": "#/$defs/operation"
},
"delete": {
"$ref": "#/$defs/operation"
},
"options": {
"$ref": "#/$defs/operation"
},
"head": {
"$ref": "#/$defs/operation"
},
"patch": {
"$ref": "#/$defs/operation"
},
"trace": {
"$ref": "#/$defs/operation"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"path-item-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/path-item"
}
},
"operation": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#operation-object",
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"summary": {
"type": "string"
},
"description": {
"type": "string"
},
"externalDocs": {
"$ref": "#/$defs/external-documentation"
},
"operationId": {
"type": "string"
},
"parameters": {
"type": "array",
"items": {
"$ref": "#/$defs/parameter-or-reference"
}
},
"requestBody": {
"$ref": "#/$defs/request-body-or-reference"
},
"responses": {
"$ref": "#/$defs/responses"
},
"callbacks": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/callbacks-or-reference"
}
},
"deprecated": {
"default": false,
"type": "boolean"
},
"security": {
"type": "array",
"items": {
"$ref": "#/$defs/security-requirement"
}
},
"servers": {
"type": "array",
"items": {
"$ref": "#/$defs/server"
}
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"external-documentation": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#external-documentation-object",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"url": {
"type": "string",
"format": "uri"
}
},
"required": [
"url"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"parameter": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#parameter-object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"in": {
"enum": [
"query",
"header",
"path",
"cookie"
]
},
"description": {
"type": "string"
},
"required": {
"default": false,
"type": "boolean"
},
"deprecated": {
"default": false,
"type": "boolean"
},
"schema": {
"$ref": "#/$defs/schema"
},
"content": {
"$ref": "#/$defs/content",
"minProperties": 1,
"maxProperties": 1
}
},
"required": [
"name",
"in"
],
"oneOf": [
{
"required": [
"schema"
]
},
{
"required": [
"content"
]
}
],
"if": {
"properties": {
"in": {
"const": "query"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"allowEmptyValue": {
"default": false,
"type": "boolean"
}
}
},
"dependentSchemas": {
"schema": {
"properties": {
"style": {
"type": "string"
},
"explode": {
"type": "boolean"
}
},
"allOf": [
{
"$ref": "#/$defs/examples"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-path"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-header"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-query"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-cookie"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-form"
}
],
"$defs": {
"styles-for-path": {
"if": {
"properties": {
"in": {
"const": "path"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"name": {
"pattern": "[^/#?]+$"
},
"style": {
"default": "simple",
"enum": [
"matrix",
"label",
"simple"
]
},
"required": {
"const": true
}
},
"required": [
"required"
]
}
},
"styles-for-header": {
"if": {
"properties": {
"in": {
"const": "header"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"style": {
"default": "simple",
"const": "simple"
}
}
}
},
"styles-for-query": {
"if": {
"properties": {
"in": {
"const": "query"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"style": {
"default": "form",
"enum": [
"form",
"spaceDelimited",
"pipeDelimited",
"deepObject"
]
},
"allowReserved": {
"default": false,
"type": "boolean"
}
}
}
},
"styles-for-cookie": {
"if": {
"properties": {
"in": {
"const": "cookie"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"style": {
"default": "form",
"const": "form"
}
}
}
},
"styles-for-form": {
"if": {
"properties": {
"style": {
"const": "form"
}
},
"required": [
"style"
]
},
"then": {
"properties": {
"explode": {
"default": true
}
}
},
"else": {
"properties": {
"explode": {
"default": false
}
}
}
}
}
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"parameter-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/parameter"
}
},
"request-body": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#request-body-object",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"content": {
"$ref": "#/$defs/content"
},
"required": {
"default": false,
"type": "boolean"
}
},
"required": [
"content"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"request-body-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/request-body"
}
},
"content": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#fixed-fields-10",
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/media-type"
},
"propertyNames": {
"format": "media-range"
}
},
"media-type": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#media-type-object",
"type": "object",
"properties": {
"schema": {
"$ref": "#/$defs/schema"
},
"encoding": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/encoding"
}
}
},
"allOf": [
{
"$ref": "#/$defs/specification-extensions"
},
{
"$ref": "#/$defs/examples"
}
],
"unevaluatedProperties": false
},
"encoding": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#encoding-object",
"type": "object",
"properties": {
"contentType": {
"type": "string",
"format": "media-range"
},
"headers": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/header-or-reference"
}
},
"style": {
"default": "form",
"enum": [
"form",
"spaceDelimited",
"pipeDelimited",
"deepObject"
]
},
"explode": {
"type": "boolean"
},
"allowReserved": {
"default": false,
"type": "boolean"
}
},
"allOf": [
{
"$ref": "#/$defs/specification-extensions"
},
{
"$ref": "#/$defs/encoding/$defs/explode-default"
}
],
"unevaluatedProperties": false,
"$defs": {
"explode-default": {
"if": {
"properties": {
"style": {
"const": "form"
}
},
"required": [
"style"
]
},
"then": {
"properties": {
"explode": {
"default": true
}
}
},
"else": {
"properties": {
"explode": {
"default": false
}
}
}
}
}
},
"responses": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#responses-object",
"type": "object",
"properties": {
"default": {
"$ref": "#/$defs/response-or-reference"
}
},
"patternProperties": {
"^[1-5](?:[0-9]{2}|XX)$": {
"$ref": "#/$defs/response-or-reference"
}
},
"minProperties": 1,
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"response": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#response-object",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"headers": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/header-or-reference"
}
},
"content": {
"$ref": "#/$defs/content"
},
"links": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/link-or-reference"
}
}
},
"required": [
"description"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"response-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/response"
}
},
"callbacks": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#callback-object",
"type": "object",
"$ref": "#/$defs/specification-extensions",
"additionalProperties": {
"$ref": "#/$defs/path-item-or-reference"
}
},
"callbacks-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/callbacks"
}
},
"example": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#example-object",
"type": "object",
"properties": {
"summary": {
"type": "string"
},
"description": {
"type": "string"
},
"value": true,
"externalValue": {
"type": "string",
"format": "uri"
}
},
"not": {
"required": [
"value",
"externalValue"
]
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"example-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/example"
}
},
"link": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#link-object",
"type": "object",
"properties": {
"operationRef": {
"type": "string",
"format": "uri-reference"
},
"operationId": {
"type": "string"
},
"parameters": {
"$ref": "#/$defs/map-of-strings"
},
"requestBody": true,
"description": {
"type": "string"
},
"body": {
"$ref": "#/$defs/server"
}
},
"oneOf": [
{
"required": [
"operationRef"
]
},
{
"required": [
"operationId"
]
}
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"link-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/link"
}
},
"header": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#header-object",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"required": {
"default": false,
"type": "boolean"
},
"deprecated": {
"default": false,
"type": "boolean"
},
"schema": {
"$ref": "#/$defs/schema"
},
"content": {
"$ref": "#/$defs/content",
"minProperties": 1,
"maxProperties": 1
}
},
"oneOf": [
{
"required": [
"schema"
]
},
{
"required": [
"content"
]
}
],
"dependentSchemas": {
"schema": {
"properties": {
"style": {
"default": "simple",
"const": "simple"
},
"explode": {
"default": false,
"type": "boolean"
}
},
"$ref": "#/$defs/examples"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"header-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/header"
}
},
"tag": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#tag-object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"externalDocs": {
"$ref": "#/$defs/external-documentation"
}
},
"required": [
"name"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"reference": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#reference-object",
"type": "object",
"properties": {
"$ref": {
"type": "string",
"format": "uri-reference"
},
"summary": {
"type": "string"
},
"description": {
"type": "string"
}
},
"unevaluatedProperties": false
},
"schema": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#schema-object",
"$dynamicAnchor": "meta",
"type": [
"object",
"boolean"
]
},
"security-scheme": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#security-scheme-object",
"type": "object",
"properties": {
"type": {
"enum": [
"apiKey",
"http",
"mutualTLS",
"oauth2",
"openIdConnect"
]
},
"description": {
"type": "string"
}
},
"required": [
"type"
],
"allOf": [
{
"$ref": "#/$defs/specification-extensions"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-apikey"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-http"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-http-bearer"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-oauth2"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-oidc"
}
],
"unevaluatedProperties": false,
"$defs": {
"type-apikey": {
"if": {
"properties": {
"type": {
"const": "apiKey"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"name": {
"type": "string"
},
"in": {
"enum": [
"query",
"header",
"cookie"
]
}
},
"required": [
"name",
"in"
]
}
},
"type-http": {
"if": {
"properties": {
"type": {
"const": "http"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"scheme": {
"type": "string"
}
},
"required": [
"scheme"
]
}
},
"type-http-bearer": {
"if": {
"properties": {
"type": {
"const": "http"
},
"scheme": {
"type": "string",
"pattern": "^[Bb][Ee][Aa][Rr][Ee][Rr]$"
}
},
"required": [
"type",
"scheme"
]
},
"then": {
"properties": {
"bearerFormat": {
"type": "string"
}
}
}
},
"type-oauth2": {
"if": {
"properties": {
"type": {
"const": "oauth2"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"flows": {
"$ref": "#/$defs/oauth-flows"
}
},
"required": [
"flows"
]
}
},
"type-oidc": {
"if": {
"properties": {
"type": {
"const": "openIdConnect"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"openIdConnectUrl": {
"type": "string",
"format": "uri"
}
},
"required": [
"openIdConnectUrl"
]
}
}
}
},
"security-scheme-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/security-scheme"
}
},
"oauth-flows": {
"type": "object",
"properties": {
"implicit": {
"$ref": "#/$defs/oauth-flows/$defs/implicit"
},
"password": {
"$ref": "#/$defs/oauth-flows/$defs/password"
},
"clientCredentials": {
"$ref": "#/$defs/oauth-flows/$defs/client-credentials"
},
"authorizationCode": {
"$ref": "#/$defs/oauth-flows/$defs/authorization-code"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false,
"$defs": {
"implicit": {
"type": "object",
"properties": {
"authorizationUrl": {
"type": "string",
"format": "uri"
},
"refreshUrl": {
"type": "string",
"format": "uri"
},
"scopes": {
"$ref": "#/$defs/map-of-strings"
}
},
"required": [
"authorizationUrl",
"scopes"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"password": {
"type": "object",
"properties": {
"tokenUrl": {
"type": "string",
"format": "uri"
},
"refreshUrl": {
"type": "string",
"format": "uri"
},
"scopes": {
"$ref": "#/$defs/map-of-strings"
}
},
"required": [
"tokenUrl",
"scopes"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"client-credentials": {
"type": "object",
"properties": {
"tokenUrl": {
"type": "string",
"format": "uri"
},
"refreshUrl": {
"type": "string",
"format": "uri"
},
"scopes": {
"$ref": "#/$defs/map-of-strings"
}
},
"required": [
"tokenUrl",
"scopes"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"authorization-code": {
"type": "object",
"properties": {
"authorizationUrl": {
"type": "string",
"format": "uri"
},
"tokenUrl": {
"type": "string",
"format": "uri"
},
"refreshUrl": {
"type": "string",
"format": "uri"
},
"scopes": {
"$ref": "#/$defs/map-of-strings"
}
},
"required": [
"authorizationUrl",
"tokenUrl",
"scopes"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
}
}
},
"security-requirement": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#security-requirement-object",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"specification-extensions": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#specification-extensions",
"patternProperties": {
"^x-": true
}
},
"examples": {
"properties": {
"example": true,
"examples": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/example-or-reference"
}
}
}
},
"map-of-strings": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
"$id": "https://spec.openapis.org/oas/3.1/schema/2022-10-07",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "The description of OpenAPI v3.1.x documents without schema validation, as defined by https://spec.openapis.org/oas/v3.1.0",
"type": "object",
"properties": {
"openapi": {
"type": "string",
"pattern": "^3\\.1\\.\\d+(-.+)?$"
},
"info": {
"$ref": "#/$defs/info"
},
"jsonSchemaDialect": {
"type": "string",
"format": "uri",
"default": "https://spec.openapis.org/oas/3.1/dialect/base"
},
"servers": {
"type": "array",
"items": {
"$ref": "#/$defs/server"
},
"default": [
{
"url": "/"
}
]
},
"paths": {
"$ref": "#/$defs/paths"
},
"webhooks": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/path-item-or-reference"
}
},
"components": {
"$ref": "#/$defs/components"
},
"security": {
"type": "array",
"items": {
"$ref": "#/$defs/security-requirement"
}
},
"tags": {
"type": "array",
"items": {
"$ref": "#/$defs/tag"
}
},
"externalDocs": {
"$ref": "#/$defs/external-documentation"
}
},
"required": [
"openapi",
"info"
],
"anyOf": [
{
"required": [
"paths"
]
},
{
"required": [
"components"
]
},
{
"required": [
"webhooks"
]
}
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false,
"$defs": {
"info": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#info-object",
"type": "object",
"properties": {
"title": {
"type": "string"
},
"summary": {
"type": "string"
},
"description": {
"type": "string"
},
"termsOfService": {
"type": "string",
"format": "uri"
},
"contact": {
"$ref": "#/$defs/contact"
},
"license": {
"$ref": "#/$defs/license"
},
"version": {
"type": "string"
}
},
"required": [
"title",
"version"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"contact": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#contact-object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"url": {
"type": "string",
"format": "uri"
},
"email": {
"type": "string",
"format": "email"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"license": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#license-object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"identifier": {
"type": "string"
},
"url": {
"type": "string",
"format": "uri"
}
},
"required": [
"name"
],
"dependentSchemas": {
"identifier": {
"not": {
"required": [
"url"
]
}
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"server": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#server-object",
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri-reference"
},
"description": {
"type": "string"
},
"variables": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/server-variable"
}
}
},
"required": [
"url"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"server-variable": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#server-variable-object",
"type": "object",
"properties": {
"enum": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
},
"default": {
"type": "string"
},
"description": {
"type": "string"
}
},
"required": [
"default"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"components": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#components-object",
"type": "object",
"properties": {
"schemas": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/schema"
}
},
"responses": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/response-or-reference"
}
},
"parameters": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/parameter-or-reference"
}
},
"examples": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/example-or-reference"
}
},
"requestBodies": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/request-body-or-reference"
}
},
"headers": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/header-or-reference"
}
},
"securitySchemes": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/security-scheme-or-reference"
}
},
"links": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/link-or-reference"
}
},
"callbacks": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/callbacks-or-reference"
}
},
"pathItems": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/path-item-or-reference"
}
}
},
"patternProperties": {
"^(schemas|responses|parameters|examples|requestBodies|headers|securitySchemes|links|callbacks|pathItems)$": {
"$comment": "Enumerating all of the property names in the regex above is necessary for unevaluatedProperties to work as expected",
"propertyNames": {
"pattern": "^[a-zA-Z0-9._-]+$"
}
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"paths": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#paths-object",
"type": "object",
"patternProperties": {
"^/": {
"$ref": "#/$defs/path-item"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"path-item": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#path-item-object",
"type": "object",
"properties": {
"summary": {
"type": "string"
},
"description": {
"type": "string"
},
"servers": {
"type": "array",
"items": {
"$ref": "#/$defs/server"
}
},
"parameters": {
"type": "array",
"items": {
"$ref": "#/$defs/parameter-or-reference"
}
},
"get": {
"$ref": "#/$defs/operation"
},
"put": {
"$ref": "#/$defs/operation"
},
"post": {
"$ref": "#/$defs/operation"
},
"delete": {
"$ref": "#/$defs/operation"
},
"options": {
"$ref": "#/$defs/operation"
},
"head": {
"$ref": "#/$defs/operation"
},
"patch": {
"$ref": "#/$defs/operation"
},
"trace": {
"$ref": "#/$defs/operation"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"path-item-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/path-item"
}
},
"operation": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#operation-object",
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"summary": {
"type": "string"
},
"description": {
"type": "string"
},
"externalDocs": {
"$ref": "#/$defs/external-documentation"
},
"operationId": {
"type": "string"
},
"parameters": {
"type": "array",
"items": {
"$ref": "#/$defs/parameter-or-reference"
}
},
"requestBody": {
"$ref": "#/$defs/request-body-or-reference"
},
"responses": {
"$ref": "#/$defs/responses"
},
"callbacks": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/callbacks-or-reference"
}
},
"deprecated": {
"default": false,
"type": "boolean"
},
"security": {
"type": "array",
"items": {
"$ref": "#/$defs/security-requirement"
}
},
"servers": {
"type": "array",
"items": {
"$ref": "#/$defs/server"
}
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"external-documentation": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#external-documentation-object",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"url": {
"type": "string",
"format": "uri"
}
},
"required": [
"url"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"parameter": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#parameter-object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"in": {
"enum": [
"query",
"header",
"path",
"cookie"
]
},
"description": {
"type": "string"
},
"required": {
"default": false,
"type": "boolean"
},
"deprecated": {
"default": false,
"type": "boolean"
},
"schema": {
"$ref": "#/$defs/schema"
},
"content": {
"$ref": "#/$defs/content",
"minProperties": 1,
"maxProperties": 1
}
},
"required": [
"name",
"in"
],
"oneOf": [
{
"required": [
"schema"
]
},
{
"required": [
"content"
]
}
],
"if": {
"properties": {
"in": {
"const": "query"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"allowEmptyValue": {
"default": false,
"type": "boolean"
}
}
},
"dependentSchemas": {
"schema": {
"properties": {
"style": {
"type": "string"
},
"explode": {
"type": "boolean"
}
},
"allOf": [
{
"$ref": "#/$defs/examples"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-path"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-header"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-query"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-cookie"
},
{
"$ref": "#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-form"
}
],
"$defs": {
"styles-for-path": {
"if": {
"properties": {
"in": {
"const": "path"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"name": {
"pattern": "[^/#?]+$"
},
"style": {
"default": "simple",
"enum": [
"matrix",
"label",
"simple"
]
},
"required": {
"const": true
}
},
"required": [
"required"
]
}
},
"styles-for-header": {
"if": {
"properties": {
"in": {
"const": "header"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"style": {
"default": "simple",
"const": "simple"
}
}
}
},
"styles-for-query": {
"if": {
"properties": {
"in": {
"const": "query"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"style": {
"default": "form",
"enum": [
"form",
"spaceDelimited",
"pipeDelimited",
"deepObject"
]
},
"allowReserved": {
"default": false,
"type": "boolean"
}
}
}
},
"styles-for-cookie": {
"if": {
"properties": {
"in": {
"const": "cookie"
}
},
"required": [
"in"
]
},
"then": {
"properties": {
"style": {
"default": "form",
"const": "form"
}
}
}
},
"styles-for-form": {
"if": {
"properties": {
"style": {
"const": "form"
}
},
"required": [
"style"
]
},
"then": {
"properties": {
"explode": {
"default": true
}
}
},
"else": {
"properties": {
"explode": {
"default": false
}
}
}
}
}
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"parameter-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/parameter"
}
},
"request-body": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#request-body-object",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"content": {
"$ref": "#/$defs/content"
},
"required": {
"default": false,
"type": "boolean"
}
},
"required": [
"content"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"request-body-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/request-body"
}
},
"content": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#fixed-fields-10",
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/media-type"
},
"propertyNames": {
"format": "media-range"
}
},
"media-type": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#media-type-object",
"type": "object",
"properties": {
"schema": {
"$ref": "#/$defs/schema"
},
"encoding": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/encoding"
}
}
},
"allOf": [
{
"$ref": "#/$defs/specification-extensions"
},
{
"$ref": "#/$defs/examples"
}
],
"unevaluatedProperties": false
},
"encoding": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#encoding-object",
"type": "object",
"properties": {
"contentType": {
"type": "string",
"format": "media-range"
},
"headers": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/header-or-reference"
}
},
"style": {
"default": "form",
"enum": [
"form",
"spaceDelimited",
"pipeDelimited",
"deepObject"
]
},
"explode": {
"type": "boolean"
},
"allowReserved": {
"default": false,
"type": "boolean"
}
},
"allOf": [
{
"$ref": "#/$defs/specification-extensions"
},
{
"$ref": "#/$defs/encoding/$defs/explode-default"
}
],
"unevaluatedProperties": false,
"$defs": {
"explode-default": {
"if": {
"properties": {
"style": {
"const": "form"
}
},
"required": [
"style"
]
},
"then": {
"properties": {
"explode": {
"default": true
}
}
},
"else": {
"properties": {
"explode": {
"default": false
}
}
}
}
}
},
"responses": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#responses-object",
"type": "object",
"properties": {
"default": {
"$ref": "#/$defs/response-or-reference"
}
},
"patternProperties": {
"^[1-5](?:[0-9]{2}|XX)$": {
"$ref": "#/$defs/response-or-reference"
}
},
"minProperties": 1,
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"response": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#response-object",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"headers": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/header-or-reference"
}
},
"content": {
"$ref": "#/$defs/content"
},
"links": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/link-or-reference"
}
}
},
"required": [
"description"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"response-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/response"
}
},
"callbacks": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#callback-object",
"type": "object",
"$ref": "#/$defs/specification-extensions",
"additionalProperties": {
"$ref": "#/$defs/path-item-or-reference"
}
},
"callbacks-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/callbacks"
}
},
"example": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#example-object",
"type": "object",
"properties": {
"summary": {
"type": "string"
},
"description": {
"type": "string"
},
"value": true,
"externalValue": {
"type": "string",
"format": "uri"
}
},
"not": {
"required": [
"value",
"externalValue"
]
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"example-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/example"
}
},
"link": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#link-object",
"type": "object",
"properties": {
"operationRef": {
"type": "string",
"format": "uri-reference"
},
"operationId": {
"type": "string"
},
"parameters": {
"$ref": "#/$defs/map-of-strings"
},
"requestBody": true,
"description": {
"type": "string"
},
"body": {
"$ref": "#/$defs/server"
}
},
"oneOf": [
{
"required": [
"operationRef"
]
},
{
"required": [
"operationId"
]
}
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"link-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/link"
}
},
"header": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#header-object",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"required": {
"default": false,
"type": "boolean"
},
"deprecated": {
"default": false,
"type": "boolean"
},
"schema": {
"$ref": "#/$defs/schema"
},
"content": {
"$ref": "#/$defs/content",
"minProperties": 1,
"maxProperties": 1
}
},
"oneOf": [
{
"required": [
"schema"
]
},
{
"required": [
"content"
]
}
],
"dependentSchemas": {
"schema": {
"properties": {
"style": {
"default": "simple",
"const": "simple"
},
"explode": {
"default": false,
"type": "boolean"
}
},
"$ref": "#/$defs/examples"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"header-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/header"
}
},
"tag": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#tag-object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"externalDocs": {
"$ref": "#/$defs/external-documentation"
}
},
"required": [
"name"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"reference": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#reference-object",
"type": "object",
"properties": {
"$ref": {
"type": "string",
"format": "uri-reference"
},
"summary": {
"type": "string"
},
"description": {
"type": "string"
}
},
"unevaluatedProperties": false
},
"schema": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#schema-object",
"$dynamicAnchor": "meta",
"type": [
"object",
"boolean"
]
},
"security-scheme": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#security-scheme-object",
"type": "object",
"properties": {
"type": {
"enum": [
"apiKey",
"http",
"mutualTLS",
"oauth2",
"openIdConnect"
]
},
"description": {
"type": "string"
}
},
"required": [
"type"
],
"allOf": [
{
"$ref": "#/$defs/specification-extensions"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-apikey"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-http"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-http-bearer"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-oauth2"
},
{
"$ref": "#/$defs/security-scheme/$defs/type-oidc"
}
],
"unevaluatedProperties": false,
"$defs": {
"type-apikey": {
"if": {
"properties": {
"type": {
"const": "apiKey"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"name": {
"type": "string"
},
"in": {
"enum": [
"query",
"header",
"cookie"
]
}
},
"required": [
"name",
"in"
]
}
},
"type-http": {
"if": {
"properties": {
"type": {
"const": "http"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"scheme": {
"type": "string"
}
},
"required": [
"scheme"
]
}
},
"type-http-bearer": {
"if": {
"properties": {
"type": {
"const": "http"
},
"scheme": {
"type": "string",
"pattern": "^[Bb][Ee][Aa][Rr][Ee][Rr]$"
}
},
"required": [
"type",
"scheme"
]
},
"then": {
"properties": {
"bearerFormat": {
"type": "string"
}
}
}
},
"type-oauth2": {
"if": {
"properties": {
"type": {
"const": "oauth2"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"flows": {
"$ref": "#/$defs/oauth-flows"
}
},
"required": [
"flows"
]
}
},
"type-oidc": {
"if": {
"properties": {
"type": {
"const": "openIdConnect"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"openIdConnectUrl": {
"type": "string",
"format": "uri"
}
},
"required": [
"openIdConnectUrl"
]
}
}
}
},
"security-scheme-or-reference": {
"if": {
"type": "object",
"required": [
"$ref"
]
},
"then": {
"$ref": "#/$defs/reference"
},
"else": {
"$ref": "#/$defs/security-scheme"
}
},
"oauth-flows": {
"type": "object",
"properties": {
"implicit": {
"$ref": "#/$defs/oauth-flows/$defs/implicit"
},
"password": {
"$ref": "#/$defs/oauth-flows/$defs/password"
},
"clientCredentials": {
"$ref": "#/$defs/oauth-flows/$defs/client-credentials"
},
"authorizationCode": {
"$ref": "#/$defs/oauth-flows/$defs/authorization-code"
}
},
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false,
"$defs": {
"implicit": {
"type": "object",
"properties": {
"authorizationUrl": {
"type": "string",
"format": "uri"
},
"refreshUrl": {
"type": "string",
"format": "uri"
},
"scopes": {
"$ref": "#/$defs/map-of-strings"
}
},
"required": [
"authorizationUrl",
"scopes"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"password": {
"type": "object",
"properties": {
"tokenUrl": {
"type": "string",
"format": "uri"
},
"refreshUrl": {
"type": "string",
"format": "uri"
},
"scopes": {
"$ref": "#/$defs/map-of-strings"
}
},
"required": [
"tokenUrl",
"scopes"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"client-credentials": {
"type": "object",
"properties": {
"tokenUrl": {
"type": "string",
"format": "uri"
},
"refreshUrl": {
"type": "string",
"format": "uri"
},
"scopes": {
"$ref": "#/$defs/map-of-strings"
}
},
"required": [
"tokenUrl",
"scopes"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
},
"authorization-code": {
"type": "object",
"properties": {
"authorizationUrl": {
"type": "string",
"format": "uri"
},
"tokenUrl": {
"type": "string",
"format": "uri"
},
"refreshUrl": {
"type": "string",
"format": "uri"
},
"scopes": {
"$ref": "#/$defs/map-of-strings"
}
},
"required": [
"authorizationUrl",
"tokenUrl",
"scopes"
],
"$ref": "#/$defs/specification-extensions",
"unevaluatedProperties": false
}
}
},
"security-requirement": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#security-requirement-object",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"specification-extensions": {
"$comment": "https://spec.openapis.org/oas/v3.1.0#specification-extensions",
"patternProperties": {
"^x-": true
}
},
"examples": {
"properties": {
"example": true,
"examples": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/example-or-reference"
}
}
}
},
"map-of-strings": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}

@@ -1,53 +0,60 @@

import tap from "tap";
import { URL } from 'url';
import { createHash } from "crypto";
import { readFileSync } from "fs";
import { strict as assert } from "node:assert/strict";
import { test } from "node:test";
import { URL } from "url";
import { readdir } from "fs/promises";
import { readFileSync } from "fs";
import { Validator } from "../index.js";
import { createHash } from "crypto";
import { Snapshot } from "./snapshot.js";
const supportedVersions = Validator.supportedVersions;
function localPath(path){
return new URL(path, import.meta.url).pathname;
function localPath(path) {
return new URL(path, import.meta.url).pathname;
}
const openApiDir = localPath('../schemas.orig');
const test = tap.test;
tap.formatSnapshot = (object) => {
const hash = createHash("sha256");
hash.update(JSON.stringify(object));
return hash.digest("hex");
};
const snapShotFile = localPath("snapshots-check-versions.json");
const updateSnapShot = process.argv[2] !== undefined;
const snapshot = new Snapshot(snapShotFile, updateSnapShot);
function matchSnapshot(obj, name) {
const hash = createHash("sha256");
hash.update(JSON.stringify(obj));
const hashValue = hash.digest("hex");
return snapshot.match(hashValue, name);
}
const openApiDir = localPath("../schemas.orig");
function readJSON(file) {
return JSON.parse(readFileSync(file));
return JSON.parse(readFileSync(file));
}
async function getOpenApiSchemasVersions(oasdir) {
const dirs = (await readdir(oasdir)).filter((d) => !d.endsWith(".html"));
return dirs;
const dirs = (await readdir(oasdir)).filter((d) => !d.endsWith(".html"));
return dirs;
}
async function testVersion(version) {
test(`Check if version ${version} is unchanged`, async (t) => {
t.plan(1);
const schemaList = (await readdir(`${openApiDir}/${version}/schema/`));
const lastSchema = schemaList.pop();
const schema = readJSON(`${openApiDir}/${version}/schema/${lastSchema}`);
t.matchSnapshot(schema, `schema v${version} is unchanged`);
});
test(`Check if version ${version} is unchanged`, async (t) => {
const schemaList = await readdir(`${openApiDir}/${version}/schema/`);
const lastSchema = schemaList.pop();
const schema = readJSON(`${openApiDir}/${version}/schema/${lastSchema}`);
assert.equal(
matchSnapshot(schema, `schema v${version} is unchanged`),
true,
);
});
}
test(`no new versions should be present`, async (t) => {
t.plan(1);
const versions = await getOpenApiSchemasVersions(openApiDir);
const difference = versions.filter((x) => !supportedVersions.has(x));
t.same(difference, [], "all versions are known");
test("no new versions should be present", async (t) => {
const versions = await getOpenApiSchemasVersions(openApiDir);
const difference = versions.filter((x) => !supportedVersions.has(x));
assert.equal(difference.length, 0, "all versions are known");
});
async function testAvailableVersions() {
const versions = await getOpenApiSchemasVersions(openApiDir);
versions.filter((x) => supportedVersions.has(x)).forEach(testVersion);
const versions = await getOpenApiSchemasVersions(openApiDir);
versions.filter((x) => supportedVersions.has(x)).forEach(testVersion);
}
// supportedVersions.forEach(testVersion);
testAvailableVersions();
import { readFileSync, readdirSync, writeFileSync } from "fs";
function localPath(path){
return new URL(path, import.meta.url).pathname;
function localPath(path) {
return new URL(path, import.meta.url).pathname;
}
const openApiSrcDir = localPath('../schemas.orig');
const openApiDestDir = localPath('../schemas');
const openApiSrcDir = localPath("../schemas.orig");
const openApiDestDir = localPath("../schemas");
const version = "3.1";

@@ -12,15 +12,15 @@ const destFilePath = `${openApiDestDir}/v${version}/schema.json`;

function importJSON(file) {
return JSON.parse(readFileSync(file));
return JSON.parse(readFileSync(file));
}
function getLatestSchema(version) {
const srcPath = `${openApiSrcDir}/${version}/schema/`
const schemaList = readdirSync(srcPath);
const lastSchema = schemaList.pop();
const schema = importJSON(`${srcPath}/${lastSchema}`);
return schema;
const srcPath = `${openApiSrcDir}/${version}/schema/`;
const schemaList = readdirSync(srcPath);
const lastSchema = schemaList.pop();
const schema = importJSON(`${srcPath}/${lastSchema}`);
return schema;
}
function escapeJsonPointer(str) {
return str.replace(/~/g, "~0").replace(/\//g, "~1");
return str.replace(/~/g, "~0").replace(/\//g, "~1");
}

@@ -33,17 +33,18 @@

const pointers = {};
pointerWords.forEach((word) => (pointers[word] = []));
for (const word of pointerWords) {
pointers[word] = [];
}
function parse(obj, path, id) {
if (!isObject(obj)) {
return;
}
if (obj.$id) {
id = obj.$id;
}
for (const prop in obj) {
if (pointerWords.has(prop)) {
pointers[prop].push({ ref: obj[prop], obj, prop, path, id });
}
parse(obj[prop], `${path}/${escapeJsonPointer(prop)}`, id);
}
if (!isObject(obj)) {
return;
}
const objId = obj.$id || id;
for (const prop in obj) {
if (pointerWords.has(prop)) {
pointers[prop].push({ ref: obj[prop], obj, prop, path, objId });
}
parse(obj[prop], `${path}/${escapeJsonPointer(prop)}`, objId);
}
}

@@ -55,21 +56,18 @@ const schema = getLatestSchema(version);

pointers.$dynamicAnchor.forEach((item) => {
const { ref, prop, path } = item;
console.log({ ref, prop, path });
dynamicAnchors[`#${ref}`] = path;
const { ref, prop, path } = item;
console.log({ ref, prop, path });
dynamicAnchors[`#${ref}`] = path;
});
pointers.$dynamicRef.forEach((item) => {
const { ref, obj, prop, path } = item;
if (!dynamicAnchors[ref]) {
throw `Can't find $dynamicAnchor for '${ref}'`;
}
console.log({ ref, prop, path, newRef: dynamicAnchors[ref] });
delete obj[prop];
obj.$ref = dynamicAnchors[ref];
const { ref, obj, prop, path } = item;
if (!dynamicAnchors[ref]) {
throw `Can't find $dynamicAnchor for '${ref}'`;
}
console.log({ ref, prop, path, newRef: dynamicAnchors[ref] });
obj[prop] = undefined;
obj.$ref = dynamicAnchors[ref];
});
writeFileSync(
`${destFilePath}`,
JSON.stringify(schema, null, 2),
);
writeFileSync(`${destFilePath}`, JSON.stringify(schema, null, "\t"));
console.log(`Written converted schema to ${destFilePath}`);
console.log(`$id: ${schema.$id}`);

@@ -1,46 +0,50 @@

function escapeMarkDown(string){
return string.replace(/[.*+?^~${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
function escapeMarkDown(string) {
return string.replace(/[.*+?^~${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}
function minorVersion(version){
const [major,minor, _] = version.split('.');
return `${major}.${minor}`;
function minorVersion(version) {
const [major, minor, _] = version.split(".");
return `${major}.${minor}`;
}
function processErrors(errors) {
const data = {};
for (const item of errors) {
const path = item.instancePath;
if (!data[path]) {
data[path] = {
path,
gitHubUrl: item.gitHubUrl,
hasValue: item.hasInstanceValue,
value: JSON.stringify(item.instanceValue, null, 2),
errors: [],
errorIdx: {}
};
}
const error = {
keyword: item.keyword,
params: JSON.stringify(item.params),
message: item.message
}
const errorKey = JSON.stringify(error);
if (!data[path].errorIdx[errorKey]) {
data[path].errorIdx[errorKey] = true;
data[path].errors.push(error);
}
}
let output = "";
for (const key in data) {
const item = data[key];
output += `
const data = {};
for (const item of errors) {
const path = item.instancePath;
if (!data[path]) {
data[path] = {
path,
gitHubUrl: item.gitHubUrl,
hasValue: item.hasInstanceValue,
value: JSON.stringify(item.instanceValue, null, 2),
errors: [],
errorIdx: {},
};
}
const error = {
keyword: item.keyword,
params: JSON.stringify(item.params),
message: item.message,
};
const errorKey = JSON.stringify(error);
if (!data[path].errorIdx[errorKey]) {
data[path].errorIdx[errorKey] = true;
data[path].errors.push(error);
}
}
let output = "";
for (const key in data) {
const item = data[key];
output += `
### Path: ${escapeMarkDown(item.path)}
Path on Github: [link](${item.gitHubUrl})
Value: ${item.hasValue ? `
Value: ${
item.hasValue
? `
\`\`\`json
${item.value}
\`\`\`` : 'content too large'}
\`\`\``
: "content too large to display here"
}

@@ -51,11 +55,12 @@ AJV errors:

|--------|-------|--------|
${item.errors.map(err => ` |${err.keyword} |${err.params}| ${err.message}`).join("\n")}
`
}
return output;
${item.errors
.map((err) => ` |${err.keyword} |${err.params}| ${err.message}`)
.join("\n")}
`;
}
return output;
}
export function createReport(results) {
return `# Results of real world testing
return `# Results of real world testing
Report generated at: ${new Date(Date.parse(results.testDate))}

@@ -69,6 +74,12 @@

${results.failedTests.map(item => `
${results.failedTests
.map(
(item) => `
## API: ${escapeMarkDown(item.name)} (version: ${item.apiVersion})
${item.openApiVersion === "2.0" ? "Swagger" : "OpenApi"}: [${item.openApiVersion}](https://spec.openapis.org/oas/v${item.openApiVersion})
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v${minorVersion(item.openApiVersion)}/schema.json)
${item.specificationType}: [${
item.specificationVersion
}](https://spec.openapis.org/oas/v${item.specificationVersion})
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v${
item.validatorVersion
}/schema.json)

@@ -79,5 +90,5 @@ API on Github: [link](${item.gitHubUrl})

${processErrors(item.result.errors)}
` ).join("\n")}`;
`,
)
.join("\n")}`;
}
# Results of real world testing
Report generated at: Thu Sep 22 2022 16:55:26 GMT+0000 (Coordinated Universal Time)
Report generated at: Tue Mar 21 2023 18:54:53 GMT+0100 (Central European Standard Time)
| APIs at [apis.guru](https://apis.guru) | #
|--------|-------|
|Total |2357
|Tested |2357
|Failed validation | 53
|Total |2508
|Tested |8
|Failed validation | 8
## API: adyen\.com:CheckoutService (version: 68)
OpenApi: [3.1.0](https://spec.openapis.org/oas/v3.1.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.1/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/adyen.com/CheckoutService/68/openapi.yaml)
API updated: 2021-11-12T23:18:19.544Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/adyen.com/CheckoutService/68/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|unevaluatedProperties |{"unevaluatedProperty":"source"}| must NOT have unevaluated properties
## API: adyen\.com:PaymentService (version: 68)
OpenApi: [3.1.0](https://spec.openapis.org/oas/v3.1.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.1/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/adyen.com/PaymentService/68/openapi.yaml)
API updated: 2021-11-12T23:18:19.544Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/adyen.com/PaymentService/68/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|unevaluatedProperties |{"unevaluatedProperty":"source"}| must NOT have unevaluated properties
## API: adyen\.com:PayoutService (version: 68)
OpenApi: [3.1.0](https://spec.openapis.org/oas/v3.1.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.1/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/adyen.com/PayoutService/68/openapi.yaml)
API updated: 2021-11-12T23:18:19.544Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/adyen.com/PayoutService/68/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|unevaluatedProperties |{"unevaluatedProperty":"source"}| must NOT have unevaluated properties
## API: adyen\.com:RecurringService (version: 68)
OpenApi: [3.1.0](https://spec.openapis.org/oas/v3.1.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.1/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/adyen.com/RecurringService/68/openapi.yaml)
API updated: 2021-11-02T23:15:52.596Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/adyen.com/RecurringService/68/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|unevaluatedProperties |{"unevaluatedProperty":"source"}| must NOT have unevaluated properties
## API: airport-web\.appspot\.com (version: v1)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)

@@ -142,19 +58,16 @@

## API: ato\.gov\.au (version: 0.0.6)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
## API: azure\.com:servicebus (version: 2017-04-01)
swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/ato.gov.au/0.0.6/swagger.yaml)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/azure.com/servicebus/2017-04-01/swagger.yaml)
API updated: 2017-09-06T11:44:38.000Z
API updated: 2019-09-23T09:26:07.000Z
### Path: /paths/\~1individuals\~1\{partyId\}/delete/responses/400
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/ato.gov.au/0.0.6/swagger.yaml#L902)
### Path: /paths/\~1subscriptions\~1\{subscriptionId\}\~1resourceGroups\~1\{resourceGroupName\}\~1providers\~1Microsoft\.ServiceBus\~1namespaces\~1\{namespaceName\}\~1topics\~1\{topicName\}\~1subscriptions\~1\{subscriptionName\}\~1rules\~1\{ruleName\}/get/externalDocs/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/azure.com/servicebus/2017-04-01/swagger.yaml#L4207)
Value:
```json
{
"$ref": "#/responses/FailedPrecondition",
"description": "Individual has related resources and cannot be deleted"
}
""
```

@@ -166,18 +79,16 @@

|--------|-------|--------|
|additionalProperties |{"additionalProperty":"$ref"}| must NOT have additional properties
|additionalProperties |{"additionalProperty":"description"}| must NOT have additional properties
|oneOf |{"passingSchemas":null}| must match exactly one schema in oneOf
|format |{"format":"uri"}| must match format "uri"
## API: azure\.com:servicebus (version: 2017-04-01)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
## API: azure\.com:storageimportexport (version: 2016-11-01)
swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/azure.com/servicebus/2017-04-01/swagger.yaml)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/azure.com/storageimportexport/2016-11-01/swagger.yaml)
API updated: 2019-09-23T09:26:07.000Z
API updated: 2019-07-22T11:03:07.000Z
### Path: /paths/\~1subscriptions\~1\{subscriptionId\}\~1resourceGroups\~1\{resourceGroupName\}\~1providers\~1Microsoft\.ServiceBus\~1namespaces\~1\{namespaceName\}\~1topics\~1\{topicName\}\~1subscriptions\~1\{subscriptionName\}\~1rules\~1\{ruleName\}/get/externalDocs/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/azure.com/servicebus/2017-04-01/swagger.yaml#L4207)
### Path: /paths/\~1providers\~1Microsoft\.ImportExport\~1locations/get/externalDocs/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/azure.com/storageimportexport/2016-11-01/swagger.yaml#L79)

@@ -197,16 +108,16 @@ Value:

## API: azure\.com:storageimportexport (version: 2016-11-01)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
## API: discourse\.local (version: latest)
openapi: [3.1.0](https://spec.openapis.org/oas/v3.1.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.1/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/azure.com/storageimportexport/2016-11-01/swagger.yaml)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/discourse.local/latest/openapi.yaml)
API updated: 2019-07-22T11:03:07.000Z
API updated: 2023-03-06T07:12:59.965Z
### Path: /paths/\~1providers\~1Microsoft\.ImportExport\~1locations/get/externalDocs/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/azure.com/storageimportexport/2016-11-01/swagger.yaml#L79)
### Path: /servers/1/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/discourse.local/latest/openapi.yaml#L68)
Value:
```json
""
"https://{defaultHost}"
```

@@ -218,3 +129,3 @@

|--------|-------|--------|
|format |{"format":"uri"}| must match format "uri"
|format |{"format":"uri-reference"}| must match format "uri-reference"

@@ -224,3 +135,3 @@

## API: gambitcomm\.local:mimic (version: 21.00)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
openapi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)

@@ -301,14 +212,17 @@

## API: googleapis\.com:accessapproval (version: v1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
## API: linode\.com (version: 4.145.0)
openapi: [3.0.1](https://spec.openapis.org/oas/v3.0.1)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/accessapproval/v1/openapi.yaml)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/linode.com/4.145.0/openapi.yaml)
API updated: 2022-08-29T23:11:50.392Z
API updated: 2023-03-06T09:58:04.581Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/accessapproval/v1/openapi.yaml#L1)
### Path: /paths/\~1domains\~1\{domainId\}\~1clone/post/requestBody/content/application\~1json/schema/properties/domain/pattern
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/linode.com/4.145.0/openapi.yaml#L5848)
Value: content too large
Value:
```json
"\\A(\\*\\.)?([a-zA-Z0-9-_]{1,63}\\.)+([a-zA-Z]{2,3}\\.)?([a-zA-Z]{2,16}|xn--[a-zA-Z0-9]+)\\Z"
```

@@ -319,757 +233,17 @@ AJV errors:

|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
|format |{"format":"regex"}| must match format "regex"
### Path: /paths/\~1domains\~1\{domainId\}\~1clone/post/requestBody/content/application\~1json/schema/properties/domain
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/linode.com/4.145.0/openapi.yaml#L5842)
## API: googleapis\.com:admin (version: reports_v1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/admin/reports_v1/openapi.yaml)
API updated: 2021-12-08T23:09:48.755Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/admin/reports_v1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:adsense (version: v2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/adsense/v2/openapi.yaml)
API updated: 2022-09-21T23:12:08.137Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/adsense/v2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:bigqueryreservation (version: v1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/bigqueryreservation/v1/openapi.yaml)
API updated: 2022-08-24T23:11:07.299Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/bigqueryreservation/v1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:cloudbilling (version: v1beta)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/cloudbilling/v1beta/openapi.yaml)
API updated: 2022-09-19T23:12:49.727Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/cloudbilling/v1beta/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:cloudbuild (version: v1beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/cloudbuild/v1beta1/openapi.yaml)
API updated: 2022-09-02T23:11:04.545Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/cloudbuild/v1beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:cloudfunctions (version: v2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/cloudfunctions/v2/openapi.yaml)
API updated: 2022-09-05T23:12:55.703Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/cloudfunctions/v2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:cloudshell (version: v1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/cloudshell/v1/openapi.yaml)
API updated: 2022-03-23T23:15:18.095Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/cloudshell/v1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:container (version: v1beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/container/v1beta1/openapi.yaml)
API updated: 2022-09-14T23:12:23.050Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/container/v1beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:datastore (version: v1beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/datastore/v1beta1/openapi.yaml)
API updated: 2022-02-14T23:08:57.692Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/datastore/v1beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:dfareporting (version: v3.4)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/dfareporting/v3.4/openapi.yaml)
API updated: undefined
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/dfareporting/v3.4/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:displayvideo (version: v2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/displayvideo/v2/openapi.yaml)
API updated: 2022-09-20T23:12:22.749Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/displayvideo/v2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:dns (version: v2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/dns/v2/openapi.yaml)
API updated: 2022-09-09T23:12:02.103Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/dns/v2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:file (version: v1beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/file/v1beta1/openapi.yaml)
API updated: 2022-08-12T23:10:40.199Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/file/v1beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:firebaseappcheck (version: v1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/firebaseappcheck/v1/openapi.yaml)
API updated: 2022-04-29T23:10:53.381Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/firebaseappcheck/v1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:firebasehosting (version: v1beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/firebasehosting/v1beta1/openapi.yaml)
API updated: 2022-06-02T23:11:00.502Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/firebasehosting/v1beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:firestore (version: v1beta2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/firestore/v1beta2/openapi.yaml)
API updated: 2022-03-24T23:10:34.757Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/firestore/v1beta2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:gameservices (version: v1beta)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/gameservices/v1beta/openapi.yaml)
API updated: 2022-09-02T23:11:04.545Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/gameservices/v1beta/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:genomics (version: v2alpha1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/genomics/v2alpha1/openapi.yaml)
API updated: 2022-03-29T23:10:57.754Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/genomics/v2alpha1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:healthcare (version: v1beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/healthcare/v1beta1/openapi.yaml)
API updated: 2022-08-17T23:12:11.899Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/healthcare/v1beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:iam (version: v2beta)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/iam/v2beta/openapi.yaml)
API updated: 2022-07-20T23:12:06.710Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/iam/v2beta/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:identitytoolkit (version: v2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/identitytoolkit/v2/openapi.yaml)
API updated: 2022-09-21T23:12:08.137Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/identitytoolkit/v2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:jobs (version: v4)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/jobs/v4/openapi.yaml)
API updated: 2022-07-21T23:12:10.721Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/jobs/v4/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:managedidentities (version: v1beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/managedidentities/v1beta1/openapi.yaml)
API updated: 2022-09-05T23:12:55.703Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/managedidentities/v1beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:monitoring (version: v1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/monitoring/v1/openapi.yaml)
API updated: 2022-09-21T23:12:08.137Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/monitoring/v1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:osconfig (version: v1beta)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/osconfig/v1beta/openapi.yaml)
API updated: 2022-07-26T23:10:14.384Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/osconfig/v1beta/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:policytroubleshooter (version: v1beta)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/policytroubleshooter/v1beta/openapi.yaml)
API updated: 2022-08-29T23:11:50.392Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/policytroubleshooter/v1beta/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:pubsub (version: v1beta2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/pubsub/v1beta2/openapi.yaml)
API updated: 2022-09-08T23:13:09.421Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/pubsub/v1beta2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:redis (version: v1beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/redis/v1beta1/openapi.yaml)
API updated: 2022-05-23T23:11:26.267Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/redis/v1beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:run (version: v2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/run/v2/openapi.yaml)
API updated: 2022-09-05T23:12:55.703Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/run/v2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:securitycenter (version: v1p1alpha1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/securitycenter/v1p1alpha1/openapi.yaml)
API updated: 2022-09-21T23:12:08.137Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/securitycenter/v1p1alpha1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:servicecontrol (version: v2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/servicecontrol/v2/openapi.yaml)
API updated: 2022-04-15T23:10:59.877Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/servicecontrol/v2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:speech (version: v2beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/speech/v2beta1/openapi.yaml)
API updated: undefined
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/speech/v2beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:tpu (version: v2alpha1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/tpu/v2alpha1/openapi.yaml)
API updated: 2022-09-12T23:11:57.151Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/tpu/v2alpha1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:verifiedaccess (version: v2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/verifiedaccess/v2/openapi.yaml)
API updated: 2022-06-29T23:10:37.342Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/verifiedaccess/v2/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: googleapis\.com:vision (version: v1p2beta1)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/vision/v1p2beta1/openapi.yaml)
API updated: 2022-09-21T23:12:08.137Z
### Path:
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/googleapis.com/vision/v1p2beta1/openapi.yaml#L1)
Value: content too large
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"source"}| must NOT have additional properties
## API: openapi-generator\.tech (version: 5.2.1)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/openapi-generator.tech/5.2.1/swagger.yaml)
API updated: 2021-08-23T09:34:59.789Z
### Path: /paths/\~1api\~1gen\~1clients\~1\{language\}/get/responses/200/schema/additionalProperties
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/openapi-generator.tech/5.2.1/swagger.yaml#L61)
Value:
```json
{
"$ref": "#/definitions/CliOption",
"originalRef": "CliOption"
"description": "The new domain for the clone. Domain labels cannot be longer than 63 characters and must conform to [RFC1035](https://tools.ietf.org/html/rfc1035). Domains must be unique on Linode's platform, including across different Linode accounts; there cannot be two Domains representing the same domain.\n",
"example": "example.org",
"maxLength": 253,
"minLength": 1,
"pattern": "\\A(\\*\\.)?([a-zA-Z0-9-_]{1,63}\\.)+([a-zA-Z]{2,3}\\.)?([a-zA-Z]{2,16}|xn--[a-zA-Z0-9]+)\\Z",
"type": "string",
"x-linode-filterable": true
}

@@ -1082,8 +256,7 @@ ```

|--------|-------|--------|
|additionalProperties |{"additionalProperty":"originalRef"}| must NOT have additional properties
|type |{"type":"boolean"}| must be boolean
|anyOf |{}| must match a schema in anyOf
|required |{"missingProperty":"$ref"}| must have required property '$ref'
|oneOf |{"passingSchemas":null}| must match exactly one schema in oneOf
### Path: /paths/\~1api\~1gen\~1clients\~1\{language\}/get/responses/200/schema
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/openapi-generator.tech/5.2.1/swagger.yaml#L60)
### Path: /paths/\~1domains\~1\{domainId\}\~1clone/post/requestBody/content/application\~1json/schema
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/linode.com/4.145.0/openapi.yaml#L5840)

@@ -1093,6 +266,16 @@ Value:

{
"additionalProperties": {
"$ref": "#/definitions/CliOption",
"originalRef": "CliOption"
"properties": {
"domain": {
"description": "The new domain for the clone. Domain labels cannot be longer than 63 characters and must conform to [RFC1035](https://tools.ietf.org/html/rfc1035). Domains must be unique on Linode's platform, including across different Linode accounts; there cannot be two Domains representing the same domain.\n",
"example": "example.org",
"maxLength": 253,
"minLength": 1,
"pattern": "\\A(\\*\\.)?([a-zA-Z0-9-_]{1,63}\\.)+([a-zA-Z]{2,3}\\.)?([a-zA-Z]{2,16}|xn--[a-zA-Z0-9]+)\\Z",
"type": "string",
"x-linode-filterable": true
}
},
"required": [
"domain"
],
"type": "object"

@@ -1106,7 +289,7 @@ }

|--------|-------|--------|
|additionalProperties |{"additionalProperty":"additionalProperties"}| must NOT have additional properties
|required |{"missingProperty":"$ref"}| must have required property '$ref'
|oneOf |{"passingSchemas":null}| must match exactly one schema in oneOf
### Path: /paths/\~1api\~1gen\~1clients\~1\{language\}/get/responses/200
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/openapi-generator.tech/5.2.1/swagger.yaml#L58)
### Path: /paths/\~1domains\~1\{domainId\}\~1clone/post/requestBody
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/linode.com/4.145.0/openapi.yaml#L5837)

@@ -1116,10 +299,25 @@ Value:

{
"description": "successful operation",
"schema": {
"additionalProperties": {
"$ref": "#/definitions/CliOption",
"originalRef": "CliOption"
},
"type": "object"
}
"content": {
"application/json": {
"schema": {
"properties": {
"domain": {
"description": "The new domain for the clone. Domain labels cannot be longer than 63 characters and must conform to [RFC1035](https://tools.ietf.org/html/rfc1035). Domains must be unique on Linode's platform, including across different Linode accounts; there cannot be two Domains representing the same domain.\n",
"example": "example.org",
"maxLength": 253,
"minLength": 1,
"pattern": "\\A(\\*\\.)?([a-zA-Z0-9-_]{1,63}\\.)+([a-zA-Z]{2,3}\\.)?([a-zA-Z]{2,16}|xn--[a-zA-Z0-9]+)\\Z",
"type": "string",
"x-linode-filterable": true
}
},
"required": [
"domain"
],
"type": "object"
}
}
},
"description": "Information about the Domain to clone.",
"required": true
}

@@ -1138,3 +336,3 @@ ```

## API: opensuse\.org:obs (version: 2.10.50)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
openapi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)

@@ -1419,83 +617,22 @@

## API: parliament\.uk:statutoryinstruments (version: v1)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
## API: royalmail\.com:click-and-drop (version: 1.0.0)
swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/parliament.uk/statutoryinstruments/v1/swagger.yaml)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/royalmail.com/click-and-drop/1.0.0/swagger.yaml)
API updated: 2021-06-21T12:16:53.715Z
API updated: 2023-03-06T07:12:59.965Z
### Path: /info/contact/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/parliament.uk/statutoryinstruments/v1/swagger.yaml#L6)
### Path: /parameters/orderIdentifiers
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/royalmail.com/click-and-drop/1.0.0/swagger.yaml#L79)
Value:
```json
""
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|format |{"format":"uri"}| must match format "uri"
## API: parliament\.uk:treaties (version: v1)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/parliament.uk/treaties/v1/swagger.yaml)
API updated: 2021-05-24T10:27:51.952Z
### Path: /info/contact/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/parliament.uk/treaties/v1/swagger.yaml#L6)
Value:
```json
""
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|format |{"format":"uri"}| must match format "uri"
## API: prss\.org (version: 2.0.0)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/prss.org/2.0.0/swagger.yaml)
API updated: 2021-06-21T12:16:53.715Z
### Path: /paths/\~1api\~1v2\~1metapub\~1program-information\~1batch/post/responses/202/schema/externalDocs/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/prss.org/2.0.0/swagger.yaml#L417)
Value:
```json
"/api/epg-cd-mapping.html"
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|format |{"format":"uri"}| must match format "uri"
### Path: /paths/\~1api\~1v2\~1metapub\~1program-information\~1batch/post/responses/202/schema
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/prss.org/2.0.0/swagger.yaml#L413)
Value:
```json
{
"$ref": "#/definitions/ProgramInformationBatch",
"externalDocs": {
"description": "Find RadioDns to ContentDepot Mapping here",
"url": "/api/epg-cd-mapping.html"
}
"description": "One or several Order Identifiers or Order References separated by semicolon. Order Identifiers are integer numbers. Order References are strings - each must be percent-encoded and surrounded by double quotation marks.",
"example": "/orders/\"ref\";1001;\"Reference%3BWith%3BSpecial%3BSymbols!\";2345/",
"in": "path",
"name": "orderIdentifiers",
"required": true,
"type": "string"
}

@@ -1508,141 +645,6 @@ ```

|--------|-------|--------|
|required |{"missingProperty":"type"}| must have required property 'type'
|required |{"missingProperty":"schema"}| must have required property 'schema'
|additionalProperties |{"additionalProperty":"example"}| must NOT have additional properties
|oneOf |{"passingSchemas":null}| must match exactly one schema in oneOf
### Path: /paths/\~1api\~1v2\~1metapub\~1program-information\~1batch/post/responses/202
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/prss.org/2.0.0/swagger.yaml#L411)
Value:
```json
{
"description": "The accepted batch information that is queued for processing.",
"schema": {
"$ref": "#/definitions/ProgramInformationBatch",
"externalDocs": {
"description": "Find RadioDns to ContentDepot Mapping here",
"url": "/api/epg-cd-mapping.html"
}
}
}
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|required |{"missingProperty":"$ref"}| must have required property '$ref'
|oneOf |{"passingSchemas":null}| must match exactly one schema in oneOf
## API: trashnothing\.com (version: 1.2)
OpenApi: [3.0.0](https://spec.openapis.org/oas/v3.0.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v3.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/trashnothing.com/1.2/openapi.yaml)
API updated: 2021-07-26T08:51:53.432Z
### Path: /info/termsOfService
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/trashnothing.com/1.2/openapi.yaml#L15)
Value:
```json
"https://trashnothing.com/tos\n"
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|format |{"format":"uri-reference"}| must match format "uri-reference"
## API: twinehealth\.com (version: v7.78.1)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/twinehealth.com/v7.78.1/swagger.yaml)
API updated: 2021-06-21T12:16:53.715Z
### Path: /securityDefinitions/OAuth2
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/twinehealth.com/v7.78.1/swagger.yaml#L77)
Value:
```json
{
"description": "Fitbit Plus allows customers to access data for their organization using client credentials.\nOAuth2 is a safe and secure way to give you access.\n",
"flow": "application",
"scopes": {
"group": "access patients and data within a group",
"organization": "access patients and data within an organization"
},
"tokenUrl": "/oauth/token",
"type": "oauth2"
}
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|additionalProperties |{"additionalProperty":"flow"}| must NOT have additional properties
|required |{"missingProperty":"name"}| must have required property 'name'
|required |{"missingProperty":"authorizationUrl"}| must have required property 'authorizationUrl'
|oneOf |{"passingSchemas":null}| must match exactly one schema in oneOf
### Path: /securityDefinitions/OAuth2/flow
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/twinehealth.com/v7.78.1/swagger.yaml#L81)
Value:
```json
"application"
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|enum |{"allowedValues":["password"]}| must be equal to one of the allowed values
### Path: /securityDefinitions/OAuth2/tokenUrl
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/twinehealth.com/v7.78.1/swagger.yaml#L85)
Value:
```json
"/oauth/token"
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|format |{"format":"uri"}| must match format "uri"
## API: whapi\.com:numbers (version: 2.0)
Swagger: [2.0](https://spec.openapis.org/oas/v2.0)
[JSON Schema](https://github.com/seriousme/openapi-schema-validator/tree/master/schemas/v2.0/schema.json)
API on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/whapi.com/numbers/2.0/swagger.yaml)
API updated: 2021-06-21T12:16:53.715Z
### Path: /info/license/url
Path on Github: [link](https://github.com/APIs-guru/openapi-directory/blob/main/APIs/whapi.com/numbers/2.0/swagger.yaml#L12)
Value:
```json
"www.williamhill.com"
```
AJV errors:
|Keyword |Params |Message |
|--------|-------|--------|
|format |{"format":"uri"}| must match format "uri"

@@ -6,3 +6,3 @@ # Real world tests

The script errors on these into account via [`failed.json`](failed.json). The [`failed.md`](failed.md) contains a human readable report, including relevant links and snippets of the errors in `failed.json`.
Validation errors are registered in [`failed.json`](failed.json). The [`failed.md`](failed.md) contains a human readable report, including relevant links and snippets of the errors in `failed.json`.

@@ -9,0 +9,0 @@ Once the script completes it creates a `failed.update.json` which you can diff with `failed.json`.

// test the validator against the APIs of https://apis.guru
import { createRequire } from 'module';
import { createRequire } from "module";
const importJSON = createRequire(import.meta.url);
const localFile = (fileName) => (new URL(fileName, import.meta.url)).pathname
const localFile = (fileName) => new URL(fileName, import.meta.url).pathname;
import { Validator } from "../../index.js";
const validator = new Validator();
import { writeFileSync } from "fs";
import fetch from "node-fetch";
import { JSON_SCHEMA, load } from "js-yaml";
import { argv, exit } from "process";
import { JSON_SCHEMA, load } from "js-yaml";
import { createReport } from "./createReport.js";
const yamlOpts = { schema: JSON_SCHEMA };
const failedFile = localFile('./failed.json');
const reportFile = localFile('./failed.md');
const newFailedFile = localFile('./failed.updated.json');
const newReportFile = localFile('./failed.updated.md');
const failedFile = localFile("./failed.json");
const reportFile = localFile("./failed.md");
const newFailedFile = localFile("./failed.updated.json");
const newReportFile = localFile("./failed.updated.md");
const defaultPercentage = 10;

@@ -21,254 +20,254 @@ const failedMap = loadFailedData(failedFile);

function loadFailedData(fileName) {
const dataMap = new Map();
try {
const data = importJSON(fileName);
data.failedTests = data.failedTests || [];
data.failedTests.forEach((item) => dataMap.set(item.name, item));
return dataMap;
} catch (_) {
return dataMap;
}
const dataMap = new Map();
try {
const data = importJSON(fileName);
data.failedTests = data.failedTests || [];
data.failedTests.forEach((item) => dataMap.set(item.name, item));
return dataMap;
} catch (_) {
return dataMap;
}
}
function sample(fullMap, percentage) {
const { floor, random } = Math;
const len = fullMap.size;
const size = floor(len * (percentage / 100));
const sampleMap = new Map();
const mapKeys = Array.from(fullMap.keys());
for (let i = 0; i < size; i++) {
let index;
let key;
do {
index = floor(random() * len);
key = mapKeys[index];
} while (sampleMap.has(key));
const { floor, random } = Math;
const len = fullMap.size;
const size = floor(len * (percentage / 100));
const sampleMap = new Map();
const mapKeys = Array.from(fullMap.keys());
for (let i = 0; i < size; i++) {
let index;
let key;
do {
index = floor(random() * len);
key = mapKeys[index];
} while (sampleMap.has(key));
sampleMap.set(key, fullMap.get(key));
}
return sampleMap;
sampleMap.set(key, fullMap.get(key));
}
return sampleMap;
}
function unescapeJsonPointer(str) {
return str.replace(/~1/g, "/").replace(/~0/g, "~");
return str.replace(/~1/g, "/").replace(/~0/g, "~");
}
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}
function makeRexp(pathItem) {
const res = unescapeJsonPointer(pathItem);
return escapeRegExp(res);
const res = unescapeJsonPointer(pathItem);
return escapeRegExp(res);
}
function yamlLine(yamlSpec, path) {
const lines = yamlSpec.split("\n");
const paths = path.split("/").slice(1);
let num = 0;
for (const pathItem of paths) {
if (Number.isInteger(+pathItem) && num) {
num = findArrayItem(lines, num, pathItem);
} else {
num = findItem(lines, num, pathItem);
}
}
return num + 1;
const lines = yamlSpec.split("\n");
const paths = path.split("/").slice(1);
let num = 0;
for (const pathItem of paths) {
if (Number.isInteger(+pathItem) && num) {
num = findArrayItem(lines, num, pathItem);
} else {
num = findItem(lines, num, pathItem);
}
}
return num + 1;
}
function findArrayItem(lines, num, pathIdx) {
if (num > lines.length - 2) {
return num;
}
const firstItem = lines[num + 1];
const match = firstItem.match(/^\s*-/);
if (match === null) {
// it was not an array index, but a key
return findItem(lines, num, pathIdx);
}
const prefix = match[0];
while (pathIdx > 0) {
num++;
if (lines[num].startsWith(prefix)) {
pathIdx--;
}
}
return num + 1;
if (num > lines.length - 2) {
return num;
}
const firstItem = lines[num + 1];
const match = firstItem.match(/^\s*-/);
if (match === null) {
// it was not an array index, but a key
return findItem(lines, num, pathIdx);
}
const prefix = match[0];
let lineNum = num;
let pathIdxCtr = pathIdx;
while (pathIdxCtr > 0) {
lineNum++;
if (lines[lineNum].startsWith(prefix)) {
pathIdxCtr--;
}
}
return lineNum + 1;
}
function findItem(lines, num, pathItem) {
const token = new RegExp(`^\\s*"?${makeRexp(pathItem)}"?:`);
const maxNum = lines.length - 1;
while (!lines[num].match(token) && num < maxNum) {
num++;
}
return num;
let lineNum = num;
const token = new RegExp(`^\\s*"?${makeRexp(pathItem)}"?:`);
const maxNum = lines.length - 1;
while (!lines[lineNum].match(token) && lineNum < maxNum) {
lineNum++;
}
return lineNum;
}
function getInstanceValue(yamlSpec, path) {
if (path === "") {
return [false, "content too large"];
}
const obj = load(yamlSpec, yamlOpts);
const paths = path.split("/").slice(1);
const result = paths.reduce((o, n) => o[unescapeJsonPointer(n)], obj);
return [true, result];
if (path === "") {
return [false, "content too large to display here"];
}
const obj = load(yamlSpec, yamlOpts);
const paths = path.split("/").slice(1);
const result = paths.reduce((o, n) => o[unescapeJsonPointer(n)], obj);
return [true, result];
}
function yamlToGitHub(url) {
return url.replace(
"https://api.apis.guru/v2/specs/",
"https://github.com/APIs-guru/openapi-directory/blob/main/APIs/",
);
return url.replace(
"https://api.apis.guru/v2/specs/",
"https://github.com/APIs-guru/openapi-directory/blob/main/APIs/",
);
}
async function fetchApiList(percentage, onlyFailed = false) {
const response = await fetch("https://api.apis.guru/v2/list.json");
const response = await fetch("https://api.apis.guru/v2/list.json");
if (!response.ok) {
throw new Error("Unable to download real-world APIs from apis.guru");
}
const apiList = await response.json();
const apiListSize = Object.keys(apiList).length;
const apiMap = new Map();
for (const key in apiList) {
if (!onlyFailed || failedMap.has(key)) {
const api = apiList[key];
const latestVersion = api.versions[api.preferred];
apiMap.set(key, {
name: key,
apiVersion: api.preferred,
openApiVersion: latestVersion.openapiVer,
yamlUrl: latestVersion.swaggerYamlUrl,
jsonUrl: latestVersion.swaggerUrl,
gitHubUrl: yamlToGitHub(latestVersion.swaggerYamlUrl),
updated: latestVersion.updated,
});
}
}
if (percentage !== 100) {
console.log(
`testing a random set containing ${percentage}% of ${apiMap.size} available APIs`,
);
return [sample(apiMap, percentage), apiListSize, apiMap.size];
}
console.log(`testing ${apiMap.size} of ${apiListSize} available APIs`);
return [apiMap, apiListSize, apiMap.size];
if (!response.ok) {
throw new Error("Unable to download real-world APIs from apis.guru");
}
const apiList = await response.json();
const apiListSize = Object.keys(apiList).length;
const apiMap = new Map();
for (const key in apiList) {
if (!onlyFailed || failedMap.has(key)) {
const api = apiList[key];
const latestVersion = api.versions[api.preferred];
apiMap.set(key, {
name: key,
apiVersion: api.preferred,
openApiVersion: latestVersion.openapiVer,
yamlUrl: latestVersion.swaggerYamlUrl,
jsonUrl: latestVersion.swaggerUrl,
gitHubUrl: yamlToGitHub(latestVersion.swaggerYamlUrl),
updated: latestVersion.updated,
});
}
}
if (percentage !== 100) {
console.log(
`testing a random set containing ${percentage}% of ${apiMap.size} available APIs`,
);
return [sample(apiMap, percentage), apiListSize, apiMap.size];
}
console.log(`testing ${apiMap.size} of ${apiListSize} available APIs`);
return [apiMap, apiListSize, apiMap.size];
}
async function fetchYaml(url) {
const response = await fetch(url);
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Unable to download ${url}`);
}
return await response.text();
if (!response.ok) {
throw new Error(`Unable to download ${url}`);
}
return await response.text();
}
function writeReport(ci, totalSize, results, failed) {
const jsonFile = ci ? failedFile : newFailedFile;
const mdFile = ci ? reportFile : newReportFile;
const data = {
testDate: new Date().toISOString(),
totalApiCount: totalSize,
testedAPICount: results.total,
failedAPICount: results.invalid,
knownFailedCount: results.knownFailed,
failedTests: Array.from(failed.values()),
};
console.log(`new/updated failures found`);
console.log(`creating ${jsonFile}`);
writeFileSync(
jsonFile,
JSON.stringify(data, null, 2),
"utf8"
);
console.log(`creating new report ${mdFile}`);
writeFileSync(
mdFile,
createReport(data),
"utf8"
);
const jsonFile = ci ? failedFile : newFailedFile;
const mdFile = ci ? reportFile : newReportFile;
const data = {
testDate: new Date().toISOString(),
totalApiCount: totalSize,
testedAPICount: results.total,
failedAPICount: results.invalid,
knownFailedCount: results.knownFailed,
failedTests: Array.from(failed.values()),
};
console.log("new/updated failures found");
console.log(`creating ${jsonFile}`);
writeFileSync(jsonFile, JSON.stringify(data, null, "\t"), "utf8");
console.log(`creating new report ${mdFile}`);
writeFileSync(mdFile, createReport(data), "utf8");
}
async function doTest(apiList) {
const failed = new Map();
const results = {
total: apiList.size,
current: 0,
valid: 0,
invalid: 0,
knownFailed: 0,
};
for (const [name, api] of apiList) {
const spec = await fetchYaml(api.yamlUrl);
results.current++;
api.result = await validator.validate(spec);
if (api.result.valid === true) {
results.valid++;
} else {
results.invalid++;
api.result.errors.map((item) => {
const [res, value] = getInstanceValue(spec, item.instancePath);
item.hasInstanceValue = res;
item.instanceValue = value;
item.gitHubUrl = `${api.gitHubUrl}#L${yamlLine(
spec,
item.instancePath
)}`;
});
if (failedMap.has(name)) {
const failedApiErrors = JSON.stringify(
failedMap.get(name).result.errors
);
if (failedApiErrors === JSON.stringify(api.result.errors)) {
results.knownFailed++;
api.knownFailed = true;
}
}
failed.set(name, api);
}
console.log(JSON.stringify(results), name);
}
return { results, failed };
const failed = new Map();
const results = {
total: apiList.size,
current: 0,
valid: 0,
invalid: 0,
knownFailed: 0,
};
for (const [name, api] of apiList) {
const spec = await fetchYaml(api.yamlUrl);
results.current++;
api.result = await validator.validate(spec);
api.validatorVersion = validator.version;
api.specificationType = validator.specificationType;
api.specificationVersion = validator.specificationVersion;
if (api.result.valid === true) {
results.valid++;
} else {
results.invalid++;
api.result.errors.map((item) => {
const [res, value] = getInstanceValue(spec, item.instancePath);
item.hasInstanceValue = res;
item.instanceValue = value;
item.gitHubUrl = `${api.gitHubUrl}#L${yamlLine(
spec,
item.instancePath,
)}`;
});
if (failedMap.has(name)) {
const failedApiErrors = JSON.stringify(
failedMap.get(name).result.errors,
);
if (failedApiErrors === JSON.stringify(api.result.errors)) {
results.knownFailed++;
api.knownFailed = true;
}
}
failed.set(name, api);
}
console.log(JSON.stringify(results), name);
}
return { results, failed };
}
async function testAPIs(percentage, onlyFailed, ci) {
if (onlyFailed || ci) {
percentage = 100;
}
const [apiList, totalSize, latestSize] = await fetchApiList(
percentage,
onlyFailed,
);
const { results, failed } = await doTest(apiList);
console.log(
`Finished testing ${results.total} APIs
async function testAPIs(testPercentage, onlyFailed, ci) {
let percentage = testPercentage;
if (onlyFailed || ci) {
percentage = 100;
}
const [apiList, totalSize, latestSize] = await fetchApiList(
percentage,
onlyFailed,
);
const { results, failed } = await doTest(apiList);
console.log(
`Finished testing ${results.total} APIs
${results.invalid} tests failed of which ${results.knownFailed} were known failures`,
);
if (
results.knownFailed !== results.invalid ||
(onlyFailed && results.invalid !== results.total)
) {
const exitCode = ci ? 0 : 1;
if (percentage === 100) {
writeReport(ci, totalSize, results, failed);
}
process.exit(exitCode);
}
);
if (
failedMap.size !== results.knownFailed ||
results.knownFailed !== results.invalid ||
(onlyFailed && results.invalid !== results.total)
) {
const exitCode = ci ? 0 : 1;
if (percentage === 100) {
writeReport(ci, totalSize, results, failed);
}
process.exit(exitCode);
}
}
function parseArgs() {
const args = argv.slice(2);
const params = new Set();
const opts = ["failedOnly", "all", "ci"];
args.forEach((arg) => {
opts.forEach((opt) => {
if (`--${opt}`.startsWith(arg)) {
params.add(opt);
}
});
});
if (params.size !== args.length) {
console.log(`
const args = argv.slice(2);
const params = new Set();
const opts = ["failedOnly", "all", "ci"];
args.forEach((arg) => {
opts.forEach((opt) => {
if (`--${opt}`.startsWith(arg)) {
params.add(opt);
}
});
});
if (params.size !== args.length) {
console.log(`
usage: ${argv[1].split("/").pop()} [--failedOnly] [--all]

@@ -280,5 +279,5 @@ where:

`);
exit(1);
}
return params;
exit(1);
}
return params;
}

@@ -290,4 +289,4 @@

if (params.has("ci")) {
console.log(`Working in CI mode, overwriting results if anything changed`);
console.log("Working in CI mode, overwriting results if anything changed");
}
testAPIs(percentage, failedOnly, params.has("ci"));

@@ -1,30 +0,28 @@

import { fileURLToPath, URL } from "url";
import { test } from "tap";
import { execSync } from "child_process"
import { execSync } from "child_process";
import { strict as assert } from "node:assert/strict";
import { test } from "node:test";
import { URL, fileURLToPath } from "url";
function localFile(fileName) {
return fileURLToPath(new URL(fileName, import.meta.url));
return fileURLToPath(new URL(fileName, import.meta.url));
}
test;
test("cli does not error", (t) => {
t.plan(1);
const cli = localFile("../bin/validate-api-cli.js");
const yamlFileName = localFile(`./validation/petstore-openapi.v3.yaml`);
const result = JSON.parse(execSync(`node ${cli} ${yamlFileName}`));
t.equal(result.valid, true, "cli validation of petstore spec works")
const cli = localFile("../bin/validate-api-cli.js");
const yamlFileName = localFile("./validation/petstore-openapi.v3.yaml");
const result = JSON.parse(execSync(`node ${cli} ${yamlFileName}`));
assert.equal(result.valid, true, "cli validation of petstore spec works");
});
test("cli fails on empty spec", (t) => {
t.plan(1);
const cli = localFile("../bin/validate-api-cli.js");
const yamlFileName = localFile(`./validation/empty.json`);
t.throws(() => execSync(`node ${cli} ${yamlFileName}`));
const cli = localFile("../bin/validate-api-cli.js");
const yamlFileName = localFile("./validation/empty.json");
assert.throws(() => execSync(`node ${cli} ${yamlFileName}`));
});
test("cli fails on no spec", (t) => {
t.plan(1);
const cli = localFile("../bin/validate-api-cli.js");
t.throws(() => execSync(`node ${cli}`));
const cli = localFile("../bin/validate-api-cli.js");
assert.throws(() => execSync(`node ${cli}`));
});

@@ -1,308 +0,310 @@

import { test } from "tap";
import { strict as assert } from "node:assert/strict";
import { test } from "node:test";
import { Validator } from "../index.js";
const validator = new Validator();
const resolve = (specification) => validator.resolveRefs({ specification });
test(`non object returns undefined`, async (t) => {
const schema = "schema";
t.plan(1);
const res = resolve(schema);
t.equal(res, undefined);
test("non object returns undefined", async (t) => {
const schema = "schema";
const res = resolve(schema);
assert.equal(res, undefined);
});
test(`Local $refs`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
test("Local $refs", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
address: {
type: "object",
properties: {
street_address: { type: "string" },
city: { type: "string" },
state: { type: "string" },
subAddress: { $ref: "http://www.example.com/#/definitions/address" },
},
},
req: { required: ["billing_address"] },
},
type: "object",
properties: {
billing_address: { $ref: "#/definitions/address" },
shipping_address: { $ref: "#/definitions/address" },
}
};
t.plan(2);
const res = resolve(schema);
const ptr = res.properties.billing_address.properties;
t.equal(ptr.city.type, "string", "followed $ref without neigbor properties");
const circular = ptr.subAddress.properties;
t.equal(
circular.city.type,
"string",
"followed circular $ref without neigbor properties"
);
definitions: {
address: {
type: "object",
properties: {
street_address: { type: "string" },
city: { type: "string" },
state: { type: "string" },
subAddress: { $ref: "http://www.example.com/#/definitions/address" },
},
},
req: { required: ["billing_address"] },
},
type: "object",
properties: {
billing_address: { $ref: "#/definitions/address" },
shipping_address: { $ref: "#/definitions/address" },
},
};
const res = resolve(schema);
const ptr = res.properties.billing_address.properties;
assert.equal(
ptr.city.type,
"string",
"followed $ref without neigbor properties",
);
const circular = ptr.subAddress.properties;
assert.equal(
circular.city.type,
"string",
"followed circular $ref without neigbor properties",
);
});
test(`number in path`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
test("number in path", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
2: {
required: ["billing_address"],
},
},
$ref: "#/definitions/2",
};
t.plan(1);
const res = resolve(schema);
t.equal(res.required[0], "billing_address", "followed number in path");
definitions: {
2: {
required: ["billing_address"],
},
},
$ref: "#/definitions/2",
};
const res = resolve(schema);
assert.equal(res.required[0], "billing_address", "followed number in path");
});
test(`ref to #`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
test("ref to #", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
2: {
required: ["billing_address"],
},
},
$ref: "#",
};
t.plan(1);
const res = resolve(schema);
t.equal(res.definitions[2].required[0], "billing_address", "followed # in path");
definitions: {
2: {
required: ["billing_address"],
},
},
$ref: "#",
};
const res = resolve(schema);
assert.equal(
res.definitions[2].required[0],
"billing_address",
"followed # in path",
);
});
test(`$ref to $anchor`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
test("$ref to $anchor", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
req: {
required: ["billing_address"],
$anchor: "myAnchor",
},
},
$ref: "#myAnchor",
};
t.plan(1);
const res = resolve(schema);
t.equal(res.required[0], "billing_address", "followed $ref to $anchor");
definitions: {
req: {
required: ["billing_address"],
$anchor: "myAnchor",
},
},
$ref: "#myAnchor",
};
const res = resolve(schema);
assert.equal(res.required[0], "billing_address", "followed $ref to $anchor");
});
test(`$dynamicRef to $dynamicAnchor`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
test("$dynamicRef to $dynamicAnchor", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
req: {
required: ["billing_address"],
$dynamicAnchor: "myAnchor",
},
},
$dynamicRef: "#myAnchor",
};
t.plan(1);
const res = resolve(schema);
t.equal(res.required[0], "billing_address", "followed $ref to $anchor");
definitions: {
req: {
required: ["billing_address"],
$dynamicAnchor: "myAnchor",
},
},
$dynamicRef: "#myAnchor",
};
const res = resolve(schema);
assert.equal(res.required[0], "billing_address", "followed $ref to $anchor");
});
test(`non-existing path throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
$ref: "#/definitions/req",
};
t.plan(1);
t.throws(
() => resolve(schema),
"Error: Can't resolve http://www.example.com/#/definitions/req",
"got expected error"
);
test("non-existing path throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
$ref: "#/definitions/req",
};
assert.throws(
() => resolve(schema),
new Error(
"Can't resolve http://www.example.com/#/definitions/req, only internal refs are supported.",
),
"got expected error",
);
});
test(`non-existing leaf path throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
req: { required: ["billing_address"] },
},
$ref: "#/definitions/non-existing",
};
t.plan(1);
t.throws(
() => resolve(schema),
"Error: Can't resolve http://www.example.com/#/definitions/req",
"got expected error"
);
test("non-existing leaf path throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
req: { required: ["billing_address"] },
},
$ref: "#/definitions/non-existing",
};
assert.throws(
() => resolve(schema),
new Error(
"Can't resolve http://www.example.com/#/definitions/non-existing, only internal refs are supported.",
),
"got expected error",
);
});
test(`non-existing uri throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
req: { required: ["billing_address"] },
},
$ref: "http://www.example.com/failed#/definitions/req",
};
t.plan(1);
t.throws(
() => resolve(schema),
new Error("Can't resolve http://www.example.com/failed#/definitions/req"),
"got expected error"
);
test("non-existing uri throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
req: { required: ["billing_address"] },
},
$ref: "http://www.example.com/failed#/definitions/req",
};
assert.throws(
() => resolve(schema),
new Error(
"Can't resolve http://www.example.com/failed#/definitions/req, only internal refs are supported.",
),
"got expected error",
);
});
test(`non-existing uri without path throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
req: { required: ["billing_address"] },
},
$ref: "http://www.example.com/failed",
};
t.plan(1);
t.throws(
() => resolve(schema),
new Error("Can't resolve http://www.example.com/failed"),
"got expected error"
);
test("non-existing uri without path throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
req: { required: ["billing_address"] },
},
$ref: "http://www.example.com/failed",
};
assert.throws(
() => resolve(schema),
new Error(
"Can't resolve http://www.example.com/failed, only internal refs are supported.",
),
"got expected error",
);
});
test(`non-existing $anchor throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
$ref: "#undefinedAnchor",
};
t.plan(1);
t.throws(
() => resolve(schema),
new Error("Can't resolve http://www.example.com/#undefinedAnchor"),
"got expected error"
);
test("non-existing $anchor throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
$ref: "#undefinedAnchor",
};
assert.throws(
() => resolve(schema),
new Error(
"Can't resolve http://www.example.com/#undefinedAnchor, only internal refs are supported.",
),
"got expected error",
);
});
test(`non-existing $dynamicAnchor throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
$dynamicRef: "#undefinedAnchor",
};
t.plan(1);
t.throws(
() => resolve(schema),
new Error("Can't resolve $dynamicAnchor : '#undefinedAnchor'"),
"got expected error"
);
test("non-existing $dynamicAnchor throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
$dynamicRef: "#undefinedAnchor",
};
assert.throws(
() => resolve(schema),
new Error("Can't resolve $dynamicAnchor : '#undefinedAnchor'"),
"got expected error",
);
});
test(`non-unique $id throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
$id: "http://www.example.com/",
},
};
t.plan(1);
t.throws(
() => resolve(schema),
new Error(
"$id : 'http://www.example.com/' defined more than once at #/definitions"
),
"got expected error"
);
test("non-unique $id throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
$id: "http://www.example.com/",
},
};
assert.throws(
() => resolve(schema),
new Error(
"$id : 'http://www.example.com/' defined more than once at #/definitions",
),
"got expected error",
);
});
test(`non-unique $anchor throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
anchor_A: { $anchor: "#myAnchor" },
anchor_B: { $anchor: "#myAnchor" },
},
};
t.plan(1);
t.throws(
() => resolve(schema),
new Error(
"$anchor : '#myAnchor' defined more than once at '#/definitions/anchor_B'"
),
"got expected error"
);
test("non-unique $anchor throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
anchor_A: { $anchor: "#myAnchor" },
anchor_B: { $anchor: "#myAnchor" },
},
};
assert.throws(
() => resolve(schema),
new Error(
"$anchor : '#myAnchor' defined more than once at '#/definitions/anchor_B'",
),
"got expected error",
);
});
test(`non-unique $dynamicAnchor throws error`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
anchor_A: { $dynamicAnchor: "#myAnchor" },
anchor_B: { $dynamicAnchor: "#myAnchor" },
},
};
t.plan(1);
t.throws(
() => resolve(schema),
new Error(
"$dynamicAnchor : '#myAnchor' defined more than once at '#/definitions/anchor_B'"
),
"got expected error"
);
test("non-unique $dynamicAnchor throws error", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
anchor_A: { $dynamicAnchor: "#myAnchor" },
anchor_B: { $dynamicAnchor: "#myAnchor" },
},
};
assert.throws(
() => resolve(schema),
new Error(
"$dynamicAnchor : '#myAnchor' defined more than once at '#/definitions/anchor_B'",
),
"got expected error",
);
});
test(`correctly URL encoded URI`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
test("correctly URL encoded URI", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
"/path{id}": {
required: ["billing_address"],
},
},
$ref: "%23%2Fdefinitions%2F~1path%7Bid%7D", // "#/definitions/~1path{id}"
};
t.plan(1);
const res = resolve(schema);
t.equal(
res.required[0],
"billing_address",
"followed $ref to URL encoded path"
);
definitions: {
"/path{id}": {
required: ["billing_address"],
},
},
$ref: "%23%2Fdefinitions%2F~1path%7Bid%7D", // "#/definitions/~1path{id}"
};
const res = resolve(schema);
assert.equal(
res.required[0],
"billing_address",
"followed $ref to URL encoded path",
);
});
test(`incorrectly URL encoded URI also works (normally blocked by schema format)`, async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
test("incorrectly URL encoded URI also works (normally blocked by schema format)", async (t) => {
const schema = {
$id: "http://www.example.com/",
$schema: "http://json-schema.org/draft-07/schema#",
definitions: {
"/path{id}": {
required: ["billing_address"],
},
},
$ref: "#/definitions/~1path{id}",
};
t.plan(1);
const res = resolve(schema);
t.equal(
res.required[0],
"billing_address",
"followed $ref to URL encoded path"
);
definitions: {
"/path{id}": {
required: ["billing_address"],
},
},
$ref: "#/definitions/~1path{id}",
};
const res = resolve(schema);
assert.equal(
res.required[0],
"billing_address",
"followed $ref to URL encoded path",
);
});

@@ -1,21 +0,22 @@

import { fileURLToPath, URL } from "url";
import { test } from "tap";
import { Validator } from "../index.js";
import { readFileSync } from "fs";
import { strict as assert } from "node:assert/strict";
import { test } from "node:test";
import { URL, fileURLToPath } from "url";
import { readFile } from "fs/promises";
import { Validator } from "../index.js";
function localFile(fileName) {
return fileURLToPath(new URL(fileName, import.meta.url));
return fileURLToPath(new URL(fileName, import.meta.url));
}
function importJSON(file) {
return JSON.parse(readFileSync(localFile(file)));
return JSON.parse(readFileSync(localFile(file)));
}
const emptySpec = importJSON(`./validation/empty.json`);
const invalidSpec = importJSON(`./validation/invalid-spec.json`);
const yamlFileName = localFile(`./validation/petstore-openapi.v3.yaml`);
const mainSpecYamlFileName = localFile(`./validation/main-spec.v3.yaml`);
const subSpecYamlFileName = localFile(`./validation/sub-spec.v3.yaml`);
const subSpec2YamlFileName = localFile(`./validation/sub-spec2.v3.yaml`);
const emptySpec = importJSON("./validation/empty.json");
const invalidSpec = importJSON("./validation/invalid-spec.json");
const yamlFileName = localFile("./validation/petstore-openapi.v3.yaml");
const mainSpecYamlFileName = localFile("./validation/main-spec.v3.yaml");
const subSpecYamlFileName = localFile("./validation/sub-spec.v3.yaml");
const subSpec2YamlFileName = localFile("./validation/sub-spec2.v3.yaml");
const subSpecUri = "http://www.example.com/subspec";

@@ -26,17 +27,23 @@ const subSpecUri2 = "subspec2";

async function testVersion(version) {
test(`version ${version} works`, async (t) => {
t.plan(2);
const petStoreSpec = importJSON(`./v${version}/petstore.json`);
const validator = new Validator();
test(`version ${version} works`, async (t) => {
const petStoreSpec = importJSON(`./v${version}/petstore.json`);
const validator = new Validator();
const res = await validator.validate(petStoreSpec);
t.equal(res.valid, true, "petstore spec is valid");
const ver = validator.version;
t.equal(ver, version, "petstore spec version matches expected version");
});
const res = await validator.validate(petStoreSpec);
assert.equal(res.valid, true, "petstore spec is valid");
const ver = validator.version;
assert.equal(
ver,
version,
"petstore spec version matches expected version",
);
});
}
test(`Validator.supportedVersions should be a Set`, (t) => {
t.plan(1);
t.type(Validator.supportedVersions, Set);
test("Validator.supportedVersions should be a Set", (t) => {
assert.equal(
Validator.supportedVersions instanceof Set,
true,
"Validator.supportedVersions is a Set",
);
});

@@ -46,202 +53,193 @@

test(`empty specification should fail`, async (t) => {
t.plan(2);
const validator = new Validator();
const res = await validator.validate(emptySpec);
t.equal(res.valid, false, "empty spec is invalid");
t.equal(
res.errors,
"Cannot find supported swagger/openapi version in specification, version must be a string.",
"correct error message",
);
test("empty specification should fail", async (t) => {
const validator = new Validator();
const res = await validator.validate(emptySpec);
assert.equal(res.valid, false, "empty spec is invalid");
assert.equal(
res.errors,
"Cannot find supported swagger/openapi version in specification, version must be a string.",
"correct error message",
);
});
test(`defect specification should fail`, async (t) => {
t.plan(2);
const validator = new Validator();
const res = await validator.validate(invalidSpec);
t.equal(res.valid, false, "defect specification is invalid");
t.type(res.errors, Array, "got array with errors");
test("defect specification should fail", async (t) => {
const validator = new Validator();
const res = await validator.validate(invalidSpec);
assert.equal(res.valid, false, "defect specification is invalid");
assert.equal(res.errors instanceof Array, true, "got array with errors");
});
test(`undefined specification should fail`, async (t) => {
t.plan(2);
const validator = new Validator();
const res = await validator.validate();
t.equal(res.valid, false, "undefined specification is invalid");
t.equal(
res.errors,
"Cannot find JSON, YAML or filename in data",
"correct error message",
);
test("undefined specification should fail", async (t) => {
const validator = new Validator();
const res = await validator.validate();
assert.equal(res.valid, false, "undefined specification is invalid");
assert.equal(
res.errors,
"Cannot find JSON, YAML or filename in data",
"correct error message",
);
});
test(`yaml specification as string works`, async (t) => {
t.plan(2);
const yamlSpec = await readFile(yamlFileName, "utf-8");
const validator = new Validator();
test("yaml specification as string works", async (t) => {
const yamlSpec = await readFile(yamlFileName, "utf-8");
const validator = new Validator();
const res = await validator.validate(yamlSpec);
t.equal(res.valid, true, "yaml spec as string is valid");
const ver = validator.version;
t.equal(ver, "3.0", "yaml spec version matches expected version");
const res = await validator.validate(yamlSpec);
assert.equal(res.valid, true, "yaml spec as string is valid");
const valVer = validator.version;
assert.equal(
valVer,
"3.0",
"yaml validator version matches expected version",
);
const specType = validator.specificationType;
assert.equal(specType, "openapi", "yaml spec type matches expected version");
const specVersion = validator.specificationVersion;
assert.equal(specVersion, "3.0.0", "yaml spec type matches expected version");
});
test(`multiple consecutive validations work`, async (t) => {
t.plan(3);
const yamlSpec = await readFile(yamlFileName, "utf-8");
const validator = new Validator();
test("multiple consecutive validations work", async (t) => {
const yamlSpec = await readFile(yamlFileName, "utf-8");
const validator = new Validator();
const res = await validator.validate(yamlSpec);
t.equal(res.valid, true, "yaml spec as string is valid in round 1");
const res2 = await validator.validate(yamlSpec);
t.equal(res2.valid, true, "yaml spec as string is valid in round 2");
const ver = validator.version;
t.equal(ver, "3.0", "yaml spec version matches expected version");
const res = await validator.validate(yamlSpec);
assert.equal(res.valid, true, "yaml spec as string is valid in round 1");
const res2 = await validator.validate(yamlSpec);
assert.equal(res2.valid, true, "yaml spec as string is valid in round 2");
const ver = validator.version;
assert.equal(ver, "3.0", "yaml spec version matches expected version");
});
test(`Invalid yaml specification as string gives an error`, async (t) => {
t.plan(2);
const yamlSpec = `
test("Invalid yaml specification as string gives an error", async (t) => {
const yamlSpec = `
yaml : : :
yaml : : :
`;
const validator = new Validator();
const validator = new Validator();
const res = await validator.validate(yamlSpec);
t.equal(res.valid, false, "validation fails as expected");
t.equal(
res.errors,
"Cannot find JSON, YAML or filename in data",
"error message matches expection",
);
const res = await validator.validate(yamlSpec);
assert.equal(res.valid, false, "validation fails as expected");
assert.equal(
res.errors,
"Cannot find JSON, YAML or filename in data",
"error message matches expection",
);
});
test(`yaml specification as filename works`, async (t) => {
t.plan(2);
const validator = new Validator();
test("yaml specification as filename works", async (t) => {
const validator = new Validator();
const res = await validator.validate(yamlFileName);
t.equal(res.valid, true, "yaml spec as filename is valid");
const ver = validator.version;
t.equal(ver, "3.0", "yaml spec version matches expected version");
const res = await validator.validate(yamlFileName);
assert.equal(res.valid, true, "yaml spec as filename is valid");
const ver = validator.version;
assert.equal(ver, "3.0", "yaml spec version matches expected version");
});
test(`original petstore spec works`, async (t) => {
t.plan(3);
const validator = new Validator();
const petStoreSpec = importJSON(`./validation/petstore-swagger.v2.json`);
const res = await validator.validate(petStoreSpec);
t.equal(res.valid, true, "original petstore spec is valid");
const ver = validator.version;
t.equal(
ver,
"2.0",
"original petstore spec version matches expected version",
);
const resolvedSpec = validator.resolveRefs();
t.equal(
resolvedSpec.paths["/pet"].post.parameters[0].schema.required[0],
"name",
"$refs are correctly resolved",
);
test("original petstore spec works", async (t) => {
const validator = new Validator();
const petStoreSpec = importJSON("./validation/petstore-swagger.v2.json");
const res = await validator.validate(petStoreSpec);
assert.equal(res.valid, true, "original petstore spec is valid");
const ver = validator.version;
assert.equal(
ver,
"2.0",
"original petstore spec version matches expected version",
);
const resolvedSpec = validator.resolveRefs();
assert.equal(
resolvedSpec.paths["/pet"].post.parameters[0].schema.required[0],
"name",
"$refs are correctly resolved",
);
});
test(`original petstore spec works with AJV strict:"log" option`, async (t) => {
t.plan(4);
let logcount = 0;
const log = () => logcount++;
const logger = { log, warn: log, error: log };
const validator = new Validator({ strict: "log", logger });
const petStoreSpec = importJSON(`./validation/petstore-swagger.v2.json`);
const res = await validator.validate(petStoreSpec);
t.equal(res.valid, true, "original petstore spec is valid");
const ver = validator.version;
t.equal(
ver,
"2.0",
"original petstore spec version matches expected version",
);
const resolvedSpec = validator.resolveRefs();
t.equal(
resolvedSpec.paths["/pet"].post.parameters[0].schema.required[0],
"name",
"$refs are correctly resolved",
);
t.equal(logcount > 0, true, "warnings are being logged");
let logcount = 0;
const log = () => logcount++;
const logger = { log, warn: log, error: log };
const validator = new Validator({ strict: "log", logger });
const petStoreSpec = importJSON("./validation/petstore-swagger.v2.json");
const res = await validator.validate(petStoreSpec);
assert.equal(res.valid, true, "original petstore spec is valid");
const ver = validator.version;
assert.equal(
ver,
"2.0",
"original petstore spec version matches expected version",
);
const resolvedSpec = validator.resolveRefs();
assert.equal(
resolvedSpec.paths["/pet"].post.parameters[0].schema.required[0],
"name",
"$refs are correctly resolved",
);
assert.equal(logcount > 0, true, "warnings are being logged");
});
test(`Invalid filename returns an error`, async (t) => {
t.plan(2);
const validator = new Validator();
test("Invalid filename returns an error", async (t) => {
const validator = new Validator();
const res = await validator.validate("nonExistingFilename");
t.equal(res.valid, false, "validation fails as expected");
t.equal(
res.errors,
"Cannot find JSON, YAML or filename in data",
"error message matches expection",
);
const res = await validator.validate("nonExistingFilename");
assert.equal(res.valid, false, "validation fails as expected");
assert.equal(
res.errors,
"Cannot find JSON, YAML or filename in data",
"error message matches expection",
);
});
test(`addSpecRef: non string URI returns an error`, (t) => {
t.plan(1);
const validator = new Validator();
t.rejects(
validator.addSpecRef(subSpecYamlFileName, null),
"uri parameter or $id attribute must be a string",
"error message matches expection",
{}
);
test("addSpecRef: non string URI throws an error", async (t) => {
const validator = new Validator();
assert.rejects(
validator.addSpecRef(subSpecYamlFileName, null),
new Error("uri parameter or $id attribute must be a string"),
"error message matches expection",
);
});
test(`addSpecRef: Invalid filename returns an error`, (t) => {
t.plan(1);
const validator = new Validator();
t.rejects(
validator.addSpecRef("nonExistingFilename", "extraUri"),
"Cannot find JSON, YAML or filename in data",
"error message matches expection",
{}
);
test("addSpecRef: Invalid filename returns an error", async (t) => {
const validator = new Validator();
assert.rejects(
validator.addSpecRef("nonExistingFilename", "extraUri"),
new Error("Cannot find JSON, YAML or filename in data"),
"error message matches expection",
);
});
test(`addSpecRef: no uri and no $id attribute returns an error`, (t) => {
t.plan(1);
const validator = new Validator();
t.rejects(
validator.addSpecRef(subSpecYamlFileName),
"uri parameter or $id attribute must be present",
"error message matches expection",
{}
);
test("addSpecRef: no uri and no $id attribute returns an error", (t) => {
const validator = new Validator();
assert.rejects(
validator.addSpecRef(subSpecYamlFileName),
new Error("uri parameter or $id attribute must be a string"),
"error message matches expection",
);
});
test(`addSpecRef works`, async (t) => {
t.plan(5);
const validator = new Validator();
await validator.addSpecRef(subSpecYamlFileName, subSpecUri);
await validator.addSpecRef(subSpec2YamlFileName);
const res = await validator.validate(mainSpecYamlFileName);
t.equal(res.valid, true, "main spec + subspec is valid");
t.equal(
validator.specification[inlinedRefs][subSpecUri].components.requestBodies
.Pet.required,
true,
);
t.equal(
validator.specification[inlinedRefs][subSpecUri2].get.summary,
"Finds Pets by status",
);
const resolvedSpec = validator.resolveRefs();
t.equal(
resolvedSpec.paths["/pet"].post.requestBody.required,
true,
"$refs from main spec to sub spec are correctly resolved",
);
t.equal(
resolvedSpec.paths["/pet/findByStatus"].get.summary,
"Finds Pets by status",
"$refs from main spec to sub2 spec are correctly resolved",
);
test("addSpecRef works", async (t) => {
const validator = new Validator();
await validator.addSpecRef(subSpecYamlFileName, subSpecUri);
await validator.addSpecRef(subSpec2YamlFileName);
const res = await validator.validate(mainSpecYamlFileName);
assert.equal(res.valid, true, "main spec + subspec is valid");
assert.equal(
validator.specification[inlinedRefs][subSpecUri].components.requestBodies
.Pet.required,
true,
);
assert.equal(
validator.specification[inlinedRefs][subSpecUri2].get.summary,
"Finds Pets by status",
);
const resolvedSpec = validator.resolveRefs();
assert.equal(
resolvedSpec.paths["/pet"].post.requestBody.required,
true,
"$refs from main spec to sub spec are correctly resolved",
);
assert.equal(
resolvedSpec.paths["/pet/findByStatus"].get.summary,
"Finds Pets by status",
"$refs from main spec to sub2 spec are correctly resolved",
);
});
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"license": {
"name": "MIT"
}
},
"host": "petstore.swagger.io",
"basePath": "/v1",
"schemes": [
"http"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"tags": [
"pets"
],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"type": "integer",
"format": "int32"
}
],
"responses": {
"200": {
"description": "An paged array of pets",
"headers": {
"x-next": {
"type": "string",
"description": "A link to the next page of responses"
}
},
"schema": {
"$ref": "#/definitions/Pets"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": [
"pets"
],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": [
"pets"
],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"type": "string"
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"schema": {
"$ref": "#/definitions/Pets"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
}
}
},
"definitions": {
"Pet": {
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
},
"Error": {
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"license": {
"name": "MIT"
}
},
"host": "petstore.swagger.io",
"basePath": "/v1",
"schemes": ["http"],
"consumes": ["application/json"],
"produces": ["application/json"],
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"tags": ["pets"],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"type": "integer",
"format": "int32"
}
],
"responses": {
"200": {
"description": "An paged array of pets",
"headers": {
"x-next": {
"type": "string",
"description": "A link to the next page of responses"
}
},
"schema": {
"$ref": "#/definitions/Pets"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": ["pets"],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": ["pets"],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"type": "string"
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"schema": {
"$ref": "#/definitions/Pets"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
}
}
},
"definitions": {
"Pet": {
"required": ["id", "name"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
},
"Error": {
"required": ["code", "message"],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
{
"openapi": "3.0.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"license": {
"name": "MIT"
}
},
"servers": [
{
"url": "http://petstore.swagger.io/v1"
}
],
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"tags": [
"pets"
],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "A paged array of pets",
"headers": {
"x-next": {
"description": "A link to the next page of responses",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": [
"pets"
],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": [
"pets"
],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
"Error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
}
"openapi": "3.0.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"license": {
"name": "MIT"
}
},
"servers": [
{
"url": "http://petstore.swagger.io/v1"
}
],
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"tags": ["pets"],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "A paged array of pets",
"headers": {
"x-next": {
"description": "A link to the next page of responses",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": ["pets"],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": ["pets"],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": ["id", "name"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
"Error": {
"type": "object",
"required": ["code", "message"],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
}
{
"openapi": "3.1.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"license": {
"name": "MIT",
"url": "https://opensource.org/licenses/MIT"
}
},
"servers": [
{
"url": "http://petstore.swagger.io/v1"
}
],
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"tags": [
"pets"
],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "A paged array of pets",
"headers": {
"x-next": {
"description": "A link to the next page of responses",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": [
"pets"
],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": [
"pets"
],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
"Error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
}
"openapi": "3.1.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"license": {
"name": "MIT",
"url": "https://opensource.org/licenses/MIT"
}
},
"servers": [
{
"url": "http://petstore.swagger.io/v1"
}
],
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"tags": ["pets"],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "A paged array of pets",
"headers": {
"x-next": {
"description": "A link to the next page of responses",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": ["pets"],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": ["pets"],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": ["id", "name"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
"Error": {
"type": "object",
"required": ["code", "message"],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
}

@@ -1,1 +0,1 @@

{}
{}
{
"openapi": "3.1.0",
"servers": [
{
"url": "http://localhost/v2"
}
],
"security": [
{
"skipped": []
}
],
"paths": {
"/pathParam/{id}": {
"get": {
"operationId": "getPathParam",
"summary": "Test path parameters",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "ok"
}
}
}
}
}
}
"openapi": "3.1.0",
"servers": [
{
"url": "http://localhost/v2"
}
],
"security": [
{
"skipped": []
}
],
"paths": {
"/pathParam/{id}": {
"get": {
"operationId": "getPathParam",
"summary": "Test path parameters",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "ok"
}
}
}
}
}
}
{
"swagger": "2.0",
"info": {
"description":
"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
"version": "1.0.0",
"title": "Swagger Petstore",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"email": "apiteam@swagger.io"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"host": "petstore.swagger.io",
"basePath": "/v2",
"tags": [
{
"name": "pet",
"description": "Everything about your Pets",
"externalDocs": {
"description": "Find out more",
"url": "http://swagger.io"
}
},
{
"name": "store",
"description": "Access to Petstore orders"
},
{
"name": "user",
"description": "Operations about user",
"externalDocs": {
"description": "Find out more about our store",
"url": "http://swagger.io"
}
}
],
"schemes": ["http"],
"paths": {
"/pet": {
"post": {
"tags": ["pet"],
"summary": "Add a new pet to the store",
"description": "",
"operationId": "addPet",
"consumes": ["application/json", "application/xml"],
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"schema": {
"$ref": "#/definitions/Pet"
}
}
],
"responses": {
"405": {
"description": "Invalid input"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
},
"put": {
"tags": ["pet"],
"summary": "Update an existing pet",
"description": "",
"operationId": "updatePet",
"consumes": ["application/json", "application/xml"],
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"schema": {
"$ref": "#/definitions/Pet"
}
}
],
"responses": {
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Pet not found"
},
"405": {
"description": "Validation exception"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
}
},
"/pet/findByStatus": {
"get": {
"tags": ["pet"],
"summary": "Finds Pets by status",
"description":
"Multiple status values can be provided with comma separated strings",
"operationId": "findPetsByStatus",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "status",
"in": "query",
"description":
"Status values that need to be considered for filter",
"required": true,
"type": "array",
"items": {
"type": "string",
"enum": ["available", "pending", "sold"],
"default": "available"
},
"collectionFormat": "multi"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
},
"400": {
"description": "Invalid status value"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
}
},
"/pet/findByTags": {
"get": {
"tags": ["pet"],
"summary": "Finds Pets by tags",
"description":
"Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.",
"operationId": "findPetsByTags",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "tags",
"in": "query",
"description": "Tags to filter by",
"required": true,
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "multi"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
},
"400": {
"description": "Invalid tag value"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
],
"deprecated": true
}
},
"/pet/{petId}": {
"get": {
"tags": ["pet"],
"summary": "Find pet by ID",
"description": "Returns a single pet",
"operationId": "getPetById",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "petId",
"in": "path",
"description": "ID of pet to return",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/Pet"
}
},
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Pet not found"
}
},
"security": [
{
"api_key": []
}
]
},
"post": {
"tags": ["pet"],
"summary": "Updates a pet in the store with form data",
"description": "",
"operationId": "updatePetWithForm",
"consumes": ["application/x-www-form-urlencoded"],
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "petId",
"in": "path",
"description": "ID of pet that needs to be updated",
"required": true,
"type": "integer",
"format": "int64"
},
{
"name": "name",
"in": "formData",
"description": "Updated name of the pet",
"required": false,
"type": "string"
},
{
"name": "status",
"in": "formData",
"description": "Updated status of the pet",
"required": false,
"type": "string"
}
],
"responses": {
"405": {
"description": "Invalid input"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
},
"delete": {
"tags": ["pet"],
"summary": "Deletes a pet",
"description": "",
"operationId": "deletePet",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "api_key",
"in": "header",
"required": false,
"type": "string"
},
{
"name": "petId",
"in": "path",
"description": "Pet id to delete",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Pet not found"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
}
},
"/pet/{petId}/uploadImage": {
"post": {
"tags": ["pet"],
"summary": "uploads an image",
"description": "",
"operationId": "uploadFile",
"consumes": ["multipart/form-data"],
"produces": ["application/json"],
"parameters": [
{
"name": "petId",
"in": "path",
"description": "ID of pet to update",
"required": true,
"type": "integer",
"format": "int64"
},
{
"name": "additionalMetadata",
"in": "formData",
"description": "Additional data to pass to server",
"required": false,
"type": "string"
},
{
"name": "file",
"in": "formData",
"description": "file to upload",
"required": false,
"type": "file"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/ApiResponse"
}
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
}
},
"/store/inventory": {
"get": {
"tags": ["store"],
"summary": "Returns pet inventories by status",
"description": "Returns a map of status codes to quantities",
"operationId": "getInventory",
"produces": ["application/json"],
"parameters": [],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "object",
"additionalProperties": {
"type": "integer",
"format": "int32"
}
}
}
},
"security": [
{
"api_key": []
}
]
}
},
"/store/order": {
"post": {
"tags": ["store"],
"summary": "Place an order for a pet",
"description": "",
"operationId": "placeOrder",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "order placed for purchasing the pet",
"required": true,
"schema": {
"$ref": "#/definitions/Order"
}
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/Order"
}
},
"400": {
"description": "Invalid Order"
}
}
}
},
"/store/order/{orderId}": {
"get": {
"tags": ["store"],
"summary": "Find purchase order by ID",
"description":
"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions",
"operationId": "getOrderById",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "orderId",
"in": "path",
"description": "ID of pet that needs to be fetched",
"required": true,
"type": "integer",
"maximum": 10,
"minimum": 1,
"format": "int64"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/Order"
}
},
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Order not found"
}
}
},
"delete": {
"tags": ["store"],
"summary": "Delete purchase order by ID",
"description":
"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors",
"operationId": "deleteOrder",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "orderId",
"in": "path",
"description": "ID of the order that needs to be deleted",
"required": true,
"type": "integer",
"minimum": 1,
"format": "int64"
}
],
"responses": {
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Order not found"
}
}
}
},
"/user": {
"post": {
"tags": ["user"],
"summary": "Create user",
"description": "This can only be done by the logged in user.",
"operationId": "createUser",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Created user object",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
},
"/user/createWithArray": {
"post": {
"tags": ["user"],
"summary": "Creates list of users with given input array",
"description": "",
"operationId": "createUsersWithArrayInput",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "List of user object",
"required": true,
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/User"
}
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
},
"/user/createWithList": {
"post": {
"tags": ["user"],
"summary": "Creates list of users with given input array",
"description": "",
"operationId": "createUsersWithListInput",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "List of user object",
"required": true,
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/User"
}
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
},
"/user/login": {
"get": {
"tags": ["user"],
"summary": "Logs user into the system",
"description": "",
"operationId": "loginUser",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "username",
"in": "query",
"description": "The user name for login",
"required": true,
"type": "string"
},
{
"name": "password",
"in": "query",
"description": "The password for login in clear text",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "string"
},
"headers": {
"X-Rate-Limit": {
"type": "integer",
"format": "int32",
"description": "calls per hour allowed by the user"
},
"X-Expires-After": {
"type": "string",
"format": "date-time",
"description": "date in UTC when token expires"
}
}
},
"400": {
"description": "Invalid username/password supplied"
}
}
}
},
"/user/logout": {
"get": {
"tags": ["user"],
"summary": "Logs out current logged in user session",
"description": "",
"operationId": "logoutUser",
"produces": ["application/xml", "application/json"],
"parameters": [],
"responses": {
"default": {
"description": "successful operation"
}
}
}
},
"/user/{username}": {
"get": {
"tags": ["user"],
"summary": "Get user by user name",
"description": "",
"operationId": "getUserByName",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "username",
"in": "path",
"description":
"The name that needs to be fetched. Use user1 for testing. ",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Invalid username supplied"
},
"404": {
"description": "User not found"
}
}
},
"put": {
"tags": ["user"],
"summary": "Updated user",
"description": "This can only be done by the logged in user.",
"operationId": "updateUser",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "username",
"in": "path",
"description": "name that need to be updated",
"required": true,
"type": "string"
},
{
"in": "body",
"name": "body",
"description": "Updated user object",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"400": {
"description": "Invalid user supplied"
},
"404": {
"description": "User not found"
}
}
},
"delete": {
"tags": ["user"],
"summary": "Delete user",
"description": "This can only be done by the logged in user.",
"operationId": "deleteUser",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "username",
"in": "path",
"description": "The name that needs to be deleted",
"required": true,
"type": "string"
}
],
"responses": {
"400": {
"description": "Invalid username supplied"
},
"404": {
"description": "User not found"
}
}
}
}
},
"securityDefinitions": {
"petstore_auth": {
"type": "oauth2",
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog",
"flow": "implicit",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
},
"api_key": {
"type": "apiKey",
"name": "api_key",
"in": "header"
}
},
"definitions": {
"Order": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"petId": {
"type": "integer",
"format": "int64"
},
"quantity": {
"type": "integer",
"format": "int32"
},
"shipDate": {
"type": "string",
"format": "date-time"
},
"status": {
"type": "string",
"description": "Order Status",
"enum": ["placed", "approved", "delivered"]
},
"complete": {
"type": "boolean",
"default": false
}
},
"xml": {
"name": "Order"
}
},
"Category": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
}
},
"xml": {
"name": "Category"
}
},
"User": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"email": {
"type": "string"
},
"password": {
"type": "string"
},
"phone": {
"type": "string"
},
"userStatus": {
"type": "integer",
"format": "int32",
"description": "User Status"
}
},
"xml": {
"name": "User"
}
},
"Tag": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
}
},
"xml": {
"name": "Tag"
}
},
"Pet": {
"type": "object",
"required": ["name", "photoUrls"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"category": {
"$ref": "#/definitions/Category"
},
"name": {
"type": "string",
"example": "doggie"
},
"photoUrls": {
"type": "array",
"xml": {
"name": "photoUrl",
"wrapped": true
},
"items": {
"type": "string"
}
},
"tags": {
"type": "array",
"xml": {
"name": "tag",
"wrapped": true
},
"items": {
"$ref": "#/definitions/Tag"
}
},
"status": {
"type": "string",
"description": "pet status in the store",
"enum": ["available", "pending", "sold"]
}
},
"xml": {
"name": "Pet"
}
},
"ApiResponse": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"type": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
},
"externalDocs": {
"description": "Find out more about Swagger",
"url": "http://swagger.io"
}
"swagger": "2.0",
"info": {
"description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
"version": "1.0.0",
"title": "Swagger Petstore",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"email": "apiteam@swagger.io"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"host": "petstore.swagger.io",
"basePath": "/v2",
"tags": [
{
"name": "pet",
"description": "Everything about your Pets",
"externalDocs": {
"description": "Find out more",
"url": "http://swagger.io"
}
},
{
"name": "store",
"description": "Access to Petstore orders"
},
{
"name": "user",
"description": "Operations about user",
"externalDocs": {
"description": "Find out more about our store",
"url": "http://swagger.io"
}
}
],
"schemes": ["http"],
"paths": {
"/pet": {
"post": {
"tags": ["pet"],
"summary": "Add a new pet to the store",
"description": "",
"operationId": "addPet",
"consumes": ["application/json", "application/xml"],
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"schema": {
"$ref": "#/definitions/Pet"
}
}
],
"responses": {
"405": {
"description": "Invalid input"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
},
"put": {
"tags": ["pet"],
"summary": "Update an existing pet",
"description": "",
"operationId": "updatePet",
"consumes": ["application/json", "application/xml"],
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"schema": {
"$ref": "#/definitions/Pet"
}
}
],
"responses": {
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Pet not found"
},
"405": {
"description": "Validation exception"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
}
},
"/pet/findByStatus": {
"get": {
"tags": ["pet"],
"summary": "Finds Pets by status",
"description": "Multiple status values can be provided with comma separated strings",
"operationId": "findPetsByStatus",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "status",
"in": "query",
"description": "Status values that need to be considered for filter",
"required": true,
"type": "array",
"items": {
"type": "string",
"enum": ["available", "pending", "sold"],
"default": "available"
},
"collectionFormat": "multi"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
},
"400": {
"description": "Invalid status value"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
}
},
"/pet/findByTags": {
"get": {
"tags": ["pet"],
"summary": "Finds Pets by tags",
"description": "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.",
"operationId": "findPetsByTags",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "tags",
"in": "query",
"description": "Tags to filter by",
"required": true,
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "multi"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
},
"400": {
"description": "Invalid tag value"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
],
"deprecated": true
}
},
"/pet/{petId}": {
"get": {
"tags": ["pet"],
"summary": "Find pet by ID",
"description": "Returns a single pet",
"operationId": "getPetById",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "petId",
"in": "path",
"description": "ID of pet to return",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/Pet"
}
},
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Pet not found"
}
},
"security": [
{
"api_key": []
}
]
},
"post": {
"tags": ["pet"],
"summary": "Updates a pet in the store with form data",
"description": "",
"operationId": "updatePetWithForm",
"consumes": ["application/x-www-form-urlencoded"],
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "petId",
"in": "path",
"description": "ID of pet that needs to be updated",
"required": true,
"type": "integer",
"format": "int64"
},
{
"name": "name",
"in": "formData",
"description": "Updated name of the pet",
"required": false,
"type": "string"
},
{
"name": "status",
"in": "formData",
"description": "Updated status of the pet",
"required": false,
"type": "string"
}
],
"responses": {
"405": {
"description": "Invalid input"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
},
"delete": {
"tags": ["pet"],
"summary": "Deletes a pet",
"description": "",
"operationId": "deletePet",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "api_key",
"in": "header",
"required": false,
"type": "string"
},
{
"name": "petId",
"in": "path",
"description": "Pet id to delete",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Pet not found"
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
}
},
"/pet/{petId}/uploadImage": {
"post": {
"tags": ["pet"],
"summary": "uploads an image",
"description": "",
"operationId": "uploadFile",
"consumes": ["multipart/form-data"],
"produces": ["application/json"],
"parameters": [
{
"name": "petId",
"in": "path",
"description": "ID of pet to update",
"required": true,
"type": "integer",
"format": "int64"
},
{
"name": "additionalMetadata",
"in": "formData",
"description": "Additional data to pass to server",
"required": false,
"type": "string"
},
{
"name": "file",
"in": "formData",
"description": "file to upload",
"required": false,
"type": "file"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/ApiResponse"
}
}
},
"security": [
{
"petstore_auth": ["write:pets", "read:pets"]
}
]
}
},
"/store/inventory": {
"get": {
"tags": ["store"],
"summary": "Returns pet inventories by status",
"description": "Returns a map of status codes to quantities",
"operationId": "getInventory",
"produces": ["application/json"],
"parameters": [],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "object",
"additionalProperties": {
"type": "integer",
"format": "int32"
}
}
}
},
"security": [
{
"api_key": []
}
]
}
},
"/store/order": {
"post": {
"tags": ["store"],
"summary": "Place an order for a pet",
"description": "",
"operationId": "placeOrder",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "order placed for purchasing the pet",
"required": true,
"schema": {
"$ref": "#/definitions/Order"
}
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/Order"
}
},
"400": {
"description": "Invalid Order"
}
}
}
},
"/store/order/{orderId}": {
"get": {
"tags": ["store"],
"summary": "Find purchase order by ID",
"description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions",
"operationId": "getOrderById",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "orderId",
"in": "path",
"description": "ID of pet that needs to be fetched",
"required": true,
"type": "integer",
"maximum": 10,
"minimum": 1,
"format": "int64"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/Order"
}
},
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Order not found"
}
}
},
"delete": {
"tags": ["store"],
"summary": "Delete purchase order by ID",
"description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors",
"operationId": "deleteOrder",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "orderId",
"in": "path",
"description": "ID of the order that needs to be deleted",
"required": true,
"type": "integer",
"minimum": 1,
"format": "int64"
}
],
"responses": {
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Order not found"
}
}
}
},
"/user": {
"post": {
"tags": ["user"],
"summary": "Create user",
"description": "This can only be done by the logged in user.",
"operationId": "createUser",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Created user object",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
},
"/user/createWithArray": {
"post": {
"tags": ["user"],
"summary": "Creates list of users with given input array",
"description": "",
"operationId": "createUsersWithArrayInput",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "List of user object",
"required": true,
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/User"
}
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
},
"/user/createWithList": {
"post": {
"tags": ["user"],
"summary": "Creates list of users with given input array",
"description": "",
"operationId": "createUsersWithListInput",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"in": "body",
"name": "body",
"description": "List of user object",
"required": true,
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/User"
}
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
},
"/user/login": {
"get": {
"tags": ["user"],
"summary": "Logs user into the system",
"description": "",
"operationId": "loginUser",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "username",
"in": "query",
"description": "The user name for login",
"required": true,
"type": "string"
},
{
"name": "password",
"in": "query",
"description": "The password for login in clear text",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "string"
},
"headers": {
"X-Rate-Limit": {
"type": "integer",
"format": "int32",
"description": "calls per hour allowed by the user"
},
"X-Expires-After": {
"type": "string",
"format": "date-time",
"description": "date in UTC when token expires"
}
}
},
"400": {
"description": "Invalid username/password supplied"
}
}
}
},
"/user/logout": {
"get": {
"tags": ["user"],
"summary": "Logs out current logged in user session",
"description": "",
"operationId": "logoutUser",
"produces": ["application/xml", "application/json"],
"parameters": [],
"responses": {
"default": {
"description": "successful operation"
}
}
}
},
"/user/{username}": {
"get": {
"tags": ["user"],
"summary": "Get user by user name",
"description": "",
"operationId": "getUserByName",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "username",
"in": "path",
"description": "The name that needs to be fetched. Use user1 for testing. ",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Invalid username supplied"
},
"404": {
"description": "User not found"
}
}
},
"put": {
"tags": ["user"],
"summary": "Updated user",
"description": "This can only be done by the logged in user.",
"operationId": "updateUser",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "username",
"in": "path",
"description": "name that need to be updated",
"required": true,
"type": "string"
},
{
"in": "body",
"name": "body",
"description": "Updated user object",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"400": {
"description": "Invalid user supplied"
},
"404": {
"description": "User not found"
}
}
},
"delete": {
"tags": ["user"],
"summary": "Delete user",
"description": "This can only be done by the logged in user.",
"operationId": "deleteUser",
"produces": ["application/xml", "application/json"],
"parameters": [
{
"name": "username",
"in": "path",
"description": "The name that needs to be deleted",
"required": true,
"type": "string"
}
],
"responses": {
"400": {
"description": "Invalid username supplied"
},
"404": {
"description": "User not found"
}
}
}
}
},
"securityDefinitions": {
"petstore_auth": {
"type": "oauth2",
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog",
"flow": "implicit",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
},
"api_key": {
"type": "apiKey",
"name": "api_key",
"in": "header"
}
},
"definitions": {
"Order": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"petId": {
"type": "integer",
"format": "int64"
},
"quantity": {
"type": "integer",
"format": "int32"
},
"shipDate": {
"type": "string",
"format": "date-time"
},
"status": {
"type": "string",
"description": "Order Status",
"enum": ["placed", "approved", "delivered"]
},
"complete": {
"type": "boolean",
"default": false
}
},
"xml": {
"name": "Order"
}
},
"Category": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
}
},
"xml": {
"name": "Category"
}
},
"User": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"email": {
"type": "string"
},
"password": {
"type": "string"
},
"phone": {
"type": "string"
},
"userStatus": {
"type": "integer",
"format": "int32",
"description": "User Status"
}
},
"xml": {
"name": "User"
}
},
"Tag": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
}
},
"xml": {
"name": "Tag"
}
},
"Pet": {
"type": "object",
"required": ["name", "photoUrls"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"category": {
"$ref": "#/definitions/Category"
},
"name": {
"type": "string",
"example": "doggie"
},
"photoUrls": {
"type": "array",
"xml": {
"name": "photoUrl",
"wrapped": true
},
"items": {
"type": "string"
}
},
"tags": {
"type": "array",
"xml": {
"name": "tag",
"wrapped": true
},
"items": {
"$ref": "#/definitions/Tag"
}
},
"status": {
"type": "string",
"description": "pet status in the store",
"enum": ["available", "pending", "sold"]
}
},
"xml": {
"name": "Pet"
}
},
"ApiResponse": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"type": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
},
"externalDocs": {
"description": "Find out more about Swagger",
"url": "http://swagger.io"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc