scorpio 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +6 -1
- data/CHANGELOG.md +10 -2
- data/LICENSE.md +2 -4
- data/README.md +81 -67
- data/documents/{github.com/OAI/OpenAPI-Specification/blob/oas3-schema/schemas/v3.0 → spec.openapis.org/oas/3.0}/schema.yaml +164 -628
- data/documents/spec.openapis.org/oas/3.1/dialect/base.schema.yaml +22 -0
- data/documents/spec.openapis.org/oas/3.1/meta/base.schema.yaml +71 -0
- data/documents/spec.openapis.org/oas/3.1/schema-base.yaml +21 -0
- data/documents/spec.openapis.org/oas/3.1/schema.yaml +980 -0
- data/documents/swagger.io/v2/schema.json +1 -1
- data/documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest.yml +44 -4
- data/lib/scorpio/google_api_document.rb +121 -193
- data/lib/scorpio/openapi/document.rb +63 -31
- data/lib/scorpio/openapi/operation.rb +114 -96
- data/lib/scorpio/openapi/operations_scope.rb +35 -19
- data/lib/scorpio/openapi/reference.rb +88 -23
- data/lib/scorpio/openapi/schema_elements/type_nullable.rb +38 -0
- data/lib/scorpio/openapi/schema_elements.rb +7 -0
- data/lib/scorpio/openapi/server.rb +34 -0
- data/lib/scorpio/openapi/tag.rb +19 -3
- data/lib/scorpio/openapi/v2/dialect.rb +66 -0
- data/lib/scorpio/openapi/v2.rb +124 -0
- data/lib/scorpio/openapi/v3_0/dialect.rb +76 -0
- data/lib/scorpio/openapi/v3_0.rb +130 -0
- data/lib/scorpio/openapi/v3_1.rb +243 -0
- data/lib/scorpio/openapi.rb +23 -203
- data/lib/scorpio/request.rb +67 -61
- data/lib/scorpio/resource_base.rb +57 -49
- data/lib/scorpio/response.rb +28 -10
- data/lib/scorpio/ur.rb +7 -3
- data/lib/scorpio/version.rb +1 -1
- data/lib/scorpio.rb +12 -6
- data/pages/Request_Configuration.md +69 -0
- data/pages/Security.md +50 -0
- data/scorpio.gemspec +6 -5
- metadata +28 -15
- data/documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest +0 -684
- data/lib/scorpio/openapi/v3/server.rb +0 -44
data/lib/scorpio/openapi/tag.rb
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
module Scorpio
|
|
2
2
|
module OpenAPI
|
|
3
3
|
module Tag
|
|
4
|
+
include(Document::Descendent)
|
|
5
|
+
|
|
4
6
|
# operations in the openapi document which have a tag with this tag's name
|
|
5
7
|
# @return [Enumerable<Scorpio::OpenAPI::Operation>]
|
|
6
8
|
def operations
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
return(@operations) if instance_variable_defined?(:@operations)
|
|
10
|
+
@operations = OperationsScope.new(each_operation)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @yield [OpenAPI::Operation]
|
|
14
|
+
def each_operation(&block)
|
|
15
|
+
return(to_enum(__method__)) unless block
|
|
16
|
+
|
|
17
|
+
openapi_document.each_operation do |op|
|
|
18
|
+
yield(op) if op.tags.respond_to?(:to_ary) && op.tags.include?(name)
|
|
9
19
|
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
10
22
|
|
|
11
|
-
|
|
23
|
+
module Tags
|
|
24
|
+
# a tag with the given name
|
|
25
|
+
# @return [OpenAPI::Tag, nil]
|
|
26
|
+
def named(name)
|
|
27
|
+
detect { |tag| tag.name == name }
|
|
12
28
|
end
|
|
13
29
|
end
|
|
14
30
|
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Scorpio
|
|
4
|
+
module OpenAPI::V2
|
|
5
|
+
VOCABULARY = JSI::Schema::Vocabulary.new(
|
|
6
|
+
elements: [
|
|
7
|
+
JSI::Schema::Elements::SELF[],
|
|
8
|
+
|
|
9
|
+
JSI::Schema::Elements::REF[exclusive: true],
|
|
10
|
+
|
|
11
|
+
JSI::Schema::Elements::MULTIPLE_OF[],
|
|
12
|
+
|
|
13
|
+
JSI::Schema::Elements::MAXIMUM_BOOLEAN_EXCLUSIVE[],
|
|
14
|
+
|
|
15
|
+
JSI::Schema::Elements::MINIMUM_BOOLEAN_EXCLUSIVE[],
|
|
16
|
+
|
|
17
|
+
JSI::Schema::Elements::MAX_LENGTH[],
|
|
18
|
+
|
|
19
|
+
JSI::Schema::Elements::MIN_LENGTH[],
|
|
20
|
+
|
|
21
|
+
JSI::Schema::Elements::PATTERN[],
|
|
22
|
+
|
|
23
|
+
# TODO this should not include additionalItems
|
|
24
|
+
JSI::Schema::Elements::ITEMS[],
|
|
25
|
+
|
|
26
|
+
JSI::Schema::Elements::MAX_ITEMS[],
|
|
27
|
+
|
|
28
|
+
JSI::Schema::Elements::MIN_ITEMS[],
|
|
29
|
+
|
|
30
|
+
JSI::Schema::Elements::UNIQUE_ITEMS[],
|
|
31
|
+
|
|
32
|
+
JSI::Schema::Elements::MAX_PROPERTIES[],
|
|
33
|
+
|
|
34
|
+
JSI::Schema::Elements::MIN_PROPERTIES[],
|
|
35
|
+
|
|
36
|
+
JSI::Schema::Elements::REQUIRED[],
|
|
37
|
+
|
|
38
|
+
# TODO this should not include patternProperties
|
|
39
|
+
JSI::Schema::Elements::PROPERTIES[],
|
|
40
|
+
|
|
41
|
+
JSI::Schema::Elements::ENUM[],
|
|
42
|
+
|
|
43
|
+
JSI::Schema::Elements::TYPE[],
|
|
44
|
+
|
|
45
|
+
JSI::Schema::Elements::ALL_OF[],
|
|
46
|
+
|
|
47
|
+
JSI::Schema::Elements::INFO_STRING[keyword: 'title'],
|
|
48
|
+
JSI::Schema::Elements::INFO_STRING[keyword: 'description'],
|
|
49
|
+
|
|
50
|
+
JSI::Schema::Elements::INFO_BOOL[keyword: 'readOnly'],
|
|
51
|
+
|
|
52
|
+
JSI::Schema::Elements::DEFAULT[],
|
|
53
|
+
|
|
54
|
+
JSI::Schema::Elements::FORMAT[],
|
|
55
|
+
|
|
56
|
+
JSI::Schema::Element.new(keyword: 'example') { }, # no actions
|
|
57
|
+
],
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# https://spec.openapis.org/oas/v2.0.html#schema-object
|
|
61
|
+
DIALECT = JSI::Schema::Dialect.new(
|
|
62
|
+
vocabularies: [VOCABULARY],
|
|
63
|
+
integer_disallows_0_fraction: true,
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Scorpio
|
|
4
|
+
module OpenAPI
|
|
5
|
+
module V2
|
|
6
|
+
autoload(:DIALECT, 'scorpio/openapi/v2/dialect')
|
|
7
|
+
|
|
8
|
+
describe_schema_ptrs = Set[
|
|
9
|
+
# this schema (Scorpio::OpenAPI::V2::Schema) describes schemas in an OpenAPI document.
|
|
10
|
+
JSI::Ptr['definitions', 'schema'],
|
|
11
|
+
# this schema describes a boolean schema, only allowed for 'additionalProperties'
|
|
12
|
+
JSI::Ptr['definitions', 'schema', 'properties', 'additionalProperties', 'anyOf', 1],
|
|
13
|
+
].freeze
|
|
14
|
+
|
|
15
|
+
Document = JSI.new_schema_module(JSON.parse(Scorpio.root.join(
|
|
16
|
+
'documents/swagger.io/v2/schema.json'
|
|
17
|
+
).read, freeze: true))
|
|
18
|
+
|
|
19
|
+
describe_schema_ptrs.each do |ptr|
|
|
20
|
+
(Document / ptr).describes_schema!(DIALECT)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# naming these is not strictly necessary, but is nice to have.
|
|
24
|
+
# generated: `puts Scorpio::OpenAPI::V2::Document.schema.definitions.keys.map { |k| "#{k[0].upcase}#{k[1..-1]} = Document.definitions['#{k}']" }`
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Info = Document.definitions['info']
|
|
28
|
+
Contact = Document.definitions['contact']
|
|
29
|
+
License = Document.definitions['license']
|
|
30
|
+
Paths = Document.definitions['paths']
|
|
31
|
+
Definitions = Document.definitions['definitions']
|
|
32
|
+
ParameterDefinitions = Document.definitions['parameterDefinitions']
|
|
33
|
+
ResponseDefinitions = Document.definitions['responseDefinitions']
|
|
34
|
+
ExternalDocs = Document.definitions['externalDocs']
|
|
35
|
+
Examples = Document.definitions['examples']
|
|
36
|
+
MimeType = Document.definitions['mimeType']
|
|
37
|
+
Operation = Document.definitions['operation']
|
|
38
|
+
PathItem = Document.definitions['pathItem']
|
|
39
|
+
Responses = Document.definitions['responses']
|
|
40
|
+
ResponseValue = Document.definitions['responseValue']
|
|
41
|
+
Response = Document.definitions['response']
|
|
42
|
+
Headers = Document.definitions['headers']
|
|
43
|
+
Header = Document.definitions['header']
|
|
44
|
+
VendorExtension = Document.definitions['vendorExtension']
|
|
45
|
+
BodyParameter = Document.definitions['bodyParameter']
|
|
46
|
+
HeaderParameterSubSchema = Document.definitions['headerParameterSubSchema']
|
|
47
|
+
QueryParameterSubSchema = Document.definitions['queryParameterSubSchema']
|
|
48
|
+
FormDataParameterSubSchema = Document.definitions['formDataParameterSubSchema']
|
|
49
|
+
PathParameterSubSchema = Document.definitions['pathParameterSubSchema']
|
|
50
|
+
NonBodyParameter = Document.definitions['nonBodyParameter']
|
|
51
|
+
Parameter = Document.definitions['parameter']
|
|
52
|
+
Schema = Document.definitions['schema']
|
|
53
|
+
FileSchema = Document.definitions['fileSchema']
|
|
54
|
+
PrimitivesItems = Document.definitions['primitivesItems']
|
|
55
|
+
Security = Document.definitions['security']
|
|
56
|
+
SecurityRequirement = Document.definitions['securityRequirement']
|
|
57
|
+
Xml = Document.definitions['xml']
|
|
58
|
+
Tag = Document.definitions['tag']
|
|
59
|
+
SecurityDefinitions = Document.definitions['securityDefinitions']
|
|
60
|
+
BasicAuthenticationSecurity = Document.definitions['basicAuthenticationSecurity']
|
|
61
|
+
ApiKeySecurity = Document.definitions['apiKeySecurity']
|
|
62
|
+
OAuth2ImplicitSecurity = Document.definitions['oauth2ImplicitSecurity']
|
|
63
|
+
OAuth2PasswordSecurity = Document.definitions['oauth2PasswordSecurity']
|
|
64
|
+
OAuth2ApplicationSecurity = Document.definitions['oauth2ApplicationSecurity']
|
|
65
|
+
OAuth2AccessCodeSecurity = Document.definitions['oauth2AccessCodeSecurity']
|
|
66
|
+
OAuth2Scopes = Document.definitions['oauth2Scopes']
|
|
67
|
+
MediaTypeList = Document.definitions['mediaTypeList']
|
|
68
|
+
ParametersList = Document.definitions['parametersList']
|
|
69
|
+
SchemesList = Document.definitions['schemesList']
|
|
70
|
+
CollectionFormat = Document.definitions['collectionFormat']
|
|
71
|
+
CollectionFormatWithMulti = Document.definitions['collectionFormatWithMulti']
|
|
72
|
+
Title = Document.definitions['title']
|
|
73
|
+
Description = Document.definitions['description']
|
|
74
|
+
Default = Document.definitions['default']
|
|
75
|
+
MultipleOf = Document.definitions['multipleOf']
|
|
76
|
+
Maximum = Document.definitions['maximum']
|
|
77
|
+
ExclusiveMaximum = Document.definitions['exclusiveMaximum']
|
|
78
|
+
Minimum = Document.definitions['minimum']
|
|
79
|
+
ExclusiveMinimum = Document.definitions['exclusiveMinimum']
|
|
80
|
+
MaxLength = Document.definitions['maxLength']
|
|
81
|
+
MinLength = Document.definitions['minLength']
|
|
82
|
+
Pattern = Document.definitions['pattern']
|
|
83
|
+
MaxItems = Document.definitions['maxItems']
|
|
84
|
+
MinItems = Document.definitions['minItems']
|
|
85
|
+
UniqueItems = Document.definitions['uniqueItems']
|
|
86
|
+
Enum = Document.definitions['enum']
|
|
87
|
+
JsonReference = Document.definitions['jsonReference']
|
|
88
|
+
|
|
89
|
+
module Operation
|
|
90
|
+
include(OpenAPI::Operation::V2Methods)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# A document that defines or describes an API conforming to the OpenAPI Specification v2 (aka Swagger).
|
|
94
|
+
#
|
|
95
|
+
# The root document is known as the Swagger Object.
|
|
96
|
+
module Document
|
|
97
|
+
include(OpenAPI::Document::V2Methods)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
module JsonReference
|
|
101
|
+
include(OpenAPI::Reference)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
module Tag
|
|
105
|
+
include(OpenAPI::Tag)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
Document.properties["tags"].include(OpenAPI::Tags)
|
|
109
|
+
|
|
110
|
+
module Paths
|
|
111
|
+
include(OpenAPI::Paths)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
module PathItem
|
|
115
|
+
include(OpenAPI::PathItem)
|
|
116
|
+
include(OpenAPI::Reference)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
module Response
|
|
120
|
+
include(OpenAPI::Response)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Scorpio
|
|
4
|
+
module OpenAPI::V3_0
|
|
5
|
+
VOCABULARY = JSI::Schema::Vocabulary.new(
|
|
6
|
+
elements: [
|
|
7
|
+
JSI::Schema::Elements::SELF[],
|
|
8
|
+
|
|
9
|
+
JSI::Schema::Elements::REF[exclusive: true],
|
|
10
|
+
|
|
11
|
+
JSI::Schema::Elements::MULTIPLE_OF[],
|
|
12
|
+
|
|
13
|
+
JSI::Schema::Elements::MAXIMUM_BOOLEAN_EXCLUSIVE[],
|
|
14
|
+
|
|
15
|
+
JSI::Schema::Elements::MINIMUM_BOOLEAN_EXCLUSIVE[],
|
|
16
|
+
|
|
17
|
+
JSI::Schema::Elements::MAX_LENGTH[],
|
|
18
|
+
|
|
19
|
+
JSI::Schema::Elements::MIN_LENGTH[],
|
|
20
|
+
|
|
21
|
+
JSI::Schema::Elements::PATTERN[],
|
|
22
|
+
|
|
23
|
+
JSI::Schema::Elements::MAX_ITEMS[],
|
|
24
|
+
|
|
25
|
+
JSI::Schema::Elements::MIN_ITEMS[],
|
|
26
|
+
|
|
27
|
+
JSI::Schema::Elements::UNIQUE_ITEMS[],
|
|
28
|
+
|
|
29
|
+
JSI::Schema::Elements::MAX_PROPERTIES[],
|
|
30
|
+
|
|
31
|
+
JSI::Schema::Elements::MIN_PROPERTIES[],
|
|
32
|
+
|
|
33
|
+
JSI::Schema::Elements::REQUIRED[],
|
|
34
|
+
|
|
35
|
+
JSI::Schema::Elements::ENUM[],
|
|
36
|
+
|
|
37
|
+
OpenAPI::SchemaElements::TYPE_NULLABLE,
|
|
38
|
+
|
|
39
|
+
JSI::Schema::Elements::ALL_OF[],
|
|
40
|
+
JSI::Schema::Elements::ONE_OF[],
|
|
41
|
+
JSI::Schema::Elements::ANY_OF[],
|
|
42
|
+
|
|
43
|
+
JSI::Schema::Elements::NOT[],
|
|
44
|
+
|
|
45
|
+
# TODO this should not include additionalItems
|
|
46
|
+
JSI::Schema::Elements::ITEMS[],
|
|
47
|
+
|
|
48
|
+
# TODO this should not include patternProperties
|
|
49
|
+
JSI::Schema::Elements::PROPERTIES[],
|
|
50
|
+
|
|
51
|
+
JSI::Schema::Elements::INFO_STRING[keyword: 'title'],
|
|
52
|
+
JSI::Schema::Elements::INFO_STRING[keyword: 'description'],
|
|
53
|
+
|
|
54
|
+
JSI::Schema::Elements::INFO_BOOL[keyword: 'readOnly'],
|
|
55
|
+
JSI::Schema::Elements::INFO_BOOL[keyword: 'writeOnly'],
|
|
56
|
+
JSI::Schema::Elements::INFO_BOOL[keyword: 'deprecated'],
|
|
57
|
+
|
|
58
|
+
JSI::Schema::Elements::DEFAULT[],
|
|
59
|
+
|
|
60
|
+
JSI::Schema::Elements::FORMAT[],
|
|
61
|
+
|
|
62
|
+
JSI::Schema::Element.new(keyword: 'externalDocs') { }, # no actions
|
|
63
|
+
JSI::Schema::Element.new(keyword: 'example') { }, # no actions
|
|
64
|
+
|
|
65
|
+
# TODO `discriminator`
|
|
66
|
+
# TODO `xml`
|
|
67
|
+
],
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# https://spec.openapis.org/oas/v3.0.4.html#schema-object
|
|
71
|
+
DIALECT = JSI::Schema::Dialect.new(
|
|
72
|
+
vocabularies: [VOCABULARY],
|
|
73
|
+
integer_disallows_0_fraction: true,
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Scorpio
|
|
4
|
+
module OpenAPI
|
|
5
|
+
module V3_0
|
|
6
|
+
autoload(:DIALECT, 'scorpio/openapi/v3_0/dialect')
|
|
7
|
+
|
|
8
|
+
describe_schema_ptrs = Set[
|
|
9
|
+
# this schema (Scorpio::OpenAPI::V3_0::Schema) describes schemas in an OpenAPI document.
|
|
10
|
+
JSI::Ptr['definitions', 'Schema'],
|
|
11
|
+
# /definitions/Schema does not allow $ref; this schema describes a schema with a $ref.
|
|
12
|
+
JSI::Ptr['definitions', 'SchemaReference'],
|
|
13
|
+
# this schema describes a boolean schema, only allowed for 'additionalProperties'
|
|
14
|
+
JSI::Ptr['definitions', 'Schema', 'properties', 'additionalProperties', 'oneOf', 2],
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
Document = JSI::JSONSchemaDraft04.new_schema_module(YAML.safe_load(Scorpio.root.join(
|
|
18
|
+
'documents/spec.openapis.org/oas/3.0/schema.yaml'
|
|
19
|
+
).read))
|
|
20
|
+
|
|
21
|
+
describe_schema_ptrs.each do |ptr|
|
|
22
|
+
(Document / ptr).describes_schema!(DIALECT)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# naming these is not strictly necessary, but is nice to have.
|
|
26
|
+
# generated: `puts Scorpio::OpenAPI::V3_0::Document.schema.definitions.keys.map { |k| "#{k[0].upcase}#{k[1..-1]} = Document.definitions['#{k}']" }`
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
Reference = Document.definitions['Reference']
|
|
30
|
+
SchemaReference = Document.definitions['SchemaReference']
|
|
31
|
+
Info = Document.definitions['Info']
|
|
32
|
+
Contact = Document.definitions['Contact']
|
|
33
|
+
License = Document.definitions['License']
|
|
34
|
+
Server = Document.definitions['Server']
|
|
35
|
+
ServerVariable = Document.definitions['ServerVariable']
|
|
36
|
+
Components = Document.definitions['Components']
|
|
37
|
+
Schema = Document.definitions['Schema']
|
|
38
|
+
Discriminator = Document.definitions['Discriminator']
|
|
39
|
+
XML = Document.definitions['XML']
|
|
40
|
+
Response = Document.definitions['Response']
|
|
41
|
+
MediaType = Document.definitions['MediaType']
|
|
42
|
+
Example = Document.definitions['Example']
|
|
43
|
+
Header = Document.definitions['Header']
|
|
44
|
+
Paths = Document.definitions['Paths']
|
|
45
|
+
PathItem = Document.definitions['PathItem']
|
|
46
|
+
Operation = Document.definitions['Operation']
|
|
47
|
+
Responses = Document.definitions['Responses']
|
|
48
|
+
SecurityRequirement = Document.definitions['SecurityRequirement']
|
|
49
|
+
Tag = Document.definitions['Tag']
|
|
50
|
+
ExternalDocumentation = Document.definitions['ExternalDocumentation']
|
|
51
|
+
Parameter = Document.definitions['Parameter']
|
|
52
|
+
PathParameter = Document.definitions['PathParameter']
|
|
53
|
+
QueryParameter = Document.definitions['QueryParameter']
|
|
54
|
+
HeaderParameter = Document.definitions['HeaderParameter']
|
|
55
|
+
CookieParameter = Document.definitions['CookieParameter']
|
|
56
|
+
RequestBody = Document.definitions['RequestBody']
|
|
57
|
+
SecurityScheme = Document.definitions['SecurityScheme']
|
|
58
|
+
APIKeySecurityScheme = Document.definitions['APIKeySecurityScheme']
|
|
59
|
+
HTTPSecurityScheme = Document.definitions['HTTPSecurityScheme']
|
|
60
|
+
OAuth2SecurityScheme = Document.definitions['OAuth2SecurityScheme']
|
|
61
|
+
OpenIdConnectSecurityScheme = Document.definitions['OpenIdConnectSecurityScheme']
|
|
62
|
+
OAuthFlows = Document.definitions['OAuthFlows']
|
|
63
|
+
ImplicitOAuthFlow = Document.definitions['ImplicitOAuthFlow']
|
|
64
|
+
PasswordOAuthFlow = Document.definitions['PasswordOAuthFlow']
|
|
65
|
+
ClientCredentialsFlow = Document.definitions['ClientCredentialsFlow']
|
|
66
|
+
AuthorizationCodeOAuthFlow = Document.definitions['AuthorizationCodeOAuthFlow']
|
|
67
|
+
Link = Document.definitions['Link']
|
|
68
|
+
Callback = Document.definitions['Callback']
|
|
69
|
+
Encoding = Document.definitions['Encoding']
|
|
70
|
+
|
|
71
|
+
module Response
|
|
72
|
+
include(OpenAPI::Response)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Describes a single API operation on a path.
|
|
76
|
+
#
|
|
77
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#operationObject
|
|
78
|
+
module Operation
|
|
79
|
+
include(OpenAPI::Operation::V3Methods)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# A document that defines or describes an API conforming to the OpenAPI Specification v3.0.
|
|
83
|
+
#
|
|
84
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#oasObject
|
|
85
|
+
module Document
|
|
86
|
+
include(OpenAPI::Document::V3Methods)
|
|
87
|
+
|
|
88
|
+
# @return [#to_hash] /components/schemas, if present, or an empty hash
|
|
89
|
+
def components_schemas
|
|
90
|
+
return JSI::Util::EMPTY_HASH unless key?('components') && components.respond_to?(:to_hash)
|
|
91
|
+
return JSI::Util::EMPTY_HASH unless components.key?('schemas') && components.schemas.respond_to?(:to_hash)
|
|
92
|
+
components.schemas
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
module Reference
|
|
97
|
+
include(OpenAPI::Reference)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
module Tag
|
|
101
|
+
include(OpenAPI::Tag)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
Document.properties["tags"].include(OpenAPI::Tags)
|
|
105
|
+
|
|
106
|
+
# An object representing a Server.
|
|
107
|
+
#
|
|
108
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#serverObject
|
|
109
|
+
module Server
|
|
110
|
+
include(OpenAPI::Server)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
module Paths
|
|
114
|
+
include(OpenAPI::Paths)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
module PathItem
|
|
118
|
+
include(OpenAPI::PathItem)
|
|
119
|
+
include(OpenAPI::Reference)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
module SecurityScheme
|
|
123
|
+
include(OpenAPI::SecurityScheme)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# @deprecated after v0.7
|
|
128
|
+
V3 = V3_0
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Scorpio
|
|
4
|
+
module OpenAPI
|
|
5
|
+
module V3_1
|
|
6
|
+
class << self
|
|
7
|
+
attr_accessor(:document_schema_modules_by_dialect_id)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
self.document_schema_modules_by_dialect_id = {}
|
|
11
|
+
|
|
12
|
+
def self.document_name_subschemas(document_schema_module, namespace)
|
|
13
|
+
namespace.const_set(:Info, document_schema_module.defs['info'])
|
|
14
|
+
namespace.const_set(:Contact, document_schema_module.defs['contact'])
|
|
15
|
+
namespace.const_set(:License, document_schema_module.defs['license'])
|
|
16
|
+
namespace.const_set(:Server, document_schema_module.defs['server'])
|
|
17
|
+
namespace.const_set(:ServerVariable, document_schema_module.defs['server-variable'])
|
|
18
|
+
namespace.const_set(:Components, document_schema_module.defs['components'])
|
|
19
|
+
namespace.const_set(:Paths, document_schema_module.defs['paths'])
|
|
20
|
+
namespace.const_set(:PathItem, document_schema_module.defs['path-item'])
|
|
21
|
+
namespace.const_set(:Operation, document_schema_module.defs['operation'])
|
|
22
|
+
namespace.const_set(:ExternalDocumentation, document_schema_module.defs['external-documentation'])
|
|
23
|
+
namespace.const_set(:Parameter, document_schema_module.defs['parameter'])
|
|
24
|
+
namespace.const_set(:RequestBody, document_schema_module.defs['request-body'])
|
|
25
|
+
namespace.const_set(:Content, document_schema_module.defs['content'])
|
|
26
|
+
namespace.const_set(:MediaType, document_schema_module.defs['media-type'])
|
|
27
|
+
namespace.const_set(:Encoding, document_schema_module.defs['encoding'])
|
|
28
|
+
namespace.const_set(:Responses, document_schema_module.defs['responses'])
|
|
29
|
+
namespace.const_set(:Response, document_schema_module.defs['response'])
|
|
30
|
+
namespace.const_set(:Callbacks, document_schema_module.defs['callbacks'])
|
|
31
|
+
namespace.const_set(:Example, document_schema_module.defs['example'])
|
|
32
|
+
namespace.const_set(:Link, document_schema_module.defs['link'])
|
|
33
|
+
namespace.const_set(:Header, document_schema_module.defs['header'])
|
|
34
|
+
namespace.const_set(:Tag, document_schema_module.defs['tag'])
|
|
35
|
+
namespace.const_set(:Reference, document_schema_module.defs['reference'])
|
|
36
|
+
namespace.const_set(:Schema, document_schema_module.defs['schema'])
|
|
37
|
+
namespace.const_set(:SecurityScheme, document_schema_module.defs['security-scheme'])
|
|
38
|
+
namespace.const_set(:OAuthFlows, document_schema_module.defs['oauth-flows'])
|
|
39
|
+
namespace.const_set(:SecurityRequirement, document_schema_module.defs['security-requirement'])
|
|
40
|
+
namespace.const_set(:Examples, document_schema_module.defs['examples'])
|
|
41
|
+
namespace.const_set(:MapOfStrings, document_schema_module.defs['map-of-strings'])
|
|
42
|
+
namespace.const_set(:ExplodeForForm, document_schema_module.defs['explode-for-form'])
|
|
43
|
+
namespace.const_set(:SpecificationExtension, document_schema_module.defs['specification-extensions'].patternProperties["^x-"])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.set_up_document_schema_module(document_schema_module)
|
|
47
|
+
document_schema_module.include(OpenAPI::V3_1::Document)
|
|
48
|
+
document_schema_module.defs['response'].include(OpenAPI::Response)
|
|
49
|
+
document_schema_module.defs['operation'].include(OpenAPI::Operation::V3Methods)
|
|
50
|
+
document_schema_module.defs['reference'].include(OpenAPI::Reference)
|
|
51
|
+
document_schema_module.defs['tag'].include(OpenAPI::Tag)
|
|
52
|
+
document_schema_module.defs['server'].include(OpenAPI::Server)
|
|
53
|
+
document_schema_module.defs['paths'].include(OpenAPI::Paths)
|
|
54
|
+
document_schema_module.defs['path-item'].include(OpenAPI::PathItem)
|
|
55
|
+
document_schema_module.defs['path-item'].include(OpenAPI::Reference)
|
|
56
|
+
document_schema_module.defs['security-scheme'].include(OpenAPI::SecurityScheme)
|
|
57
|
+
|
|
58
|
+
document_schema_module
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# This is pretty much: `Unscoped::Document.with_dynamic_scope_from(JSI.registry.find(dialect_id))`
|
|
62
|
+
# plus {.set_up_document_schema_module}.
|
|
63
|
+
#
|
|
64
|
+
# However, this also supports a dialect whose meta-schema isn't aware of dynamic scope and doesn't
|
|
65
|
+
# have a `$dynamicAnchor: "meta"`, e.g. `jsonSchemaDialect: "http://json-schema.org/draft-07/schema"`.
|
|
66
|
+
#
|
|
67
|
+
# A schema like {Ext::ExtDocument} exists to `$ref` to {Unscoped::Document} with anchor `meta`
|
|
68
|
+
# in dynamic scope, with the `$dynamicAnchor: "meta"` schema `$ref`ing to {Ext::MetaSchema}.
|
|
69
|
+
# This method obviates the need for such a schema, directly applying dynamic scope.
|
|
70
|
+
def self.document_schema_module_by_dialect_id(dialect_id)
|
|
71
|
+
dialect_uri = JSI::Util.uri(dialect_id)
|
|
72
|
+
document_schema_modules_by_dialect_id[dialect_uri] ||= begin
|
|
73
|
+
metaschema = JSI.registry.find(dialect_uri)
|
|
74
|
+
dynamic_anchor_map = metaschema.jsi_next_schema_dynamic_anchor_map
|
|
75
|
+
unless dynamic_anchor_map.key?('meta')
|
|
76
|
+
# hax: pretend that the identified meta-schema has `$dynamicAnchor: "meta"`
|
|
77
|
+
# this enables e.g. `jsonSchemaDialect: "http://json-schema.org/draft-07/schema"` to work
|
|
78
|
+
# this is non-API JSI internals.
|
|
79
|
+
dynamic_anchor_map = dynamic_anchor_map.merge({
|
|
80
|
+
'meta' => [metaschema, [].freeze].freeze,
|
|
81
|
+
}).freeze
|
|
82
|
+
end
|
|
83
|
+
document_schema = Unscoped::Document.schema.jsi_with_schema_dynamic_anchor_map(dynamic_anchor_map)
|
|
84
|
+
set_up_document_schema_module(document_schema.jsi_schema_module)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Instantiates `instance` v3.1 OAD with schemas of the dialect indicated by `jsonSchemaDialect`
|
|
89
|
+
# @param instance [#to_hash]
|
|
90
|
+
# @return [JSI::Base + Scorpio::OpenAPI::V3_1::Document]
|
|
91
|
+
def self.new_document(instance, **new_param)
|
|
92
|
+
#jsonSchemaDialect = Scorpio::OpenAPI::V3_1::Unscoped::Document.new_jsi(instance, **new_param).jsonSchemaDialect(use_default: true)
|
|
93
|
+
jsonSchemaDialect = instance.fetch('jsonSchemaDialect') { Unscoped::Document.properties['jsonSchemaDialect'].default }
|
|
94
|
+
document_schema_module = document_schema_module_by_dialect_id(jsonSchemaDialect)
|
|
95
|
+
|
|
96
|
+
document_schema_module.new_jsi(instance, **new_param)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
module Document
|
|
101
|
+
include(OpenAPI::Document::V3Methods)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# namespace
|
|
106
|
+
module Unscoped
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
Unscoped::Document = JSI.new_schema_module(
|
|
110
|
+
YAML.safe_load(Scorpio.root.join('documents/spec.openapis.org/oas/3.1/schema.yaml').read),
|
|
111
|
+
)
|
|
112
|
+
# Schema module: describes an OpenAPI document, but not normally instantiated.
|
|
113
|
+
#
|
|
114
|
+
# This document schema has no dynamic scope pointing `$dynamicAnchor: "meta"` to a real
|
|
115
|
+
# meta-schema. Schemas in the document described by this are just `type: [object, boolean]`,
|
|
116
|
+
# have no dialect, and are not usable schemas.
|
|
117
|
+
#
|
|
118
|
+
# - $id: `https://spec.openapis.org/oas/3.1/schema/2025-11-23`
|
|
119
|
+
module Unscoped::Document
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# "Ext" is abbreviation for the "OpenAPI extension schema dialect" that extends JSON Schema draft 2020-12
|
|
124
|
+
# and defines keywords: `discriminator`, `example`, `externalDocs`, `xml`.
|
|
125
|
+
# This module is a namespace for that.
|
|
126
|
+
module Ext
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# vocabulary for implementation of keywords: `discriminator`, `example`, `externalDocs`, `xml`
|
|
130
|
+
Ext::VOCAB = JSI::Schema::Vocabulary.new(
|
|
131
|
+
id: "https://spec.openapis.org/oas/3.1/vocab/base",
|
|
132
|
+
elements: [
|
|
133
|
+
# TODO:
|
|
134
|
+
# - discriminator
|
|
135
|
+
# - example
|
|
136
|
+
# - externalDocs
|
|
137
|
+
# - xml
|
|
138
|
+
],
|
|
139
|
+
)
|
|
140
|
+
JSI.registry.register_vocabulary(Ext::VOCAB)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
Ext::ExtDocument = JSI.new_schema_module(
|
|
144
|
+
YAML.safe_load(Scorpio.root.join('documents/spec.openapis.org/oas/3.1/schema-base.yaml').read),
|
|
145
|
+
)
|
|
146
|
+
# Schema module: Describes an OAD with schemas of the OpenAPI extension schema dialect.
|
|
147
|
+
# This exists to dynamically scope the `meta` anchor
|
|
148
|
+
# for {Unscoped::Document} `<https://spec.openapis.org/oas/3.1/schema/2025-11-23>`
|
|
149
|
+
# to {Ext::MetaSchema} `<https://spec.openapis.org/oas/3.1/dialect/2024-11-10>`
|
|
150
|
+
# via `<#/$defs/schema>` {Ext::ExtDocument::Schema}.
|
|
151
|
+
#
|
|
152
|
+
# - $id: `https://spec.openapis.org/oas/3.1/schema-base/2025-11-23`
|
|
153
|
+
# - $ref: {Ext::Document} `<https://spec.openapis.org/oas/3.1/schema/2025-11-23>`
|
|
154
|
+
# - $dynamicAnchor: `meta` in `/$defs/schema` ({Ext::ExtDocument::Schema})
|
|
155
|
+
# - properties: jsonSchemaDialect const {Ext::MetaSchema} `<https://spec.openapis.org/oas/3.1/dialect/2024-11-10>`
|
|
156
|
+
module Ext::ExtDocument
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
Ext::ExtDocument::Schema = Ext::ExtDocument["$defs"]["schema"]
|
|
160
|
+
# Schema module: Describes schemas in an Ext::Document
|
|
161
|
+
#
|
|
162
|
+
# - $dynamicAnchor: `meta`
|
|
163
|
+
# - $ref: {Ext::MetaSchema} `<https://spec.openapis.org/oas/3.1/dialect/2024-11-10>`
|
|
164
|
+
# - properties: $schema const {Ext::MetaSchema} `<https://spec.openapis.org/oas/3.1/dialect/2024-11-10>`
|
|
165
|
+
module Ext::ExtDocument::Schema
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
# Some Ext schemas are used with dynamic scope from {Ext::ExtDocument}; Ext::Unscoped namespace
|
|
170
|
+
# contains those schemas without that dynamic scope. These are not normally instantiated.
|
|
171
|
+
module Ext::Unscoped
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
Ext::Unscoped::VocabSchema = JSI.new_schema_module(
|
|
175
|
+
YAML.safe_load(Scorpio.root.join('documents/spec.openapis.org/oas/3.1/meta/base.schema.yaml').read),
|
|
176
|
+
)
|
|
177
|
+
module Ext::Unscoped::VocabSchema
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
Ext::VocabSchema = Ext::Unscoped::VocabSchema.with_dynamic_scope_from(Ext::ExtDocument)
|
|
181
|
+
# Schema module: vocabulary schema for {Ext::VOCAB}
|
|
182
|
+
#
|
|
183
|
+
# - $id: `https://spec.openapis.org/oas/3.1/meta/2024-11-10`
|
|
184
|
+
# - $dynamicAnchor: `meta` (unused)
|
|
185
|
+
# - properties (schema keywords) discriminator, example, externalDocs, xml
|
|
186
|
+
module Ext::VocabSchema
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
Ext::Unscoped::MetaSchema = JSI.new_schema_module(
|
|
190
|
+
YAML.safe_load(Scorpio.root.join('documents/spec.openapis.org/oas/3.1/dialect/base.schema.yaml').read),
|
|
191
|
+
)
|
|
192
|
+
module Ext::Unscoped::MetaSchema
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
Ext::MetaSchema = Ext::Unscoped::MetaSchema.with_dynamic_scope_from(Ext::ExtDocument)
|
|
196
|
+
Ext::MetaSchema.describes_schema!
|
|
197
|
+
# Schema module: Meta-schema describing schemas within an OpenAPI document with the OpenAPI extension schema dialect
|
|
198
|
+
#
|
|
199
|
+
# - $id: `https://spec.openapis.org/oas/3.1/dialect/2024-11-10`
|
|
200
|
+
# - $dynamicAnchor: `meta` (overridden by dynamic scope with `meta` → {Ext::ExtDocument::Schema})
|
|
201
|
+
# - $vocabulary:
|
|
202
|
+
# - The draft/2020-12 vocabularies - core, applicator, validation, etc (required: true)
|
|
203
|
+
# - {Ext::VOCAB} `<https://spec.openapis.org/oas/3.1/vocab/base>` (required: false)
|
|
204
|
+
# - allOf:
|
|
205
|
+
# - $ref: {Ext::JSONSchemaDraft202012} `<https://json-schema.org/draft/2020-12/schema>`
|
|
206
|
+
# - $ref: {Ext::VocabSchema} `<https://spec.openapis.org/oas/3.1/meta/2024-11-10>`
|
|
207
|
+
module Ext::MetaSchema
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
Ext::Document = Unscoped::Document.with_dynamic_scope_from(Ext::ExtDocument)
|
|
211
|
+
# Schema module: Describes an OpenAPI document containing schemas of the Ext dialect.
|
|
212
|
+
# This is {Unscoped::Document}, with dynamic scope pointing `$dynamicAnchor: "meta"` to {Ext::ExtDocument::Schema}.
|
|
213
|
+
module Ext::Document
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
set_up_document_schema_module(Ext::Document)
|
|
217
|
+
document_name_subschemas(Ext::Document, Ext)
|
|
218
|
+
# note: without this mapping set, document_schema_module_by_dialect_id(Ext::MetaSchema.schema_uri)
|
|
219
|
+
# would be Unscoped::Document.with_dynamic_scope_from(Ext::Unscoped::MetaSchema)
|
|
220
|
+
# instead of Unscoped::Document.with_dynamic_scope_from(Ext::ExtDocument)
|
|
221
|
+
# schemas in OADs with this jsonSchemaDialect would have the right dialect, but
|
|
222
|
+
# Ext::ExtDocument does also validate OAD jsonSchemaDialect and schema $schema properties.
|
|
223
|
+
document_schema_modules_by_dialect_id[Ext::MetaSchema.schema_uri] = Ext::ExtDocument
|
|
224
|
+
|
|
225
|
+
Ext::JSONSchemaDraft202012 = JSI::JSONSchemaDraft202012.with_dynamic_scope_from(Ext::ExtDocument)
|
|
226
|
+
JSI::JSONSchemaDraft202012.name_vocab_schemas(Ext::JSONSchemaDraft202012)
|
|
227
|
+
# JSI::JSONSchemaDraft202012, with dynamic scope pointing `$dynamicAnchor: "meta"` to {Ext::ExtDocument::Schema}.
|
|
228
|
+
module Ext::JSONSchemaDraft202012
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
module JSONSchemaDraft202012
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
JSONSchemaDraft202012::Document = Unscoped::Document.with_dynamic_scope_from(JSI::JSONSchemaDraft202012)
|
|
236
|
+
# Describes an OAD with `jsonSchemaDialect: "https://json-schema.org/draft/2020-12/schema"`
|
|
237
|
+
module JSONSchemaDraft202012::Document
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
document_name_subschemas(JSONSchemaDraft202012::Document, JSONSchemaDraft202012)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|