dry-swagger 0.3.0 → 0.5.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.
- checksums.yaml +4 -4
 - data/Gemfile.lock +1 -1
 - data/README.md +71 -14
 - data/lib/dry/swagger.rb +6 -16
 - data/lib/dry/swagger/config/configuration.rb +32 -0
 - data/lib/dry/swagger/config/contract_configuration.rb +15 -0
 - data/lib/dry/swagger/config/struct_configuration.rb +15 -0
 - data/lib/dry/swagger/contract_parser.rb +10 -45
 - data/lib/dry/swagger/documentation_generator.rb +86 -0
 - data/lib/dry/swagger/errors/missing_hash_schema_error.rb +15 -0
 - data/lib/dry/swagger/errors/missing_type_error.rb +15 -0
 - data/lib/dry/swagger/struct_parser.rb +119 -56
 - data/lib/dry/swagger/version.rb +1 -1
 - metadata +8 -3
 - data/lib/helpers/configuration.rb +0 -27
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 5179183ed4122bcf5042f8aa812b6830b1126ae00d4eb2975bd17203af2bf375
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 9eb614eaaaca4752a39f9a77ef2fac3dffb4df2179a0c7e7f427d13f9f02333e
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 58dea258473d5fea4c521d699a2332ec8a444d15504b81ff3eefba0ef50c08371fe5d9b3fd7e2d3331613375f625bdb3ea54073dde31cfc20eafdc0d29e49202
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 2ec6862a8021cb836101cac89b394482507a6b48021cfbf304b63c8753fe0bcefb822730a194ae869da6c83dc34e965af771a58b6052dc729cea0d528a97b6a4
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -33,7 +33,7 @@ Or install it yourself as: 
     | 
|
| 
       33 
33 
     | 
    
         
             
                    end
         
     | 
| 
       34 
34 
     | 
    
         
             
                end
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                Dry::Swagger::ContractParser.new.call(Contract)
         
     | 
| 
      
 36 
     | 
    
         
            +
                Dry::Swagger::ContractParser.new.call(Contract).to_swagger
         
     | 
| 
       37 
