praxis 2.0.pre.6 → 2.0.pre.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +1 -3
- data/CHANGELOG.md +25 -0
- data/TODO.md +1 -4
- data/bin/praxis +67 -12
- data/lib/praxis.rb +10 -3
- data/lib/praxis/action_definition.rb +15 -13
- data/lib/praxis/action_definition/headers_dsl_compiler.rb +0 -7
- data/lib/praxis/api_general_info.rb +1 -1
- data/lib/praxis/application.rb +6 -2
- data/lib/praxis/blueprint.rb +357 -0
- data/lib/praxis/bootloader.rb +9 -3
- data/lib/praxis/bootloader_stages/environment.rb +16 -13
- data/lib/praxis/collection.rb +1 -11
- data/lib/praxis/config_hash.rb +44 -0
- data/lib/praxis/docs/{openapi → open_api}/info_object.rb +18 -10
- data/lib/praxis/docs/{openapi → open_api}/media_type_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/operation_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/parameter_object.rb +2 -2
- data/lib/praxis/docs/{openapi → open_api}/paths_object.rb +12 -15
- data/lib/praxis/docs/{openapi → open_api}/request_body_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/response_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/responses_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/schema_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/server_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/tag_object.rb +0 -0
- data/lib/praxis/docs/open_api_generator.rb +91 -6
- data/lib/praxis/endpoint_definition.rb +273 -0
- data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +57 -8
- data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +3 -16
- data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +20 -8
- data/lib/praxis/extensions/field_expansion.rb +3 -36
- data/lib/praxis/extensions/pagination.rb +5 -32
- data/lib/praxis/extensions/pagination/ordering_params.rb +5 -1
- data/lib/praxis/extensions/pagination/pagination_params.rb +10 -4
- data/lib/praxis/field_expander.rb +90 -0
- data/lib/praxis/finalizable.rb +34 -0
- data/lib/praxis/mapper/active_model_compat.rb +4 -0
- data/lib/praxis/mapper/resource.rb +18 -2
- data/lib/praxis/mapper/selector_generator.rb +2 -1
- data/lib/praxis/mapper/sequel_compat.rb +7 -0
- data/lib/praxis/media_type.rb +3 -68
- data/lib/praxis/plugin_concern.rb +1 -1
- data/lib/praxis/plugins/mapper_plugin.rb +24 -15
- data/lib/praxis/plugins/pagination_plugin.rb +34 -4
- data/lib/praxis/renderer.rb +88 -0
- data/lib/praxis/request.rb +1 -1
- data/lib/praxis/resource_definition.rb +2 -311
- data/lib/praxis/response_definition.rb +2 -10
- data/lib/praxis/response_template.rb +3 -3
- data/lib/praxis/router.rb +2 -2
- data/lib/praxis/routing_config.rb +1 -1
- data/lib/praxis/tasks/api_docs.rb +17 -64
- data/lib/praxis/tasks/routes.rb +2 -2
- data/lib/praxis/types/media_type_common.rb +1 -11
- data/lib/praxis/version.rb +1 -1
- data/praxis.gemspec +0 -1
- data/spec/functional_spec.rb +5 -9
- data/spec/praxis/action_definition_spec.rb +12 -20
- data/spec/praxis/blueprint_spec.rb +373 -0
- data/spec/praxis/bootloader_spec.rb +10 -2
- data/spec/praxis/collection_spec.rb +0 -13
- data/spec/praxis/config_hash_spec.rb +64 -0
- data/spec/praxis/{resource_definition_spec.rb → endpoint_definition_spec.rb} +37 -64
- data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +19 -8
- data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +106 -0
- data/spec/praxis/extensions/field_expansion_spec.rb +5 -24
- data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +1 -1
- data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +1 -1
- data/spec/praxis/extensions/support/spec_resources_active_model.rb +1 -1
- data/spec/praxis/field_expander_spec.rb +149 -0
- data/spec/praxis/mapper/selector_generator_spec.rb +1 -1
- data/spec/praxis/media_type_identifier_spec.rb +5 -4
- data/spec/praxis/media_type_spec.rb +4 -93
- data/spec/praxis/renderer_spec.rb +188 -0
- data/spec/praxis/response_definition_spec.rb +0 -31
- data/spec/praxis/response_spec.rb +1 -1
- data/spec/praxis/router_spec.rb +8 -8
- data/spec/praxis/routing_config_spec.rb +3 -3
- data/spec/spec_app/app/controllers/instances.rb +13 -7
- data/spec/spec_app/design/media_types/instance.rb +1 -19
- data/spec/spec_app/design/media_types/volume.rb +1 -1
- data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -14
- data/spec/spec_app/design/resources/instances.rb +5 -8
- data/spec/spec_app/design/resources/volume_snapshots.rb +1 -1
- data/spec/spec_app/design/resources/volumes.rb +1 -1
- data/spec/support/spec_authorization_plugin.rb +1 -1
- data/spec/support/spec_blueprints.rb +72 -0
- data/spec/support/{spec_resource_definitions.rb → spec_endpoint_definitions.rb} +2 -2
- data/spec/support/spec_media_types.rb +6 -26
- data/tasks/thor/app.rb +8 -34
- data/tasks/thor/example.rb +51 -285
- data/tasks/thor/model.rb +40 -0
- data/tasks/thor/scaffold.rb +117 -0
- data/tasks/thor/templates/generator/empty_app/.gitignore +0 -1
- data/tasks/thor/templates/generator/empty_app/Gemfile +7 -23
- data/tasks/thor/templates/generator/empty_app/README.md +1 -1
- data/tasks/thor/templates/generator/empty_app/Rakefile +4 -13
- data/tasks/thor/templates/generator/empty_app/{design/response_templates → app/v1/resources}/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/{design/response_templates → app/v1/resources}/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/config/environment.rb +26 -17
- data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/design/v1/endpoints/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/design/v1/endpoints/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/docs/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/docs/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/spec/spec_helper.rb +14 -9
- data/tasks/thor/templates/generator/example_app/.gitignore +1 -0
- data/tasks/thor/templates/generator/example_app/Gemfile +19 -0
- data/tasks/thor/templates/generator/example_app/Rakefile +61 -0
- data/tasks/thor/templates/generator/example_app/app/models/user.rb +6 -0
- data/tasks/thor/templates/generator/example_app/app/v1/concerns/controller_base.rb +24 -0
- data/tasks/thor/templates/generator/example_app/app/v1/controllers/users.rb +17 -0
- data/tasks/thor/templates/generator/example_app/app/v1/resources/base.rb +11 -0
- data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +25 -0
- data/tasks/thor/templates/generator/example_app/config.ru +30 -0
- data/tasks/thor/templates/generator/example_app/config/environment.rb +41 -0
- data/tasks/thor/templates/generator/example_app/db/migrate/20201010101010_create_users_table.rb +12 -0
- data/tasks/thor/templates/generator/example_app/db/seeds.rb +6 -0
- data/tasks/thor/templates/generator/example_app/design/api.rb +18 -0
- data/tasks/thor/templates/generator/example_app/design/v1/endpoints/users.rb +37 -0
- data/tasks/thor/templates/generator/example_app/design/v1/media_types/user.rb +21 -0
- data/tasks/thor/templates/generator/example_app/spec/helpers/database_helper.rb +20 -0
- data/tasks/thor/templates/generator/example_app/spec/spec_helper.rb +42 -0
- data/tasks/thor/templates/generator/example_app/spec/v1/controllers/users_spec.rb +37 -0
- data/tasks/thor/templates/generator/scaffold/design/endpoints/collection.rb +98 -0
- data/tasks/thor/templates/generator/scaffold/design/media_types/item.rb +18 -0
- data/tasks/thor/templates/generator/scaffold/implementation/controllers/collection.rb +77 -0
- data/tasks/thor/templates/generator/scaffold/implementation/resources/base.rb +11 -0
- data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +45 -0
- data/tasks/thor/templates/generator/scaffold/models/active_record.rb +6 -0
- data/tasks/thor/templates/generator/scaffold/models/sequel.rb +6 -0
- metadata +62 -136
- data/lib/api_browser/.bowerrc +0 -3
- data/lib/api_browser/.editorconfig +0 -21
- data/lib/api_browser/Gruntfile.js +0 -581
- data/lib/api_browser/app/index.html +0 -59
- data/lib/api_browser/app/js/app.js +0 -48
- data/lib/api_browser/app/js/controllers/action.js +0 -47
- data/lib/api_browser/app/js/controllers/controller.js +0 -10
- data/lib/api_browser/app/js/controllers/menu.js +0 -93
- data/lib/api_browser/app/js/controllers/trait.js +0 -10
- data/lib/api_browser/app/js/controllers/type.js +0 -24
- data/lib/api_browser/app/js/directives/attribute_description.js +0 -56
- data/lib/api_browser/app/js/directives/attribute_table.js +0 -28
- data/lib/api_browser/app/js/directives/conditional_requirements.js +0 -13
- data/lib/api_browser/app/js/directives/fixed_if_fits.js +0 -38
- data/lib/api_browser/app/js/directives/highlight.js +0 -14
- data/lib/api_browser/app/js/directives/menu_item.js +0 -59
- data/lib/api_browser/app/js/directives/no_container.js +0 -8
- data/lib/api_browser/app/js/directives/readable_list.js +0 -87
- data/lib/api_browser/app/js/directives/request_examples.js +0 -31
- data/lib/api_browser/app/js/directives/type_placeholder.js +0 -30
- data/lib/api_browser/app/js/directives/url.js +0 -15
- data/lib/api_browser/app/js/factories/Configuration.js +0 -12
- data/lib/api_browser/app/js/factories/Documentation.js +0 -61
- data/lib/api_browser/app/js/factories/Example.js +0 -51
- data/lib/api_browser/app/js/factories/PageInfo.js +0 -9
- data/lib/api_browser/app/js/factories/normalize_attributes.js +0 -20
- data/lib/api_browser/app/js/factories/prepare_template.js +0 -15
- data/lib/api_browser/app/js/factories/template_for.js +0 -128
- data/lib/api_browser/app/js/filters/attribute_name.js +0 -10
- data/lib/api_browser/app/js/filters/friendly_json.js +0 -5
- data/lib/api_browser/app/js/filters/has_requirement.js +0 -14
- data/lib/api_browser/app/js/filters/header_info.js +0 -9
- data/lib/api_browser/app/js/filters/is_empty.js +0 -8
- data/lib/api_browser/app/js/filters/markdown.js +0 -6
- data/lib/api_browser/app/js/filters/resource_name.js +0 -5
- data/lib/api_browser/app/js/filters/tag_requirement.js +0 -13
- data/lib/api_browser/app/sass/modules/_body.scss +0 -40
- data/lib/api_browser/app/sass/modules/_cloke.scss +0 -8
- data/lib/api_browser/app/sass/modules/_header.scss +0 -10
- data/lib/api_browser/app/sass/modules/_nav.scss +0 -7
- data/lib/api_browser/app/sass/modules/_sidebar.scss +0 -134
- data/lib/api_browser/app/sass/modules/_switch.scss +0 -55
- data/lib/api_browser/app/sass/modules/_table.scss +0 -13
- data/lib/api_browser/app/sass/praxis.scss +0 -70
- data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +0 -774
- data/lib/api_browser/app/views/action.html +0 -97
- data/lib/api_browser/app/views/builtin/field-selector.html +0 -24
- data/lib/api_browser/app/views/controller.html +0 -55
- data/lib/api_browser/app/views/directives/attribute_description.html +0 -2
- data/lib/api_browser/app/views/directives/attribute_description/default.html +0 -2
- data/lib/api_browser/app/views/directives/attribute_description/example.html +0 -13
- data/lib/api_browser/app/views/directives/attribute_description/headers.html +0 -8
- data/lib/api_browser/app/views/directives/attribute_description/member_options.html +0 -4
- data/lib/api_browser/app/views/directives/attribute_description/values.html +0 -14
- data/lib/api_browser/app/views/directives/attribute_table.html +0 -17
- data/lib/api_browser/app/views/directives/menu_item.html +0 -8
- data/lib/api_browser/app/views/directives/url.html +0 -3
- data/lib/api_browser/app/views/examples/general.html +0 -26
- data/lib/api_browser/app/views/home.html +0 -5
- data/lib/api_browser/app/views/layout.html +0 -8
- data/lib/api_browser/app/views/menu.html +0 -42
- data/lib/api_browser/app/views/navbar.html +0 -9
- data/lib/api_browser/app/views/trait.html +0 -13
- data/lib/api_browser/app/views/type.html +0 -6
- data/lib/api_browser/app/views/type/details.html +0 -33
- data/lib/api_browser/app/views/types/embedded/array.html +0 -2
- data/lib/api_browser/app/views/types/embedded/default.html +0 -12
- data/lib/api_browser/app/views/types/embedded/field-selector.html +0 -13
- data/lib/api_browser/app/views/types/embedded/links.html +0 -11
- data/lib/api_browser/app/views/types/embedded/requirements.html +0 -6
- data/lib/api_browser/app/views/types/embedded/single_req.html +0 -9
- data/lib/api_browser/app/views/types/embedded/struct.html +0 -14
- data/lib/api_browser/app/views/types/label/link.html +0 -1
- data/lib/api_browser/app/views/types/label/primitive.html +0 -1
- data/lib/api_browser/app/views/types/label/primitive_collection.html +0 -1
- data/lib/api_browser/app/views/types/label/type.html +0 -1
- data/lib/api_browser/app/views/types/label/type_collection.html +0 -1
- data/lib/api_browser/app/views/types/main/array.html +0 -22
- data/lib/api_browser/app/views/types/main/default.html +0 -23
- data/lib/api_browser/app/views/types/main/hash.html +0 -23
- data/lib/api_browser/app/views/types/standalone/array.html +0 -3
- data/lib/api_browser/app/views/types/standalone/default.html +0 -18
- data/lib/api_browser/app/views/types/standalone/struct.html +0 -2
- data/lib/api_browser/bower_template.json +0 -41
- data/lib/api_browser/package-lock.json +0 -7110
- data/lib/api_browser/package.json +0 -43
- data/lib/praxis/docs/generator.rb +0 -243
- data/lib/praxis/docs/link_builder.rb +0 -30
- data/lib/praxis/links.rb +0 -135
- data/lib/praxis/types/multipart.rb +0 -109
- data/spec/api_browser/directives/type_placeholder_spec.js +0 -134
- data/spec/api_browser/factories/configuration_spec.js +0 -32
- data/spec/api_browser/factories/documentation_spec.js +0 -100
- data/spec/api_browser/factories/normalize_attributes_spec.js +0 -92
- data/spec/api_browser/factories/template_for_spec.js +0 -67
- data/spec/api_browser/filters/attribute_name_spec.js +0 -23
- data/spec/praxis/types/multipart_spec.rb +0 -112
- data/tasks/thor/templates/generator/empty_app/.rspec +0 -1
- data/tasks/thor/templates/generator/empty_app/Guardfile +0 -3
- data/tasks/thor/templates/generator/empty_app/config/rainbows.rb +0 -57
- data/tasks/thor/templates/generator/empty_app/docs/app.js +0 -1
- data/tasks/thor/templates/generator/empty_app/docs/styles.scss +0 -3
data/lib/praxis/request.rb
CHANGED
@@ -82,7 +82,7 @@ module Praxis
|
|
82
82
|
PATH_VERSION_PREFIX
|
83
83
|
end
|
84
84
|
|
85
|
-
# DEPRECATED: remove with
|
85
|
+
# DEPRECATED: remove with EndpointDefinition.version using: :path
|
86
86
|
PATH_VERSION_MATCHER = %r{^#{self.path_version_prefix}(?<version>[^\/]+)\/}.freeze
|
87
87
|
|
88
88
|
def path_version_matcher
|
@@ -1,312 +1,3 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
require 'active_support/inflector'
|
3
1
|
|
4
|
-
|
5
|
-
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
DEFAULT_RESOURCE_HREF_ACTION = :show
|
9
|
-
|
10
|
-
included do
|
11
|
-
@version = 'n/a'.freeze
|
12
|
-
@actions = Hash.new
|
13
|
-
@responses = Hash.new
|
14
|
-
|
15
|
-
@action_defaults = Trait.new &ResourceDefinition.generate_defaults_block
|
16
|
-
|
17
|
-
@version_options = {}
|
18
|
-
@metadata = {}
|
19
|
-
@traits = []
|
20
|
-
|
21
|
-
if self.name
|
22
|
-
@prefix = '/' + self.name.split("::").last.underscore
|
23
|
-
else
|
24
|
-
@prefix = '/'
|
25
|
-
end
|
26
|
-
|
27
|
-
@version_prefix = ''
|
28
|
-
|
29
|
-
@parent = nil
|
30
|
-
@parent_prefix = ''
|
31
|
-
|
32
|
-
@routing_prefix = nil
|
33
|
-
|
34
|
-
@on_finalize = Array.new
|
35
|
-
|
36
|
-
Application.instance.resource_definitions << self
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.generate_defaults_block( version: nil )
|
40
|
-
|
41
|
-
# Ensure we inherit any base params defined in the API definition for the passed in version
|
42
|
-
base_attributes = if (base_params = ApiDefinition.instance.info(version).base_params)
|
43
|
-
base_params.attributes
|
44
|
-
else
|
45
|
-
{}
|
46
|
-
end
|
47
|
-
|
48
|
-
Proc.new do
|
49
|
-
unless base_attributes.empty?
|
50
|
-
params do
|
51
|
-
base_attributes.each do |base_name, base_attribute|
|
52
|
-
attribute base_name, base_attribute.type, **base_attribute.options
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.finalize!
|
60
|
-
Application.instance.resource_definitions.each do |resource_definition|
|
61
|
-
while (block = resource_definition.on_finalize.shift)
|
62
|
-
block.call
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
module ClassMethods
|
70
|
-
attr_reader :actions
|
71
|
-
attr_reader :responses
|
72
|
-
attr_reader :version_options
|
73
|
-
attr_reader :traits
|
74
|
-
attr_reader :version_prefix
|
75
|
-
attr_reader :parent_prefix
|
76
|
-
|
77
|
-
# opaque hash of user-defined medata, used to decorate the definition,
|
78
|
-
# and also available in the generated JSON documents
|
79
|
-
attr_reader :metadata
|
80
|
-
|
81
|
-
attr_accessor :controller
|
82
|
-
|
83
|
-
def display_name( string=nil )
|
84
|
-
unless string
|
85
|
-
return @display_name ||= self.name.split("::").last # Best guess at a display name?
|
86
|
-
end
|
87
|
-
@display_name = string
|
88
|
-
end
|
89
|
-
|
90
|
-
def on_finalize(&block)
|
91
|
-
if block_given?
|
92
|
-
@on_finalize << proc(&block)
|
93
|
-
end
|
94
|
-
|
95
|
-
@on_finalize
|
96
|
-
end
|
97
|
-
|
98
|
-
def prefix(prefix=nil)
|
99
|
-
return @prefix if prefix.nil?
|
100
|
-
@routing_prefix = nil # reset routing_prefix
|
101
|
-
@prefix = prefix
|
102
|
-
end
|
103
|
-
|
104
|
-
def media_type(media_type=nil)
|
105
|
-
return @media_type if media_type.nil?
|
106
|
-
|
107
|
-
if media_type.kind_of?(String)
|
108
|
-
media_type = SimpleMediaType.new(media_type)
|
109
|
-
end
|
110
|
-
@media_type = media_type
|
111
|
-
end
|
112
|
-
|
113
|
-
|
114
|
-
def parent(parent=nil, **mapping)
|
115
|
-
return @parent if parent.nil?
|
116
|
-
|
117
|
-
@routing_prefix = nil # reset routing_prefix
|
118
|
-
|
119
|
-
parent_action = parent.canonical_path
|
120
|
-
parent_route = parent_action.route.path
|
121
|
-
|
122
|
-
# if a mapping is passed, it *must* resolve any param name conflicts
|
123
|
-
unless mapping.any?
|
124
|
-
# assume last capture is the relevant one to replace
|
125
|
-
# if not... then I quit.
|
126
|
-
parent_param_name = parent_route.names.last
|
127
|
-
|
128
|
-
# more assumptions about names
|
129
|
-
parent_name = parent.name.demodulize.underscore.singularize
|
130
|
-
|
131
|
-
# put it together to find what we should call this new param
|
132
|
-
param = "#{parent_name}_#{parent_param_name}".to_sym
|
133
|
-
mapping[parent_param_name.to_sym] = param
|
134
|
-
end
|
135
|
-
|
136
|
-
# complete the mapping and massage the route
|
137
|
-
parent_route.names.collect(&:to_sym).each do |name|
|
138
|
-
if mapping.key?(name)
|
139
|
-
param = mapping[name]
|
140
|
-
# FIXME: this won't handle URI Template type paths, ie '/{parent_id}'
|
141
|
-
prefixed_path = parent_action.route.prefixed_path
|
142
|
-
@parent_prefix = prefixed_path.gsub(/(:)(#{name})(\W+|$)/, "\\1#{param.to_s}\\3")
|
143
|
-
else
|
144
|
-
mapping[name] = name
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
self.on_finalize do
|
149
|
-
self.inherit_params_from_parent(parent_action, **mapping)
|
150
|
-
end
|
151
|
-
|
152
|
-
@parent = parent
|
153
|
-
end
|
154
|
-
|
155
|
-
def inherit_params_from_parent(parent_action, **mapping)
|
156
|
-
actions.each do |name, action|
|
157
|
-
action.params do
|
158
|
-
mapping.each do |parent_name, name|
|
159
|
-
next if action.params && action.params.attributes.key?(name)
|
160
|
-
|
161
|
-
parent_attribute = parent_action.params.attributes[parent_name]
|
162
|
-
|
163
|
-
attribute name, parent_attribute.type, **parent_attribute.options
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
169
|
-
|
170
|
-
attr_writer :routing_prefix
|
171
|
-
|
172
|
-
def routing_prefix
|
173
|
-
return @routing_prefix if @routing_prefix
|
174
|
-
|
175
|
-
@routing_prefix = parent_prefix + prefix
|
176
|
-
end
|
177
|
-
|
178
|
-
|
179
|
-
def version(version=nil, options=nil)
|
180
|
-
return @version unless version
|
181
|
-
|
182
|
-
@version = version
|
183
|
-
|
184
|
-
unless options.nil?
|
185
|
-
warn 'DEPRECATED: ResourceDefinition.version with options is no longer supported. Define in api global info instead.'
|
186
|
-
|
187
|
-
@version_options = options
|
188
|
-
version_using = Array(@version_options[:using])
|
189
|
-
if version_using.include?(:path)
|
190
|
-
@version_prefix = "#{Praxis::Request::path_version_prefix}#{self.version}"
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
@action_defaults.instance_eval &ResourceDefinition.generate_defaults_block( version: version )
|
195
|
-
end
|
196
|
-
|
197
|
-
|
198
|
-
def canonical_path(action_name=nil)
|
199
|
-
if action_name
|
200
|
-
raise "Canonical path for #{self.name} is already defined as: '#{@canonical_action_name}'. 'canonical_path' can only be defined once." if @canonical_action_name
|
201
|
-
@canonical_action_name = action_name
|
202
|
-
else
|
203
|
-
# Resolution of the actual action definition needs to be done lazily, since we can use the `canonical_path` stanza
|
204
|
-
# at the top of the resource, well before the actual action is defined.
|
205
|
-
unless @canonical_action
|
206
|
-
href_action = @canonical_action_name || DEFAULT_RESOURCE_HREF_ACTION
|
207
|
-
@canonical_action = actions.fetch(href_action) do
|
208
|
-
raise "Error: trying to set canonical_href of #{self.name}. Action '#{href_action}' does not exist"
|
209
|
-
end
|
210
|
-
end
|
211
|
-
return @canonical_action
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def to_href( params )
|
216
|
-
canonical_path.route.path.expand(params)
|
217
|
-
end
|
218
|
-
|
219
|
-
def parse_href(path)
|
220
|
-
if path.kind_of?(::URI::Generic)
|
221
|
-
path = path.path
|
222
|
-
end
|
223
|
-
param_values = canonical_path.route.path.params(path)
|
224
|
-
attrs = canonical_path.params.attributes
|
225
|
-
param_values.each_with_object({}) do |(key,value),hash|
|
226
|
-
hash[key.to_sym] = attrs[key.to_sym].load(value,[key])
|
227
|
-
end
|
228
|
-
rescue => e
|
229
|
-
raise Praxis::Exception.new("Error parsing or coercing parameters from href: #{path}\n"+e.message)
|
230
|
-
end
|
231
|
-
|
232
|
-
def trait(trait_name)
|
233
|
-
unless ApiDefinition.instance.traits.has_key? trait_name
|
234
|
-
raise Exceptions::InvalidTrait.new("Trait #{trait_name} not found in the system")
|
235
|
-
end
|
236
|
-
trait = ApiDefinition.instance.traits.fetch(trait_name)
|
237
|
-
@traits << trait_name
|
238
|
-
end
|
239
|
-
alias_method :use, :trait
|
240
|
-
|
241
|
-
def action_defaults(&block)
|
242
|
-
if block_given?
|
243
|
-
@action_defaults.instance_eval(&block)
|
244
|
-
end
|
245
|
-
|
246
|
-
@action_defaults
|
247
|
-
end
|
248
|
-
|
249
|
-
def params(type=Attributor::Struct, **opts, &block)
|
250
|
-
warn 'DEPRECATED: ResourceDefinition.params is deprecated. Use it in action_defaults instead.'
|
251
|
-
action_defaults do
|
252
|
-
params type, **opts, &block
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
def payload(type=Attributor::Struct, **opts, &block)
|
257
|
-
warn 'DEPRECATED: ResourceDefinition.payload is deprecated. Use action_defaults instead.'
|
258
|
-
action_defaults do
|
259
|
-
payload type, **opts, &block
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
def headers(**opts, &block)
|
264
|
-
warn 'DEPRECATED: ResourceDefinition.headers is deprecated. Use action_defaults instead.'
|
265
|
-
action_defaults do
|
266
|
-
headers **opts, &block
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
def response(name, **args)
|
271
|
-
warn 'DEPRECATED: ResourceDefinition.response is deprecated. Use action_defaults instead.'
|
272
|
-
action_defaults do
|
273
|
-
response name, **args
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def action(name, &block)
|
278
|
-
raise ArgumentError, "can not create ActionDefinition without block" unless block_given?
|
279
|
-
raise ArgumentError, "Action names must be defined using symbols (Got: #{name} (of type #{name.class}))" unless name.is_a? Symbol
|
280
|
-
@actions[name] = ActionDefinition.new(name, self, &block)
|
281
|
-
end
|
282
|
-
|
283
|
-
def description(text=nil)
|
284
|
-
@description = text if text
|
285
|
-
@description
|
286
|
-
end
|
287
|
-
|
288
|
-
def id
|
289
|
-
self.name.gsub('::'.freeze,'-'.freeze)
|
290
|
-
end
|
291
|
-
|
292
|
-
def describe(context: nil)
|
293
|
-
{}.tap do |hash|
|
294
|
-
hash[:description] = description
|
295
|
-
hash[:media_type] = media_type.describe(true) if media_type
|
296
|
-
hash[:actions] = actions.values.collect{|action| action.describe(context: context)}
|
297
|
-
hash[:name] = self.name
|
298
|
-
hash[:parent] = self.parent.id if self.parent
|
299
|
-
hash[:display_name] = self.display_name
|
300
|
-
hash[:metadata] = metadata
|
301
|
-
hash[:traits] = self.traits
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
def nodoc!
|
306
|
-
metadata[:doc_visibility] = :none
|
307
|
-
end
|
308
|
-
|
309
|
-
end
|
310
|
-
|
311
|
-
end
|
312
|
-
end
|
2
|
+
raise "ResourceDefinition class has changed name in this version of Praxis.\n" \
|
3
|
+
'Please blanket-replace all uses of ResourceDefinition with EndpointDefinition instead.'
|
@@ -311,16 +311,8 @@ module Praxis
|
|
311
311
|
def validate_parts!(response)
|
312
312
|
return unless parts
|
313
313
|
|
314
|
-
|
315
|
-
|
316
|
-
response.body.each do |part|
|
317
|
-
parts.validate(part)
|
318
|
-
end
|
319
|
-
else
|
320
|
-
# TODO: remove with other Multipart deprecations.
|
321
|
-
response.parts.each do |name, part|
|
322
|
-
parts.validate(part)
|
323
|
-
end
|
314
|
+
response.body.each do |part|
|
315
|
+
parts.validate(part)
|
324
316
|
end
|
325
317
|
end
|
326
318
|
|
@@ -9,15 +9,15 @@ module Praxis
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def compile(action=nil, **args)
|
12
|
-
# Default media_type to the
|
12
|
+
# Default media_type to the endpoint_definition one, if the block has it in
|
13
13
|
# its required args but no value is passed (funky, but can help in the common case)
|
14
14
|
if block.parameters.any? { |(type, name)| name == :media_type && type == :keyreq } && action
|
15
15
|
unless args.has_key? :media_type
|
16
|
-
media_type = action.
|
16
|
+
media_type = action.endpoint_definition.media_type
|
17
17
|
unless media_type
|
18
18
|
raise Exceptions::InvalidConfiguration.new(
|
19
19
|
"Could not default :media_type argument for response template #{@name}." +
|
20
|
-
"
|
20
|
+
" Endpoint #{action.endpoint_definition} does not have an associated mediatype and none was passed"
|
21
21
|
)
|
22
22
|
end
|
23
23
|
args[:media_type] = media_type
|
data/lib/praxis/router.rb
CHANGED
@@ -52,8 +52,8 @@ module Praxis
|
|
52
52
|
def add_route(target, route)
|
53
53
|
path_versioning = (Application.instance.versioning_scheme == :path)
|
54
54
|
|
55
|
-
# DEPRECATED: remove with
|
56
|
-
path_versioning ||= (target.action.
|
55
|
+
# DEPRECATED: remove with EndpointDefinition.version using: :path
|
56
|
+
path_versioning ||= (target.action.endpoint_definition.version_options[:using] == :path)
|
57
57
|
|
58
58
|
unless path_versioning
|
59
59
|
target = VersionMatcher.new(target, version: route.version)
|
@@ -53,7 +53,7 @@ module Praxis
|
|
53
53
|
end
|
54
54
|
prefixed_path = path.gsub('//','/')
|
55
55
|
path = (base + path).gsub('//','/')
|
56
|
-
pattern = Mustermann.new(path, {ignore_unknown_options: true}.merge( options ))
|
56
|
+
pattern = Mustermann.new(path, **{ignore_unknown_options: true}.merge( options ))
|
57
57
|
@route = Route.new(verb, pattern, version, prefixed_path: prefixed_path, **options)
|
58
58
|
end
|
59
59
|
|
@@ -2,68 +2,8 @@ namespace :praxis do
|
|
2
2
|
|
3
3
|
namespace :docs do
|
4
4
|
|
5
|
-
def base_path
|
6
|
-
require 'uri'
|
7
|
-
documentation_url = Praxis::ApiDefinition.instance.global_info.documentation_url
|
8
|
-
URI(documentation_url).path.gsub(/\/[^\/]*$/, '/') if documentation_url
|
9
|
-
end
|
10
|
-
|
11
|
-
path = File.expand_path(File.join(File.dirname(__FILE__), '../../api_browser'))
|
12
|
-
|
13
|
-
desc "Install dependencies"
|
14
|
-
task :install do
|
15
|
-
unless system("npm install --production", chdir: path)
|
16
|
-
raise Exception.new("NPM Install Failed")
|
17
|
-
end
|
18
|
-
|
19
|
-
docs_dir = File.join(Dir.pwd, 'docs')
|
20
|
-
FileUtils.mkdir_p docs_dir unless File.directory? docs_dir
|
21
|
-
|
22
|
-
# The doc browser will need to have a minimal app.js and styles.css file at the root
|
23
|
-
# Let's add them if the app has not overriden them
|
24
|
-
js_file = File.join(Dir.pwd, 'docs', 'app.js')
|
25
|
-
scss_file = File.join(Dir.pwd, 'docs', 'styles.scss')
|
26
|
-
template_directory = File.expand_path(File.join(File.dirname(__FILE__), '../../../tasks/thor/templates/generator/empty_app/docs'))
|
27
|
-
|
28
|
-
unless File.exists? js_file
|
29
|
-
FileUtils.cp File.join(template_directory, 'app.js'), js_file
|
30
|
-
end
|
31
|
-
unless File.exists? scss_file
|
32
|
-
FileUtils.cp File.join(template_directory, 'styles.scss'), scss_file
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
desc "Run API Documentation Browser"
|
37
|
-
task :preview, [:port] => [:install, :generate] do |t, args|
|
38
|
-
doc_port = args[:port] || '9090'
|
39
|
-
exec({
|
40
|
-
'USER_DOCS_PATH' => File.join(Dir.pwd, 'docs'),
|
41
|
-
'DOC_PORT' => doc_port,
|
42
|
-
'PLUGIN_PATHS' => Praxis::Application.instance.doc_browser_plugin_paths.join(':'),
|
43
|
-
'BASE_PATH' => '/'
|
44
|
-
}, "#{path}/node_modules/.bin/grunt serve --gruntfile '#{path}/Gruntfile.js'")
|
45
|
-
end
|
46
|
-
|
47
|
-
desc "Build docs that can be shipped"
|
48
|
-
task :build => [:install, :generate] do
|
49
|
-
exec({
|
50
|
-
'USER_DOCS_PATH' => File.join(Dir.pwd, 'docs'),
|
51
|
-
'PLUGIN_PATHS' => Praxis::Application.instance.doc_browser_plugin_paths.join(':'),
|
52
|
-
'BASE_PATH' => base_path
|
53
|
-
}, "#{path}/node_modules/.bin/grunt build --gruntfile '#{path}/Gruntfile.js'")
|
54
|
-
end
|
55
|
-
|
56
|
-
desc "Generate API docs (JSON definitions) for a Praxis App"
|
57
|
-
task :generate => [:environment] do |t, args|
|
58
|
-
require 'fileutils'
|
59
|
-
|
60
|
-
Praxis::Blueprint.caching_enabled = false
|
61
|
-
generator = Praxis::Docs::Generator.new(Dir.pwd)
|
62
|
-
generator.save!
|
63
|
-
end
|
64
|
-
|
65
5
|
desc "Generate OpenAPI 3 docs for a Praxis App"
|
66
|
-
task :
|
6
|
+
task :generate => [:environment] do |t, args|
|
67
7
|
require 'fileutils'
|
68
8
|
|
69
9
|
Praxis::Blueprint.caching_enabled = false
|
@@ -72,7 +12,7 @@ namespace :praxis do
|
|
72
12
|
end
|
73
13
|
|
74
14
|
desc "Preview (and Generate) OpenAPI 3 docs for a Praxis App"
|
75
|
-
task :
|
15
|
+
task :preview => [:generate] do |t, args|
|
76
16
|
require 'webrick'
|
77
17
|
docs_port = 9090
|
78
18
|
root = Dir.pwd + '/docs/openapi/'
|
@@ -81,9 +21,22 @@ namespace :praxis do
|
|
81
21
|
trap('INT') { s.shutdown }
|
82
22
|
s.start
|
83
23
|
end
|
84
|
-
|
24
|
+
# If there is only 1 version we'll feature it and open the browser onto it
|
25
|
+
versions = Dir.children(root)
|
26
|
+
featured_version = (versions.size < 2) ? "#{versions.first}/" : ''
|
27
|
+
`open http://localhost:#{docs_port}/#{featured_version}`
|
85
28
|
wb.join
|
86
29
|
end
|
87
|
-
|
30
|
+
desc "Generate and package all OpenApi Docs into a zip, ready for a Web server (like S3...) to present it"
|
31
|
+
task :package => [:generate] do |t, args|
|
32
|
+
docs_root = Dir.pwd + '/docs/openapi/'
|
33
|
+
zip_file = Dir.pwd + '/docs/openapi.zip'
|
34
|
+
`rm -f #{zip_file}`
|
35
|
+
# NOTE: This assumes the "zip" utility is installed, supporting the recursive flag.
|
36
|
+
`zip -r #{zip_file} #{docs_root}`
|
37
|
+
puts
|
38
|
+
puts "Left packaged API docs in #{zip_file}"
|
39
|
+
puts " --> To view the docs, unzip the file under a web server (or S3...) and access the index.hml files from a browser"
|
40
|
+
end
|
88
41
|
end
|
89
42
|
end
|