openapi_parser 0.1.5 → 0.1.6

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -2
  3. data/.rubocop_ignore.yml +6 -0
  4. data/.travis.yml +33 -4
  5. data/CHANGELOG.md +9 -0
  6. data/README.md +39 -6
  7. data/lib/openapi_parser/concern.rb +2 -1
  8. data/lib/openapi_parser/concerns/expandable.rb +52 -44
  9. data/lib/openapi_parser/concerns/media_type_selectable.rb +26 -0
  10. data/lib/openapi_parser/concerns/parser.rb +43 -0
  11. data/lib/openapi_parser/concerns/parser/core.rb +21 -0
  12. data/lib/openapi_parser/concerns/parser/hash.rb +10 -0
  13. data/lib/openapi_parser/concerns/parser/hash_body.rb +12 -0
  14. data/lib/openapi_parser/concerns/parser/list.rb +10 -0
  15. data/lib/openapi_parser/concerns/parser/object.rb +14 -0
  16. data/lib/openapi_parser/concerns/parser/value.rb +14 -0
  17. data/lib/openapi_parser/concerns/schema_loader.rb +58 -0
  18. data/lib/openapi_parser/concerns/schema_loader/base.rb +28 -0
  19. data/lib/openapi_parser/concerns/schema_loader/creator.rb +48 -0
  20. data/lib/openapi_parser/concerns/schema_loader/hash_body_loader.rb +37 -0
  21. data/lib/openapi_parser/concerns/schema_loader/hash_objects_loader.rb +29 -0
  22. data/lib/openapi_parser/concerns/schema_loader/list_loader.rb +28 -0
  23. data/lib/openapi_parser/concerns/schema_loader/objects_loader.rb +21 -0
  24. data/lib/openapi_parser/concerns/schema_loader/values_loader.rb +10 -0
  25. data/lib/openapi_parser/config.rb +1 -1
  26. data/lib/openapi_parser/errors.rb +9 -0
  27. data/lib/openapi_parser/path_item_finder.rb +18 -18
  28. data/lib/openapi_parser/request_operation.rb +4 -4
  29. data/lib/openapi_parser/schema_validator.rb +77 -54
  30. data/lib/openapi_parser/schema_validators/all_of_validator.rb +16 -0
  31. data/lib/openapi_parser/schema_validators/any_of_validator.rb +1 -1
  32. data/lib/openapi_parser/schema_validators/array_validator.rb +2 -4
  33. data/lib/openapi_parser/schema_validators/base.rb +9 -6
  34. data/lib/openapi_parser/schema_validators/boolean_validator.rb +11 -9
  35. data/lib/openapi_parser/schema_validators/float_validator.rb +8 -10
  36. data/lib/openapi_parser/schema_validators/integer_validator.rb +11 -10
  37. data/lib/openapi_parser/schema_validators/nil_validator.rb +1 -0
  38. data/lib/openapi_parser/schema_validators/object_validator.rb +3 -3
  39. data/lib/openapi_parser/schema_validators/string_validator.rb +13 -13
  40. data/lib/openapi_parser/schemas/base.rb +1 -2
  41. data/lib/openapi_parser/schemas/media_type.rb +3 -1
  42. data/lib/openapi_parser/schemas/openapi.rb +1 -1
  43. data/lib/openapi_parser/schemas/operation.rb +17 -14
  44. data/lib/openapi_parser/schemas/parameter.rb +2 -2
  45. data/lib/openapi_parser/schemas/request_body.rb +12 -5
  46. data/lib/openapi_parser/schemas/response.rb +4 -4
  47. data/lib/openapi_parser/schemas/responses.rb +21 -3
  48. data/lib/openapi_parser/version.rb +1 -1
  49. data/openapi_parser.gemspec +3 -2
  50. metadata +51 -19
  51. data/lib/openapi_parser/concerns/parseable.rb +0 -238
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1635ca728b8c31ce02b997acea2b7fb763b15558a785b17e95ca2ee47fe58232
4
- data.tar.gz: ff8c1957b980f7f363f7e68e44098e862996c73d140b57a9e02d0b39c4527a77
3
+ metadata.gz: e0035d4ece30f151226f04a1462ae6cf4d54c36011b315810bd49588f66b0632
4
+ data.tar.gz: cae26e5b18e0ab71b2027d56a828cccd737126852b96c68facf88f8ba27db0ab
5
5
  SHA512:
