open_api_import 0.12.1 → 0.12.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1bdc8574c5269031de67696726c02074c76f9984fce636eaf30975d4e2f68f7
4
- data.tar.gz: 5fe961eea45418c8d304dea541c6eb50e62a6bb7284ebfe6b4a427e3359dc3b1
3
+ metadata.gz: 74cd0d1b3fe72eae2aad945df578673832e5a2a58ad938e065abe70db5edc161
4
+ data.tar.gz: f5e13c3fc110c404c14065aeb5d626ddea4a8171ae1a4174b492cbf19c0f0660
5
5
  SHA512:
6
- metadata.gz: 06132d15447601dab341129865b759ea4d723bd93463f1d3ac8a9f105ee2d4a8d6f704a8f200dcbd7a29e81587690c6f0e05dc5446284d7f4eb83cd528e937fa
7
- data.tar.gz: 55f730d08221bb65e4481688a9f84390d70695a0f2d5902de376807ff2b7fc19666015f8cad9551fcf51e0c9450d171bfb1f34807c3f7b231c8449c569a43fc0
6
+ metadata.gz: 67225ba813dfd134e16fd7682704259397281f77f81f0641f8181830af10c8b025d75f6afa5b5a20a8407baf39c38762c69d2dbdd240ee321faa577554f5967d
7
+ data.tar.gz: 1ac239ef7256b100a920ca79f3766a6b3bddfad3effce4ce745225a89da55275e379fad9833c788bb6e430a5be8e424602d1f68e400dcbc6ac1b54d9e1b55ca6
@@ -8,6 +8,7 @@ module LibOpenApiImport
8
8
  example << "{" unless properties.empty? || (type == :only_value)
9
9
  properties.each do |prop, val|
10
10
  unless remove_readonly && val.key?(:readOnly) && (val[:readOnly] == true)
11
+ key = ruby_hash_key(prop)
11
12
  effective_type = val[:type]
12
13
  if val.key?(:properties) && !val.key?(:example) && !val.key?(:type)
13
14
  effective_type = "object"
@@ -23,23 +24,23 @@ module LibOpenApiImport
23
24
 
24
25
  if effective_example
25
26
  if effective_example.is_a?(Array) && val.key?(:type) && (val[:type] == "string")
26
- example << " #{prop.to_sym}: \"#{effective_example[0]}\", "
27
+ example << " #{key} #{effective_example[0].to_s.inspect}, "
27
28
  elsif effective_example.is_a?(String)
28
29
  escaped = effective_example.include?("'") ? effective_example : effective_example.gsub('"', "'")
29
- example << " #{prop.to_sym}: \"#{escaped}\", "
30
+ example << " #{key} #{escaped.inspect}, "
30
31
  elsif effective_example.is_a?(Time)
31
- example << " #{prop.to_sym}: \"#{effective_example}\", "
32
+ example << " #{key} #{effective_example.to_s.inspect}, "
32
33
  else
33
- example << " #{prop.to_sym}: #{effective_example}, "
34
+ example << " #{key} #{effective_example.inspect}, "
34
35
  end
35
36
  elsif effective_type
36
37
  format = val[:format]
37
38
  format = effective_type if format.to_s == ""
38
39
  case effective_type.downcase
39
40
  when "string"
40
- example << " #{prop.to_sym}: \"#{format}\", "
41
+ example << " #{key} #{format.to_s.inspect}, "
41
42
  when "integer"
42
- example << " #{prop.to_sym}: 0, "
43
+ example << " #{key} 0, "
43
44
  when "number"
44
45
  format_name = format.to_s.downcase
45
46
  number_value = if %w[float double decimal].include?(format_name)
@@ -47,9 +48,9 @@ module LibOpenApiImport
47
48
  else
48
49
  "0"
49
50
  end
50
- example << " #{prop.to_sym}: #{number_value}, "
51
+ example << " #{key} #{number_value}, "
51
52
  when "boolean"
52
- example << " #{prop.to_sym}: true, "
53
+ example << " #{key} true, "
53
54
  when "array"
54
55
  items_enum = if val.key?(:items) && val[:items].is_a?(Hash) && (val[:items].size == 1) && val[:items].key?(:type)
55
56
  [val[:items][:type]]
@@ -59,15 +60,9 @@ module LibOpenApiImport
59
60
 
60
61
  if items_enum
61
62
  if type == :only_value
62
- if items_enum[0].is_a?(String)
63
- example << " [\"#{items_enum[0]}\"] "
64
- else
65
- example << " [#{items_enum[0]}] "
66
- end
67
- elsif items_enum[0].is_a?(String)
68
- example << " #{prop.to_sym}: [\"#{items_enum[0]}\"], "
63
+ example << " #{[items_enum[0]].inspect} "
69
64
  else
70
- example << " #{prop.to_sym}: [#{items_enum[0]}], "
65
+ example << " #{key} #{[items_enum[0]].inspect}, "
71
66
  end
72
67
  else
