openapi_sdk_generator_gem 0.1.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5de5faec687e88d6cd692bb5f08b3cbda8c0003e4dd0dd2f75f438a7d19b1c0b
4
- data.tar.gz: b8c7d77286398b2fe0af806fa84075ff6fb423cd904ad2f58f216f1ef35b79dc
3
+ metadata.gz: 2b7199578a41927a7b94a00e995cab096eb77c148e6837a53e55bc5f2ce02845
4
+ data.tar.gz: f758e337a3dde8a1fe681d62e83d9bfb8c0abeb6460c56a1a2a163615aa9dafe
5
5
  SHA512:
6
- metadata.gz: 376afa723a81952b594008f7c73a345b567b0020993a2202beb9e140ce7cc57fbe788f0fa6e815a43bdd59870ce2cdb4dabe7092babeecc814013873703ea9be
7
- data.tar.gz: f1d182b79a0e0dd0a65c911eb24ebf233b84c0d8c07f9f4a8043c91ffd026bca6169f2ceb36536351139293881af7f1347765e1a40230ac48b7219a8cbe683a3
6
+ metadata.gz: 4e5ee24a140baed8a34b3c668f0da4dcb7676a481644d19502d3fa2755b975a64fc6357983772c17ee0b1bf225adc18c801cefe917fb320f7b888d7462718302
7
+ data.tar.gz: 4093d3f8b34ee6d799f25b1b42119d54122de01e1af15cd2ac4c0978c3869437eacdaf04f1d87ea85ef5a7fce2dd218ea9f827b79c363cc969bf665abe94c064
@@ -11,7 +11,7 @@ parser = OptionParser.new do |opts|
11
11
  opts.separator "Generate SDK from OpenAPI specification"
12
12
  opts.separator ""
13
13
 
14
- opts.on("-i", "--input FILE", "OpenAPI specification file (JSON or YAML)") do |v|
14
+ opts.on("-i", "--input FILE_OR_URL", "OpenAPI specification file (JSON/YAML) or URL") do |v|
15
15
  options[:input] = v
16
16
  end
17
17
 
@@ -25,6 +25,13 @@ parser = OptionParser.new do |opts|
25
25
 
26
26
  opts.on("-h", "--help", "Show this help message") do
27
27
  puts opts
28
+ puts ""
29
+ puts "Examples:"
30
+ puts " # From local file"
31
+ puts " openapi-sdk-generator -i petstore.yaml -o ./output -l ruby"
32
+ puts ""
33
+ puts " # From URL"
34
+ puts " openapi-sdk-generator -i https://example.com/api-spec.yaml -o ./output -l javascript"
28
35
  exit
29
36
  end
30
37
 
@@ -10,15 +10,13 @@ module OpenapiSdkGenerator
10
10
  def write_to_directory(output_dir)
11
11
  FileUtils.mkdir_p(output_dir)
12
12
 
13
- # Write client file
13
+
14
14
  client_content = generate_client
15
15
  File.write(File.join(output_dir, 'client.js'), client_content)
16
16
 
17
- # Write package.json
18
17
  package_json = generate_package_json
19
18
  File.write(File.join(output_dir, 'package.json'), package_json)
20
19
 
21
- # Write README
22
20
  readme_content = generate_readme
23
21
  File.write(File.join(output_dir, 'README.md'), readme_content)
24
22
  end
@@ -12,18 +12,15 @@ module OpenapiSdkGenerator
12
12
  FileUtils.mkdir_p(output_dir)
13
13
  FileUtils.mkdir_p(File.join(output_dir, 'models'))
14
14
 
15
- # Write client file
16
15
  client_content = generate_client
17
16
  File.write(File.join(output_dir, 'client.rb'), client_content)
18
17
 
19
- # Write model files
20
18
  parser.models.each do |name, model|
21
19
  model_content = generate_model(model)
22
20
  filename = "#{sanitize_name(name)}.rb"
23
21
  File.write(File.join(output_dir, 'models', filename), model_content)
24
22
  end
25
23
 
26
- # Write README
27
24
  readme_content = generate_readme
28
25
  File.write(File.join(output_dir, 'README.md'), readme_content)
29
26
  end
@@ -93,9 +90,6 @@ module OpenapiSdkGenerator
93
90
  end
94
91
  end
95
92
 
96
-
97
-
98
-
99
93
  # Converts parameters into Ruby method signature
100
94
  def format_method_params(params)
101
95
  return "" unless params.is_a?(Array) && !params.empty?
@@ -109,7 +103,7 @@ module OpenapiSdkGenerator
109
103
  end.compact.join(", ")
110
104
  end
111
105
 
112
- # Converts "/pets/{petId}""/pets/#{pet_id}"
106
+ # /pets/{petId} → /pets/#{pet_id}
113
107
  def format_url_path(path, params = [])
114
108
  return path unless params.is_a?(Array) && !params.empty?
115
109
 
@@ -1,3 +1,7 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'openssl'
4
+
1
5
  module OpenapiSdkGenerator
2
6
  class Parser
3
7
  attr_reader :spec, :api_info, :base_url, :endpoints, :models
@@ -26,18 +30,75 @@ module OpenapiSdkGenerator
26
30
  private
27
31
 
28
32
  def load_spec
