dry-swagger 0.5.1 → 0.6.2
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/.gitignore +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +4 -1
- data/README.md +226 -240
- data/lib/dry/swagger.rb +3 -0
- data/lib/dry/swagger/contract_parser.rb +2 -12
- data/lib/dry/swagger/documentation_generator.rb +68 -61
- data/lib/dry/swagger/errors/missing_hash_schema_error.rb +1 -1
- data/lib/dry/swagger/errors/missing_type_error.rb +1 -1
- data/lib/dry/swagger/railtie.rb +15 -0
- data/lib/dry/swagger/struct_parser.rb +2 -3
- data/lib/dry/swagger/tasks/configuration_generator.rake +49 -0
- data/lib/dry/swagger/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b26879187416eeb9a9bafee3cb7f7cfc11cf507b7c9684fc8415f12ed246bfd
|
4
|
+
data.tar.gz: dea3839fce17641081fc569c29f32d758eccb5bfe2b3e9139e35b9495104be47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1526dbb96d90dfa3631d92289e861d66af20bd7709a4e79d214275699e611f22739e660ea1ec4a3a7c93eb19bf92141d8dd2e5fce4f177567db50a07a6b3d37
|
7
|
+
data.tar.gz: 0a51759965cd85fd48a5177ddb68b8999a3b2b63eb6d8108e4b6d39ae07696b9b46cc095ff01f470fb413b956196c94a9d7655eb7cc1d64419dfcb6268d9ea84
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dry-swagger (0.
|
4
|
+
dry-swagger (0.6.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -46,6 +46,8 @@ GEM
|
|
46
46
|
dry-equalizer (~> 0.2)
|
47
47
|
dry-initializer (~> 3.0)
|
48
48
|
dry-schema (~> 1.5, >= 1.5.2)
|
49
|
+
i18n (1.8.10)
|
50
|
+
concurrent-ruby (~> 1.0)
|
49
51
|
ice_nine (0.11.2)
|
50
52
|
rake (12.3.3)
|
51
53
|
rspec (3.10.0)
|
@@ -69,6 +71,7 @@ DEPENDENCIES
|
|
69
71
|
dry-struct
|
70
72
|
dry-swagger!
|
71
73
|
dry-validation
|
74
|
+
i18n
|
72
75
|
rake (~> 12.0)
|
73
76
|
rspec (~> 3.0)
|
74
77
|
|
data/README.md
CHANGED
@@ -15,269 +15,269 @@ And then execute:
|
|
15
15
|
|
16
16
|
bundle install
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
gem install dry-swagger
|
21
|
-
|
22
|
-
## Usage
|
23
|
-
## Dry::Validation::Contract
|
24
|
-
class Contract < Dry::Validation::Contract
|
25
|
-
json do
|
26
|
-
required(:required_field).value(:str?)
|
27
|
-
required(:required_nullable_field).maybe(:str?)
|
28
|
-
required(:required_filled_field).filled(:str?)
|
29
|
-
|
30
|
-
optional(:optional_field).value(:str?)
|
31
|
-
optional(:optional_nullable_field).maybe(:str?)
|
32
|
-
optional(:optional_filled_field).filled(:str?)
|
33
|
-
end
|
34
|
-
end
|
18
|
+
After installing, execute the following command:
|
35
19
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
},
|
56
|
-
"optional_nullable_field": {
|
57
|
-
"type": "string",
|
58
|
-
"nullable": true
|
59
|
-
},
|
60
|
-
"optional_filled_field": {
|
61
|
-
"type": "string",
|
62
|
-
"nullable": false
|
63
|
-
}
|
64
|
-
},
|
65
|
-
"required": [
|
66
|
-
"required_field",
|
67
|
-
"required_nullable_field",
|
68
|
-
"required_filled_field"
|
69
|
-
]
|
70
|
-
}
|
71
|
-
#### With nested fields - hash or array
|
72
|
-
class Contract < Dry::Validation::Contract
|
73
|
-
json do
|
74
|
-
required(:array_field).array(:int?)
|
75
|
-
required(:array_of_hash).array(:hash) do
|
76
|
-
required(:field).value(:str?)
|
77
|
-
end
|
78
|
-
required(:hash_field).hash do
|
79
|
-
required(:field).value(:str?)
|
20
|
+
rake dry-swagger:install
|
21
|
+
|
22
|
+
This will generate configuration files in your project under `project/config`. See Configuration section for more details.
|
23
|
+
|
24
|
+
##Usage
|
25
|
+
|
26
|
+
####With Dry::Validation::Contract
|
27
|
+
Lets say we have the following Dry::Validation::Contract definition:
|
28
|
+
|
29
|
+
class TestContract < Dry::Validation::Contract
|
30
|
+
params do
|
31
|
+
required(:some_field).value(:str?, min_size?: 5, max_size?: 10)
|
32
|
+
required(:some_array_of_objects).array(:hash) do
|
33
|
+
required(:some_nested_attribute).value(:str?)
|
34
|
+
end
|
35
|
+
required(:some_array_of_integers).array(:int?)
|
36
|
+
required(:dto).value(:hash) do
|
37
|
+
optional(:some_nested_attribute).maybe(:str?)
|
38
|
+
end
|
80
39
|
end
|
81
|
-
end
|
82
40
|
end
|
83
41
|
|
84
|
-
Dry::Swagger::ContractParser.new
|
85
|
-
=> {
|
86
|
-
"type": "object",
|
87
|
-
"properties": {
|
88
|
-
"array_field": {
|
89
|
-
"type": "array",
|
90
|
-
"items": {
|
91
|
-
"type": "integer"
|
92
|
-
}
|
93
|
-
},
|
94
|
-
"array_of_hash": {
|
95
|
-
"type": "array",
|
96
|
-
"items": {
|
97
|
-
"type": "object",
|
98
|
-
"properties": {
|
99
|
-
"field": {
|
100
|
-
"type": "string",
|
101
|
-
"x-nullable": false
|
102
|
-
}
|
103
|
-
},
|
104
|
-
"required": [
|
105
|
-
"field"
|
106
|
-
]
|
107
|
-
}
|
108
|
-
},
|
109
|
-
"hash_field": {
|
110
|
-
"type": "object",
|
111
|
-
"properties": {
|
112
|
-
"field": {
|
113
|
-
"type": "string",
|
114
|
-
"x-nullable": false
|
115
|
-
}
|
116
|
-
},
|
117
|
-
"required": [
|
118
|
-
"field"
|
119
|
-
]
|
120
|
-
}
|
121
|
-
},
|
122
|
-
"required": [
|
123
|
-
"array_field",
|
124
|
-
"array_of_hash",
|
125
|
-
"hash_field"
|
126
|
-
]
|
127
|
-
}
|
42
|
+
parser = Dry::Swagger::ContractParser.new
|
128
43
|
|
129
|
-
|
130
|
-
class DTO < Dry::Struct
|
131
|
-
attribute :required_string, Types::String
|
132
|
-
attribute :required_nullable_string, Types::String.optional
|
133
|
-
attribute :required_string_with_enum, Types::String.enum('enum1')
|
134
|
-
attribute? :optional_string, Types::String
|
135
|
-
attribute? :optional_nullable_string, Types::String.optional
|
136
|
-
end
|
44
|
+
`parser.call(TestContract)` will set the `keys` of the `parser` object to:
|
137
45
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
"enum1"
|
154
|
-
],
|
155
|
-
"x-nullable": false
|
156
|
-
},
|
157
|
-
"optional_string": {
|
158
|
-
"type": "string",
|
159
|
-
"x-nullable": false
|
160
|
-
},
|
161
|
-
"optional_nullable_string": {
|
162
|
-
"type": "string",
|
163
|
-
"x-nullable": true
|
164
|
-
}
|
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
|
+
}
|
165
61
|
},
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
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:
|
186
96
|
|
187
|
-
|
188
|
-
=> {
|
97
|
+
{
|
189
98
|
"type": "object",
|
190
99
|
"properties": {
|
191
|
-
"
|
192
|
-
"type": "
|
193
|
-
"
|
194
|
-
"type": "integer"
|
195
|
-
},
|
100
|
+
"some_field": {
|
101
|
+
"type": "string",
|
102
|
+
"description": "Minimum size: 5, Maximum size: 10",
|
196
103
|
"x-nullable": false
|
197
104
|
},
|
198
|
-
"
|
105
|
+
"some_array_of_objects": {
|
199
106
|
"type": "array",
|
200
107
|
"items": {
|
201
108
|
"type": "object",
|
202
109
|
"properties": {
|
203
|
-
"
|
204
|
-
"type": "string",
|
205
|
-
"x-nullable": false
|
206
|
-
},
|
207
|
-
"required_nullable_string": {
|
208
|
-
"type": "string",
|
209
|
-
"x-nullable": true
|
210
|
-
},
|
211
|
-
"required_string_with_enum": {
|
212
|
-
"type": "string",
|
213
|
-
"enum": [
|
214
|
-
"enum1"
|
215
|
-
],
|
216
|
-
"x-nullable": false
|
217
|
-
},
|
218
|
-
"optional_string": {
|
110
|
+
"some_nested_attribute": {
|
219
111
|
"type": "string",
|
220
112
|
"x-nullable": false
|
221
|
-
},
|
222
|
-
"optional_nullable_string": {
|
223
|
-
"type": "string",
|
224
|
-
"x-nullable": true
|
225
113
|
}
|
226
114
|
},
|
227
115
|
"required": [
|
228
|
-
"
|
229
|
-
|
230
|
-
|
231
|
-
|
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
|
232
127
|
},
|
233
128
|
"x-nullable": false
|
234
129
|
},
|
235
130
|
"dto": {
|
236
131
|
"type": "object",
|
237
132
|
"properties": {
|
238
|
-
"
|
239
|
-
"type": "string",
|
240
|
-
"x-nullable": false
|
241
|
-
},
|
242
|
-
"required_nullable_string": {
|
243
|
-
"type": "string",
|
244
|
-
"x-nullable": true
|
245
|
-
},
|
246
|
-
"required_string_with_enum": {
|
247
|
-
"type": "string",
|
248
|
-
"enum": [
|
249
|
-
"enum1"
|
250
|
-
],
|
251
|
-
"x-nullable": false
|
252
|
-
},
|
253
|
-
"optional_string": {
|
254
|
-
"type": "string",
|
255
|
-
"x-nullable": false
|
256
|
-
},
|
257
|
-
"optional_nullable_string": {
|
133
|
+
"some_nested_attribute": {
|
258
134
|
"type": "string",
|
259
135
|
"x-nullable": true
|
260
136
|
}
|
261
137
|
},
|
262
138
|
"required": [
|
263
|
-
|
264
|
-
"required_nullable_string",
|
265
|
-
"required_string_with_enum"
|
139
|
+
|
266
140
|
],
|
267
141
|
"x-nullable": false
|
268
142
|
}
|
269
143
|
},
|
270
144
|
"required": [
|
271
|
-
"
|
272
|
-
"
|
145
|
+
"some_field",
|
146
|
+
"some_array_of_objects",
|
147
|
+
"some_array_of_integers",
|
273
148
|
"dto"
|
274
149
|
]
|
275
150
|
}
|
276
|
-
## Overriding fields on run time
|
277
|
-
You can also modify the fields during runtime by passing a block after the .call() method.
|
278
151
|
|
279
|
-
|
152
|
+
####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
|
+
class DTO1 < Dry::Struct
|
165
|
+
attribute :dto1_field, Types::String
|
166
|
+
end
|
167
|
+
|
168
|
+
class DTO2 < Dry::Struct
|
169
|
+
attribute :dto2_field, Types::String
|
170
|
+
end
|
171
|
+
|
172
|
+
class DTO < Dry::Struct
|
173
|
+
attribute :dynamic_dto, DTO1 | DTO2
|
174
|
+
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
|
+
|
207
|
+
Calling `parser.to_swagger` will give the following result:
|
280
208
|
|
209
|
+
{
|
210
|
+
"type": "object",
|
211
|
+
"properties": {
|
212
|
+
"dynamic_dto": {
|
213
|
+
"type": "object",
|
214
|
+
"properties": {
|
215
|
+
"definition_1": {
|
216
|
+
"type": "object",
|
217
|
+
"properties": {
|
218
|
+
"dto1_field": {
|
219
|
+
"type": "string",
|
220
|
+
"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",
|
233
|
+
"x-nullable": false
|
234
|
+
}
|
235
|
+
},
|
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",
|
249
|
+
"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",
|
262
|
+
"x-nullable": false
|
263
|
+
}
|
264
|
+
},
|
265
|
+
"required": [
|
266
|
+
"dto2_field"
|
267
|
+
],
|
268
|
+
"x-nullable": false
|
269
|
+
}
|
270
|
+
]
|
271
|
+
}
|
272
|
+
},
|
273
|
+
"required": [
|
274
|
+
"dynamic_dto"
|
275
|
+
]
|
276
|
+
}
|
277
|
+
|
278
|
+
## Overriding fields
|
279
|
+
You can also modify the fields by passing a block after the .call() method.
|
280
|
+
|
281
281
|
Dry::Swagger::StructParser.new.call(DTO) do |it|
|
282
282
|
# types = string/integer/hash/array
|
283
283
|
|
@@ -311,26 +311,12 @@ For example:
|
|
311
311
|
}
|
312
312
|
|
313
313
|
end.to_swagger()
|
314
|
-
## Custom Configuration For Your Project
|
315
|
-
You can override default configurations by creating a file in config/initializers/dry-swagger.rb and changing the following values.
|
316
|
-
|
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
314
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
config.nullable_type = :"x-nullable" / :nullable
|
331
|
-
end
|
332
|
-
|
333
|
-
By default, all these settings are true, and nullable_type is :"x-nullable".
|
315
|
+
##Custom Configuration For Your Project
|
316
|
+
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.
|
317
|
+
|
318
|
+
To modify the descriptions for the Contracts, modify the values in `config/locale/dry-swagger.yml`.
|
319
|
+
|
334
320
|
## Development
|
335
321
|
|
336
322
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/dry/swagger.rb
CHANGED
@@ -7,8 +7,11 @@ require 'dry/swagger/errors/missing_type_error'
|
|
7
7
|
require 'dry/swagger/config/configuration'
|
8
8
|
require 'dry/swagger/config/contract_configuration'
|
9
9
|
require 'dry/swagger/config/struct_configuration'
|
10
|
+
require 'i18n'
|
10
11
|
|
11
12
|
module Dry
|
12
13
|
module Swagger
|
14
|
+
::I18n.load_path << Dir[File.expand_path("config/locales") + "/*.yml"]
|
15
|
+
require 'my_gem/railtie' if defined?(Rails)
|
13
16
|
end
|
14
17
|
end
|
@@ -116,18 +116,8 @@ module Dry
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
-
def predicate_description(name,
|
120
|
-
|
121
|
-
when 'eql?' then "Must be equal to #{validation}"
|
122
|
-
when 'max_size?' then "Maximum size: #{validation}"
|
123
|
-
when 'min_size?' then "Minimum size: #{validation}"
|
124
|
-
when 'gteq?' then "Greater or equal #{validation}"
|
125
|
-
when 'gt?' then "Greater than #{validation}"
|
126
|
-
when 'lt?' then "Lower than #{validation}"
|
127
|
-
when 'lteq?' then "Lower than or equal to #{validation}"
|
128
|
-
else
|
129
|
-
''
|
130
|
-
end
|
119
|
+
def predicate_description(name, value)
|
120
|
+
::I18n.t("contract.descriptions.#{name}", value: value, default: '')
|
131
121
|
end
|
132
122
|
|
133
123
|
def to_swagger
|
@@ -17,83 +17,90 @@ module Dry
|
|
17
17
|
|
18
18
|
def generate_documentation(fields)
|
19
19
|
documentation = { properties: {}, required: [] }
|
20
|
-
fields.each do |field_name,
|
21
|
-
documentation[:properties][field_name] = generate_field_properties(
|
22
|
-
if
|
23
|
-
documentation[:required] << field_name if
|
20
|
+
fields.each do |field_name, definition|
|
21
|
+
documentation[:properties][field_name] = generate_field_properties(definition)
|
22
|
+
if definition.is_a?(Hash)
|
23
|
+
documentation[:required] << field_name if definition.fetch(:required, true) && @config.enable_required_validation
|
24
24
|
else
|
25
|
-
documentation[:required] << field_name if
|
25
|
+
documentation[:required] << field_name if definition[0].fetch(:required, true) && @config.enable_required_validation
|
26
26
|
end
|
27
27
|
|
28
28
|
rescue Errors::MissingTypeError => e
|
29
|
-
raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys,
|
29
|
+
raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys, definition: definition }
|
30
30
|
rescue Errors::MissingHashSchemaError => e
|
31
|
-
raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys,
|
31
|
+
raise StandardError.new e.message % { field_name: field_name, valid_types: SWAGGER_FIELD_TYPE_DEFINITIONS.keys, definition: definition }
|
32
32
|
end
|
33
33
|
|
34
34
|
{ :type => :object, :properties => documentation[:properties], :required => documentation[:required] }
|
35
35
|
end
|
36
36
|
|
37
|
-
def generate_field_properties(
|
38
|
-
if
|
39
|
-
properties = {}
|
40
|
-
attributes_hash.each_with_index do |_, index|
|
41
|
-
properties["definition_#{index + 1}"] = generate_field_properties(attributes_hash[index])
|
42
|
-
end
|
43
|
-
if attributes_hash[0][:type] == 'array'
|
44
|
-
attributes_hash.each { |definition| definition[:type] = 'hash'}
|
45
|
-
{
|
46
|
-
type: :array,
|
47
|
-
items: {
|
48
|
-
type: :object,
|
49
|
-
properties: properties,
|
50
|
-
oneOf: attributes_hash.map{ |it| generate_field_properties(it) },
|
51
|
-
example: 'Dynamic Field. See Model Definitions'
|
52
|
-
},
|
53
|
-
}
|
54
|
-
else
|
55
|
-
{
|
56
|
-
oneOf: attributes_hash.map{ |it| generate_field_properties(it) },
|
57
|
-
type: :object,
|
58
|
-
properties: properties,
|
59
|
-
example: 'Dynamic Field. See Model Definitions'
|
60
|
-
}
|
61
|
-
end
|
62
|
-
else
|
63
|
-
if attributes_hash[:type] == 'array'
|
64
|
-
items = generate_documentation(attributes_hash.fetch(:keys))
|
65
|
-
items = @config.enable_nullable_validation ?
|
66
|
-
items.merge(@config.nullable_type => attributes_hash.fetch(@config.nullable_type, false)) :
|
67
|
-
items.merge(@config.nullable_type => true)
|
68
|
-
documentation = { type: :array, items: items }
|
69
|
-
elsif attributes_hash[:array] && attributes_hash.fetch(:type) != 'array'
|
70
|
-
items = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(attributes_hash.fetch(:type))
|
71
|
-
items = @config.enable_nullable_validation ?
|
72
|
-
items.merge(@config.nullable_type => attributes_hash.fetch(@config.nullable_type, false)) :
|
73
|
-
items.merge(@config.nullable_type => true)
|
74
|
-
documentation = { type: :array, items: items }
|
75
|
-
elsif attributes_hash[:type] == 'hash'
|
76
|
-
raise Errors::MissingHashSchemaError.new unless attributes_hash[:keys]
|
77
|
-
documentation = generate_documentation(attributes_hash.fetch(:keys))
|
78
|
-
else
|
79
|
-
documentation = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(attributes_hash.fetch(:type))
|
80
|
-
if attributes_hash[:enum] && @config.enable_enums
|
81
|
-
documentation = documentation.merge(enum: attributes_hash.fetch(:enum))
|
82
|
-
end
|
83
|
-
|
84
|
-
if attributes_hash[:description] && @config.enable_descriptions
|
85
|
-
documentation = documentation.merge(description: attributes_hash.fetch(:description))
|
86
|
-
end
|
87
|
-
end
|
37
|
+
def generate_field_properties(definition)
|
38
|
+
return generate_for_sti_type(definition) if definition.is_a?(Array)
|
88
39
|
|
89
|
-
|
90
|
-
|
91
|
-
|
40
|
+
if definition[:type] == 'array' || definition[:array]
|
41
|
+
documentation = generate_for_array(definition)
|
42
|
+
elsif definition[:type] == 'hash'
|
43
|
+
documentation = generate_for_hash(definition)
|
44
|
+
else
|
45
|
+
documentation = generate_for_primitive_type(definition)
|
92
46
|
end
|
47
|
+
@config.enable_nullable_validation ?
|
48
|
+
documentation.merge(@config.nullable_type => definition.fetch(@config.nullable_type, false)) :
|
49
|
+
documentation.merge(@config.nullable_type => true)
|
93
50
|
|
94
51
|
rescue KeyError
|
95
52
|
raise Errors::MissingTypeError.new
|
96
53
|
end
|
54
|
+
|
55
|
+
def generate_for_sti_type(definition)
|
56
|
+
properties = {}
|
57
|
+
|
58
|
+
definition.each_with_index do |_, index|
|
59
|
+
properties["definition_#{index + 1}"] = generate_field_properties(definition[index])
|
60
|
+
end
|
61
|
+
|
62
|
+
documentation = {
|
63
|
+
type: :object,
|
64
|
+
properties: properties,
|
65
|
+
example: 'Dynamic Field. See Model Definitions'
|
66
|
+
}
|
67
|
+
|
68
|
+
if definition[0][:type] == 'array'
|
69
|
+
definition.each { |it| it[:type] = 'hash'}
|
70
|
+
documentation[:oneOf] = definition.map{ |it| generate_field_properties(it) }
|
71
|
+
{ type: :array, items: documentation }
|
72
|
+
else
|
73
|
+
documentation[:oneOf] = definition.map{ |it| generate_field_properties(it) }
|
74
|
+
documentation
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate_for_array(definition)
|
79
|
+
items = array_of_primitive_type?(definition) ?
|
80
|
+
SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(definition.fetch(:type)) :
|
81
|
+
generate_documentation(definition.fetch(:keys))
|
82
|
+
items = @config.enable_nullable_validation ?
|
83
|
+
items.merge(@config.nullable_type => definition.fetch(@config.nullable_type, false)) :
|
84
|
+
items.merge(@config.nullable_type => true)
|
85
|
+
{ type: :array, items: items }
|
86
|
+
end
|
87
|
+
|
88
|
+
def generate_for_hash(definition)
|
89
|
+
raise Errors::MissingHashSchemaError.new unless definition[:keys]
|
90
|
+
generate_documentation(definition.fetch(:keys))
|
91
|
+
end
|
92
|
+
|
93
|
+
def generate_for_primitive_type(definition)
|
94
|
+
documentation = SWAGGER_FIELD_TYPE_DEFINITIONS.fetch(definition.fetch(:type))
|
95
|
+
documentation = documentation.merge(enum: definition.fetch(:enum)) if definition[:enum] && @config.enable_enums
|
96
|
+
documentation = documentation.merge(description: definition.fetch(:description)) if definition[:description] &&
|
97
|
+
@config.enable_descriptions
|
98
|
+
documentation
|
99
|
+
end
|
100
|
+
|
101
|
+
def array_of_primitive_type?(definition)
|
102
|
+
definition[:array] && definition.fetch(:type) != 'array'
|
103
|
+
end
|
97
104
|
end
|
98
105
|
end
|
99
106
|
end
|
@@ -6,7 +6,7 @@ module Dry
|
|
6
6
|
"Could not generate documentation for field %{field_name}. The field is defined as hash,
|
7
7
|
but the schema is not defined.
|
8
8
|
Valid types are: %{valid_types}.
|
9
|
-
The parser has generated the following definition for the field: %{field_name}: %{
|
9
|
+
The parser has generated the following definition for the field: %{field_name}: %{definition}
|
10
10
|
"
|
11
11
|
end
|
12
12
|
end
|
@@ -6,7 +6,7 @@ module Dry
|
|
6
6
|
"Could not generate documentation for field %{field_name}. The field is missing a type.
|
7
7
|
If the field you have defined is an array, you must specify the type of the elements in that array.
|
8
8
|
Valid types are: %{valid_types}.
|
9
|
-
The parser has generated the following definition for the field: %{field_name}: %{
|
9
|
+
The parser has generated the following definition for the field: %{field_name}: %{definition}.
|
10
10
|
"
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'dry/swagger'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module Dry
|
5
|
+
module Swagger
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
railtie_name :my_gem
|
8
|
+
|
9
|
+
rake_tasks do
|
10
|
+
path = File.expand_path(__dir__)
|
11
|
+
Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -119,10 +119,9 @@ module Dry
|
|
119
119
|
if node[0][0].equal?(:constrained)
|
120
120
|
opts[:nullable] = true
|
121
121
|
visit(node[1], opts) # ignore NilClass constrained
|
122
|
-
elsif node[0][0].equal?(:struct)
|
122
|
+
elsif node[0][0].equal?(:struct) || node[0][0].equal?(:sum)
|
123
123
|
opts[:oneOf] = true
|
124
|
-
visit(
|
125
|
-
visit(node[1], opts)
|
124
|
+
node.each { |child| visit(child, opts) unless child.is_a?(Hash) }
|
126
125
|
end
|
127
126
|
end
|
128
127
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
namespace 'dry-swagger' do
|
4
|
+
desc 'Create a configuration file for Struct and Contract'
|
5
|
+
task :create_configuration_file do
|
6
|
+
FileUtils.mkdir_p "#{ Dir.pwd }/config/initializers/"
|
7
|
+
File.open("#{ Dir.pwd }/config/initializers/dry-swagger.rb", "w") { |file|
|
8
|
+
file.puts 'Dry::Swagger::Config::StructConfiguration.configuration do |config|
|
9
|
+
config.enable_required_validation = true
|
10
|
+
config.enable_nullable_validation = true
|
11
|
+
config.enable_enums = true
|
12
|
+
config.enable_descriptions = true
|
13
|
+
config.nullable_type = :"x-nullable" # or :nullable
|
14
|
+
end
|
15
|
+
|
16
|
+
Dry::Swagger::Config::ContractConfiguration.configuration do |config|
|
17
|
+
config.enable_required_validation = true
|
18
|
+
config.enable_nullable_validation = true
|
19
|
+
config.enable_enums = true
|
20
|
+
config.enable_descriptions = true
|
21
|
+
config.nullable_type = :"x-nullable" # or :nullable
|
22
|
+
end'
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Create a YAML file for Contract swagger field descriptions'
|
27
|
+
task :create_contract_descriptions_yaml do
|
28
|
+
FileUtils.mkdir_p "#{ Dir.pwd }/config/locales/"
|
29
|
+
File.open("#{ Dir.pwd }/config/locales/dry-swagger.yml", "w") { |file|
|
30
|
+
file.puts 'en:
|
31
|
+
contract:
|
32
|
+
descriptions:
|
33
|
+
eql?: "Must be equal to %{value}"
|
34
|
+
max_size?: "Maximum size: %{value}"
|
35
|
+
min_size?: "Minimum size: %{value}"
|
36
|
+
gteq?: "Greater than or equal to %{value}"
|
37
|
+
gt?: "Greater than %{value}"
|
38
|
+
lt?: "Lower than %{value}"
|
39
|
+
lteq?: "Lower than or equal to %{value}"
|
40
|
+
'
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
desc 'Creates configuration files'
|
45
|
+
task :install do
|
46
|
+
Rake::Task['dry-swagger:create_configuration_file'].execute
|
47
|
+
Rake::Task['dry-swagger:create_contract_descriptions_yaml'].execute
|
48
|
+
end
|
49
|
+
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.6.2
|
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-08-
|
11
|
+
date: 2021-08-06 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
|
@@ -39,7 +39,9 @@ files:
|
|
39
39
|
- lib/dry/swagger/documentation_generator.rb
|
40
40
|
- lib/dry/swagger/errors/missing_hash_schema_error.rb
|
41
41
|
- lib/dry/swagger/errors/missing_type_error.rb
|
42
|
+
- lib/dry/swagger/railtie.rb
|
42
43
|
- lib/dry/swagger/struct_parser.rb
|
44
|
+
- lib/dry/swagger/tasks/configuration_generator.rake
|
43
45
|
- lib/dry/swagger/types.rb
|
44
46
|
- lib/dry/swagger/version.rb
|
45
47
|
homepage: https://github.com/Jane-Terziev/dry-swagger
|