73
68
  examplet = get_response_examples({ schema: val }, remove_readonly).join("\n")
@@ -75,7 +70,7 @@ module LibOpenApiImport
75
70
  if type == :only_value
76
71
  example << examplet
77
72
  else
78
- example << " #{prop.to_sym}: #{examplet}, "
73
+ example << " #{key} #{examplet}, "
79
74
  end
80
75
  end
81
76
  when "object"
@@ -85,9 +80,9 @@ module LibOpenApiImport
85
80
  else
86
81
  res_ex = res_ex.join("\n")
87
82
  end
88
- example << " #{prop.to_sym}: #{res_ex}, "
83
+ example << " #{key} #{res_ex}, "
89
84
  else
90
- example << " #{prop.to_sym}: \"#{format}\", "
85
+ example << " #{key} #{format.to_s.inspect}, "
91
86
  end
92
87
  end
93
88
  end
@@ -7,43 +7,36 @@ module LibOpenApiImport
7
7
  data_pattern = []
8
8
  effective_type = dpv[:type]
9
9
  effective_type = Array(effective_type).reject { |t| t == "null" }.first if effective_type.is_a?(Array)
10
+ key = ruby_hash_key(dpk)
10
11
 
11
12
  if dpv.keys.include?(:pattern)
12
- if dpv[:pattern].include?('\\\\/')
13
- data_pattern << "'#{dpk}': /#{dpv[:pattern].to_s.gsub('\/', "/")}/"
14
- elsif dpv[:pattern].match?(/\\x[0-9ABCDEF][0-9ABCDEF]-/)
15
- data_pattern << "'#{dpk}': /#{dpv[:pattern].to_s.gsub('\\x', '\\u00')}/"
16
- elsif dpv[:pattern].include?('\\x')
17
- data_pattern << "'#{dpk}': /#{dpv[:pattern].to_s.gsub('\\x', '\\u')}/"
18
- else
19
- data_pattern << "'#{dpk}': /#{dpv[:pattern]}/"
20
- end
13
+ pattern = dpv[:pattern].to_s
14
+ pattern = pattern.gsub('\/', "/") if pattern.include?('\\\\/')
15
+ pattern = pattern.gsub('\\x', '\\u00') if pattern.match?(/\\x[0-9ABCDEF][0-9ABCDEF]-/)
16
+ pattern = pattern.gsub('\\x', '\\u') if pattern.include?('\\x')
17
+ data_pattern << "#{key} #{Regexp.new(pattern).inspect}"
21
18
  elsif dpv.key?(:minLength) && dpv.key?(:maxLength)
22
- data_pattern << "'#{dpk}': :'#{dpv[:minLength]}-#{dpv[:maxLength]}:LN$'"
19
+ data_pattern << "#{key} #{ruby_symbol_literal("#{dpv[:minLength]}-#{dpv[:maxLength]}:LN$")}"
23
20
  elsif dpv.key?(:minLength) && !dpv.key?(:maxLength)
24
- data_pattern << "'#{dpk}': :'#{dpv[:minLength]}:LN$'"
21
+ data_pattern << "#{key} #{ruby_symbol_literal("#{dpv[:minLength]}:LN$")}"
25
22
  elsif !dpv.key?(:minLength) && dpv.key?(:maxLength)
26
- data_pattern << "'#{dpk}': :'0-#{dpv[:maxLength]}:LN$'"
23
+ data_pattern << "#{key} #{ruby_symbol_literal("0-#{dpv[:maxLength]}:LN$")}"
27
24
  elsif dpv.key?(:minimum) && dpv.key?(:maximum) && (effective_type == "string")
28
- data_pattern << "'#{dpk}': :'#{dpv[:minimum]}-#{dpv[:maximum]}:LN$'"
25
+ data_pattern << "#{key} #{ruby_symbol_literal("#{dpv[:minimum]}-#{dpv[:maximum]}:LN$")}"
29
26
  elsif dpv.key?(:minimum) && dpv.key?(:maximum)
30
- data_pattern << "'#{dpk}': #{dpv[:minimum]}..#{dpv[:maximum]}"
27
+ data_pattern << "#{key} #{dpv[:minimum].inspect}..#{dpv[:maximum].inspect}"
31
28
  elsif dpv.key?(:minimum) && !dpv.key?(:maximum)
32
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.6.0")
33
- data_pattern << "'#{dpk}': #{dpv[:minimum]}.. "
34
- else
35
- data_pattern << "#'#{dpk}': #{dpv[:minimum]}.. # INFINITE only working on ruby>=2.6.0"
36
- end
29
+ data_pattern << "#{key} #{dpv[:minimum].inspect}.. "
37
30
  elsif !dpv.key?(:minimum) && dpv.key?(:maximum)
38
- data_pattern << "'#{dpk}': 0..#{dpv[:maximum]}"
31
+ data_pattern << "#{key} 0..#{dpv[:maximum].inspect}"
39
32
  elsif dpv[:format] == "date-time"