29
- content = File.read(@file_path)
30
- if @file_path.end_with?('.json')
33
+ content = fetch_content
34
+ parse_content(content)
35
+ rescue => e
36
+ raise Error, "Failed to load OpenAPI spec: #{e.message}"
37
+ end
38
+
39
+ def fetch_content
40
+ if url?(@file_path)
41
+ fetch_from_url(@file_path)
42
+ else
43
+ fetch_from_file(@file_path)
44
+ end
45
+ end
46
+
47
+ def url?(path)
48
+ path =~ /\A#{URI::DEFAULT_PARSER.make_regexp(%w[http https])}\z/
49
+ end
50
+
51
+ def fetch_from_url(url)
52
+
53
+ uri = URI.parse(url)
54
+
55
+ http = Net::HTTP.new(uri.host, uri.port)
56
+ http.use_ssl = (uri.scheme == 'https')
57
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
58
+
59
+ request = Net::HTTP::Get.new(uri.request_uri)
60
+ response = http.request(request)
61
+
62
+ unless response.is_a?(Net::HTTPSuccess)
63
+ raise Error, "Failed to fetch URL: #{response.code} #{response.message}"
64
+ end
65
+
66
+ response.body
67
+ rescue SocketError, Net::OpenTimeout, Net::ReadTimeout => e
68
+ raise Error, "Network error while fetching URL: #{e.message}"
69
+ end
70
+
71
+ def fetch_from_file(file_path)
72
+ unless File.exist?(file_path)
73
+ raise Error, "File not found: #{file_path}"
74
+ end
75
+ File.read(file_path)
76
+ end
77
+
78
+ def parse_content(content)
79
+ if looks_like_json?(content)
31
80
  JSON.parse(content)
32
- elsif @file_path.end_with?('.yaml', '.yml')
81
+ elsif looks_like_yaml?(content)
33
82
  YAML.load(content)
34
83
  else
35
- raise Error, "Unsupported file format. Use .json, .yaml, or .yml"
84
+ begin
85
+ JSON.parse(content)
86
+ rescue JSON::ParserError
87
+ YAML.load(content)
88
+ end
36
89
  end
37
- rescue => e
90
+ rescue JSON::ParserError, Psych::SyntaxError => e
38
91
  raise Error, "Failed to parse OpenAPI spec: #{e.message}"
39
92
  end
40
93
 
94
+ def looks_like_json?(content)
95
+ content.strip.start_with?('{', '[')
96
+ end
97
+
98
+ def looks_like_yaml?(content)
99
+ content =~ /^\w+:/
100
+ end
101
+
41
102
  def parse_spec
42
103
  parse_info
43
104
  parse_servers
@@ -120,16 +181,45 @@ module OpenapiSdkGenerator
120
181
  def parse_schemas
121
182
  components = @spec['components'] || {}
122
183
  schemas = components['schemas'] || {}
123
-
184
+
124
185
  schemas.each do |name, schema|
186
+ resolved_schema = resolve_schema(schema)
187
+
125
188
  @models[name] = {
126
189
  name: name,
127
- type: schema['type'],
128
- properties: parse_properties(schema['properties']),
129
- required: schema['required'] || []
190
+ type: resolved_schema['type'],
191
+ properties: parse_properties(resolved_schema['properties']),
192
+ required: resolved_schema['required'] || []
130
193
  }
131
194
  end
132
195
  end
196
+
197
+
198
+ def resolve_schema(schema)
199
+ if schema['$ref']
200
+ return resolve_schema(ref_to_schema(schema['$ref']))
201
+ end
202
+
203
+ if schema['allOf']
204
+ merged = { 'properties' => {}, 'required' => [] }
205
+
206
+ schema['allOf'].each do |subschema|
207
+ resolved = resolve_schema(subschema)
208
+ merged['properties'].merge!(resolved['properties'] || {})
209
+ merged['required'] |= (resolved['required'] || [])
210
+ end
211
+
212
+ return merged
213
+ end
214
+
215
+ schema
216
+ end
217
+
218
+
219
+ def ref_to_schema(ref)
220
+ ref_path = ref.sub('#/components/schemas/', '')
221
+ @spec['components']['schemas'][ref_path]
222
+ end
133
223
 
134
224
  def parse_properties(properties)
135
225
  return {} unless properties
@@ -29,7 +29,7 @@ module OpenapiSdkGenerator
29
29
  generator.write_to_directory(@options[:output])
30
30
 
31
31
  puts " SDK generated successfully!"
32
- puts "📁 Output directory: #{@options[:output]}"
32
+ puts "Output directory: #{@options[:output]}"
33
33
  rescue => e
34
34
  puts " Error: #{e.message}"
35
35
  exit 1
@@ -37,13 +37,20 @@ module OpenapiSdkGenerator
37
37
 
38
38
  private
39
39
 
40
- def validate_options!
41
- raise Error, "Input file is required" unless @options[:input]
42
- raise Error, "Output directory is required" unless @options[:output]
43
- raise Error, "Language is required (ruby or javascript)" unless @options[:language]
44
- raise Error, "Input file not found" unless File.exist?(@options[:input])
40
+ def validate_options!
41
+ raise Error, "Input is required" unless @options[:input]
42
+ raise Error, "Output directory is required" unless @options[:output]
43
+ raise Error, "Language is required (ruby or javascript)" unless @options[:language]
44
+
45
+ unless url?(@options[:input]) || File.exist?(@options[:input])
46
+ raise Error, "Input must be a valid file path or URL"
47
+ end
48
+ end
49
+
50
+
51
+ def url?(value)
52
+ value.start_with?("http://", "https://")
45
53
  end
46
-
47
54
  def create_generator(language, parser)
48
55
  case language.downcase
49
56
  when 'ruby'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openapi_sdk_generator_gem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taimour Afzal