diff --git a/package-lock.json b/package-lock.json index b7cb7b2e..74caf757 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19466,7 +19466,7 @@ "license": "MIT", "dependencies": { "@har-sdk/core": "*", - "ajv": "^8.10.0", + "ajv": "^8.12.0", "ajv-errors": "^3.0.0", "ajv-formats": "^2.1.1", "semver": "^7.3.5", diff --git a/packages/validator/package.json b/packages/validator/package.json index eedee3f5..9971a80c 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -45,7 +45,7 @@ ], "dependencies": { "@har-sdk/core": "*", - "ajv": "^8.10.0", + "ajv": "^8.12.0", "ajv-errors": "^3.0.0", "ajv-formats": "^2.1.1", "semver": "^7.3.5", diff --git a/packages/validator/src/schemas/openapi/v3.1.0.json b/packages/validator/src/schemas/openapi/v3.1.0.json new file mode 100644 index 00000000..a9c59185 --- /dev/null +++ b/packages/validator/src/schemas/openapi/v3.1.0.json @@ -0,0 +1,1322 @@ +{ + "$id": "https://spec.openapis.org/oas/3.1/schema/2022-10-07", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$async": true, + "description": "Validation schema for OpenAPI Specification 3.1.X.", + "type": "object", + "required": ["openapi", "info", "servers"], + "properties": { + "openapi": { + "type": "string", + "pattern": "^3\\.1\\.\\d+(-.+)?$" + }, + "info": { + "$ref": "#/$defs/info" + }, + "externalDocs": { + "$ref": "#/$defs/external-documentation" + }, + "servers": { + "type": "array", + "items": { + "$ref": "#/$defs/server" + }, + "minItems": 1, + "default": [ + { + "url": "/" + } + ] + }, + "security": { + "type": "array", + "items": { + "$ref": "#/$defs/security-requirement" + } + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/$defs/tag" + }, + "uniqueItems": true + }, + "paths": { + "$ref": "#/$defs/paths" + }, + "components": { + "$ref": "#/$defs/components" + }, + "webhooks": { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/path-item-or-reference" + } + }, + "jsonSchemaDialect": { + "type": "string", + "format": "uri", + "default": "https://spec.openapis.org/oas/3.1/dialect/base" + } + }, + "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", + "required": ["title", "version"], + "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" + } + }, + "$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", + "required": ["name"], + "properties": { + "name": { + "type": "string" + }, + "identifier": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "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", + "required": ["url"], + "properties": { + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "variables": { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/server-variable" + } + } + }, + "if": { + "required": ["variables"] + }, + "then": { + "properties": { + "url": { + "type": "string", + "format": "uri-template" + } + } + }, + "else": { + "properties": { + "url": { + "type": "string", + "format": "uri" + } + } + }, + "$ref": "#/$defs/specification-extensions", + "unevaluatedProperties": false + }, + "server-variable": { + "$comment": "https://spec.openapis.org/oas/v3.1.0#server-variable-object", + "type": "object", + "required": ["default"], + "properties": { + "enum": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "default": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "$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": { + "$dynamicRef": "#meta" + } + }, + "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, + "errorMessage": { + "unevaluatedProperties": "The property `paths` must have path names that start with \"/\"" + } + }, + "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" + } + } + }, + "patternProperties": { + "^(get|put|post|delete|options|head|patch|trace)$": { + "$ref": "#/$defs/operation" + }, + "^x-": {} + }, + "$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", + "required": ["url"], + "properties": { + "description": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "$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": { + "type": "boolean", + "default": false + }, + "deprecated": { + "type": "boolean", + "default": false + }, + "schema": { + "$dynamicRef": "#meta" + }, + "content": { + "$ref": "#/$defs/content", + "minProperties": 1, + "maxProperties": 1 + } + }, + "errorMessage": { + "properties": { + "in": "The property `in` must have one of the following values: \"path\", \"query\", \"header\", \"cookie\"" + } + }, + "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": { + "required": ["in"], + "properties": { + "in": { + "const": "path" + } + } + }, + "then": { + "properties": { + "name": { + "pattern": "[^/#?]+$" + }, + "style": { + "enum": ["matrix", "label", "simple"], + "default": "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": { + "$dynamicRef": "#meta" + }, + "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" + }, + "^x-": {} + }, + "not": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "patternProperties": { + "^x-": {} + } + }, + "minProperties": 1, + "$ref": "#/$defs/specification-extensions", + "unevaluatedProperties": false, + "errorMessage": { + "not": "The property `response` must define at least one response, in addition to any vendor extension (`x-*`) fields", + "unevaluatedProperties": "The property `response` must have the following values: three-digit status codes, `default`, and vendor extensions (`x-*`)" + } + }, + "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": { + "$dynamicRef": "#meta" + }, + "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", + "required": ["authorizationUrl", "scopes"], + "properties": { + "authorizationUrl": { + "type": "string", + "format": "uri" + }, + "refreshUrl": { + "type": "string", + "format": "uri" + }, + "scopes": { + "$ref": "#/$defs/map-of-strings" + } + }, + "$ref": "#/$defs/specification-extensions", + "unevaluatedProperties": false + }, + "password": { + "type": "object", + "required": ["tokenUrl", "scopes"], + "properties": { + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "refreshUrl": { + "type": "string", + "format": "uri" + }, + "scopes": { + "$ref": "#/$defs/map-of-strings" + } + }, + "$ref": "#/$defs/specification-extensions", + "unevaluatedProperties": false + }, + "client-credentials": { + "type": "object", + "required": ["tokenUrl", "scopes"], + "properties": { + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "refreshUrl": { + "type": "string", + "format": "uri" + }, + "scopes": { + "$ref": "#/$defs/map-of-strings" + } + }, + "$ref": "#/$defs/specification-extensions", + "unevaluatedProperties": false + }, + "authorization-code": { + "type": "object", + "required": ["authorizationUrl", "tokenUrl", "scopes"], + "properties": { + "authorizationUrl": { + "type": "string", + "format": "uri" + }, + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "refreshUrl": { + "type": "string", + "format": "uri" + }, + "scopes": { + "$ref": "#/$defs/map-of-strings" + } + }, + "$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" + } + } + } +} diff --git a/packages/validator/src/validator/BaseValidator.ts b/packages/validator/src/validator/AjvValidator.ts similarity index 80% rename from packages/validator/src/validator/BaseValidator.ts rename to packages/validator/src/validator/AjvValidator.ts index 4cfc31ee..49750237 100644 --- a/packages/validator/src/validator/BaseValidator.ts +++ b/packages/validator/src/validator/AjvValidator.ts @@ -4,18 +4,17 @@ import Ajv, { AnySchema, AsyncSchema, ValidateFunction, - ErrorObject + ErrorObject, + Options } from 'ajv'; import addFormats from 'ajv-formats'; import ajvErrors from 'ajv-errors'; -export abstract class BaseValidator - implements Validator -{ +export abstract class AjvValidator implements Validator { private readonly ajv: Ajv; protected constructor(schemas: AnySchema[]) { - this.ajv = new Ajv({ + this.ajv = this.createAjv({ allErrors: true, strict: false }); @@ -28,10 +27,10 @@ export abstract class BaseValidator this.ajv.addSchema(schemas); } - protected abstract getSchemaId(document: T): string; + protected abstract getSchemaKeyRef(document?: T): string; public async verify(document: T): Promise { - const schemaId = this.getSchemaId(document); + const schemaId = this.getSchemaKeyRef(document); const validateFn: ValidateFunction = schemaId ? this.ajv.getSchema(schemaId) : null; @@ -53,6 +52,10 @@ export abstract class BaseValidator } } + protected createAjv(options: Options): Ajv { + return new Ajv(options); + } + private verifySchema(schema: AnySchema): void { if (!(schema as AsyncSchema).$async) { throw Error( diff --git a/packages/validator/src/validator/Draft2020AjvValidator.ts b/packages/validator/src/validator/Draft2020AjvValidator.ts new file mode 100644 index 00000000..f35c3e93 --- /dev/null +++ b/packages/validator/src/validator/Draft2020AjvValidator.ts @@ -0,0 +1,16 @@ +import { Document } from './Validator'; +import { AjvValidator } from './AjvValidator'; +import Ajv, { AnySchema, Options } from 'ajv'; +import Ajv2020 from 'ajv/dist/2020'; + +export abstract class Draft2020AjvValidator< + T extends Document +> extends AjvValidator { + protected constructor(schemas: AnySchema[]) { + super(schemas); + } + + protected override createAjv(options: Options): Ajv { + return new Ajv2020(options); + } +} diff --git a/packages/validator/src/validator/HarValidator.ts b/packages/validator/src/validator/HarValidator.ts index e6badb7f..12e58329 100644 --- a/packages/validator/src/validator/HarValidator.ts +++ b/packages/validator/src/validator/HarValidator.ts @@ -1,8 +1,8 @@ -import { BaseValidator } from './BaseValidator'; +import { AjvValidator } from './AjvValidator'; import schema from '../schemas/har/v1.2.json'; import { Har } from '@har-sdk/core'; -export class HarValidator extends BaseValidator { +export class HarValidator extends AjvValidator { private readonly SCHEMA_ID = 'https://github.com/ahmadnassri/har-spec/blob/master/versions/1.2.md/'; @@ -10,7 +10,7 @@ export class HarValidator extends BaseValidator { super([schema]); } - protected getSchemaId(_: Har): string { + protected getSchemaKeyRef(): string { return this.SCHEMA_ID; } } diff --git a/packages/validator/src/validator/OAS3Validator.ts b/packages/validator/src/validator/OAS3Validator.ts new file mode 100644 index 00000000..60bfcb0b --- /dev/null +++ b/packages/validator/src/validator/OAS3Validator.ts @@ -0,0 +1,16 @@ +import { AjvValidator } from './AjvValidator'; +import schemaV3 from '../schemas/openapi/v3.0.0.json'; +import { OpenAPIV3 } from '@har-sdk/core'; + +export class OAS3Validator extends AjvValidator { + private readonly SCHEMA_KEY_REF = + 'https://spec.openapis.org/oas/3.0/schema/2021-09-28'; + + constructor() { + super([schemaV3]); + } + + protected getSchemaKeyRef(): string { + return this.SCHEMA_KEY_REF; + } +} diff --git a/packages/validator/src/validator/OAS3_1Validator.ts b/packages/validator/src/validator/OAS3_1Validator.ts new file mode 100644 index 00000000..8ab487ee --- /dev/null +++ b/packages/validator/src/validator/OAS3_1Validator.ts @@ -0,0 +1,17 @@ +import schemaV3_1 from '../schemas/openapi/v3.1.0.json'; +import { Draft2020AjvValidator } from './Draft2020AjvValidator'; +import { OpenAPIV3_1 } from '@har-sdk/core'; + +// eslint-disable-next-line @typescript-eslint/naming-convention +export class OAS3_1Validator extends Draft2020AjvValidator { + private readonly SCHEMA_KEY_REF = + 'https://spec.openapis.org/oas/3.1/schema/2022-10-07'; + + constructor() { + super([schemaV3_1]); + } + + protected getSchemaKeyRef(): string { + return this.SCHEMA_KEY_REF; + } +} diff --git a/packages/validator/src/validator/OASValidator.ts b/packages/validator/src/validator/OASValidator.ts index 16cf2f7f..dac7b062 100644 --- a/packages/validator/src/validator/OASValidator.ts +++ b/packages/validator/src/validator/OASValidator.ts @@ -1,37 +1,55 @@ -import { BaseValidator } from './BaseValidator'; -import schemaV2 from '../schemas/openapi/v2.0.0.json'; -import schemaV3 from '../schemas/openapi/v3.0.0.json'; -import { OpenAPI, OpenAPIV2 } from '@har-sdk/core'; +import { Validator } from './Validator'; +import { SwaggerValidator } from './SwaggerValidator'; +import { OAS3Validator } from './OAS3Validator'; +import { OAS3_1Validator } from './OAS3_1Validator'; import semver from 'semver'; +import { OpenAPI, OpenAPIV2, OpenAPIV3, OpenAPIV3_1 } from '@har-sdk/core'; +import { ErrorObject } from 'ajv'; -export class OASValidator extends BaseValidator { - private readonly MIN_ALLOWED_VERSION = '2.0.0'; +export class OASValidator implements Validator { + private readonly validators: ReadonlyMap< + string, + Validator + > = new Map( + Object.entries({ + '2.x.x': new SwaggerValidator(), + '3.0.x': new OAS3Validator(), + '3.1.x': new OAS3_1Validator() + }) + ); - private readonly VERSION_SCHEMA_MAP: Readonly> = { - 2: 'http://swagger.io/v2/schema.json#', - 3: 'https://spec.openapis.org/oas/3.0/schema/2021-09-28' - }; + public async verify(document: OpenAPI.Document): Promise { + const version = this.extractSpecVersion(document); + const validator = this.getValidator(version); - constructor() { - super([schemaV2, schemaV3]); + if (!validator) { + throw new Error('Unsupported or invalid specification version'); + } + + return validator.verify(document); } - protected getSchemaId(document: OpenAPI.Document): string { - let version = ( + private extractSpecVersion( + document: OpenAPIV2.Document | OpenAPIV3.Document | OpenAPIV3_1.Document + ): string { + const version = ( 'openapi' in document ? document.openapi : (document as OpenAPIV2.Document).swagger || '' ).trim(); - if ( - !semver.valid(version) && - this.MIN_ALLOWED_VERSION.startsWith(version) - ) { - version = this.MIN_ALLOWED_VERSION; - } + return semver.coerce(version)?.format() ?? ''; + } - const major = semver.valid(version) && semver.major(version); + private getValidator( + version: string + ): Validator | undefined { + const [, schema]: [string?, Validator?] = + [...this.validators].find( + ([range, validator]: [string, Validator]) => + semver.satisfies(version, range) ? validator : undefined + ) ?? []; - return (major && this.VERSION_SCHEMA_MAP[major]) || ''; + return schema; } } diff --git a/packages/validator/src/validator/PostmanValidator.ts b/packages/validator/src/validator/PostmanValidator.ts index aeb6beeb..e6316df9 100644 --- a/packages/validator/src/validator/PostmanValidator.ts +++ b/packages/validator/src/validator/PostmanValidator.ts @@ -1,9 +1,9 @@ -import { BaseValidator } from './BaseValidator'; +import { AjvValidator } from './AjvValidator'; import schemaV2 from '../schemas/postman/v2.0.0.json'; import schemaV21 from '../schemas/postman/v2.1.0.json'; import { Postman } from '@har-sdk/core'; -export class PostmanValidator extends BaseValidator { +export class PostmanValidator extends AjvValidator { private readonly VERSION_SCHEMA_MAP: Readonly> = { 'v2.0.0': 'https://schema.getpostman.com/json/draft-07/collection/v2.0.0/', 'v2.1.0': 'https://schema.getpostman.com/json/draft-07/collection/v2.1.0/' @@ -13,7 +13,7 @@ export class PostmanValidator extends BaseValidator { super([schemaV2, schemaV21]); } - protected getSchemaId(document: Postman.Document): string { + protected getSchemaKeyRef(document: Postman.Document): string { const versions = Object.keys(this.VERSION_SCHEMA_MAP); const version = document.info.schema diff --git a/packages/validator/src/validator/SwaggerValidator.ts b/packages/validator/src/validator/SwaggerValidator.ts new file mode 100644 index 00000000..a19140b6 --- /dev/null +++ b/packages/validator/src/validator/SwaggerValidator.ts @@ -0,0 +1,15 @@ +import { AjvValidator } from './AjvValidator'; +import schemaV2 from '../schemas/openapi/v2.0.0.json'; +import { OpenAPIV2 } from '@har-sdk/core'; + +export class SwaggerValidator extends AjvValidator { + private readonly SCHEMA_KEY_REF = 'http://swagger.io/v2/schema.json#'; + + constructor() { + super([schemaV2]); + } + + protected getSchemaKeyRef(): string { + return this.SCHEMA_KEY_REF; + } +} diff --git a/packages/validator/tests/fixtures/oas3.1.petstore.yaml b/packages/validator/tests/fixtures/oas3.1.petstore.yaml new file mode 100644 index 00000000..4c378ac8 --- /dev/null +++ b/packages/validator/tests/fixtures/oas3.1.petstore.yaml @@ -0,0 +1,801 @@ +openapi: 3.1.0 +info: + title: Swagger Petstore - OpenAPI 3.1 + description: |- + This is a sample Pet Store Server based on the OpenAPI 3.1 specification. You can find out more about + Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach! + You can now help us improve the API whether it's by making changes to the definition itself or to the code. + That way, with time, we can improve the API in general, and expose some of the new features in OAS3. + + Some useful links: + - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore) + - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml) + + 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 + version: 1.0.11 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: + - url: https://petstore3.swagger.io/api/v3 +tags: + - name: pet + description: Everything about your Pets + externalDocs: + description: Find out more + url: http://swagger.io + - name: store + description: Access to Petstore orders + externalDocs: + description: Find out more about our store + url: http://swagger.io + - name: user + description: Operations about user +paths: + /pet: + put: + tags: + - pet + summary: Update an existing pet + description: Update an existing pet by Id + operationId: updatePet + requestBody: + description: Update an existent pet in the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + required: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation exception + security: + - petstore_auth: + - write:pets + - read:pets + post: + tags: + - pet + summary: Add a new pet to the store + description: Add a new pet to the store + operationId: addPet + requestBody: + description: Create a new pet in the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Pet' + required: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + '405': + description: Invalid input + 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 + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: false + explode: true + schema: + type: string + default: available + enum: + - available + - pending + - sold + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid status value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/findByTags: + get: + tags: + - pet + summary: Finds Pets by tags + description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + operationId: findPetsByTags + parameters: + - name: tags + in: query + description: Tags to filter by + required: false + explode: true + schema: + type: array + items: + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid tag value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/{petId}: + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - api_key: [] + - petstore_auth: + - write:pets + - read:pets + post: + tags: + - pet + summary: Updates a pet in the store with form data + description: '' + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: integer + format: int64 + - name: name + in: query + description: Name of pet that needs to be updated + schema: + type: string + - name: status + in: query + description: Status of pet that needs to be updated + schema: + type: string + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + delete: + tags: + - pet + summary: Deletes a pet + description: delete a pet + operationId: deletePet + parameters: + - name: api_key + in: header + description: '' + required: false + schema: + type: string + - name: petId + in: path + description: Pet id to delete + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid pet value + security: + - petstore_auth: + - write:pets + - read:pets + /pet/{petId}/uploadImage: + post: + tags: + - pet + summary: uploads an image + description: '' + operationId: uploadFile + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + schema: + type: integer + format: int64 + - name: additionalMetadata + in: query + description: Additional Metadata + required: false + schema: + type: string + requestBody: + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/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 + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + /store/order: + post: + tags: + - store + summary: Place an order for a pet + description: Place a new order in the store + operationId: placeOrder + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Order' + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + '405': + description: Invalid input + /store/order/{orderId}: + get: + tags: + - store + summary: Find purchase order by ID + description: For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions. + operationId: getOrderById + parameters: + - name: orderId + in: path + description: ID of order that needs to be fetched + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/xml: + schema: + $ref: '#/components/schemas/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 value < 1000. Anything above 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + schema: + type: integer + 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 + requestBody: + description: Created user object + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + responses: + default: + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + description: Creates list of users with given input array + operationId: createUsersWithListInput + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + default: + description: successful operation + /user/login: + get: + tags: + - user + summary: Logs user into the system + description: '' + operationId: loginUser + parameters: + - name: username + in: query + description: The user name for login + required: false + schema: + type: string + - name: password + in: query + description: The password for login in clear text + required: false + schema: + type: string + responses: + '200': + description: successful operation + headers: + X-Rate-Limit: + description: calls per hour allowed by the user + schema: + type: integer + format: int32 + X-Expires-After: + description: date in UTC when token expires + schema: + type: string + format: date-time + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + '400': + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + description: '' + operationId: logoutUser + parameters: [] + responses: + default: + description: successful operation + /user/{username}: + get: + tags: + - user + summary: Get user by user name + description: '' + operationId: getUserByName + parameters: + - name: username + in: path + description: 'The name that needs to be fetched. Use user1 for testing. ' + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + '400': + description: Invalid username supplied + '404': + description: User not found + put: + tags: + - user + summary: Update user + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - name: username + in: path + description: name that need to be deleted + required: true + schema: + type: string + requestBody: + description: Update an existent user in the store + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + responses: + default: + description: successful operation + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid username supplied + '404': + description: User not found +components: + schemas: + Order: + type: object + properties: + id: + type: integer + format: int64 + example: 10 + petId: + type: integer + format: int64 + example: 198772 + quantity: + type: integer + format: int32 + example: 7 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + example: approved + enum: + - placed + - approved + - delivered + complete: + type: boolean + xml: + name: order + Customer: + type: object + properties: + id: + type: integer + format: int64 + example: 100000 + username: + type: string + example: fehguy + address: + type: array + xml: + name: addresses + wrapped: true + items: + $ref: '#/components/schemas/Address' + xml: + name: customer + Address: + type: object + properties: + street: + type: string + example: 437 Lytton + city: + type: string + example: Palo Alto + state: + type: string + example: CA + zip: + type: string + example: '94301' + xml: + name: address + Category: + type: object + properties: + id: + type: integer + format: int64 + example: 1 + name: + type: string + example: Dogs + xml: + name: category + User: + type: object + properties: + id: + type: integer + format: int64 + example: 10 + username: + type: string + example: theUser + firstName: + type: string + example: John + lastName: + type: string + example: James + email: + type: string + example: john@email.com + password: + type: string + example: '12345' + phone: + type: string + example: '12345' + userStatus: + type: integer + description: User Status + format: int32 + example: 1 + xml: + name: user + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: tag + Pet: + required: + - name + - photoUrls + type: object + properties: + id: + type: integer + format: int64 + example: 10 + name: + type: string + example: doggie + category: + $ref: '#/components/schemas/Category' + photoUrls: + type: array + xml: + wrapped: true + items: + type: string + xml: + name: photoUrl + tags: + type: array + xml: + wrapped: true + items: + $ref: '#/components/schemas/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 + xml: + name: '##default' + requestBodies: + Pet: + description: Pet object that needs to be added to the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + UserArray: + description: List of user object + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + securitySchemes: + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: https://petstore3.swagger.io/oauth/authorize + scopes: + write:pets: modify pets in your account + read:pets: read your pets + api_key: + type: apiKey + name: api_key + in: header diff --git a/packages/validator/tests/oas.spec.ts b/packages/validator/tests/oas.spec.ts index f20f59a0..80ee1670 100644 --- a/packages/validator/tests/oas.spec.ts +++ b/packages/validator/tests/oas.spec.ts @@ -52,6 +52,19 @@ describe('OASValidator', () => { expect(result).toEqual([]); }); + it('should successfully validate valid oas v3.1 document (Petstore, yaml)', async () => { + const input: OpenAPIV3.Document = yaml.load( + await promisify(readFile)( + resolve(__dirname, './fixtures/oas3.1.petstore.yaml'), + 'utf8' + ) + ) as OpenAPIV3.Document; + + const result = await validator.verify(input); + + expect(result).toEqual([]); + }); + it('should throw exception if cannot determine version of document', async () => { const input: OpenAPIV2.Document = { swagger: 'xyz',