brainstem 1.4.1 → 2.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.
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