praxis 2.0.pre.3 → 2.0.pre.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +0 -1
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.md +26 -0
  5. data/Gemfile +1 -1
  6. data/Guardfile +2 -1
  7. data/Rakefile +1 -7
  8. data/TODO.md +28 -0
  9. data/lib/api_browser/package-lock.json +7110 -0
  10. data/lib/praxis.rb +7 -4
  11. data/lib/praxis/action_definition.rb +9 -16
  12. data/lib/praxis/api_general_info.rb +21 -0
  13. data/lib/praxis/application.rb +1 -2
  14. data/lib/praxis/bootloader_stages/routing.rb +2 -4
  15. data/lib/praxis/docs/generator.rb +11 -6
  16. data/lib/praxis/docs/open_api_generator.rb +255 -0
  17. data/lib/praxis/docs/openapi/info_object.rb +31 -0
  18. data/lib/praxis/docs/openapi/media_type_object.rb +59 -0
  19. data/lib/praxis/docs/openapi/operation_object.rb +40 -0
  20. data/lib/praxis/docs/openapi/parameter_object.rb +69 -0
  21. data/lib/praxis/docs/openapi/paths_object.rb +55 -0
  22. data/lib/praxis/docs/openapi/request_body_object.rb +51 -0
  23. data/lib/praxis/docs/openapi/response_object.rb +63 -0
  24. data/lib/praxis/docs/openapi/responses_object.rb +44 -0
  25. data/lib/praxis/docs/openapi/schema_object.rb +87 -0
  26. data/lib/praxis/docs/openapi/server_object.rb +24 -0
  27. data/lib/praxis/docs/openapi/tag_object.rb +21 -0
  28. data/lib/praxis/extensions/attribute_filtering.rb +2 -0
  29. data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +148 -157
  30. data/lib/praxis/extensions/attribute_filtering/active_record_patches.rb +15 -0
  31. data/lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb +90 -0
  32. data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_0.rb +68 -0
  33. data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb +58 -0
  34. data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +35 -0
  35. data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +13 -12
  36. data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +3 -2
  37. data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +7 -9
  38. data/lib/praxis/extensions/field_selection/field_selector.rb +4 -0
  39. data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +6 -9
  40. data/lib/praxis/extensions/pagination.rb +130 -0
  41. data/lib/praxis/extensions/pagination/active_record_pagination_handler.rb +42 -0
  42. data/lib/praxis/extensions/pagination/header_generator.rb +70 -0
  43. data/lib/praxis/extensions/pagination/ordering_params.rb +238 -0
  44. data/lib/praxis/extensions/pagination/pagination_handler.rb +68 -0
  45. data/lib/praxis/extensions/pagination/pagination_params.rb +378 -0
  46. data/lib/praxis/extensions/pagination/sequel_pagination_handler.rb +45 -0
  47. data/lib/praxis/handlers/json.rb +2 -0
  48. data/lib/praxis/handlers/www_form.rb +5 -0
  49. data/lib/praxis/handlers/{xml.rb → xml-sample.rb} +6 -0
  50. data/lib/praxis/links.rb +4 -0
  51. data/lib/praxis/mapper/active_model_compat.rb +23 -5
  52. data/lib/praxis/mapper/resource.rb +16 -9
  53. data/lib/praxis/mapper/selector_generator.rb +11 -10
  54. data/lib/praxis/mapper/sequel_compat.rb +1 -0
  55. data/lib/praxis/media_type.rb +1 -56
  56. data/lib/praxis/multipart/part.rb +5 -2
  57. data/lib/praxis/plugins/mapper_plugin.rb +1 -1
  58. data/lib/praxis/plugins/pagination_plugin.rb +71 -0
  59. data/lib/praxis/resource_definition.rb +4 -12
  60. data/lib/praxis/response_definition.rb +1 -1
  61. data/lib/praxis/route.rb +2 -4
  62. data/lib/praxis/routing_config.rb +4 -8
  63. data/lib/praxis/tasks/api_docs.rb +23 -0
  64. data/lib/praxis/tasks/routes.rb +10 -15
  65. data/lib/praxis/types/media_type_common.rb +10 -0
  66. data/lib/praxis/types/multipart_array.rb +62 -0
  67. data/lib/praxis/validation_handler.rb +1 -2
  68. data/lib/praxis/version.rb +1 -1
  69. data/praxis.gemspec +4 -5
  70. data/spec/functional_spec.rb +9 -6
  71. data/spec/praxis/action_definition_spec.rb +4 -16
  72. data/spec/praxis/api_general_info_spec.rb +6 -6
  73. data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +304 -0
  74. data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +39 -0
  75. data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +34 -0
  76. data/spec/praxis/extensions/field_expansion_spec.rb +6 -24
  77. data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +15 -11
  78. data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +4 -3
  79. data/spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb +130 -0
  80. data/spec/praxis/extensions/{field_selection/support → support}/spec_resources_active_model.rb +45 -2
  81. data/spec/praxis/extensions/{field_selection/support → support}/spec_resources_sequel.rb +0 -0
  82. data/spec/praxis/mapper/selector_generator_spec.rb +32 -0
  83. data/spec/praxis/media_type_spec.rb +5 -129
  84. data/spec/praxis/request_spec.rb +3 -22
  85. data/spec/praxis/resource_definition_spec.rb +1 -1
  86. data/spec/praxis/response_definition_spec.rb +8 -9
  87. data/spec/praxis/route_spec.rb +2 -9
  88. data/spec/praxis/routing_config_spec.rb +4 -13
  89. data/spec/praxis/types/multipart_array_spec.rb +4 -21
  90. data/spec/spec_app/config/environment.rb +0 -2
  91. data/spec/spec_app/design/api.rb +7 -1
  92. data/spec/spec_app/design/media_types/instance.rb +0 -8
  93. data/spec/spec_app/design/media_types/volume.rb +0 -12
  94. data/spec/spec_app/design/resources/instances.rb +1 -2
  95. data/spec/spec_helper.rb +6 -0
  96. data/spec/support/spec_media_types.rb +0 -73
  97. metadata +51 -49
  98. data/spec/praxis/handlers/xml_spec.rb +0 -177
  99. data/spec/praxis/links_spec.rb +0 -68