40
- data_pattern << "'#{dpk}': DateTime"
33
+ data_pattern << "#{key} DateTime"
41
34
  elsif effective_type == "boolean"
42
- data_pattern << "'#{dpk}': Boolean"
35
+ data_pattern << "#{key} Boolean"
43
36
  elsif dpv.key?(:enum)
44
- data_pattern << "'#{dpk}': :'#{dpv[:enum].join("|")}'"
37
+ data_pattern << "#{key} #{dpv[:enum].join("|").to_sym.inspect}"
45
38
  elsif (effective_type == "array") && dpv.key?(:items) && dpv[:items].is_a?(Hash) && dpv[:items].key?(:enum) && dpv[:items][:enum].is_a?(Array)
46
- data_pattern << "'#{dpk}': [:'#{dpv[:items][:enum].join("|")}']"
39
+ data_pattern << "#{key} [#{dpv[:items][:enum].join("|").to_sym.inspect}]"
47
40
  elsif (effective_type == "array") && dpv.key?(:items) && dpv[:items].is_a?(Hash) && !dpv[:items].key?(:enum) && dpv[:items].key?(:properties)
48
41
  dpv[:items][:properties].each do |dpkk, dpvv|
49
42
  if dpk == ""
@@ -58,9 +51,9 @@ module LibOpenApiImport
58
51
  if result.empty?
59
52
  item_type = dpv[:items][:type]
60
53
  item_type = Array(item_type).reject { |t| t == "null" }.first if item_type.is_a?(Array)
61
- data_pattern << "'#{dpk}': [:'#{item_type}']"
54
+ data_pattern << "#{key} [#{item_type.to_s.to_sym.inspect}]"
62
55
  else
63
- data_pattern << "'#{dpk}': [ #{result.join[4..]} ]"
56
+ data_pattern << "#{key} [ #{result.join[4..]} ]"
64
57
  end
65
58
  elsif (effective_type == "object") && dpv.key?(:properties)
66
59
  dpv[:properties].each do |dpkk, dpvv|
@@ -15,22 +15,13 @@ module LibOpenApiImport
15
15
  v = v[:content][:"application/json"].dup
16
16
  end
17
17
  if v.key?(:examples) && v[:examples].is_a?(Hash) && v[:examples].key?(:"application/json")
18
- if v[:examples][:"application/json"].is_a?(String)
19
- response_example << v[:examples][:"application/json"]
20
- elsif v[:examples][:"application/json"].is_a?(Hash)
21
- exs = v[:examples][:"application/json"].to_s
22
- exs.gsub!(/:(\w+)=>/, "\n\\1: ")
23
- response_example << exs
24
- elsif v[:examples][:"application/json"].is_a?(Array)
18
+ example = v[:examples][:"application/json"]
19
+ if example.is_a?(Array)
25
20
  response_example << "["
26
- v[:examples][:"application/json"].each do |ex|
27
- exs = ex.to_s
28
- if ex.is_a?(Hash)
29
- exs.gsub!(/:(\w+)=>/, "\n\\1: ")
30
- end
31
- response_example << "#{exs}, "
32
- end
21
+ example.each { |item| response_example << "#{item.inspect}, " }
33
22
  response_example << "]"
23
+ else
24
+ response_example << example.inspect
34
25
  end
35
26
  # for open api 3.0. examples on reponses, for example: api-with-examples.yaml
36
27
  elsif v.key?(:content) && v[:content].is_a?(Hash) && v[:content].key?(:"application/json") &&
@@ -43,22 +34,12 @@ module LibOpenApiImport
43
34
  else
44
35
  tresp = ""
45
36
  end
46
- if tresp.is_a?(String)
47
- response_example << tresp
48
- elsif tresp.is_a?(Hash)
49
- exs = tresp.to_s
50
- exs.gsub!(/:(\w+)=>/, "\n\\1: ")
51
- response_example << exs
52
- elsif tresp.is_a?(Array)
37
+ if tresp.is_a?(Array)
53
38
  response_example << "["
54
- tresp.each do |ex|
55
- exs = ex.to_s
56
- if ex.is_a?(Hash)
57
- exs.gsub!(/:(\w+)=>/, "\n\\1: ")
58
- end
59
- response_example << "#{exs}, "
60
- end
39
+ tresp.each { |item| response_example << "#{item.inspect}, " }
61
40
  response_example << "]"
41
+ else
42
+ response_example << tresp.inspect
62
43
  end
63
44
  break # only the first one it is considered
64
45
  end
@@ -91,7 +72,7 @@ module LibOpenApiImport
91
72
  end
92
73
  elsif v.key?(:schema) && v[:schema].key?(:items) && v[:schema][:items].is_a?(Hash) && v[:schema][:items].key?(:type)
93
74
  # for the case only type supplied but nothing else for the array
94
- response_example << "[\"#{v[:schema][:items][:type]}\"]"
75
+ response_example << [v[:schema][:items][:type].to_s].inspect
95
76
  end
96
77
  response_example.each do |rs|
97
78
  # (@type Google) for the case in example the key is something like: @type:
