Skip to content

Commit

Permalink
Merge pull request #96 from martindale/api-docs
Browse files Browse the repository at this point in the history
API Documentation
  • Loading branch information
martindale committed Aug 10, 2015
2 parents ec3e46a + 0148b50 commit 1a3df09
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 24 deletions.
70 changes: 46 additions & 24 deletions lib/Service/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,12 @@ HTTP.prototype.provide = function() {
}
});

res.format( formatters );
if (req.param('format') === 'json') {
formatters.json();
} else {
res.format( formatters );
}


};

Expand Down Expand Up @@ -311,36 +316,53 @@ HTTP.prototype.attach = function( maki ) {
})
}

maki.app.all('/', function(req, res, next) {
if ('OPTIONS' === req.method) {
var resourceList = Object.keys( maki.resources ).filter(function(r) {
var resource = maki.resources[ r ];
return !resource.internal || !resource.static;
}).map(function(r) {
var resource = maki.resources[ r ];

var realPaths = {};
Object.keys( resource.paths ).forEach(function( path ) {
realPaths[ path ] = resource.paths[ path ].toString();
});
resource.paths = realPaths;
function serveDocumentation(req, res, next) {
var resourceList = Object.keys( maki.resources ).filter(function(r) {
var resource = maki.resources[ r ];
return !resource.internal || !resource.static;
}).map(function(r) {
var resource = maki.resources[ r ];

return resource;
var realPaths = {};
Object.keys( resource.paths ).forEach(function( path ) {
realPaths[ path ] = resource.paths[ path ].toString();
});
resource.paths = realPaths;

return res.send({
config: {
views: {
client: maki.config.views.client
}
},
// TODO: fix circular JSON issue here
resources: resourceList
});
return resource;
});

return res.format({
html: function() {
res.render('endpoints', {
resources: resourceList
})
},
json: function() {
res.send({
config: {
views: {
client: maki.config.views.client
}
},
// TODO: fix circular JSON issue here
resources: resourceList
});
}
});
}

maki.app.all('/', function(req, res, next) {
if ('OPTIONS' === req.method) {
return serveDocumentation(req, res, next);
}
next();
});

maki.app.get('/api', function(req, res, next) {
return serveDocumentation(req, res, next);
});

function filePopulatorFor(field) {
return function(req, res, next) {
var db = maki.datastore.mongoose.connections[0].db;
Expand Down
75 changes: 75 additions & 0 deletions views/endpoints.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
extends layouts/default

block content
h1 #{config.service.name} API

h3 Generally
p <strong>Formatting:</strong> All endpoints serve both JSON and HTML, controlled by the <code>Accept</code> header of your request. You can force the formatting of any resource using the <code>format</code> parameter: i.e., append <code>?format=json</code> to any URL to retrieve the underlying resource as JSON.
p <strong>Events:</strong> Any endpoint can be connected to with a WebSocket, and updates to that resource will be served to you as messages. These messages will be formatted as JSON-PATCH arrays, wrapped in JSON-RPC with the method name <code>patch</code>. The <code>channel</code> parameter will correspond to the resource's route. For more information, see <a href="https://github.com/martindale/maki#pubsub">the Maki documentation on PubSub &amp; Messaging</a>.
p All endpoints can also be interacted with via the following HTTP verbs:
pre
code.
query, get: GET
create: POST, PUT
update: PATCH
delete: DELETE

- var methodMap = { query: 'GET', get: 'GET', create: 'POST', update: 'PATCH', destroy: 'DELETE' }

.ui.stackable.grid
.four.wide.column
.ui.vertical.fluid.menu
for resource in resources
a.item(href="/api##{resource.plural.toLowerCase()}")
if (resource.options.icon)
i.icon(class="#{resource.options.icon}")
| #{resource.plural}
.twelve.wide.column
.ui.cards
for resource in resources
.ui.fluid.card
.content
.header
if (resource.options.icon)
i.icon(class="#{resource.options.icon}")
a(href="##{resource.plural.toLowerCase()}", name="#{resource.plural.toLowerCase()}") #{resource.plural}
.description #{resource.description}
.description
h4 Paths
table.ui.table
thead
tr
th Operation
th HTTP Method
th Route
tbody
for method in Object.keys(resource.routes)
tr
td #{method}
td #{methodMap[method]}
td #{resource.routes[method]}

h3 Attributes
table.ui.table
thead
tr
th Name
th Type
th Required?
th Allowed Values
th Default
th Min
th Max
th Validator
tbody
for name in Object.keys(resource.attributes)
- var attribute = resource.attributes[name]
tr
td #{name}
td #{(attribute.type && attribute.type.name) ? attribute.type.name : attribute.type}
td #{attribute.required}
td #{attribute.enum}
td #{attribute.default}
td #{attribute.min}
td #{attribute.max}
td #{attribute.validator}

0 comments on commit 1a3df09

Please sign in to comment.