@@ -50,7 +50,7 @@ module Praxis
50
50
  autoload :RestfulDocGenerator, 'praxis/restful_doc_generator'
51
51
  module Docs
52
52
  autoload :Generator, 'praxis/docs/generator'
53
- autoload :LinkBuilder, 'praxis/docs/link_builder'
53
+ autoload :OpenApiGenerator, 'praxis/docs/open_api_generator'
54
54
  end
55
55
 
56
56
  # types
@@ -60,7 +60,6 @@ module Praxis
60
60
  autoload :MultipartArray, 'praxis/types/multipart_array'
61
61
  end
62
62
 
63
- autoload :Links, 'praxis/links'
64
63
  autoload :MediaType, 'praxis/media_type'
65
64
  autoload :MediaTypeIdentifier, 'praxis/media_type_identifier'
66
65
  autoload :Multipart, 'praxis/types/multipart'
@@ -88,15 +87,19 @@ module Praxis
88
87
  autoload :MapperSelectors, 'praxis/extensions/mapper_selectors'
89
88
  autoload :Rendering, 'praxis/extensions/rendering'
90
89
  autoload :FieldExpansion, 'praxis/extensions/field_expansion'
90
+ autoload :AttributeFiltering, 'praxis/extensions/attribute_filtering'
91
91
  autoload :ActiveRecordFilterQueryBuilder, 'praxis/extensions/attribute_filtering/active_record_filter_query_builder'
92
92
  autoload :SequelFilterQueryBuilder, 'praxis/extensions/attribute_filtering/sequel_filter_query_builder'
93
+ autoload :Pagination, 'praxis/extensions/pagination'
94
+ module Pagination
95
+ autoload :ActiveRecordPaginationHandler, 'praxis/extensions/pagination/active_record_pagination_handler'
96
+ autoload :SequelPaginationHandler, 'praxis/extensions/pagination/sequel_pagination_handler'
97
+ end
93
98
  end
94
99
 
95
100
  module Handlers
96
101
  autoload :Plain, 'praxis/handlers/plain'
97
102
  autoload :JSON, 'praxis/handlers/json'
98
- autoload :WWWForm, 'praxis/handlers/www_form'
99
- autoload :XML, 'praxis/handlers/xml'
100
103
  end
101
104
 
102
105
  module BootloaderStages
@@ -12,9 +12,8 @@ module Praxis
12
12
 
13
13
  attr_reader :name
14
14
  attr_reader :resource_definition
