dry-swagger 1.0.0 → 2.0.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: 0f02e4e684a8418f7df9ef80cfbbfdbe7169e1e5db8f4bedde227cda11dddf64
4
- data.tar.gz: 860a49c5384ca32c9895df6dac3cbec40e2033f6a910c6ae1a00887bf7eeea56
3
+ metadata.gz: e9f90c08a2cc2e78fca981c2e4db7836cb1f14632b478d6bb951146cb9101d66
4
+ data.tar.gz: 33bf560f05ecac510ff401ebe3067e487ee28b7378395a0f97b3a44f6a4388a7
5
5
  SHA512:
6
- metadata.gz: 9ab94e41fa7b4e410c1aae8c1b2276ae87455ce85d7ee9b56ee507073cddecd6d32d23e4467d306a717b275e8e19cd794f09adf7dba2e38cd35d8fe74f66fcc1
7
- data.tar.gz: 1e70ba36734ba3b2e072b9b840829b30736abe07bdaa8eb57251172681bd53960f1399d6a0f044e514c5d87df3c81c1847b56e27cb6767d22547ff2401ad1e3d
6
+ metadata.gz: 93d02007263ab18d0f37f7e41013eeb75082ceaec296f8023d104f6cbf5ea15874a6130cb89b0bfe5af5dbc602104948b41d2bc4ce929397535210e3d9e63158
7
+ data.tar.gz: 80436b836812d8550c7798506e585ba7368f61db3afa08fae34c3ae7eeb940b24dedcab2e297176140d060a4841d8f4716d9ea3add070fbdbac90f7b51efebec
@@ -0,0 +1,27 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ pull_request:
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ name: Ruby ${{ matrix.ruby }}
14
+ strategy:
15
+ matrix:
16
+ ruby:
17
+ - '3.2.2'
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby }}
25
+ bundler-cache: true
26
+ - name: Run Tests
27
+ run: bundle exec rspec
data/.gitignore CHANGED
@@ -10,5 +10,5 @@
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
12
  .idea/
13
- config/
14
- rakelib/
13
+ rakelib/
14
+ /config/
data/CODE_OF_CONDUCT.md CHANGED
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
55
55
  ## Enforcement
56
56
 
57
57
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at jane.terziev@webfactory.mk. All
58
+ reported by contacting the project team at janeterziev@gmail.com. All
59
59
  complaints will be reviewed and investigated and will result in a response that
60
60
  is deemed necessary and appropriate to the circumstances. The project team is
61
61
  obligated to maintain confidentiality with regard to the reporter of an incident.
data/Gemfile CHANGED
@@ -5,6 +5,6 @@ gemspec
5
5
 
6
6
  gem "rake", "~> 12.0"
7
7
  gem "rspec", "~> 3.0"
8
- gem "dry-validation"
9
- gem "dry-struct"
8
+ gem "dry_struct_parser"
9
+ gem "dry_validation_parser"
10
10
  gem 'i18n'
data/Gemfile.lock CHANGED
@@ -1,51 +1,59 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dry-swagger (1.0.0)
4
+ dry-swagger (2.0.0)
5
+ dry_struct_parser
6
+ dry_validation_parser
5
7
 
6
8
  GEM
7
9
  remote: https://rubygems.org/
8
10
  specs:
9
- concurrent-ruby (1.1.9)
11
+ bigdecimal (3.1.5)
12
+ concurrent-ruby (1.2.2)
10
13
  diff-lcs (1.4.4)
11
- dry-configurable (0.12.1)
14
+ dry-configurable (1.1.0)
15
+ dry-core (~> 1.0, < 2)
16
+ zeitwerk (~> 2.6)
17
+ dry-core (1.0.1)
12
18
  concurrent-ruby (~> 1.0)
13
- dry-core (~> 0.5, >= 0.5.0)
14
- dry-container (0.8.0)
19
+ zeitwerk (~> 2.6)
20
+ dry-inflector (1.0.0)
21
+ dry-initializer (3.1.1)
22
+ dry-logic (1.5.0)
15
23
  concurrent-ruby (~> 1.0)
16
- dry-configurable (~> 0.1, >= 0.1.3)
17
- dry-core (0.7.1)
24
+ dry-core (~> 1.0, < 2)
25
+ zeitwerk (~> 2.6)
26
+ dry-schema (1.13.3)
18
27
  concurrent-ruby (~> 1.0)
