rspec_api_documentation 5.1.0 → 6.0.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 +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
|