brainstem 1.4.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -0
  3. data/README.md +119 -0
  4. data/docs/api_doc_generator.markdown +45 -4
  5. data/docs/brainstem_executable.markdown +1 -1
  6. data/docs/oas_2_docgen.png +0 -0
  7. data/docs/oas_2_docgen_ascii.txt +78 -0
  8. data/lib/brainstem/api_docs.rb +23 -9
  9. data/lib/brainstem/api_docs/abstract_collection.rb +0 -13
  10. data/lib/brainstem/api_docs/atlas.rb +0 -14
  11. data/lib/brainstem/api_docs/builder.rb +0 -14
  12. data/lib/brainstem/api_docs/controller.rb +7 -16
  13. data/lib/brainstem/api_docs/controller_collection.rb +0 -3
  14. data/lib/brainstem/api_docs/endpoint.rb +73 -19
  15. data/lib/brainstem/api_docs/endpoint_collection.rb +0 -7
  16. data/lib/brainstem/api_docs/formatters/abstract_formatter.rb +0 -2
  17. data/lib/brainstem/api_docs/formatters/markdown/controller_formatter.rb +1 -9
  18. data/lib/brainstem/api_docs/formatters/markdown/endpoint_collection_formatter.rb +1 -9
  19. data/lib/brainstem/api_docs/formatters/markdown/endpoint_formatter.rb +39 -24
  20. data/lib/brainstem/api_docs/formatters/markdown/helper.rb +0 -13
  21. data/lib/brainstem/api_docs/formatters/markdown/presenter_formatter.rb +22 -35
  22. data/lib/brainstem/api_docs/formatters/open_api_specification/helper.rb +66 -0
  23. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/controller_formatter.rb +57 -0
  24. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/param_definitions_formatter.rb +311 -0
  25. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/response_definitions_formatter.rb +197 -0
  26. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_collection_formatter.rb +60 -0
  27. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_formatter.rb +162 -0
  28. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/info_formatter.rb +126 -0
  29. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/presenter_formatter.rb +132 -0
  30. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/security_definitions_formatter.rb +99 -0
  31. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/tags_formatter.rb +123 -0
  32. data/lib/brainstem/api_docs/introspectors/abstract_introspector.rb +0 -7
  33. data/lib/brainstem/api_docs/introspectors/rails_introspector.rb +1 -20
  34. data/lib/brainstem/api_docs/presenter.rb +21 -27
  35. data/lib/brainstem/api_docs/presenter_collection.rb +1 -11
  36. data/lib/brainstem/api_docs/resolver.rb +1 -8
  37. data/lib/brainstem/api_docs/sinks/abstract_sink.rb +0 -4
  38. data/lib/brainstem/api_docs/sinks/controller_presenter_multifile_sink.rb +0 -9
  39. data/lib/brainstem/api_docs/sinks/open_api_specification_sink.rb +234 -0
  40. data/lib/brainstem/api_docs/sinks/stdout_sink.rb +0 -5
  41. data/lib/brainstem/cli.rb +0 -13
  42. data/lib/brainstem/cli/abstract_command.rb +0 -7
  43. data/lib/brainstem/cli/generate_api_docs_command.rb +48 -24
  44. data/lib/brainstem/concerns/controller_dsl.rb +288 -145
  45. data/lib/brainstem/concerns/formattable.rb +0 -5
  46. data/lib/brainstem/concerns/optional.rb +0 -1
  47. data/lib/brainstem/concerns/presenter_dsl.rb +2 -21
  48. data/lib/brainstem/dsl/configuration.rb +0 -11
  49. data/lib/brainstem/presenter.rb +0 -4
  50. data/lib/brainstem/version.rb +1 -1
  51. data/spec/brainstem/api_docs/abstract_collection_spec.rb +0 -11
  52. data/spec/brainstem/api_docs/atlas_spec.rb +0 -6
  53. data/spec/brainstem/api_docs/builder_spec.rb +0 -4
  54. data/spec/brainstem/api_docs/controller_collection_spec.rb +0 -2
  55. data/spec/brainstem/api_docs/controller_spec.rb +29 -18
  56. data/spec/brainstem/api_docs/endpoint_collection_spec.rb +0 -6
  57. data/spec/brainstem/api_docs/endpoint_spec.rb +343 -13
  58. data/spec/brainstem/api_docs/formatters/abstract_formatter_spec.rb +0 -2
  59. data/spec/brainstem/api_docs/formatters/markdown/controller_formatter_spec.rb +0 -1
  60. data/spec/brainstem/api_docs/formatters/markdown/endpoint_collection_formatter_spec.rb +0 -5
  61. data/spec/brainstem/api_docs/formatters/markdown/endpoint_formatter_spec.rb +94 -8
  62. data/spec/brainstem/api_docs/formatters/markdown/helper_spec.rb +0 -8
  63. data/spec/brainstem/api_docs/formatters/markdown/presenter_formatter_spec.rb +0 -7
  64. data/spec/brainstem/api_docs/formatters/open_api_specification/helper_spec.rb +210 -0
  65. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/controller_formatter_spec.rb +81 -0
  66. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/param_definitions_formatter_spec.rb +672 -0
  67. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/response_definitions_formatter_spec.rb +335 -0
  68. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_collection_formatter_spec.rb +59 -0
  69. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_formatter_spec.rb +308 -0
  70. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/info_formatter_spec.rb +89 -0
  71. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/presenter_formatter_spec.rb +430 -0
  72. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/security_definitions_formatter_spec.rb +190 -0
  73. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/tags_formatter_spec.rb +217 -0
  74. data/spec/brainstem/api_docs/introspectors/abstract_introspector_spec.rb +0 -2
  75. data/spec/brainstem/api_docs/introspectors/rails_introspector_spec.rb +0 -2
  76. data/spec/brainstem/api_docs/presenter_collection_spec.rb +0 -2
  77. data/spec/brainstem/api_docs/presenter_spec.rb +58 -18
  78. data/spec/brainstem/api_docs/resolver_spec.rb +0 -1
  79. data/spec/brainstem/api_docs/sinks/controller_presenter_multifile_sink_spec.rb +0 -2
  80. data/spec/brainstem/api_docs/sinks/open_api_specification_sink_spec.rb +371 -0
  81. data/spec/brainstem/api_docs_spec.rb +2 -0
  82. data/spec/brainstem/cli/abstract_command_spec.rb +0 -4
  83. data/spec/brainstem/cli/generate_api_docs_command_spec.rb +53 -2
  84. data/spec/brainstem/concerns/controller_dsl_spec.rb +430 -64
  85. data/spec/brainstem/concerns/presenter_dsl_spec.rb +0 -20
  86. data/spec/brainstem/preloader_spec.rb +0 -7
  87. data/spec/brainstem/presenter_spec.rb +0 -1
  88. data/spec/dummy/rails.rb +0 -1
  89. data/spec/spec_helpers/db.rb +0 -1
  90. metadata +37 -2
