open_api_import 0.10.9 → 0.11.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/lib/open_api_import/filter.rb +28 -0
- data/lib/open_api_import/get_data_all_of_bodies.rb +22 -0
- data/lib/open_api_import/get_examples.rb +88 -0
- data/lib/open_api_import/get_patterns.rb +67 -0
- data/lib/open_api_import/get_required_data.rb +30 -0
- data/lib/open_api_import/get_response_examples.rb +104 -0
- data/lib/open_api_import/open_api_import.rb +693 -0
- data/lib/open_api_import/pretty_hash_symbolized.rb +18 -0
- data/lib/open_api_import.rb +10 -1024
- metadata +36 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f325c36f3cd721eaeedafc552c28ae05aeaca61e1b28db412b1a43c7b1eb94b9
|
4
|
+
data.tar.gz: '08e087bd46c830537ff2302af6f9d0ec71003ea48836bb36f59890a41ef5a1da'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 416f1458f279a4a1c6e4c69ee55997fd36c133ff72ffa12b584777e4f60baffcf5327c0e685dd21c7f02c84d85a2c3152137784d86354e0cfe59abbd93aaf2eb
|
7
|
+
data.tar.gz: 8b63487982fe8884a9ad220e707c847a03cad7d1aada0e0d9ad156492cb65e51d027063e9320e5898335ecf26b4b7eb9f3c066ba58539815538764dfe32a7e2b
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module LibOpenApiImport
|
2
|
+
#filter hash
|
3
|
+
def filter(hash, keys, nested = false)
|
4
|
+
result = {}
|
5
|
+
keys = [keys] unless keys.is_a?(Array)
|
6
|
+
if nested
|
7
|
+
result = hash.nice_filter(keys)
|
8
|
+
else
|
9
|
+
#to be backwards compatible
|
10
|
+
keys.each do |k|
|
11
|
+
if k.is_a?(Symbol) and hash.key?(k)
|
12
|
+
if hash[k].is_a?(Hash)
|
13
|
+
result[k] = {}
|
14
|
+
else
|
15
|
+
result[k] = hash[k]
|
16
|
+
end
|
17
|
+
elsif k.is_a?(Symbol) and k.to_s.include?(".") and hash.key?((k.to_s.scan(/(\w+)\./).join).to_sym) #nested 'uno.dos.tres
|
18
|
+
kn = k.to_s.split(".")
|
19
|
+
vn = kn[1].to_sym
|
20
|
+
result[kn.first.to_sym][vn] = filter(hash[kn.first.to_sym], vn).values[0]
|
21
|
+
elsif k.is_a?(Hash) and hash.key?(k.keys[0]) #nested {uno: {dos: :tres}}
|
22
|
+
result[k.keys[0]][k.values[0]] = filter(hash[k.keys[0]], k.values[0]).values[0]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
return result
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module LibOpenApiImport
|
2
|
+
private def get_data_all_of_bodies(p)
|
3
|
+
bodies = []
|
4
|
+
data_examples_all_of = false
|
5
|
+
if p.is_a?(Array)
|
6
|
+
q = p
|
7
|
+
elsif p.key?(:schema) and p[:schema].key?(:allOf)
|
8
|
+
q = p[:schema][:allOf]
|
9
|
+
else
|
10
|
+
q = [p]
|
11
|
+
end
|
12
|
+
q.each do |pt|
|
13
|
+
if pt.is_a?(Hash) and pt.key?(:allOf)
|
14
|
+
bodies += get_data_all_of_bodies(pt[:allOf])[1]
|
15
|
+
data_examples_all_of = true
|
16
|
+
else
|
17
|
+
bodies << pt
|
18
|
+
end
|
19
|
+
end
|
20
|
+
return data_examples_all_of, bodies
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module LibOpenApiImport
|
2
|
+
# Retrieve the examples from the properties hash
|
3
|
+
private def get_examples(properties, type = :key_value, remove_readonly = false)
|
4
|
+
#todo: consider using this method also to get data examples
|
5
|
+
example = []
|
6
|
+
example << "{" unless properties.empty? or type == :only_value
|
7
|
+
properties.each do |prop, val|
|
8
|
+
unless remove_readonly and val.key?(:readOnly) and val[:readOnly] == true
|
9
|
+
if val.key?(:properties) and !val.key?(:example) and !val.key?(:type)
|
10
|
+
val[:type] = "object"
|
11
|
+
end
|
12
|
+
if val.key?(:items) and !val.key?(:example) and !val.key?(:type)
|
13
|
+
val[:type] = "array"
|
14
|
+
end
|
15
|
+
if val.key?(:example)
|
16
|
+
if val[:example].is_a?(Array) and val.key?(:type) and val[:type] == "string"
|
17
|
+
example << " #{prop.to_sym}: \"#{val[:example][0]}\", " # only the first example
|
18
|
+
else
|
19
|
+
if val[:example].is_a?(String)
|
20
|
+
val[:example].gsub!('"', "'")
|
21
|
+
example << " #{prop.to_sym}: \"#{val[:example]}\", "
|
22
|
+
elsif val[:example].is_a?(Time)
|
23
|
+
example << " #{prop.to_sym}: \"#{val[:example]}\", "
|
24
|
+
else
|
25
|
+
example << " #{prop.to_sym}: #{val[:example]}, "
|
26
|
+
end
|
27
|
+
end
|
28
|
+
elsif val.key?(:type)
|
29
|
+
format = val[:format]
|
30
|
+
format = val[:type] if format.to_s == ""
|
31
|
+
case val[:type].downcase
|
32
|
+
when "string"
|
33
|
+
example << " #{prop.to_sym}: \"#{format}\", "
|
34
|
+
when "integer", "number"
|
35
|
+
example << " #{prop.to_sym}: 0, "
|
36
|
+
when "boolean"
|
37
|
+
example << " #{prop.to_sym}: true, "
|
38
|
+
when "array"
|
39
|
+
if val.key?(:items) and val[:items].size == 1 and val[:items].is_a?(Hash) and val[:items].key?(:type)
|
40
|
+
val[:items][:enum] = [val[:items][:type]]
|
41
|
+
end
|
42
|
+
|
43
|
+
if val.key?(:items) and val[:items].key?(:enum)
|
44
|
+
#before we were getting in all these cases a random value from the enum, now we are getting the first position by default
|
45
|
+
#the reason is to avoid confusion later in case we want to compare two swaggers and verify the changes
|
46
|
+
if type == :only_value
|
47
|
+
if val[:items][:enum][0].is_a?(String)
|
48
|
+
example << " [\"" + val[:items][:enum][0] + "\"] "
|
49
|
+
else
|
50
|
+
example << " [" + val[:items][:enum][0] + "] "
|
51
|
+
end
|
52
|
+
else
|
53
|
+
if val[:items][:enum][0].is_a?(String)
|
54
|
+
example << " #{prop.to_sym}: [\"" + val[:items][:enum][0] + "\"], "
|
55
|
+
else
|
56
|
+
example << " #{prop.to_sym}: [" + val[:items][:enum][0] + "], "
|
57
|
+
end
|
58
|
+
end
|
59
|
+
else
|
60
|
+
#todo: differ between response examples and data examples
|
61
|
+
examplet = get_response_examples({ schema: val }, remove_readonly).join("\n")
|
62
|
+
examplet = '[]' if examplet.empty?
|
63
|
+
if type == :only_value
|
64
|
+
example << examplet
|
65
|
+
else
|
66
|
+
example << " #{prop.to_sym}: " + examplet + ", "
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
when "object"
|
71
|
+
#todo: differ between response examples and data examples
|
72
|
+
res_ex = get_response_examples({ schema: val }, remove_readonly)
|
73
|
+
if res_ex.size == 0
|
74
|
+
res_ex = "{ }"
|
75
|
+
else
|
76
|
+
res_ex = res_ex.join("\n")
|
77
|
+
end
|
78
|
+
example << " #{prop.to_sym}: " + res_ex + ", "
|
79
|
+
else
|
80
|
+
example << " #{prop.to_sym}: \"#{format}\", "
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
example << "}" unless properties.empty? or type == :only_value
|
86
|
+
example
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module LibOpenApiImport
|
2
|
+
# Get patterns
|
3
|
+
private def get_patterns(dpk, dpv)
|
4
|
+
data_pattern = []
|
5
|
+
if dpv.keys.include?(:pattern)
|
6
|
+
#todo: control better the cases with back slashes
|
7
|
+
if dpv[:pattern].include?('\\\\/')
|
8
|
+
#for cases like this: ^[^\.\\/:*?"<>|][^\\/:*?"<>|]{0,13}[^\.\\/:*?"<>|]?$
|
9
|
+
data_pattern << "'#{dpk}': /#{dpv[:pattern].to_s.gsub('\/', "/")}/"
|
10
|
+
elsif dpv[:pattern].include?('\\x')
|
11
|
+
data_pattern << "'#{dpk}': /#{dpv[:pattern].to_s.gsub('\\x', '\\u')}/"
|
12
|
+
else
|
13
|
+
data_pattern << "'#{dpk}': /#{dpv[:pattern].to_s}/"
|
14
|
+
end
|
15
|
+
elsif dpv.key?(:minLength) and dpv.key?(:maxLength)
|
16
|
+
data_pattern << "'#{dpk}': :'#{dpv[:minLength]}-#{dpv[:maxLength]}:LN$'"
|
17
|
+
elsif dpv.key?(:minLength) and !dpv.key?(:maxLength)
|
18
|
+
data_pattern << "'#{dpk}': :'#{dpv[:minLength]}:LN$'"
|
19
|
+
elsif !dpv.key?(:minLength) and dpv.key?(:maxLength)
|
20
|
+
data_pattern << "'#{dpk}': :'0-#{dpv[:maxLength]}:LN$'"
|
21
|
+
elsif dpv.key?(:minimum) and dpv.key?(:maximum) and dpv[:type] == "string"
|
22
|
+
data_pattern << "'#{dpk}': :'#{dpv[:minimum]}-#{dpv[:maximum]}:LN$'"
|
23
|
+
elsif dpv.key?(:minimum) and dpv.key?(:maximum)
|
24
|
+
data_pattern << "'#{dpk}': #{dpv[:minimum]}..#{dpv[:maximum]}"
|
25
|
+
elsif dpv.key?(:minimum) and !dpv.key?(:maximum)
|
26
|
+
if RUBY_VERSION >= "2.6.0"
|
27
|
+
data_pattern << "'#{dpk}': #{dpv[:minimum]}.. "
|
28
|
+
else
|
29
|
+
data_pattern << "#'#{dpk}': #{dpv[:minimum]}.. # INFINITE only working on ruby>=2.6.0"
|
30
|
+
end
|
31
|
+
elsif !dpv.key?(:minimum) and dpv.key?(:maximum)
|
32
|
+
data_pattern << "'#{dpk}': 0..#{dpv[:maximum]}"
|
33
|
+
elsif dpv[:format] == "date-time"
|
34
|
+
data_pattern << "'#{dpk}': DateTime"
|
35
|
+
elsif dpv[:type] == "boolean"
|
36
|
+
data_pattern << "'#{dpk}': Boolean"
|
37
|
+
elsif dpv.key?(:enum)
|
38
|
+
data_pattern << "'#{dpk}': :'#{dpv[:enum].join("|")}'"
|
39
|
+
elsif dpv[:type] == "array" and dpv.key?(:items) and dpv[:items].is_a?(Hash) and dpv[:items].key?(:enum) and dpv[:items][:enum].is_a?(Array)
|
40
|
+
#{:title=>"Balala", :type=>"array", :items=>{:type=>"string", :enum=>["uno","dos"], :example=>"uno"}}
|
41
|
+
data_pattern << "'#{dpk}': [:'#{dpv[:items][:enum].join("|")}']"
|
42
|
+
elsif dpv[:type] == "array" and dpv.key?(:items) and dpv[:items].is_a?(Hash) and !dpv[:items].key?(:enum) and dpv[:items].key?(:properties)
|
43
|
+
#{:title=>"Balala", :type=>"array", :items=>{title: 'xxxx, properties: {server: {enum:['ibm','msa','pytan']}}}
|
44
|
+
dpv[:items][:properties].each do |dpkk, dpvv|
|
45
|
+
if dpk == ""
|
46
|
+
data_pattern += get_patterns("#{dpkk}", dpvv)
|
47
|
+
else
|
48
|
+
data_pattern += get_patterns("#{dpk}.#{dpkk}", dpvv)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
elsif dpv[:type] == "array" and dpv.key?(:items) and dpv[:items].is_a?(Hash) and
|
52
|
+
!dpv[:items].key?(:enum) and !dpv[:items].key?(:properties) and dpv[:items].key?(:type)
|
53
|
+
#{:title=>"labels", :description=>"Labels specified for the file system", :type=>"array", :items=>{:type=>"string", :enum=>["string"]}}
|
54
|
+
data_pattern << "'#{dpk}': [ #{get_patterns("", dpv[:items]).join[4..-1]} ]"
|
55
|
+
elsif dpv[:type] == "object" and dpv.key?(:properties)
|
56
|
+
dpv[:properties].each do |dpkk, dpvv|
|
57
|
+
if dpk == ""
|
58
|
+
data_pattern += get_patterns("#{dpkk}", dpvv)
|
59
|
+
else
|
60
|
+
data_pattern += get_patterns("#{dpk}.#{dpkk}", dpvv)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
data_pattern.uniq!
|
65
|
+
return data_pattern
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module LibOpenApiImport
|
2
|
+
# Get required data
|
3
|
+
private def get_required_data(body)
|
4
|
+
data_required = []
|
5
|
+
if body.keys.include?(:required) and body[:required].size > 0
|
6
|
+
body[:required].each do |r|
|
7
|
+
data_required << r.to_sym
|
8
|
+
end
|
9
|
+
end
|
10
|
+
if body.key?(:allOf)
|
11
|
+
body[:allOf].each do |r|
|
12
|
+
if r.key?(:required)
|
13
|
+
r[:required].each do |r2|
|
14
|
+
data_required << r2.to_sym
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
data_required.each do |key|
|
20
|
+
if body.key?(:properties) and body[:properties][key].is_a?(Hash) and
|
21
|
+
body[:properties][key].key?(:required) and body[:properties][key][:required].size > 0
|
22
|
+
dr = get_required_data(body[:properties][key])
|
23
|
+
dr.each do |k|
|
24
|
+
data_required.push("#{key}.#{k}".to_sym)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
return data_required
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module LibOpenApiImport
|
2
|
+
# Retrieve the response examples from the hash
|
3
|
+
private def get_response_examples(v, remove_readonly = false)
|
4
|
+
# TODO: take in consideration the case allOf, oneOf... schema.items.allOf[0].properties schema.items.allOf[1].properties
|
5
|
+
# example on https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/yaml/petstore-expanded.yaml
|
6
|
+
v = v.dup
|
7
|
+
response_example = Array.new()
|
8
|
+
# for open api 3.0 with responses schema inside content
|
9
|
+
if v.key?(:content) && v[:content].is_a?(Hash) && v[:content].key?(:'application/json') &&
|
10
|
+
v[:content][:'application/json'].key?(:schema)
|
11
|
+
v = v[:content][:'application/json'].dup
|
12
|
+
end
|
13
|
+
if v.key?(:examples) && v[:examples].is_a?(Hash) && v[:examples].key?(:'application/json')
|
14
|
+
if v[:examples][:'application/json'].is_a?(String)
|
15
|
+
response_example << v[:examples][:'application/json']
|
16
|
+
elsif v[:examples][:'application/json'].is_a?(Hash)
|
17
|
+
exs = v[:examples][:'application/json'].to_s
|
18
|
+
exs.gsub!(/:(\w+)=>/, "\n\\1: ")
|
19
|
+
response_example << exs
|
20
|
+
elsif v[:examples][:'application/json'].is_a?(Array)
|
21
|
+
response_example << "["
|
22
|
+
v[:examples][:'application/json'].each do |ex|
|
23
|
+
exs = ex.to_s
|
24
|
+
if ex.is_a?(Hash)
|
25
|
+
exs.gsub!(/:(\w+)=>/, "\n\\1: ")
|
26
|
+
end
|
27
|
+
response_example << (exs + ", ")
|
28
|
+
end
|
29
|
+
response_example << "]"
|
30
|
+
end
|
31
|
+
# for open api 3.0. examples on reponses, for example: api-with-examples.yaml
|
32
|
+
elsif v.key?(:content) && v[:content].is_a?(Hash) && v[:content].key?(:'application/json') &&
|
33
|
+
v[:content][:'application/json'].key?(:examples)
|
34
|
+
v[:content][:'application/json'][:examples].each do |tk, tv|
|
35
|
+
#todo: for the moment we only take in consideration the first example of response.
|
36
|
+
# we need to decide how to manage to do it correctly
|
37
|
+
if tv.key?(:value)
|
38
|
+
tresp = tv[:value]
|
39
|
+
else
|
40
|
+
tresp = ""
|
41
|
+
end
|
42
|
+
if tresp.is_a?(String)
|
43
|
+
response_example << tresp
|
44
|
+
elsif tresp.is_a?(Hash)
|
45
|
+
exs = tresp.to_s
|
46
|
+
exs.gsub!(/:(\w+)=>/, "\n\\1: ")
|
47
|
+
response_example << exs
|
48
|
+
elsif tresp.is_a?(Array)
|
49
|
+
response_example << "["
|
50
|
+
tresp.each do |ex|
|
51
|
+
exs = ex.to_s
|
52
|
+
if ex.is_a?(Hash)
|
53
|
+
exs.gsub!(/:(\w+)=>/, "\n\\1: ")
|
54
|
+
end
|
55
|
+
response_example << (exs + ", ")
|
56
|
+
end
|
57
|
+
response_example << "]"
|
58
|
+
end
|
59
|
+
break #only the first one it is considered
|
60
|
+
end
|
61
|
+
elsif v.key?(:schema) && v[:schema].is_a?(Hash) &&
|
62
|
+
(v[:schema].key?(:properties) ||
|
63
|
+
(v[:schema].key?(:items) && v[:schema][:items].key?(:properties)) ||
|
64
|
+
(v[:schema].key?(:items) && v[:schema][:items].key?(:allOf)) ||
|
65
|
+
v[:schema].key?(:allOf))
|
66
|
+
properties = {}
|
67
|
+
if v[:schema].key?(:properties)
|
68
|
+
properties = v[:schema][:properties]
|
69
|
+
elsif v[:schema].key?(:allOf)
|
70
|
+
v[:schema][:allOf].each do |pr|
|
71
|
+
properties.merge!(pr[:properties]) if pr.key?(:properties)
|
72
|
+
end
|
73
|
+
elsif v[:schema][:items].key?(:properties)
|
74
|
+
properties = v[:schema][:items][:properties]
|
75
|
+
response_example << "["
|
76
|
+
elsif v[:schema][:items].key?(:allOf)
|
77
|
+
v[:schema][:items][:allOf].each do |pr|
|
78
|
+
properties.merge!(pr[:properties]) if pr.key?(:properties)
|
79
|
+
end
|
80
|
+
response_example << "["
|
81
|
+
end
|
82
|
+
|
83
|
+
response_example += get_examples(properties, :key_value, remove_readonly) unless properties.empty?
|
84
|
+
|
85
|
+
unless response_example.empty?
|
86
|
+
if v[:schema].key?(:properties) || v[:schema].key?(:allOf)
|
87
|
+
#
|
88
|
+
else # array, items
|
89
|
+
response_example << "]"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
elsif v.key?(:schema) and v[:schema].key?(:items) and v[:schema][:items].key?(:type)
|
93
|
+
# for the case only type supplied but nothing else for the array
|
94
|
+
response_example << "[\"#{v[:schema][:items][:type]}\"]"
|
95
|
+
end
|
96
|
+
response_example.each do |rs|
|
97
|
+
#(@type Google) for the case in example the key is something like: @type:
|
98
|
+
if rs.match?(/^\s*@\w+:/)
|
99
|
+
rs.gsub!(/@(\w+):/, '\'@\1\':')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
return response_example
|
103
|
+
end
|
104
|
+
end
|