19
- dry-equalizer (0.3.0)
20
- dry-inflector (0.2.1)
21
- dry-initializer (3.0.4)
22
- dry-logic (1.2.0)
23
- concurrent-ruby (~> 1.0)
24
- dry-core (~> 0.5, >= 0.5)
25
- dry-schema (1.7.0)
26
- concurrent-ruby (~> 1.0)
27
- dry-configurable (~> 0.8, >= 0.8.3)
28
- dry-core (~> 0.5, >= 0.5)
28
+ dry-configurable (~> 1.0, >= 1.0.1)
29
+ dry-core (~> 1.0, < 2)
29
30
  dry-initializer (~> 3.0)
30
- dry-logic (~> 1.0)
31
- dry-types (~> 1.5)
32
- dry-struct (1.4.0)
33
- dry-core (~> 0.5, >= 0.5)
34
- dry-types (~> 1.5)
31
+ dry-logic (>= 1.4, < 2)
32
+ dry-types (>= 1.7, < 2)
33
+ zeitwerk (~> 2.6)
34
+ dry-struct (1.6.0)
35
+ dry-core (~> 1.0, < 2)
36
+ dry-types (>= 1.7, < 2)
35
37
  ice_nine (~> 0.11)
36
- dry-types (1.5.1)
38
+ zeitwerk (~> 2.6)
39
+ dry-types (1.7.2)
40
+ bigdecimal (~> 3.0)
37
41
  concurrent-ruby (~> 1.0)
38
- dry-container (~> 0.3)
39
- dry-core (~> 0.5, >= 0.5)
40
- dry-inflector (~> 0.1, >= 0.1.2)
41
- dry-logic (~> 1.0, >= 1.0.2)
42
- dry-validation (1.6.0)
42
+ dry-core (~> 1.0)
43
+ dry-inflector (~> 1.0)
44
+ dry-logic (~> 1.4)
45
+ zeitwerk (~> 2.6)
46
+ dry-validation (1.10.0)
43
47
  concurrent-ruby (~> 1.0)
44
- dry-container (~> 0.7, >= 0.7.1)
45
- dry-core (~> 0.4)
46
- dry-equalizer (~> 0.2)
48
+ dry-core (~> 1.0, < 2)
47
49
  dry-initializer (~> 3.0)
48
- dry-schema (~> 1.5, >= 1.5.2)
50
+ dry-schema (>= 1.12, < 2)
51
+ zeitwerk (~> 2.6)
52
+ dry_struct_parser (0.1.0)
53
+ dry-struct (~> 1)
54
+ dry_validation_parser (0.1.7)
55
+ dry-types (~> 1)
56
+ dry-validation (~> 1)
49
57
  i18n (1.8.10)
50
58
  concurrent-ruby (~> 1.0)
51
59
  ice_nine (0.11.2)
@@ -63,17 +71,18 @@ GEM
63
71
  diff-lcs (>= 1.2.0, < 2.0)
64
72
  rspec-support (~> 3.10.0)
65
73
  rspec-support (3.10.2)
74
+ zeitwerk (2.6.12)
66
75
 
67
76
  PLATFORMS
68
77
  ruby
69
78
 
70
79
  DEPENDENCIES
71
- dry-struct
72
80
  dry-swagger!
73
- dry-validation
81
+ dry_struct_parser
82
+ dry_validation_parser
74
83
  i18n
75
84
  rake (~> 12.0)
76
85
  rspec (~> 3.0)
77
86
 
78
87
  BUNDLED WITH
79
- 2.1.4
88
+ 2.5.4
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2021 wf-janeterziev
3
+ Copyright (c) 2021 Jane-Terziev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -3,6 +3,25 @@
3
3
  Generate a valid and up to date swagger documentation out of your dry-structs and dry-validations
4
4
 
5
5
  The gem is still work in progress and is not yet fully tested.