@@ -5,7 +5,7 @@ using OpenApiImportStringExt
5
5
  class OpenApiImport
6
6
  class ParseError < StandardError; end
7
7
 
8
- VERSION = "0.12.1"
8
+ VERSION = "0.12.2"
9
9
 
10
10
  extend LibOpenApiImport
11
11
 
@@ -81,18 +81,16 @@ class OpenApiImport
81
81
 
82
82
  raw[:host] if raw.key?(:host)
83
83
  base_path = raw[:basePath] if raw.key?(:basePath)
84
- module_name = raw[:info][:title].camel_case
85
- module_version = "V#{raw[:info][:version].to_s.snake_case}"
84
+ module_name = ruby_constant_name(raw[:info][:title])
85
+ module_version = ruby_module_version(raw[:info][:version])
86
86
 
87
87
  output = []
88
88
  output_header = []
89
89
  output_header << ("#" * 50)
90
- output_header << "# #{raw[:info][:title]}"
91
- output_header << "# version: #{raw[:info][:version]}"
90
+ output_header.concat comment_lines(raw[:info][:title])
91
+ output_header.concat comment_lines(raw[:info][:version], prefix: "# version: ")
92
92
  output_header << "# description: "
93
- raw[:info][:description].to_s.split("\n").each do |d|
94
- output_header << "# #{d}" unless d == ""
95
- end
93
+ output_header.concat comment_lines(raw[:info][:description], prefix: "# ")
96
94
  output_header << ("#" * 50)
97
95
 
98
96
  output_header << "module Swagger"
@@ -124,7 +122,7 @@ class OpenApiImport
124
122
  if %w[get post put delete patch].include?(met.to_s.downcase)
125
123
  params = []
126
124
  params_path = []
127
- params_query = []
125
+ params_query = {}
128
126
  params_required = []
129
127
  params_data = []
130
128
  description_parameters = []
@@ -145,9 +143,9 @@ class OpenApiImport
145
143
  method_name.chop! if method_name[-1] == "_"
146
144
  elsif create_method_name == :operation_id
147
145
  if ((name_for_module == :tags) || (name_for_module == :tags_file)) && cont.key?(:tags) && cont[:tags].is_a?(Array) && cont[:tags].size.positive?