15
- attr_reader :routes
16
- attr_reader :primary_route
17
- attr_reader :named_routes
15
+ attr_reader :api_definition
16
+ attr_reader :route
18
17
  attr_reader :responses
19
18
  attr_reader :traits
20
19
 
@@ -37,7 +36,7 @@ module Praxis
37
36
  @resource_definition = resource_definition
38
37
  @responses = Hash.new
39
38
  @metadata = Hash.new
40
- @routes = []
39
+ @route = nil
41
40
  @traits = []
42
41
 
43
42
  if (media_type = resource_definition.media_type)
@@ -179,12 +178,7 @@ module Praxis
179
178
  def routing(&block)
180
179
  @routing_config.instance_eval &block
181
180
 
182
- @routes = @routing_config.routes
183
- @primary_route = @routing_config.routes.first
184
- @named_routes = @routing_config.routes.each_with_object({}) do |route, hash|
185
- next if route.name.nil?
186
- hash[route.name] = route
187
- end
181
+ @route = @routing_config.route
188
182
  end
189
183
 
190
184
 
@@ -232,9 +226,8 @@ module Praxis
232
226
  end
233
227
  hash[:traits] = traits if traits.any?
234
228
  # FIXME: change to :routes along with api browser
235
- hash[:urls] = routes.collect do |route|
236
- ActionDefinition.url_description(route: route, params: self.params, params_example: params_example)
237
- end.compact
229
+ # FIXME: change urls to url ... (along with the browser)
230
+ hash[:urls] = [ ActionDefinition.url_description(route: route, params: self.params, params_example: params_example) ]
238
231
  self.class.doc_decorations.each do |callback|
239
232
  callback.call(self, hash)
240
233
  end
@@ -252,10 +245,10 @@ module Praxis
252
245
 
253
246
  def params_description(example:)
254
247
  route_params = []
255
- if primary_route.nil?
256
- warn "Warning: No routes defined for #{resource_definition.name}##{name}."
248
+ if route.nil?
249
+ warn "Warning: No route defined for #{resource_definition.name}##{name}."
257
250
  else
258
- route_params = primary_route.path.
251
+ route_params = route.path.
259
252
  named_captures.
260
253
  keys.
261
254
  collect(&:to_sym)
@@ -15,6 +15,19 @@ module Praxis
15
15
  end
16
16
  end
17
17
 
18
+ # Allow any custom method to get/set any value
19
+ def method_missing(name, val=nil)
20
+ if val.nil?
21
+ get(name)
22
+ else
23
+ set(name, val)
24
+ end
25
+ end
26
+
27
+ def respond_to_missing?(*)
28
+ true
29
+ end
30
+
18
31
  def get(k)
19
32
  return @data[k] if @data.key?(k)
20
33
  return @global_info.get(k) if @global_info
@@ -41,6 +54,14 @@ module Praxis
41
54
  end
42
55
  end
43
56
 
57
+ def logo_url(val=nil)
58
+ if val.nil?
59
+ get(:logo_url)
60
+ else
61
+ set(:logo_url, val)
62
+ end
63
+ end
64
+
44
65
  def description(val=nil)
45
66
  if val.nil?
46
67
  get(:description)
@@ -61,8 +61,7 @@ module Praxis
61
61
 
62
62
  builtin_handlers = {
63
63
  'plain' => Praxis::Handlers::Plain,
64
- 'json' => Praxis::Handlers::JSON,
65
- 'x-www-form-urlencoded' => Praxis::Handlers::WWWForm
64
+ 'json' => Praxis::Handlers::JSON
66
65
  }
67
66
  # Register built-in handlers unless the app already provided its own
68
67
  builtin_handlers.each_pair do |name, handler|
@@ -23,10 +23,8 @@ module Praxis
23
23
  def execute
24
24
  application.controllers.each do |controller|
25
25
  controller.definition.actions.each do |action_name, action|
26
- action.routes.each do |route|
27
- target = target_factory(controller, action_name)
28
- application.router.add_route target, route
29
- end
26
+ target = target_factory(controller, action_name)
27
+ application.router.add_route target, action.route
30
28
  end
31
29
  end
32
30
  end
@@ -120,12 +120,7 @@ module Praxis
120
120
  File.open(filename, 'w') {|f| f.write(JSON.pretty_generate(data))}
121
121
  end
122
122
 