6
+ ## IMPORTANT:
7
+
8
+ If you are upgrading from version 1 to version 2, you will need to replace:
9
+
10
+ Dry::Swagger::StructParser.new.call(struct)
11
+ with
12
+
13
+ Dry::Swagger::DocumentationGenerator.new.from_struct(struct)
14
+ and replace
15
+
16
+ Dry::Swagger::ContractParser.new.call(contract)
17
+ with
18
+
19
+ Dry::Swagger::DocumentationGenerator.new.from_validation(contract).
20
+
21
+ For the configuration file in project/config/initializers/dry-swagger.rb, you will need to replace:
22
+
23
+ Dry::Swagger::Config::ContractConfiguration -> Dry::Swagger::Config::SwaggerConfiguration
24
+ you do not need both ContractConfiguration and StructConfiguration.
6
25
  ## Installation
7
26
 
8
27
  Add this line to your application's Gemfile:
@@ -24,8 +43,6 @@ This will generate configuration files in your project under `project/config`. S
24
43
  ## Usage
25
44
 
26
45
  #### With Dry::Validation::Contract
27
- Lets say we have the following Dry::Validation::Contract definition:
28
-
29
46
  class TestContract < Dry::Validation::Contract
30
47
  params do
31
48
  required(:some_field).value(:str?, min_size?: 5, max_size?: 10)
@@ -39,128 +56,63 @@ Lets say we have the following Dry::Validation::Contract definition:
39
56
  end
40
57
  end
41
58
 
