praxis 2.0.pre.17 → 2.0.pre.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +54 -0
- data/.simplecov +3 -1
- data/.travis.yml +2 -1
- data/CHANGELOG.md +19 -0
- data/CONTRIBUTING.md +2 -79
- data/Gemfile +5 -1
- data/Guardfile +6 -4
- data/LICENSE +0 -2
- data/MAINTAINERS.md +1 -0
- data/README.md +15 -22
- data/Rakefile +4 -2
- data/bin/praxis +55 -58
- data/lib/praxis/action_definition/headers_dsl_compiler.rb +5 -6
- data/lib/praxis/action_definition.rb +65 -95
- data/lib/praxis/api_definition.rb +21 -29
- data/lib/praxis/api_general_info.rb +55 -66
- data/lib/praxis/application.rb +15 -32
- data/lib/praxis/blueprint.rb +80 -73
- data/lib/praxis/bootloader.rb +24 -33
- data/lib/praxis/bootloader_stages/environment.rb +5 -10
- data/lib/praxis/bootloader_stages/file_loader.rb +3 -6
- data/lib/praxis/bootloader_stages/plugin_config_load.rb +4 -6
- data/lib/praxis/bootloader_stages/plugin_config_prepare.rb +2 -2
- data/lib/praxis/bootloader_stages/plugin_loader.rb +3 -7
- data/lib/praxis/bootloader_stages/plugin_setup.rb +3 -3
- data/lib/praxis/bootloader_stages/routing.rb +5 -8
- data/lib/praxis/bootloader_stages/subgroup_loader.rb +2 -10
- data/lib/praxis/bootloader_stages/warn_unloaded_files.rb +15 -19
- data/lib/praxis/callbacks.rb +12 -11
- data/lib/praxis/collection.rb +11 -14
- data/lib/praxis/config.rb +17 -28
- data/lib/praxis/config_hash.rb +2 -1
- data/lib/praxis/controller.rb +7 -6
- data/lib/praxis/dispatcher.rb +34 -42
- data/lib/praxis/docs/open_api/info_object.rb +11 -8
- data/lib/praxis/docs/open_api/media_type_object.rb +18 -17
- data/lib/praxis/docs/open_api/operation_object.rb +7 -4
- data/lib/praxis/docs/open_api/parameter_object.rb +17 -14
- data/lib/praxis/docs/open_api/paths_object.rb +11 -9
- data/lib/praxis/docs/open_api/request_body_object.rb +14 -13
- data/lib/praxis/docs/open_api/response_object.rb +24 -18
- data/lib/praxis/docs/open_api/responses_object.rb +3 -1
- data/lib/praxis/docs/open_api/schema_object.rb +61 -29
- data/lib/praxis/docs/open_api/server_object.rb +5 -2
- data/lib/praxis/docs/open_api/tag_object.rb +9 -6
- data/lib/praxis/docs/open_api_generator.rb +114 -150
- data/lib/praxis/endpoint_definition.rb +60 -77
- data/lib/praxis/error_handler.rb +2 -2
- data/lib/praxis/exception.rb +2 -0
- data/lib/praxis/exceptions/config.rb +3 -1
- data/lib/praxis/exceptions/config_load.rb +2 -0
- data/lib/praxis/exceptions/config_validation.rb +3 -1
- data/lib/praxis/exceptions/invalid_configuration.rb +3 -1
- data/lib/praxis/exceptions/invalid_response.rb +3 -1
- data/lib/praxis/exceptions/invalid_trait.rb +3 -1
- data/lib/praxis/exceptions/stage_not_found.rb +3 -1
- data/lib/praxis/exceptions/validation.rb +4 -3
- data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +163 -149
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb +18 -13
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_0.rb +13 -9
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb +14 -11
- data/lib/praxis/extensions/attribute_filtering/active_record_patches.rb +12 -9
- data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +8 -5
- data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +89 -65
- data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +68 -62
- data/lib/praxis/extensions/attribute_filtering.rb +3 -1
- data/lib/praxis/extensions/field_expansion.rb +6 -4
- data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +10 -8
- data/lib/praxis/extensions/field_selection/field_selector.rb +91 -92
- data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +12 -12
- data/lib/praxis/extensions/field_selection.rb +3 -1
- data/lib/praxis/extensions/pagination/active_record_pagination_handler.rb +6 -4
- data/lib/praxis/extensions/pagination/header_generator.rb +16 -11
- data/lib/praxis/extensions/pagination/ordering_params.rb +29 -28
- data/lib/praxis/extensions/pagination/pagination_handler.rb +44 -42
- data/lib/praxis/extensions/pagination/pagination_params.rb +29 -48
- data/lib/praxis/extensions/pagination/sequel_pagination_handler.rb +8 -7
- data/lib/praxis/extensions/pagination.rb +10 -15
- data/lib/praxis/extensions/rails_compat/request_methods.rb +3 -4
- data/lib/praxis/extensions/rails_compat.rb +2 -0
- data/lib/praxis/extensions/rendering.rb +12 -12
- data/lib/praxis/field_expander.rb +8 -9
- data/lib/praxis/file_group.rb +8 -12
- data/lib/praxis/finalizable.rb +1 -0
- data/lib/praxis/handlers/json.rb +5 -2
- data/lib/praxis/handlers/plain.rb +2 -1
- data/lib/praxis/handlers/www_form.rb +6 -3
- data/lib/praxis/handlers/{xml-sample.rb → xml_sample.rb} +26 -22
- data/lib/praxis/mapper/active_model_compat.rb +13 -10
- data/lib/praxis/mapper/resource.rb +196 -181
- data/lib/praxis/mapper/selector_generator.rb +106 -112
- data/lib/praxis/mapper/sequel_compat.rb +70 -67
- data/lib/praxis/media_type.rb +2 -2
- data/lib/praxis/media_type_identifier.rb +26 -22
- data/lib/praxis/middleware_app.rb +18 -15
- data/lib/praxis/multipart/parser.rb +46 -51
- data/lib/praxis/multipart/part.rb +78 -110
- data/lib/praxis/notifications.rb +2 -4
- data/lib/praxis/plugin.rb +11 -18
- data/lib/praxis/plugin_concern.rb +12 -15
- data/lib/praxis/plugins/mapper_plugin.rb +15 -13
- data/lib/praxis/plugins/pagination_plugin.rb +8 -6
- data/lib/praxis/plugins/rails_plugin.rb +33 -28
- data/lib/praxis/renderer.rb +11 -15
- data/lib/praxis/request.rb +48 -44
- data/lib/praxis/request_stages/action.rb +4 -6
- data/lib/praxis/request_stages/load_request.rb +2 -4
- data/lib/praxis/request_stages/request_stage.rb +19 -23
- data/lib/praxis/request_stages/response.rb +4 -6
- data/lib/praxis/request_stages/validate.rb +3 -5
- data/lib/praxis/request_stages/validate_params_and_headers.rb +15 -22
- data/lib/praxis/request_stages/validate_payload.rb +25 -28
- data/lib/praxis/request_superclassing.rb +3 -3
- data/lib/praxis/resource_definition.rb +1 -0
- data/lib/praxis/response.rb +24 -26
- data/lib/praxis/response_definition.rb +77 -122
- data/lib/praxis/response_template.rb +11 -15
- data/lib/praxis/responses/http.rb +23 -44
- data/lib/praxis/responses/internal_server_error.rb +18 -21
- data/lib/praxis/responses/multipart_ok.rb +4 -9
- data/lib/praxis/responses/validation_error.rb +8 -15
- data/lib/praxis/route.rb +8 -10
- data/lib/praxis/router/rack.rb +13 -7
- data/lib/praxis/router/simple.rb +10 -5
- data/lib/praxis/router.rb +27 -34
- data/lib/praxis/routing_config.rb +52 -29
- data/lib/praxis/simple_media_type.rb +5 -8
- data/lib/praxis/stage.rb +17 -25
- data/lib/praxis/tasks/api_docs.rb +17 -16
- data/lib/praxis/tasks/console.rb +3 -1
- data/lib/praxis/tasks/environment.rb +2 -0
- data/lib/praxis/tasks/routes.rb +26 -24
- data/lib/praxis/tasks.rb +3 -1
- data/lib/praxis/trait.rb +37 -46
- data/lib/praxis/types/fuzzy_hash.rb +13 -14
- data/lib/praxis/types/media_type_common.rb +11 -10
- data/lib/praxis/types/multipart_array/part_definition.rb +14 -17
- data/lib/praxis/types/multipart_array.rb +100 -115
- data/lib/praxis/validation_handler.rb +5 -3
- data/lib/praxis/version.rb +3 -1
- data/lib/praxis.rb +4 -5
- data/praxis.gemspec +22 -21
- data/spec/functional_spec.rb +44 -56
- data/spec/praxis/action_definition_spec.rb +39 -48
- data/spec/praxis/api_definition_spec.rb +45 -47
- data/spec/praxis/api_general_info_spec.rb +28 -29
- data/spec/praxis/application_spec.rb +18 -14
- data/spec/praxis/blueprint_spec.rb +33 -34
- data/spec/praxis/bootloader_spec.rb +32 -30
- data/spec/praxis/callbacks_spec.rb +37 -37
- data/spec/praxis/collection_spec.rb +18 -25
- data/spec/praxis/config_hash_spec.rb +5 -4
- data/spec/praxis/config_spec.rb +27 -26
- data/spec/praxis/controller_spec.rb +8 -9
- data/spec/praxis/endpoint_definition_spec.rb +25 -32
- data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +171 -114
- data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +22 -21
- data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +112 -60
- data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +37 -38
- data/spec/praxis/extensions/field_expansion_spec.rb +8 -10
- data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +14 -13
- data/spec/praxis/extensions/field_selection/field_selector_spec.rb +9 -16
- data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +50 -49
- data/spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb +32 -31
- data/spec/praxis/extensions/rendering_spec.rb +9 -9
- data/spec/praxis/extensions/support/spec_resources_active_model.rb +32 -49
- data/spec/praxis/extensions/support/spec_resources_sequel.rb +48 -48
- data/spec/praxis/field_expander_spec.rb +6 -5
- data/spec/praxis/file_group_spec.rb +3 -1
- data/spec/praxis/handlers/json_spec.rb +6 -5
- data/spec/praxis/mapper/resource_spec.rb +39 -29
- data/spec/praxis/mapper/selector_generator_spec.rb +80 -46
- data/spec/praxis/media_type_identifier_spec.rb +13 -10
- data/spec/praxis/media_type_spec.rb +12 -12
- data/spec/praxis/middleware_app_spec.rb +23 -22
- data/spec/praxis/multipart/parser_spec.rb +7 -9
- data/spec/praxis/notifications_spec.rb +4 -4
- data/spec/praxis/plugin_concern_spec.rb +5 -6
- data/spec/praxis/renderer_spec.rb +10 -9
- data/spec/praxis/request_spec.rb +38 -41
- data/spec/praxis/request_stages/action_spec.rb +14 -15
- data/spec/praxis/request_stages/request_stage_spec.rb +30 -41
- data/spec/praxis/request_stages/validate_spec.rb +3 -1
- data/spec/praxis/response_definition_spec.rb +79 -92
- data/spec/praxis/response_spec.rb +35 -40
- data/spec/praxis/responses/internal_server_error_spec.rb +6 -9
- data/spec/praxis/responses/validation_error_spec.rb +17 -18
- data/spec/praxis/route_spec.rb +4 -7
- data/spec/praxis/router_spec.rb +69 -79
- data/spec/praxis/routing_config_spec.rb +15 -14
- data/spec/praxis/stage_spec.rb +56 -53
- data/spec/praxis/trait_spec.rb +17 -17
- data/spec/praxis/types/fuzzy_hash_spec.rb +11 -9
- data/spec/praxis/types/multipart_array/part_definition_spec.rb +3 -2
- data/spec/praxis/types/multipart_array_spec.rb +33 -48
- data/spec/spec_app/app/concerns/authenticated.rb +5 -5
- data/spec/spec_app/app/concerns/basic_api.rb +3 -1
- data/spec/spec_app/app/concerns/log_wrapper.rb +5 -3
- data/spec/spec_app/app/controllers/base_class.rb +6 -5
- data/spec/spec_app/app/controllers/instances.rb +31 -34
- data/spec/spec_app/app/controllers/volumes.rb +6 -6
- data/spec/spec_app/app/responses/multipart.rb +1 -2
- data/spec/spec_app/app/responses/other_response.rb +2 -2
- data/spec/spec_app/config/environment.rb +19 -6
- data/spec/spec_app/config.ru +4 -3
- data/spec/spec_app/design/api.rb +13 -15
- data/spec/spec_app/design/media_types/instance.rb +6 -6
- data/spec/spec_app/design/media_types/volume.rb +2 -1
- data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -1
- data/spec/spec_app/design/resources/instances.rb +11 -17
- data/spec/spec_app/design/resources/volume_snapshots.rb +4 -5
- data/spec/spec_app/design/resources/volumes.rb +4 -5
- data/spec/spec_helper.rb +11 -13
- data/spec/support/be_deep_equal_matcher.rb +5 -0
- data/spec/support/spec_authorization_plugin.rb +7 -12
- data/spec/support/spec_blueprints.rb +5 -4
- data/spec/support/spec_complex_authentication_plugin.rb +17 -34
- data/spec/support/spec_endpoint_definitions.rb +2 -3
- data/spec/support/spec_media_types.rb +28 -35
- data/spec/support/spec_resources.rb +22 -16
- data/spec/support/spec_simple_authentication_plugin.rb +5 -9
- data/tasks/loader.thor +4 -2
- data/tasks/thor/app.rb +7 -5
- data/tasks/thor/example.rb +23 -22
- data/tasks/thor/model.rb +7 -7
- data/tasks/thor/scaffold.rb +23 -23
- data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +0 -8
- data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +1 -2
- metadata +72 -84
- data/MAINTAINERS +0 -2
- data/TODO.md +0 -25
- data/spec/praxis/api_resource_spec.rb +0 -0
- data/spec/praxis/dispatcher_spec.rb +0 -0
- data/spec/spec_app/app/responses/bulk_response.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22211954ff9fa77a0667e1daf3ae00b30d1d599cd5a25b65547321295e5a2fcb
|
4
|
+
data.tar.gz: 3ec2f9c7f2cd9d261f09675a25ca5211131c65d58cc088a539f60f273d5ac207
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d46f5cd5b91786467262f2baf3e2e60d27431f3b01ac7d674508f66b33046cb26b6489541eb55324354762964f017dc0e448f69d895dfc7804149e87f57b3b0b
|
7
|
+
data.tar.gz: 957d3f7d32a54f8990e1697a6e6c8182042f15879ef0f8689298ca751b5e0fc5eb64a9f530064066d8722f41b57ddf014889736c5959097c013759ba911beddd
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# require:
|
2
|
+
# - rubocop-thread_safety
|
3
|
+
|
4
|
+
AllCops:
|
5
|
+
Exclude:
|
6
|
+
- "_site/**/*"
|
7
|
+
- "coverage/**/*"
|
8
|
+
- "docs_docusaurus/**/*"
|
9
|
+
- "tmp/**/*"
|
10
|
+
- "pkg/**/*"
|
11
|
+
- "vendor/cache/**/*"
|
12
|
+
- "tasks/thor/templates/**/*"
|
13
|
+
TargetRubyVersion: 2.5
|
14
|
+
NewCops: disable
|
15
|
+
|
16
|
+
Metrics/BlockLength:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Metrics/ClassLength:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Metrics/ModuleLength:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Metrics/CyclomaticComplexity:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Metrics/PerceivedComplexity:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Metrics/MethodLength:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Layout/LineLength:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Style/Documentation:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
#### RE-ENABLE PLEASE
|
44
|
+
Metrics/BlockNesting:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
Style/OptionalBooleanParameter:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Lint/Void:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
Lint/MissingSuper:
|
54
|
+
Enabled: false
|
data/.simplecov
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
## next
|
4
4
|
|
5
|
+
## 2.0.pre.21
|
6
|
+
* Fix nullable attribute in OpenApi generation
|
7
|
+
## 2.0.pre.20
|
8
|
+
* Changed the behavior of dev-mode when validate_responses. Now they return a 500 status code (instead of a 400) but with the same validation error format body.
|
9
|
+
* validate_responses is meant to catch the application returning non-compliant responses for development only. As such, a 500 is much more appropriate and clear, as the validation is done on the behavior of the server, and not on the information sent by the client (i.e., it is a server problem, not reacting the way the API is defined)
|
10
|
+
* Introduced a method to reload a Resouce (.reload), which will clear the memoized values and call record.reload as well
|
11
|
+
* Open API Generation enhancements:
|
12
|
+
* Fixed type discovery (where some types wouldn't be included in the output)
|
13
|
+
* Changed the generation to output named types into components, and use `$ref` to point to them whenever appropriate
|
14
|
+
* Report nullable attributes
|
15
|
+
## 2.0.pre.19
|
16
|
+
* Introduced a new DSL for the `FilteringParams` type that allows filters for common attributes in your Media Types:
|
17
|
+
* The new `any` DSL allows you to define which final leaf attribute to always allow, and with which operators and/or fuzzy restrictions.
|
18
|
+
* For example, you can add `any updated_at, using: ['>','<']` which would allow the type to accept filters like `updated_at>2000-01-01`, or any existing nested fields like `posts.comments.updated_at>2000-01-01`
|
19
|
+
* Note that the path of attributes passed in, will still need to exist and will be validated. Also, you still need to make sure that you have the right `filters_mapping` defined in your resources.
|
20
|
+
* Changed `filters_mapping` to allow implicitly any filter path that is a valid representation of existing columns and associations. I.e., you do not have to explicitly define long nested filters that correspond to the same underlying path of associations and columns.
|
21
|
+
## 2.0.pre.18
|
22
|
+
* Upgraded to newest Attributor, which cleans up the required: true semantics to only work on keys, and introduces null: true for nullability of values (independent from presence of keys or not)
|
23
|
+
* Fixed a selector generator bug that would occur when using deep nested resource dependencies as strings 'foo.bar.baz.bam'. In this cases only partial tracking of relationships would be built, which could cause to not fully eager load DB queries.
|
5
24
|
## 2.0.pre.17
|
6
25
|
* Changed the Parameter Filtering to use left outer joins (and extra conditions), to allow for the proper results when OR clauses are involved in certain configurations.
|
7
26
|
* Built support for allowing filtering directly on associations using `!` and `!!` operators. This allows to filter results where
|
data/CONTRIBUTING.md
CHANGED
@@ -19,13 +19,8 @@ Before submitting any contributions, please read the below description of what
|
|
19
19
|
the problems Praxis aims to solve. Contributions that are not aligned with
|
20
20
|
Praxis' goals will not be accepted.
|
21
21
|
|
22
|
-
Praxis is a web framework for developing usable, consistent and
|
23
|
-
self-documenting HTTP APIs for
|
24
|
-
[SOA](http://en.wikipedia.org/wiki/Service-oriented_architecture) systems.
|
25
|
-
|
26
22
|
Praxis is not a Rails plugin or extension. If you want to use Praxis with
|
27
|
-
Rails, please
|
28
|
-
with Rails-specific functionality.
|
23
|
+
Rails, please look at the MiddlewareApp class on how to embed it on an existing Rails project.
|
29
24
|
|
30
25
|
Praxis is also not designed for service any kind of UI, although UIs can
|
31
26
|
certainly be powered by Praxis apps.
|
@@ -36,10 +31,6 @@ We are always thrilled to receive pull requests, and do our best to process
|
|
36
31
|
them as fast as possible. Not sure if that typo is worth a pull request? Do it!
|
37
32
|
We will appreciate it.
|
38
33
|
|
39
|
-
If your pull request is not accepted on the first try, don't be discouraged! If
|
40
|
-
there's a problem with the implementation, hopefully you received feedback on
|
41
|
-
what to improve.
|
42
|
-
|
43
34
|
We're trying very hard to keep Praxis lean and focused. We don't want it to do
|
44
35
|
everything for everybody. This means that we might decide against incorporating
|
45
36
|
a new feature. However, there might be a way to implement that feature *on top
|
@@ -72,13 +63,7 @@ help prioritize the most common problems and requests.
|
|
72
63
|
|
73
64
|
### Conventions
|
74
65
|
|
75
|
-
Fork the repository and make changes on your fork in a feature branch
|
76
|
-
|
77
|
-
- If it's a bug fix branch, name it XXXX-something where XXXX is the number of
|
78
|
-
the issue.
|
79
|
-
- If it's a feature branch, create an enhancement issue to announce your
|
80
|
-
intentions, and name it XXXX-something where XXXX is the number of the issue.
|
81
|
-
|
66
|
+
Fork the repository and make changes on your fork in a feature branch.
|
82
67
|
Submit unit tests for your changes. Take a look at existing tests for
|
83
68
|
inspiration. Run the full test suite on your branch before submitting a pull
|
84
69
|
request.
|
@@ -115,68 +100,6 @@ github team.
|
|
115
100
|
|
116
101
|
Add a quick summary of your change to the changelog, under the `next` heading.
|
117
102
|
|
118
|
-
### Sign your work
|
119
|
-
|
120
|
-
The sign-off is a simple line at the end of the explanation for the
|
121
|
-
patch, which certifies that you wrote it or otherwise have the right to
|
122
|
-
pass it on as an open-source patch. The rules are pretty simple: if you
|
123
|
-
can certify the below (from
|
124
|
-
[developercertificate.org](http://developercertificate.org/)):
|
125
|
-
|
126
|
-
```
|
127
|
-
Developer Certificate of Origin
|
128
|
-
Version 1.1
|
129
|
-
|
130
|
-
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
131
|
-
660 York Street, Suite 102,
|
132
|
-
San Francisco, CA 94110 USA
|
133
|
-
|
134
|
-
Everyone is permitted to copy and distribute verbatim copies of this
|
135
|
-
license document, but changing it is not allowed.
|
136
|
-
|
137
|
-
Developer's Certificate of Origin 1.1
|
138
|
-
|
139
|
-
By making a contribution to this project, I certify that:
|
140
|
-
|
141
|
-
(a) The contribution was created in whole or in part by me and I
|
142
|
-
have the right to submit it under the open source license
|
143
|
-
indicated in the file; or
|
144
|
-
|
145
|
-
(b) The contribution is based upon previous work that, to the best
|
146
|
-
of my knowledge, is covered under an appropriate open source
|
147
|
-
license and I have the right under that license to submit that
|
148
|
-
work with modifications, whether created in whole or in part
|
149
|
-
by me, under the same open source license (unless I am
|
150
|
-
permitted to submit under a different license), as indicated
|
151
|
-
in the file; or
|
152
|
-
|
153
|
-
(c) The contribution was provided directly to me by some other
|
154
|
-
person who certified (a), (b) or (c) and I have not modified
|
155
|
-
it.
|
156
|
-
|
157
|
-
(d) I understand and agree that this project and the contribution
|
158
|
-
are public and that a record of the contribution (including all
|
159
|
-
personal information I submit with it, including my sign-off) is
|
160
|
-
maintained indefinitely and may be redistributed consistent with
|
161
|
-
this project or the open source license(s) involved.
|
162
|
-
```
|
163
|
-
|
164
|
-
Then you just add a line to every git commit message:
|
165
|
-
|
166
|
-
Signed-off-by: Joe Smith <joe.smith@email.com> Using your real name
|
167
|
-
(sorry, no pseudonyms or anonymous contributions.)
|
168
|
-
|
169
|
-
If you set your user.name and user.email git configs, you can sign your
|
170
|
-
commit automatically with git commit -s.
|
171
|
-
|
172
|
-
#### Small patch exception
|
173
|
-
|
174
|
-
There are several exceptions to the signing requirement. Currently these are:
|
175
|
-
|
176
|
-
* Your patch fixes spelling or grammar errors.
|
177
|
-
* Your patch is a single line change to documentation.
|
178
|
-
* Your patch fixes Markdown formatting or syntax errors in the documentation.
|
179
|
-
|
180
103
|
### How can I become a maintainer?
|
181
104
|
|
182
105
|
* Step 1: Learn the component inside out
|
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
guard :rspec, cmd: 'bundle exec rspec --format=Fuubar', \
|
2
4
|
all_after_pass: false, all_on_start: false, failed_mode: :focus do
|
3
5
|
watch(%r{^spec/.+_spec\.rb$})
|
4
6
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
5
|
-
watch('spec/spec_helper.rb') {
|
6
|
-
watch('spec/functional_spec.rb')
|
7
|
-
watch(%r{^lib/(.+)\.rb$}) { |
|
8
|
-
watch(%r{^app/(.+)\.rb$}) {
|
7
|
+
watch('spec/spec_helper.rb') { 'spec/' }
|
8
|
+
watch('spec/functional_spec.rb') { 'spec/' }
|
9
|
+
watch(%r{^lib/(.+)\.rb$}) { |_m| 'spec/functional_spec.rb' }
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { 'spec/' }
|
9
11
|
watch(%r{^spec/support}) { 'spec/' }
|
10
12
|
end
|
data/LICENSE
CHANGED
data/MAINTAINERS.md
CHANGED
data/README.md
CHANGED
@@ -1,42 +1,35 @@
|
|
1
1
|
# Praxis [![TravisCI][travis-img-url]][travis-ci-url] [![Coverage Status][coveralls-img-url]][coveralls-url]
|
2
2
|
|
3
|
-
[
|
4
|
-
|
5
|
-
[travis-img-url]: https://travis-ci.org/praxis/praxis.svg?branch=master
|
6
|
-
[travis-ci-url]:https://travis-ci.org/praxis/praxis
|
3
|
+
[travis-img-url]: https://app.travis-ci.com/praxis/praxis.svg?branch=master
|
4
|
+
[travis-ci-url]: https://app.travis-ci.com/praxis/praxis
|
7
5
|
[coveralls-img-url]:https://coveralls.io/repos/github/praxis/praxis/badge.svg?branch=master
|
8
6
|
[coveralls-url]:https://coveralls.io/github/praxis/praxis?branch=master
|
9
|
-
[gemnasium-img-url]:https://gemnasium.com/praxis/praxis.svg
|
10
|
-
[gemnasium-url]:https://gemnasium.com/praxis/praxis
|
11
|
-
|
12
|
-
Praxis is a framework for both _designing_ and _implementing_ APIs.
|
13
7
|
|
14
|
-
|
8
|
+
A fast and highly efficient paradigm to build beautiful service APIs
|
15
9
|
|
16
|
-
|
10
|
+
Praxis is built to empower development teams with extreme productivty tools to create fast, and modern APIs that will delight their customers. Some of the salient features are:
|
17
11
|
|
18
|
-
|
12
|
+
* **Truthful & Beautiful Docs:** Automatically generate Open API 3.x documents from the actual functioning code, and rest assured they're always correct.
|
19
13
|
|
20
|
-
|
21
|
-
*
|
22
|
-
*
|
14
|
+
* **GraphQL Flexibility, REST Simplicity:** Allow customers to specify which fields they want to receive using the GraphQL syntax, but exposing them through well known REST endpoints.
|
15
|
+
* **Fast Runtime and Blazing Fast Development:** Deploy your API using one of the best Ruby performing frameworks and take advantage of an unprecedented development speed.
|
16
|
+
* **API Design-First Philosophy:** Craft and visualize your API design upfont, without writing a single line of code. Forget about implementing any of the API validations, the framework fully takes care of it from your design specification.
|
17
|
+
* **Feature Rich yet Fully Customizable:** Fully take advantage of the tons of best practices, proven methods, standards and features that the frameworks comes with, or pick and choose only the ones you want to enable.
|
18
|
+
* **Hardnened & Battle Tested:** Rest assured you'll get the advertised results as this framework has been deployed in production environments since before 2014.
|
23
19
|
|
24
20
|
## Quickstart
|
25
21
|
```bash
|
26
22
|
# Install the praxis gem
|
27
23
|
gem install praxis
|
28
24
|
|
29
|
-
# Generate a praxis application named my-app in ./my-app
|
30
|
-
praxis example my-app
|
25
|
+
# Generate and bundle a praxis application named my-app in ./my-app
|
26
|
+
praxis example my-app && cd my-app && bundle
|
31
27
|
|
32
28
|
# Run it!
|
33
|
-
cd my-app
|
34
|
-
bundle
|
35
29
|
rackup
|
36
30
|
```
|
37
31
|
|
38
|
-
Or
|
39
|
-
|
32
|
+
Or check the getting started tutorial and reference docs at https://www.praxis-framework.io all that Praxis has to offer.
|
40
33
|
|
41
34
|
## Mailing List
|
42
35
|
Join our Google Groups for discussion, support and announcements.
|
@@ -59,10 +52,10 @@ for further details on what contributions are accepted and how to go about
|
|
59
52
|
contributing.
|
60
53
|
|
61
54
|
## Requirements
|
62
|
-
Praxis requires Ruby 2.
|
55
|
+
Praxis requires Ruby 2.5.0 or greater.
|
63
56
|
|
64
57
|
## License
|
65
58
|
|
66
59
|
This software is released under the [MIT License](http://www.opensource.org/licenses/MIT). Please see [LICENSE](LICENSE) for further details.
|
67
60
|
|
68
|
-
|
61
|
+
This framework was initially developed and used at RightScale, and was open sourced in 2014, after a few years of its production use.
|
data/Rakefile
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
2
4
|
|
3
5
|
require 'praxis'
|
4
6
|
require 'praxis/tasks'
|
@@ -9,4 +11,4 @@ require 'bundler/gem_tasks'
|
|
9
11
|
|
10
12
|
RSpec::Core::RakeTask.new(:spec)
|
11
13
|
|
12
|
-
task :
|
14
|
+
task default: :spec
|
data/bin/praxis
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'bundler'
|
4
5
|
|
@@ -9,119 +10,116 @@ rescue Bundler::GemfileNotFound
|
|
9
10
|
# no-op: we might be installed as a system gem
|
10
11
|
end
|
11
12
|
|
12
|
-
if ARGV[0] ==
|
13
|
+
if ARGV[0] == 'version'
|
13
14
|
require 'praxis/version'
|
14
15
|
puts "Praxis version #{Praxis::VERSION}"
|
15
16
|
exit 0
|
16
17
|
end
|
17
18
|
|
18
|
-
if [
|
19
|
+
if %w[routes docs console].include? ARGV[0]
|
19
20
|
require 'rake'
|
20
21
|
require 'praxis'
|
21
22
|
require 'praxis/tasks'
|
22
23
|
load 'Rakefile' # Ensure that we read the App's Rakefile, to pickup any definitions etc.
|
23
24
|
|
24
25
|
case ARGV[0]
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
26
|
+
when 'routes'
|
27
|
+
Rake::Task['praxis:routes'].invoke(ARGV[1])
|
28
|
+
when 'docs'
|
29
|
+
task_name = case ARGV[1]
|
30
|
+
when nil, 'browser'
|
31
|
+
'praxis:docs:preview'
|
32
|
+
when 'generate'
|
33
|
+
'praxis:docs:generate'
|
34
|
+
when 'package'
|
35
|
+
'praxis:docs:package'
|
36
|
+
end
|
37
|
+
Rake::Task[task_name].invoke
|
38
|
+
when 'console'
|
39
|
+
Rake::Task['praxis:console'].invoke
|
39
40
|
end
|
40
41
|
exit 0
|
41
42
|
end
|
42
43
|
# Thor tasks
|
43
44
|
path_to_praxis = File.expand_path(File.dirname(File.dirname(__FILE__)))
|
44
|
-
path_to_loader = '
|
45
|
+
path_to_loader = format('%<path>s/tasks/loader.thor', path: path_to_praxis)
|
45
46
|
|
46
47
|
load path_to_loader
|
47
48
|
|
48
49
|
class PraxisGenerator < Thor
|
49
|
-
|
50
50
|
# Include a few fake thor action descriptions (for the rake tasks above) so they can show up in the same usage messages
|
51
|
-
desc
|
52
|
-
def routes
|
53
|
-
end
|
51
|
+
desc 'routes [json]', 'Prints the route table of the application. Defaults to table format, but can produce json'
|
52
|
+
def routes; end
|
54
53
|
|
55
|
-
desc
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
def docs
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
def console
|
66
|
-
end
|
54
|
+
desc 'docs [generate|browser|package]', <<~HELP
|
55
|
+
Generates API documentation and a Web App to inspect it
|
56
|
+
generate - Generates the JSON docs
|
57
|
+
browser - (default) Generates JSON docs, and automatically starts a Web app to browse them.
|
58
|
+
package - Generates JSON docs, and neatly packages all the necessary static files ready for exporting the browsing app.
|
59
|
+
HELP
|
60
|
+
def docs; end
|
61
|
+
|
62
|
+
desc 'console', 'Open a console to the application, with its environment loaded'
|
63
|
+
def console; end
|
67
64
|
|
68
65
|
# Simple helper to go get the existing description for the real action
|
69
|
-
# Usage must still be provided rather than retrieved (since it is not a
|
66
|
+
# Usage must still be provided rather than retrieved (since it is not a
|
70
67
|
# straight "usage" from the remote action when arguments are defined )
|
71
|
-
def self.desc_for(
|
68
|
+
def self.desc_for(usage_string, klass, action_name, description_prefix = '')
|
72
69
|
action_name = action_name.to_s
|
73
70
|
cmd = klass.commands[action_name]
|
74
71
|
raise "Error, could not find description for #{klass.name}##{action_name}" if cmd.nil?
|
72
|
+
|
75
73
|
desc usage_string, "#{description_prefix}#{cmd.description}"
|
76
74
|
end
|
77
75
|
|
78
|
-
desc_for
|
76
|
+
desc_for 'new APP_NAME', ::PraxisGen::App, :new
|
79
77
|
def new(app_name)
|
80
78
|
gen = ::PraxisGen::App.new([app_name])
|
81
79
|
gen.destination_root = app_name
|
82
80
|
gen.invoke_all
|
83
81
|
end
|
84
82
|
|
85
|
-
desc_for
|
83
|
+
desc_for 'example APP_NAME', ::PraxisGen::Example, :example
|
86
84
|
def example(app_name)
|
87
85
|
gen = ::PraxisGen::Example.new([app_name])
|
88
86
|
gen.destination_root = app_name
|
89
87
|
gen.invoke(:example)
|
90
88
|
end
|
91
89
|
|
92
|
-
desc_for
|
90
|
+
desc_for 'g COLLECTION_NAME', ::PraxisGen::Scaffold, :g
|
93
91
|
# Cannot use the argument below or it will apply to all commands (the action in the class has it)
|
94
92
|
# argument :collection_name, required: false
|
95
93
|
# The options, however, since they're optional are fine (But need to be duplicated from the class :( )
|
96
94
|
option :version, required: false, default: '1',
|
97
|
-
|
95
|
+
desc: 'Version string for the API endpoint. This also dictates the directory structure (i.e., v1/endpoints/...))'
|
98
96
|
option :design, type: :boolean, default: true,
|
99
|
-
|
97
|
+
desc: 'Include the Endpoint and MediaType files for the collection'
|
100
98
|
option :implementation, type: :boolean, default: true,
|
101
|
-
|
99
|
+
desc: 'Include the Controller and (possibly the) Resource files for the collection (see --no-resource)'
|
102
100
|
option :resource, type: :boolean, default: true,
|
103
|
-
|
104
|
-
option :model, type: :string, enum: [
|
105
|
-
|
106
|
-
option :actions, type: :string, default: 'crud', enum: [
|
107
|
-
|
101
|
+
desc: 'Disable (or enable) the creation of the Resource files when generating implementation'
|
102
|
+
option :model, type: :string, enum: %w[activerecord sequel],
|
103
|
+
desc: 'It also generates a model for the given ORM. An empty --model flag will default to activerecord'
|
104
|
+
option :actions, type: :string, default: 'crud', enum: %w[cr cru crud u ud d],
|
105
|
+
desc: 'Specifies the actions to generate for the API. cr=create, u=update, d=delete. Index and show actions are always generated'
|
108
106
|
def g(*args)
|
109
107
|
# Because we cannot share the :collection_name argument, we need to do this check here, before
|
110
108
|
# we "parse" it and pass it to the g command
|
111
109
|
unless args.size == 1
|
112
|
-
::PraxisGen::Scaffold.command_help(shell
|
110
|
+
::PraxisGen::Scaffold.command_help(shell, :g)
|
113
111
|
exit 1
|
114
112
|
end
|
115
113
|
|
116
|
-
collection_name,
|
117
|
-
::PraxisGen::Scaffold.new([collection_name],options).invoke(:g)
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
114
|
+
collection_name, = args
|
115
|
+
::PraxisGen::Scaffold.new([collection_name], options).invoke(:g)
|
116
|
+
return unless options[:model]
|
117
|
+
|
118
|
+
# Make it easy to be able to both enable or not enable the creation of the model, by passing --model=...
|
119
|
+
# but also make it easy so that if there is no value for it, it default to activerecord
|
120
|
+
opts = { orm: options[:model] }
|
121
|
+
opts[:orm] = 'activerecord' if opts[:orm] == 'model' # value is model param passed by no value
|
122
|
+
::PraxisGen::Model.new([collection_name.singularize], opts).invoke(:g)
|
125
123
|
end
|
126
124
|
|
127
125
|
# Initially, the idea was to build some quick model generator, but I think it's better to keep it
|
@@ -144,7 +142,6 @@ class PraxisGenerator < Thor
|
|
144
142
|
# model_name,_ = args
|
145
143
|
# ::PraxisGen::Model.new([model_name],options).invoke(:g)
|
146
144
|
# end
|
147
|
-
|
148
145
|
end
|
149
|
-
|
146
|
+
|
150
147
|
PraxisGenerator.start(ARGV)
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Praxis
|
2
4
|
class ActionDefinition
|
3
5
|
class HeadersDSLCompiler < Attributor::DSLCompiler
|
4
|
-
|
5
6
|
# it allows to define expectations on incoming headers. For example:
|
6
7
|
# header :X_SpecialCookie => implies the header is required
|
7
8
|
# header :X_Something, /matching_this/ => implies that if the name header exists, it should match the regexp
|
@@ -11,10 +12,8 @@ module Praxis
|
|
11
12
|
# required: true => to make it required
|
12
13
|
# description: "lorem ipsum" => to describe it (like any other attribute)
|
13
14
|
|
14
|
-
def header(name, val=nil, **options)
|
15
|
-
if val.
|
16
|
-
return key name, val, **options
|
17
|
-
end
|
15
|
+
def header(name, val = nil, **options)
|
16
|
+
return key name, val, **options if val.is_a?(Class)
|
18
17
|
|
19
18
|
case val
|
20
19
|
when Regexp
|
@@ -25,7 +24,7 @@ module Praxis
|
|
25
24
|
# Defining the existence without any other options can only mean that it is required (otherwise it is a useless definition)
|
26
25
|
options[:required] = true if options.empty?
|
27
26
|
end
|
28
|
-
key name
|
27
|
+
key name, String, **options
|
29
28
|
end
|
30
29
|
end
|
31
30
|
end
|