123
- def write_version_file( version )
124
- version_info = infos_by_version[version]
125
- # Hack, let's "inherit/copy" all traits of a version from the global definition
126
- # Eventually traits should be defined for a version (and inheritable from global) so we'll emulate that here
127
- version_info[:traits] = infos_by_version[:traits]
128
- dumped_resources = dump_resources( resources_by_version[version] )
123
+ def scan_types_for_version(version, dumped_resources)
129
124
  found_media_types = resources_by_version[version].select{|r| r.media_type}.collect {|r| r.media_type.describe }
130
125
 
131
126
  # We'll start by processing the rendered mediatypes
@@ -150,7 +145,17 @@ module Praxis
150
145
  processed_types += newfound
151
146
  newfound = scan_dump_for_types( dumped, processed_types )
152
147
  end
148
+ processed_types
149
+ end
153
150
 
151
+ def write_version_file( version )
152
+ version_info = infos_by_version[version]
153
+ # Hack, let's "inherit/copy" all traits of a version from the global definition
154
+ # Eventually traits should be defined for a version (and inheritable from global) so we'll emulate that here
155
+ version_info[:traits] = infos_by_version[:traits]
156
+
157
+ dumped_resources = dump_resources( resources_by_version[version] )
158
+ processed_types = scan_types_for_version(version, dumped_resources)
154
159
  dumped_schemas = dump_schemas( processed_types )
