rspec_api_documentation 5.1.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rspec_api_documentation.rb +26 -1
- data/lib/rspec_api_documentation/api_documentation.rb +2 -0
- data/lib/rspec_api_documentation/configuration.rb +11 -1
- data/lib/rspec_api_documentation/dsl/endpoint.rb +33 -1
- data/lib/rspec_api_documentation/dsl/endpoint/params.rb +19 -3
- data/lib/rspec_api_documentation/dsl/endpoint/set_param.rb +12 -1
- data/lib/rspec_api_documentation/dsl/resource.rb +23 -0
- data/lib/rspec_api_documentation/open_api/contact.rb +9 -0
- data/lib/rspec_api_documentation/open_api/example.rb +7 -0
- data/lib/rspec_api_documentation/open_api/header.rb +12 -0
- data/lib/rspec_api_documentation/open_api/headers.rb +7 -0
- data/lib/rspec_api_documentation/open_api/helper.rb +29 -0
- data/lib/rspec_api_documentation/open_api/info.rb +12 -0
- data/lib/rspec_api_documentation/open_api/license.rb +8 -0
- data/lib/rspec_api_documentation/open_api/node.rb +112 -0
- data/lib/rspec_api_documentation/open_api/operation.rb +18 -0
- data/lib/rspec_api_documentation/open_api/parameter.rb +33 -0
- data/lib/rspec_api_documentation/open_api/path.rb +13 -0
- data/lib/rspec_api_documentation/open_api/paths.rb +7 -0
- data/lib/rspec_api_documentation/open_api/response.rb +10 -0
- data/lib/rspec_api_documentation/open_api/responses.rb +9 -0
- data/lib/rspec_api_documentation/open_api/root.rb +21 -0
- data/lib/rspec_api_documentation/open_api/schema.rb +15 -0
- data/lib/rspec_api_documentation/open_api/security_definitions.rb +7 -0
- data/lib/rspec_api_documentation/open_api/security_schema.rb +14 -0
- data/lib/rspec_api_documentation/open_api/tag.rb +9 -0
- data/lib/rspec_api_documentation/views/api_blueprint_example.rb +15 -3
- data/lib/rspec_api_documentation/views/api_blueprint_index.rb +17 -2
- data/lib/rspec_api_documentation/views/markdown_example.rb +1 -1
- data/lib/rspec_api_documentation/views/markup_example.rb +8 -3
- data/lib/rspec_api_documentation/views/slate_index.rb +4 -0
- data/lib/rspec_api_documentation/writers/combined_json_writer.rb +1 -1
- data/lib/rspec_api_documentation/writers/json_iodocs_writer.rb +2 -2
- data/lib/rspec_api_documentation/writers/json_writer.rb +6 -6
- data/lib/rspec_api_documentation/writers/markdown_writer.rb +1 -1
- data/lib/rspec_api_documentation/writers/open_api_writer.rb +244 -0
- data/lib/rspec_api_documentation/writers/slate_writer.rb +2 -8
- data/templates/rspec_api_documentation/api_blueprint_index.mustache +6 -5
- data/templates/rspec_api_documentation/slate_index.mustache +8 -0
- metadata +57 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: debdb41655fc2b0d61d43a0feaffa6a3c4e1ae6c
|
4
|
+
data.tar.gz: e560cee22b88bda2b3779a4e9f26561e3d4195ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6530d774c6e77fe56a65ee073d74f7b7acec77d8feeb63aace0b0b931975f59253be12d8c091c6bae743b884db9cadf723159f59c273c0dfe2acfdb2eb0106a3
|
7
|
+
data.tar.gz: 08e6146400b65497daea2d47c257ecead4436a37779b689215bab75830aab20f66e9e71698cb14a02101aea334555aae8be69aad56736e69ba483581b150aea3
|
@@ -37,7 +37,7 @@ module RspecApiDocumentation
|
|
37
37
|
autoload :HtmlWriter
|
38
38
|
autoload :TextileWriter
|
39
39
|
autoload :MarkdownWriter
|
40
|
-
autoload :
|
40
|
+
autoload :JSONWriter
|
41
41
|
autoload :AppendJsonWriter
|
42
42
|
autoload :JsonIodocsWriter
|
43
43
|
autoload :IndexHelper
|
@@ -45,6 +45,31 @@ module RspecApiDocumentation
|
|
45
45
|
autoload :CombinedJsonWriter
|
46
46
|
autoload :SlateWriter
|
47
47
|
autoload :ApiBlueprintWriter
|
48
|
+
autoload :OpenApiWriter
|
49
|
+
end
|
50
|
+
|
51
|
+
module OpenApi
|
52
|
+
extend ActiveSupport::Autoload
|
53
|
+
|
54
|
+
autoload :Helper
|
55
|
+
autoload :Node
|
56
|
+
autoload :Root
|
57
|
+
autoload :Info
|
58
|
+
autoload :Contact
|
59
|
+
autoload :License
|
60
|
+
autoload :Paths
|
61
|
+
autoload :Path
|
62
|
+
autoload :Tag
|
63
|
+
autoload :Operation
|
64
|
+
autoload :Parameter
|
65
|
+
autoload :Responses
|
66
|
+
autoload :Response
|
67
|
+
autoload :Example
|
68
|
+
autoload :Headers
|
69
|
+
autoload :Header
|
70
|
+
autoload :Schema
|
71
|
+
autoload :SecurityDefinitions
|
72
|
+
autoload :SecuritySchema
|
48
73
|
end
|
49
74
|
|
50
75
|
module Views
|
@@ -51,6 +51,14 @@ module RspecApiDocumentation
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
add_setting :configurations_dir, :default => lambda { |config|
|
55
|
+
if defined?(Rails)
|
56
|
+
Rails.root.join('doc', 'configurations', 'api')
|
57
|
+
else
|
58
|
+
Pathname.new('doc/configurations/api')
|
59
|
+
end
|
60
|
+
}
|
61
|
+
|
54
62
|
add_setting :docs_dir, :default => lambda { |config|
|
55
63
|
if defined?(Rails)
|
56
64
|
Rails.root.join("doc", "api")
|
@@ -110,7 +118,7 @@ module RspecApiDocumentation
|
|
110
118
|
# See RspecApiDocumentation::DSL::Endpoint#do_request
|
111
119
|
add_setting :response_body_formatter, default: Proc.new { |_, _|
|
112
120
|
Proc.new do |content_type, response_body|
|
113
|
-
if content_type =~ /application
|
121
|
+
if content_type =~ /application\/.*json/
|
114
122
|
JSON.pretty_generate(JSON.parse(response_body))
|
115
123
|
else
|
116
124
|
response_body
|
@@ -119,6 +127,8 @@ module RspecApiDocumentation
|
|
119
127
|
}
|
120
128
|
|
121
129
|
def client_method=(new_client_method)
|
130
|
+
return if new_client_method == client_method
|
131
|
+
|
122
132
|
RspecApiDocumentation::DSL::Resource.module_eval <<-RUBY
|
123
133
|
alias :#{new_client_method} #{client_method}
|
124
134
|
undef #{client_method}
|
@@ -38,6 +38,9 @@ module RspecApiDocumentation::DSL
|
|
38
38
|
params_or_body = nil
|
39
39
|
path_or_query = path
|
40
40
|
|
41
|
+
extended_parameters
|
42
|
+
extract_route_parameters!
|
43
|
+
|
41
44
|
if http_method == :get && !query_string.blank?
|
42
45
|
path_or_query += "?#{query_string}"
|
43
46
|
else
|
@@ -74,6 +77,36 @@ module RspecApiDocumentation::DSL
|
|
74
77
|
example.metadata[:headers][name] = value
|
75
78
|
end
|
76
79
|
|
80
|
+
def authentication(type, value, opts = {})
|
81
|
+
name, new_opts =
|
82
|
+
case type
|
83
|
+
when :basic then ['Authorization', opts.merge(type: type)]
|
84
|
+
when :apiKey then [opts[:name], opts.merge(type: type, in: :header)]
|
85
|
+
else raise 'Not supported type for authentication'
|
86
|
+
end
|
87
|
+
header(name, value)
|
88
|
+
example.metadata[:authentications] ||= {}
|
89
|
+
example.metadata[:authentications][name] = new_opts
|
90
|
+
end
|
91
|
+
|
92
|
+
def extract_route_parameters!
|
93
|
+
example.metadata[:route].gsub(URL_PARAMS_REGEX) do |match|
|
94
|
+
value =
|
95
|
+
if extra_params.keys.include?($1)
|
96
|
+
extra_params[$1]
|
97
|
+
elsif respond_to?($1)
|
98
|
+
send($1)
|
99
|
+
else
|
100
|
+
match
|
101
|
+
end
|
102
|
+
extended_parameters << {name: match[1..-1], value: value, in: :path}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def extended_parameters
|
107
|
+
example.metadata[:extended_parameters] ||= Params.new(self, example, extra_params).extended
|
108
|
+
end
|
109
|
+
|
77
110
|
def headers
|
78
111
|
return unless example.metadata[:headers]
|
79
112
|
example.metadata[:headers].inject({}) do |hash, (header, value)|
|
@@ -144,6 +177,5 @@ module RspecApiDocumentation::DSL
|
|
144
177
|
def delete_extra_param(key)
|
145
178
|
@extra_params.delete(key.to_sym) || @extra_params.delete(key.to_s)
|
146
179
|
end
|
147
|
-
|
148
180
|
end
|
149
181
|
end
|
@@ -13,11 +13,27 @@ module RspecApiDocumentation
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def call
|
16
|
-
|
16
|
+
set_param = -> hash, param {
|
17
17
|
SetParam.new(self, hash, param).call
|
18
|
+
}
|
19
|
+
|
20
|
+
example.metadata.fetch(:parameters, {}).inject({}, &set_param)
|
21
|
+
.deep_merge(
|
22
|
+
example.metadata.fetch(:attributes, {}).inject({}, &set_param)
|
23
|
+
).deep_merge(extra_params)
|
24
|
+
end
|
25
|
+
|
26
|
+
def extended
|
27
|
+
example.metadata.fetch(:parameters, {}).map do |param|
|
28
|
+
p = Marshal.load(Marshal.dump(param))
|
29
|
+
p[:value] = SetParam.new(self, nil, p).value
|
30
|
+
unless p[:value]
|
31
|
+
cur = extra_params
|
32
|
+
[*p[:scope]].each { |scope| cur = cur && (cur[scope.to_sym] || cur[scope.to_s]) }
|
33
|
+
p[:value] = cur && (cur[p[:name].to_s] || cur[p[:name].to_sym])
|
34
|
+
end
|
35
|
+
p
|
18
36
|
end
|
19
|
-
parameters.deep_merge!(extra_params)
|
20
|
-
parameters
|
21
37
|
end
|
22
38
|
|
23
39
|
private
|
@@ -15,6 +15,10 @@ module RspecApiDocumentation
|
|
15
15
|
hash.deep_merge build_param_hash(key_scope || [key])
|
16
16
|
end
|
17
17
|
|
18
|
+
def value
|
19
|
+
example_group.send(method_name) if method_name
|
20
|
+
end
|
21
|
+
|
18
22
|
private
|
19
23
|
|
20
24
|
attr_reader :parent, :hash, :param
|
@@ -36,6 +40,10 @@ module RspecApiDocumentation
|
|
36
40
|
param[:method]
|
37
41
|
end
|
38
42
|
|
43
|
+
def set_value
|
44
|
+
param[:value]
|
45
|
+
end
|
46
|
+
|
39
47
|
def path_name
|
40
48
|
scoped_key || key
|
41
49
|
end
|
@@ -51,11 +59,14 @@ module RspecApiDocumentation
|
|
51
59
|
scoped_key
|
52
60
|
elsif key && example_group.respond_to?(key)
|
53
61
|
key
|
62
|
+
elsif key && set_value
|
63
|
+
key
|
54
64
|
end
|
55
65
|
end
|
56
66
|
|
57
67
|
def build_param_hash(keys)
|
58
|
-
value =
|
68
|
+
value = param[:value] if param.has_key?(:value)
|
69
|
+
value ||= keys[1] ? build_param_hash(keys[1..-1]) : example_group.send(method_name)
|
59
70
|
{ keys[0].to_s => value }
|
60
71
|
end
|
61
72
|
end
|
@@ -70,6 +70,25 @@ module RspecApiDocumentation::DSL
|
|
70
70
|
headers[name] = value
|
71
71
|
end
|
72
72
|
|
73
|
+
def authentication(type, value, opts = {})
|
74
|
+
name, new_opts =
|
75
|
+
case type
|
76
|
+
when :basic then ['Authorization', opts.merge(type: type)]
|
77
|
+
when :apiKey then [opts[:name], opts.merge(type: type, in: :header)]
|
78
|
+
else raise 'Not supported type for authentication'
|
79
|
+
end
|
80
|
+
header(name, value)
|
81
|
+
authentications[name] = new_opts
|
82
|
+
end
|
83
|
+
|
84
|
+
def route_summary(text)
|
85
|
+
safe_metadata(:route_summary, text)
|
86
|
+
end
|
87
|
+
|
88
|
+
def route_description(text)
|
89
|
+
safe_metadata(:route_description, text)
|
90
|
+
end
|
91
|
+
|
73
92
|
def explanation(text)
|
74
93
|
safe_metadata(:resource_explanation, text)
|
75
94
|
end
|
@@ -107,6 +126,10 @@ module RspecApiDocumentation::DSL
|
|
107
126
|
safe_metadata(:headers, {})
|
108
127
|
end
|
109
128
|
|
129
|
+
def authentications
|
130
|
+
safe_metadata(:authentications, {})
|
131
|
+
end
|
132
|
+
|
110
133
|
def parameter_keys
|
111
134
|
parameters.map { |param| param[:name] }
|
112
135
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module OpenApi
|
3
|
+
class Header < Node
|
4
|
+
add_setting :description, :default => ''
|
5
|
+
add_setting :type, :required => true, :default => lambda { |header|
|
6
|
+
Helper.extract_type(header.public_send('x-example-value'))
|
7
|
+
}
|
8
|
+
add_setting :format
|
9
|
+
add_setting 'x-example-value'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module OpenApi
|
3
|
+
module Helper
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def extract_type(value)
|
7
|
+
case value
|
8
|
+
when Rack::Test::UploadedFile then :file
|
9
|
+
when Array then :array
|
10
|
+
when Hash then :object
|
11
|
+
when TrueClass, FalseClass then :boolean
|
12
|
+
when Integer then :integer
|
13
|
+
when Float then :number
|
14
|
+
else :string
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def extract_items(value, opts = {})
|
19
|
+
result = {type: extract_type(value)}
|
20
|
+
if result[:type] == :array
|
21
|
+
result[:items] = extract_items(value[0], opts)
|
22
|
+
else
|
23
|
+
opts.each { |k, v| result[k] = v if v }
|
24
|
+
end
|
25
|
+
result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module OpenApi
|
3
|
+
class Info < Node
|
4
|
+
add_setting :title, :default => 'OpenAPI Specification', :required => true
|
5
|
+
add_setting :description, :default => 'This is a sample server Petstore server.'
|
6
|
+
add_setting :termsOfService, :default => 'http://open-api.io/terms/'
|
7
|
+
add_setting :contact, :default => Contact.new, :schema => Contact
|
8
|
+
add_setting :license, :default => License.new, :schema => License
|
9
|
+
add_setting :version, :default => '1.0.0', :required => true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module OpenApi
|
3
|
+
class Node
|
4
|
+
# this is used to define class of incoming option attribute
|
5
|
+
# If +false+ then do not create new setting
|
6
|
+
# If +true+ then create new setting with raw passed value
|
7
|
+
# If RspecApiDocumentation::OpenApi::Node then create new setting and wrap it in this class
|
8
|
+
CHILD_CLASS = false
|
9
|
+
|
10
|
+
# This attribute allow us to hide some of children through configuration file
|
11
|
+
attr_accessor :hide
|
12
|
+
|
13
|
+
def self.add_setting(name, opts = {})
|
14
|
+
class_settings << name
|
15
|
+
|
16
|
+
define_method("#{name}_schema") { opts[:schema] || NilClass }
|
17
|
+
define_method("#{name}=") { |value| settings[name] = value }
|
18
|
+
define_method("#{name}") do
|
19
|
+
if settings.has_key?(name)
|
20
|
+
settings[name]
|
21
|
+
elsif !opts[:default].nil?
|
22
|
+
if opts[:default].respond_to?(:call)
|
23
|
+
opts[:default].call(self)
|
24
|
+
else
|
25
|
+
opts[:default]
|
26
|
+
end
|
27
|
+
elsif opts[:required]
|
28
|
+
raise "setting: #{name} required in #{self}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(opts = {})
|
34
|
+
return unless opts
|
35
|
+
|
36
|
+
opts.each do |name, value|
|
37
|
+
if name.to_s == 'hide'
|
38
|
+
self.hide = value
|
39
|
+
elsif self.class::CHILD_CLASS
|
40
|
+
add_setting name, :value => self.class::CHILD_CLASS === true ? value : self.class::CHILD_CLASS.new(value)
|
41
|
+
elsif setting_exist?(name.to_sym)
|
42
|
+
schema = setting_schema(name)
|
43
|
+
converted =
|
44
|
+
case
|
45
|
+
when schema.is_a?(Array) && schema[0] <= Node then value.map { |v| v.is_a?(schema[0]) ? v : schema[0].new(v) }
|
46
|
+
when schema <= Node then value.is_a?(schema) ? value : schema.new(value)
|
47
|
+
else
|
48
|
+
value
|
49
|
+
end
|
50
|
+
assign_setting(name, converted)
|
51
|
+
else
|
52
|
+
public_send("#{name}=", value) if respond_to?("#{name}=")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def assign_setting(name, value); public_send("#{name}=", value) unless value.nil? end
|
58
|
+
def safe_assign_setting(name, value); assign_setting(name, value) unless settings.has_key?(name) end
|
59
|
+
def setting(name); public_send(name) end
|
60
|
+
def setting_schema(name); public_send("#{name}_schema") end
|
61
|
+
def setting_exist?(name); existing_settings.include?(name) end
|
62
|
+
def existing_settings; self.class.class_settings + instance_settings end
|
63
|
+
|
64
|
+
def add_setting(name, opts = {})
|
65
|
+
return false if setting_exist?(name)
|
66
|
+
|
67
|
+
instance_settings << name
|
68
|
+
|
69
|
+
settings[name] = opts[:value] if opts[:value]
|
70
|
+
|
71
|
+
define_singleton_method("#{name}_schema") { opts[:schema] || NilClass }
|
72
|
+
define_singleton_method("#{name}=") { |value| settings[name] = value }
|
73
|
+
define_singleton_method("#{name}") do
|
74
|
+
if settings.has_key?(name)
|
75
|
+
settings[name]
|
76
|
+
elsif !opts[:default].nil?
|
77
|
+
if opts[:default].respond_to?(:call)
|
78
|
+
opts[:default].call(self)
|
79
|
+
else
|
80
|
+
opts[:default]
|
81
|
+
end
|
82
|
+
elsif opts[:required]
|
83
|
+
raise "setting: #{name} required in #{self}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def as_json
|
89
|
+
existing_settings.inject({}) do |hash, name|
|
90
|
+
value = setting(name)
|
91
|
+
case
|
92
|
+
when value.is_a?(Node)
|
93
|
+
hash[name] = value.as_json unless value.hide
|
94
|
+
when value.is_a?(Array) && value[0].is_a?(Node)
|
95
|
+
tmp = value.select { |v| !v.hide }.map { |v| v.as_json }
|
96
|
+
hash[name] = tmp unless tmp.empty?
|
97
|
+
else
|
98
|
+
hash[name] = value
|
99
|
+
end unless value.nil?
|
100
|
+
|
101
|
+
hash
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def settings; @settings ||= {} end
|
108
|
+
def instance_settings; @instance_settings ||= [] end
|
109
|
+
def self.class_settings; @class_settings ||= [] end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|