swagger23 0.1.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.
data/lib/swagger23.rb ADDED
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require_relative "swagger23/version"
5
+ require_relative "swagger23/error"
6
+ require_relative "swagger23/ref_rewriter"
7
+ require_relative "swagger23/schema_processor"
8
+ require_relative "swagger23/converters/info"
9
+ require_relative "swagger23/converters/servers"
10
+ require_relative "swagger23/converters/paths"
11
+ require_relative "swagger23/converters/components"
12
+ require_relative "swagger23/converters/security"
13
+ require_relative "swagger23/converter"
14
+
15
+ module Swagger23
16
+ # Parse a JSON or YAML string into a Ruby Hash.
17
+ #
18
+ # Detection strategy: inspect the first non-whitespace byte.
19
+ # '{' or '[' → JSON (the only two valid JSON document starters)
20
+ # anything else → YAML
21
+ #
22
+ # This avoids trying to JSON-parse a UTF-8 YAML string, which raises
23
+ # Encoding::InvalidByteSequenceError when the Ruby process is running with
24
+ # an ASCII locale.
25
+ #
26
+ # @param source [String] raw JSON or YAML content
27
+ # @return [Hash] parsed document
28
+ # @raise [Swagger23::Error] if the source cannot be parsed as either format
29
+ def self.parse(source)
30
+ # Ensure we always work with a UTF-8 string regardless of how the caller
31
+ # obtained it (File.read without encoding:, STDIN.read, etc.).
32
+ source = source.dup.force_encoding("UTF-8") unless source.encoding == Encoding::UTF_8
33
+
34
+ first = source.lstrip[0]
35
+
36
+ if first == "{" || first == "["
37
+ begin
38
+ JSON.parse(source)
39
+ rescue JSON::ParserError => e
40
+ raise Swagger23::Error, "JSON parse error: #{e.message}"
41
+ end
42
+ else
43
+ require "yaml"
44
+ begin
45
+ result = YAML.safe_load(source)
46
+ rescue Psych::SyntaxError => e
47
+ raise Swagger23::Error, "Could not parse input as YAML: #{e.message}"
48
+ end
49
+
50
+ if result.nil?
51
+ raise Swagger23::Error, "Could not parse input: document is empty or null"
52
+ end
53
+
54
+ unless result.is_a?(Hash)
55
+ raise Swagger23::Error, "Input parsed to #{result.class}, expected a Hash"
56
+ end
57
+
58
+ result
59
+ end
60
+ end
61
+
62
+ # Convert a Swagger 2.0 Hash to an OpenAPI 3.0 Hash.
63
+ #
64
+ # @param swagger [Hash] parsed Swagger 2.0 document
65
+ # @return [Hash] OpenAPI 3.0 document
66
+ def self.convert(swagger)
67
+ Converter.new(swagger).convert
68
+ end
69
+
70
+ # Parse a JSON or YAML string and return the converted OpenAPI 3.0 document
71
+ # as a pretty-printed JSON string.
72
+ #
73
+ # @param source [String] Swagger 2.0 document as JSON or YAML
74
+ # @return [String] OpenAPI 3.0 document as JSON
75
+ def self.convert_string(source)
76
+ JSON.pretty_generate(convert(parse(source)))
77
+ end
78
+
79
+ # Parse a JSON or YAML string and return the converted OpenAPI 3.0 document
80
+ # as a YAML string.
81
+ #
82
+ # @param source [String] Swagger 2.0 document as JSON or YAML
83
+ # @return [String] OpenAPI 3.0 document as YAML
84
+ def self.convert_to_yaml(source)
85
+ require "yaml"
86
+ YAML.dump(stringify_keys_deep(convert(parse(source))))
87
+ end
88
+
89
+ # @deprecated Use {convert_string} instead (identical behaviour, clearer name).
90
+ def self.convert_json(source)
91
+ convert_string(source)
92
+ end
93
+
94
+ # ── Internal helpers ──────────────────────────────────────────────────────
95
+
96
+ # YAML.dump can emit symbols as keys if the hash was built with symbol keys.
97
+ # Our converter always uses string keys (coming from JSON.parse), but we
98
+ # normalise just in case a caller passes in a symbolised hash.
99
+ def self.stringify_keys_deep(obj)
100
+ case obj
101
+ in Hash
102
+ obj.each_with_object({}) do |(k, v), h|
103
+ h[k.to_s] = stringify_keys_deep(v)
104
+ end
105
+ in Array
106
+ obj.map { |item| stringify_keys_deep(item) }
107
+ else
108
+ obj
109
+ end
110
+ end
111
+ private_class_method :stringify_keys_deep
112
+ end
data/sig/swagger23.rbs ADDED
@@ -0,0 +1,71 @@
1
+ # Type signatures for the swagger23 gem public API.
2
+ # Compatible with Steep, Sorbet (via rbs), and IDEs such as RubyMine / VS Code + ruby-lsp.
3
+
4
+ module Swagger23
5
+ VERSION: String
6
+
7
+ class Error < StandardError
8
+ end
9
+
10
+ class InvalidSwaggerError < Error
11
+ end
12
+
13
+ # Parse a JSON or YAML string into a Ruby Hash.
14
+ def self.parse: (String source) -> Hash[String, untyped]
15
+
16
+ # Convert a Swagger 2.0 Hash to an OpenAPI 3.0 Hash.
17
+ def self.convert: (Hash[String, untyped] swagger) -> Hash[String, untyped]
18
+
19
+ # Parse and convert, returning a pretty-printed JSON string.
20
+ def self.convert_string: (String source) -> String
21
+
22
+ # Parse and convert, returning a YAML string.
23
+ def self.convert_to_yaml: (String source) -> String
24
+
25
+ # @deprecated Use convert_string instead.
26
+ def self.convert_json: (String source) -> String
27
+
28
+ class Converter
29
+ SUPPORTED_SWAGGER_VERSION: String
30
+ TARGET_OPENAPI_VERSION: String
31
+
32
+ def initialize: (Hash[String, untyped] swagger) -> void
33
+ def convert: () -> Hash[String, untyped]
34
+ end
35
+
36
+ module RefRewriter
37
+ REF_MAP: Hash[String, String]
38
+
39
+ def self.rewrite: (untyped obj) -> untyped
40
+ end
41
+
42
+ module SchemaProcessor
43
+ def self.process: (untyped obj) -> untyped
44
+ end
45
+
46
+ module Converters
47
+ module Info
48
+ def self.convert: (Hash[String, untyped] swagger) -> Hash[String, untyped]
49
+ end
50
+
51
+ module Servers
52
+ def self.convert: (Hash[String, untyped] swagger) -> Array[Hash[String, untyped]]
53
+ end
54
+
55
+ module Paths
56
+ HTTP_METHODS: Array[String]
57
+
58
+ def self.convert: (Hash[String, untyped] swagger) -> Hash[String, untyped]
59
+ end
60
+
61
+ module Components
62
+ def self.convert: (Hash[String, untyped] swagger) -> Hash[String, untyped]
63
+ end
64
+
65
+ module Security
66
+ def self.convert: (Hash[String, untyped] swagger) -> Hash[String, untyped]
67
+ end
68
+
69
+ ParameterConverter: singleton(Paths)
70
+ end
71
+ end
data/swagger23.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/swagger23/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "swagger23"
7
+ spec.version = Swagger23::VERSION
8
+ spec.authors = ["Maxim Veysgeym"]
9
+ spec.email = []
10
+ spec.summary = "Convert Swagger 2.0 to OpenAPI 3.0 — Ruby library and CLI"
11
+ spec.description = <<~DESC
12
+ swagger23 converts Swagger 2.0 (OAS 2) API specifications into OpenAPI 3.0.3 (OAS 3)
13
+ specifications. Accepts JSON or YAML input, produces JSON or YAML output.
14
+ Works as a Ruby library (Swagger23.convert) or a standalone CLI tool (swagger23).
15
+ Handles paths, parameters, requestBody, components/schemas, securitySchemes,
16
+ servers, $ref rewriting, collectionFormat, x-nullable, discriminator, OAuth2 flows,
17
+ and file uploads. No external runtime dependencies. Safe for large specs.
18
+ DESC
19
+ spec.license = "MIT"
20
+ spec.homepage = "https://github.com/Qew7/swagger23"
21
+
22
+ spec.metadata = {
23
+ "homepage_uri" => spec.homepage,
24
+ "source_code_uri" => spec.homepage,
25
+ "bug_tracker_uri" => "#{spec.homepage}/issues",
26
+ "documentation_uri" => "#{spec.homepage}/blob/main/README.md"
27
+ }
28
+
29
+ spec.required_ruby_version = ">= 3.2.0"
30
+
31
+ spec.files = Dir[
32
+ "lib/**/*.rb",
33
+ "sig/**/*.rbs",
34
+ "bin/*",
35
+ "swagger23.gemspec",
36
+ "README.md",
37
+ "LICENSE"
38
+ ]
39
+
40
+ spec.bindir = "bin"
41
+ spec.executables = ["swagger23"]
42
+ spec.require_paths = ["lib"]
43
+
44
+ spec.add_dependency "json", ">= 2.0"
45
+
46
+ spec.add_development_dependency "rspec", "~> 3.12"
47
+ spec.add_development_dependency "rake", "~> 13.0"
48
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: swagger23
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Maxim Veysgeym
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-03-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ description: |
56
+ swagger23 converts Swagger 2.0 (OAS 2) API specifications into OpenAPI 3.0.3 (OAS 3)
57
+ specifications. Accepts JSON or YAML input, produces JSON or YAML output.
58
+ Works as a Ruby library (Swagger23.convert) or a standalone CLI tool (swagger23).
59
+ Handles paths, parameters, requestBody, components/schemas, securitySchemes,
60
+ servers, $ref rewriting, collectionFormat, x-nullable, discriminator, OAuth2 flows,
61
+ and file uploads. No external runtime dependencies. Safe for large specs.
62
+ email: []
63
+ executables:
64
+ - swagger23
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - LICENSE
69
+ - README.md
70
+ - bin/swagger23
71
+ - lib/swagger23.rb
72
+ - lib/swagger23/converter.rb
73
+ - lib/swagger23/converters/components.rb
74
+ - lib/swagger23/converters/info.rb
75
+ - lib/swagger23/converters/paths.rb
76
+ - lib/swagger23/converters/security.rb
77
+ - lib/swagger23/converters/servers.rb
78
+ - lib/swagger23/error.rb
79
+ - lib/swagger23/ref_rewriter.rb
80
+ - lib/swagger23/schema_processor.rb
81
+ - lib/swagger23/version.rb
82
+ - sig/swagger23.rbs
83
+ - swagger23.gemspec
84
+ homepage: https://github.com/Qew7/swagger23
85
+ licenses:
86
+ - MIT
87
+ metadata:
88
+ homepage_uri: https://github.com/Qew7/swagger23
89
+ source_code_uri: https://github.com/Qew7/swagger23
90
+ bug_tracker_uri: https://github.com/Qew7/swagger23/issues
91
+ documentation_uri: https://github.com/Qew7/swagger23/blob/main/README.md
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 3.2.0
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubygems_version: 3.4.19
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Convert Swagger 2.0 to OpenAPI 3.0 — Ruby library and CLI
111
+ test_files: []