148
- metnametmp = cont[:operationId].gsub(/^#{cont[:tags].join}[\s_]*/, "")
146
+ metnametmp = cont[:operationId].gsub(/^#{Regexp.escape(cont[:tags].join)}[\s_]*/, "")
149
147
  cont[:tags].join.split.each do |tag|
150
- metnametmp = metnametmp.gsub(/^#{tag}[\s_]*/i, "")
148
+ metnametmp = metnametmp.gsub(/^#{Regexp.escape(tag)}[\s_]*/i, "")
151
149
  end
152
150
  metnametmp = met if metnametmp == ""
153
151
  else
@@ -155,14 +153,15 @@ class OpenApiImport
155
153
  end
156
154
  method_name = metnametmp.to_s.snake_case
157
155
  elsif ((name_for_module == :tags) || (name_for_module == :tags_file)) && cont.key?(:tags) && cont[:tags].is_a?(Array) && cont[:tags].size.positive?
158
- method_name = cont[:operationId].gsub(/^#{cont[:tags].join}[\s_]*/, "")
156
+ method_name = cont[:operationId].gsub(/^#{Regexp.escape(cont[:tags].join)}[\s_]*/, "")
159
157
  cont[:tags].join.split.each do |tag|
160
- method_name = method_name.gsub(/^#{tag}[\s_]*/i, "")
158
+ method_name = method_name.gsub(/^#{Regexp.escape(tag)}[\s_]*/i, "")
161
159
  end
162
160
  method_name = met if method_name == ""
163
161
  else
164
162
  method_name = cont[:operationId]
165
163
  end
164
+ method_name = ruby_method_name(method_name, preserve_case: create_method_name == :operationId)
166
165
  path_txt = path.path.dup.to_s
167
166
  if [:path, :path_file, :tags, :tags_file].include?(name_for_module)
168
167
  old_module_requests = module_requests
@@ -173,17 +172,20 @@ class OpenApiImport
173
172
  module_requests = "Root"
174
173
  else
175
174
  res_path = path_requests.scan(/(\w+)/)
176
- module_requests = res_path[0][0].camel_case
175
+ module_requests = ruby_constant_name(res_path[0][0])
177
176
  end
178
177
  elsif cont.key?(:tags) && cont[:tags].is_a?(Array) && cont[:tags].size.positive?
179
- module_requests = cont[:tags].join(" ").camel_case
178
+ module_requests = ruby_constant_name(cont[:tags].join(" "))
180
179
  else
181
180
  module_requests = "Undefined"
182
181
  end
183
182
 
184
183
  if /^(?<vers>v\d+)/i =~ method_name
185
184
  method_name = method_name.gsub(/^#{vers}_?/, "")
186
- module_requests = (vers.capitalize + module_requests).camel_case unless module_requests.start_with?(vers)
185
+ method_name = ruby_method_name(method_name, preserve_case: create_method_name == :operationId)
186
+ unless module_requests.start_with?(vers)
187
+ module_requests = ruby_constant_name(vers.capitalize + module_requests)
188
+ end
187
189
  end
188
190
 
189
191
  if old_module_requests != module_requests
@@ -204,16 +206,16 @@ class OpenApiImport
204
206
  end
205
207
 
206
208
  output << ""
207
- output << "# operationId: #{cont[:operationId]}, method: #{met}"
208
- output << "# summary: #{cont[:summary].split("\n").join("\n# ")}" if cont.key?(:summary)
209
- if cont[:description].to_s.split("\n").empty?
210
- output << "# description: #{cont[:description]}"
211
- else
212
- output << "# description: "
213
- cont[:description].to_s.split("\n").each do |d|
214
- output << "# #{d}" unless d == ""
209
+ output.concat comment_lines("#{cont[:operationId]}, method: #{met}", prefix: "# operationId: ")
210
+ if cont.key?(:summary)
211
+ summary_lines = cont[:summary].to_s.split(/\R/)
212
+ output << "# summary: #{summary_lines[0]}" unless summary_lines.empty?
213
+ summary_lines.drop(1).each do |line|
214
+ output << "# #{line}" unless line.empty?
215
215
  end
216
216
  end
217
+ output << "# description: "
218
+ output.concat comment_lines(cont[:description], prefix: "# ")
217
219
 
218
220
  mock_example = []
219
221
 
@@ -223,18 +225,19 @@ class OpenApiImport
223
225
 
224
226
  data_pattern += get_patterns("", v[:schema]) if v.key?(:schema)
225
227
  data_pattern.uniq!
226
- resp_description = v[:description].to_s.gsub("'", %q(\\\'))
228
+ response_key = ruby_symbol_key(k)
229
+ resp_description = v[:description].to_s.inspect
227
230
  if response_example.empty?
228
- responses << "'#{k}': { message: '#{resp_description}'}, "
231
+ responses << "#{response_key} { message: #{resp_description}}, "
229
232
  else
230
- responses << "'#{k}': { "
231
- responses << "message: '#{resp_description}', "
233
+ responses << "#{response_key} { "
234
+ responses << "message: #{resp_description}, "
232
235
  responses << "data: "
233
236
  responses << response_example
234
237
  responses << "},"
235
238
  if mock_response && mock_example.empty?
236
- mock_example << "code: '#{k}',"
237
- mock_example << "message: '#{resp_description}',"
239
+ mock_example << "code: #{k.to_s.inspect},"
240
+ mock_example << "message: #{resp_description},"
238
241
  mock_example << "data: "
239
242
  mock_example << response_example
240
243
  end
@@ -262,43 +265,40 @@ class OpenApiImport
262
265
  end
263
266
 
264
267
  if p[:in] == "path"
265
- if create_method_name == :operationId
266
- param_name = p[:name]
267
- path_txt = path_txt.gsub("{#{param_name}}", "\#{#{param_name}}")
268
- else
269
- param_name = p[:name].to_s.snake_case
270
- path_txt = path_txt.gsub("{#{p[:name]}}", "\#{#{param_name}}")
271
- end
268
+ param_name = ruby_parameter_name(p[:name])
269
+ path_txt = path_txt.gsub("{#{p[:name]}}", "\#{#{param_name}}")
272
270
  unless params_path.include?(param_name)
273
271
  if create_constants
274
- params_path << "#{param_name}: #{param_name.upcase}"
275
- required_constants << param_name.upcase
272
+ constant_name = ruby_environment_constant(param_name)
273
+ params_path << "#{param_name}: #{constant_name}"
274
+ required_constants << constant_name
276
275
  else
277
276
  params_path << param_name
278
277
  end
279
278
  @logger.warn "Description key is missing for #{met} #{path.path} #{p[:name]}" if p[:description].nil?
280
- description_parameters << "# #{p[:name]}: (#{type}) #{"(required)" if p[:required].to_s == "true"} #{p[:description].to_s.split("\n").join("\n#\t\t\t")}"
279
+ description_parameters.concat parameter_comment_lines(p[:name], type, p[:required], p[:description])
281
280
  end
282
281
  elsif p[:in] == "query"
283
- params_query << p[:name]
284
- params_required << p[:name] if p[:required].to_s == "true"
282
+ param_name = ruby_parameter_name(p[:name])
283
+ params_query[param_name] = p[:name].to_s
284
+ params_required << param_name if p[:required].to_s == "true"
285
285
  @logger.warn "Description key is missing for #{met} #{path.path} #{p[:name]}" if p[:description].nil?
286
- description_parameters << "# #{p[:name]}: (#{type}) #{"(required)" if p[:required].to_s == "true"} #{p[:description].to_s.split("\n").join("\n#\t\t\t")}"
286
+ description_parameters.concat parameter_comment_lines(p[:name], type, p[:required], p[:description])
287
287
  elsif (p[:in] == "formData") || (p[:in] == "formdata")
288
- description_parameters << "# #{p[:name]}: (#{p[:type]}) #{p[:description].split("\n").join("\n#\t\t\t")}"
288
+ description_parameters.concat parameter_comment_lines(p[:name], p[:type], p[:required], p[:description])
289
289
 
290
290
  case p[:type]
291
291
  when /^string$/i
292
- data_form << "#{p[:name]}: ''"
292
+ data_form << "#{ruby_hash_key(p[:name])} ''"
293
293
  data_form_hash[p[:name].to_sym] = ""
294
294
  when /^boolean$/i
295
- data_form << "#{p[:name]}: true"
295
+ data_form << "#{ruby_hash_key(p[:name])} true"
296
296
  data_form_hash[p[:name].to_sym] = true
297
297
  when /^number$/i
298
- data_form << "#{p[:name]}: 0"
298
+ data_form << "#{ruby_hash_key(p[:name])} 0"
299
299
  data_form_hash[p[:name].to_sym] = 0
300
300
  when /^integer$/i
301
- data_form << "#{p[:name]}: 0"
301
+ data_form << "#{ruby_hash_key(p[:name])} 0"
302
302
  data_form_hash[p[:name].to_sym] = 0
303
303
  else
304
304
  puts "! on formData not supported type #{p[:type]}"
@@ -356,7 +356,7 @@ class OpenApiImport
356
356
  end
357
357
 
358
358
  if dpv.keys.include?(:description)
359
- description_parameters << "# #{dpk}: (#{dpv[:type]}) #{dpv[:description].split("\n").join("\n#\t\t\t")}"
359
+ description_parameters.concat parameter_comment_lines(dpk, dpv[:type], false, dpv[:description])
360
360
  end
361
361
 
362
362
  data_pattern += get_patterns(dpk, dpv)
@@ -377,13 +377,7 @@ class OpenApiImport
377
377
  data_read_only << dpk
378
378
  end
379
379
  if dpv.keys.include?(:default)
380
- if dpv[:default].nil?
381
- data_default << "#{dpk}: nil"
382
- elsif dpv.type != "string"
383
- data_default << "#{dpk}: #{dpv[:default]}"
384
- else
385
- data_default << "#{dpk}: '#{dpv[:default]}'"
386
- end
380
+ data_default << "#{ruby_hash_key(dpk)} #{dpv[:default].inspect}"
387
381
  end
388
382
 
389
383
  params_data_hash[dpk] = build_example_value(dpv)
@@ -392,13 +386,13 @@ class OpenApiImport
392
386
  params_data << get_examples({ dpk => dpv }, :only_value, true).join
393
387
  params_data[-1].chop!.chop! if params_data[-1].to_s[-2..] == ", "
394
388
  params_data.pop if params_data[-1].match?(/^\s*$/im)
389
+ elsif dpv.keys.include?(:example)
390
+ raw = dpv[:example].is_a?(Array) && dpv.type != "array" ? dpv[:example][0] : dpv[:example]
391
+ params_data << "#{ruby_hash_key(dpk)} #{raw.inspect}"
392
+ elsif valv.to_s.empty?
393
+ params_data << "#{ruby_hash_key(dpk)} \"\""
395
394
  else
396
- if valv.to_s == ""
397
- valv = '""'
398
- elsif valv.include?('"')
399
- valv = valv.gsub('"', "'") unless valv.include?("'")
400
- end
401
- params_data << "#{dpk}: #{valv}"
395
+ params_data << "#{ruby_hash_key(dpk)} #{valv}"
402
396
  end
403
397
  end
404
398
  if params_data.size.positive?
@@ -420,7 +414,7 @@ class OpenApiImport
420
414
 
421
415
  unless data_required.empty?
422
416
  data_required.uniq!
423
- output << "# required data: #{data_required.inspect}"
417
+ output.concat comment_lines(data_required.inspect, prefix: "# required data: ")
424
418
  end
425
419
  end
426
420
  elsif p[:in] == "header"
@@ -438,32 +432,34 @@ class OpenApiImport
438
432
  if create_constants
439
433
  if params_query.include?(pr)
440
434
  if create_method_name == :operationId
441
- path_txt += "#{pr}=\#{#{pr}}&"
442
- params << "#{pr}: #{pr.upcase}"
443
- required_constants << pr.upcase
435
+ constant_name = ruby_environment_constant(pr)
436
+ path_txt += "#{params_query[pr]}=\#{#{pr}}&"
437
+ params << "#{pr}: #{constant_name}"
444
438
  else
445
- path_txt += "#{pr}=\#{#{pr.to_s.snake_case}}&"
446
- params << "#{pr.to_s.snake_case}: #{pr.to_s.snake_case.upcase}"
447
- required_constants << pr.to_s.snake_case.upcase
439
+ parameter_name = ruby_parameter_name(pr)
440
+ constant_name = ruby_environment_constant(parameter_name)
441
+ path_txt += "#{params_query[pr]}=\#{#{parameter_name}}&"
442
+ params << "#{parameter_name}: #{constant_name}"
448
443
  end
444
+ required_constants << constant_name
449
445
  end
450
446
  elsif params_query.include?(pr)
451
447
  if create_method_name == :operationId
452
- path_txt += "#{pr}=\#{#{pr}}&"
448
+ path_txt += "#{params_query[pr]}=\#{#{pr}}&"
453
449
  params << pr.to_s
454
450
  else
455
- path_txt += "#{pr}=\#{#{pr.to_s.snake_case}}&"
451
+ path_txt += "#{params_query[pr]}=\#{#{pr.to_s.snake_case}}&"
456
452
  params << pr.to_s.snake_case.to_s
457
453
  end
458
454
  end
459
455
  end
460
- params_query.each do |pq|
456
+ params_query.each do |pq, query_name|
461
457
  unless params_required.include?(pq)
462
458
  if create_method_name == :operationId
463
- path_txt += "#{pq}=\#{#{pq}}&"
459
+ path_txt += "#{query_name}=\#{#{pq}}&"
464
460
  params << "#{pq}: ''"
465
461
  else
466
- path_txt += "#{pq}=\#{#{pq.to_s.snake_case}}&"
462
+ path_txt += "#{query_name}=\#{#{pq.to_s.snake_case}}&"
467
463
  params << "#{pq.to_s.snake_case}: ''"
468
464
  end
469
465
  end
@@ -480,8 +476,9 @@ class OpenApiImport
480
476
  paramst = []
481
477
  prms = path_txt.scan(/[^#]{(\w+)}/)
482
478
  prms.each do |p|
483
- paramst << p[0].to_s.snake_case
484
- path_txt = path_txt.gsub("{#{p[0]}}", "\#{#{p[0].to_s.snake_case}}")
479
+ param_name = ruby_parameter_name(p[0])
480
+ paramst << param_name
481
+ path_txt = path_txt.gsub("{#{p[0]}}", "\#{#{param_name}}")
485
482
  end
486
483
  paramst.concat params
487
484
  params = paramst
@@ -491,20 +488,21 @@ class OpenApiImport
491
488
 
492
489
  output << "{"
493
490
 
494
- output << "name: \"#{module_requests}.#{method_name}\","
491
+ output << "name: #{"#{module_requests}.#{method_name}".inspect},"
495
492
 
496
- output << "path: \"#{base_path}#{path_txt}\","
493
+ interpolation_names = path_txt.scan(/#\{([A-Za-z_][A-Za-z0-9_]*)\}/).flatten
494
+ output << "path: #{ruby_interpolated_string("#{base_path}#{path_txt}", interpolation_names)},"
497
495
 
498
496
  output << "method: :#{met}," if met.to_s != ""
499
497
 
500
498
  unless data_required.empty?
501
499
  output << "data_required: ["
502
- output << ":'#{data_required.uniq.join("', :'")}'"
500
+ output << data_required.uniq.inspect[1..-2]
503
501
  output << "],"
504
502
  end
505
503
  unless data_read_only.empty?
506
504
  output << "data_read_only: ["
507
- output << ":'#{data_read_only.uniq.join("', :'")}'"
505
+ output << data_read_only.uniq.inspect[1..-2]
508
506
  output << "],"
509
507
  end
510
508
  unless data_default.empty?
@@ -552,7 +550,7 @@ class OpenApiImport
552
550
  data_examples[0].each do |edata|
553
551
  read_only = false
554
552
  data_read_only.each do |rdata|
555
- if edata.scan(/^#{rdata}:/).size.positive?
553
+ if edata.scan(/^#{Regexp.escape(rdata.to_s)}:/).size.positive?
556
554
  read_only = true
557
555
  break
558
556
  elsif edata.scan(":").empty?
@@ -632,7 +630,8 @@ class OpenApiImport
632
630
  output = output_header + out_mod + output_footer
633
631
  output_txt = output.join("\n")
634
632
  requests_file_path = "#{file_to_convert}_#{mod}.rb"
635
- requires_txt += "require_relative '#{File.basename(swagger_file)}_#{mod}'\n"
633
+ required_path = "#{File.basename(swagger_file)}_#{mod}"
634
+ requires_txt += "require_relative #{required_path.inspect}\n"
636
635
  if return_data
637
636
  generated_files[requests_file_path] = output_txt
638
637
  else
@@ -10,10 +10,10 @@ module LibOpenApiImport
10
10
  hash.each do |kr, kv|
11
11
  if kv.is_a?(Hash)
12
12
  restv = pretty_hash_symbolized(kv)
13
- restv[0] = "#{kr}: {"
13
+ restv[0] = "#{ruby_hash_key(kr)} {"
14
14
  output += restv
15
15
  else
16
- output << "#{kr}: #{kv.inspect}, "
16
+ output << "#{ruby_hash_key(kr)} #{kv.inspect}, "
17
17
  end
18
18
  end
19
19
  output << "},"
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ using OpenApiImportStringExt
4
+
5
+ module LibOpenApiImport
6
+ RUBY_KEYWORDS = %w[
7
+ BEGIN END alias and begin break case class def defined? do else elsif end
8
+ ensure false for if in module next nil not or redo rescue retry return self
9
+ super then true undef unless until when while yield
10
+ ].freeze
11
+
12
+ private
13
+
14
+ # Prefix every physical line so spec text cannot terminate a Ruby comment.
15
+ def comment_lines(text, prefix: "# ")
16
+ text.to_s.split(/\R/).reject(&:empty?).map { |line| "#{prefix}#{line}" }
17
+ end
18
+
19
+ def ruby_constant_name(text, fallback: "Untitled")
20
+ name = text.to_s.camel_case.gsub(/[^A-Za-z0-9_]/, "")
21
+ name = fallback if name.empty?
22
+ name = "C#{name}" unless name.match?(/\A[A-Z]/)
23
+ name
24
+ end
25
+
26
+ def ruby_module_version(text, fallback: "V0")
27
+ name = "V#{text.to_s.snake_case}".gsub(/[^A-Za-z0-9_]/, "")
28
+ name = fallback if name.empty? || name == "V"
29
+ name
30
+ end
31
+
32
+ def ruby_method_name(text, preserve_case: false, fallback: "undefined")
33
+ source = text.to_s.split(/\R/).join("_")
34
+ name = if preserve_case
35
+ source.gsub(/[^A-Za-z0-9_]/, "")
36
+ else
37
+ source.snake_case.gsub(/[^a-z0-9_]/, "")
38
+ end
39
+ name = fallback if name.empty?
40
+ name = "_#{name}" unless name.match?(/\A[A-Za-z_]/)
41
+ name = "#{name}_" if RUBY_KEYWORDS.include?(name)
42
+ name
43
+ end
44
+
45
+ def ruby_parameter_name(text, fallback: "parameter")
46
+ ruby_method_name(text, fallback: fallback)
47
+ end
48
+
49
+ def ruby_environment_constant(text)
50
+ name = ruby_parameter_name(text).upcase
51
+ name = "C#{name}" unless name.match?(/\A[A-Z]/)
52
+ name
53
+ end
54
+
55
+ def ruby_hash_key(text)
56
+ name = text.to_s
57
+ if name.match?(/\A[A-Za-z_][A-Za-z0-9_]*\z/) && !RUBY_KEYWORDS.include?(name)
58
+ "#{name}:"
59
+ else
60
+ "#{name.inspect} =>"
61
+ end
62
+ end
63
+
64
+ def ruby_symbol_key(text)
65
+ "#{text.to_s.inspect}:"
66
+ end
67
+
68
+ def ruby_symbol_literal(text)
69
+ text.to_s.to_sym.inspect
70
+ end
71
+
72
+ # String#inspect escapes interpolation. Re-enable only placeholders that were
73
+ # generated from identifiers already reduced to Ruby local-variable syntax.
74
+ def ruby_interpolated_string(text, variable_names)
75
+ literal = text.to_s.inspect
76
+ variable_names.uniq.each do |name|
77
+ token = format("\#{%s}", name)
78
+ literal = literal.gsub("\\#{token}", token)
79
+ end
80
+ literal
81
+ end
82
+
83
+ def parameter_comment_lines(name, type, required, description)
84
+ required_label = required.to_s == "true" ? "(required) " : ""
85
+ rendered = "#{name}: (#{type}) #{required_label}#{description}".rstrip
86
+ comment_lines(rendered, prefix: "# ")
87
+ end
88
+ end
@@ -11,7 +11,7 @@ module OpenApiImportStringExt
11
11
  end
12
12
 
13
13
  def camel_case
14
- return self if self !~ /_/ && self !~ /-/ && self !~ /\s/ && self =~ /^[A-Z]+.*/
14
+ return self if self =~ /\A[A-Z][A-Za-z0-9]*\z/
15
15
 
16
16
  gsub(/\W/, "_")
17
17
  .split("_").map(&:capitalize).join
@@ -3,6 +3,7 @@
3
3
  require "fileutils"
4
4
 
5
5
  require_relative "open_api_import/utils"
6
+ require_relative "open_api_import/safe_codegen"
6
7
  require_relative "open_api_import/filter"
7
8
  require_relative "open_api_import/pretty_hash_symbolized"
8
9
  require_relative "open_api_import/get_patterns"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open_api_import
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Ruiz
@@ -129,6 +129,7 @@ files:
129
129
  - lib/open_api_import/get_response_examples.rb
130
130
  - lib/open_api_import/open_api_import.rb
131
131
  - lib/open_api_import/pretty_hash_symbolized.rb
132
+ - lib/open_api_import/safe_codegen.rb
132
133
  - lib/open_api_import/utils.rb
133
134
  homepage: https://github.com/MarioRuiz/open_api_import
134
135
  licenses: