github
Version:
NodeJS wrapper for the GitHub API
162 lines (134 loc) • 4.53 kB
JavaScript
/** section: github, internal
* class ApiGenerator
*
* Copyright 2012 Cloud9 IDE, Inc.
*
* This product includes software developed by
* Cloud9 IDE, Inc (http://c9.io).
*
* Author: Mike de Boer <mike@c9.io>
**/
;
var fs = require("fs");
var Path = require("path");
var Util = require("./util");
var Mustache = require("mustache");
var typeMap = {
Json: "string",
String: "string",
Number: "number",
Boolean: "boolean",
};
// XXX: maybe a better idea to update routes.json to include array value types.
function replaceArrayTypes(type, name) {
switch (name) {
case "scopes":
case "add_scopes":
case "remove_scopes":
case "parents":
case "assignees":
case "body":
case "repositories":
case "repo_names":
case "events":
case "add_events":
case "remove_events":
case "contexts":
case "required_contexts":
case "maintainers":
case "reviewers":
case "comments":
return "string[]";
default:
return type;
}
}
function paramData(key, definition) {
if (definition === null) {
return {};
}
var typeName = typeMap[definition.type] || definition.type;
var type = replaceArrayTypes(typeName, key);
var enums = definition.enum ?
definition.enum.map(JSON.stringify).join("|")
: null;
return {
name: pascalcase(key),
key: key,
required: definition.required,
type: enums ? enums : type,
};
}
function capitalize(string) {
return string.charAt(0).toUpperCase().concat(string.slice(1));
}
function camelcase(string) {
return string.replace(/(?:-|_)([a-z])/g, function (_, character) {
return capitalize(character);
});
}
function pascalcase(string) {
return capitalize(camelcase(string));
}
function isGlobalParam(name) {
return name.charAt(0) === "$";
}
function isLocalParam(name) {
return !isGlobalParam(name);
}
function entries(object) {
return Object.keys(object).map(function (key) {
return [key, object[key]];
});
}
function combineParamData(params, entry) {
return params.concat(paramData.apply(null, entry));
}
var main = module.exports = function(languageName, templateFile, outputFile) {
var templatePath = Path.join(__dirname, "..", "templates", templateFile);
var template = fs.readFileSync(templatePath, "utf8");
// check routes path
var routesPath = Path.join(__dirname, "routes.json");
var routes = JSON.parse(fs.readFileSync(routesPath, "utf8"));
if (!routes.defines) {
Util.log("No routes defined.", "fatal");
process.exit(1);
}
var defines = routes.defines;
var requestHeaders = defines["request-headers"];
delete routes.defines;
Util.log("Generating " + languageName + " types...");
var params = entries(defines.params).reduce(combineParamData, []);
var namespaces = Object.keys(routes).reduce(function (namespaces, namespace) {
var methods = entries(routes[namespace]).reduce(function (methods, entry) {
var unionTypeNames = Object.keys(entry[1].params)
.filter(isGlobalParam)
.reduce(function (params, name) {
return params.concat(pascalcase(name.slice(1)));
}, []);
var ownParams = entries(entry[1].params)
.filter(function (entry) { return isLocalParam(entry[0]); })
.reduce(combineParamData, []);
var hasParams = unionTypeNames.length > 0 || ownParams.length > 0;
var paramTypeName = pascalcase(namespace + "-" + entry[0] + "Params");
return methods.concat({
method: camelcase(entry[0]),
paramTypeName: hasParams && paramTypeName,
unionTypeNames: unionTypeNames.length > 0 && unionTypeNames,
ownParams: ownParams.length > 0 && { params: ownParams },
});
}, []);
return namespaces.concat({
namespace: camelcase(namespace),
methods: methods,
});
}, []);
var body = Mustache.render(template, {
requestHeaders: requestHeaders.map(JSON.stringify),
params: params,
namespaces: namespaces,
});
Util.log("Writing " + languageName + " declarations file");
fs.writeFileSync(Path.join(__dirname, outputFile), body, "utf8");
};