diff --git a/package.json b/package.json index 01be1c8d5c..78f8407b14 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,10 @@ "README.md", "schemas/*" ], - "dependencies": {}, + "dependencies": { + "@hyperjump/json-schema": "^0.17.0", + "@hyperjump/json-schema-core": "^0.20.0" + }, "devDependencies": { "mdv": "^1.0.7", "yaml": "^1.8.3" diff --git a/schemas/v3.1/README.md b/schemas/v3.1/README.md new file mode 100644 index 0000000000..6c93d49a8d --- /dev/null +++ b/schemas/v3.1/README.md @@ -0,0 +1,16 @@ +OpenAPI 3.1.X JSON Schema +--- + +Here you can find the JSON Schema for validating OpenAPI definitions of versions 3.1.X. + +As a reminder, the JSON Schema is not the source of truth for the Specification. In cases of conflicts between the Specification itself and the JSON Schema, the Specification wins. Also, some Specification constraints cannot be represented with the JSON Schema so it's highly recommended to employ other methods to ensure compliance. + +The iteration version of the JSON Schema can be found in the `$id` field. For example, the value of `$id: https://spec.openapis.org/oas/3.1/schema/2021-02-18` means this iteration was created on February 18th, 2021. + +To submit improvements to the schema, modify the schema.yaml file only. + +The TSC will then: +- Run tests on the updated schema +- Update the iteration version +- Convert the schema.yaml to schema.json +- Publish the new version diff --git a/schemas/v3.1/schema.json b/schemas/v3.1/schema.json new file mode 100644 index 0000000000..796434c404 --- /dev/null +++ b/schemas/v3.1/schema.json @@ -0,0 +1,1468 @@ +{ + "$id": "https://spec.openapis.org/oas/3.1/schema/2021-02-18", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "required": [ + "openapi", + "info" + ], + "anyOf": [ + { + "required": [ + "components" + ] + }, + { + "required": [ + "paths" + ] + }, + { + "required": [ + "webhooks" + ] + } + ], + "$ref": "#/$defs/Mixins/$defs/Extensible", + "properties": { + "openapi": { + "type": "string", + "pattern": "^3\\.1\\.\\d+(-.+)?$" + }, + "jsonSchemaDialect": { + "type": "string", + "format": "uri" + }, + "info": { + "$ref": "#Info" + }, + "externalDocs": { + "$ref": "#ExternalDocumentation" + }, + "servers": { + "type": "array", + "items": { + "$ref": "#Server" + } + }, + "security": { + "type": "array", + "items": { + "$ref": "#SecurityRequirement" + } + }, + "tags": { + "type": "array", + "items": { + "$ref": "#Tag" + }, + "uniqueItems": true + }, + "paths": { + "$ref": "#Paths" + }, + "webhooks": { + "$comment": "TODO: Implement meta-schema for webhooks" + }, + "components": { + "$ref": "#Components" + } + }, + "unevaluatedProperties": false, + "$defs": { + "Mixins": { + "$defs": { + "Describable": { + "properties": { + "description": { + "type": "string" + } + } + }, + "Requireable": { + "properties": { + "required": { + "type": "boolean", + "default": false + } + } + }, + "Deprecatable": { + "properties": { + "deprecated": { + "type": "boolean", + "default": false + } + } + }, + "DescReqDep": { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Requireable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Deprecatable" + } + ] + }, + "Extensible": { + "patternProperties": { + "^x-": true + } + }, + "WithSingleExample": { + "properties": { + "example": true, + "examples": false + } + }, + "WithExampleObjects": { + "properties": { + "example": false, + "examples": { + "type": "object", + "additionalProperties": { + "$ref": "#Example" + } + } + } + }, + "WithExamples": { + "oneOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithSingleExample" + }, + { + "$ref": "#/$defs/Mixins/$defs/WithExampleObjects" + } + ] + }, + "WithSchema": { + "properties": { + "schema": { + "$ref": "#Schema" + }, + "content": false + } + }, + "WithSchemaAndExamples": { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithSchema" + }, + { + "$ref": "#/$defs/Mixins/$defs/WithExamples" + } + ] + }, + "WithContent": { + "properties": { + "schema": false, + "content": { + "type": "object", + "additionalProperties": { + "$ref": "#MediaType" + }, + "minProperties": 1, + "maxProperties": 1 + } + } + }, + "WithNameAndLocation": { + "required": [ + "name", + "in" + ], + "properties": { + "name": { + "type": "string" + }, + "in": { + "type": "string", + "enum": [ + "path", + "query", + "header", + "cookie" + ] + } + } + }, + "WithExplodeAndReserved": { + "properties": { + "explode": { + "type": "boolean" + }, + "allowReserved": { + "type": "boolean", + "default": false + } + } + }, + "WithEmpty": { + "properties": { + "allowEmptyValue": { + "type": "boolean", + "default": false + } + } + }, + "WithExplodeReservedAndEmpty": { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithExplodeAndReserved" + }, + { + "$ref": "#/$defs/Mixins/$defs/WithEmpty" + } + ] + }, + "StyledSimple": { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty" + } + ], + "properties": { + "style": { + "type": "string", + "const": "simple", + "default": "simple" + } + } + }, + "StyledMatrix": { + "properties": { + "style": { + "type": "string", + "enum": [ + "matrix", + "label", + "simple" + ], + "default": "simple" + } + } + }, + "StyledFormOnly": { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty" + } + ], + "properties": { + "style": { + "type": "string", + "const": "form", + "default": "form" + } + } + }, + "StyledFormComplexNoDefaultOrEmpty": { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithExplodeAndReserved" + } + ], + "properties": { + "style": { + "type": "string", + "enum": [ + "form", + "spaceDelimited", + "pipeDelimited", + "deepObject" + ] + } + } + }, + "StyledFormComplex": { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/StyledFormComplexNoDefaultOrEmpty" + }, + { + "$ref": "#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty" + } + ], + "properties": { + "style": { + "default": "form" + } + } + } + } + }, + "Objects": { + "$defs": { + "Reference": { + "$anchor": "Reference", + "type": "object", + "required": [ + "$ref" + ], + "properties": { + "$ref": { + "type": "string", + "format": "uri-reference" + } + } + }, + "Info": { + "$anchor": "Info", + "type": "object", + "required": [ + "title", + "version" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "title": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "termsOfService": { + "type": "string", + "format": "uri-reference" + }, + "contact": { + "$ref": "#Contact" + }, + "license": { + "$ref": "#License" + } + }, + "$defs": { + "Contact": { + "$anchor": "Contact", + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri-reference" + }, + "email": { + "type": "string", + "format": "email" + } + }, + "unevaluatedProperties": false + }, + "License": { + "$anchor": "License", + "type": "object", + "required": [ + "name" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri-reference" + }, + "identifier": { + "type": "string" + } + }, + "unevaluatedProperties": false + } + } + }, + "Server": { + "$anchor": "Server", + "type": "object", + "required": [ + "url" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "url": { + "type": "string" + }, + "variables": { + "type": "object", + "additionalProperties": { + "type": "object", + "required": [ + "default" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "enum": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "default": { + "type": "string" + } + }, + "unevaluatedProperties": false + } + } + }, + "unevaluatedProperties": false + }, + "Response": { + "$anchor": "Response", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "type": "object", + "required": [ + "description" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "headers": { + "type": "object", + "additionalProperties": { + "$ref": "#Header" + } + }, + "content": { + "type": "object", + "additionalProperties": { + "$ref": "#MediaType" + } + }, + "links": { + "type": "object", + "additionalProperties": { + "$ref": "#Link" + } + } + }, + "unevaluatedProperties": false + } + ] + }, + "MediaType": { + "$anchor": "MediaType", + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithSchemaAndExamples" + } + ], + "properties": { + "encoding": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/StyledFormComplexNoDefaultOrEmpty" + } + ], + "properties": { + "contentType": { + "type": "string" + }, + "headers": { + "type": "object", + "additionalProperties": { + "$ref": "#Header" + } + } + } + } + }, + "unevaluatedProperties": false + }, + "Example": { + "$anchor": "Example", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "summary": { + "type": "string" + }, + "value": true, + "externalValue": { + "type": "string", + "format": "uri-reference" + } + }, + "unevaluatedProperties": false + } + ] + }, + "Header": { + "$anchor": "Header", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "type": "object", + "required": [ + "schema" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/DescReqDep" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "oneOf": [ + { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithSchemaAndExamples" + }, + { + "$ref": "#/$defs/Mixins/$defs/StyledSimple" + } + ] + }, + { + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithContent" + }, + { + "$ref": "#/$defs/Mixins/$defs/WithEmpty" + } + ] + } + ], + "unevaluatedProperties": false + } + ] + }, + "Paths": { + "$anchor": "Paths", + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "patternProperties": { + "^/": { + "type": "object", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "$ref": "#PathItem" + } + ] + } + }, + "unevaluatedProperties": false + }, + "PathItem": { + "$anchor": "PathItem", + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "summary": { + "type": "string" + }, + "servers": { + "type": "array", + "items": { + "$ref": "#Server" + } + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#Parameter" + }, + "uniqueItems": true + } + } + }, + "Operation": { + "$anchor": "Operation", + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Deprecatable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "summary": { + "type": "string" + }, + "externalDocs": { + "$ref": "#ExternalDocumentation" + }, + "operationId": { + "type": "string" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#Parameter" + }, + "uniqueItems": true + }, + "requestBody": { + "$ref": "#RequestBody" + }, + "responses": { + "$ref": "#Responses" + }, + "callback": { + "$ref": "#Callback" + }, + "security": { + "type": "array", + "items": { + "$ref": "#SecurityRequirement" + } + }, + "servers": { + "type": "array", + "items": { + "$ref": "#Server" + } + } + }, + "unevaluatedProperties": false + }, + "Responses": { + "$anchor": "Responses", + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "default": { + "$ref": "#Response" + } + }, + "patternProperties": { + "^[1-5](?:\\d{2}|XX)$": { + "$ref": "#Response" + } + }, + "minProperties": 1, + "unevaluatedProperties": false + }, + "SecurityRequirement": { + "$anchor": "SecurityRequirement", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "Tag": { + "$anchor": "Tag", + "type": "object", + "required": [ + "name" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "name": { + "type": "string" + }, + "externalDocs": { + "$ref": "#ExternalDocumentation" + } + }, + "unevaluatedProperties": false + }, + "ExternalDocumentation": { + "$anchor": "ExternalDocumentation", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + }, + { + "$ref": "#/$defs/Mixins/$defs/Describable" + } + ], + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string", + "format": "uri-reference" + } + } + }, + "Parameter": { + "$anchor": "Parameter", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithNameAndLocation" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + }, + { + "oneOf": [ + { + "allOf": [ + { + "$ref": "#PathParam" + }, + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Deprecatable" + }, + { + "required": [ + "required" + ], + "properties": { + "required": { + "const": true, + "default": true + } + } + } + ] + }, + { + "allOf": [ + { + "anyOf": [ + { + "$ref": "#QueryParam" + }, + { + "$ref": "#HeaderParam" + }, + { + "$ref": "#CookieParam" + } + ] + }, + { + "$ref": "#/$defs/Mixins/$defs/DescReqDep" + } + ] + } + ] + } + ], + "oneOf": [ + { + "allOf": [ + { + "required": [ + "schema" + ] + }, + { + "$ref": "#/$defs/Mixins/$defs/WithSchemaAndExamples" + }, + { + "oneOf": [ + { + "allOf": [ + { + "$ref": "#PathParam" + }, + { + "$ref": "#/$defs/Mixins/$defs/StyledMatrix" + } + ] + }, + { + "allOf": [ + { + "$ref": "#QueryParam" + }, + { + "$ref": "#/$defs/Mixins/$defs/StyledFormComplex" + } + ] + }, + { + "allOf": [ + { + "$ref": "#HeaderParam" + }, + { + "$ref": "#/$defs/Mixins/$defs/StyledSimple" + } + ] + }, + { + "allOf": [ + { + "$ref": "#CookieParam" + }, + { + "$ref": "#/$defs/Mixins/$defs/StyledFormOnly" + } + ] + } + ] + } + ] + }, + { + "allOf": [ + { + "required": [ + "content" + ] + }, + { + "$ref": "#/$defs/Mixins/$defs/WithContent" + }, + { + "$ref": "#/$defs/Mixins/$defs/WithEmpty" + } + ] + } + ], + "unevaluatedProperties": false + } + ], + "$defs": { + "PathParam": { + "$anchor": "PathParam", + "properties": { + "in": { + "const": "path" + } + } + }, + "QueryParam": { + "$anchor": "QueryParam", + "properties": { + "in": { + "const": "query" + } + } + }, + "HeaderParam": { + "$anchor": "HeaderParam", + "properties": { + "in": { + "const": "header" + } + } + }, + "CookieParam": { + "$anchor": "CookieParam", + "properties": { + "in": { + "const": "cookie" + } + } + } + } + }, + "RequestBody": { + "$anchor": "RequestBody", + "required": [ + "content" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Requireable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "content": { + "type": "object", + "additionalProperties": { + "$ref": "#MediaType" + } + } + }, + "unevaluatedProperties": false + }, + "SecurityScheme": { + "$anchor": "SecurityScheme", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "type": "object", + "required": [ + "type" + ], + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "apiKey", + "http", + "bearer", + "mutualTLS", + "oauth2", + "openIdConnect" + ] + } + }, + "oneOf": [ + { + "$ref": "#APIKey" + }, + { + "$ref": "#HTTP" + }, + { + "$ref": "#MutualTLS" + }, + { + "$ref": "#OAuth2" + }, + { + "$ref": "#OpenIdConnect" + } + ], + "unevaluatedProperties": false + } + ], + "$defs": { + "APIKey": { + "$anchor": "APIKey", + "properties": { + "type": { + "const": "apiKey" + } + }, + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/WithNameAndLocation" + } + ], + "not": { + "$ref": "#PathParam" + } + }, + "HTTP": { + "$anchor": "HTTP", + "required": [ + "scheme" + ], + "properties": { + "scheme": { + "type": "string" + } + }, + "oneOf": [ + { + "properties": { + "type": { + "const": "http" + } + } + }, + { + "properties": { + "type": { + "const": "bearer" + }, + "bearerFormat": { + "type": "string" + } + } + } + ] + }, + "MutalTLS": { + "$anchor": "MutualTLS", + "properties": { + "type": { + "const": "mutualTLS" + } + } + }, + "OAuth2": { + "$anchor": "OAuth2", + "required": [ + "flows" + ], + "properties": { + "type": { + "const": "oauth2" + }, + "flows": { + "$ref": "#OAuthFlows" + } + } + }, + "OpenIdConnect": { + "$anchor": "OpenIdConnect", + "required": [ + "openIdConnectUrl" + ], + "properties": { + "type": { + "const": "openIdConnect" + }, + "openIdConnectUrl": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "OAuthFlows": { + "$anchor": "OAuthFlows", + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "properties": { + "implicit": { + "allOf": [ + { + "required": [ + "scopes" + ] + }, + { + "$ref": "#CommonFlow" + }, + { + "$ref": "#AuthorizationFlow" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "unevaluatedProperties": false + }, + "password": { + "allOf": [ + { + "$ref": "#CommonFlow" + }, + { + "$ref": "#TokenFlow" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "unevaluatedProperties": false + }, + "clientCredentials": { + "allOf": [ + { + "$ref": "#CommonFlow" + }, + { + "$ref": "#TokenFlow" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "unevaluatedProperties": false + }, + "authorizationCode": { + "allOf": [ + { + "$ref": "#CommonFlow" + }, + { + "$ref": "#TokenFlow" + }, + { + "$ref": "#AuthorizationFlow" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "unevaluatedProperties": false + } + }, + "unevaluatedProperties": false, + "$defs": { + "Common": { + "$anchor": "CommonFlow", + "properties": { + "refreshUrl": { + "type": "string", + "format": "uri-reference" + }, + "scopes": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "Token": { + "$anchor": "TokenFlow", + "required": [ + "tokenUrl" + ], + "properties": { + "tokenUrl": { + "type": "string", + "format": "uri-reference" + } + } + }, + "Authorization": { + "$anchor": "AuthorizationFlow", + "required": [ + "authorizationUrl" + ], + "properties": { + "authorizationUrl": { + "type": "string", + "format": "uri-reference" + } + } + } + } + }, + "Link": { + "$anchor": "Link", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Describable" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "oneOf": [ + { + "properties": { + "operationRef": { + "type": "string", + "format": "uri-reference" + }, + "operationId": false + } + }, + { + "properties": { + "operationRef": false, + "operationId": { + "type": "string" + } + } + } + ], + "properties": { + "parameters": { + "type": "object", + "additionalProperties": true + }, + "requestBody": true, + "server": { + "$ref": "#Server" + } + }, + "unevaluatedProperties": false + } + ] + }, + "Callback": { + "$anchor": "Callback", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "unevaluatedProperties": false + } + ] + }, + "Schema": { + "$anchor": "Schema", + "oneOf": [ + { + "$ref": "#Reference" + }, + { + "type": "object", + "allOf": [ + { + "$ref": "https://json-schema.org/draft/2020-12/schema" + }, + { + "$ref": "#SchemaExtensions" + }, + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + } + ], + "unevaluatedProperties": false + } + ], + "$defs": { + "Extensions": { + "$anchor": "SchemaExtensions", + "properties": { + "discriminator": { + "$ref": "#Discriminator" + }, + "externalDocs": { + "$ref": "#ExternalDocumentation" + }, + "xml": { + "$ref": "#XML" + } + } + }, + "Discriminator": { + "$anchor": "Discriminator", + "type": "object", + "required": [ + "propertyName" + ], + "properties": { + "propertyName": { + "type": "string" + }, + "mapping": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "XML": { + "$anchor": "XML", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string", + "format": "url" + }, + "prefix": { + "type": "string" + }, + "attribute": { + "type": "boolean", + "default": false + }, + "wrapped": { + "type": "boolean", + "default": false + } + } + } + ], + "unevaluatedProperties": false + } + } + }, + "Components": { + "$anchor": "Components", + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/Mixins/$defs/Extensible" + }, + { + "additionalProperties": { + "$comment": "All sub-objects have the same property name constraints", + "type": "object", + "propertyNames": { + "pattern": "^[a-zA-Z0-9\\.\\-_]+$" + } + } + } + ], + "properties": { + "schemas": { + "additionalProperties": { + "$ref": "#Schema" + } + }, + "responses": { + "additionalProperties": { + "$ref": "#Response" + } + }, + "parameters": { + "additionalProperties": { + "$ref": "#Parameter" + } + }, + "pathItems": { + "additionalProperties": { + "$ref": "#PathItem" + } + }, + "examples": { + "additionalProperties": { + "$ref": "#Example" + } + }, + "requestBodies": { + "additionalProperties": { + "$ref": "#RequestBody" + } + }, + "headers": { + "additionalProperties": { + "$ref": "#Header" + } + }, + "links": { + "additionalProperties": { + "$ref": "#Link" + } + }, + "callbacks": { + "additionalProperties": { + "$ref": "#Callback" + } + } + }, + "unevaluatedProperties": false + } + } + } + } +} diff --git a/schemas/v3.1/schema.yaml b/schemas/v3.1/schema.yaml new file mode 100644 index 0000000000..0e04cb66ff --- /dev/null +++ b/schemas/v3.1/schema.yaml @@ -0,0 +1,776 @@ +$id: 'https://spec.openapis.org/oas/3.1/schema/2021-02-18' +$schema: 'https://json-schema.org/draft/2020-12/schema' +type: object +required: + - openapi + - info +anyOf: + - required: + - components + - required: + - paths + - required: + - webhooks +$ref: '#/$defs/Mixins/$defs/Extensible' +properties: + openapi: + type: string + pattern: ^3\.1\.\d+(-.+)?$ + jsonSchemaDialect: + type: string + format: uri + info: + $ref: '#Info' + externalDocs: + $ref: '#ExternalDocumentation' + servers: + type: array + items: + $ref: '#Server' + security: + type: array + items: + $ref: '#SecurityRequirement' + tags: + type: array + items: + $ref: '#Tag' + uniqueItems: true + paths: + $ref: '#Paths' + webhooks: + $comment: 'TODO: Implement meta-schema for webhooks' + components: + $ref: '#Components' +unevaluatedProperties: false +$defs: + Mixins: + $defs: + Describable: + properties: + description: + type: string + Requireable: + properties: + required: + type: boolean + default: false + Deprecatable: + properties: + deprecated: + type: boolean + default: false + DescReqDep: + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Requireable' + - $ref: '#/$defs/Mixins/$defs/Deprecatable' + Extensible: + patternProperties: + ^x-: true + WithSingleExample: + properties: + example: true + examples: false + WithExampleObjects: + properties: + example: false + examples: + type: object + additionalProperties: + $ref: '#Example' + WithExamples: + oneOf: + - $ref: '#/$defs/Mixins/$defs/WithSingleExample' + - $ref: '#/$defs/Mixins/$defs/WithExampleObjects' + WithSchema: + properties: + schema: + $ref: '#Schema' + content: false + WithSchemaAndExamples: + allOf: + - $ref: '#/$defs/Mixins/$defs/WithSchema' + - $ref: '#/$defs/Mixins/$defs/WithExamples' + WithContent: + properties: + schema: false + content: + type: object + additionalProperties: + $ref: '#MediaType' + minProperties: 1 + maxProperties: 1 + WithNameAndLocation: + required: + - name + - in + properties: + name: + type: string + in: + type: string + enum: + - path + - query + - header + - cookie + WithExplodeAndReserved: + properties: + explode: + type: boolean + allowReserved: + type: boolean + default: false + WithEmpty: + properties: + allowEmptyValue: + type: boolean + default: false + WithExplodeReservedAndEmpty: + allOf: + - $ref: '#/$defs/Mixins/$defs/WithExplodeAndReserved' + - $ref: '#/$defs/Mixins/$defs/WithEmpty' + StyledSimple: + allOf: + - $ref: '#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty' + properties: + style: + type: string + const: simple + default: simple + StyledMatrix: + properties: + style: + type: string + enum: + - matrix + - label + - simple + default: simple + StyledFormOnly: + allOf: + - $ref: '#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty' + properties: + style: + type: string + const: form + default: form + StyledFormComplexNoDefaultOrEmpty: + allOf: + - $ref: '#/$defs/Mixins/$defs/WithExplodeAndReserved' + properties: + style: + type: string + enum: + - form + - spaceDelimited + - pipeDelimited + - deepObject + StyledFormComplex: + allOf: + - $ref: '#/$defs/Mixins/$defs/StyledFormComplexNoDefaultOrEmpty' + - $ref: '#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty' + properties: + style: + default: form + Objects: + $defs: + Reference: + $anchor: Reference + type: object + required: + - $ref + properties: + $ref: + type: string + format: uri-reference + summary: + type: string + $ref: '#/$defs/Mixins/$defs/Describable' + unevaluatedProperties: false + Info: + $anchor: Info + type: object + required: + - title + - version + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + title: + type: string + summary: + type: string + termsOfService: + type: string + format: uri-reference + contact: + $ref: '#Contact' + license: + $ref: '#License' + $defs: + Contact: + $anchor: Contact + type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + name: + type: string + url: + type: string + format: uri-reference + email: + type: string + format: email + unevaluatedProperties: false + License: + $anchor: License + type: object + required: + - name + allOf: + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + name: + type: string + url: + type: string + format: uri-reference + identifier: + type: string + unevaluatedProperties: false + Server: + $anchor: Server + type: object + required: + - url + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + url: + type: string + variables: + type: object + additionalProperties: + type: object + required: + - default + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + enum: + type: array + items: + type: string + minItems: 1 + default: + type: string + unevaluatedProperties: false + unevaluatedProperties: false + Response: + $anchor: Response + oneOf: + - $ref: '#Reference' + - type: object + required: + - description + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + headers: + type: object + additionalProperties: + $ref: '#Header' + content: + type: object + additionalProperties: + $ref: '#MediaType' + links: + type: object + additionalProperties: + $ref: '#Link' + unevaluatedProperties: false + MediaType: + $anchor: MediaType + type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/WithSchemaAndExamples' + properties: + encoding: + type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/StyledFormComplexNoDefaultOrEmpty' + properties: + contentType: + type: string + headers: + type: object + additionalProperties: + $ref: '#Header' + unevaluatedProperties: false + Example: + $anchor: Example + oneOf: + - $ref: '#Reference' + - type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + summary: + type: string + value: true + externalValue: + type: string + format: uri-reference + unevaluatedProperties: false + Header: + $anchor: Header + oneOf: + - $ref: '#Reference' + - type: object + required: + - schema + allOf: + - $ref: '#/$defs/Mixins/$defs/DescReqDep' + - $ref: '#/$defs/Mixins/$defs/Extensible' + oneOf: + - allOf: + - $ref: '#/$defs/Mixins/$defs/WithSchemaAndExamples' + - $ref: '#/$defs/Mixins/$defs/StyledSimple' + - allOf: + - $ref: '#/$defs/Mixins/$defs/WithContent' + - $ref: '#/$defs/Mixins/$defs/WithEmpty' + unevaluatedProperties: false + Paths: + $anchor: Paths + type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/Extensible' + patternProperties: + ^/: + type: object + oneOf: + - $ref: '#Reference' + - $ref: '#PathItem' + unevaluatedProperties: false + PathItem: + $anchor: PathItem + type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + summary: + type: string + servers: + type: array + items: + $ref: '#Server' + parameters: + type: array + items: + $ref: '#Parameter' + uniqueItems: true + Responses: + $anchor: Responses + type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + default: + $ref: '#Response' + patternProperties: + '^[1-5](?:\d{2}|XX)$': + $ref: '#Response' + minProperties: 1 + unevaluatedProperties: false + SecurityRequirement: + $anchor: SecurityRequirement + type: object + additionalProperties: + type: array + items: + type: string + Tag: + $anchor: Tag + type: object + required: + - name + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + name: + type: string + externalDocs: + $ref: '#ExternalDocumentation' + unevaluatedProperties: false + ExternalDocumentation: + $anchor: ExternalDocumentation + allOf: + - $ref: '#/$defs/Mixins/$defs/Extensible' + - $ref: '#/$defs/Mixins/$defs/Describable' + type: object + required: + - url + properties: + url: + type: string + format: uri-reference + Parameter: + $anchor: Parameter + oneOf: + - $ref: '#Reference' + - type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/WithNameAndLocation' + - $ref: '#/$defs/Mixins/$defs/Extensible' + - oneOf: + - allOf: + - $ref: '#PathParam' + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Deprecatable' + - required: + - required + properties: + required: + const: true + default: true + - allOf: + - anyOf: + - $ref: '#QueryParam' + - $ref: '#HeaderParam' + - $ref: '#CookieParam' + - $ref: '#/$defs/Mixins/$defs/DescReqDep' + oneOf: + - allOf: + - required: + - schema + - $ref: '#/$defs/Mixins/$defs/WithSchemaAndExamples' + - oneOf: + - allOf: + - $ref: '#PathParam' + - $ref: '#/$defs/Mixins/$defs/StyledMatrix' + - allOf: + - $ref: '#QueryParam' + - $ref: '#/$defs/Mixins/$defs/StyledFormComplex' + - allOf: + - $ref: '#HeaderParam' + - $ref: '#/$defs/Mixins/$defs/StyledSimple' + - allOf: + - $ref: '#CookieParam' + - $ref: '#/$defs/Mixins/$defs/StyledFormOnly' + - allOf: + - required: + - content + - $ref: '#/$defs/Mixins/$defs/WithContent' + - $ref: '#/$defs/Mixins/$defs/WithEmpty' + unevaluatedProperties: false + $defs: + PathParam: + $anchor: PathParam + properties: + in: + const: path + QueryParam: + $anchor: QueryParam + properties: + in: + const: query + HeaderParam: + $anchor: HeaderParam + properties: + in: + const: header + CookieParam: + $anchor: CookieParam + properties: + in: + const: cookie + RequestBody: + $anchor: RequestBody + required: + - content + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Requireable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + content: + type: object + additionalProperties: + $ref: '#MediaType' + unevaluatedProperties: false + SecurityScheme: + $anchor: SecurityScheme + oneOf: + - $ref: '#Reference' + - type: object + required: + - type + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + type: + type: string + enum: + - apiKey + - http + - bearer + - mutualTLS + - oauth2 + - openIdConnect + oneOf: + - $ref: '#APIKey' + - $ref: '#HTTP' + - $ref: '#MutualTLS' + - $ref: '#OAuth2' + - $ref: '#OpenIdConnect' + unevaluatedProperties: false + $defs: + APIKey: + $anchor: APIKey + properties: + type: + const: apiKey + allOf: + - $ref: '#/$defs/Mixins/$defs/WithNameAndLocation' + not: + $ref: '#PathParam' + HTTP: + $anchor: HTTP + required: + - scheme + properties: + scheme: + type: string + oneOf: + - properties: + type: + const: http + - properties: + type: + const: bearer + bearerFormat: + type: string + MutalTLS: + $anchor: MutualTLS + properties: + type: + const: mutualTLS + OAuth2: + $anchor: OAuth2 + required: + - flows + properties: + type: + const: oauth2 + flows: + $ref: '#OAuthFlows' + OpenIdConnect: + $anchor: OpenIdConnect + required: + - openIdConnectUrl + properties: + type: + const: openIdConnect + openIdConnectUrl: + type: string + format: uri + OAuthFlows: + $anchor: OAuthFlows + type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/Extensible' + properties: + implicit: + allOf: + - required: + - scopes + - $ref: '#CommonFlow' + - $ref: '#AuthorizationFlow' + - $ref: '#/$defs/Mixins/$defs/Extensible' + unevaluatedProperties: false + password: + allOf: + - $ref: '#CommonFlow' + - $ref: '#TokenFlow' + - $ref: '#/$defs/Mixins/$defs/Extensible' + unevaluatedProperties: false + clientCredentials: + allOf: + - $ref: '#CommonFlow' + - $ref: '#TokenFlow' + - $ref: '#/$defs/Mixins/$defs/Extensible' + unevaluatedProperties: false + authorizationCode: + allOf: + - $ref: '#CommonFlow' + - $ref: '#TokenFlow' + - $ref: '#AuthorizationFlow' + - $ref: '#/$defs/Mixins/$defs/Extensible' + unevaluatedProperties: false + unevaluatedProperties: false + $defs: + Common: + $anchor: CommonFlow + properties: + refreshUrl: + type: string + format: uri-reference + scopes: + type: object + additionalProperties: + type: string + Token: + $anchor: TokenFlow + required: + - tokenUrl + properties: + tokenUrl: + type: string + format: uri-reference + Authorization: + $anchor: AuthorizationFlow + required: + - authorizationUrl + properties: + authorizationUrl: + type: string + format: uri-reference + Link: + $anchor: Link + oneOf: + - $ref: '#Reference' + - type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/Describable' + - $ref: '#/$defs/Mixins/$defs/Extensible' + oneOf: + - properties: + operationRef: + type: string + format: uri-reference + operationId: false + - properties: + operationRef: false + operationId: + type: string + properties: + parameters: + type: object + additionalProperties: true + requestBody: true + server: + $ref: '#Server' + unevaluatedProperties: false + Callback: + $anchor: Callback + oneOf: + - $ref: '#Reference' + - type: object + allOf: + - $ref: '#/$defs/Mixins/$defs/Extensible' + additionalProperties: + $ref: '#PathItem' + unevaluatedProperties: false + Schema: + $anchor: Schema + oneOf: + - $ref: '#Reference' + - type: object + allOf: + - $ref: 'https://json-schema.org/draft/2020-12/schema' + - $ref: '#SchemaExtensions' + - $ref: '#/$defs/Mixins/$defs/Extensible' + unevaluatedProperties: false + $defs: + Extensions: + $anchor: SchemaExtensions + properties: + discriminator: + $ref: '#Discriminator' + externalDocs: + $ref: '#ExternalDocumentation' + xml: + $ref: '#XML' + example: + deprecated: true + Discriminator: + $anchor: Discriminator + type: object + required: + - propertyName + properties: + propertyName: + type: string + mapping: + type: object + additionalProperties: + type: string + XML: + $anchor: XML + allOf: + - $ref: '#/$defs/Mixins/$defs/Extensible' + - type: object + properties: + name: + type: string + namespace: + type: string + format: url + prefix: + type: string + attribute: + type: boolean + default: false + wrapped: + type: boolean + default: false + unevaluatedProperties: false + Components: + $anchor: Components + type: object + $ref: '#/$defs/Mixins/$defs/Extensible' + patternProperties: + '': + $comment: All sub-objects have the same property name constraints + propertyNames: + pattern: '^[a-zA-Z0-9\.\-_]+$' + properties: + schemas: + additionalProperties: + $ref: '#Schema' + responses: + additionalProperties: + $ref: '#Response' + parameters: + additionalProperties: + $ref: '#Parameter' + pathItems: + additionalProperties: + $ref: '#PathItem' + examples: + additionalProperties: + $ref: '#Example' + requestBodies: + additionalProperties: + $ref: '#RequestBody' + headers: + additionalProperties: + $ref: '#Header' + links: + additionalProperties: + $ref: '#Link' + callbacks: + additionalProperties: + $ref: '#Callback' + unevaluatedProperties: false diff --git a/schemas/v3.1/validate.js b/schemas/v3.1/validate.js new file mode 100644 index 0000000000..dcb9fadfee --- /dev/null +++ b/schemas/v3.1/validate.js @@ -0,0 +1,19 @@ +const JsonSchema = require("@hyperjump/json-schema"); +JsonSchema.setMetaOutputFormat(JsonSchema.BASIC); +JsonSchema.setShouldMetaValidate(false); +(async function () { + try { + // Compile / meta-validate + const schema = await JsonSchema.get(`file://${__dirname}/schema.json`); + const validateSchema = await JsonSchema.validate(schema); + // Validate instance + const instance = ""; + const results = validateSchema(instance, JsonSchema.DETAILED); + console.log(JSON.stringify(results, null, " ")); + } catch (error) { + console.log("************* Error ***************"); + console.log(error); + console.log(JSON.stringify(error.output, null, " ")); + //console.log(error.output); + } +}());