openapi_first 1.3.2 → 1.3.4
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/CHANGELOG.md +7 -0
- data/lib/openapi_first/definition/operation.rb +1 -1
- data/lib/openapi_first/failure.rb +2 -2
- data/lib/openapi_first/json_refs.rb +89 -79
- data/lib/openapi_first/runtime_response.rb +4 -2
- data/lib/openapi_first/schema.rb +1 -1
- data/lib/openapi_first/version.rb +1 -1
- data/lib/openapi_first.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5505b1339baa8f9dcfdcbedb2270eb67436f0661ebd04115bc6d3346da9d09c6
|
4
|
+
data.tar.gz: 4bea9a7977b95fbb05499d2c1a01eaef54dbabcdccab85c0ab327059e4450db4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78597035bfd86554fe437f8c26d285572bdc7eb5c19a8e7fa70cb55942e3df3f57bb7851666787b111fbf29e59ac03eb1a1db2bbf8d81b1f92d50298c3559e74
|
7
|
+
data.tar.gz: ff9b1d5871a855187aef2de7c6eec5324b8ba32c95560d1478f5b61566f7d53d7138d5a52dc4a13a78c5a518f6de83fec6f56ef2354509297cfcd15202cc3eda
|
data/CHANGELOG.md
CHANGED
@@ -95,7 +95,7 @@ module OpenapiFirst
|
|
95
95
|
# Returns a unique name for this operation. Used for generating error messages.
|
96
96
|
# @visibility private
|
97
97
|
def name
|
98
|
-
@name ||= "#{method.upcase} #{path}
|
98
|
+
@name ||= "#{method.upcase} #{path}"
|
99
99
|
end
|
100
100
|
|
101
101
|
# Returns the path parameters of the operation.
|
@@ -71,8 +71,8 @@ module OpenapiFirst
|
|
71
71
|
private
|
72
72
|
|
73
73
|
def generate_message
|
74
|
-
messages = errors&.take(
|
75
|
-
messages << "... (#{errors.size} errors total)" if errors && errors.size >
|
74
|
+
messages = errors&.take(3)&.map(&:error)
|
75
|
+
messages << "... (#{errors.size} errors total)" if errors && errors.size > 3
|
76
76
|
messages&.join('. ')
|
77
77
|
end
|
78
78
|
end
|
@@ -32,112 +32,122 @@ require 'hana'
|
|
32
32
|
require 'json'
|
33
33
|
require 'yaml'
|
34
34
|
|
35
|
-
module
|
36
|
-
class
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
module OpenapiFirst
|
36
|
+
class FileNotFoundError < StandardError; end
|
37
|
+
|
38
|
+
module JsonRefs
|
39
|
+
class << self
|
40
|
+
def dereference(doc)
|
41
|
+
file_cache = {}
|
42
|
+
Dereferencer.new(Dir.pwd, doc, file_cache).call
|
43
|
+
end
|
41
44
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
def load(filename)
|
46
|
+
doc_dir = File.dirname(filename)
|
47
|
+
doc = Loader.handle(filename)
|
48
|
+
file_cache = {}
|
49
|
+
Dereferencer.new(filename, doc_dir, doc, file_cache).call
|
50
|
+
end
|
47
51
|
end
|
48
|
-
end
|
49
52
|
|
50
|
-
|
51
|
-
|
53
|
+
module LocalRef
|
54
|
+
module_function
|
52
55
|
|
53
|
-
|
54
|
-
|
56
|
+
def call(path:, doc:)
|
57
|
+
Hana::Pointer.new(path[1..]).eval(doc)
|
58
|
+
end
|
55
59
|
end
|
56
|
-
end
|
57
60
|
|
58
|
-
|
59
|
-
|
61
|
+
module Loader
|
62
|
+
module_function
|
60
63
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
+
def handle(filename)
|
65
|
+
body = File.read(filename)
|
66
|
+
return JSON.parse(body) if File.extname(filename) == '.json'
|
64
67
|
|
65
|
-
|
68
|
+
YAML.unsafe_load(body)
|
69
|
+
end
|
66
70
|
end
|
67
|
-
end
|
68
71
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
class Dereferencer
|
73
|
+
def initialize(filename, doc_dir, doc, file_cache)
|
74
|
+
@filename = filename
|
75
|
+
@doc = doc
|
76
|
+
@doc_dir = doc_dir
|
77
|
+
@file_cache = file_cache
|
78
|
+
end
|
75
79
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
80
|
+
def call(doc = @doc, keys = [])
|
81
|
+
if doc.is_a?(Array)
|
82
|
+
doc.each_with_index do |value, idx|
|
83
|
+
call(value, keys + [idx])
|
84
|
+
end
|
85
|
+
elsif doc.is_a?(Hash)
|
86
|
+
if doc.key?('$ref')
|
87
|
+
dereference(keys, doc['$ref'])
|
88
|
+
else
|
89
|
+
doc.each do |key, value|
|
90
|
+
call(value, keys + [key])
|
91
|
+
end
|
87
92
|
end
|
88
93
|
end
|
94
|
+
doc
|
89
95
|
end
|
90
|
-
doc
|
91
|
-
end
|
92
96
|
|
93
|
-
|
97
|
+
private
|
94
98
|
|
95
|
-
|
99
|
+
attr_reader :doc_dir
|
96
100
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
+
def dereference(paths, referenced_path)
|
102
|
+
key = paths.pop
|
103
|
+
target = paths.inject(@doc) do |obj, k|
|
104
|
+
obj[k]
|
105
|
+
end
|
106
|
+
value = follow_referenced_value(referenced_path)
|
107
|
+
target[key] = value
|
101
108
|
end
|
102
|
-
value = follow_referenced_value(referenced_path)
|
103
|
-
target[key] = value
|
104
|
-
end
|
105
109
|
|
106
|
-
|
107
|
-
|
108
|
-
|
110
|
+
def follow_referenced_value(referenced_path)
|
111
|
+
value = referenced_value(referenced_path)
|
112
|
+
return referenced_value(value['$ref']) if value.is_a?(Hash) && value.key?('$ref')
|
109
113
|
|
110
|
-
|
111
|
-
|
114
|
+
value
|
115
|
+
end
|
112
116
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
+
def referenced_value(referenced_path)
|
118
|
+
filepath, pointer = referenced_path.split('#')
|
119
|
+
pointer&.prepend('#')
|
120
|
+
return dereference_local(pointer) if filepath.empty?
|
117
121
|
|
118
|
-
|
119
|
-
|
122
|
+
dereferenced_file = dereference_file(filepath)
|
123
|
+
return dereferenced_file if pointer.nil?
|
120
124
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
125
|
+
LocalRef.call(
|
126
|
+
path: pointer,
|
127
|
+
doc: dereferenced_file
|
128
|
+
)
|
129
|
+
end
|
126
130
|
|
127
|
-
|
128
|
-
|
129
|
-
|
131
|
+
def dereference_local(referenced_path)
|
132
|
+
LocalRef.call(path: referenced_path, doc: @doc)
|
133
|
+
end
|
130
134
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
+
def dereference_file(referenced_path)
|
136
|
+
referenced_path = File.expand_path(referenced_path, doc_dir) unless File.absolute_path?(referenced_path)
|
137
|
+
@file_cache[referenced_path] ||= load_referenced_file(referenced_path)
|
138
|
+
end
|
135
139
|
|
136
|
-
|
137
|
-
|
140
|
+
def load_referenced_file(absolute_path)
|
141
|
+
directory = File.dirname(absolute_path)
|
138
142
|
|
139
|
-
|
140
|
-
|
143
|
+
unless File.exist?(absolute_path)
|
144
|
+
raise FileNotFoundError,
|
145
|
+
"Problem while loading file referenced in #{@filename}: File not found #{absolute_path}"
|
146
|
+
end
|
147
|
+
|
148
|
+
referenced_doc = Loader.handle(absolute_path)
|
149
|
+
Dereferencer.new(@filename, directory, referenced_doc, @file_cache).call
|
150
|
+
end
|
141
151
|
end
|
142
152
|
end
|
143
153
|
end
|
@@ -22,8 +22,10 @@ module OpenapiFirst
|
|
22
22
|
# @attr_reader [String] content_type The content_type of the Rack::Response.
|
23
23
|
def_delegators :@rack_response, :status, :content_type
|
24
24
|
|
25
|
-
# @
|
26
|
-
|
25
|
+
# @return [String] name The name of the operation. Used for generating error messages.
|
26
|
+
def name
|
27
|
+
"#{@operation.name} response status: #{status}"
|
28
|
+
end
|
27
29
|
|
28
30
|
# Checks if the response is valid. Runs the validation unless it has been run before.
|
29
31
|
# @return [Boolean]
|
data/lib/openapi_first/schema.rb
CHANGED
@@ -42,7 +42,7 @@ module OpenapiFirst
|
|
42
42
|
def binary_format(data, property, property_schema, _parent)
|
43
43
|
return unless property_schema.is_a?(Hash) && property_schema['format'] == 'binary'
|
44
44
|
|
45
|
-
data[property] = data
|
45
|
+
data[property] = data.dig(property, :tempfile)&.read if data[property]
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
data/lib/openapi_first.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openapi_first
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Haller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hana
|