rest-methods
Version:
Declaratively publish functions for remote invocation.
192 lines (152 loc) • 6.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
var _fs = require("fs");
var _fs2 = _interopRequireDefault(_fs);
var _path = require("path");
var _path2 = _interopRequireDefault(_path);
var _url = require("url");
var _url2 = _interopRequireDefault(_url);
var _lodash = require("lodash");
var _lodash2 = _interopRequireDefault(_lodash);
var _manifest = require("./manifest");
var _manifest2 = _interopRequireDefault(_manifest);
var _pageJs = require("../page-js");
var _pageJs2 = _interopRequireDefault(_pageJs);
var _docs = require("../docs");
var _docs2 = _interopRequireDefault(_docs);
var _const = require("../const");
var _stylus = require("stylus");
var _stylus2 = _interopRequireDefault(_stylus);
var _nib = require("nib");
var _nib2 = _interopRequireDefault(_nib);
var FAVICON = _fs2["default"].readFileSync(_path2["default"].join(__dirname, "../docs/favicon.ico"));
/**
* Determines whether the given URL path matches any of
* the method routes.
* @param server: {Server} instance to examine.
* @param url: {string} The URL path to match.
* @param verb: {string} The HTTP verb to match (GET|PUT|POST|DELETE).
* @return {ServerMethod}
*/
var matchMethodUrl = function matchMethodUrl(server, url, verb) {
verb = verb.toLowerCase();
var context = new _pageJs2["default"].Context(url);
var methods = server[_const.METHODS];
var methodNames = Object.keys(methods);
if (!_lodash2["default"].isEmpty(methodNames)) {
var methodName = _lodash2["default"].find(Object.keys(methods), function (key) {
var methodVerb = methods[key][verb];
var isMatch = methodVerb && methodVerb.pathRoute.match(context.path, context.params);
return isMatch;
});
var method = methods[methodName];
}
return method ? method[verb] : undefined;
};
/**
* The connect middleware for managing API calls to the server.
* @param server: {Server} instance the middleware is handling.
* @return the connect middleware function.
*/
exports.matchMethodUrl = matchMethodUrl;
exports["default"] = function (server) {
// Middleware.
return function (req, res, next) {
var basePath = server.basePath.replace(/\/$/, "");
var url = _url2["default"].parse(req.url, true);
var cache = {};
var send = function send(content, contentType) {
res.setHeader("Content-Type", contentType);
res.end(content);
};
var getFile = function getFile(fileName) {
var path = _path2["default"].join(__dirname, fileName);
if (!cache[path]) {
// NB: Only load from file if not in the cache.
var text = _fs2["default"].readFileSync(path).toString();
cache[path] = { text: text, path: path };
}
return cache[path];
};
var sendJs = function sendJs(fileName) {
var js = getFile("../../.build/" + fileName).text;
send(js, "application/javascript");
};
var sendJson = function sendJson(obj) {
send(JSON.stringify(obj), "application/json");
};
var sendHtml = function sendHtml(html) {
send(html, "text/html");
};
var sendCss = function sendCss(css) {
send(css, "text/css");
};
var sendStylus = function sendStylus(fileName) {
var file = getFile(fileName);
(0, _stylus2["default"])(file.text).set("filename", file.path).include(_nib2["default"].path).render(function (err, css) {
if (err) {
throw err;
}
sendCss(css);
});
};
var sendDocsHtml = function sendDocsHtml() {
var manifest = (0, _manifest2["default"])(server, { docs: true });
var pageProps = {
title: server.name + " (API)",
manifest: manifest,
faviconPath: basePath + "/favicon.ico",
stylePath: basePath + "/style.css",
scriptPath: basePath + "/docs.js",
bodyHtml: _docs2["default"].toHtml(_docs2["default"].Shell, { manifest: manifest })
};
sendHtml(_docs2["default"].pageHtml(pageProps));
};
// Match the route.
switch (url.pathname) {
// GET: An HTML representation of the API (docs).
case basePath:
sendDocsHtml();
break;
case basePath + "/":
sendDocsHtml();
break;
case basePath + "/style.css":
sendStylus("../docs/css/index.styl");
break;
case basePath + "/favicon.ico":
send(FAVICON, "image/x-icon");
break;
// GET: The manifest of methods.
case _const.MANIFEST_PATH:
var withDocs = url.query.docs === "true";
sendJson((0, _manifest2["default"])(server, { docs: withDocs }));
break;
// GET: Serve the client JS.
case basePath + "/browser.js":
sendJs("browser.js");
break;
case basePath + "/docs.js":
sendJs("docs.js");
break;
default:
// Attempt to match the URL for a method.
var methodVerb = matchMethodUrl(server, req.url, req.method);
if (methodVerb) {
// Invoke the method.
methodVerb.invoke(req.body.args, req.url).then(function (result) {
sendJson(result);
})["catch"](function (err) {
res.statusCode = err.status || 500;
res.end(JSON.stringify(err));
});
} else {
// No match - continue to [next] middleware method.
next();
}
}
};
};