praxis 2.0.pre.8 → 2.0.pre.13

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +1 -3
  5. data/CHANGELOG.md +33 -0
  6. data/TODO.md +1 -4
  7. data/bin/praxis +67 -12
  8. data/lib/praxis.rb +10 -3
  9. data/lib/praxis/action_definition.rb +15 -13
  10. data/lib/praxis/action_definition/headers_dsl_compiler.rb +0 -7
  11. data/lib/praxis/api_general_info.rb +1 -1
  12. data/lib/praxis/application.rb +6 -2
  13. data/lib/praxis/blueprint.rb +357 -0
  14. data/lib/praxis/bootloader.rb +9 -3
  15. data/lib/praxis/bootloader_stages/environment.rb +16 -13
  16. data/lib/praxis/collection.rb +1 -11
  17. data/lib/praxis/config_hash.rb +44 -0
  18. data/lib/praxis/docs/{openapi → open_api}/info_object.rb +18 -10
  19. data/lib/praxis/docs/{openapi → open_api}/media_type_object.rb +0 -0
  20. data/lib/praxis/docs/{openapi → open_api}/operation_object.rb +0 -0
  21. data/lib/praxis/docs/{openapi → open_api}/parameter_object.rb +0 -0
  22. data/lib/praxis/docs/{openapi → open_api}/paths_object.rb +0 -0
  23. data/lib/praxis/docs/{openapi → open_api}/request_body_object.rb +0 -0
  24. data/lib/praxis/docs/{openapi → open_api}/response_object.rb +0 -0
  25. data/lib/praxis/docs/{openapi → open_api}/responses_object.rb +0 -0
  26. data/lib/praxis/docs/{openapi → open_api}/schema_object.rb +0 -0
  27. data/lib/praxis/docs/{openapi → open_api}/server_object.rb +0 -0
  28. data/lib/praxis/docs/{openapi → open_api}/tag_object.rb +0 -0
  29. data/lib/praxis/docs/open_api_generator.rb +91 -6
  30. data/lib/praxis/endpoint_definition.rb +273 -0
  31. data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +182 -58
  32. data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +3 -2
  33. data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +47 -56
  34. data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +153 -0
  35. data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +20 -8
  36. data/lib/praxis/extensions/field_expansion.rb +3 -36
  37. data/lib/praxis/extensions/pagination.rb +5 -32
  38. data/lib/praxis/extensions/pagination/ordering_params.rb +1 -1
  39. data/lib/praxis/extensions/pagination/pagination_params.rb +6 -4
  40. data/lib/praxis/field_expander.rb +90 -0
  41. data/lib/praxis/finalizable.rb +34 -0
  42. data/lib/praxis/mapper/active_model_compat.rb +4 -0
  43. data/lib/praxis/mapper/resource.rb +18 -2
  44. data/lib/praxis/mapper/selector_generator.rb +2 -1
  45. data/lib/praxis/mapper/sequel_compat.rb +7 -0
  46. data/lib/praxis/media_type.rb +3 -68
  47. data/lib/praxis/plugin_concern.rb +1 -1
  48. data/lib/praxis/plugins/mapper_plugin.rb +24 -15
  49. data/lib/praxis/plugins/pagination_plugin.rb +34 -4
  50. data/lib/praxis/renderer.rb +88 -0
  51. data/lib/praxis/request.rb +1 -1
  52. data/lib/praxis/resource_definition.rb +2 -311
  53. data/lib/praxis/response_definition.rb +2 -10
  54. data/lib/praxis/response_template.rb +3 -3
  55. data/lib/praxis/router.rb +2 -2
  56. data/lib/praxis/routing_config.rb +1 -1
  57. data/lib/praxis/tasks/api_docs.rb +17 -64
  58. data/lib/praxis/tasks/routes.rb +1 -1
  59. data/lib/praxis/types/media_type_common.rb +1 -11
  60. data/lib/praxis/version.rb +1 -1
  61. data/praxis.gemspec +0 -1
  62. data/spec/functional_spec.rb +5 -9
  63. data/spec/praxis/action_definition_spec.rb +12 -20
  64. data/spec/praxis/blueprint_spec.rb +373 -0
  65. data/spec/praxis/bootloader_spec.rb +10 -2
  66. data/spec/praxis/collection_spec.rb +0 -13
  67. data/spec/praxis/config_hash_spec.rb +64 -0
  68. data/spec/praxis/{resource_definition_spec.rb → endpoint_definition_spec.rb} +37 -64
  69. data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +249 -168
  70. data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +25 -6
  71. data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +190 -8
  72. data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +140 -0
  73. data/spec/praxis/extensions/field_expansion_spec.rb +5 -24
  74. data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +1 -1
  75. data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +1 -1
  76. data/spec/praxis/extensions/support/spec_resources_active_model.rb +1 -1
  77. data/spec/praxis/field_expander_spec.rb +149 -0
  78. data/spec/praxis/mapper/selector_generator_spec.rb +1 -1
  79. data/spec/praxis/media_type_identifier_spec.rb +5 -4
  80. data/spec/praxis/media_type_spec.rb +4 -93
  81. data/spec/praxis/renderer_spec.rb +188 -0
  82. data/spec/praxis/response_definition_spec.rb +0 -31
  83. data/spec/praxis/response_spec.rb +1 -1
  84. data/spec/praxis/router_spec.rb +8 -8
  85. data/spec/praxis/routing_config_spec.rb +3 -3
  86. data/spec/spec_app/app/controllers/instances.rb +13 -7
  87. data/spec/spec_app/design/media_types/instance.rb +1 -19
  88. data/spec/spec_app/design/media_types/volume.rb +1 -1
  89. data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -14
  90. data/spec/spec_app/design/resources/instances.rb +5 -8
  91. data/spec/spec_app/design/resources/volume_snapshots.rb +1 -1
  92. data/spec/spec_app/design/resources/volumes.rb +1 -1
  93. data/spec/support/spec_authorization_plugin.rb +1 -1
  94. data/spec/support/spec_blueprints.rb +72 -0
  95. data/spec/support/{spec_resource_definitions.rb → spec_endpoint_definitions.rb} +2 -2
  96. data/spec/support/spec_media_types.rb +6 -26
  97. data/tasks/thor/app.rb +8 -34
  98. data/tasks/thor/example.rb +51 -285
  99. data/tasks/thor/model.rb +40 -0
  100. data/tasks/thor/scaffold.rb +117 -0
  101. data/tasks/thor/templates/generator/empty_app/.gitignore +0 -1
  102. data/tasks/thor/templates/generator/empty_app/Gemfile +7 -23
  103. data/tasks/thor/templates/generator/empty_app/README.md +1 -1
  104. data/tasks/thor/templates/generator/empty_app/Rakefile +4 -13
  105. data/tasks/thor/templates/generator/empty_app/{design/response_templates → app/v1/resources}/.empty_directory +0 -0
  106. data/tasks/thor/templates/generator/empty_app/{design/response_templates → app/v1/resources}/.gitkeep +0 -0
  107. data/tasks/thor/templates/generator/empty_app/config/environment.rb +26 -17
  108. data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.empty_directory +0 -0
  109. data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.gitkeep +0 -0
  110. data/tasks/thor/templates/generator/empty_app/design/v1/endpoints/.empty_directory +0 -0
  111. data/tasks/thor/templates/generator/empty_app/design/v1/endpoints/.gitkeep +0 -0
  112. data/tasks/thor/templates/generator/empty_app/docs/.empty_directory +0 -0
  113. data/tasks/thor/templates/generator/empty_app/docs/.gitkeep +0 -0
  114. data/tasks/thor/templates/generator/empty_app/spec/spec_helper.rb +14 -9
  115. data/tasks/thor/templates/generator/example_app/.gitignore +1 -0
  116. data/tasks/thor/templates/generator/example_app/Gemfile +19 -0
  117. data/tasks/thor/templates/generator/example_app/Rakefile +61 -0
  118. data/tasks/thor/templates/generator/example_app/app/models/user.rb +6 -0
  119. data/tasks/thor/templates/generator/example_app/app/v1/concerns/controller_base.rb +24 -0
  120. data/tasks/thor/templates/generator/example_app/app/v1/controllers/users.rb +17 -0
  121. data/tasks/thor/templates/generator/example_app/app/v1/resources/base.rb +11 -0
  122. data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +25 -0
  123. data/tasks/thor/templates/generator/example_app/config.ru +30 -0
  124. data/tasks/thor/templates/generator/example_app/config/environment.rb +41 -0
  125. data/tasks/thor/templates/generator/example_app/db/migrate/20201010101010_create_users_table.rb +12 -0
  126. data/tasks/thor/templates/generator/example_app/db/seeds.rb +6 -0
  127. data/tasks/thor/templates/generator/example_app/design/api.rb +18 -0
  128. data/tasks/thor/templates/generator/example_app/design/v1/endpoints/users.rb +37 -0
  129. data/tasks/thor/templates/generator/example_app/design/v1/media_types/user.rb +21 -0
  130. data/tasks/thor/templates/generator/example_app/spec/helpers/database_helper.rb +20 -0
  131. data/tasks/thor/templates/generator/example_app/spec/spec_helper.rb +42 -0
  132. data/tasks/thor/templates/generator/example_app/spec/v1/controllers/users_spec.rb +37 -0
  133. data/tasks/thor/templates/generator/scaffold/design/endpoints/collection.rb +98 -0
  134. data/tasks/thor/templates/generator/scaffold/design/media_types/item.rb +18 -0
  135. data/tasks/thor/templates/generator/scaffold/implementation/controllers/collection.rb +77 -0
  136. data/tasks/thor/templates/generator/scaffold/implementation/resources/base.rb +11 -0
  137. data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +45 -0
  138. data/tasks/thor/templates/generator/scaffold/models/active_record.rb +6 -0
  139. data/tasks/thor/templates/generator/scaffold/models/sequel.rb +6 -0
  140. metadata +64 -136
  141. data/lib/api_browser/.bowerrc +0 -3
  142. data/lib/api_browser/.editorconfig +0 -21
  143. data/lib/api_browser/Gruntfile.js +0 -581
  144. data/lib/api_browser/app/index.html +0 -59
  145. data/lib/api_browser/app/js/app.js +0 -48
  146. data/lib/api_browser/app/js/controllers/action.js +0 -47
  147. data/lib/api_browser/app/js/controllers/controller.js +0 -10
  148. data/lib/api_browser/app/js/controllers/menu.js +0 -93
  149. data/lib/api_browser/app/js/controllers/trait.js +0 -10
  150. data/lib/api_browser/app/js/controllers/type.js +0 -24
  151. data/lib/api_browser/app/js/directives/attribute_description.js +0 -56
  152. data/lib/api_browser/app/js/directives/attribute_table.js +0 -28
  153. data/lib/api_browser/app/js/directives/conditional_requirements.js +0 -13
  154. data/lib/api_browser/app/js/directives/fixed_if_fits.js +0 -38
  155. data/lib/api_browser/app/js/directives/highlight.js +0 -14
  156. data/lib/api_browser/app/js/directives/menu_item.js +0 -59
  157. data/lib/api_browser/app/js/directives/no_container.js +0 -8
  158. data/lib/api_browser/app/js/directives/readable_list.js +0 -87
  159. data/lib/api_browser/app/js/directives/request_examples.js +0 -31
  160. data/lib/api_browser/app/js/directives/type_placeholder.js +0 -30
  161. data/lib/api_browser/app/js/directives/url.js +0 -15
  162. data/lib/api_browser/app/js/factories/Configuration.js +0 -12
  163. data/lib/api_browser/app/js/factories/Documentation.js +0 -61
  164. data/lib/api_browser/app/js/factories/Example.js +0 -51
  165. data/lib/api_browser/app/js/factories/PageInfo.js +0 -9
  166. data/lib/api_browser/app/js/factories/normalize_attributes.js +0 -20
  167. data/lib/api_browser/app/js/factories/prepare_template.js +0 -15
  168. data/lib/api_browser/app/js/factories/template_for.js +0 -128
  169. data/lib/api_browser/app/js/filters/attribute_name.js +0 -10
  170. data/lib/api_browser/app/js/filters/friendly_json.js +0 -5
  171. data/lib/api_browser/app/js/filters/has_requirement.js +0 -14
  172. data/lib/api_browser/app/js/filters/header_info.js +0 -9
  173. data/lib/api_browser/app/js/filters/is_empty.js +0 -8
  174. data/lib/api_browser/app/js/filters/markdown.js +0 -6
  175. data/lib/api_browser/app/js/filters/resource_name.js +0 -5
  176. data/lib/api_browser/app/js/filters/tag_requirement.js +0 -13
  177. data/lib/api_browser/app/sass/modules/_body.scss +0 -40
  178. data/lib/api_browser/app/sass/modules/_cloke.scss +0 -8
  179. data/lib/api_browser/app/sass/modules/_header.scss +0 -10
  180. data/lib/api_browser/app/sass/modules/_nav.scss +0 -7
  181. data/lib/api_browser/app/sass/modules/_sidebar.scss +0 -134
  182. data/lib/api_browser/app/sass/modules/_switch.scss +0 -55
  183. data/lib/api_browser/app/sass/modules/_table.scss +0 -13
  184. data/lib/api_browser/app/sass/praxis.scss +0 -70
  185. data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +0 -774
  186. data/lib/api_browser/app/views/action.html +0 -97
  187. data/lib/api_browser/app/views/builtin/field-selector.html +0 -24
  188. data/lib/api_browser/app/views/controller.html +0 -55
  189. data/lib/api_browser/app/views/directives/attribute_description.html +0 -2
  190. data/lib/api_browser/app/views/directives/attribute_description/default.html +0 -2
  191. data/lib/api_browser/app/views/directives/attribute_description/example.html +0 -13
  192. data/lib/api_browser/app/views/directives/attribute_description/headers.html +0 -8
  193. data/lib/api_browser/app/views/directives/attribute_description/member_options.html +0 -4
  194. data/lib/api_browser/app/views/directives/attribute_description/values.html +0 -14
  195. data/lib/api_browser/app/views/directives/attribute_table.html +0 -17
  196. data/lib/api_browser/app/views/directives/menu_item.html +0 -8
  197. data/lib/api_browser/app/views/directives/url.html +0 -3
  198. data/lib/api_browser/app/views/examples/general.html +0 -26
  199. data/lib/api_browser/app/views/home.html +0 -5
  200. data/lib/api_browser/app/views/layout.html +0 -8
  201. data/lib/api_browser/app/views/menu.html +0 -42
  202. data/lib/api_browser/app/views/navbar.html +0 -9
  203. data/lib/api_browser/app/views/trait.html +0 -13
  204. data/lib/api_browser/app/views/type.html +0 -6
  205. data/lib/api_browser/app/views/type/details.html +0 -33
  206. data/lib/api_browser/app/views/types/embedded/array.html +0 -2
  207. data/lib/api_browser/app/views/types/embedded/default.html +0 -12
  208. data/lib/api_browser/app/views/types/embedded/field-selector.html +0 -13
  209. data/lib/api_browser/app/views/types/embedded/links.html +0 -11
  210. data/lib/api_browser/app/views/types/embedded/requirements.html +0 -6
  211. data/lib/api_browser/app/views/types/embedded/single_req.html +0 -9
  212. data/lib/api_browser/app/views/types/embedded/struct.html +0 -14
  213. data/lib/api_browser/app/views/types/label/link.html +0 -1
  214. data/lib/api_browser/app/views/types/label/primitive.html +0 -1
  215. data/lib/api_browser/app/views/types/label/primitive_collection.html +0 -1
  216. data/lib/api_browser/app/views/types/label/type.html +0 -1
  217. data/lib/api_browser/app/views/types/label/type_collection.html +0 -1
  218. data/lib/api_browser/app/views/types/main/array.html +0 -22
  219. data/lib/api_browser/app/views/types/main/default.html +0 -23
  220. data/lib/api_browser/app/views/types/main/hash.html +0 -23
  221. data/lib/api_browser/app/views/types/standalone/array.html +0 -3
  222. data/lib/api_browser/app/views/types/standalone/default.html +0 -18
  223. data/lib/api_browser/app/views/types/standalone/struct.html +0 -2
  224. data/lib/api_browser/bower_template.json +0 -41
  225. data/lib/api_browser/package-lock.json +0 -7110
  226. data/lib/api_browser/package.json +0 -43
  227. data/lib/praxis/docs/generator.rb +0 -243
  228. data/lib/praxis/docs/link_builder.rb +0 -30
  229. data/lib/praxis/links.rb +0 -135
  230. data/lib/praxis/types/multipart.rb +0 -109
  231. data/spec/api_browser/directives/type_placeholder_spec.js +0 -134
  232. data/spec/api_browser/factories/configuration_spec.js +0 -32
  233. data/spec/api_browser/factories/documentation_spec.js +0 -100
  234. data/spec/api_browser/factories/normalize_attributes_spec.js +0 -92
  235. data/spec/api_browser/factories/template_for_spec.js +0 -67
  236. data/spec/api_browser/filters/attribute_name_spec.js +0 -23
  237. data/spec/praxis/types/multipart_spec.rb +0 -112
  238. data/tasks/thor/templates/generator/empty_app/.rspec +0 -1
  239. data/tasks/thor/templates/generator/empty_app/Guardfile +0 -3
  240. data/tasks/thor/templates/generator/empty_app/config/rainbows.rb +0 -57
  241. data/tasks/thor/templates/generator/empty_app/docs/app.js +0 -1
  242. data/tasks/thor/templates/generator/empty_app/docs/styles.scss +0 -3