6
- metadata.gz: b39a5c07adaed7a98b0ed984767cf6bf0c92d6e8261f1cd94ddc4fe5598b0277c990b30901ed03eabbce638a434d2a8d78c9be18d1eaaac95805604929a57d8f
7
- data.tar.gz: 2e99c3ae918a2f1c4bc07e66ec71dddf877dda8457ded288aa744449806c02eae38d82c6c47782503fa3bec91b18bb5757605febfdd591ada31d24ebe94524f1
6
+ metadata.gz: 0456ee6d9363ff05c1ef517cbc9aa8cfbcad55aa054e012009ec685a5b97c7779c897842918a868dae3acefa143bbfa7790fc7bb1ba370e04293fc7ead130ef4
7
+ data.tar.gz: d2855d0574bfdc5a769576ffa89af5d1006f960af4a4790e92edfbe5763eb3a954698f71522d599524b1b9d906f11632440167c4e37e524435804873aeede533
@@ -1,10 +1,13 @@
1
1
  inherit_gem:
2
2
  fincop:
3
- - 'config/rails.yml'
3
+ # - 'config/rails.yml'
4
4
  - 'config/rspec.yml'
5
5
  - 'config/rubocop.yml'
6
- # If you are using Rails 4, activate this cop.
6
+ # If you are using Rails 4, activate this cop.
7
7
  # - 'config/disabled_for_rails_4.yml'
8
8
 
9
+ inherit_from:
10
+ - '.rubocop_ignore.yml'
11
+
9
12
  AllCops:
10
13
  TargetRubyVersion: 2.5
@@ -0,0 +1,6 @@
1
+ Metrics/ParameterLists:
2
+ Exclude:
3
+ - lib/openapi_parser/concerns/parser.rb
4
+
5
+ RSpec/FilePath:
6
+ Enabled: false
@@ -1,7 +1,36 @@
1
- ---
2
- sudo: false
1
+ env:
2
+ global:
3
+ - CC_TEST_REPORTER_ID=b49a1717b8ff0aef9eced41d0f87d350a88b46d55083ba2e3df8b6f441ae3fb7
4
+
3
5
  language: ruby
4
- cache: bundler
6
+
5
7
  rvm:
8
+ - 2.3.8
9
+ - 2.4.5
6
10
  - 2.5.3
