UNPKG

rest-methods

Version:

Declaratively publish functions for remote invocation.

249 lines (205 loc) 8.16 kB
"use strict"; 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 _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj["default"] = obj; return newObj; } } 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 _ClientMethod = require("./ClientMethod"); var _ClientMethod2 = _interopRequireDefault(_ClientMethod); var _jsUtil = require("js-util"); var util = _interopRequireWildcard(_jsUtil); var _httpPromisesBrowser = require("http-promises/browser"); var _httpPromisesBrowser2 = _interopRequireDefault(_httpPromisesBrowser); var _const = require("../const"); var STATE = Symbol("state"); exports.STATE = STATE; var isBrowser = typeof window !== "undefined" && window !== null; /** * Initalizes the proxy with the server methods. * @param {Client} client: The Client proxy to the server. * @param {object} methodsManifest: An object containing the method definitions from the server. * NB: The the [methods] object form the manifest. */ var registerMethods = function registerMethods(client) { var methodsManifest = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var _client$STATE = client[STATE]; var host = _client$STATE.host; var http = _client$STATE.http; // Store methods. _lodash2["default"].keys(methodsManifest).forEach(function (key) { var options = methodsManifest[key]; options.host = host; var method = new _ClientMethod2["default"](key, http, options); client[STATE].methods[key] = method; // Create proxy-stubs to the method. var stub = util.ns(client.methods, key, { delimiter: "/" }); _lodash2["default"].keys(method.verbs).forEach(function (verb) { stub[verb] = function () { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return method.invoke(verb, args); }; }); }); // Invoke ready handlers. client.isReady = true; client[STATE].readyHandlers.invoke(); client[STATE].readyHandlers = new _jsUtil.Handlers(); // Reset. }; exports.registerMethods = registerMethods; /** * The client proxy to server methods. */ var Client = (function () { /** * Constructor. * Initializes the module client-side, pulling the * manifest of methods from the server. * @param options * - http: The HTTP object to use for making requests. * - host: The host-name of the remote server, * For example: * - http://domain.com * - localhost:3030 */ function Client() { var _this = this; var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; _classCallCheck(this, Client); // Private field: HTTP. var http = options.http; if (isBrowser && !http) { http = _httpPromisesBrowser2["default"]; } if (!http) { throw new Error("An [http] gateway was not given to the [Client]."); } // Private field: Host. var host = options.host; if (!isBrowser && !host) { throw new Error("A [host] name must be given when connecting a server to a remove server (eg. https://domain.com, or localhost:3030) "); } if (host) { if (!_lodash2["default"].startsWith(host, "http")) { host = "http://" + host; } host = host.replace(/\/*$/, ""); } // Private field: State. this[STATE] = { methods: {}, readyHandlers: new _jsUtil.Handlers(), http: http, host: host }; /** * Flag indicating the ready state of the client. * Is true after `init` has retrieved methods from the server. */ this.isReady = false; /** * An object containing proxy"s to server methods. * This object is populated after initialization completes. */ this.methods = {}; // Connect to the server. var url = _const.MANIFEST_PATH; if (!isBrowser && host) { url = "" + host + url; } http.get(url).then(function (result) { registerMethods(_this, result.methods); })["catch"](function (err) { throw err; }); } // ---------------------------------------------------------------------------- /** * Registers a callback to be invoked when the server-proxy is ready. * @param func: The callback function. */ _createClass(Client, [{ key: "onReady", value: function onReady(func) { if (this.isReady) { // Already initialized - invoke callback immediately. if (_lodash2["default"].isFunction(func)) { func(); } } else { // Store callback to invoke later. this[STATE].readyHandlers.push(func); } return this; } /** * Invokes the specified method taking an array of parameters. * * @param verb: The HTTP verb (GET/PUT/POST/DELETE). * @param methodName: The name/key of the method to invoke. * @param args: Optional. The arguments to pass to the method. * * @return promise. */ }, { key: "invoke", value: function invoke(verb, methodName) { var args = arguments.length <= 2 || arguments[2] === undefined ? [] : arguments[2]; // Setup initial conditions. if (!_lodash2["default"].isArray(args)) { args = [args]; } if (!this.isReady) { throw new Error("Initializion must be complete before invoking methods. See \"isReady\" flag."); } // Invoke the method. var method = this[STATE].methods[methodName]; if (!method || !method.verbs[verb.toLowerCase()]) { throw new Error("Failed to invoke. A " + verb + " method \"" + methodName + "\" does not exist."); } return method.invoke(verb, args); } // HTTP verb specific invoker methods. }, { key: "get", value: function get(methodName) { for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } return this.invoke("GET", methodName, args); } }, { key: "put", value: function put(methodName) { for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { args[_key3 - 1] = arguments[_key3]; } return this.invoke("PUT", methodName, args); } }, { key: "post", value: function post(methodName) { for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { args[_key4 - 1] = arguments[_key4]; } return this.invoke("POST", methodName, args); } }, { key: "delete", value: function _delete(methodName) { for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { args[_key5 - 1] = arguments[_key5]; } return this.invoke("DELETE", methodName, args); } }]); return Client; })(); exports["default"] = function (options) { return new Client(options); };