@@ -1,43 +0,0 @@
1
- {
2
- "name": "api_doc_browser",
3
- "version": "0.13.0",
4
- "description": "Praxis API Browser app",
5
- "repository": "https://github.com/praxis/praxis",
6
- "private": true,
7
- "scripts": {
8
- "test": "node_modules/.bin/grunt ci"
9
- },
10
- "author": "",
11
- "license": "BSD",
12
- "dependencies": {
13
- "grunt": "~0.4.2",
14
- "grunt-angular-templates": "^0.5.5",
15
- "grunt-cli": "^0.1.13",
16
- "grunt-contrib-clean": "^0.5.0",
17
- "grunt-contrib-concat": "^0.4.0",
18
- "grunt-contrib-connect": "^0.7.1",
19
- "grunt-contrib-copy": "^0.5.0",
20
- "grunt-contrib-cssmin": "^0.9.0",
21
- "grunt-contrib-uglify": "^0.4.0",
22
- "grunt-contrib-watch": "~0.5.3",
23
- "grunt-file-blocks": "^0.3.0",
24
- "grunt-filerev": "^0.2.1",
25
- "grunt-ng-annotate": "^0.10.0",
26
- "grunt-sass": "^1.0.0",
27
- "grunt-usemin": "^2.1.1",
28
- "grunt-wiredep": "^1.7.0",
29
- "load-grunt-tasks": "^0.4.0",
30
- "package-merge": "gampleman/package-merge",
31
- "bower": "^1.7.0"
32
- },
33
- "devDependencies": {
34
- "grunt-contrib-jshint": "^0.11.0",
35
- "grunt-karma": "^0.10.1",
36
- "jasmine-core": "^2.2.0",
37
- "karma": "^0.12.31",
38
- "karma-jasmine": "^0.3.5",
39
- "karma-phantomjs-launcher": "^0.1.4",
40
- "quick_check": "^0.4.2",
41
- "time-grunt": "^0.3.1"
42
- }
43
- }
@@ -1,243 +0,0 @@
1
- module Praxis
2
- module Docs
3
-
4
- class Generator
5
- require 'active_support/core_ext/enumerable' # For index_by
6
-
7
- API_DOCS_DIRNAME = 'docs/api'
8
-
9
- attr_reader :resources_by_version, :types_by_id, :infos_by_version
10
- attr_reader :doc_root_dir
11
-
12
- EXCLUDED_TYPES_FROM_OUTPUT = Set.new([
13
- Attributor::Boolean,
14
- Attributor::CSV,
15
- Attributor::DateTime,
16
- Attributor::Date,
17
- Attributor::Float,
18
- Attributor::Hash,
19
- Attributor::Ids,
20
- Attributor::Integer,
21
- Attributor::Object,
22
- Attributor::String,
23
- Attributor::Symbol,
24
- Attributor::URI,
25
- ]).freeze
26
-
27
-
28
- def initialize(root)
29
- require 'yaml'
30
- @resources_by_version = Hash.new do |h,k|
31
- h[k] = Set.new
32
- end
33
- initialize_directories(root)
34
-
35
- Attributor::AttributeResolver.current = Attributor::AttributeResolver.new
36
- collect_infos
37
- collect_resources
38
- collect_types
39
- end
40
-
41
- def save!
42
- # Restrict the versions listed in the index file to the ones for which we have at least 1 resource
43
- write_index_file( for_versions: resources_by_version.keys )
44
- resources_by_version.keys.each do |version|
45
- write_version_file(version)
46
- end
47
- end
48
-
49
- private
50
-
51
- def initialize_directories(root)
52
- @doc_root_dir = File.join(root, API_DOCS_DIRNAME)
53
-
54
- # remove previous data (and reset the directory)
55
- FileUtils.rm_rf @doc_root_dir if File.exists?(@doc_root_dir)
56
- FileUtils.mkdir_p @doc_root_dir unless File.exists? @doc_root_dir
57
- end
58
-
59
- def collect_resources
60
- # load all resource definitions registered with Praxis
61
- Praxis::Application.instance.resource_definitions.map do |resource|
62
- # skip resources with doc_visibility of :none
63
- next if resource.metadata[:doc_visibility] == :none
64
- version = resource.version
65
- # TODO: it seems that we shouldn't hardcode n/a in Praxis
66
- # version = "unversioned" if version == "n/a"
67
- @resources_by_version[version] << resource
68
- end
69
- end
70
-
71
- def collect_types
72
- @types_by_id = ObjectSpace.each_object( Class ).select do |obj|
73
- obj < Attributor::Type
74
- end.index_by(&:id)
75
- end
76
-
77
- def collect_infos
78
- # All infos. Including keys for `:global`, "n/a", and any string version
79
- @infos_by_version = ApiDefinition.instance.describe
80
- end
81
-
82
-
83
- # Data: hash/array structure of dumped resources and/or types
84
- # processed_types: list of type classes that have already gone through a describe+collect (this or previous rounds)
85
- # ... any processed type won't need to be described+reached any longer
86
- # newly_found: list of type classes that have been seen in the search (and that weren't already in the processed type)
87
- def scan_dump_for_types( data, processed_types )
88
- newfound_types = Set.new
89
- case data
90
- when Array
91
- data.collect{|item| newfound_types += scan_dump_for_types( item , processed_types ) }
92
- when Hash
93
- if data.key?(:type) && data[:type].kind_of?(Hash) && ( [:id,:name,:family] - data[:type].keys ).empty?
94
- type_id = data[:type][:id]
95
- unless type_id.nil? || type_id == Praxis::SimpleMediaType.id #SimpleTypes shouldn't be collected
96
- unless types_by_id[type_id]
97
- raise "Error! We have detected a reference to a 'Type' with id='#{type_id}' which is not derived from Attributor::Type" +
98
- " Document generation cannot proceed."
99
- end
100
- newfound_types << types_by_id[type_id] unless processed_types.include? types_by_id[type_id]
101
- end
102
- end
103
- data.values.map{|item| newfound_types += scan_dump_for_types( item , processed_types)}
104
- end
105
- newfound_types
106
- end
107
-
108
- def write_index_file( for_versions: )
109
- # Gather the versions
110
- versions = infos_by_version.keys.reject{|v| v == :global || v == :traits || !for_versions.include?(v) }.map do |version|
111
- version == "n/a" ? "unversioned" : version
112
- end
113
- data = {
114
- info: infos_by_version[:global][:info],
115
- versions: versions
116
- # Note, I don't think we need to report the global traits (but rather the ones in the version)
117
- }
118
- filename = File.join(doc_root_dir, "index-new.json")
119
- puts "Generating Index file: #{filename}"
120
- File.open(filename, 'w') {|f| f.write(JSON.pretty_generate(data))}
121
- end
122
-
123
- def scan_types_for_version(version, dumped_resources)
124
- found_media_types = resources_by_version[version].select{|r| r.media_type}.collect {|r| r.media_type.describe }
125
-
126
- # We'll start by processing the rendered mediatypes
127
- processed_types = Set.new(resources_by_version[version].select do|r|
128
- r.media_type && !r.media_type.is_a?(Praxis::SimpleMediaType)
129
- end.collect(&:media_type))
130
-
131
- newfound = Set.new
132
- found_media_types.each do |mt|
133
- newfound += scan_dump_for_types( { type: mt} , processed_types )
134
- end
135
- # Then will process the rendered resources (noting)
136
- newfound += scan_dump_for_types( dumped_resources, Set.new )
137
-
138
- # At this point we've done a scan of the dumped resources and mediatypes.
139
- # In that scan we've discovered a bunch of types, however, many of those might have appeared in the JSON
140
- # rendered in just shallow mode, so it is not guaranteed that we've seen all the available types.
141
- # For that we'll do a (non-shallow) dump of all the types we found, and scan them until the scans do not
142
- # yield types we haven't seen before
143
- while !newfound.empty? do
144
- dumped = newfound.collect(&:describe)
145
- processed_types += newfound
146
- newfound = scan_dump_for_types( dumped, processed_types )
147
- end
148
- processed_types
149
- end
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)
159
- dumped_schemas = dump_schemas( processed_types )
160
- full_data = {
161
- info: version_info[:info],
162
- resources: dumped_resources,
163
- schemas: dumped_schemas,
164
- traits: version_info[:traits] || []
165
- }
166
- # Write the file
167
- version_file = ( version == "n/a" ? "unversioned" : version )
168
- filename = File.join(doc_root_dir, version_file)
169
-
170
- puts "Generating API file: #{filename} (in json and yaml)"
171
- File.open(filename+".json", 'w') {|f| f.write(JSON.pretty_generate(full_data))}
172
- File.open(filename+".yml", 'w') {|f| f.write(YAML.dump(full_data))}
173
- end
174
-
175
-
176
- def dump_resources( resources )
177
- resources.each_with_object({}) do |r, hash|
178
- # Do not report undocumentable resources
179
- next if r.metadata[:doc_visibility] == :none
180
- context = [r.id]
181
- resource_description = r.describe(context: context)
182
-
183
- # strip actions with doc_visibility of :none
184
- resource_description[:actions].reject! { |a| a[:metadata][:doc_visibility] == :none }
185
-
186
- # Go through the params/payload of each action and augment them by
187
- # adding a generated example (then stick it into the description hash)
188
- r.actions.each do |action_name, action|
189
- # skip actions with doc_visibility of :none
190
- next if action.metadata[:doc_visibility] == :none
191
-
192
- action_description = resource_description[:actions].find {|a| a[:name] == action_name }
193
- end
194
-
195
- hash[r.id] = resource_description
196
- end
197
- end
198
-
199
-
200
- def dump_schemas(types)
201
- reportable_types = types - EXCLUDED_TYPES_FROM_OUTPUT
202
- reportable_types.each_with_object({}) do |type, array|
203
- next if ( type.respond_to?(:anonymous?) && type.anonymous? )
204
-
205
- context = [type.id]
206
- example_data = type.example(context)
207
- type_output = type.describe(false, example: example_data)
208
-
209
- type_output[:display_name] = type.display_name if type.respond_to?(:display_name)
210
- unless type_output[:display_name]
211
- # For non MediaTypes or pure types or anonymous types fallback to their name, and worst case to their id
212
- type_output[:display_name] = type_output[:name] || type_output[:id]
213
- end
214
- if type_output[:views]
215
- type_output[:views].delete(:master)
216
- type_output[:views].each do |view_name, view_info|
217
- view_info[:example] = example_data.render(view: view_name)
218
- end
219
- end
220
- type_output[:example] = if example_data.respond_to? :render
221
- example_data.render(view: :master)
222
- else
223
- type.dump(example_data)
224
- end
225
- array[type.id] = type_output
226
- end
227
- end
228
-
229
-
230
- def dump_example_for(context_name, object)
231
- example = object.example(Array(context_name))
232
- if object.is_a? Praxis::Blueprint
233
- example.render(view: :master)
234
- elsif object.is_a? Attributor::Attribute
235
- object.dump(example)
236
- else
237
- raise "Do not know how to dump this object (it is not a Blueprint or an Attribute): #{object}"
238
- end
239
- end
240
-
241
- end
242
- end
243
- end
@@ -1,30 +0,0 @@
1
- module Praxis
2
- module Docs
3
- # Generates links into the generated doc browser.
4
- class LinkBuilder
5
- include Singleton
6
-
7
- # Generates a link based on a request gone wrong.
8
- # @return [String, nil] The doc browser link.
9
- def for_request(req)
10
- build_link req.version, 'controller', req.action.resource_definition.id, req.action.name
11
- end
12
-
13
- private
14
-
15
- def build_link(*segments)
16
- if endpoint
17
- endpoint + '#' + segments.join('/')
18
- end
19
- end
20
-
21
- def endpoint
22
- @endpoint ||= begin
23
- endpoint = ApiDefinition.instance.global_info.documentation_url
24
- endpoint.gsub(/\/index\.html$/i, '/') if endpoint
25
- end
26
- end
27
- end
28
-
29
- end
30
- end
data/lib/praxis/links.rb DELETED
@@ -1,135 +0,0 @@
1
- module Praxis
2
-
3
- # Container for links for a given type
4
- class Links < Praxis::Blueprint
5
-
6
- class DSLCompiler < Attributor::DSLCompiler
7
- attr_reader :links
8
- def initialize(target, dsl_compiler_options:{}, **options)
9
- @links = dsl_compiler_options[:links]
10
-
11
- super
12
- end
13
-
14
- def link(name, type=nil, using: name, **opts, &block)
15
- links[name] = using
16
- if type.nil? && (name != using)
17
- type = options[:reference].attributes[using].type
18
- end
19
- attribute(name, type, **opts, &block)
20
- end
21
- end
22
-
23
- class << self
24
- attr_reader :links
25
- end
26
-
27
- def self.for(reference)
28
- if defined?(reference::Links)
29
- return reference::Links
30
- end
31
-
32
- klass = Class.new(self) do
33
- @reference = reference
34
- @links = Hash.new
35
- anonymous_type
36
- end
37
-
38
- reference.const_set :Links, klass
39
- end
40
-
41
- def self.constructable?
42
- true
43
- end
44
-
45
- def self.construct(constructor_block, options)
46
- options[:reference] = @reference
47
- options[:dsl_compiler_options] = {links: self.links}
48
-
49
- self.attributes(options, &constructor_block)
50
- self
51
- end
52
-
53
- def self.describe(shallow=false,**opts)
54
- super(false,**opts) # Links must always describe attributes
55
- end
56
-
57
- def self.json_schema_type
58
- @attribute.type.json_schema_type
59
- end
60
-
61
- def self._finalize!
62
- super
63
- if @attribute
64
- # Master and default views must be set for all attributes, always using their :link view
65
- self.define_default_view
66
- self.define_master_view
67
- self.fixup_reference_struct_methods
68
- end
69
- end
70
-
71
- def self.define_reader!(name)
72
- # it's faster to use define_method in this case than module_eval
73
- # because we save the attribute lookup on every access.
74
- attribute = self.attributes[name]
75
- using = self.links.fetch(name) do
76
- raise Exceptions::InvalidConfiguration.new("Cannot define attribute for #{name.inspect}")
77
- end
78
-
79
- define_method(name) do
80
- value = @object.__send__(using)
81
- return value if value.nil? || value.kind_of?(attribute.type)
82
- attribute.load(value)
83
- end
84
-
85
- # do whatever crazy aliasing we need to here....
86
- unless name == using
87
- @attribute.type.instance_eval do
88
- define_method(using) do
89
- self.__send__(name)
90
- end
91
- end
92
- end
93
-
94
- end
95
-
96
- def self.define_default_view
97
- return unless view(:default).nil?
98
-
99
- view(:default) {}
100
- self.attributes.each do |name, attribute|
101
- view(:default).attribute(name, view: :link)
102
- end
103
- end
104
-
105
- def self.define_master_view
106
-
107
- view(:master) {}
108
- self.attributes.each do |name, attribute|
109
- view(:master).attribute(name, view: :link)
110
- end
111
- end
112
-
113
- # Define methods on the inner Struct class for
114
- # links that do not have corresponding top-level attributes.
115
- # This is primarily necessary only for example generation.
116
- def self.fixup_reference_struct_methods
117
- self.links.each do |name, using|
118
- next if @reference.attribute.attributes.has_key?(using)
119
- @reference.attribute.type.instance_eval do
120
- define_method(using) do
121
- return nil unless attributes[:links]
122
- attributes[:links].__send__(name)
123
- end
124
- end
125
- end
126
- end
127
-
128
- def self.validate(*args)
129
- # FIXME: what to validate for links?
130
- []
131
- end
132
-
133
- end
134
-
135
- end