@@ -8,14 +8,12 @@ module Brainstem
8
8
  class PresenterCollection < AbstractCollection
9
9
  include Concerns::Formattable
10
10
 
11
-
12
11
  def valid_options
13
12
  super | [ :presenter_constant_lookup_method ]
14
13
  end
15
14
 
16
15
  attr_writer :presenter_constant_lookup_method
17
16
 
18
-
19
17
  #
20
18
  # Finds or creates a presenter with the given target class and appends it to the
21
19
  # members list if it is new.
@@ -27,7 +25,6 @@ module Brainstem
27
25
  alias_method :find_or_create_by_target_class,
28
26
  :find_or_create_from_target_class
29
27
 
30
-
31
28
  #
32
29
  # Finds a presenter for the given class
33
30
  #
@@ -35,7 +32,6 @@ module Brainstem
35
32
  find { |p| p.target_class == target_class }
36
33
  end
37
34
 
38
-
39
35
  #
40
36
  # Creates a new +Presenter+ wrapper and appends it to the collection. If
41
37
  # the constant lookup for the actual presenter class fails, returns nil.
@@ -49,7 +45,6 @@ module Brainstem
49
45
  nil
50
46
  end
51
47
 
52
-
53
48
  def find_or_create_from_presenter_collection(target_class, const)
54
49
  find_by_target_class(target_class) ||
55
50
  create_from_presenter_collection(target_class, const)
@@ -57,7 +52,6 @@ module Brainstem
57
52
  alias_method :find_or_create_by_presenter_collection,
58
53
  :find_or_create_from_presenter_collection
59
54
 
60
-
61
55
  def create_from_presenter_collection(target_class, const)
