openapi_contracts 0.8.0 → 0.9.1
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/README.md +41 -20
- data/lib/openapi_contracts/doc/operation.rb +27 -0
- data/lib/openapi_contracts/doc/parameter.rb +22 -59
- data/lib/openapi_contracts/doc/path.rb +23 -38
- data/lib/openapi_contracts/doc/pointer.rb +81 -0
- data/lib/openapi_contracts/doc/request.rb +17 -0
- data/lib/openapi_contracts/doc/response.rb +5 -5
- data/lib/openapi_contracts/doc/schema.rb +49 -10
- data/lib/openapi_contracts/doc/with_parameters.rb +9 -0
- data/lib/openapi_contracts/doc.rb +17 -20
- data/lib/openapi_contracts/match.rb +34 -10
- data/lib/openapi_contracts/operation_router.rb +33 -0
- data/lib/openapi_contracts/parser/transformers/base.rb +15 -0
- data/lib/openapi_contracts/parser/transformers/nullable.rb +10 -0
- data/lib/openapi_contracts/parser/transformers/pointer.rb +34 -0
- data/lib/openapi_contracts/parser/transformers.rb +5 -0
- data/lib/openapi_contracts/parser.rb +61 -0
- data/lib/openapi_contracts/payload_parser.rb +39 -0
- data/lib/openapi_contracts/rspec.rb +2 -2
- data/lib/openapi_contracts/validators/base.rb +5 -1
- data/lib/openapi_contracts/validators/documented.rb +12 -5
- data/lib/openapi_contracts/validators/headers.rb +4 -0
- data/lib/openapi_contracts/validators/http_status.rb +2 -6
- data/lib/openapi_contracts/validators/request_body.rb +26 -0
- data/lib/openapi_contracts/validators/response_body.rb +28 -0
- data/lib/openapi_contracts/validators/schema_validation.rb +40 -0
- data/lib/openapi_contracts/validators.rb +9 -6
- data/lib/openapi_contracts.rb +10 -5
- metadata +32 -22
- data/lib/openapi_contracts/doc/file_parser.rb +0 -85
- data/lib/openapi_contracts/doc/method.rb +0 -18
- data/lib/openapi_contracts/doc/parser.rb +0 -44
- data/lib/openapi_contracts/validators/body.rb +0 -38
@@ -1,11 +1,18 @@
|
|
1
1
|
module OpenapiContracts
|
2
2
|
class Match
|
3
|
+
DEFAULT_OPTIONS = {request_body: false}.freeze
|
4
|
+
MIN_REQUEST_ANCESTORS = %w(Rack::Request::Env Rack::Request::Helpers).freeze
|
5
|
+
MIN_RESPONSE_ANCESTORS = %w(Rack::Response::Helpers).freeze
|
6
|
+
|
3
7
|
attr_reader :errors
|
4
8
|
|
5
9
|
def initialize(doc, response, options = {})
|
6
10
|
@doc = doc
|
7
11
|
@response = response
|
8
|
-
@
|
12
|
+
@request = options.delete(:request) { response.request }
|
13
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
14
|
+
raise ArgumentError, "#{@response} must be compatible with Rack::Response::Helpers" unless response_compatible?
|
15
|
+
raise ArgumentError, "#{@request} must be compatible with Rack::Request::{Env,Helpers}" unless request_compatible?
|
9
16
|
end
|
10
17
|
|
11
18
|
def valid?
|
@@ -17,18 +24,35 @@ module OpenapiContracts
|
|
17
24
|
|
18
25
|
private
|
19
26
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@
|
27
|
+
def matchers
|
28
|
+
env = Env.new(
|
29
|
+
options: @options,
|
30
|
+
operation: operation,
|
31
|
+
request: @request,
|
32
|
+
response: @response
|
25
33
|
)
|
34
|
+
validators = Validators::ALL.dup
|
35
|
+
validators.delete(Validators::HttpStatus) unless @options[:status]
|
36
|
+
validators.delete(Validators::RequestBody) unless @options[:request_body]
|
37
|
+
validators.reverse
|
38
|
+
.reduce(->(err) { err }) { |s, m| m.new(s, env) }
|
26
39
|
end
|
27
40
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
41
|
+
def operation
|
42
|
+
@doc.operation_for(
|
43
|
+
@options.fetch(:path, @request.path),
|
44
|
+
@request.request_method.downcase
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def request_compatible?
|
49
|
+
ancestors = @request.class.ancestors.map(&:to_s)
|
50
|
+
MIN_REQUEST_ANCESTORS.all? { |s| ancestors.include?(s) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def response_compatible?
|
54
|
+
ancestors = @response.class.ancestors.map(&:to_s)
|
55
|
+
MIN_RESPONSE_ANCESTORS.all? { |s| ancestors.include?(s) }
|
32
56
|
end
|
33
57
|
end
|
34
58
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module OpenapiContracts
|
2
|
+
class OperationRouter
|
3
|
+
def initialize(doc)
|
4
|
+
@doc = doc
|
5
|
+
@dynamic_paths = doc.paths.select(&:dynamic?)
|
6
|
+
end
|
7
|
+
|
8
|
+
def route(actual_path, method)
|
9
|
+
@doc.with_path(actual_path)&.then { |p| return p.with_method(method) }
|
10
|
+
|
11
|
+
@dynamic_paths.each do |path|
|
12
|
+
next unless path.supports_method?(method)
|
13
|
+
next unless m = path.path_regexp.match(actual_path)
|
14
|
+
|
15
|
+
operation = path.with_method(method)
|
16
|
+
parameters = (path.parameters + operation.parameters).select(&:in_path?)
|
17
|
+
|
18
|
+
return operation if parameter_match?(m.named_captures, parameters)
|
19
|
+
end
|
20
|
+
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def parameter_match?(actual_params, parameters)
|
27
|
+
actual_params.each do |k, v|
|
28
|
+
return false unless parameters&.find { |s| s.name == k }&.matches?(v)
|
29
|
+
end
|
30
|
+
true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module OpenapiContracts::Parser::Transformers
|
2
|
+
class Pointer < Base
|
3
|
+
def call(object)
|
4
|
+
return unless object['$ref'].present?
|
5
|
+
|
6
|
+
object['$ref'] = transform_pointer(object['$ref'])
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def transform_pointer(target)
|
12
|
+
if %r{^#/(?<pointer>.*)} =~ target
|
13
|
+
# A JSON Pointer
|
14
|
+
generate_absolute_pointer(pointer)
|
15
|
+
elsif %r{^(?<relpath>[^#]+)(?:#/(?<pointer>.*))?} =~ target
|
16
|
+
ptr = @parser.filenesting[@cwd.join(relpath)]
|
17
|
+
tgt = ptr.to_json_pointer
|
18
|
+
tgt += "/#{pointer}" if pointer
|
19
|
+
tgt
|
20
|
+
else
|
21
|
+
target
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# A JSON pointer to the currently parsed file as seen from the root openapi file
|
26
|
+
def generate_absolute_pointer(json_pointer)
|
27
|
+
if @pointer.empty?
|
28
|
+
"#/#{json_pointer}"
|
29
|
+
else
|
30
|
+
"#{@pointer.to_json_pointer}/#{json_pointer}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module OpenapiContracts
|
2
|
+
class Parser
|
3
|
+
autoload :Transformers, 'openapi_contracts/parser/transformers'
|
4
|
+
|
5
|
+
TRANSFORMERS = [Transformers::Nullable, Transformers::Pointer].freeze
|
6
|
+
|
7
|
+
def self.call(dir, filename)
|
8
|
+
new(dir.join(filename)).parse
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :filenesting, :rootfile
|
12
|
+
|
13
|
+
def initialize(rootfile)
|
14
|
+
@cwd = rootfile.parent
|
15
|
+
@rootfile = rootfile
|
16
|
+
@filenesting = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse
|
20
|
+
@filenesting = build_file_list
|
21
|
+
@filenesting.each_with_object({}) do |(path, pointer), schema|
|
22
|
+
target = pointer.to_a.reduce(schema) { |d, k| d[k] ||= {} }
|
23
|
+
target.delete('$ref') # ref file pointers must be replaced
|
24
|
+
target.merge! file_to_data(path, pointer)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def build_file_list
|
31
|
+
list = {@rootfile.relative_path_from(@cwd) => Doc::Pointer[]}
|
32
|
+
Dir[File.expand_path('components/**/*.yaml', @cwd)].each do |file|
|
33
|
+
pathname = Pathname(file).relative_path_from(@cwd)
|
34
|
+
pointer = Doc::Pointer.from_path pathname.sub_ext('')
|
35
|
+
list.merge! pathname => pointer
|
36
|
+
end
|
37
|
+
YAML.safe_load_file(@rootfile).fetch('paths') { {} }.each_pair do |k, v|
|
38
|
+
next unless v['$ref'] && !v['$ref'].start_with?('#')
|
39
|
+
|
40
|
+
list.merge! Pathname(v['$ref']) => Doc::Pointer['paths', k]
|
41
|
+
end
|
42
|
+
list
|
43
|
+
end
|
44
|
+
|
45
|
+
def file_to_data(pathname, pointer)
|
46
|
+
YAML.safe_load_file(@cwd.join(pathname)).tap do |data|
|
47
|
+
transform_objects!(data, pathname.parent, pointer)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def transform_objects!(object, cwd, pointer)
|
52
|
+
case object
|
53
|
+
when Hash
|
54
|
+
object.each_value { |v| transform_objects!(v, cwd, pointer) }
|
55
|
+
TRANSFORMERS.map { |t| t.new(self, cwd, pointer) }.each { |t| t.call(object) }
|
56
|
+
when Array
|
57
|
+
object.each { |o| transform_objects!(o, cwd, pointer) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module OpenapiContracts
|
4
|
+
class PayloadParser
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
class << self
|
8
|
+
delegate :parse, :register, to: :instance
|
9
|
+
end
|
10
|
+
|
11
|
+
Entry = Struct.new(:matcher, :parser) do
|
12
|
+
def call(raw)
|
13
|
+
parser.call(raw)
|
14
|
+
end
|
15
|
+
|
16
|
+
def match?(media_type)
|
17
|
+
matcher == media_type || matcher.match?(media_type)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@parsers = []
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse(media_type, payload)
|
26
|
+
parser = @parsers.find { |e| e.match?(media_type) }
|
27
|
+
raise ArgumentError, "#{media_type.inspect} is not supported yet" unless parser
|
28
|
+
|
29
|
+
parser.call(payload)
|
30
|
+
end
|
31
|
+
|
32
|
+
def register(matcher, parser)
|
33
|
+
@parsers << Entry.new(matcher, parser)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
PayloadParser.register(%r{(/|\+)json$}, ->(raw) { JSON(raw) })
|
38
|
+
PayloadParser.register('application/x-www-form-urlencoded', ->(raw) { Rack::Utils.parse_nested_query(raw) })
|
39
|
+
end
|
@@ -14,12 +14,12 @@ RSpec::Matchers.define :match_openapi_doc do |doc, options = {}| # rubocop:disab
|
|
14
14
|
end
|
15
15
|
|
16
16
|
description do
|
17
|
-
desc = '
|
17
|
+
desc = 'match the openapi schema'
|
18
18
|
desc << " with #{http_status_desc(@status)}" if @status
|
19
19
|
desc
|
20
20
|
end
|
21
21
|
|
22
|
-
failure_message do |
|
22
|
+
failure_message do |_response|
|
23
23
|
@errors.map { |e| "* #{e}" }.join("\n")
|
24
24
|
end
|
25
25
|
|
@@ -22,7 +22,11 @@ module OpenapiContracts::Validators
|
|
22
22
|
|
23
23
|
private
|
24
24
|
|
25
|
-
delegate :
|
25
|
+
delegate :operation, :options, :request, :response, to: :@env
|
26
|
+
|
27
|
+
def response_desc
|
28
|
+
"#{request.request_method} #{request.path}"
|
29
|
+
end
|
26
30
|
|
27
31
|
# :nocov:
|
28
32
|
def validate
|
@@ -1,18 +1,25 @@
|
|
1
1
|
module OpenapiContracts::Validators
|
2
|
+
# Purpose of this validator
|
3
|
+
# * ensure the operation is documented (combination http-method + path)
|
4
|
+
# * ensure the response-status is documented on the operation
|
2
5
|
class Documented < Base
|
3
6
|
self.final = true
|
4
7
|
|
5
8
|
private
|
6
9
|
|
7
10
|
def validate
|
8
|
-
return
|
11
|
+
return operation_missing unless operation
|
9
12
|
|
10
|
-
|
11
|
-
|
13
|
+
response_missing unless operation.response_for_status(response.status)
|
14
|
+
end
|
15
|
+
|
16
|
+
def operation_missing
|
17
|
+
@errors << "Undocumented operation for #{response_desc.inspect}"
|
12
18
|
end
|
13
19
|
|
14
|
-
def
|
15
|
-
|
20
|
+
def response_missing
|
21
|
+
status_desc = http_status_desc(response.status)
|
22
|
+
@errors << "Undocumented response for #{response_desc.inspect} with #{status_desc}"
|
16
23
|
end
|
17
24
|
end
|
18
25
|
end
|
@@ -5,13 +5,9 @@ module OpenapiContracts::Validators
|
|
5
5
|
private
|
6
6
|
|
7
7
|
def validate
|
8
|
-
return if
|
8
|
+
return if options[:status] == response.status
|
9
9
|
|
10
|
-
@errors << "Response has #{http_status_desc}"
|
11
|
-
end
|
12
|
-
|
13
|
-
def http_status_desc
|
14
|
-
"http status #{Rack::Utils::HTTP_STATUS_CODES[response.status]} (#{response.status})"
|
10
|
+
@errors << "Response has #{http_status_desc(response.status)}"
|
15
11
|
end
|
16
12
|
end
|
17
13
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module OpenapiContracts::Validators
|
2
|
+
class RequestBody < Base
|
3
|
+
include SchemaValidation
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
delegate :media_type, to: :request
|
8
|
+
delegate :request_body, to: :operation
|
9
|
+
|
10
|
+
def data_for_validation
|
11
|
+
request.body.rewind
|
12
|
+
raw = request.body.read
|
13
|
+
OpenapiContracts::PayloadParser.parse(media_type, raw)
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate
|
17
|
+
if !request_body
|
18
|
+
@errors << "Undocumented request body for #{response_desc.inspect}"
|
19
|
+
elsif !request_body.supports_media_type?(media_type)
|
20
|
+
@errors << "Undocumented request with media-type #{media_type.inspect}"
|
21
|
+
else
|
22
|
+
@errors += validate_schema(request_body.schema_for(media_type), data_for_validation)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module OpenapiContracts::Validators
|
2
|
+
class ResponseBody < Base
|
3
|
+
include SchemaValidation
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
delegate :media_type, to: :response
|
8
|
+
|
9
|
+
def data_for_validation
|
10
|
+
# ActionDispatch::Response body is a plain string, while Rack::Response returns an array
|
11
|
+
OpenapiContracts::PayloadParser.parse(media_type, Array.wrap(response.body).join)
|
12
|
+
end
|
13
|
+
|
14
|
+
def spec
|
15
|
+
@spec ||= operation.response_for_status(response.status)
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate
|
19
|
+
if spec.no_content?
|
20
|
+
@errors << 'Expected empty response body' if Array.wrap(response.body).any?(&:present?)
|
21
|
+
elsif !spec.supports_media_type?(media_type)
|
22
|
+
@errors << "Undocumented response with content-type #{media_type.inspect}"
|
23
|
+
else
|
24
|
+
@errors += validate_schema(spec.schema_for(media_type), data_for_validation)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module OpenapiContracts::Validators
|
2
|
+
module SchemaValidation
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def build_validation_schema(schema)
|
6
|
+
schema.raw.merge(
|
7
|
+
'$ref' => schema.fragment,
|
8
|
+
'$schema' => schema_draft_version(schema)
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
def error_to_message(error)
|
13
|
+
pointer = " at #{error['data_pointer']}" if error['data_pointer'].present?
|
14
|
+
if error.key?('details')
|
15
|
+
error['details'].to_a.map { |(key, val)|
|
16
|
+
"#{key.humanize}: #{val}#{pointer}"
|
17
|
+
}.to_sentence
|
18
|
+
else
|
19
|
+
"#{error['data'].inspect}#{pointer} does not match the schema"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def schema_draft_version(schema)
|
24
|
+
if schema.openapi_version.blank? || schema.openapi_version < Gem::Version.new('3.1')
|
25
|
+
# Closest compatible version is actually draft 5 but not supported by json-schemer
|
26
|
+
'http://json-schema.org/draft-04/schema#'
|
27
|
+
else
|
28
|
+
# >= 3.1 is actually comptable with 2020-12 but not yet supported by json-schemer
|
29
|
+
'http://json-schema.org/draft-07/schema#'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_schema(schema, data)
|
34
|
+
schemer = JSONSchemer.schema(build_validation_schema(schema))
|
35
|
+
schemer.validate(data).map do |err|
|
36
|
+
error_to_message(err)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,16 +1,19 @@
|
|
1
1
|
module OpenapiContracts
|
2
2
|
module Validators
|
3
|
-
autoload :Base,
|
4
|
-
autoload :
|
5
|
-
autoload :
|
6
|
-
autoload :
|
7
|
-
autoload :
|
3
|
+
autoload :Base, 'openapi_contracts/validators/base'
|
4
|
+
autoload :Documented, 'openapi_contracts/validators/documented'
|
5
|
+
autoload :Headers, 'openapi_contracts/validators/headers'
|
6
|
+
autoload :HttpStatus, 'openapi_contracts/validators/http_status'
|
7
|
+
autoload :RequestBody, 'openapi_contracts/validators/request_body'
|
8
|
+
autoload :ResponseBody, 'openapi_contracts/validators/response_body'
|
9
|
+
autoload :SchemaValidation, 'openapi_contracts/validators/schema_validation'
|
8
10
|
|
9
11
|
# Defines order of matching
|
10
12
|
ALL = [
|
11
13
|
Documented,
|
12
14
|
HttpStatus,
|
13
|
-
|
15
|
+
RequestBody,
|
16
|
+
ResponseBody,
|
14
17
|
Headers
|
15
18
|
].freeze
|
16
19
|
end
|
data/lib/openapi_contracts.rb
CHANGED
@@ -4,17 +4,22 @@ require 'active_support/core_ext/hash'
|
|
4
4
|
require 'active_support/core_ext/class'
|
5
5
|
require 'active_support/core_ext/module'
|
6
6
|
require 'active_support/core_ext/string'
|
7
|
+
require 'rubygems/version'
|
7
8
|
|
8
9
|
require 'json_schemer'
|
10
|
+
require 'rack'
|
9
11
|
require 'yaml'
|
10
12
|
|
11
13
|
module OpenapiContracts
|
12
|
-
autoload :Doc,
|
13
|
-
autoload :Helper,
|
14
|
-
autoload :Match,
|
15
|
-
autoload :
|
14
|
+
autoload :Doc, 'openapi_contracts/doc'
|
15
|
+
autoload :Helper, 'openapi_contracts/helper'
|
16
|
+
autoload :Match, 'openapi_contracts/match'
|
17
|
+
autoload :OperationRouter, 'openapi_contracts/operation_router'
|
18
|
+
autoload :Parser, 'openapi_contracts/parser'
|
19
|
+
autoload :PayloadParser, 'openapi_contracts/payload_parser'
|
20
|
+
autoload :Validators, 'openapi_contracts/validators'
|
16
21
|
|
17
|
-
Env = Struct.new(:
|
22
|
+
Env = Struct.new(:operation, :options, :request, :response, keyword_init: true)
|
18
23
|
|
19
24
|
module_function
|
20
25
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openapi_contracts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mkon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -36,42 +36,42 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.
|
39
|
+
version: 1.0.3
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 0.
|
46
|
+
version: 1.0.3
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
48
|
+
name: rack
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- - "
|
51
|
+
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
54
|
-
type: :
|
53
|
+
version: 2.0.0
|
54
|
+
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
|
-
- - "
|
58
|
+
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
60
|
+
version: 2.0.0
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: json_spec
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
67
|
+
version: 1.1.5
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
74
|
+
version: 1.1.5
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: rspec
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,28 +92,28 @@ dependencies:
|
|
92
92
|
requirements:
|
93
93
|
- - '='
|
94
94
|
- !ruby/object:Gem::Version
|
95
|
-
version: 1.
|
95
|
+
version: 1.55.1
|
96
96
|
type: :development
|
97
97
|
prerelease: false
|
98
98
|
version_requirements: !ruby/object:Gem::Requirement
|
99
99
|
requirements:
|
100
100
|
- - '='
|
101
101
|
- !ruby/object:Gem::Version
|
102
|
-
version: 1.
|
102
|
+
version: 1.55.1
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
104
|
name: rubocop-rspec
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
107
|
- - '='
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: 2.
|
109
|
+
version: 2.23.0
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
112
|
version_requirements: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
114
114
|
- - '='
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version: 2.
|
116
|
+
version: 2.23.0
|
117
117
|
- !ruby/object:Gem::Dependency
|
118
118
|
name: simplecov
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,23 +138,33 @@ files:
|
|
138
138
|
- README.md
|
139
139
|
- lib/openapi_contracts.rb
|
140
140
|
- lib/openapi_contracts/doc.rb
|
141
|
-
- lib/openapi_contracts/doc/file_parser.rb
|
142
141
|
- lib/openapi_contracts/doc/header.rb
|
143
|
-
- lib/openapi_contracts/doc/
|
142
|
+
- lib/openapi_contracts/doc/operation.rb
|
144
143
|
- lib/openapi_contracts/doc/parameter.rb
|
145
|
-
- lib/openapi_contracts/doc/parser.rb
|
146
144
|
- lib/openapi_contracts/doc/path.rb
|
145
|
+
- lib/openapi_contracts/doc/pointer.rb
|
146
|
+
- lib/openapi_contracts/doc/request.rb
|
147
147
|
- lib/openapi_contracts/doc/response.rb
|
148
148
|
- lib/openapi_contracts/doc/schema.rb
|
149
|
+
- lib/openapi_contracts/doc/with_parameters.rb
|
149
150
|
- lib/openapi_contracts/helper.rb
|
150
151
|
- lib/openapi_contracts/match.rb
|
152
|
+
- lib/openapi_contracts/operation_router.rb
|
153
|
+
- lib/openapi_contracts/parser.rb
|
154
|
+
- lib/openapi_contracts/parser/transformers.rb
|
155
|
+
- lib/openapi_contracts/parser/transformers/base.rb
|
156
|
+
- lib/openapi_contracts/parser/transformers/nullable.rb
|
157
|
+
- lib/openapi_contracts/parser/transformers/pointer.rb
|
158
|
+
- lib/openapi_contracts/payload_parser.rb
|
151
159
|
- lib/openapi_contracts/rspec.rb
|
152
160
|
- lib/openapi_contracts/validators.rb
|
153
161
|
- lib/openapi_contracts/validators/base.rb
|
154
|
-
- lib/openapi_contracts/validators/body.rb
|
155
162
|
- lib/openapi_contracts/validators/documented.rb
|
156
163
|
- lib/openapi_contracts/validators/headers.rb
|
157
164
|
- lib/openapi_contracts/validators/http_status.rb
|
165
|
+
- lib/openapi_contracts/validators/request_body.rb
|
166
|
+
- lib/openapi_contracts/validators/response_body.rb
|
167
|
+
- lib/openapi_contracts/validators/schema_validation.rb
|
158
168
|
homepage: https://github.com/mkon/openapi_contracts
|
159
169
|
licenses:
|
160
170
|
- MIT
|
@@ -168,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
168
178
|
requirements:
|
169
179
|
- - ">="
|
170
180
|
- !ruby/object:Gem::Version
|
171
|
-
version: '
|
181
|
+
version: '3.0'
|
172
182
|
- - "<"
|
173
183
|
- !ruby/object:Gem::Version
|
174
184
|
version: '3.3'
|