praxis 0.20.1 → 0.21
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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +2 -2
- data/CHANGELOG.md +36 -0
- data/lib/api_browser/Gruntfile.js +33 -3
- data/lib/api_browser/app/index.html +3 -0
- data/lib/api_browser/app/js/factories/Example.js +4 -0
- data/lib/api_browser/app/js/factories/template_for.js +14 -0
- data/lib/api_browser/app/js/filters/attribute_name.js +3 -2
- data/lib/api_browser/app/js/filters/header_info.js +9 -0
- data/lib/api_browser/app/views/action.html +11 -2
- data/lib/api_browser/app/views/controller.html +5 -5
- data/lib/api_browser/app/views/menu.html +1 -1
- data/lib/api_browser/app/views/type.html +4 -23
- data/lib/api_browser/app/views/type/details.html +7 -4
- data/lib/api_browser/app/views/types/main/array.html +22 -0
- data/lib/api_browser/app/views/types/main/default.html +23 -0
- data/lib/api_browser/app/views/types/main/hash.html +23 -0
- data/lib/praxis.rb +2 -0
- data/lib/praxis/action_definition.rb +0 -8
- data/lib/praxis/api_definition.rb +11 -6
- data/lib/praxis/api_general_info.rb +13 -0
- data/lib/praxis/bootloader.rb +11 -5
- data/lib/praxis/docs/generator.rb +31 -11
- data/lib/praxis/docs/link_builder.rb +30 -0
- data/lib/praxis/extensions/field_expansion.rb +2 -2
- data/lib/praxis/media_type.rb +1 -1
- data/lib/praxis/middleware_app.rb +30 -0
- data/lib/praxis/resource_definition.rb +24 -2
- data/lib/praxis/response.rb +2 -1
- data/lib/praxis/response_definition.rb +2 -2
- data/lib/praxis/responses/http.rb +28 -92
- data/lib/praxis/responses/validation_error.rb +4 -1
- data/lib/praxis/tasks/api_docs.rb +11 -24
- data/lib/praxis/trait.rb +12 -7
- data/lib/praxis/validation_handler.rb +2 -1
- data/lib/praxis/version.rb +1 -1
- data/praxis.gemspec +11 -7
- data/spec/api_browser/filters/attribute_name_spec.js +2 -2
- data/spec/praxis/action_definition_spec.rb +23 -1
- data/spec/praxis/bootloader_spec.rb +28 -0
- data/spec/praxis/extensions/field_expansion_spec.rb +10 -0
- data/spec/praxis/middleware_app_spec.rb +55 -0
- data/spec/praxis/plugins/praxis_mapper_plugin_spec.rb +8 -3
- data/spec/praxis/resource_definition_spec.rb +51 -2
- data/spec/praxis/response_definition_spec.rb +16 -4
- data/spec/praxis/response_spec.rb +1 -1
- data/spec/praxis/trait_spec.rb +13 -0
- data/spec/spec_app/config/environment.rb +11 -1
- metadata +30 -25
- data/lib/praxis/restful_doc_generator.rb +0 -439
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0a0928d3b9a59294d32767a333b73c03a0a7955
|
4
|
+
data.tar.gz: 840261c0c55f18280f3c32d53a62053ed8582834
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c7d30737b31ec8204e030ca43577d8a4620b4a16ee3f9ec00c40ef740f08db8c7c21d9bc1d06dc7ddc56e2223dc0f9aaa990526a6f92f7297493dcf02158c11
|
7
|
+
data.tar.gz: b1e794d55ef40a616c21adeb8a72cea53b796e4a943636c5a16a576f282298c6f573b730f708ab2a0bbb050784c56c3b1fe53f760488c3100d98958a2b50f6eb
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.3
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,42 @@
|
|
2
2
|
|
3
3
|
## next
|
4
4
|
|
5
|
+
## 0.21
|
6
|
+
|
7
|
+
* Protect against `MediaType`s that do not have any links defined.
|
8
|
+
* More robust scanning of existing types when generating docs. Some types might have not been
|
9
|
+
properly reported in the `schemas` section of the JSON docs if they were only used somewhere
|
10
|
+
deep in some other type or action hierarchy
|
11
|
+
* Build doc browser support for defining top-level home pages for types.
|
12
|
+
Apps can achieve the override by registering templates that respond to the ‘main’ type (instead of
|
13
|
+
the other existing ‘label’,’embedded’ and ‘standalone’ modes).
|
14
|
+
* Enhance doc browser to show header and location expectations on action responses that have them
|
15
|
+
defined
|
16
|
+
* Allow Plugin registration without requiring config_key
|
17
|
+
* registration will select a default config_key based on the class name
|
18
|
+
* A new `documentation_url` global directive is exposed for authors to be able to
|
19
|
+
indicate where documentation will be hosted.
|
20
|
+
* If this is provided, the default *validation handler* will add a `documentation`
|
21
|
+
key to the response pointing at a url that should correspond to the documentation
|
22
|
+
for the resource the user was requesting.
|
23
|
+
* `Praxis::Docs::LinkBuilder` can be used to generate these documentation urls from
|
24
|
+
the praxis application.
|
25
|
+
* You can now switch your doc browser to use HTML5 style urls (i.e.
|
26
|
+
`/1.0/type/V1-MediaTypes-PriceFilter` instead of
|
27
|
+
`/index.html#/1.0/type/V1-MediaTypes-PriceFilter`).
|
28
|
+
* Remove deprecated rake tasks.
|
29
|
+
* Remove some remaining inline styling in doc browser.
|
30
|
+
* Adds a `ExampleProvider.removeHandlersForKey` call. You can use `ExampleProvider.removeHandlersForKey('general')`
|
31
|
+
to get rid of the default example if required.
|
32
|
+
* Make Traits accumulate block definitions for `params`,`headers` and `payload` rather than overriding them.
|
33
|
+
* Switch to lazy evaluation of `base_params` from `ApiDefinition` to properly inherit them into the resources
|
34
|
+
and their corresponding actions even before the application's `MediaTtypes` have been finalized.
|
35
|
+
* Built the `MiddlewareApp` class to make it easy to run a Praxis app mounted as an intercepting
|
36
|
+
middleware which will only forward requests down the stack if they didn't match any of its routes.
|
37
|
+
* Note: it properly skips forwarding when 404s are purposedly returned by the application itself.
|
38
|
+
* Note2: it also respects the `X-Cascade=pass` conventions.
|
39
|
+
|
40
|
+
|
5
41
|
## 0.20.1
|
6
42
|
|
7
43
|
* Doc generation: handle SimpleMediaTypes so that they don’t show up in the generated schemas.
|
@@ -13,7 +13,8 @@ module.exports = function(grunt) {
|
|
13
13
|
pluginPaths = process.env.PLUGIN_PATHS ? process.env.PLUGIN_PATHS.split(':') : [],
|
14
14
|
buildPath = userDocsPath + '/output',
|
15
15
|
browserPort = process.env.DOC_PORT || '9090',
|
16
|
-
bowerPaths = pluginPaths.concat([userDocsPath]).map(function(f) { return f + '/bower.json'; })
|
16
|
+
bowerPaths = pluginPaths.concat([userDocsPath]).map(function(f) { return f + '/bower.json'; }),
|
17
|
+
basePath = process.env.BASE_PATH || '';
|
17
18
|
|
18
19
|
var cssOutput = {};
|
19
20
|
cssOutput[buildPath + '/css/main.css'] = userDocsPath + '/styles.scss';
|
@@ -75,7 +76,28 @@ module.exports = function(grunt) {
|
|
75
76
|
'.tmp',
|
76
77
|
'.data',
|
77
78
|
'app'
|
78
|
-
])
|
79
|
+
]),
|
80
|
+
// This is to handle support of using $locationProvider.html5Mode(true).
|
81
|
+
middleware: function(connect, options, middlewares) {
|
82
|
+
middlewares.push(function(req, res, next) {
|
83
|
+
var segments = require('url').parse(req.url).pathname.split('/'),
|
84
|
+
last = segments[segments.length - 1];
|
85
|
+
if (last.split('.').length === 1) {
|
86
|
+
try {
|
87
|
+
var index = grunt.file.read('.tmp/index.html');
|
88
|
+
res.setHeader("Content-Type", "text/html");
|
89
|
+
res.write(index, 'utf8');
|
90
|
+
res.end()
|
91
|
+
} catch(e) {
|
92
|
+
next(e);
|
93
|
+
}
|
94
|
+
} else {
|
95
|
+
next();
|
96
|
+
}
|
97
|
+
});
|
98
|
+
|
99
|
+
return middlewares;
|
100
|
+
}
|
79
101
|
}
|
80
102
|
},
|
81
103
|
dist: {
|
@@ -362,7 +384,15 @@ module.exports = function(grunt) {
|
|
362
384
|
html: [buildPath + '/index.html'],
|
363
385
|
css: [buildPath + '/css/{,*/}*.css'],
|
364
386
|
options: {
|
365
|
-
assetsDirs: [buildPath]
|
387
|
+
assetsDirs: [buildPath],
|
388
|
+
blockReplacements: {
|
389
|
+
base: function(block) {
|
390
|
+
if (basePath !== '') {
|
391
|
+
return '<base href="' + basePath + '">';
|
392
|
+
}
|
393
|
+
return '';
|
394
|
+
}
|
395
|
+
}
|
366
396
|
}
|
367
397
|
},
|
368
398
|
|
@@ -6,6 +6,9 @@
|
|
6
6
|
<title ng-bind="subtitle ? title + ' – ' + subtitle : title">API Browser</title>
|
7
7
|
<meta name="description" content="">
|
8
8
|
<meta name="viewport" content="width=device-width">
|
9
|
+
<!-- build:base base -->
|
10
|
+
<base src="/">
|
11
|
+
<!-- endbuild -->
|
9
12
|
<!-- build:css({.tmp,app,/}) css/other.css -->
|
10
13
|
<!-- bower:css -->
|
11
14
|
<!-- endbower -->
|
@@ -80,6 +80,20 @@ app.provider('templateFor', function() {
|
|
80
80
|
}
|
81
81
|
});
|
82
82
|
|
83
|
+
this.register(function mainPageResolver($family, $requestedTemplate) {
|
84
|
+
'ngInject';
|
85
|
+
if ($requestedTemplate === 'main') {
|
86
|
+
switch ($family) {
|
87
|
+
case 'hash':
|
88
|
+
return 'views/types/main/hash.html';
|
89
|
+
case 'array':
|
90
|
+
return 'views/types/main/array.html';
|
91
|
+
default:
|
92
|
+
return 'views/types/main/default.html';
|
93
|
+
}
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
83
97
|
this.$get = function($injector, prepareTemplate) {
|
84
98
|
return function(type, templateType) {
|
85
99
|
for (var i = 0; i < resolvers.length; i++) {
|
@@ -1,8 +1,9 @@
|
|
1
1
|
app.filter('attributeName', function($sce) {
|
2
2
|
return function(input) {
|
3
3
|
var parts = input.split('.');
|
4
|
-
if (parts.length
|
5
|
-
|
4
|
+
if (parts.length > 1) {
|
5
|
+
var prefix = _.take(parts, parts.length-1).join('.');
|
6
|
+
return $sce.trustAsHtml('<span class="attribute-prefix">' + prefix + '.</span>' + _.last(parts));
|
6
7
|
}
|
7
8
|
return $sce.trustAsHtml(input);
|
8
9
|
};
|
@@ -56,12 +56,21 @@
|
|
56
56
|
<h5>Description</h5>
|
57
57
|
<div ng-bind-html="response.description | markdown"></div>
|
58
58
|
</div>
|
59
|
-
<h5>Status</h5>
|
60
|
-
<p>{{ response.status }}</p>
|
59
|
+
<h5>Status: {{ response.status }}</h5>
|
61
60
|
<div ng-if="response.examples.json">
|
62
61
|
<h5>Content-Type</h5>
|
63
62
|
<p>{{ response.examples.json.content_type }}</p>
|
64
63
|
</div>
|
64
|
+
<div ng-if="response.location">
|
65
|
+
<h5>Location:</h5>
|
66
|
+
<p>{{response.location.value}} <em>({{response.location.type}})</em></p>
|
67
|
+
</div>
|
68
|
+
<div ng-hide="response.headers | isEmpty">
|
69
|
+
<h5>Headers:</h5>
|
70
|
+
<div ng-repeat="(hname, hinfo) in response.headers">
|
71
|
+
<p> {{hname}}: {{ hinfo | headerInfo }}</p>
|
72
|
+
</div>
|
73
|
+
</div>
|
65
74
|
<div ng-if="response.payload.id">
|
66
75
|
<h5>Media Type</h5>
|
67
76
|
<p><type-placeholder template="label" type="response.payload"></type-placeholder></p>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<div class="row">
|
6
6
|
<div class="col-lg-12">
|
7
7
|
<h1 class="page-header">
|
8
|
-
{{ controller.name | resourceName }}
|
8
|
+
{{ controller.display_name || (controller.name | resourceName) }}
|
9
9
|
</h1>
|
10
10
|
|
11
11
|
<p ng-bind-html="controller.description | markdown"></p>
|
@@ -16,7 +16,7 @@
|
|
16
16
|
</p>
|
17
17
|
</div>
|
18
18
|
</div>
|
19
|
-
<div class="row" ng-if="controller.actions.length">
|
19
|
+
<div class="row actions-overview" ng-if="controller.actions.length">
|
20
20
|
<div class="col-lg-12">
|
21
21
|
<h2>Actions</h2>
|
22
22
|
<div class="table-responsive">
|
@@ -30,13 +30,13 @@
|
|
30
30
|
</thead>
|
31
31
|
<tbody>
|
32
32
|
<tr ng-repeat="action in controller.actions">
|
33
|
-
<td>
|
33
|
+
<td class="action-overview-name">
|
34
34
|
<a ui-sref="root.action({action: action.name, controller: controllerName, version: apiVersion})">{{ action.name }}</a>
|
35
35
|
</td>
|
36
|
-
<td>
|
36
|
+
<td class="action-overview-url">
|
37
37
|
<url action="action"></url>
|
38
38
|
</td>
|
39
|
-
<td
|
39
|
+
<td class="action-overview-description">
|
40
40
|
<p ng-bind-html="action.description | markdown"></p>
|
41
41
|
</td>
|
42
42
|
</tr>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<div class="row">
|
3
3
|
<div class="col-sm-12">
|
4
4
|
<p>
|
5
|
-
<div ng-if="versions.length > 1" dropdown
|
5
|
+
<div ng-if="versions.length > 1" dropdown dropdown-append-to-body>
|
6
6
|
<button type="button" class="btn btn-success" dropdown-toggle ng-disabled="disabled">
|
7
7
|
{{:: versionLabel}}: {{selectedVersion}} <span class="caret"></span>
|
8
8
|
</button>
|
@@ -1,25 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
<
|
4
|
-
<p>The requested type could not be found.</p>
|
5
|
-
</div>
|
6
|
-
<div ng-if="type">
|
7
|
-
<div class="row">
|
8
|
-
<div class="col-lg-12">
|
9
|
-
<h1>
|
10
|
-
{{ type.name | resourceName }}
|
11
|
-
</h1>
|
12
|
-
</div>
|
13
|
-
</div>
|
14
|
-
<div class="row" ng-if="controllers.length">
|
15
|
-
<div class="col-lg-12">
|
16
|
-
<h3>Served by</h3>
|
17
|
-
<ul>
|
18
|
-
<li ng-repeat="controller in controllers">
|
19
|
-
<a ui-sref="root.controller({version: apiVersion, controller: controller.id})">{{ controller.name | resourceName }}</a>
|
20
|
-
</li>
|
21
|
-
</ul>
|
22
|
-
</div>
|
1
|
+
<div ng-if="type">
|
2
|
+
<div ng-if="error" class="alert alert-danger">
|
3
|
+
<p>The requested type could not be found.</p>
|
23
4
|
</div>
|
24
|
-
<
|
5
|
+
<type-placeholder type="type" template="main" details="type.attributes"></type-placeholder>
|
25
6
|
</div>
|
@@ -1,10 +1,13 @@
|
|
1
1
|
<div class="row" ng-if="type">
|
2
2
|
<div class="col-lg-12">
|
3
|
-
<
|
4
|
-
|
5
|
-
|
3
|
+
<div ng-if="type.attributes">
|
4
|
+
<h2>Schema</h2>
|
5
|
+
<p ng-if="type.identifier"><b>Media-type identifier: {{ type.identifier }}</b></p>
|
6
|
+
<div ng-if="type.description" ng-bind-html="type.description | markdown"></div>
|
6
7
|
|
7
|
-
|
8
|
+
<attribute-table attributes="type.attributes"></attribute-table>
|
9
|
+
</div>
|
10
|
+
<div ng-if="type.attributes === undefined" type-placeholder type="type" template="standalone" name="type.name" details="type"></div>
|
8
11
|
</div>
|
9
12
|
</div>
|
10
13
|
<div class="row" ng-if="views.length">
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<div ng-if="type">
|
2
|
+
<div class="row">
|
3
|
+
<div class="col-lg-12">
|
4
|
+
<h1>
|
5
|
+
{{ type.name | resourceName }}
|
6
|
+
</h1>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
<div class="row" ng-if="controllers.length">
|
10
|
+
<div class="col-lg-12">
|
11
|
+
<h3>Served by</h3>
|
12
|
+
<ul>
|
13
|
+
<li ng-repeat="controller in controllers">
|
14
|
+
<a ui-sref="root.controller({version: apiVersion, controller: controller.id})">{{ controller.name | resourceName }}</a>
|
15
|
+
</li>
|
16
|
+
</ul>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
<p>A Collection of:</p>
|
20
|
+
|
21
|
+
<type-placeholder type="type.member_attribute.type" template="standalone" details="type.member_attribute.type.attributes"></type-placeholder>
|
22
|
+
</div>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<div ng-if="error" class="alert alert-danger">
|
2
|
+
<p>The requested type could not be found.</p>
|
3
|
+
</div>
|
4
|
+
<div ng-if="type">
|
5
|
+
<div class="row">
|
6
|
+
<div class="col-lg-12">
|
7
|
+
<h1>
|
8
|
+
{{ type.name | resourceName }}
|
9
|
+
</h1>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
<div class="row" ng-if="controllers.length">
|
13
|
+
<div class="col-lg-12">
|
14
|
+
<h3>Served by</h3>
|
15
|
+
<ul>
|
16
|
+
<li ng-repeat="controller in controllers">
|
17
|
+
<a ui-sref="root.controller({version: apiVersion, controller: controller.id})">{{ controller.name | resourceName }}</a>
|
18
|
+
</li>
|
19
|
+
</ul>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
<ng-include src="'views/type/details.html'" />
|
23
|
+
</div>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<div ng-if="error" class="alert alert-danger">
|
2
|
+
<p>The requested type could not be found.</p>
|
3
|
+
</div>
|
4
|
+
<div ng-if="type">
|
5
|
+
<div class="row">
|
6
|
+
<div class="col-lg-12">
|
7
|
+
<h1>
|
8
|
+
{{ type.name | resourceName }}
|
9
|
+
</h1>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
<div class="row" ng-if="controllers.length">
|
13
|
+
<div class="col-lg-12">
|
14
|
+
<h3>Served by</h3>
|
15
|
+
<ul>
|
16
|
+
<li ng-repeat="controller in controllers">
|
17
|
+
<a ui-sref="root.controller({version: apiVersion, controller: controller.id})">{{ controller.name | resourceName }}</a>
|
18
|
+
</li>
|
19
|
+
</ul>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
<ng-include src="'views/type/details.html'" />
|
23
|
+
</div>
|
data/lib/praxis.rb
CHANGED
@@ -45,10 +45,12 @@ module Praxis
|
|
45
45
|
|
46
46
|
autoload :Stats, 'praxis/stats'
|
47
47
|
autoload :Notifications, 'praxis/notifications'
|
48
|
+
autoload :MiddlewareApp, 'praxis/middleware_app'
|
48
49
|
|
49
50
|
autoload :RestfulDocGenerator, 'praxis/restful_doc_generator'
|
50
51
|
module Docs
|
51
52
|
autoload :Generator, 'praxis/docs/generator'
|
53
|
+
autoload :LinkBuilder, 'praxis/docs/link_builder'
|
52
54
|
end
|
53
55
|
|
54
56
|
# types
|
@@ -118,14 +118,6 @@ module Praxis
|
|
118
118
|
update_attribute(@params, opts, block)
|
119
119
|
else
|
120
120
|
@params = create_attribute(type, **opts, &block)
|
121
|
-
if (api_info = ApiDefinition.instance.info(resource_definition.version))
|
122
|
-
if api_info.base_params
|
123
|
-
base_attrs = api_info.base_params.attributes
|
124
|
-
@params.attributes.merge!(base_attrs) do |key, oldval, newval|
|
125
|
-
oldval
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
121
|
end
|
130
122
|
|
131
123
|
@params
|
@@ -92,17 +92,22 @@ module Praxis
|
|
92
92
|
end
|
93
93
|
|
94
94
|
define do |api|
|
95
|
-
api.response_template :ok do |media_type: |
|
96
|
-
media_type media_type
|
95
|
+
api.response_template :ok do |media_type: , location: nil, headers: nil, description: nil |
|
97
96
|
status 200
|
98
|
-
description 'Standard response for successful HTTP requests.'
|
97
|
+
description( description || 'Standard response for successful HTTP requests.' )
|
98
|
+
|
99
|
+
media_type media_type
|
100
|
+
location location
|
101
|
+
headers headers if headers
|
99
102
|
end
|
100
103
|
|
101
|
-
api.response_template :created do |location: nil,
|
104
|
+
api.response_template :created do |media_type: nil, location: nil, headers: nil, description: nil|
|
105
|
+
status 201
|
106
|
+
description( description || 'The request has been fulfilled and resulted in a new resource being created.' )
|
107
|
+
|
102
108
|
media_type media_type if media_type
|
103
109
|
location location
|
104
|
-
|
105
|
-
description 'The request has been fulfilled and resulted in a new resource being created.'
|
110
|
+
headers headers if headers
|
106
111
|
end
|
107
112
|
end
|
108
113
|
|