62
56
  ::Brainstem::ApiDocs::Presenter.new(atlas,
63
57
  target_class: target_class,
@@ -65,7 +59,6 @@ module Brainstem
65
59
  ).tap { |p| self.<< p }
66
60
  end
67
61
 
68
-
69
62
  #########################################################################
70
63
  private
71
64
  #########################################################################
@@ -78,7 +71,6 @@ module Brainstem
78
71
  presenter_constant_lookup_method.call(target_class.to_s)
79
72
  end
80
73
 
81
-
82
74
  #
83
75
  # A callable method by which presenter constants can be looked up from
84
76
  # their human name.
@@ -87,11 +79,9 @@ module Brainstem
87
79
  # to reduce total surface.
88
80
  #
89
81
  def presenter_constant_lookup_method
90
- @presenter_constant_lookup_method ||= \
91
- Brainstem.presenter_collection.presenters.method(:fetch)
82
+ @presenter_constant_lookup_method ||= Brainstem.presenter_collection.presenters.method(:fetch)
92
83
  end
93
84
 
94
-
95
85
  end
96
86
  end
97
87
  end
@@ -12,7 +12,6 @@ module Brainstem
12
12
  class Resolver
13
13
  include Brainstem::Concerns::Optional
14
14
 
15
-
16
15
  def valid_options
17
16
  [
18
17
  :presenter_constant_lookup_method,
@@ -24,11 +23,9 @@ module Brainstem
24
23
  super options
25
24
  end
26
25
 
27
-
28
26
  attr_accessor :atlas,
29
27
  :presenter_constant_lookup_method
30
28
 
31
-
32
29
  def find_by_class(klass)
33
30
  if klass == :polymorphic
34
31
  nil
@@ -37,7 +34,6 @@ module Brainstem
37
34
  end
38
35
  end
39
36
 
40
-
41
37
  #########################################################################
42
38
  private
43
39
  #########################################################################
@@ -49,7 +45,6 @@ module Brainstem
49
45
  nil
50
46
  end
51
47
 
52
-
53
48
  #
54
49
  # Converts a class into a presenter constant. Raises an error
55
50
  # if not found.
@@ -58,14 +53,12 @@ module Brainstem
58
53
  presenter_constant_lookup_method.call(target_class.to_s)
59
54
  end
60
55
 
61
-
62
56
  #
63
57
  # A callable method by which presenter constants can be looked up from
64
58
  # their human name.
65
59
  #
66
60
  def presenter_constant_lookup_method
67
- @presenter_constant_lookup_method ||= \
68
- Brainstem.presenter_collection.presenters.method(:fetch)
61
+ @presenter_constant_lookup_method ||= Brainstem.presenter_collection.presenters.method(:fetch)
69
62
  end
70
63
  end
71
64
  end
@@ -6,7 +6,6 @@ module Brainstem
6
6
  class AbstractSink
7
7
  include Concerns::Optional
8
8
 
9
-
10
9
  #
11
10
  # Primary method for putting the atlas into the sink.
12
11
  #
@@ -16,12 +15,10 @@ module Brainstem
16
15
  raise NotImplementedError
17
16
  end
18
17
 
19
-
20
18
  #######################################################################$
21
19
  private
22
20
  ########################################################################
23
21
 
24
-
25
22
  #
26
23
  # Whitelist of options which can be set on an instance.
27
24
  #
@@ -30,7 +27,6 @@ module Brainstem
30
27
  def valid_options
31
28
  []
32
29
  end
33
-
34
30
  end
35
31
  end
36
32
  end
@@ -10,7 +10,6 @@ module Brainstem
10
10
 
11
11
  delegate [:controllers, :presenters] => :atlas
12
12
 
13
-
14
13
  def <<(atlas)
15
14
  self.atlas = atlas
16
15
 
@@ -18,19 +17,16 @@ module Brainstem
18
17
  write_presenter_files
19
18
  end
20
19
 
21
-
22
20
  def valid_options
23
21
  super | [ :write_method, :format, :write_path ]
24
22
  end
25
23
 
26
-
27
24
  attr_writer :write_method,
28
25
  :write_path
29
26
 
30
27
  attr_accessor :atlas,
31
28
  :format
32
29
 
33
-
34
30
  #######################################################################
35
31
  private
36
32
  #######################################################################
@@ -46,7 +42,6 @@ module Brainstem
46
42
  )
47
43
  end
48
44
 
