Skip to content

Instantly share code, notes, and snippets.

@olegp
Created April 14, 2011 02:55
Show Gist options
  • Save olegp/918816 to your computer and use it in GitHub Desktop.
Save olegp/918816 to your computer and use it in GitHub Desktop.
const GET = "GET", PUT = "PUT", POST = "POST", DELETE = "DELETE", HEAD = "HEAD";
function generate(base, endpoints) {
function camelCase(string) {
return string.charAt(0).toUpperCase() + string.substring(1);
}
function isArgument(component) {
return component.indexOf("{") == 0 &&
(component.indexOf("}") == component.length - 1);
}
var proxy = {};
for(var key in endpoints) {
var methods = endpoints[key];
var eps = key.split('/');
for(var i = 0, l = methods.length; i < l; i ++) {
var meth = methods[i];
var name = [], locs = [];
for(var j = 0, m = eps.length; j < m; j ++) {
var component = eps[j];
if(isArgument(component)) {
locs.push(j);
} else {
name.push(camelCase(component));
}
}
proxy[meth.toLowerCase() + name.join('')] = function() {
var method = meth, endpoint = key, components = eps, locations = locs;
return function() {
var args = Array.prototype.slice.call(arguments);
var url = [base];
for(var k = 0, n = components.length; k < n; k ++) {
if(isArgument(components[k])) {
url.push(args.shift());
} else {
url.push(components[k]);
}
if(k != n - 1) {
url.push('/');
}
}
var headers = args.shift(), params = args.shift(), body = args.shift();
if(params) {
url.push("?");
for(var param in params) {
//TODO urlencode
url.push(param, "=", params[param], "&");
}
url.pop();
}
print(method + " " + url.join('') + " " + (body ? JSON.stringify(body) : ''));
}
}();
}
}
return proxy;
}
// test
var api = {
"users/{id}/profile/{id}": [GET],
"messages/{id}": [PUT, DELETE]
};
var test = generate("http://api.test.com/", api);
test.getUsersProfile(1, 2);
test.putMessages(2, {}, {}, {test:"test"});
test.deleteMessages(2);
@korenyushkin
Copy link

First of all, do you use Akshell?

Style issues (we should maintain consistency across all new libs):

  • Indentation should be 2 spaces
  • a space should be placed after if and for
  • single quotes are preferred
  • constants like GET shouldn't be used, they just pollute namespaces, 'GET' is OK
  • eps vs. endpoints is unclear
  • each var declaration should be on a separate line
  • ++ shouldn't be separated by a space
  • variables like m and l shouldn't be introduced: V8 will handle this stuff
  • one-line if and else statements shouldn't be surrounded by {} unless the other statement is multiline
  • name should be nameParts or nameBits or something
  • there's no need to create the camelCase and isArgument funcs: they are called only once (btw camelCase should be capitalize)
  • Array.prototype.slice.call is just Array.slice (defined in the base.js file of the ak lib)
  • url should be urlParts
  • encodeURIComponent should be used
  • tricky closure should be moved into a separate func, as a bonus, it'll eliminate the need to duplicate names
  • second call to isArgument is bad, you can place e.g. nulls instead of '{bla}' strings
  • not only JSON bodies should be supported

@olegp
Copy link
Author

olegp commented Apr 14, 2011

  • This was written and tested on RingoJS, since I was on a train with no net and hence couldn't use Akshell
  • Also, we need to standardize our http lib on the commonjs one before it makes too much sense to get this going on Akshell.
  • Variable names are a mess, I know,moving closure out would make sense.
  • We should avoid ak dependencies so this could run on other platforms, so I'm against using base.js unnecessarily.
  • Let's discuss styles - I think this needs some work and there are a few points I disagree on, mostly due to C++/Java influences, but agree that consistency is important.
  • This code isn't final, hence the unnecessary cameCase functions etc. feel free to edit and refactor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment