gitlab-grape-swagger 1.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 +7 -0
- data/.coveralls.yml +1 -0
- data/.github/dependabot.yml +20 -0
- data/.github/workflows/ci.yml +45 -0
- data/.gitignore +44 -0
- data/.gitlab-ci.yml +19 -0
- data/.rspec +3 -0
- data/.rubocop.yml +136 -0
- data/.rubocop_todo.yml +60 -0
- data/.ruby-gemset +1 -0
- data/CHANGELOG.md +671 -0
- data/CONTRIBUTING.md +126 -0
- data/Dangerfile +3 -0
- data/Gemfile +45 -0
- data/Gemfile.lock +249 -0
- data/LICENSE.txt +20 -0
- data/README.md +1772 -0
- data/RELEASING.md +82 -0
- data/Rakefile +20 -0
- data/UPGRADING.md +201 -0
- data/example/api/endpoints.rb +131 -0
- data/example/api/entities.rb +18 -0
- data/example/config.ru +42 -0
- data/example/example_requests.postman_collection +146 -0
- data/example/splines.png +0 -0
- data/example/swagger-example.png +0 -0
- data/grape-swagger.gemspec +23 -0
- data/lib/grape-swagger/doc_methods/build_model_definition.rb +68 -0
- data/lib/grape-swagger/doc_methods/data_type.rb +110 -0
- data/lib/grape-swagger/doc_methods/extensions.rb +101 -0
- data/lib/grape-swagger/doc_methods/file_params.rb +17 -0
- data/lib/grape-swagger/doc_methods/format_data.rb +53 -0
- data/lib/grape-swagger/doc_methods/headers.rb +20 -0
- data/lib/grape-swagger/doc_methods/move_params.rb +209 -0
- data/lib/grape-swagger/doc_methods/operation_id.rb +32 -0
- data/lib/grape-swagger/doc_methods/optional_object.rb +30 -0
- data/lib/grape-swagger/doc_methods/parse_params.rb +190 -0
- data/lib/grape-swagger/doc_methods/path_string.rb +52 -0
- data/lib/grape-swagger/doc_methods/produces_consumes.rb +15 -0
- data/lib/grape-swagger/doc_methods/status_codes.rb +21 -0
- data/lib/grape-swagger/doc_methods/tag_name_description.rb +34 -0
- data/lib/grape-swagger/doc_methods/version.rb +20 -0
- data/lib/grape-swagger/doc_methods.rb +142 -0
- data/lib/grape-swagger/endpoint/params_parser.rb +76 -0
- data/lib/grape-swagger/endpoint.rb +476 -0
- data/lib/grape-swagger/errors.rb +17 -0
- data/lib/grape-swagger/instance.rb +7 -0
- data/lib/grape-swagger/model_parsers.rb +42 -0
- data/lib/grape-swagger/rake/oapi_tasks.rb +135 -0
- data/lib/grape-swagger/version.rb +5 -0
- data/lib/grape-swagger.rb +174 -0
- data/spec/issues/267_nested_namespaces.rb +55 -0
- data/spec/issues/403_versions_spec.rb +124 -0
- data/spec/issues/427_entity_as_string_spec.rb +39 -0
- data/spec/issues/430_entity_definitions_spec.rb +94 -0
- data/spec/issues/532_allow_custom_format_spec.rb +42 -0
- data/spec/issues/533_specify_status_code_spec.rb +78 -0
- data/spec/issues/537_enum_values_spec.rb +50 -0
- data/spec/issues/539_array_post_body_spec.rb +65 -0
- data/spec/issues/542_array_of_type_in_post_body_spec.rb +46 -0
- data/spec/issues/553_align_array_put_post_params_spec.rb +152 -0
- data/spec/issues/572_array_post_body_spec.rb +51 -0
- data/spec/issues/579_align_put_post_parameters_spec.rb +185 -0
- data/spec/issues/582_file_response_spec.rb +55 -0
- data/spec/issues/587_range_parameter_delimited_by_dash_spec.rb +26 -0
- data/spec/issues/605_root_route_documentation_spec.rb +23 -0
- data/spec/issues/650_params_array_spec.rb +65 -0
- data/spec/issues/677_consumes_produces_add_swagger_documentation_options_spec.rb +100 -0
- data/spec/issues/680_keep_204_error_schemas_spec.rb +55 -0
- data/spec/issues/721_set_default_parameter_location_based_on_consumes_spec.rb +62 -0
- data/spec/issues/751_deeply_nested_objects_spec.rb +190 -0
- data/spec/issues/776_multiple_presents_spec.rb +59 -0
- data/spec/issues/784_extensions_on_params_spec.rb +42 -0
- data/spec/issues/809_utf8_routes_spec.rb +55 -0
- data/spec/issues/832_array_hash_float_decimal_spec.rb +114 -0
- data/spec/issues/847_route_param_options_spec.rb +37 -0
- data/spec/issues/873_wildcard_segments_path_parameters_spec.rb +28 -0
- data/spec/issues/878_optional_path_segments_spec.rb +29 -0
- data/spec/issues/881_handle_file_params_spec.rb +38 -0
- data/spec/issues/883_query_array_parameter_spec.rb +46 -0
- data/spec/issues/884_dont_document_non_schema_examples_spec.rb +49 -0
- data/spec/issues/887_prevent_duplicate_operation_ids_spec.rb +35 -0
- data/spec/lib/data_type_spec.rb +111 -0
- data/spec/lib/endpoint/params_parser_spec.rb +124 -0
- data/spec/lib/endpoint_spec.rb +153 -0
- data/spec/lib/extensions_spec.rb +185 -0
- data/spec/lib/format_data_spec.rb +115 -0
- data/spec/lib/model_parsers_spec.rb +104 -0
- data/spec/lib/move_params_spec.rb +444 -0
- data/spec/lib/oapi_tasks_spec.rb +163 -0
- data/spec/lib/operation_id_spec.rb +55 -0
- data/spec/lib/optional_object_spec.rb +47 -0
- data/spec/lib/parse_params_spec.rb +68 -0
- data/spec/lib/path_string_spec.rb +101 -0
- data/spec/lib/produces_consumes_spec.rb +116 -0
- data/spec/lib/tag_name_description_spec.rb +80 -0
- data/spec/lib/version_spec.rb +28 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/empty_model_parser.rb +23 -0
- data/spec/support/grape_version.rb +13 -0
- data/spec/support/mock_parser.rb +23 -0
- data/spec/support/model_parsers/entity_parser.rb +334 -0
- data/spec/support/model_parsers/mock_parser.rb +346 -0
- data/spec/support/model_parsers/representable_parser.rb +406 -0
- data/spec/support/namespace_tags.rb +93 -0
- data/spec/support/the_paths_definitions.rb +109 -0
- data/spec/swagger_v2/api_documentation_spec.rb +42 -0
- data/spec/swagger_v2/api_swagger_v2_additional_properties_spec.rb +83 -0
- data/spec/swagger_v2/api_swagger_v2_body_definitions_spec.rb +48 -0
- data/spec/swagger_v2/api_swagger_v2_definitions-models_spec.rb +36 -0
- data/spec/swagger_v2/api_swagger_v2_detail_spec.rb +79 -0
- data/spec/swagger_v2/api_swagger_v2_extensions_spec.rb +145 -0
- data/spec/swagger_v2/api_swagger_v2_format-content_type_spec.rb +137 -0
- data/spec/swagger_v2/api_swagger_v2_global_configuration_spec.rb +56 -0
- data/spec/swagger_v2/api_swagger_v2_hash_and_array_spec.rb +64 -0
- data/spec/swagger_v2/api_swagger_v2_headers_spec.rb +58 -0
- data/spec/swagger_v2/api_swagger_v2_hide_documentation_path_spec.rb +57 -0
- data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +109 -0
- data/spec/swagger_v2/api_swagger_v2_ignore_defaults_spec.rb +48 -0
- data/spec/swagger_v2/api_swagger_v2_mounted_spec.rb +153 -0
- data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +355 -0
- data/spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb +217 -0
- data/spec/swagger_v2/api_swagger_v2_param_type_spec.rb +247 -0
- data/spec/swagger_v2/api_swagger_v2_request_params_fix_spec.rb +80 -0
- data/spec/swagger_v2/api_swagger_v2_response_spec.rb +147 -0
- data/spec/swagger_v2/api_swagger_v2_response_with_examples_spec.rb +135 -0
- data/spec/swagger_v2/api_swagger_v2_response_with_headers_spec.rb +216 -0
- data/spec/swagger_v2/api_swagger_v2_response_with_models_spec.rb +53 -0
- data/spec/swagger_v2/api_swagger_v2_response_with_root_spec.rb +153 -0
- data/spec/swagger_v2/api_swagger_v2_spec.rb +245 -0
- data/spec/swagger_v2/api_swagger_v2_status_codes_spec.rb +93 -0
- data/spec/swagger_v2/api_swagger_v2_type-format_spec.rb +90 -0
- data/spec/swagger_v2/boolean_params_spec.rb +38 -0
- data/spec/swagger_v2/default_api_spec.rb +175 -0
- data/spec/swagger_v2/deprecated_field_spec.rb +25 -0
- data/spec/swagger_v2/description_not_initialized_spec.rb +39 -0
- data/spec/swagger_v2/endpoint_versioned_path_spec.rb +130 -0
- data/spec/swagger_v2/errors_spec.rb +77 -0
- data/spec/swagger_v2/float_api_spec.rb +36 -0
- data/spec/swagger_v2/form_params_spec.rb +76 -0
- data/spec/swagger_v2/grape-swagger_spec.rb +17 -0
- data/spec/swagger_v2/guarded_endpoint_spec.rb +162 -0
- data/spec/swagger_v2/hide_api_spec.rb +147 -0
- data/spec/swagger_v2/host_spec.rb +43 -0
- data/spec/swagger_v2/inheritance_and_discriminator_spec.rb +57 -0
- data/spec/swagger_v2/mount_override_api_spec.rb +58 -0
- data/spec/swagger_v2/mounted_target_class_spec.rb +76 -0
- data/spec/swagger_v2/namespace_tags_prefix_spec.rb +122 -0
- data/spec/swagger_v2/namespace_tags_spec.rb +78 -0
- data/spec/swagger_v2/namespaced_api_spec.rb +121 -0
- data/spec/swagger_v2/nicknamed_api_spec.rb +25 -0
- data/spec/swagger_v2/operation_id_api_spec.rb +27 -0
- data/spec/swagger_v2/param_multi_type_spec.rb +82 -0
- data/spec/swagger_v2/param_type_spec.rb +95 -0
- data/spec/swagger_v2/param_values_spec.rb +180 -0
- data/spec/swagger_v2/params_array_collection_format_spec.rb +105 -0
- data/spec/swagger_v2/params_array_spec.rb +225 -0
- data/spec/swagger_v2/params_example_spec.rb +38 -0
- data/spec/swagger_v2/params_hash_spec.rb +77 -0
- data/spec/swagger_v2/params_nested_spec.rb +92 -0
- data/spec/swagger_v2/parent_less_namespace_spec.rb +32 -0
- data/spec/swagger_v2/reference_entity_spec.rb +129 -0
- data/spec/swagger_v2/security_requirement_spec.rb +46 -0
- data/spec/swagger_v2/simple_mounted_api_spec.rb +332 -0
- data/spec/version_spec.rb +10 -0
- metadata +225 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'representable/json'
|
|
4
|
+
|
|
5
|
+
RSpec.shared_context 'representable swagger example' do
|
|
6
|
+
before :all do
|
|
7
|
+
module Entities
|
|
8
|
+
class Something < Representable::Decorator
|
|
9
|
+
include Representable::JSON
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
# Representable doesn't have documentation method, mock this
|
|
13
|
+
def documentation
|
|
14
|
+
{
|
|
15
|
+
id: { type: Integer, desc: 'Identity of Something' },
|
|
16
|
+
text: { type: String, desc: 'Content of something.' },
|
|
17
|
+
links: { type: 'link', is_array: true },
|
|
18
|
+
others: { type: 'text', is_array: false }
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
property :id, documentation: { type: Integer, desc: 'Identity of Something' }
|
|
24
|
+
property :text, documentation: { type: String, desc: 'Content of something.' }
|
|
25
|
+
property :links, documentation: { type: 'link', is_array: true }
|
|
26
|
+
property :others, documentation: { type: 'text', is_array: false }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class EnumValues < Representable::Decorator
|
|
30
|
+
include Representable::JSON
|
|
31
|
+
|
|
32
|
+
property :gender, documentation: { type: 'string', desc: 'Content of something.', values: %w[Male Female] }
|
|
33
|
+
property :number, documentation: { type: 'integer', desc: 'Content of something.', values: [1, 2] }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class AliasedThing < Representable::Decorator
|
|
37
|
+
include Representable::JSON
|
|
38
|
+
|
|
39
|
+
property :something, as: :post, decorator: Entities::Something, documentation: { type: 'Something', desc: 'Reference to something.' }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class FourthLevel < Representable::Decorator
|
|
43
|
+
include Representable::JSON
|
|
44
|
+
|
|
45
|
+
property :text, documentation: { type: 'string' }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class ThirdLevel < Representable::Decorator
|
|
49
|
+
include Representable::JSON
|
|
50
|
+
|
|
51
|
+
property :parts, decorator: Entities::FourthLevel, documentation: { type: 'FourthLevel' }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class SecondLevel < Representable::Decorator
|
|
55
|
+
include Representable::JSON
|
|
56
|
+
|
|
57
|
+
property :parts, decorator: Entities::ThirdLevel, documentation: { type: 'ThirdLevel' }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class FirstLevel < Representable::Decorator
|
|
61
|
+
include Representable::JSON
|
|
62
|
+
|
|
63
|
+
property :parts, decorator: Entities::SecondLevel, documentation: { type: 'SecondLevel' }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class QueryInputElement < Representable::Decorator
|
|
67
|
+
include Representable::JSON
|
|
68
|
+
|
|
69
|
+
property :key, documentation: {
|
|
70
|
+
type: String, desc: 'Name of parameter', required: true
|
|
71
|
+
}
|
|
72
|
+
property :value, documentation: {
|
|
73
|
+
type: String, desc: 'Value of parameter', required: true
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class QueryInput < Representable::Decorator
|
|
78
|
+
include Representable::JSON
|
|
79
|
+
|
|
80
|
+
property :elements, decorator: Entities::QueryInputElement, documentation: {
|
|
81
|
+
type: 'QueryInputElement',
|
|
82
|
+
desc: 'Set of configuration',
|
|
83
|
+
param_type: 'body',
|
|
84
|
+
is_array: true,
|
|
85
|
+
required: true
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class ApiError < Representable::Decorator
|
|
90
|
+
include Representable::JSON
|
|
91
|
+
|
|
92
|
+
property :code, documentation: { type: Integer, desc: 'status code' }
|
|
93
|
+
property :message, documentation: { type: String, desc: 'error message' }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
module NestedModule
|
|
97
|
+
class ApiResponse < Representable::Decorator
|
|
98
|
+
include Representable::JSON
|
|
99
|
+
|
|
100
|
+
property :status, documentation: { type: String }
|
|
101
|
+
property :error, documentation: { type: ::Entities::ApiError }
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class SecondApiError < Representable::Decorator
|
|
106
|
+
include Representable::JSON
|
|
107
|
+
|
|
108
|
+
property :code, documentation: { type: Integer }
|
|
109
|
+
property :severity, documentation: { type: String }
|
|
110
|
+
property :message, documentation: { type: String }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class ResponseItem < Representable::Decorator
|
|
114
|
+
include Representable::JSON
|
|
115
|
+
|
|
116
|
+
class << self
|
|
117
|
+
def documentation
|
|
118
|
+
{
|
|
119
|
+
id: { type: Integer },
|
|
120
|
+
name: { type: String }
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
property :id, documentation: { type: Integer }
|
|
126
|
+
property :name, documentation: { type: String }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class OtherItem < Representable::Decorator
|
|
130
|
+
include Representable::JSON
|
|
131
|
+
|
|
132
|
+
property :key, documentation: { type: Integer }
|
|
133
|
+
property :symbol, documentation: { type: String }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
class UseResponse < Representable::Decorator
|
|
137
|
+
include Representable::JSON
|
|
138
|
+
|
|
139
|
+
class << self
|
|
140
|
+
def documentation
|
|
141
|
+
{
|
|
142
|
+
:description => { type: String },
|
|
143
|
+
'$responses' => { is_array: true }
|
|
144
|
+
}
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
property :description, documentation: { type: String }
|
|
149
|
+
property :items, as: '$responses', decorator: Entities::ResponseItem, documentation: { is_array: true }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
class UseItemResponseAsType < Representable::Decorator
|
|
153
|
+
include Representable::JSON
|
|
154
|
+
|
|
155
|
+
property :description, documentation: { type: String }
|
|
156
|
+
property :responses, documentation: { type: Entities::ResponseItem, is_array: false }
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
class UseAddress < Representable::Decorator
|
|
160
|
+
include Representable::JSON
|
|
161
|
+
|
|
162
|
+
property :street, documentation: { type: String, desc: 'street' }
|
|
163
|
+
property :postcode, documentation: { type: String, desc: 'postcode' }
|
|
164
|
+
property :city, documentation: { type: String, desc: 'city' }
|
|
165
|
+
property :country, documentation: { type: String, desc: 'country' }
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
class UseNestedWithAddress < Representable::Decorator
|
|
169
|
+
include Representable::JSON
|
|
170
|
+
|
|
171
|
+
property :name, documentation: { type: String }
|
|
172
|
+
property :address, decorator: Entities::UseAddress
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
class TypedDefinition < Representable::Decorator
|
|
176
|
+
include Representable::JSON
|
|
177
|
+
|
|
178
|
+
property :prop_integer, documentation: { type: Integer, desc: 'prop_integer description' }
|
|
179
|
+
property :prop_long, documentation: { type: Numeric, desc: 'prop_long description' }
|
|
180
|
+
property :prop_float, documentation: { type: Float, desc: 'prop_float description' }
|
|
181
|
+
property :prop_double, documentation: { type: BigDecimal, desc: 'prop_double description' }
|
|
182
|
+
property :prop_string, documentation: { type: String, desc: 'prop_string description' }
|
|
183
|
+
property :prop_symbol, documentation: { type: Symbol, desc: 'prop_symbol description' }
|
|
184
|
+
property :prop_date, documentation: { type: Date, desc: 'prop_date description' }
|
|
185
|
+
property :prop_date_time, documentation: { type: DateTime, desc: 'prop_date_time description' }
|
|
186
|
+
property :prop_time, documentation: { type: Time, desc: 'prop_time description' }
|
|
187
|
+
property :prop_password, documentation: { type: 'password', desc: 'prop_password description' }
|
|
188
|
+
property :prop_email, documentation: { type: 'email', desc: 'prop_email description' }
|
|
189
|
+
property :prop_boolean, documentation: { type: Grape::API::Boolean, desc: 'prop_boolean description' }
|
|
190
|
+
property :prop_file, documentation: { type: File, desc: 'prop_file description' }
|
|
191
|
+
property :prop_json, documentation: { type: JSON, desc: 'prop_json description' }
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
class RecursiveModel < Representable::Decorator
|
|
195
|
+
include Representable::JSON
|
|
196
|
+
|
|
197
|
+
property :name, documentation: { type: String, desc: 'The name.' }
|
|
198
|
+
property :children, decorator: self, documentation: { type: 'RecursiveModel', is_array: true, desc: 'The child nodes.' }
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
class DocumentedHashAndArrayModel < Representable::Decorator
|
|
202
|
+
include Representable::JSON
|
|
203
|
+
|
|
204
|
+
property :raw_hash, documentation: { type: Hash, desc: 'Example Hash.' }
|
|
205
|
+
property :raw_array, documentation: { type: Array, desc: 'Example Array' }
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
let(:swagger_definitions_models) do
|
|
211
|
+
{
|
|
212
|
+
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } } },
|
|
213
|
+
'ResponseItem' => { 'type' => 'object', 'properties' => { 'id' => { 'description' => '', 'type' => 'integer', 'format' => 'int32' }, 'name' => { 'description' => '', 'type' => 'string' } } },
|
|
214
|
+
'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' }, 'description' => '' } } },
|
|
215
|
+
'RecursiveModel' => { 'type' => 'object', 'properties' => { 'name' => { 'type' => 'string', 'description' => 'The name.' }, 'children' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/RecursiveModel' }, 'description' => 'The child nodes.' } } }
|
|
216
|
+
}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
let(:swagger_nested_type) do
|
|
220
|
+
{
|
|
221
|
+
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' },
|
|
222
|
+
'UseItemResponseAsType' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, 'responses' => { 'description' => '', 'type' => 'ResponseItem' } }, 'description' => 'UseItemResponseAsType model' }
|
|
223
|
+
}
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
let(:swagger_entity_as_response_object) do
|
|
227
|
+
{
|
|
228
|
+
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' },
|
|
229
|
+
'ResponseItem' => { 'type' => 'object', 'properties' => { 'id' => { 'description' => '', 'type' => 'integer', 'format' => 'int32' }, 'name' => { 'description' => '', 'type' => 'string' } } },
|
|
230
|
+
'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' }, 'description' => '' } }, 'description' => 'UseResponse model' }
|
|
231
|
+
}
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
let(:swagger_params_as_response_object) do
|
|
235
|
+
{
|
|
236
|
+
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' }
|
|
237
|
+
}
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
let(:swagger_typed_defintion) do
|
|
241
|
+
{
|
|
242
|
+
'prop_boolean' => { 'description' => 'prop_boolean description', 'type' => 'boolean' },
|
|
243
|
+
'prop_date' => { 'description' => 'prop_date description', 'type' => 'string', 'format' => 'date' },
|
|
244
|
+
'prop_date_time' => { 'description' => 'prop_date_time description', 'type' => 'string', 'format' => 'date-time' },
|
|
245
|
+
'prop_double' => { 'description' => 'prop_double description', 'type' => 'number', 'format' => 'double' },
|
|
246
|
+
'prop_email' => { 'description' => 'prop_email description', 'type' => 'string', 'format' => 'email' },
|
|
247
|
+
'prop_file' => { 'description' => 'prop_file description', 'type' => 'file' },
|
|
248
|
+
'prop_float' => { 'description' => 'prop_float description', 'type' => 'number', 'format' => 'float' },
|
|
249
|
+
'prop_integer' => { 'description' => 'prop_integer description', 'type' => 'integer', 'format' => 'int32' },
|
|
250
|
+
'prop_json' => { 'description' => 'prop_json description', 'type' => 'JSON' },
|
|
251
|
+
'prop_long' => { 'description' => 'prop_long description', 'type' => 'integer', 'format' => 'int64' },
|
|
252
|
+
'prop_password' => { 'description' => 'prop_password description', 'type' => 'string', 'format' => 'password' },
|
|
253
|
+
'prop_string' => { 'description' => 'prop_string description', 'type' => 'string' },
|
|
254
|
+
'prop_symbol' => { 'description' => 'prop_symbol description', 'type' => 'string' },
|
|
255
|
+
'prop_time' => { 'description' => 'prop_time description', 'type' => 'string', 'format' => 'date-time' }
|
|
256
|
+
}
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
let(:swagger_json) do
|
|
260
|
+
{
|
|
261
|
+
'info' => {
|
|
262
|
+
'title' => 'The API title to be displayed on the API homepage.',
|
|
263
|
+
'description' => 'A description of the API.',
|
|
264
|
+
'termsOfService' => 'www.The-URL-of-the-terms-and-service.com',
|
|
265
|
+
'contact' => { 'name' => 'Contact name', 'email' => 'Contact@email.com', 'url' => 'Contact URL' },
|
|
266
|
+
'license' => { 'name' => 'The name of the license.', 'url' => 'www.The-URL-of-the-license.org' },
|
|
267
|
+
'version' => '0.0.1'
|
|
268
|
+
},
|
|
269
|
+
'swagger' => '2.0',
|
|
270
|
+
'produces' => ['application/json'],
|
|
271
|
+
'host' => 'example.org',
|
|
272
|
+
'basePath' => '/api',
|
|
273
|
+
'tags' => [
|
|
274
|
+
{ 'name' => 'other_thing', 'description' => 'Operations about other_things' },
|
|
275
|
+
{ 'name' => 'thing', 'description' => 'Operations about things' },
|
|
276
|
+
{ 'name' => 'thing2', 'description' => 'Operations about thing2s' },
|
|
277
|
+
{ 'name' => 'dummy', 'description' => 'Operations about dummies' }
|
|
278
|
+
],
|
|
279
|
+
'paths' => {
|
|
280
|
+
'/v3/other_thing/{elements}' => {
|
|
281
|
+
'get' => {
|
|
282
|
+
'description' => 'nested route inside namespace',
|
|
283
|
+
'produces' => ['application/json'],
|
|
284
|
+
'parameters' => [{ 'in' => 'body', 'name' => 'elements', 'description' => 'Set of configuration', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => true }],
|
|
285
|
+
'responses' => { '200' => { 'description' => 'nested route inside namespace', 'schema' => { '$ref' => '#/definitions/QueryInput' } } },
|
|
286
|
+
'tags' => ['other_thing'],
|
|
287
|
+
'operationId' => 'getV3OtherThingElements',
|
|
288
|
+
'x-amazon-apigateway-auth' => { 'type' => 'none' },
|
|
289
|
+
'x-amazon-apigateway-integration' => { 'type' => 'aws', 'uri' => 'foo_bar_uri', 'httpMethod' => 'get' }
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
'/thing' => {
|
|
293
|
+
'get' => {
|
|
294
|
+
'description' => 'This gets Things.',
|
|
295
|
+
'produces' => ['application/json'],
|
|
296
|
+
'parameters' => [
|
|
297
|
+
{ 'in' => 'query', 'name' => 'id', 'description' => 'Identity of Something', 'type' => 'integer', 'format' => 'int32', 'required' => false },
|
|
298
|
+
{ 'in' => 'query', 'name' => 'text', 'description' => 'Content of something.', 'type' => 'string', 'required' => false },
|
|
299
|
+
{ 'in' => 'formData', 'name' => 'links', 'type' => 'array', 'items' => { 'type' => 'link' }, 'required' => false },
|
|
300
|
+
{ 'in' => 'query', 'name' => 'others', 'type' => 'text', 'required' => false }
|
|
301
|
+
],
|
|
302
|
+
'responses' => { '200' => { 'description' => 'This gets Things.' }, '401' => { 'description' => 'Unauthorized', 'schema' => { '$ref' => '#/definitions/ApiError' } } },
|
|
303
|
+
'tags' => ['thing'],
|
|
304
|
+
'operationId' => 'getThing'
|
|
305
|
+
},
|
|
306
|
+
'post' => {
|
|
307
|
+
'description' => 'This creates Thing.',
|
|
308
|
+
'produces' => ['application/json'],
|
|
309
|
+
'consumes' => ['application/x-www-form-urlencoded'],
|
|
310
|
+
'parameters' => [
|
|
311
|
+
{ 'in' => 'formData', 'name' => 'text', 'description' => 'Content of something.', 'type' => 'string', 'required' => true },
|
|
312
|
+
{ 'in' => 'formData', 'name' => 'links', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => true }
|
|
313
|
+
],
|
|
314
|
+
'responses' => { '201' => { 'description' => 'This creates Thing.', 'schema' => { '$ref' => '#/definitions/Something' } }, '422' => { 'description' => 'Unprocessible Entity' } },
|
|
315
|
+
'tags' => ['thing'],
|
|
316
|
+
'operationId' => 'postThing'
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
'/thing/{id}' => {
|
|
320
|
+
'get' => {
|
|
321
|
+
'description' => 'This gets Thing.',
|
|
322
|
+
'produces' => ['application/json'],
|
|
323
|
+
'parameters' => [{ 'in' => 'path', 'name' => 'id', 'type' => 'integer', 'format' => 'int32', 'required' => true }],
|
|
324
|
+
'responses' => { '200' => { 'description' => 'getting a single thing' }, '401' => { 'description' => 'Unauthorized' } },
|
|
325
|
+
'tags' => ['thing'],
|
|
326
|
+
'operationId' => 'getThingId'
|
|
327
|
+
},
|
|
328
|
+
'put' => {
|
|
329
|
+
'description' => 'This updates Thing.',
|
|
330
|
+
'produces' => ['application/json'],
|
|
331
|
+
'consumes' => ['application/x-www-form-urlencoded'],
|
|
332
|
+
'parameters' => [
|
|
333
|
+
{ 'in' => 'path', 'name' => 'id', 'type' => 'integer', 'format' => 'int32', 'required' => true },
|
|
334
|
+
{ 'in' => 'formData', 'name' => 'text', 'description' => 'Content of something.', 'type' => 'string', 'required' => false },
|
|
335
|
+
{ 'in' => 'formData', 'name' => 'links', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => false }
|
|
336
|
+
],
|
|
337
|
+
'responses' => { '200' => { 'description' => 'This updates Thing.', 'schema' => { '$ref' => '#/definitions/Something' } } },
|
|
338
|
+
'tags' => ['thing'],
|
|
339
|
+
'operationId' => 'putThingId'
|
|
340
|
+
},
|
|
341
|
+
'delete' => {
|
|
342
|
+
'description' => 'This deletes Thing.',
|
|
343
|
+
'produces' => ['application/json'],
|
|
344
|
+
'parameters' => [{ 'in' => 'path', 'name' => 'id', 'type' => 'integer', 'format' => 'int32', 'required' => true }],
|
|
345
|
+
'responses' => { '200' => { 'description' => 'This deletes Thing.', 'schema' => { '$ref' => '#/definitions/Something' } } },
|
|
346
|
+
'tags' => ['thing'],
|
|
347
|
+
'operationId' => 'deleteThingId'
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
'/thing2' => {
|
|
351
|
+
'get' => {
|
|
352
|
+
'description' => 'This gets Things.',
|
|
353
|
+
'produces' => ['application/json'],
|
|
354
|
+
'responses' => { '200' => { 'description' => 'get Horses', 'schema' => { '$ref' => '#/definitions/Something' } }, '401' => { 'description' => 'HorsesOutError', 'schema' => { '$ref' => '#/definitions/ApiError' } } },
|
|
355
|
+
'tags' => ['thing2'],
|
|
356
|
+
'operationId' => 'getThing2'
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
'/dummy/{id}' => {
|
|
360
|
+
'delete' => {
|
|
361
|
+
'description' => 'dummy route.',
|
|
362
|
+
'produces' => ['application/json'],
|
|
363
|
+
'parameters' => [{ 'in' => 'path', 'name' => 'id', 'type' => 'integer', 'format' => 'int32', 'required' => true }],
|
|
364
|
+
'responses' => { '204' => { 'description' => 'dummy route.' }, '401' => { 'description' => 'Unauthorized' } },
|
|
365
|
+
'tags' => ['dummy'],
|
|
366
|
+
'operationId' => 'deleteDummyId'
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
'definitions' => {
|
|
371
|
+
'QueryInput' => {
|
|
372
|
+
'type' => 'object',
|
|
373
|
+
'required' => ['elements'],
|
|
374
|
+
'properties' => { 'elements' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/QueryInputElement' }, 'description' => 'Set of configuration' } },
|
|
375
|
+
'description' => 'QueryInput model'
|
|
376
|
+
},
|
|
377
|
+
'QueryInputElement' => {
|
|
378
|
+
'type' => 'object',
|
|
379
|
+
'required' => %w[key value],
|
|
380
|
+
'properties' => { 'key' => { 'type' => 'string', 'description' => 'Name of parameter' }, 'value' => { 'type' => 'string', 'description' => 'Value of parameter' } }
|
|
381
|
+
},
|
|
382
|
+
'ApiError' => {
|
|
383
|
+
'type' => 'object',
|
|
384
|
+
'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } },
|
|
385
|
+
'description' => 'ApiError model'
|
|
386
|
+
},
|
|
387
|
+
'Something' => {
|
|
388
|
+
'type' => 'object',
|
|
389
|
+
'properties' => {
|
|
390
|
+
'id' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'Identity of Something' },
|
|
391
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' },
|
|
392
|
+
'links' => { 'type' => 'array', 'items' => { 'description' => '', 'type' => 'link' } },
|
|
393
|
+
'others' => { 'description' => '', 'type' => 'text' }
|
|
394
|
+
},
|
|
395
|
+
'description' => 'Something model'
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
let(:http_verbs) { %w[get post put delete] }
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def mounted_paths
|
|
405
|
+
%w[/thing /other_thing /dummy]
|
|
406
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.shared_context 'namespace example' do
|
|
4
|
+
before :all do
|
|
5
|
+
module TheApi
|
|
6
|
+
# rubocop:disable Lint/EmptyClass
|
|
7
|
+
class CustomType; end
|
|
8
|
+
# rubocop:enable Lint/EmptyClass
|
|
9
|
+
|
|
10
|
+
class NamespaceApi < Grape::API
|
|
11
|
+
namespace :hudson do
|
|
12
|
+
desc 'Document root'
|
|
13
|
+
get '/' do
|
|
14
|
+
{ message: 'hi' }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
namespace :colorado do
|
|
19
|
+
desc 'This gets something.',
|
|
20
|
+
notes: '_test_'
|
|
21
|
+
|
|
22
|
+
get '/simple' do
|
|
23
|
+
{ bla: 'something' }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
namespace :colorado do
|
|
28
|
+
desc 'This gets something for URL using - separator.',
|
|
29
|
+
notes: '_test_'
|
|
30
|
+
|
|
31
|
+
get '/simple-test' do
|
|
32
|
+
{ bla: 'something' }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
namespace :thames do
|
|
37
|
+
desc 'this gets something else',
|
|
38
|
+
headers: {
|
|
39
|
+
'XAuthToken' => { description: 'A required header.', required: true },
|
|
40
|
+
'XOtherHeader' => { description: 'An optional header.', required: false }
|
|
41
|
+
},
|
|
42
|
+
http_codes: [
|
|
43
|
+
{ code: 403, message: 'invalid pony' },
|
|
44
|
+
{ code: 405, message: 'no ponies left!' }
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
get '/simple_with_headers' do
|
|
48
|
+
{ bla: 'something_else' }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
namespace :niles do
|
|
53
|
+
desc 'this takes an array of parameters',
|
|
54
|
+
params: {
|
|
55
|
+
'items[]' => { description: 'array of items', is_array: true }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
post '/items' do
|
|
59
|
+
{}
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
namespace :niles do
|
|
64
|
+
desc 'this uses a custom parameter',
|
|
65
|
+
params: {
|
|
66
|
+
'custom' => { type: CustomType, description: 'array of items', is_array: true }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get '/custom' do
|
|
70
|
+
{}
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class ParentLessNamespaceApi < Grape::API
|
|
76
|
+
route_param :animal do
|
|
77
|
+
route_param :breed do
|
|
78
|
+
resource :queues do
|
|
79
|
+
route_param :queue_id do
|
|
80
|
+
resource :reservations do
|
|
81
|
+
desc 'Lists all reservations specific type of animal of specific breed in specific queue'
|
|
82
|
+
get do
|
|
83
|
+
{ bla: 'Bla Black' }
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.shared_context 'the api paths/defs' do
|
|
4
|
+
let(:paths) do
|
|
5
|
+
{
|
|
6
|
+
'/in_body' => {
|
|
7
|
+
post: {
|
|
8
|
+
produces: ['application/json'],
|
|
9
|
+
consumes: ['application/json'],
|
|
10
|
+
parameters: [
|
|
11
|
+
{ in: 'body', name: 'in_body_1', description: 'in_body_1', type: 'integer', format: 'int32', required: true, example: 23 },
|
|
12
|
+
{ in: 'body', name: 'in_body_2', description: 'in_body_2', type: 'string', required: false },
|
|
13
|
+
{ in: 'body', name: 'in_body_3', description: 'in_body_3', type: 'string', required: false }
|
|
14
|
+
],
|
|
15
|
+
responses: { 201 => { description: 'post in body /wo entity', schema: { '$ref' => '#/definitions/InBody' } } },
|
|
16
|
+
tags: ['in_body'],
|
|
17
|
+
operationId: 'postInBody'
|
|
18
|
+
},
|
|
19
|
+
get: {
|
|
20
|
+
produces: ['application/json'],
|
|
21
|
+
responses: { 200 => { description: 'get in path /wo entity', schema: { '$ref' => '#/definitions/InBody' } } },
|
|
22
|
+
tags: ['in_body'],
|
|
23
|
+
operationId: 'getInBody'
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
'/in_body/{key}' => {
|
|
27
|
+
put: {
|
|
28
|
+
produces: ['application/json'],
|
|
29
|
+
consumes: ['application/json'],
|
|
30
|
+
parameters: [
|
|
31
|
+
{ in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
|
|
32
|
+
{ in: 'body', name: 'in_body_1', description: 'in_body_1', type: 'integer', format: 'int32', required: true },
|
|
33
|
+
{ in: 'body', name: 'in_body_2', description: 'in_body_2', type: 'string', required: false },
|
|
34
|
+
{ in: 'body', name: 'in_body_3', description: 'in_body_3', type: 'string', required: false, example: 'my example string' }
|
|
35
|
+
],
|
|
36
|
+
responses: { 200 => { description: 'put in body /wo entity', schema: { '$ref' => '#/definitions/InBody' } } },
|
|
37
|
+
tags: ['in_body'],
|
|
38
|
+
operationId: 'putInBodyKey'
|
|
39
|
+
},
|
|
40
|
+
get: {
|
|
41
|
+
produces: ['application/json'],
|
|
42
|
+
parameters: [
|
|
43
|
+
{ in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true }
|
|
44
|
+
],
|
|
45
|
+
responses: { 200 => { description: 'get in path /wo entity', schema: { '$ref' => '#/definitions/InBody' } } },
|
|
46
|
+
tags: ['in_body'],
|
|
47
|
+
operationId: 'getInBodyKey'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
let(:found_path) do
|
|
54
|
+
{
|
|
55
|
+
post: {
|
|
56
|
+
produces: ['application/json'],
|
|
57
|
+
consumes: ['application/json'],
|
|
58
|
+
parameters: [
|
|
59
|
+
{ in: 'body', name: 'in_body_1', description: 'in_body_1', type: 'integer', format: 'int32', required: true },
|
|
60
|
+
{ in: 'body', name: 'in_body_2', description: 'in_body_2', type: 'string', required: false },
|
|
61
|
+
{ in: 'body', name: 'in_body_3', description: 'in_body_3', type: 'string', required: false }
|
|
62
|
+
],
|
|
63
|
+
responses: { 201 => { description: 'post in body /wo entity', schema: { '$ref' => '#/definitions/InBody' } } },
|
|
64
|
+
tags: ['in_body'],
|
|
65
|
+
operationId: 'postInBody'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
let(:definitions) do
|
|
71
|
+
{
|
|
72
|
+
'InBody' => {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
in_body_1: { type: 'integer', format: 'int32' },
|
|
76
|
+
in_body_2: { type: 'string' },
|
|
77
|
+
in_body_3: { type: 'string' },
|
|
78
|
+
key: { type: 'integer', format: 'int32' }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
let(:expected_post_defs) do
|
|
85
|
+
{
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
in_body_1: { type: 'integer', format: 'int32', description: 'in_body_1', example: 23 },
|
|
89
|
+
in_body_2: { type: 'string', description: 'in_body_2' },
|
|
90
|
+
in_body_3: { type: 'string', description: 'in_body_3' }
|
|
91
|
+
},
|
|
92
|
+
required: [:in_body_1]
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
let(:expected_put_defs) do
|
|
97
|
+
{
|
|
98
|
+
type: 'object',
|
|
99
|
+
properties: {
|
|
100
|
+
in_body_1: { type: 'integer', format: 'int32', description: 'in_body_1' },
|
|
101
|
+
in_body_2: { type: 'string', description: 'in_body_2' },
|
|
102
|
+
in_body_3: { type: 'string', description: 'in_body_3', example: 'my example string' }
|
|
103
|
+
},
|
|
104
|
+
required: [:in_body_1]
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
let(:expected_path) { [] }
|
|
109
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'API with additional options' do
|
|
6
|
+
let(:api) do
|
|
7
|
+
Class.new(Grape::API) do
|
|
8
|
+
add_swagger_documentation \
|
|
9
|
+
api_documentation: { desc: 'Swagger compatible API description' },
|
|
10
|
+
specific_api_documentation: { desc: 'Swagger compatible API description for specific API' }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
subject do
|
|
15
|
+
api.routes.map do |route|
|
|
16
|
+
route.settings[:description]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'documents api' do
|
|
21
|
+
expect(subject).to eq(
|
|
22
|
+
[
|
|
23
|
+
{ description: 'Swagger compatible API description' },
|
|
24
|
+
{
|
|
25
|
+
description: 'Swagger compatible API description for specific API',
|
|
26
|
+
params: {
|
|
27
|
+
'locale' => {
|
|
28
|
+
desc: 'Locale of API documentation',
|
|
29
|
+
required: false,
|
|
30
|
+
type: 'Symbol'
|
|
31
|
+
},
|
|
32
|
+
'name' => {
|
|
33
|
+
desc: 'Resource name of mounted API',
|
|
34
|
+
required: true,
|
|
35
|
+
type: 'String'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
end
|