rest-methods
Version:
Declaratively publish functions for remote invocation.
176 lines (140 loc) • 5.77 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _lodash = require("lodash");
var _lodash2 = _interopRequireDefault(_lodash);
var _bluebird = require("bluebird");
var _bluebird2 = _interopRequireDefault(_bluebird);
var _errors = require("../errors");
var _pageJs = require("../page-js");
var _pageJs2 = _interopRequireDefault(_pageJs);
var _url = require("../url");
var parseError = function parseError(err) {
// Convert the [HttpError] into a [ServerMethodError].
try {
var _JSON$parse = JSON.parse(err.message);
var status = _JSON$parse.status;
var method = _JSON$parse.method;
var args = _JSON$parse.args;
var message = _JSON$parse.message;
} catch (e) {
// The server did not return JSON details about the method error.
message = err.message;
}
return new _errors.ServerMethodError(status, method, args, message);
};
/**
* Represents a proxy to a single method on the server.
*/
var ClientMethod = (function () {
/**
* Constructor.
* @param name: The unique name of the method.
* @param http: The HTTP object to use for making requests.
* @param options:
* - host: The host-name of the remote server.
* - url: The method"s URL path/route-pattern.
* - get: Definition of the GET function, eg. { params:["text", "number"] }
* - put: ..
* - post: ..
* - delete: ..
*/
function ClientMethod(name, http) {
var _this = this;
var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
_classCallCheck(this, ClientMethod);
if (!http) {
throw new Error("An [http] gateway was not given to the [ClientMethod].");
}
// Prepare the URL.
var url = options.url;
if (!url) {
// If a URL was not specified use the method name.
url = "/" + name.replace(/^\/*/, "");
}
// Store values.
this.name = name;
this.verbs = {};
this.urlPattern = url;
this.route = new _pageJs2["default"].Route(this.urlPattern);
this.http = http;
this.host = options.host;
// Store individual invoker methods for each HTTP verb.
["get", "put", "post", "delete"].forEach(function (verb) {
if (options[verb]) {
_this.verbs[verb] = options[verb];
}
});
}
/**
* The URL to the method"s resource.
* @param args: Optional. An array of arguments.
*/
_createClass(ClientMethod, [{
key: "url",
value: function url() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return (0, _url.getMethodUrl)(this.name, this.host, this.route, args);
}
/**
* Invokes the method on the server.
* @param verb: The HTTP verb (GET | PUT | POST | DELETE)
* @param args: An array of arguments.
* @return promise.
*/
}, {
key: "invoke",
value: function invoke() {
var _this2 = this;
for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
var verb = arguments.length <= 0 || arguments[0] === undefined ? "GET" : arguments[0];
// Setup initial conditions.
verb = verb.toUpperCase();
args = _lodash2["default"].flatten(args);
args = _lodash2["default"].compact(args);
return new _bluebird2["default"](function (resolve, reject) {
// Prepare the URL.
var url = _this2.url(args);
var urlParamsTotal = _this2.route.keys.length;
if (urlParamsTotal > 0) {
// The URL contained parameters that were taken from the args.
// Remove them from the set of arguments passed in the payload.
args = _lodash2["default"].clone(args);
args = args.splice(urlParamsTotal, args.length);
}
if ((verb === "GET" || verb === "DELETE") && args.length > 0) {
var msg = "Cannot send arguments to the \"" + _this2.name + "\", REST does not allow you to submit data to a " + verb + " method. Instead use the PUT or POST verbs.";
if (urlParamsTotal > 0) {
msg += " This method\"s URL does, however, take parameters (" + _this2.urlPattern + ").";
}
throw new Error(msg);
}
// Setup the payload to send.
var payload = {
verb: verb,
method: _this2.name,
args: args
};
// Send to the server.
var httpMethod = _this2.http[verb.toLowerCase()];
httpMethod(url, payload).then(function (result) {
resolve(result);
})["catch"](function (err) {
err = parseError(err);
reject(err);
});
});
}
}]);
return ClientMethod;
})();
exports["default"] = ClientMethod;
module.exports = exports["default"];