open_api_import 0.10.9 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|