dry-swagger 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ea8396c1d7976844254a7e7564a74a0cdc0391c3bf42a4aa49fc479fd99e11e
4
- data.tar.gz: 611a49427c0c0ece4bd4ec1e134afd8bcebc01f43b0803eecabdd9cf16df4d14
3
+ metadata.gz: 5179183ed4122bcf5042f8aa812b6830b1126ae00d4eb2975bd17203af2bf375
4
+ data.tar.gz: 9eb614eaaaca4752a39f9a77ef2fac3dffb4df2179a0c7e7f427d13f9f02333e
5
5
  SHA512:
6
- metadata.gz: 7d1e8404d230897c6f4e88fffbd1870ee1fbf305b725d8d9067f5529c3f2bcdda71990b364372478d3ff9f780e6a997144c557f57f574768d705caea10255923
7
- data.tar.gz: 0d7b5f769a536d9fd18b594cf097c5c9922b92f74bdf009ff2dd90ea099e90c5bc9d36aa684efcdd49a1176f299d6db2574a786a8a98213a5301a15bfdb223bf
6
+ metadata.gz: 58dea258473d5fea4c521d699a2332ec8a444d15504b81ff3eefba0ef50c08371fe5d9b3fd7e2d3331613375f625bdb3ea54073dde31cfc20eafdc0d29e49202
7
+ data.tar.gz: 2ec6862a8021cb836101cac89b394482507a6b48021cfbf304b63c8753fe0bcefb822730a194ae869da6c83dc34e965af771a58b6052dc729cea0d528a97b6a4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dry-swagger (0.3.0)
4
+ dry-swagger (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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.struct_enable_required_validation = true / false
266
- config.struct_enable_nullable_validation = true / false
267
- config.struct_enable_enums = true / false
268
- config.struct_enable_descriptions = true / false
269
-
270
- config.contract_enable_required_validation = true / false
271
- config.contract_enable_nullable_validation = true / false
272
- config.contract_enable_enums = true / false
273
- config.contract_enable_descriptions = true / false
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 'helpers/configuration'
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
- to_swagger
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
- key = opts[:key]
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) if ::Dry::Swagger.contract_enable_required_validation
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) if ::Dry::Swagger.contract_enable_required_validation
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) } if ::Dry::Swagger.contract_enable_required_validation
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
- keys[key][:enum] = rest[0][1]
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
- SWAGGER_FIELD_TYPE_DEFINITIONS = {
5
- "String" => { type: :string },
6
- "Integer" => { type: :integer },
7
- "TrueClass | FalseClass" => { type: :boolean },
8
- "BigDecimal" => { type: :decimal },
9
- "Float" => { type: :float },
10
- "DateTime" => { type: :string, format: :datetime },
11
- "Date" => { type: :string, format: :date },
12
- "Time" => { type: :string, format: :time }
13
- }
14
-
15
- def call(dto)
16
- documentation = generate_fields_documentation(dto.schema)
17
- { :type => :object, :properties => documentation[:properties], :required => documentation[:required]}
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 generate_fields_documentation(dto_schema)
21
- documentation = { properties: {}, required: [] }
22
- dto_schema.name_key_map.each do |name, schema_key_object|
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
- documentation[:required] << name if ::Dry::Swagger.struct_enable_required_validation && schema_key_object.required?
28
- end
29
- documentation
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 generate_field_properties(type, nullable)
33
- field_type = type.name
34
- if SWAGGER_FIELD_TYPE_DEFINITIONS[field_type] # IS PRIMITIVE FIELD?
35
- definition = SWAGGER_FIELD_TYPE_DEFINITIONS[field_type]
36
- definition = definition
37
- if is_enum?(type.class.name) && ::Dry::Swagger.struct_enable_enums
38
- enums = type.values
39
- enums += [nil] if nullable
40
- definition = definition.merge(enum: enums)
41
- end
42
- elsif is_array?(field_type)
43
- definition = { type: :array }
44
- if is_primitive?(type.type.member.name)
45
- definition = definition
46
- definition = definition.merge(items: SWAGGER_FIELD_TYPE_DEFINITIONS[type.type.member.name])
47
- else
48
- schema = is_array_with_dynamic_schema?(type.type.member) ? type.type.member.left : type.type.member
49
- definition = definition.merge(items: call(schema))
50
- end
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
- schema = is_dynamic_schema?(type) ? type.left : type
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
- ::Dry::Swagger.struct_enable_nullable_validation ? definition.merge(::Dry::Swagger.nullable_type => nullable) : definition
78
+ def visit_constrained(node, opts = {})
79
+ node.each {|it| visit(it, opts) }
57
80
  end
58
81
 
59
- private
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
- def is_enum?(class_name)
62
- class_name == 'Dry::Types::Enum'
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 is_array?(type_name)
66
- type_name == 'Array'
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 is_primitive?(type_name)
70
- !SWAGGER_FIELD_TYPE_DEFINITIONS[type_name].nil?
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 is_array_with_dynamic_schema?(member)
74
- member.respond_to?(:right)
135
+ def visit_array(node, opts = {})
136
+ opts[:array] = true
137
+ visit(node[0], opts)
75
138
  end
76
139
 
77
- def is_dynamic_schema?(type)
78
- !type.respond_to?(:schema)
140
+ def to_swagger
141
+ DocumentationGenerator.new(@config).generate_documentation(keys)
79
142
  end
80
143
  end
81
144
  end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Swagger
3
- VERSION = "0.3.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
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.3.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-07-31 00:00:00.000000000 Z
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