Skip to content

Commit

Permalink
feat(template): Support any named path parameter
Browse files Browse the repository at this point in the history
Handle path parameters other than `{id}` and `{parentId}` such that
individual API developers can choose to name parameters as they see
fit.

Currently the paths only support 2 levels, after the 2nd path
parameter the generator will fall back to the default handlers.

closes #8
  • Loading branch information
kenjones-cisco committed Jan 8, 2016
1 parent bc6a955 commit 77eb93a
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 177 deletions.
29 changes: 15 additions & 14 deletions handlers/templates/_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ var <%=dbmodel.name%> = require('<%=dbmodel.path%>');<%})%>
* Operations on <%=path%>
*/
module.exports = {
<% _.forEach(methods, function (method, i) {%>
<% var metadata = helpers.getPathMetadata(path);
_.forEach(methods, function (method, i) {%>
/**
* <%=method.description%>
*
Expand All @@ -23,42 +24,42 @@ module.exports = {
var includeOpts = {
Model: dbmodels[0].name,
method: method,
formatSuccessResponse: helpers.formatSuccessResponse
formatSuccessResponse: helpers.formatSuccessResponse,
subModelAttribute: metadata.subResource,
id: metadata.id,
parentId: metadata.parentId
};
var includeSubOpts = _.defaults({
subModelAttribute: helpers.getSubResourceAttribute(path)
}, includeOpts);

switch (helpers.getPathType(path, method.method)) {
switch (method.method + metadata.type) {
case 'getResources':%>
<%- include('getResources', includeOpts); %>
<%break;
case 'getResource':%>
<%- include('getResource', includeOpts); %>
<%break;
case 'getSubResources':%>
<%- include('getSubResources', includeSubOpts); %>
<%- include('getSubResources', includeOpts); %>
<%break;
case 'getSubResource':%>
<%- include('getSubResource', includeSubOpts); %>
<%- include('getSubResource', includeOpts); %>
<%break;
case 'putResource':%>
<%- include('putResource', includeOpts); %>
<%break;
case 'putSubResource':%>
<%- include('putSubResource', includeSubOpts); %>
<%- include('putSubResource', includeOpts); %>
<%break;
case 'deleteResource':%>
<%- include('deleteResource', includeOpts); %>
<%break;
case 'deleteSubResource':%>
<%- include('deleteSubResource', includeSubOpts); %>
<%- include('deleteSubResource', includeOpts); %>
<%break;
case 'postResource':%>
<%- include('postResource', includeOpts); %>
case 'postResources':%>
<%- include('postResources', includeOpts); %>
<%break;
case 'postSubResource':%>
<%- include('postSubResource', includeSubOpts); %>
case 'postSubResources':%>
<%- include('postSubResources', includeOpts); %>
<%break;
default:%>
<%- include('default'); %>
Expand Down
2 changes: 1 addition & 1 deletion handlers/templates/deleteResource.ejs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%=Model%>.findByIdAndRemove(req.params.id).exec().then(function (item) {
<%=Model%>.findByIdAndRemove(req.params.<%=id%>).exec().then(function (item) {
if (!item) {
res.sendStatus(404);
return next();
Expand Down
4 changes: 2 additions & 2 deletions handlers/templates/deleteSubResource.ejs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<%=Model%>.findById(req.params.parentId).exec().then(function (item) {
<%=Model%>.findById(req.params.<%=parentId%>).exec().then(function (item) {
if (!item) {
res.sendStatus(404);
return next();
}
item.<%=subModelAttribute%>.id(req.params.id).remove();
item.<%=subModelAttribute%>.id(req.params.<%=id%>).remove();
item.save(function (saveErr) {
return next(saveErr);
});
Expand Down
2 changes: 1 addition & 1 deletion handlers/templates/getResource.ejs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var fields = !req.query.fields ? null : req.query.fields.replace(',', ' ');
<%=Model%>.findById(req.params.id, fields).exec().then(function (item) {
<%=Model%>.findById(req.params.<%=id%>, fields).exec().then(function (item) {
if (!item) {
res.sendStatus(404);
return next();
Expand Down
4 changes: 2 additions & 2 deletions handlers/templates/getSubResource.ejs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<%=Model%>.findById(req.params.parentId).exec().then(function (item) {
<%=Model%>.findById(req.params.<%=parentId%>).exec().then(function (item) {
if (!item) {
res.sendStatus(404);
return next();
}

var subDoc = item.<%=subModelAttribute%>.id(req.params.id);
var subDoc = item.<%=subModelAttribute%>.id(req.params.<%=id%>);
if (!subDoc) {
res.sendStatus(404);
return next();
Expand Down
2 changes: 1 addition & 1 deletion handlers/templates/getSubResources.ejs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%=Model%>.findById(req.params.id).exec().then(function (item) {
<%=Model%>.findById(req.params.<%=id%>).exec().then(function (item) {
if (!item) {
res.sendStatus(404);
return next();
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%=Model%>.findById(req.params.parentId).exec().then(function (item) {
<%=Model%>.findById(req.params.<%=parentId%>).exec().then(function (item) {
if (!item) {
res.sendStatus(404);
return next();
Expand Down
2 changes: 1 addition & 1 deletion handlers/templates/putResource.ejs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%=Model%>.findByIdAndUpdate(req.params.id, req.body, {'new': true}).exec().then(function (item) {
<%=Model%>.findByIdAndUpdate(req.params.<%=id%>, req.body, {'new': true}).exec().then(function (item) {
if (!item) {
res.sendStatus(404);
return next();
Expand Down
4 changes: 2 additions & 2 deletions handlers/templates/putSubResource.ejs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<%=Model%>.findById(req.params.parentId).exec().then(function (item) {
<%=Model%>.findById(req.params.<%=parentId%>).exec().then(function (item) {
if (!item) {
res.sendStatus(404);
return next();
}

var subDoc = item.<%=subModelAttribute%>.id(req.params.id);
var subDoc = item.<%=subModelAttribute%>.id(req.params.<%=id%>);
if (!subDoc) {
res.sendStatus(404);
return next();
Expand Down
91 changes: 37 additions & 54 deletions lib/specutil.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ var helpers = module.exports;


var refRegExp = /^#\/definitions\/(\w*)$/;
var pathParamRegExp = /^{.*}$/;


var simpleTypes = {
integer: 'Number',
Expand Down Expand Up @@ -150,66 +152,47 @@ helpers.getRespSchema = function getRespSchema(object) {
return _.uniq(schemas);
};

helpers.getPathType = function getPathType(routePath, verb) {
var parent = false;
var byId = false;
var subDoc = false;
routePath.split('/').forEach(function (element) {
if (element) {
if (element === '{parentId}') {
parent = true;
} else if (element === '{id}') {
byId = true;
} else {
if (byId) {
subDoc = true;
}
helpers.getPathMetadata = function getPathMetadata(routePath) {
var totParam = 0;
var totPaths = 0;
var metadata = {
type: null,
subResource: null,
parentId: null,
id: null
};

_.compact(routePath.split('/')).forEach(function (element) {
if (pathParamRegExp.test(element)) {
element = element.replace(/{/g, '').replace(/}/g, '');
totParam += 1;
if (!metadata.id) {
metadata.id = element;
} else if (!metadata.parentId) {
metadata.parentId = metadata.id;
metadata.id = element;
}
} else {
totPaths += 1;
metadata.subResource = element;
}
});

switch (verb) {
case 'get':
if (!byId && !parent) {
return 'getResources';
}
if (byId) {
if (parent) {
return 'getSubResource';
}
return subDoc ? 'getSubResources' : 'getResource';
}
break;
case 'put':
if (byId && !subDoc) {
return parent ? 'putSubResource' : 'putResource';
}
break;
case 'delete':
if (byId && !subDoc) {
return parent ? 'deleteSubResource' : 'deleteResource';
}
break;
case 'post':
return byId ? 'postSubResource' : 'postResource';
default:
break;
}
return null;
};

helpers.getSubResourceAttribute = function getSubResourceAttribute(routePath) {
var parts = routePath.split('/');
var subattr = null;

while (parts) {
var part = parts.pop();
if (part && part !== '{parentId}' && part !== '{id}') {
subattr = part;
break;
if (totParam === 0 && totPaths > 0) {
metadata.type = 'Resources';
} else if (totParam === 1) {
if (totPaths === 1) {
metadata.type = 'Resource';
}
if (totPaths === 2) {
metadata.type = 'SubResources';
}
} else if (totParam === 2) {
metadata.type = 'SubResource';
}
return subattr;

debug('path metadata', metadata);
return metadata;
};

helpers.formatSuccessResponse = function formatSuccessResponse(responses, returnKey) {
Expand Down
Loading

0 comments on commit 77eb93a

Please sign in to comment.