49
-
50
45
  #
51
46
  # Dumps each formatted presenter to a file.
52
47
  #
@@ -54,7 +49,6 @@ module Brainstem
54
49
  presenters.each_formatted_with_filename(format, &method(:write_buffer_to_file))
55
50
  end
56
51
 
57
-
58
52
  #
59
53
  # Writes a given bufer to a filename within the base path.
60
54
  #
@@ -64,7 +58,6 @@ module Brainstem
64
58
  write_method.call(abs_path, buffer)
65
59
  end
66
60
 
67
-
68
61
  #
69
62
  # Asserts that a directory exists, creating it if it does not.
70
63
  #
@@ -73,7 +66,6 @@ module Brainstem
73
66
  FileUtils.mkdir_p(dir) unless File.directory?(dir)
74
67
  end
75
68
 
76
-
77
69
  #
78
70
  # Defines how we write out the files.
79
71
  #
@@ -83,7 +75,6 @@ module Brainstem
83
75
  end
84
76
  end
85
77
 
86
-
87
78
  def write_path
88
79
  @write_path ||= ::Brainstem::ApiDocs.write_path
89
80
  end
@@ -0,0 +1,234 @@
1
+ require 'brainstem/api_docs'
2
+ require 'brainstem/api_docs/formatters/open_api_specification/helper'
3
+ require 'brainstem/api_docs/sinks/abstract_sink'
4
+ require 'fileutils'
5
+ require 'forwardable'
6
+
7
+ module Brainstem
8
+ module ApiDocs
9
+ module Sinks
10
+ class OpenApiSpecificationSink < AbstractSink
11
+ include Brainstem::ApiDocs::Formatters::OpenApiSpecification::Helper
12
+ extend Forwardable
13
+
14
+ def valid_options
15
+ super | [
16
+ :api_version,
17
+ :ignore_tagging,
18
+ :format,
19
+ :write_method,
20
+ :write_path,
21
+ :oas_filename_pattern,
22
+ :output_extension,
23
+ ]
24
+ end
25
+
26
+ attr_writer :write_method,
27
+ :write_path
28
+
29
+ attr_accessor :api_version,
30
+ :atlas,
31
+ :format,
32
+ :ignore_tagging,
33
+ :oas_filename_pattern,
34
+ :output_extension,
35
+ :output
36
+
37
+ delegate [:controllers, :presenters] => :atlas
38
+
39
+ def <<(atlas)
40
+ self.atlas = atlas
41
+ self.output = ActiveSupport::HashWithIndifferentAccess.new
42
+
43
+ write_info_object!
44
+ write_presenter_definitions!
45
+ write_error_definitions!
46
+ write_endpoint_definitions!
47
+ write_tag_definitions!
48
+ write_security_definitions!
49
+
50
+ write_spec_to_file!
51
+ end
52
+
53
+ #######################################################################
54
+ private
55
+ #######################################################################
56
+
57
+ DEFAULT_API_VERSION = '1.0.0'
58
+ private_constant :DEFAULT_API_VERSION
59
+
60
+ #
61
+ # Returns the version of the API.
62
+ #
63
+ def formatted_version
64
+ self.api_version.presence || DEFAULT_API_VERSION
65
+ end
66
+
67
+ #
68
+ # Use the Info formatter to get the swagger & info object.
69
+ #
70
+ def write_info_object!
71
+ self.output.merge!(
72
+ ::Brainstem::ApiDocs::FORMATTERS[:info][format].call(version: formatted_version)
73
+ )
74
+ end
75
+
76
+ #
77
+ # Use the presenter formatters to add schema definitions to the specification.
78
+ #
79
+ def write_presenter_definitions!
80
+ presenter_definitions = presenters
81
+ .formatted(format)
82
+ .inject({}) do |definitions, object_with_definition|
83
+
84
+ definitions.merge(object_with_definition)
85
+ end
86
+
87
+ inject_objects_under_key!(:definitions, presenter_definitions, true)
88
+ end
89
+
90
+ #
91
+ # Add standard error structure to the definitions of the specification.
92
+ #
93
+ def write_error_definitions!
94
+ self.output[:definitions].merge!(
95
+ 'Error' => {
96
+ type: 'object',
97
+ properties: {
98
+ type: type_and_format('string'),
99
+ message: type_and_format('string')
100
+ }
101
+ },
102
+ 'Errors' => {
103
+ type: 'object',
104
+ properties: {
105
+ errors: {
106
+ type: 'array',
107
+ items: { '$ref' => '#/definitions/Error' }
108
+ }
109
+ }
110
+ }
111
+ )
112
+ end
113
+
114
+ #
115
+ # Use the controller formatters to add endpoint definitions to the specification.
116
+ #
117
+ def write_endpoint_definitions!
118
+ controller_definitions = controllers
119
+ .formatted(format)
120
+ .inject({}) do |definitions, path_definition|
121
+
122
+ definitions.merge(path_definition)
123
+ end
124
+
125
+ inject_objects_under_key!(:paths, controller_definitions, true)
126
+ end
127
+
128
+ #
129
+ # Use the controllers names as tag defintions
130
+ #
131
+ def write_tag_definitions!
132
+ self.output.merge!(
133
+ ::Brainstem::ApiDocs::FORMATTERS[:tags][format].call(controllers, ignore_tagging: self.ignore_tagging)
134
+ )
135
+ end
136
+
137
+ #
138
+ # Use the Security Definitions formatter to get the security definitions & scopes.
139
+ #
140
+ def write_security_definitions!
141
+ self.output.merge!(
142
+ ::Brainstem::ApiDocs::FORMATTERS[:security][format].call
143
+ )
144
+ end
145
+
146
+ #
147
+ # Sort hash by keys and add them to the output nested under the specified top level key
148
+ #
149
+ def inject_objects_under_key!(top_level_key, objects, sort = false)
150
+ self.output[top_level_key] ||= {}
151
+
152
+ ordered_keys = sort ? objects.keys.sort : objects.keys
153
+ ordered_keys.each do |object_key|
154
+ self.output[top_level_key][object_key] = objects[object_key]
155
+ end
156
+
157
+ self.output
158
+ end
159
+
160
+ #
161
+ # Writes a given bufer to a filename within the base path.
162
+ #
163
+ def write_spec_to_file!
164
+ formatted_output = format_output(output, extension)
165
+ abs_path = File.join(write_path, suggested_filename)
166
+
167
+ assert_directory_exists!(abs_path)
168
+ write_method.call(abs_path, formatted_output)
169
+ end
170
+
171
+ #
172
+ # Format output to the requested format.
173
+ #
174
+ def format_output(output, requested_format)
175
+ unless %w(json yaml yml).include?(requested_format)
176
+ raise "Open API Specification only supports generation of json / yaml files"
177
+ end
178
+
179
+ data = output.to_hash
180
+ requested_format == 'json' ? data.to_json : data.to_yaml
181
+ end
182
+
183
+ #
184
+ # Asserts that a directory exists, creating it if it does not.
185
+ #
186
+ def assert_directory_exists!(path)
187
+ dir = File.dirname(path)
188
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
189
+ end
190
+
191
+ #
192
+ # Defines how we write out the files.
193
+ #
194
+ def write_method
195
+ @write_method ||= Proc.new do |name, buff|
196
+ File.write(name, buff, mode: 'w')
197
+ end
198
+ end
199
+
200
+ #
201
+ # Defines the output directory for the file.
202
+ #
203
+ def write_path
204
+ @write_path ||= ::Brainstem::ApiDocs.write_path
205
+ end
206
+
207
+ #
208
+ # Defines the file extension for the output file.
209
+ #
210
+ def extension
211
+ return output_extension.downcase.to_s if output_extension.present?
212
+
213
+ configured_extension = Brainstem::ApiDocs.output_extension.downcase.to_s
214
+ configured_extension == "markdown" ? DEFAULT_OAS_EXTENSION : configured_extension
215
+ end
216
+
217
+ DEFAULT_OAS_EXTENSION = 'yml'
218
+ private_constant :DEFAULT_OAS_EXTENSION
219
+
220
+ #
221
+ # Defines the name of the file.
222
+ #
223
+ def suggested_filename
224
+ (oas_filename_pattern.presence || DEFAULT_FILENAME_PATTERN)
225
+ .gsub('{{version}}', formatted_version)
226
+ .gsub('{{extension}}', extension)
227
+ end
228
+
229
+ DEFAULT_FILENAME_PATTERN = 'specification.{{extension}}'
230
+ private_constant :DEFAULT_FILENAME_PATTERN
231
+ end
232
+ end
233
+ end
234
+ end