42
- parser = Dry::Swagger::ContractParser.new
43
-
44
- `parser.call(TestContract)` will set the `keys` of the `parser` object to:
45
-
46
- {
47
- :some_field => {
48
- :required => true,
49
- :type => "string",
50
- :description => "Minimum size: 5, Maximum size: 10"
51
- },
52
- :some_array_of_objects => {
53
- :required => true,
54
- :array => true,
55
- :type => "array",
56
- :keys => {
57
- :some_nested_attribute => {
58
- :required=>true, :type=>"string"
59
- }
60
- }
61
- },
62
- :some_array_of_integers => {
63
- :required=>true,
64
- :array=>true,
65
- :type=>"integer"
66
- },
67
- :dto => {
68
- :required => true,
69
- :type => "hash",
70
- :keys => {
71
- :some_nested_attribute => {
72
- :required => false,
73
- :"x-nullable"=>true,
74
- :type=>"string"
75
- }
76
- }
77
- }
78
- }
79
-
80
- As we can see, the `ContractParser` goes through all the params defined in the
81
- schema and generates a hash. The hash is saved in the `keys` attribute of the parser,
82
- so that we can call `to_swagger` later.
83
-
84
- The required key in our result will be set to `true` if the field is defined as
85
- `required(:field_name)`, and `false` if defined as `optional(:field_name)`.
86
-
87
- The "x-nullable" key depends on whether we have defined the field as value, maybe or filled.
88
-
89
- For nested objects like array of objects or hash, we add a keys field with a definition
90
- for each field inside the nested hash.
91
-
92
- If the field is an array of primitive type, the type field will equal to the primitive type, and a
93
- array flag will be set on the field.
94
-
95
- Calling `parser.to_swagger` will give the following result:
96
-
97
- {
98
- "type": "object",
99
- "properties": {
100
- "some_field": {
101
- "type": "string",
102
- "description": "Minimum size: 5, Maximum size: 10",
103
- "x-nullable": false
104
- },
105
- "some_array_of_objects": {
106
- "type": "array",
107
- "items": {
108
- "type": "object",
109
- "properties": {
110
- "some_nested_attribute": {
111
- "type": "string",
112
- "x-nullable": false
113
- }
114
- },
115
- "required": [
116
- "some_nested_attribute"
117
- ],
118
- "x-nullable": false
119
- },
120
- "x-nullable": false
121
- },
122
- "some_array_of_integers": {
123
- "type": "array",
124
- "items": {
125
- "type": "integer",
126
- "x-nullable": false
127
- },
128
- "x-nullable": false
129
- },
130
- "dto": {
59
+ Dry::Swagger::DocumentationGenerator.new.from_validation(TestContract)
60
+ => {
131
61
  "type": "object",
132
62
  "properties": {
133
- "some_nested_attribute": {
63
+ "some_field": {
134
64
  "type": "string",
135
- "x-nullable": true
65
+ "description": "Minimum size: 5, Maximum size: 10",
66
+ "x-nullable": false
67
+ },
68
+ "some_array_of_objects": {
69
+ "type": "array",
70
+ "items": {
71
+ "type": "object",
72
+ "properties": {
73
+ "some_nested_attribute": {
74
+ "type": "string",
75
+ "x-nullable": false
76
+ }
77
+ },
78
+ "required": [
79
+ "some_nested_attribute"
80
+ ],
81
+ "x-nullable": false
82
+ },
83
+ "x-nullable": false
84
+ },
85
+ "some_array_of_integers": {
86
+ "type": "array",
87
+ "items": {
88
+ "type": "integer",
89
+ "x-nullable": false
90
+ },
91
+ "x-nullable": false
92
+ },
93
+ "dto": {
94
+ "type": "object",
95
+ "properties": {
96
+ "some_nested_attribute": {
97
+ "type": "string",
98
+ "x-nullable": true
99
+ }
100
+ },
101
+ "required": [
102
+
103
+ ],
104
+ "x-nullable": false
136
105
  }
137
106
  },
138
107
  "required": [
139
-
140
- ],
141
- "x-nullable": false
108
+ "some_field",
109
+ "some_array_of_objects",
110
+ "some_array_of_integers",
111
+ "dto"
112
+ ]
142
113
  }
143
- },
144
- "required": [
145
- "some_field",
146
- "some_array_of_objects",
147
- "some_array_of_integers",
148
- "dto"
149
- ]
150
- }
151
114
 
152
115
  #### With Dry::Struct
153
- The `Dry::Swagger::StructParser` works the same as the contract parser.
154
-
155
- The required key depends on whether we define the field as attribute or attribute?
156
-
157
- The "x-nullable" key depends on whether we define the type as Type or Type.optional.
158
-
159
- For more complex types, for example DTO1 | DTO2 or Types::Array.of(DTO1 | DTO2),
160
- the parser converts the field value to an array of both schemas.
161
-
162
- Example:
163
-
164
116
  class DTO1 < Dry::Struct
165
117
  attribute :dto1_field, Types::String
166
118
  end
@@ -172,145 +124,79 @@ Example:
172
124
  class DTO < Dry::Struct
173
125
  attribute :dynamic_dto, DTO1 | DTO2
174
126
  end
175
- parser = Dry::Swagger::StructParser.new
176
-
177
- parser.call(DTO)
178
- => {
179
- "dynamic_dto": [ # ARRAY
180
- {
181
- "type": "hash",
182
- "required": true,
183
- "x-nullable": false,
184
- "keys": {
185
- "dto1_field": {
186
- "type": "string",
187
- "required": true,
188
- "x-nullable": false
189
- }
190
- }
191
- },
192
- {
193
- "type": "hash",
194
- "required": true,
195
- "x-nullable": false,
196
- "keys": {
197
- "dto2_field": {
198
- "type": "string",
199
- "required": true,
200
- "x-nullable": false
201
- }
202
- }
203
- }
204
- ]
205
- }
206
127
 
207
- Calling `parser.to_swagger` will give the following result:
208
-
209
- {
210
- "type": "object",
211
- "properties": {
212
- "dynamic_dto": {
128
+ Dry::Swagger::DocumentationGenerator.new.from_struct(DTO)
129
+ => {
213
130
  "type": "object",
214
131
  "properties": {
215
- "definition_1": {
132
+ "dynamic_dto": {
216
133
  "type": "object",
217
134
  "properties": {
218
- "dto1_field": {
219
- "type": "string",
135
+ "definition_1": {
136
+ "type": "object",
137
+ "properties": {
138
+ "dto1_field": {
139
+ "type": "string",
140
+ "x-nullable": false
141
+ }
142
+ },
143
+ "required": [
144
+ "dto1_field"
145
+ ],
220
146
  "x-nullable": false
221
- }
222
- },
223
- "required": [
224
- "dto1_field"
225
- ],
226
- "x-nullable": false
227
- },
228
- "definition_2": {
229
- "type": "object",
230
- "properties": {
231
- "dto2_field": {
232
- "type": "string",
147
+ },
148
+ "definition_2": {
149
+ "type": "object",
150
+ "properties": {
151
+ "dto2_field": {
152
+ "type": "string",
153
+ "x-nullable": false
154
+ }
155
+ },
156
+ "required": [
157
+ "dto2_field"
158
+ ],
233
159
  "x-nullable": false
234
160
  }
235
161
  },
236
- "required": [
237
- "dto2_field"
238
- ],
239
- "x-nullable": false
240
- }
241
- },
242
- "example": "Dynamic Field. See Model Definitions",
243
- "oneOf": [
244
- {
245
- "type": "object",
246
- "properties": {
247
- "dto1_field": {
248
- "type": "string",
162
+ "example": "Dynamic Field. See Model Definitions",
163
+ "oneOf": [
164
+ {
165
+ "type": "object",
166
+ "properties": {
167
+ "dto1_field": {
168
+ "type": "string",
169
+ "x-nullable": false
170
+ }
171
+ },
172
+ "required": [
173
+ "dto1_field"
174
+ ],
249
175
  "x-nullable": false
250
- }
251
- },
252
- "required": [
253
- "dto1_field"
254
- ],
255
- "x-nullable": false
256
- },
257
- {
258
- "type": "object",
259
- "properties": {
260
- "dto2_field": {
261
- "type": "string",
176
+ },
177
+ {
178
+ "type": "object",
179
+ "properties": {
180
+ "dto2_field": {
181
+ "type": "string",
182
+ "x-nullable": false
183
+ }
184
+ },
185
+ "required": [
186
+ "dto2_field"
187
+ ],
262
188
  "x-nullable": false
263
189
  }
264
- },
265
- "required": [
266
- "dto2_field"
267
- ],
268
- "x-nullable": false
190
+ ]
269
191
  }
192
+ },
193
+ "required": [
194
+ "dynamic_dto"
270
195
  ]
271
196
  }
272
- },
273
- "required": [
274
- "dynamic_dto"
275
- ]
276
- }
277
197
 
278
198
  ## Overriding fields
279
- You can also modify the fields by passing a block after the .call() method.
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()
199
+ The documentation generator returns the result as a hash, so you can easily modify it based on your needs.
314
200
 
315
201
  ## Custom Configuration For Your Project
316
202
  You can override default configurations by changing the values in the `config/initializers/dry-swagger.rb` file generated from the rake command in the Installation section.
data/dry-swagger.gemspec CHANGED
@@ -26,4 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.bindir = "exe"
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
+
30
+ spec.add_dependency "dry_struct_parser"
31
+ spec.add_dependency "dry_validation_parser"
29
32
  end
@@ -1,7 +1,7 @@
1
1
  module Dry
2
2
  module Swagger
3
3
  module Config
4
- module StructConfiguration
4
+ module SwaggerConfiguration
5
5
  extend Configuration
6
6
 
7
7
  define_setting :enable_required_validation, true
@@ -11,8 +11,16 @@ module Dry
11
11
  "time" => { type: :string, format: :time },
12
12
  }.freeze
13
13
 
14
- def initialize(config)
15
- @config = config
14
+ def initialize
15
+ @config = Config::SwaggerConfiguration
16
+ end
17
+
18
+ def from_struct(struct)
19
+ generate_documentation(DryStructParser::StructSchemaParser.new.call(struct).keys)
20
+ end
21
+
22
+ def from_validation(validation)
23
+ generate_documentation(DryValidationParser::ValidationSchemaParser.new.call(validation).keys)
16
24
  end
17
25
 
18
26
  def generate_documentation(fields)
@@ -45,7 +53,7 @@ module Dry
45
53
  documentation = generate_for_primitive_type(definition)
46
54
  end
47
55
  @config.enable_nullable_validation ?
48
- documentation.merge(@config.nullable_type => definition.fetch(@config.nullable_type, false)) :
56
+ documentation.merge(@config.nullable_type => definition.fetch(:nullable, false)) :
49
57
  documentation.merge(@config.nullable_type => true)
50
58
 
51
59
  rescue KeyError
@@ -80,7 +88,7 @@ module Dry
80
88
  SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(definition.fetch(:type)) :
81
89
  generate_documentation(definition.fetch(:keys))
82
90
  items = @config.enable_nullable_validation ?
83
- items.merge(@config.nullable_type => definition.fetch(@config.nullable_type, false)) :
91
+ items.merge(@config.nullable_type => definition.fetch(:nullable, false)) :
84
92
  items.merge(@config.nullable_type => true)
85
93
  { type: :array, items: items }
86
94
  end
@@ -1,26 +1,19 @@
1
1
  require 'fileutils'
2
2
 
3
3
  namespace 'dry-swagger' do
4
- desc 'Create a configuration file for Struct and Contract'
4
+ desc 'Create a configuration file for Dry Swagger Documentation Generator'
5
5
  task :create_configuration_file do
6
6
  FileUtils.mkdir_p "#{ Dir.pwd }/config/initializers/"
7
7
  puts "Created #{ Dir.pwd }/config/initializers/dry-swagger.rb"
8
8
  File.open("#{ Dir.pwd }/config/initializers/dry-swagger.rb", "w") { |file|
9
- file.puts 'Dry::Swagger::Config::StructConfiguration.configuration do |config|
9
+ file.puts 'Dry::Swagger::Config::SwaggerConfiguration.configuration do |config|
10
10
  config.enable_required_validation = true
11
11
  config.enable_nullable_validation = true
12
12
  config.enable_enums = true
13
13
  config.enable_descriptions = true
14
14
  config.nullable_type = :"x-nullable" # or :nullable
15
15
  end
16
-
17
- Dry::Swagger::Config::ContractConfiguration.configuration do |config|
18
- config.enable_required_validation = true
19
- config.enable_nullable_validation = true
20
- config.enable_enums = true
21
- config.enable_descriptions = true
22
- config.nullable_type = :"x-nullable" # or :nullable
23
- end'
16
+ '
24
17
  }
25
18
  end
26
19
 
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Swagger
3
- VERSION = "1.0.0"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
data/lib/dry/swagger.rb CHANGED
@@ -1,12 +1,9 @@
1
1
  require "dry/swagger/version"
2
- require "dry/swagger/contract_parser"
3
- require "dry/swagger/struct_parser"
4
2
  require 'dry/swagger/documentation_generator'
5
3
  require 'dry/swagger/errors/missing_hash_schema_error'
6
4
  require 'dry/swagger/errors/missing_type_error'
7
5
  require 'dry/swagger/config/configuration'
8
- require 'dry/swagger/config/contract_configuration'
9
- require 'dry/swagger/config/struct_configuration'
6
+ require 'dry/swagger/config/swagger_configuration'
10
7
  require 'i18n'
11
8
  require 'dry/swagger/railtie' if defined?(Rails)
12
9
 
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-swagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.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: 2022-04-29 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2024-01-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry_struct_parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dry_validation_parser
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  description: A parser which converts dry-validation or dry-struct into valid swagger
14
42
  documentation
15
43
  email:
@@ -18,10 +46,10 @@ executables: []
18
46
  extensions: []
19
47
  extra_rdoc_files: []
20
48
  files:
49
+ - ".github/workflows/main.yml"
21
50
  - ".gitignore"
22
51
  - ".rakeTasks"
23
52
  - ".rspec"
24
- - ".travis.yml"
25
53
  - CODE_OF_CONDUCT.md
26
54
  - Gemfile
27
55
  - Gemfile.lock
@@ -33,14 +61,11 @@ files:
33
61
  - dry-swagger.gemspec
34
62
  - lib/dry/swagger.rb
35
63
  - lib/dry/swagger/config/configuration.rb
36
- - lib/dry/swagger/config/contract_configuration.rb
37
- - lib/dry/swagger/config/struct_configuration.rb
38
- - lib/dry/swagger/contract_parser.rb
64
+ - lib/dry/swagger/config/swagger_configuration.rb
39
65
  - lib/dry/swagger/documentation_generator.rb
40
66
  - lib/dry/swagger/errors/missing_hash_schema_error.rb
41
67
  - lib/dry/swagger/errors/missing_type_error.rb
42
68
  - lib/dry/swagger/railtie.rb
43
- - lib/dry/swagger/struct_parser.rb
44
69
  - lib/dry/swagger/tasks/configuration_generator.rake
45
70
  - lib/dry/swagger/types.rb
46
71
  - lib/dry/swagger/version.rb
@@ -67,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
92
  - !ruby/object:Gem::Version
68
93
  version: '0'
69
94
  requirements: []
70
- rubygems_version: 3.1.6
95
+ rubygems_version: 3.4.10
71
96
  signing_key:
72
97
  specification_version: 4
73
98
  summary: Generate dry-validation and dry-struct into valid swagger documentation
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.1
6
- before_install: gem install bundler -v 2.1.4
@@ -1,15 +0,0 @@
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
@@ -1,128 +0,0 @@
1
- module Dry
2
- module Swagger
3
- class ContractParser
4
- PREDICATE_TO_TYPE = {
5
- array?: 'array',
6
- bool?: 'boolean',
7
- date?: 'date',
8
- date_time?: 'datetime',
9
- decimal?: 'float',
10
- float?: 'float',
11
- hash?: 'hash',
12
- int?: 'integer',
13
- nil?: 'nil',
14
- str?: 'string',
15
- time?: 'time'
16
- }.freeze
17
-
18
- # @api private
19
- attr_reader :keys
20
-
21
- # @api private
22
- def initialize
23
- @keys = {}
24
- @config = Config::ContractConfiguration
25
- end
26
-
27
- # @api private
28
- def to_h
29
- { keys: keys }
30
- end
31
-
32
- # @api private
33
- def call(contract, &block)
34
- @keys = {}
35
- visit(contract.schema.to_ast)
36
- instance_eval(&block) if block_given?
37
- self
38
- end
39
-
40
- # @api private
41
- def visit(node, opts = {})
42
- meth, rest = node
43
- public_send(:"visit_#{meth}", rest, opts)
44
- end
45
-
46
- # @api private
47
- def visit_set(node, opts = {})
48
- target = (key = opts[:key]) ? self.class.new : self
49
-
50
- node.map { |child| target.visit(child, opts) }
51
-
52
- return unless key
53
-
54
- target_info = opts[:member] ? target.to_h : target.to_h
55
- type = keys[key][:array] ? 'array' : 'hash'
56
-
57
- keys.update(key => { **keys[key], type: type, **target_info })
58
- end
59
-
60
- # @api private
61
- def visit_and(node, opts = {})
62
- left, right = node
63
-
64
- visit(left, opts)
65
- visit(right, opts)
66
- end
67
-
68
- def visit_not(_node, opts = {})
69
- keys[opts[:key]][@config.nullable_type] = true
70
- end
71
-
72
- # @api private
73
- def visit_implication(node, opts = {})
74
- node.each do |el|
75
- opts = opts.merge(required: false)
76
- visit(el, opts)
77
- end
78
- end
79
-
80
- # @api private
81
- def visit_each(node, opts = {})
82
- visit(node, opts.merge(member: true))
83
- end
84
-
85
- # @api private
86
- def visit_key(node, opts = {})
87
- name, rest = node
88
- opts = opts.merge(key: name)
89
- opts = opts.merge(required: true)
90
- visit(rest, opts)
91
- end
92
-
93
- # @api private
94
- def visit_predicate(node, opts = {})
95
- name, rest = node
96
-
97
- key = opts[:key]
98
-
99
- if name.equal?(:key?)
100
- keys[rest[0][1]] = { required: opts.fetch(:required, true) }
101
- elsif name.equal?(:array?)
102
- keys[key][:array] = true
103
- elsif name.equal?(:included_in?)
104
- enums = rest[0][1]
105
- enums += [nil] if opts.fetch(@config.nullable_type, false)
106
- keys[key][:enum] = enums
107
- elsif PREDICATE_TO_TYPE[name]
108
- keys[key][:type] = PREDICATE_TO_TYPE[name]
109
- else
110
- description = predicate_description(name.to_s, rest[0][1].to_s)
111
- if keys[key][:description].to_s.empty?
112
- keys[key][:description] = description unless description.to_s.empty?
113
- else
114
- keys[key][:description] += ", #{description}" unless description.to_s.empty?
115
- end
116
- end
117
- end
118
-
119
- def predicate_description(name, value)
120
- ::I18n.t("contract.descriptions.#{name}", value: value, default: '')
121
- end
122
-
123
- def to_swagger
124
- DocumentationGenerator.new(@config).generate_documentation(keys)
125
- end
126
- end
127
- end
128
- end
@@ -1,150 +0,0 @@
1
- module Dry
2
- module Swagger
3
- class StructParser
4
- PREDICATE_TYPES = {
5
- String: 'string',
6
- Integer: 'integer',
7
- TrueClass: 'boolean',
8
- FalseClass: 'boolean',
9
- Float: 'float',
10
- Date: 'date',
11
- DateTime: 'datetime',
12
- Time: 'time'
13
- }.freeze
14
-
15
- attr_reader :keys
16
-
17
- def initialize
18
- @keys = {}
19
- @config = Dry::Swagger::Config::StructConfiguration
20
- end
21
-
22
- def to_h
23
- { keys: keys }
24
- end
25
-
26
- def call(dto, &block)
27
- @keys = {}
28
- visit(dto.schema.to_ast)
29
- instance_eval(&block) if block_given?
30
- self
31
- end
32
-
33
- def visit(node, opts = {})
34
- meth, rest = node
35
- public_send(:"visit_#{meth}", rest, opts)
36
- end
37
-
38
- def visit_constructor(node, opts = {})
39
- visit(node[0], opts)
40
- end
41
-
42
- def visit_schema(node, opts = {})
43
- target = (key = opts[:key]) ? self.class.new : self
44
-
45
- required = opts.fetch(:required, true)
46
- nullable = opts.fetch(:nullable, false)
47
-
48
- node[0].each do |child|
49
- target.visit(child)
50
- end
51
-
52
- return unless key
53
-
54
- target_info = target.to_h if opts[:member]
55
-
56
- type = opts[:array]? 'array' : 'hash'
57
-
58
- definition = {
59
- type: type,
60
- required: required,
61
- @config.nullable_type => nullable,
62
- **target_info
63
- }
64
-
65
- if opts[:oneOf]
66
- keys[key] = keys[key] ? keys[key] << definition : [definition]
67
- else
68
- keys[key] = definition
69
- end
70
- end
71
-
72
- def visit_key(node, opts = {})
73
- name, required, rest = node
74
- opts[:key] = name
75
- opts[:required] = required
76
- visit(rest, opts)
77
- end
78
-
79
- def visit_constrained(node, opts = {})
80
- node.each {|it| visit(it, opts) }
81
- end
82
-
83
- def visit_nominal(_node, _opts); end
84
-
85
- def visit_predicate(node, opts = {})
86
- name, rest = node
87
- type = rest[0][1]
88
-
89
- if name.equal?(:type?)
90
- type = type.to_s.to_sym
91
- return unless PREDICATE_TYPES[type]
92
-
93
- # print node
94
- # puts
95
- # print opts
96
- # puts
97
-
98
- type_definition = {
99
- type: PREDICATE_TYPES[type],
100
- required: opts.fetch(:required),
101
- @config.nullable_type => opts.fetch(:nullable, false)
102
- }
103
-
104
- type_definition[:array] = opts[:array] if opts[:array]
105
-
106
- keys[opts[:key]] = type_definition
107
- elsif name.equal?(:included_in?)
108
- type += [nil] if opts.fetch(:nullable, false)
109
- keys[opts[:key]][:enum] = type
110
- end
111
- end
112
-
113
- def visit_and(node, opts = {})
114
- left, right = node
115
-
116
- visit(left, opts)
117
- visit(right, opts)
118
- end
119
-
120
- def visit_enum(node, opts = {})
121
- visit(node[0], opts)
122
- end
123
-
124
- def visit_sum(node, opts = {})
125
- if node[0][0].equal?(:constrained)
126
- opts[:nullable] = true if node[0][1][0][1][0].equal?(NilClass)
127
- visit(node[1], opts) # ignore NilClass constrained
128
- elsif node[0][0].equal?(:struct) || node[0][0].equal?(:sum)
129
- opts[:oneOf] = true
130
- node.each { |child| visit(child, opts) unless child.is_a?(Hash) }
131
- end
132
- end
133
-
134
- def visit_struct(node, opts = {})
135
- opts[:member] = true
136
-
137
- visit(node[1], opts)
138
- end
139
-
140
- def visit_array(node, opts = {})
141
- opts[:array] = true
142
- visit(node[0], opts)
143
- end
144
-
145
- def to_swagger
146
- DocumentationGenerator.new(@config).generate_documentation(keys)
147
- end
148
- end
149
- end
150
- end