37 
     | 
    
         
             
                => {
         
     | 
| 
       38 
38 
     | 
    
         
             
                     "type": "object",
         
     | 
| 
       39 
39 
     | 
    
         
             
                     "properties": {
         
     | 
| 
         @@ -81,7 +81,7 @@ Or install it yourself as: 
     | 
|
| 
       81 
81 
     | 
    
         
             
                  end
         
     | 
| 
       82 
82 
     | 
    
         
             
                end
         
     | 
| 
       83 
83 
     | 
    
         | 
| 
       84 
     | 
    
         
            -
                Dry::Swagger::ContractParser.new.call(Contract)
         
     | 
| 
      
 84 
     | 
    
         
            +
                Dry::Swagger::ContractParser.new.call(Contract).to_swagger
         
     | 
| 
       85 
85 
     | 
    
         
             
                => {
         
     | 
| 
       86 
86 
     | 
    
         
             
                     "type": "object",
         
     | 
| 
       87 
87 
     | 
    
         
             
                     "properties": {
         
     | 
| 
         @@ -135,7 +135,7 @@ Or install it yourself as: 
     | 
|
| 
       135 
135 
     | 
    
         
             
                  attribute? :optional_nullable_string, Types::String.optional
         
     | 
| 
       136 
136 
     | 
    
         
             
                end
         
     | 
| 
       137 
137 
     | 
    
         | 
| 
       138 
     | 
    
         
            -
                Dry::Swagger::StructParser.new.call(DTO)
         
     | 
| 
      
 138 
     | 
    
         
            +
                Dry::Swagger::StructParser.new.call(DTO).to_swagger
         
     | 
| 
       139 
139 
     | 
    
         
             
                => {
         
     | 
| 
       140 
140 
     | 
    
         
             
                     "type": "object",
         
     | 
| 
       141 
141 
     | 
    
         
             
                     "properties": {
         
     | 
| 
         @@ -170,7 +170,22 @@ Or install it yourself as: 
     | 
|
| 
       170 
170 
     | 
    
         
             
                     ]
         
     | 
| 
       171 
171 
     | 
    
         
             
                   }
         
     | 
| 
       172 
172 
     | 
    
         
             
            #### With nested fields
         
     | 
| 
       173 
     | 
    
         
            -
                 
     | 
| 
      
 173 
     | 
    
         
            +
                class NestedDTO < Dry::Struct
         
     | 
| 
      
 174 
     | 
    
         
            +
                  attribute  :required_string, Types::String
         
     | 
| 
      
 175 
     | 
    
         
            +
                  attribute  :required_nullable_string, Types::String.optional
         
     | 
| 
      
 176 
     | 
    
         
            +
                  attribute  :required_string_with_enum, Types::String.enum('enum1')
         
     | 
| 
      
 177 
     | 
    
         
            +
                  attribute? :optional_string, Types::String
         
     | 
| 
      
 178 
     | 
    
         
            +
                  attribute? :optional_nullable_string, Types::String.optional
         
     | 
| 
      
 179 
     | 
    
         
            +
                end
         
     | 
| 
      
 180 
     | 
    
         
            +
                
         
     | 
| 
      
 181 
     | 
    
         
            +
                class DTO < Dry::Struct
         
     | 
| 
      
 182 
     | 
    
         
            +
                  attribute  :array_of_integer, Types::Array.of(Types::Integer)
         
     | 
| 
      
 183 
     | 
    
         
            +
                  attribute  :array_of_objects, Types::Array.of(NestedDTO)
         
     | 
| 
      
 184 
     | 
    
         
            +
                  attribute  :dto, NestedDTO
         
     | 
| 
      
 185 
     | 
    
         
            +
                end
         
     | 
| 
      
 186 
     | 
    
         
            +
                
         
     | 
| 
      
 187 
     | 
    
         
            +
                Dry::Swagger::StructParser.new.call(DTO).to_swagger
         
     | 
| 
      
 188 
     | 
    
         
            +
                => {
         
     | 
| 
       174 
189 
     | 
    
         
             
                  "type": "object",
         
     | 
| 
       175 
190 
     | 
    
         
             
                  "properties": {
         
     | 
| 
       176 
191 
     | 
    
         
             
                    "array_of_integer": {
         
     | 
| 
         @@ -258,21 +273,63 @@ Or install it yourself as: 
     | 
|
| 
       258 
273 
     | 
    
         
             
                    "dto"
         
     | 
| 
       259 
274 
     | 
    
         
             
                  ]
         
     | 
| 
       260 
275 
     | 
    
         
             
                }
         
     | 
| 
      
 276 
     | 
    
         
            +
            ## Overriding fields on run time
         
     | 
| 
      
 277 
     | 
    
         
            +
            You can also modify the fields during runtime by passing a block after the .call() method.
         
     | 
| 
      
 278 
     | 
    
         
            +
             
     | 
| 
      
 279 
     | 
    
         
            +
            For example:
         
     | 
| 
      
 280 
     | 
    
         
            +
                
         
     | 
| 
      
 281 
     | 
    
         
            +
                Dry::Swagger::StructParser.new.call(DTO) do |it|
         
     | 
| 
      
 282 
     | 
    
         
            +
                  # types = string/integer/hash/array
         
     | 
| 
      
 283 
     | 
    
         
            +
                  
         
     | 
| 
      
 284 
     | 
    
         
            +
                  # Remove a field
         
     | 
| 
      
 285 
     | 
    
         
            +
                  its.keys = it.keys.except(:field_name) 
         
     | 
| 
      
 286 
     | 
    
         
            +
                  
         
     | 
| 
      
 287 
     | 
    
         
            +
                  # Add new field on root level
         
     | 
| 
      
 288 
     | 
    
         
            +
                  it.keys[:new_field_name] = { type: type, required: true/false, :it.config.nullable_type=>true/false } 
         
     | 
| 
      
 289 
     | 
    
         
            +
                  
         
     | 
| 
      
 290 
     | 
    
         
            +
                  # Add a new field in nested hash/array
         
     | 
| 
      
 291 
     | 
    
         
            +
                  it.keys[:nested_field][:keys][:new_field_name] = { 
         
     | 
| 
      
 292 
     | 
    
         
            +
                    type: type, required: true/false, :it.config.nullable_type=>true/false
         
     | 
| 
      
 293 
     | 
    
         
            +
                  }
         
     | 
| 
      
 294 
     | 
    
         
            +
                  
         
     | 
| 
      
 295 
     | 
    
         
            +
                  # Remove a field in nested hash/array
         
     | 
| 
      
 296 
     | 
    
         
            +
                  it.keys = it.keys[:nested_field][:keys].except(:field_name)
         
     | 
| 
      
 297 
     | 
    
         
            +
                  
         
     | 
| 
      
 298 
     | 
    
         
            +
                  # Add an array or hash
         
     | 
| 
      
 299 
     | 
    
         
            +
                  it.keys[:nested_field] = { 
         
     | 
| 
      
 300 
     | 
    
         
            +
                    type: "array/hash", required: true/false, :it.config.nullable_type=> true/false, keys: {
         
     | 
| 
      
 301 
     | 
    
         
            +
                      # List all nested fields
         
     | 
| 
      
 302 
     | 
    
         
            +
                      new_field: { type: :type, required: true/false, :it.config.nullable_type=>true/false }
         
     | 
| 
      
 303 
     | 
    
         
            +
                    }
         
     | 
| 
      
 304 
     | 
    
         
            +
                  }
         
     | 
| 
      
 305 
     | 
    
         
            +
                  
         
     | 
| 
      
 306 
     | 
    
         
            +
                  # Add an Array of primitive types, type field needs to be the element type(string, integer, float), 
         
     | 
| 
      
 307 
     | 
    
         
            +
                  and add an array: true flag
         
     | 
| 
      
 308 
     | 
    
         
            +
                  
         
     | 
| 
      
 309 
     | 
    
         
            +
                  it.keys[:array_field_name] = { 
         
     | 
| 
      
 310 
     | 
    
         
            +
                    type: type, array: true, required: true/false, :it.config.nullable_type=> true/false 
         
     | 
| 
      
 311 
     | 
    
         
            +
                  }
         
     | 
| 
      
 312 
     | 
    
         
            +
                  
         
     | 
| 
      
 313 
     | 
    
         
            +
                end.to_swagger()
         
     | 
| 
       261 
314 
     | 
    
         
             
            ## Custom Configuration For Your Project
         
     | 
| 
       262 
315 
     | 
    
         
             
            You can override default configurations by creating a file in config/initializers/dry-swagger.rb and changing the following values.
         
     | 
| 
       263 
316 
     | 
    
         | 
| 
       264 
     | 
    
         
            -
                Dry::Swagger.configuration do |config|
         
     | 
| 
       265 
     | 
    
         
            -
                  config. 
     | 
| 
       266 
     | 
    
         
            -
                  config. 
     | 
| 
       267 
     | 
    
         
            -
                  config. 
     | 
| 
       268 
     | 
    
         
            -
                  config. 
     | 
| 
       269 
     | 
    
         
            -
                  
         
     | 
| 
       270 
     | 
    
         
            -
             
     | 
| 
       271 
     | 
    
         
            -
             
     | 
| 
       272 
     | 
    
         
            -
             
     | 
| 
       273 
     | 
    
         
            -
                  config. 
     | 
| 
      
 317 
     | 
    
         
            +
                Dry::Swagger::Config::StructConfiguration.configuration do |config|
         
     | 
| 
      
 318 
     | 
    
         
            +
                  config.enable_required_validation = true / false       
         
     | 
| 
      
 319 
     | 
    
         
            +
                  config.enable_nullable_validation = true / false
         
     | 
| 
      
 320 
     | 
    
         
            +
                  config.enable_enums = true / false
         
     | 
| 
      
 321 
     | 
    
         
            +
                  config.enable_descriptions = true / false
         
     | 
| 
      
 322 
     | 
    
         
            +
                  config.nullable_type = :"x-nullable" / :nullable
         
     | 
| 
      
 323 
     | 
    
         
            +
                end
         
     | 
| 
      
 324 
     | 
    
         
            +
                
         
     | 
| 
      
 325 
     | 
    
         
            +
                Dry::Swagger::Config::ContractConfiguration.configuration do |config|
         
     | 
| 
      
 326 
     | 
    
         
            +
                  config.enable_required_validation = true / false       
         
     | 
| 
      
 327 
     | 
    
         
            +
                  config.enable_nullable_validation = true / false
         
     | 
| 
      
 328 
     | 
    
         
            +
                  config.enable_enums = true / false
         
     | 
| 
      
 329 
     | 
    
         
            +
                  config.enable_descriptions = true / false
         
     | 
| 
       274 
330 
     | 
    
         
             
                  config.nullable_type = :"x-nullable" / :nullable
         
     | 
| 
       275 
331 
     | 
    
         
             
                end
         
     | 
| 
      
 332 
     | 
    
         
            +
                    
         
     | 
| 
       276 
333 
     | 
    
         
             
            By default, all these settings are true, and nullable_type is :"x-nullable".
         
     | 
| 
       277 
334 
     | 
    
         
             
            ## Development
         
     | 
| 
       278 
335 
     | 
    
         | 
    
        data/lib/dry/swagger.rb
    CHANGED
    
    | 
         @@ -1,24 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "dry/swagger/version"
         
     | 
| 
       2 
2 
     | 
    
         
             
            require "dry/swagger/contract_parser"
         
     | 
| 
       3 
3 
     | 
    
         
             
            require "dry/swagger/struct_parser"
         
     | 
| 
       4 
     | 
    
         
            -
            require ' 
     | 
| 
      
 4 
     | 
    
         
            +
            require 'dry/swagger/documentation_generator'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'dry/swagger/errors/missing_hash_schema_error'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'dry/swagger/errors/missing_type_error'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'dry/swagger/config/configuration'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'dry/swagger/config/contract_configuration'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'dry/swagger/config/struct_configuration'
         
     | 
| 
       5 
10 
     | 
    
         | 
| 
       6 
11 
     | 
    
         
             
            module Dry
         
     | 
| 
       7 
12 
     | 
    
         
             
              module Swagger
         
     | 
| 
       8 
     | 
    
         
            -
                class Error < StandardError; end
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                extend Configuration
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                define_setting :struct_enable_required_validation, true
         
     | 
| 
       13 
     | 
    
         
            -
                define_setting :struct_enable_nullable_validation, true
         
     | 
| 
       14 
     | 
    
         
            -
                define_setting :struct_enable_enums, true
         
     | 
| 
       15 
     | 
    
         
            -
                define_setting :struct_enable_descriptions, true
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                define_setting :contract_enable_required_validation, true
         
     | 
| 
       18 
     | 
    
         
            -
                define_setting :contract_enable_nullable_validation, true
         
     | 
| 
       19 
     | 
    
         
            -
                define_setting :contract_enable_enums, true
         
     | 
| 
       20 
     | 
    
         
            -
                define_setting :contract_enable_descriptions, true
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                define_setting :nullable_type, :"x-nullable"
         
     | 
| 
       23 
13 
     | 
    
         
             
              end
         
     | 
| 
       24 
14 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Swagger
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Config
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module Configuration
         
     | 
| 
      
 5 
     | 
    
         
            +
                    def configuration
         
     | 
| 
      
 6 
     | 
    
         
            +
                      yield self
         
     | 
| 
      
 7 
     | 
    
         
            +
                    end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def define_setting(name, default = nil)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      class_variable_set("@@#{name}", default)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                      define_class_method "#{name}=" do |value|
         
     | 
| 
      
 13 
     | 
    
         
            +
                        class_variable_set("@@#{name}", value)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                      define_class_method name do
         
     | 
| 
      
 17 
     | 
    
         
            +
                        class_variable_get("@@#{name}")
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    private
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    def define_class_method(name, &block)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      (class << self; self; end).instance_eval do
         
     | 
| 
      
 25 
     | 
    
         
            +
                        define_method name, &block
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Swagger
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Config
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module ContractConfiguration
         
     | 
| 
      
 5 
     | 
    
         
            +
                    extend Configuration
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    define_setting :enable_required_validation, true
         
     | 
| 
      
 8 
     | 
    
         
            +
                    define_setting :enable_nullable_validation, true
         
     | 
| 
      
 9 
     | 
    
         
            +
                    define_setting :enable_enums, true
         
     | 
| 
      
 10 
     | 
    
         
            +
                    define_setting :enable_descriptions, true
         
     | 
| 
      
 11 
     | 
    
         
            +
                    define_setting :nullable_type, :"x-nullable"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Swagger
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Config
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module StructConfiguration
         
     | 
| 
      
 5 
     | 
    
         
            +
                    extend Configuration
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    define_setting :enable_required_validation, true
         
     | 
| 
      
 8 
     | 
    
         
            +
                    define_setting :enable_nullable_validation, true
         
     | 
| 
      
 9 
     | 
    
         
            +
                    define_setting :enable_enums, true
         
     | 
| 
      
 10 
     | 
    
         
            +
                    define_setting :enable_descriptions, true
         
     | 
| 
      
 11 
     | 
    
         
            +
                    define_setting :nullable_type, :"x-nullable"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -15,22 +15,13 @@ module Dry 
     | 
|
| 
       15 
15 
     | 
    
         
             
                      time?: 'time'
         
     | 
| 
       16 
16 
     | 
    
         
             
                  }.freeze
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                  SWAGGER_FIELD_TYPE_DEFINITIONS = {
         
     | 
| 
       19 
     | 
    
         
            -
                      "string" => { type: :string },
         
     | 
| 
       20 
     | 
    
         
            -
                      "integer" => { type: :integer },
         
     | 
| 
       21 
     | 
    
         
            -
                      "boolean" => { type: :boolean },
         
     | 
| 
       22 
     | 
    
         
            -
                      "float" => { type: :float },
         
     | 
| 
       23 
     | 
    
         
            -
                      "datetime" => { type: :string, format: :datetime },
         
     | 
| 
       24 
     | 
    
         
            -
                      "date" => { type: :string, format: :date },
         
     | 
| 
       25 
     | 
    
         
            -
                      "time" => { type: :string, format: :time },
         
     | 
| 
       26 
     | 
    
         
            -
                  }.freeze
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
18 
     | 
    
         
             
                  # @api private
         
     | 
| 
       29 
19 
     | 
    
         
             
                  attr_reader :keys
         
     | 
| 
       30 
20 
     | 
    
         | 
| 
       31 
21 
     | 
    
         
             
                  # @api private
         
     | 
| 
       32 
22 
     | 
    
         
             
                  def initialize
         
     | 
| 
       33 
23 
     | 
    
         
             
                    @keys = {}
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @config = Config::ContractConfiguration
         
     | 
| 
       34 
25 
     | 
    
         
             
                  end
         
     | 
| 
       35 
26 
     | 
    
         | 
| 
       36 
27 
     | 
    
         
             
                  # @api private
         
     | 
| 
         @@ -43,7 +34,7 @@ module Dry 
     | 
|
| 
       43 
34 
     | 
    
         
             
                    @keys = {}
         
     | 
| 
       44 
35 
     | 
    
         
             
                    visit(contract.schema.to_ast)
         
     | 
| 
       45 
36 
     | 
    
         
             
                    instance_eval(&block) if block_given?
         
     | 
| 
       46 
     | 
    
         
            -
                     
     | 
| 
      
 37 
     | 
    
         
            +
                    self
         
     | 
| 
       47 
38 
     | 
    
         
             
                  end
         
     | 
| 
       48 
39 
     | 
    
         | 
| 
       49 
40 
     | 
    
         
             
                  # @api private
         
     | 
| 
         @@ -75,14 +66,13 @@ module Dry 
     | 
|
| 
       75 
66 
     | 
    
         
             
                  end
         
     | 
| 
       76 
67 
     | 
    
         | 
| 
       77 
68 
     | 
    
         
             
                  def visit_not(_node, opts = {})
         
     | 
| 
       78 
     | 
    
         
            -
                     
     | 
| 
       79 
     | 
    
         
            -
                    keys[key][::Dry::Swagger.nullable_type] = true if ::Dry::Swagger.contract_enable_nullable_validation
         
     | 
| 
      
 69 
     | 
    
         
            +
                    keys[opts[:key]][@config.nullable_type] = true
         
     | 
| 
       80 
70 
     | 
    
         
             
                  end
         
     | 
| 
       81 
71 
     | 
    
         | 
| 
       82 
72 
     | 
    
         
             
                  # @api private
         
     | 
| 
       83 
73 
     | 
    
         
             
                  def visit_implication(node, opts = {})
         
     | 
| 
       84 
74 
     | 
    
         
             
                    node.each do |el|
         
     | 
| 
       85 
     | 
    
         
            -
                      opts = opts.merge(required: false) 
     | 
| 
      
 75 
     | 
    
         
            +
                      opts = opts.merge(required: false)
         
     | 
| 
       86 
76 
     | 
    
         
             
                      visit(el, opts)
         
     | 
| 
       87 
77 
     | 
    
         
             
                    end
         
     | 
| 
       88 
78 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -96,7 +86,7 @@ module Dry 
     | 
|
| 
       96 
86 
     | 
    
         
             
                  def visit_key(node, opts = {})
         
     | 
| 
       97 
87 
     | 
    
         
             
                    name, rest = node
         
     | 
| 
       98 
88 
     | 
    
         
             
                    opts = opts.merge(key: name)
         
     | 
| 
       99 
     | 
    
         
            -
                    opts = opts.merge(required: true) 
     | 
| 
      
 89 
     | 
    
         
            +
                    opts = opts.merge(required: true)
         
     | 
| 
       100 
90 
     | 
    
         
             
                    visit(rest, opts)
         
     | 
| 
       101 
91 
     | 
    
         
             
                  end
         
     | 
| 
       102 
92 
     | 
    
         | 
| 
         @@ -107,11 +97,13 @@ module Dry 
     | 
|
| 
       107 
97 
     | 
    
         
             
                    key = opts[:key]
         
     | 
| 
       108 
98 
     | 
    
         | 
| 
       109 
99 
     | 
    
         
             
                    if name.equal?(:key?)
         
     | 
| 
       110 
     | 
    
         
            -
                      keys[rest[0][1]] = { required: opts.fetch(:required, true) } 
     | 
| 
      
 100 
     | 
    
         
            +
                      keys[rest[0][1]] = { required: opts.fetch(:required, true) }
         
     | 
| 
       111 
101 
     | 
    
         
             
                    elsif name.equal?(:array?)
         
     | 
| 
       112 
102 
     | 
    
         
             
                      keys[key][:array] = true
         
     | 
| 
       113 
103 
     | 
    
         
             
                    elsif name.equal?(:included_in?)
         
     | 
| 
       114 
     | 
    
         
            -
                       
     | 
| 
      
 104 
     | 
    
         
            +
                      enums = rest[0][1]
         
     | 
| 
      
 105 
     | 
    
         
            +
                      enums += [nil] if opts.fetch(@config.nullable_type, false)
         
     | 
| 
      
 106 
     | 
    
         
            +
                      keys[key][:enum] = enums
         
     | 
| 
       115 
107 
     | 
    
         
             
                    elsif PREDICATE_TO_TYPE[name]
         
     | 
| 
       116 
108 
     | 
    
         
             
                      keys[key][:type] = PREDICATE_TO_TYPE[name]
         
     | 
| 
       117 
109 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -139,34 +131,7 @@ module Dry 
     | 
|
| 
       139 
131 
     | 
    
         
             
                  end
         
     | 
| 
       140 
132 
     | 
    
         | 
| 
       141 
133 
     | 
    
         
             
                  def to_swagger
         
     | 
| 
       142 
     | 
    
         
            -
                    generate_documentation(keys)
         
     | 
| 
       143 
     | 
    
         
            -
                  end
         
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
                  private
         
     | 
| 
       146 
     | 
    
         
            -
             
     | 
| 
       147 
     | 
    
         
            -
                  def generate_documentation(fields)
         
     | 
| 
       148 
     | 
    
         
            -
                    documentation = { properties: {}, required: [] }
         
     | 
| 
       149 
     | 
    
         
            -
                    fields.each do |field_name, attributes_hash|
         
     | 
| 
       150 
     | 
    
         
            -
                      documentation[:properties][field_name] = generate_field_properties(attributes_hash)
         
     | 
| 
       151 
     | 
    
         
            -
                      documentation[:required] << field_name if ::Dry::Swagger.contract_enable_required_validation && attributes_hash[:required]
         
     | 
| 
       152 
     | 
    
         
            -
                    end
         
     | 
| 
       153 
     | 
    
         
            -
                    { :type => :object, :properties => documentation[:properties], :required => documentation[:required] }
         
     | 
| 
       154 
     | 
    
         
            -
                  end
         
     | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
       156 
     | 
    
         
            -
                  def generate_field_properties(attributes_hash)
         
     | 
| 
       157 
     | 
    
         
            -
                    if attributes_hash[:type] == 'array'
         
     | 
| 
       158 
     | 
    
         
            -
                      { type: :array, items: generate_documentation(attributes_hash[:keys]) }
         
     | 
| 
       159 
     | 
    
         
            -
                    elsif attributes_hash[:array] && attributes_hash[:type] != 'array'
         
     | 
| 
       160 
     | 
    
         
            -
                      { type: :array, items: SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(attributes_hash[:type]) }
         
     | 
| 
       161 
     | 
    
         
            -
                    elsif attributes_hash[:type] == 'hash'
         
     | 
| 
       162 
     | 
    
         
            -
                      generate_documentation(attributes_hash[:keys])
         
     | 
| 
       163 
     | 
    
         
            -
                    else
         
     | 
| 
       164 
     | 
    
         
            -
                      field = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(attributes_hash[:type])
         
     | 
| 
       165 
     | 
    
         
            -
                      field = field.merge(::Dry::Swagger.nullable_type => attributes_hash[::Dry::Swagger.nullable_type] | false) if ::Dry::Swagger.contract_enable_nullable_validation
         
     | 
| 
       166 
     | 
    
         
            -
                      field = field.merge(enum: attributes_hash[:enum]) if attributes_hash[:enum] if ::Dry::Swagger.contract_enable_enums
         
     | 
| 
       167 
     | 
    
         
            -
                      field = field.merge(description: attributes_hash[:description]) if attributes_hash[:description] if ::Dry::Swagger.contract_enable_descriptions
         
     | 
| 
       168 
     | 
    
         
            -
                      field
         
     | 
| 
       169 
     | 
    
         
            -
                    end
         
     | 
| 
      
 134 
     | 
    
         
            +
                    DocumentationGenerator.new(@config).generate_documentation(keys)
         
     | 
| 
       170 
135 
     | 
    
         
             
                  end
         
     | 
| 
       171 
136 
     | 
    
         
             
                end
         
     | 
| 
       172 
137 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Swagger
         
     | 
| 
      
 3 
     | 
    
         
            +
                class DocumentationGenerator
         
     | 
| 
      
 4 
     | 
    
         
            +
                  SWAGGER_FIELD_TYPE_DEFINITIONS = {
         
     | 
| 
      
 5 
     | 
    
         
            +
                      "string" => { type: :string },
         
     | 
| 
      
 6 
     | 
    
         
            +
                      "integer" => { type: :integer },
         
     | 
| 
      
 7 
     | 
    
         
            +
                      "boolean" => { type: :boolean },
         
     | 
| 
      
 8 
     | 
    
         
            +
                      "float" => { type: :float },
         
     | 
| 
      
 9 
     | 
    
         
            +
                      "datetime" => { type: :string, format: :datetime },
         
     | 
| 
      
 10 
     | 
    
         
            +
                      "date" => { type: :string, format: :date },
         
     | 
| 
      
 11 
     | 
    
         
            +
                      "time" => { type: :string, format: :time },
         
     | 
| 
      
 12 
     | 
    
         
            +
                  }.freeze
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def initialize(config)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @config = config
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def generate_documentation(fields)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    documentation = { properties: {}, required: [] }
         
     | 
| 
      
 20 
     | 
    
         
            +
                    fields.each do |field_name, attributes_hash|
         
     | 
| 
      
 21 
     | 
    
         
            +
                      documentation[:properties][field_name] = generate_field_properties(attributes_hash)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      if attributes_hash.is_a?(Hash)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        documentation[:required] << field_name if attributes_hash.fetch(:required, true) && @config.enable_required_validation
         
     | 
| 
      
 24 
     | 
    
         
            +
                      else
         
     | 
| 
      
 25 
     | 
    
         
            +
                        documentation[:required] << field_name if attributes_hash[0].fetch(:required, true) && @config.enable_required_validation
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    rescue Errors::MissingTypeError => e
         
     | 
| 
      
 29 
     | 
    
         
            +
                      raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys, attributes_hash: attributes_hash }
         
     | 
| 
      
 30 
     | 
    
         
            +
                    rescue Errors::MissingHashSchemaError => e
         
     | 
| 
      
 31 
     | 
    
         
            +
                      raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys, attributes_hash: attributes_hash }
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    { :type => :object, :properties => documentation[:properties], :required => documentation[:required] }
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def generate_field_properties(attributes_hash)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    if attributes_hash.is_a?(Array)
         
     | 
| 
      
 39 
     | 
    
         
            +
                      properties = {}
         
     | 
| 
      
 40 
     | 
    
         
            +
                      attributes_hash.each_with_index do |_, index|
         
     | 
| 
      
 41 
     | 
    
         
            +
                        properties["definition_#{index + 1}"] = generate_field_properties(attributes_hash[index])
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                      {
         
     | 
| 
      
 44 
     | 
    
         
            +
                          oneOf: attributes_hash.map{ |it| generate_field_properties(it) },
         
     | 
| 
      
 45 
     | 
    
         
            +
                          type: :object,
         
     | 
| 
      
 46 
     | 
    
         
            +
                          properties: properties,
         
     | 
| 
      
 47 
     | 
    
         
            +
                          example: 'Dynamic Field. See Model Definitions'
         
     | 
| 
      
 48 
     | 
    
         
            +
                      }
         
     | 
| 
      
 49 
     | 
    
         
            +
                    else
         
     | 
| 
      
 50 
     | 
    
         
            +
                      if attributes_hash[:type] == 'array'
         
     | 
| 
      
 51 
     | 
    
         
            +
                        items = generate_documentation(attributes_hash.fetch(:keys))
         
     | 
| 
      
 52 
     | 
    
         
            +
                        items =  @config.enable_nullable_validation ?
         
     | 
| 
      
 53 
     | 
    
         
            +
                                     items.merge(@config.nullable_type => attributes_hash.fetch(@config.nullable_type, false)) :
         
     | 
| 
      
 54 
     | 
    
         
            +
                                     items.merge(@config.nullable_type => true)
         
     | 
| 
      
 55 
     | 
    
         
            +
                        documentation = { type: :array, items: items }
         
     | 
| 
      
 56 
     | 
    
         
            +
                      elsif attributes_hash[:array] && attributes_hash.fetch(:type) != 'array'
         
     | 
| 
      
 57 
     | 
    
         
            +
                        items = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(attributes_hash.fetch(:type))
         
     | 
| 
      
 58 
     | 
    
         
            +
                        items = @config.enable_nullable_validation ?
         
     | 
| 
      
 59 
     | 
    
         
            +
                                    items.merge(@config.nullable_type => attributes_hash.fetch(@config.nullable_type, false)) :
         
     | 
| 
      
 60 
     | 
    
         
            +
                                    items.merge(@config.nullable_type => true)
         
     | 
| 
      
 61 
     | 
    
         
            +
                        documentation = { type: :array, items:  items }
         
     | 
| 
      
 62 
     | 
    
         
            +
                      elsif attributes_hash[:type] == 'hash'
         
     | 
| 
      
 63 
     | 
    
         
            +
                        raise Errors::MissingHashSchemaError.new unless attributes_hash[:keys]
         
     | 
| 
      
 64 
     | 
    
         
            +
                        documentation = generate_documentation(attributes_hash.fetch(:keys))
         
     | 
| 
      
 65 
     | 
    
         
            +
                      else
         
     | 
| 
      
 66 
     | 
    
         
            +
                        documentation = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(attributes_hash.fetch(:type))
         
     | 
| 
      
 67 
     | 
    
         
            +
                        if attributes_hash[:enum] && @config.enable_enums
         
     | 
| 
      
 68 
     | 
    
         
            +
                          documentation = documentation.merge(enum: attributes_hash.fetch(:enum))
         
     | 
| 
      
 69 
     | 
    
         
            +
                        end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                        if attributes_hash[:description] && @config.enable_descriptions
         
     | 
| 
      
 72 
     | 
    
         
            +
                          documentation = documentation.merge(description: attributes_hash.fetch(:description))
         
     | 
| 
      
 73 
     | 
    
         
            +
                        end
         
     | 
| 
      
 74 
     | 
    
         
            +
                      end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                      @config.enable_nullable_validation ?
         
     | 
| 
      
 77 
     | 
    
         
            +
                          documentation.merge(@config.nullable_type => attributes_hash.fetch(@config.nullable_type, false)) :
         
     | 
| 
      
 78 
     | 
    
         
            +
                          documentation.merge(@config.nullable_type => true)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  rescue KeyError
         
     | 
| 
      
 82 
     | 
    
         
            +
                    raise Errors::MissingTypeError.new
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Swagger
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Errors
         
     | 
| 
      
 4 
     | 
    
         
            +
                  class MissingHashSchemaError < StandardError
         
     | 
| 
      
 5 
     | 
    
         
            +
                    def message
         
     | 
| 
      
 6 
     | 
    
         
            +
                      "Could not generate documentation for field %{field_name}. The field is defined as hash,
         
     | 
| 
      
 7 
     | 
    
         
            +
                      but the schema is not defined.
         
     | 
| 
      
 8 
     | 
    
         
            +
                      Valid types are: %{valid_types}.
         
     | 
| 
      
 9 
     | 
    
         
            +
                      The parser has generated the following definition for the field: %{field_name}: %{attributes_hash}
         
     | 
| 
      
 10 
     | 
    
         
            +
                      "
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Swagger
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Errors
         
     | 
| 
      
 4 
     | 
    
         
            +
                  class MissingTypeError < StandardError
         
     | 
| 
      
 5 
     | 
    
         
            +
                    def message
         
     | 
| 
      
 6 
     | 
    
         
            +
                      "Could not generate documentation for field %{field_name}. The field is missing a type.
         
     | 
| 
      
 7 
     | 
    
         
            +
                      If the field you have defined is an array, you must specify the type of the elements in that array.
         
     | 
| 
      
 8 
     | 
    
         
            +
                      Valid types are: %{valid_types}.
         
     | 
| 
      
 9 
     | 
    
         
            +
                      The parser has generated the following definition for the field: %{field_name}: %{attributes_hash}.
         
     | 
| 
      
 10 
     | 
    
         
            +
                      "
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,81 +1,144 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Dry
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Swagger
         
     | 
| 
       3 
3 
     | 
    
         
             
                class StructParser
         
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
       5 
     | 
    
         
            -
                       
     | 
| 
       6 
     | 
    
         
            -
                       
     | 
| 
       7 
     | 
    
         
            -
                       
     | 
| 
       8 
     | 
    
         
            -
                       
     | 
| 
       9 
     | 
    
         
            -
                       
     | 
| 
       10 
     | 
    
         
            -
                       
     | 
| 
       11 
     | 
    
         
            -
                       
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                     
     | 
| 
      
 4 
     | 
    
         
            +
                  PREDICATE_TYPES = {
         
     | 
| 
      
 5 
     | 
    
         
            +
                      String: 'string',
         
     | 
| 
      
 6 
     | 
    
         
            +
                      Integer: 'integer',
         
     | 
| 
      
 7 
     | 
    
         
            +
                      Bool: 'boolean',
         
     | 
| 
      
 8 
     | 
    
         
            +
                      Float: 'float',
         
     | 
| 
      
 9 
     | 
    
         
            +
                      Date: 'date',
         
     | 
| 
      
 10 
     | 
    
         
            +
                      DateTime: 'datetime',
         
     | 
| 
      
 11 
     | 
    
         
            +
                      Time: 'time'
         
     | 
| 
      
 12 
     | 
    
         
            +
                  }.freeze
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  attr_reader :keys
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @keys = {}
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @config = Dry::Swagger::Config::StructConfiguration
         
     | 
| 
       18 
19 
     | 
    
         
             
                  end
         
     | 
| 
       19 
20 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                  def  
     | 
| 
       21 
     | 
    
         
            -
                     
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                      documentation[:properties][name] = schema_key_object.type.optional? ?
         
     | 
| 
       24 
     | 
    
         
            -
                                                             generate_field_properties(schema_key_object.type.right, true) :
         
     | 
| 
       25 
     | 
    
         
            -
                                                             generate_field_properties(schema_key_object.type, false)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 22 
     | 
    
         
            +
                    { keys: keys }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
       26 
24 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                     
     | 
| 
       29 
     | 
    
         
            -
                     
     | 
| 
      
 25 
     | 
    
         
            +
                  def call(dto, &block)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @keys = {}
         
     | 
| 
      
 27 
     | 
    
         
            +
                    visit(dto.schema.to_ast)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    instance_eval(&block) if block_given?
         
     | 
| 
      
 29 
     | 
    
         
            +
                    self
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def visit(node, opts = {})
         
     | 
| 
      
 33 
     | 
    
         
            +
                    meth, rest = node
         
     | 
| 
      
 34 
     | 
    
         
            +
                    public_send(:"visit_#{meth}", rest, opts)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def visit_constructor(node, opts = {})
         
     | 
| 
      
 38 
     | 
    
         
            +
                    visit(node[0], opts)
         
     | 
| 
       30 
39 
     | 
    
         
             
                  end
         
     | 
| 
       31 
40 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                  def  
     | 
| 
       33 
     | 
    
         
            -
                     
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                     
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def visit_schema(node, opts = {})
         
     | 
| 
      
 42 
     | 
    
         
            +
                    target = (key = opts[:key]) ? self.class.new : self
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    required = opts.fetch(:required, true)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    nullable = opts.fetch(:nullable, false)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    node[0].each do |child|
         
     | 
| 
      
 48 
     | 
    
         
            +
                      target.visit(child)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    return unless key
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    target_info =  target.to_h if opts[:member]
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    type = opts[:array]? 'array' : 'hash'
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    definition = {
         
     | 
| 
      
 58 
     | 
    
         
            +
                        type: type,
         
     | 
| 
      
 59 
     | 
    
         
            +
                        required: required,
         
     | 
| 
      
 60 
     | 
    
         
            +
                        @config.nullable_type => nullable,
         
     | 
| 
      
 61 
     | 
    
         
            +
                        **target_info
         
     | 
| 
      
 62 
     | 
    
         
            +
                    }
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    if opts[:oneOf]
         
     | 
| 
      
 65 
     | 
    
         
            +
                      keys[key] = keys[key] ? keys[key] << definition : [definition]
         
     | 
| 
       51 
66 
     | 
    
         
             
                    else
         
     | 
| 
       52 
     | 
    
         
            -
                       
     | 
| 
       53 
     | 
    
         
            -
                      definition = call(schema)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      keys[key] = definition
         
     | 
| 
       54 
68 
     | 
    
         
             
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                  def visit_key(node, opts = {})
         
     | 
| 
      
 72 
     | 
    
         
            +
                    name, required, rest = node
         
     | 
| 
      
 73 
     | 
    
         
            +
                    opts[:key] = name
         
     | 
| 
      
 74 
     | 
    
         
            +
                    opts[:required] = required
         
     | 
| 
      
 75 
     | 
    
         
            +
                    visit(rest, opts)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
       55 
77 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
      
 78 
     | 
    
         
            +
                  def visit_constrained(node, opts = {})
         
     | 
| 
      
 79 
     | 
    
         
            +
                    node.each {|it| visit(it, opts) }
         
     | 
| 
       57 
80 
     | 
    
         
             
                  end
         
     | 
| 
       58 
81 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
                   
     | 
| 
      
 82 
     | 
    
         
            +
                  def visit_nominal(_node, _opts); end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  def visit_predicate(node, opts = {})
         
     | 
| 
      
 85 
     | 
    
         
            +
                    name, rest = node
         
     | 
| 
      
 86 
     | 
    
         
            +
                    type = rest[0][1]
         
     | 
| 
       60 
87 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
      
 88 
     | 
    
         
            +
                    if name.equal?(:type?)
         
     | 
| 
      
 89 
     | 
    
         
            +
                      type = type.to_s.to_sym
         
     | 
| 
      
 90 
     | 
    
         
            +
                      return unless PREDICATE_TYPES[type]
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                      type_definition = {
         
     | 
| 
      
 93 
     | 
    
         
            +
                          type: PREDICATE_TYPES[type],
         
     | 
| 
      
 94 
     | 
    
         
            +
                          required: opts.fetch(:required),
         
     | 
| 
      
 95 
     | 
    
         
            +
                          @config.nullable_type => opts.fetch(:nullable, false)
         
     | 
| 
      
 96 
     | 
    
         
            +
                      }
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                      type_definition[:array] = opts[:array] if opts[:array]
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                      keys[opts[:key]] = type_definition
         
     | 
| 
      
 101 
     | 
    
         
            +
                    elsif name.equal?(:included_in?)
         
     | 
| 
      
 102 
     | 
    
         
            +
                      type += [nil] if opts.fetch(:nullable, false)
         
     | 
| 
      
 103 
     | 
    
         
            +
                      keys[opts[:key]][:enum] = type
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
       63 
105 
     | 
    
         
             
                  end
         
     | 
| 
       64 
106 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
                  def  
     | 
| 
       66 
     | 
    
         
            -
                     
     | 
| 
      
 107 
     | 
    
         
            +
                  def visit_and(node, opts = {})
         
     | 
| 
      
 108 
     | 
    
         
            +
                    left, right = node
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                    visit(left, opts)
         
     | 
| 
      
 111 
     | 
    
         
            +
                    visit(right, opts)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                  def visit_enum(node, opts = {})
         
     | 
| 
      
 115 
     | 
    
         
            +
                    visit(node[0], opts)
         
     | 
| 
       67 
116 
     | 
    
         
             
                  end
         
     | 
| 
       68 
117 
     | 
    
         | 
| 
       69 
     | 
    
         
            -
                  def  
     | 
| 
       70 
     | 
    
         
            -
                     
     | 
| 
      
 118 
     | 
    
         
            +
                  def visit_sum(node, opts = {})
         
     | 
| 
      
 119 
     | 
    
         
            +
                    if node[0][0].equal?(:constrained)
         
     | 
| 
      
 120 
     | 
    
         
            +
                      opts[:nullable] = true
         
     | 
| 
      
 121 
     | 
    
         
            +
                      visit(node[1], opts) # ignore NilClass constrained
         
     | 
| 
      
 122 
     | 
    
         
            +
                    elsif node[0][0].equal?(:struct) && node[1][0].equal?(:struct)
         
     | 
| 
      
 123 
     | 
    
         
            +
                      opts[:oneOf] = true
         
     | 
| 
      
 124 
     | 
    
         
            +
                      visit(node[0], opts)
         
     | 
| 
      
 125 
     | 
    
         
            +
                      visit(node[1], opts)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  def visit_struct(node, opts = {})
         
     | 
| 
      
 130 
     | 
    
         
            +
                    opts[:member] = true
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                    visit(node[1], opts)
         
     | 
| 
       71 
133 
     | 
    
         
             
                  end
         
     | 
| 
       72 
134 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
                  def  
     | 
| 
       74 
     | 
    
         
            -
                     
     | 
| 
      
 135 
     | 
    
         
            +
                  def visit_array(node, opts = {})
         
     | 
| 
      
 136 
     | 
    
         
            +
                    opts[:array] = true
         
     | 
| 
      
 137 
     | 
    
         
            +
                    visit(node[0], opts)
         
     | 
| 
       75 
138 
     | 
    
         
             
                  end
         
     | 
| 
       76 
139 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
                  def  
     | 
| 
       78 
     | 
    
         
            -
                     
     | 
| 
      
 140 
     | 
    
         
            +
                  def to_swagger
         
     | 
| 
      
 141 
     | 
    
         
            +
                    DocumentationGenerator.new(@config).generate_documentation(keys)
         
     | 
| 
       79 
142 
     | 
    
         
             
                  end
         
     | 
| 
       80 
143 
     | 
    
         
             
                end
         
     | 
| 
       81 
144 
     | 
    
         
             
              end
         
     | 
    
        data/lib/dry/swagger/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: dry-swagger
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.5.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Jane-Terziev
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2021- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2021-08-03 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies: []
         
     | 
| 
       13 
13 
     | 
    
         
             
            description: A parser which converts dry-validation or dry-struct into valid swagger
         
     | 
| 
       14 
14 
     | 
    
         
             
              documentation
         
     | 
| 
         @@ -32,11 +32,16 @@ files: 
     | 
|
| 
       32 
32 
     | 
    
         
             
            - bin/setup
         
     | 
| 
       33 
33 
     | 
    
         
             
            - dry-swagger.gemspec
         
     | 
| 
       34 
34 
     | 
    
         
             
            - lib/dry/swagger.rb
         
     | 
| 
      
 35 
     | 
    
         
            +
            - lib/dry/swagger/config/configuration.rb
         
     | 
| 
      
 36 
     | 
    
         
            +
            - lib/dry/swagger/config/contract_configuration.rb
         
     | 
| 
      
 37 
     | 
    
         
            +
            - lib/dry/swagger/config/struct_configuration.rb
         
     | 
| 
       35 
38 
     | 
    
         
             
            - lib/dry/swagger/contract_parser.rb
         
     | 
| 
      
 39 
     | 
    
         
            +
            - lib/dry/swagger/documentation_generator.rb
         
     | 
| 
      
 40 
     | 
    
         
            +
            - lib/dry/swagger/errors/missing_hash_schema_error.rb
         
     | 
| 
      
 41 
     | 
    
         
            +
            - lib/dry/swagger/errors/missing_type_error.rb
         
     | 
| 
       36 
42 
     | 
    
         
             
            - lib/dry/swagger/struct_parser.rb
         
     | 
| 
       37 
43 
     | 
    
         
             
            - lib/dry/swagger/types.rb
         
     | 
| 
       38 
44 
     | 
    
         
             
            - lib/dry/swagger/version.rb
         
     | 
| 
       39 
     | 
    
         
            -
            - lib/helpers/configuration.rb
         
     | 
| 
       40 
45 
     | 
    
         
             
            homepage: https://github.com/Jane-Terziev/dry-swagger
         
     | 
| 
       41 
46 
     | 
    
         
             
            licenses:
         
     | 
| 
       42 
47 
     | 
    
         
             
            - MIT
         
     | 
| 
         @@ -1,27 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Configuration
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              def configuration
         
     | 
| 
       4 
     | 
    
         
            -
                yield self
         
     | 
| 
       5 
     | 
    
         
            -
              end
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
              def define_setting(name, default = nil)
         
     | 
| 
       8 
     | 
    
         
            -
                class_variable_set("@@#{name}", default)
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                define_class_method "#{name}=" do |value|
         
     | 
| 
       11 
     | 
    
         
            -
                  class_variable_set("@@#{name}", value)
         
     | 
| 
       12 
     | 
    
         
            -
                end
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                define_class_method name do
         
     | 
| 
       15 
     | 
    
         
            -
                  class_variable_get("@@#{name}")
         
     | 
| 
       16 
     | 
    
         
            -
                end
         
     | 
| 
       17 
     | 
    
         
            -
              end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
              private
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
              def define_class_method(name, &block)
         
     | 
| 
       22 
     | 
    
         
            -
                (class << self; self; end).instance_eval do
         
     | 
| 
       23 
     | 
    
         
            -
                  define_method name, &block
         
     | 
| 
       24 
     | 
    
         
            -
                end
         
     | 
| 
       25 
     | 
    
         
            -
              end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
            end
         
     |