7
- before_install: gem install bundler -v 1.16.6
11
+ - 2.6.0
12
+ - ruby-head
13
+
14
+ cache: bundler
15
+
16
+ before_script:
17
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
18
+ - chmod +x ./cc-test-reporter
19
+ - ./cc-test-reporter before-build
20
+
21
+ script: bundle exec rspec
22
+
23
+ after_script:
24
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
25
+
26
+ notifications:
27
+ email: false
28
+
29
+ sudo: false
30
+
31
+ git:
32
+ depth: 10
33
+
34
+ matrix:
35
+ allow_failures:
36
+ - rvm: ruby-head
@@ -0,0 +1,9 @@
1
+ ## Unreleased
2
+
3
+ ## 0.1.6 (2018-12-29)
4
+ * Support allOf definition (#11)
5
+ * Support wildcard status code (#12)
6
+ * Support wildcard content type (#13)
7
+
8
+ ## 0.1.5 (2018-12-23)
9
+ * First release for production usage
data/README.md CHANGED
@@ -1,8 +1,41 @@
1
1
  # OpenAPI Parser
2
+ [![Build Status](https://travis-ci.org/ota42y/openapi_parser.svg?branch=master)](https://travis-ci.org/ota42y/openapi_parser)
3
+ [![Gem Version](https://badge.fury.io/rb/openapi_parser.svg)](https://badge.fury.io/rb/openapi_parser)
4
+ [![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/openapi_parser)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/62bad4bcb3f691d46487/maintainability)](https://codeclimate.com/github/ota42y/openapi_parser/maintainability)
6
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/62bad4bcb3f691d46487/test_coverage)](https://codeclimate.com/github/ota42y/openapi_parser/test_coverage)
7
+ [![Inch CI](https://inch-ci.org/github/ota42y/openapi_parser.svg?branch=master)](https://inch-ci.org/github/ota42y/openapi_parser)
2
8
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/openapi_parser`. To experiment with that code, run `bin/console` for an interactive prompt.
9
+ This is OpenAPI3 parser and validator.
4
10
 
5
- TODO: Delete this and the text above, and describe your gem
11
+ ## Usage
12
+
13
+ ```ruby
14
+ root = OpenAPIParser.parse(YAML.load_file('open_api_3/schema.yml'))
15
+
16
+ # request operation combine path parameters and OpenAPI3's Operation Object
17
+ request_operation = root.request_operation(:post, '/validate')
18
+
19
+ ret = request_operation.validate_request_body('application/json', {"integer" => 1})
20
+ # => {"integer" => 1}
21
+
22
+ # invalid parameter
23
+ request_operation.validate_request_body('application/json', {"integer" => '1'})
24
+ # => OpenAPIParser::ValidateError: 1 class is String but it's not valid integer in #/paths/~1validate/post/requestBody/content/application~1json/schema/properties/integer
25
+
26
+ # path parameter
27
+ request_operation = root.request_operation(:get, '/path_template_test/1')
28
+ request_operation.path_params
29
+ # => {"template_name"=>"1"}
30
+
31
+ # coerce parameter
32
+ root = OpenAPIParser.parse(YAML.load_file('open_api_3/schema.yml'), {coerce_value: true, datetime_coerce_class: DateTime})
33
+ request_operation = root.request_operation(:get, '/string_params_coercer')
34
+ request_operation.validate_request_parameter({'integer_1' => '1', 'datetime_string' => '2016-04-01T16:00:00+09:00'})
35
+ # => {"integer_1"=>1, "datetime_string"=>#<DateTime: 2016-04-01T16:00:00+09:00 ((2457480j,25200s,0n),+32400s,2299161j)>
36
+ # convert number string to Integer and datetime string to DateTime class
37
+
38
+ ```
6
39
 
7
40
  ## Installation
8
41
 
@@ -20,9 +53,9 @@ Or install it yourself as:
20
53
 
21
54
  $ gem install openapi_parser
22
55
 
23
- ## Usage
24
-
25
- TODO: Write usage instructions here
56
+ ## ToDo
57
+ - correct schema checker
58
+ - more detailed validator
26
59
 
27
60
  ## Development
28
61
 
@@ -32,7 +65,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
65
 
33
66
  ## Contributing
34
67
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/openapi_parser. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
68
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ota42y/openapi_parser. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
69
 
37
70
  ## License
38
71
 
@@ -1,3 +1,4 @@
1
- require_relative 'concerns/parseable'
1
+ require_relative 'concerns/parser'
2
2
  require_relative 'concerns/findable'
3
3
  require_relative 'concerns/expandable'
4
+ require_relative 'concerns/media_type_selectable'
@@ -1,25 +1,30 @@
1
1
  module OpenAPIParser::Expandable
2
+ # expand refs
3
+ # @param [OpenAPIParser::Schemas::Base] root
4
+ # @return nil
2
5
  def expand_reference(root)
3
- expand_list_objects(root, self.class._openapi_attr_list_objects&.keys)
4
- expand_objects(root, self.class._openapi_attr_objects&.keys)
5
- expand_hash_objects(root, self.class._openapi_attr_hash_objects&.keys)
6
- expand_hash_objects(root, self.class._openapi_attr_hash_body_objects&.keys)
6
+ expand_list_objects(root, self.class._openapi_attr_list_objects.keys)
7
+ expand_objects(root, self.class._openapi_attr_objects.keys)
8
+ expand_hash_objects(root, self.class._openapi_attr_hash_objects.keys)
9
+ expand_hash_objects(root, self.class._openapi_attr_hash_body_objects.keys)
10
+ nil
7
11
  end
8
12
 
9
13
  private
10
14
 
11
- def expand_hash_objects(root, attribute_names)
12
- return unless attribute_names
15
+ def expand_hash_objects(root, attribute_names)
16
+ return unless attribute_names
13
17
 
14
- attribute_names.each do |name|
18
+ attribute_names.each { |name| expand_hash_attribute(root, name) }
19
+ end
20
+
21
+ def expand_hash_attribute(root, name)
15
22
  h = send(name)
16
- next if h.nil?
23
+ return if h.nil?
17
24
 
18
25
  update_values = h.map do |k, v|
19
- next [k, referenced_object(root, v)] if v.is_a?(OpenAPIParser::Schemas::Reference)
20
- v.expand_reference(root) if v.is_a?(OpenAPIParser::Expandable)
21
-
22
- nil
26
+ new_object = expand_object(root, v)
27
+ new_object.nil? ? nil : [k, new_object]
23
28
  end
24
29
 
25
30
  update_values.compact.each do |k, v|
@@ -27,50 +32,53 @@ module OpenAPIParser::Expandable
27
32
  h[k] = v
28
33
  end
29
34
  end
30
- end
31
35
 
32
- def expand_objects(root, attribute_names)
33
- return unless attribute_names
36
+ def expand_objects(root, attribute_names)
37
+ return unless attribute_names
34
38
 
35
- attribute_names.each do |name|
36
- v = send(name)
37
- next if v.nil?
39
+ attribute_names.each do |name|
40
+ v = send(name)
41
+ next if v.nil?
38
42
 
39
- if v.is_a?(OpenAPIParser::Schemas::Reference)
40
- obj = referenced_object(root, v)
41
- _update_child_object(v, obj)
42
- self.instance_variable_set("@#{name}", obj)
43
- elsif v.is_a?(OpenAPIParser::Expandable)
44
- v.expand_reference(root)
43
+ new_object = expand_object(root, v)
44
+ next if new_object.nil?
45
+
46
+ _update_child_object(v, new_object)
47
+ self.instance_variable_set("@#{name}", new_object)
45
48
  end
46
49
  end
47
- end
48
50
 
49
- def expand_list_objects(root, attribute_names)
50
- return unless attribute_names
51
+ def expand_list_objects(root, attribute_names)
52
+ return unless attribute_names
53
+
54
+ attribute_names.each do |name|
55
+ l = send(name)
56
+ next if l.nil?
51
57
 
52
- attribute_names.each do |name|
53
- l = send(name)
54
- next if l.nil?
58
+ l.each_with_index do |v, idx|
59
+ new_object = expand_object(root, v)
60
+ next if new_object.nil?
55
61
 
56
- l.each_with_index do |v, idx|
57
- if v.is_a?(OpenAPIParser::Schemas::Reference)
58
- obj = referenced_object(root, v)
59
- _update_child_object(v, obj)
60
- l[idx] = obj
61
- elsif v.is_a?(OpenAPIParser::Expandable)
62
- v.expand_reference(root)
62
+ _update_child_object(v, new_object)
63
+ l[idx] = new_object
63
64
  end
64
65
  end
65
66
  end
66
- end
67
67
 
68
+ def expand_object(root, object)
69
+ if object.kind_of?(OpenAPIParser::Schemas::Reference)
70
+ return referenced_object(root, object)
71
+ end
72
+
73
+ object.expand_reference(root) if object.kind_of?(OpenAPIParser::Expandable)
74
+ nil
75
+ end
68
76
 
69
- # @param [OpenAPIParser::Schemas::OpenAPI] root
70
- # @param [OpenAPIParser::Schemas::Reference] reference
71
- def referenced_object(root, reference)
72
- obj = root.find_object(reference.ref)
77
+ # @param [OpenAPIParser::Schemas::OpenAPI] root
78
+ # @param [OpenAPIParser::Schemas::Reference] reference
79
+ def referenced_object(root, reference)
80
+ obj = root.find_object(reference.ref)
73
81
 
74
- obj.is_a?(OpenAPIParser::Schemas::Reference) ? referenced_object(root, obj) : obj
75
- end
82
+ obj.kind_of?(OpenAPIParser::Schemas::Reference) ? referenced_object(root, obj) : obj
83
+ end
76
84
  end
@@ -0,0 +1,26 @@
1
+ module OpenAPIParser::MediaTypeSelectable
2
+ # select media type by content_type (consider wild card definition)
3
+ # @param [String] content_type
4
+ # @param [Hash{String => OpenAPIParser::Schemas::MediaType}] content
5
+ # @return [OpenAPIParser::Schemas::MediaType, nil]
6
+ def select_media_type(content_type, content)
7
+ return nil unless content_type
8
+
9
+ if (media_type = content[content_type])
10
+ return media_type
11
+ end
12
+
13
+ # application/json => [application, json]
14
+ splited = content_type.split('/')
15
+
16
+ if (media_type = content["#{splited.first}/*"])
17
+ return media_type
18
+ end
19
+
20
+ if (media_type = content['*/*'])
21
+ return media_type
22
+ end
23
+
24
+ nil
25
+ end
26
+ end
@@ -0,0 +1,43 @@
1
+ module OpenAPIParser::Parser
2
+ end
3
+
4
+ require_relative './parser/core'
5
+ require_relative './schema_loader'
6
+
7
+ module OpenAPIParser::Parser
8
+ def self.included(base)
9
+ base.extend(ClassMethods)
10
+ end
11
+ module ClassMethods
12
+ extend Forwardable
13
+
14
+ def_delegators :_parser_core, :_openapi_attr_values, :openapi_attr_value, :openapi_attr_values
15
+ def_delegators :_parser_core, :_openapi_attr_objects, :openapi_attr_objects, :openapi_attr_object
16
+ def_delegators :_parser_core, :_openapi_attr_list_objects, :openapi_attr_list_object
17
+ def_delegators :_parser_core, :_openapi_attr_hash_objects, :openapi_attr_hash_object
18
+ def_delegators :_parser_core, :_openapi_attr_hash_body_objects, :openapi_attr_hash_body_objects
19
+
20
+ def _parser_core
21
+ @_parser_core ||= OpenAPIParser::Parser::Core.new(self)
22
+ end
23
+ end
24
+
25
+ # @param [OpenAPIParser::Schemas::Base] old
26
+ # @param [OpenAPIParser::Schemas::Base] new
27
+ def _update_child_object(old, new)
28
+ _openapi_all_child_objects[old.object_reference] = new
29
+ end
30
+
31
+ # @return [Hash{String => OpenAPIParser::Schemas::Base}]
32
+ def _openapi_all_child_objects
33
+ @_openapi_all_child_objects ||= {}
34
+ end
35
+
36
+ # load data by schema definition in core and set children to _openapi_all_child_objects
37
+ # @return nil
38
+ def load_data
39
+ loader = ::OpenAPIParser::SchemaLoader.new(self, self.class._parser_core)
40
+ @_openapi_all_child_objects = loader.load_data
41
+ nil
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ require_relative './value'
2
+ require_relative './object'
3
+ require_relative './list'
4
+ require_relative './hash'
5
+ require_relative './hash_body'
6
+
7
+ class OpenAPIParser::Parser::Core
8
+ include OpenAPIParser::Parser::Value
9
+ include OpenAPIParser::Parser::Object
10
+ include OpenAPIParser::Parser::List
11
+ include OpenAPIParser::Parser::Hash
12
+ include OpenAPIParser::Parser::HashBody
13
+
14
+ def initialize(target_klass)
15
+ @target_klass = target_klass
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :target_klass
21
+ end
@@ -0,0 +1,10 @@
1
+ module OpenAPIParser::Parser::Hash
2
+ def _openapi_attr_hash_objects
3
+ @_openapi_attr_hash_objects ||= {}
4
+ end
5
+
6
+ def openapi_attr_hash_object(name, klass, options = {})
7
+ target_klass.send(:attr_reader, name)
8
+ _openapi_attr_hash_objects[name] = ::OpenAPIParser::SchemaLoader::HashObjectsLoader.new(name, options.merge(klass: klass))
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module OpenAPIParser::Parser::HashBody
2
+ def _openapi_attr_hash_body_objects
3
+ @_openapi_attr_hash_body_objects ||= {}
4
+ end
5
+
6
+ def openapi_attr_hash_body_objects(name, klass, options = {})
7
+ #options[:reject_keys] = options[:reject_keys] ? options[:reject_keys].map(&:to_s) : []
8
+
9
+ target_klass.send(:attr_reader, name)
10
+ _openapi_attr_hash_body_objects[name] = ::OpenAPIParser::SchemaLoader::HashBodyLoader.new(name, options.merge(klass: klass))
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module OpenAPIParser::Parser::List
2
+ def _openapi_attr_list_objects
3
+ @_openapi_attr_list_objects ||= {}
4
+ end
5
+
6
+ def openapi_attr_list_object(name, klass, options = {})
7
+ target_klass.send(:attr_reader, name)
8
+ _openapi_attr_list_objects[name] = OpenAPIParser::SchemaLoader::ListLoader.new(name, options.merge(klass: klass))
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ module OpenAPIParser::Parser::Object
2
+ def _openapi_attr_objects
3
+ @_openapi_attr_objects ||= {}
4
+ end
5
+
6
+ def openapi_attr_objects(*names, klass)
7
+ names.each { |name| openapi_attr_object(name, klass) }
8
+ end
9
+
10
+ def openapi_attr_object(name, klass, options = {})
11
+ target_klass.send(:attr_reader, name)
12
+ _openapi_attr_objects[name] = OpenAPIParser::SchemaLoader::ObjectsLoader.new(name, options.merge(klass: klass))
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module OpenAPIParser::Parser::Value
2
+ def _openapi_attr_values
3
+ @_openapi_attr_values ||= {}
4
+ end
5
+
6
+ def openapi_attr_values(*names)
7
+ names.each { |name| openapi_attr_value(name) }
8
+ end
9
+
10
+ def openapi_attr_value(name, options = {})
11
+ target_klass.send(:attr_reader, name)
12
+ _openapi_attr_values[name] = OpenAPIParser::SchemaLoader::ValuesLoader.new(name, options)
13
+ end
14
+ end