155
160
  full_data = {
156
161
  info: version_info[:info],
@@ -0,0 +1,255 @@
1
+ require_relative 'openapi/info_object.rb'
2
+ require_relative 'openapi/server_object.rb'
3
+ require_relative 'openapi/paths_object.rb'
4
+ require_relative 'openapi/tag_object.rb'
5
+
6
+ module Praxis
7
+ module Docs
8
+
9
+ class OpenApiGenerator < Generator
10
+ API_DOCS_DIRNAME = 'docs/openapi'
11
+
12
+ # substitutes ":params_like_so" for {params_like_so}
13
+ def self.templatize_url( string )
14
+ Mustermann.new(string).to_templates.first
15
+ end
16
+
17
+ def save!
18
+ initialize_directories
19
+ # Restrict the versions listed in the index file to the ones for which we have at least 1 resource
20
+ write_index_file( for_versions: resources_by_version.keys )
21
+ resources_by_version.keys.each do |version|
22
+ write_version_file(version)
23
+ end
24
+ end
25
+
26
+ def initialize(root)
27
+ require 'yaml'
28
+ @root = root
29
+ @resources_by_version = Hash.new do |h,k|
30
+ h[k] = Set.new
31
+ end
32
+
33
+ @infos = ApiDefinition.instance.infos
34
+ collect_resources
35
+ collect_types
36
+ end
37
+
38
+ private
39
+
40
+ def write_index_file( for_versions: )
41
+ # TODO. create a simple html file that can link to the individual versions available
42
+ end
43
+
44
+ def write_version_file( version )
45
+ # version_info = infos_by_version[version]
46
+ # # Hack, let's "inherit/copy" all traits of a version from the global definition
47
+ # # Eventually traits should be defined for a version (and inheritable from global) so we'll emulate that here
48
+ # version_info[:traits] = infos_by_version[:traits]
49
+ dumped_resources = dump_resources( resources_by_version[version] )
50
+ processed_types = scan_types_for_version(version, dumped_resources)
51
+
52
+ # Here we have:
53
+ # processed types: which includes mediatypes and normal types...real classes
54
+ # processed resources for this version: resources_by_version[version]
55
+
56
+ info_object = OpenApi::InfoObject.new(version: version, api_definition_info: @infos[version])
57
+ # We only support a server in Praxis ... so we'll use the base path
58
+ server_object = OpenApi::ServerObject.new( url: @infos[version].base_path )
59
+
60
+ paths_object = OpenApi::PathsObject.new( resources: resources_by_version[version])
61
+
62
+ full_data = {
63
+ openapi: "3.0.2",
64
+ info: info_object.dump,
65
+ servers: [server_object.dump],
66
+ paths: paths_object.dump,
67
+ # responses: {}, #TODO!! what do we get here? the templates?...need to transform to "Responses Definitions Object"
68
+ # securityDefinitions: {}, # NOTE: No security definitions in Praxis
69
+ # security: [], # NOTE: No security definitions in Praxis
70
+ }
71
+
72
+ # Create the top level tags by:
73
+ # 1- First adding all the resource display names (and descriptions)
74
+ tags_for_resources = resources_by_version[version].collect do |resource|
75
+ OpenApi::TagObject.new(name: resource.display_name, description: resource.description ).dump
76
+ end
77
+ full_data[:tags] = tags_for_resources
78
+ # 2- Then adding all of the top level traits but marking them special with the x-traitTag (of Redoc)
79
+ tags_for_traits = (ApiDefinition.instance.traits).collect do |name, info|
80
+ OpenApi::TagObject.new(name: name, description: info.description).dump.merge(:'x-traitTag' => true)
81
+ end
82
+ unless tags_for_traits.empty?
83
+ full_data[:tags] = full_data[:tags] + tags_for_traits
84
+ end
85
+
86
+ # Include only MTs (i.e., not custom types or simple types...)
87
+ component_schemas = reusable_schema_objects(processed_types.select{|t| t < Praxis::MediaType})
88
+
89
+ # 3- Then adding all of the top level Mediatypes...so we can present them at the bottom, otherwise they don't show
90
+ tags_for_mts = component_schemas.map do |(name, info)|
91
+ special_redoc_anchor = "<SchemaDefinition schemaRef=\"#/components/schemas/#{name}\" showReadOnly={true} showWriteOnly={true} />"
92
+ guessed_display = name.split('-').last # TODO!!!the informational hash does not seem to come with the "description" value set...hmm
93
+ OpenApi::TagObject.new(name: name, description: special_redoc_anchor).dump.merge(:'x-displayName' => guessed_display)
94
+ end
95
+ unless tags_for_mts.empty?
96
+ full_data[:tags] = full_data[:tags] + tags_for_mts
97
+ end
98
+
99
+ # Include all the reusable schemas in the components hash
100
+ full_data[:components] = {
101
+ schemas: component_schemas
102
+ }
103
+
104
+ # REDOC specific grouping of sidebar
105
+ resource_tags = { name: 'Resources', tags: tags_for_resources.map{|t| t[:name]} }
106
+ schema_tags = { name: 'Models', tags: tags_for_mts.map{|t| t[:name]} }
107
+ full_data['x-tagGroups'] = [resource_tags, schema_tags]
108
+
109
+ # if parameter_object = convert_to_parameter_object( version_info[:info][:base_params] )
110
+ # full_data[:parameters] = parameter_object
111
+ # end
112
+ #puts JSON.pretty_generate( full_data )
113
+ # Write the file
114
+ version_file = ( version == "n/a" ? "unversioned" : version )
115
+ filename = File.join(doc_root_dir, version_file, 'openapi')
116
+
117
+ puts "Generating Open API file : #{filename} (json and yml) "
118
+ json_data = JSON.pretty_generate(full_data)
119
+ File.open(filename+".json", 'w') {|f| f.write(json_data)}
120
+ converted_full_data = JSON.parse( json_data ) # So symbols disappear
121
+ File.open(filename+".yml", 'w') {|f| f.write(YAML.dump(converted_full_data))}
122
+
123
+ html =<<-EOB
124
+ <!DOCTYPE html>
125
+ <html>
126
+ <head>
127
+ <title>ReDoc</title>
128
+ <!-- needed for adaptive design -->
129
+ <meta charset="utf-8"/>
130
+ <meta name="viewport" content="width=device-width, initial-scale=1">
131
+ <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
132
+
133
+ <!--
134
+ ReDoc doesn't change outer page styles
135
+ -->
136
+ <style>
137
+ body {
138
+ margin: 0;
139
+ padding: 0;
140
+ }
141
+ </style>
142
+ </head>
143
+ <body>
144
+ <redoc spec-url='http://localhost:9090/#{version_file}/openapi.json'></redoc>
145
+ <script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
146
+ </body>
147
+ </html>
148
+ EOB
149
+ html_file = File.join(doc_root_dir, version_file, 'index.html')
150
+ File.write(html_file, html)
151
+ end
152
+
153
+ def initialize_directories
154
+ @doc_root_dir = File.join(@root, API_DOCS_DIRNAME)
155
+
156
+ # remove previous data (and reset the directory)
157
+ FileUtils.rm_rf @doc_root_dir if File.exists?(@doc_root_dir)
158
+ FileUtils.mkdir_p @doc_root_dir unless File.exists? @doc_root_dir
159
+ resources_by_version.keys.each do |version|
160
+ FileUtils.mkdir_p @doc_root_dir + '/' + version
161
+ end
162
+ FileUtils.mkdir_p @doc_root_dir + '/unversioned'
163
+ end
164
+
165
+ def normalize_media_types( mtis )
166
+ mtis.collect do |mti|
167
+ MediaTypeIdentifier.load(mti).to_s
168
+ end
169
+ end
170
+
171
+ def reusable_schema_objects(types)
172
+ types.each_with_object({}) do |(type), accum|
173
+ the_type = \
174
+ if type.respond_to? :as_json_schema
175
+ type
176
+ else # If it is a blueprint ... for now, it'd be through the attribute
177
+ type.attribute
178
+ end
179
+ accum[type.id] = the_type.as_json_schema(shallow: false)
180
+ end
181
+ end
182
+
183
+ def convert_to_parameter_object( params )
184
+ # TODO!! actually convert each of them
185
+ puts "TODO! convert to parameter object"
186
+ params
187
+ end
188
+
189
+ def convert_traits_to_tags( traits )
190
+ traits.collect do |name, info|
191
+ { name: name, description: info[:description] }
192
+ end
193
+ end
194
+
195
+
196
+ def dump_responses_object( responses )
197
+ responses.each_with_object({}) do |(name, info), hash|
198
+ data = { description: info[:description] || "" }
199
+ if payload = info[:payload]
200
+ body_type= payload[:id]
201
+ raise "WAIT! response payload doesn't have an existing id for the schema!!! (do an if, and describe it if so)" unless body_type
202
+ data[:schema] = {"$ref" => "#/definitions/#{body_type}" }
203
+ end
204
+
205
+ # data[:schema] = ???TODO!!
206
+ if headers_object = dump_response_headers_object( info[:headers] )
207
+ data[:headers] = headers_object
208
+ end
209
+ if info[:payload] && ( examples_object = dump_response_examples_object( info[:payload][:examples] ) )
210
+ data[:examples] = examples_object
211
+ end
212
+ hash[info[:status]] = data
213
+ end
214
+ end
215
+ # def dump_response_headers_object( headers )
216
+ # puts "WARNING!! Finish this. It seems that headers for responses are never set in the hash??"
217
+ # unless headers.empty?
218
+ # binding.pry
219
+ # puts headers
220
+ # end
221
+ # end
222
+
223
+ def dump_response_examples_object( examples )
224
+ examples.each_with_object({}) do |(name, info), hash|
225
+ hash[info[:content_type]] = info[:body]
226
+ end
227
+ end
228
+
229
+
230
+ def dump_resources( resources )
231
+ resources.each_with_object({}) do |r, hash|
232
+ # Do not report undocumentable resources
233
+ next if r.metadata[:doc_visibility] == :none
234
+ context = [r.id]
235
+ resource_description = r.describe(context: context)
236
+
237
+ # strip actions with doc_visibility of :none
238
+ resource_description[:actions].reject! { |a| a[:metadata][:doc_visibility] == :none }
239
+
240
+ # Go through the params/payload of each action and augment them by
241
+ # adding a generated example (then stick it into the description hash)
242
+ r.actions.each do |action_name, action|
243
+ # skip actions with doc_visibility of :none
244
+ next if action.metadata[:doc_visibility] == :none
245
+
246
+ action_description = resource_description[:actions].find {|a| a[:name] == action_name }
247
+ end
248
+
249
+ hash[r.id] = resource_description
250
+ end
251
+ end
252
+
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,31 @@
1
+ module Praxis
2
+ module Docs
3
+ module OpenApi
4
+ class InfoObject
5
+ attr_reader :info, :version
6
+ def initialize(version: , api_definition_info: )
7
+ @version = version
8
+ @info = api_definition_info
9
+ raise "OpenApi docs require a 'Title' for your API." unless info.title
10
+ end
11
+
12
+ def dump
13
+ data ={
14
+ title: info.title,
15
+ description: info.description,
16
+ termsOfService: info.termsOfService,
17
+ contact: info.contact,
18
+ license: info.license,
19
+ version: version,
20
+ :'x-name' => info.name,
21
+ :'x-logo' => {
22
+ url: info.logo_url,
23
+ backgroundColor: "#FFFFFF",
24
+ altText: info.title
25
+ }
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end