1 | ;
|
2 |
|
3 | var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
|
4 |
|
5 | var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
|
6 |
|
7 | var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
|
8 |
|
9 | var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
|
10 |
|
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
12 |
|
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
14 |
|
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
|
16 |
|
17 | var _createClass3 = _interopRequireDefault(_createClass2);
|
18 |
|
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
20 |
|
21 | var ExecInfo = require('./ExecInfo');
|
22 | var Promise = require('bluebird');
|
23 | var _ = require('lodash');
|
24 |
|
25 | var _require = require('./utils');
|
26 |
|
27 | var execHook = _require.execHook;
|
28 | var logError = _require.logError;
|
29 | var possiblyCallback = _require.possiblyCallback;
|
30 | var resultsTransform = _require.resultsTransform;
|
31 |
|
32 | // Implements command implementation functions binding and wrapping.
|
33 |
|
34 | var CommandBinder = function () {
|
35 | function CommandBinder(server, transport, userName) {
|
36 | (0, _classCallCheck3.default)(this, CommandBinder);
|
37 |
|
38 | this.server = server;
|
39 | this.transport = transport;
|
40 | this.userName = userName;
|
41 | }
|
42 |
|
43 | (0, _createClass3.default)(CommandBinder, [{
|
44 | key: 'commandWatcher',
|
45 | value: function commandWatcher(id, name) {
|
46 | var _this = this;
|
47 |
|
48 | this.server.runningCommands++;
|
49 | return Promise.resolve().disposer(function () {
|
50 | _this.server.runningCommands--;
|
51 | if (_this.transport.closed && _this.server.runningCommands <= 0) {
|
52 | _this.server.emit('commandsFinished');
|
53 | }
|
54 | });
|
55 | }
|
56 | }, {
|
57 | key: 'makeCommand',
|
58 | value: function makeCommand(name, fn) {
|
59 | var _this2 = this;
|
60 |
|
61 | var validator = this.server.validator;
|
62 |
|
63 | var beforeHook = this.server.hooks[name + 'Before'];
|
64 | var afterHook = this.server.hooks[name + 'After'];
|
65 | return function (args, info) {
|
66 | var execInfo = new ExecInfo();
|
67 | _.assign(execInfo, { server: _this2.server, userName: _this2.userName });
|
68 | _.assign(execInfo, info);
|
69 | _.assign(execInfo, validator.splitArguments(name, args));
|
70 | return Promise.using(_this2.commandWatcher(info.id, name), function () {
|
71 | return validator.checkArguments.apply(validator, [name].concat((0, _toConsumableArray3.default)(execInfo.args))).then(function () {
|
72 | if (beforeHook && !execInfo.bypassHooks) {
|
73 | return execHook(beforeHook, execInfo);
|
74 | } else {
|
75 | return Promise.resolve();
|
76 | }
|
77 | }).then(function (results) {
|
78 | if (results && results.length) {
|
79 | return results;
|
80 | }
|
81 | return fn.apply(undefined, (0, _toConsumableArray3.default)(execInfo.args).concat([execInfo])).then(function (result) {
|
82 | execInfo.results = [result];
|
83 | }, function (error) {
|
84 | execInfo.error = error;
|
85 | }).then(function () {
|
86 | if (afterHook && !execInfo.bypassHooks) {
|
87 | return execHook(afterHook, execInfo);
|
88 | } else {
|
89 | return Promise.resolve();
|
90 | }
|
91 | }).then(function (results) {
|
92 | if (results && results.length) {
|
93 | return results;
|
94 | } else if (execInfo.error) {
|
95 | return Promise.reject(execInfo.error);
|
96 | } else {
|
97 | return execInfo.results;
|
98 | }
|
99 | });
|
100 | });
|
101 | }).catch(function (error) {
|
102 | return logError(error);
|
103 | });
|
104 | };
|
105 | }
|
106 | }, {
|
107 | key: 'bindDisconnect',
|
108 | value: function bindDisconnect(id, fn) {
|
109 | var _this3 = this;
|
110 |
|
111 | var server = this.server;
|
112 | var hook = this.server.hooks.onDisconnect;
|
113 | this.transport.bindHandler(id, 'disconnect', function () {
|
114 | return Promise.using(_this3.commandWatcher(id, 'disconnect'), function () {
|
115 | return fn(id).then(function () {
|
116 | return execHook(hook, server, id);
|
117 | }).catchReturn();
|
118 | });
|
119 | });
|
120 | }
|
121 | }, {
|
122 | key: 'bindCommand',
|
123 | value: function bindCommand(id, name, fn) {
|
124 | var cmd = this.makeCommand(name, fn);
|
125 | var useErrorObjects = this.server.useRawErrorObjects;
|
126 | var info = { id: id };
|
127 | return this.transport.bindHandler(id, name, function () {
|
128 | var _possiblyCallback = possiblyCallback(arguments);
|
129 |
|
130 | var _possiblyCallback2 = (0, _slicedToArray3.default)(_possiblyCallback, 2);
|
131 |
|
132 | var args = _possiblyCallback2[0];
|
133 | var cb = _possiblyCallback2[1];
|
134 |
|
135 | var ack = resultsTransform(useErrorObjects, cb);
|
136 | return cmd(args, info).asCallback(ack, { spread: true });
|
137 | });
|
138 | }
|
139 | }]);
|
140 | return CommandBinder;
|
141 | }();
|
142 |
|
143 | module.exports = CommandBinder;
|
144 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Db21tYW5kQmluZGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLElBQU0sV0FBVyxRQUFRLFlBQVIsQ0FBakI7QUFDQSxJQUFNLFVBQVUsUUFBUSxVQUFSLENBQWhCO0FBQ0EsSUFBTSxJQUFJLFFBQVEsUUFBUixDQUFWOztlQUVRLFFBQVEsU0FBUixDOztJQURBLFEsWUFBQSxRO0lBQVUsUSxZQUFBLFE7SUFBVSxnQixZQUFBLGdCO0lBQWtCLGdCLFlBQUEsZ0I7O0FBRzlDOztJQUNNLGE7QUFFSix5QkFBYSxNQUFiLEVBQXFCLFNBQXJCLEVBQWdDLFFBQWhDLEVBQTBDO0FBQUE7O0FBQ3hDLFNBQUssTUFBTCxHQUFjLE1BQWQ7QUFDQSxTQUFLLFNBQUwsR0FBaUIsU0FBakI7QUFDQSxTQUFLLFFBQUwsR0FBZ0IsUUFBaEI7QUFDRDs7OzttQ0FFZSxFLEVBQUksSSxFQUFNO0FBQUE7O0FBQ3hCLFdBQUssTUFBTCxDQUFZLGVBQVo7QUFDQSxhQUFPLFFBQVEsT0FBUixHQUFrQixRQUFsQixDQUEyQixZQUFNO0FBQ3RDLGNBQUssTUFBTCxDQUFZLGVBQVo7QUFDQSxZQUFJLE1BQUssU0FBTCxDQUFlLE1BQWYsSUFBeUIsTUFBSyxNQUFMLENBQVksZUFBWixJQUErQixDQUE1RCxFQUErRDtBQUM3RCxnQkFBSyxNQUFMLENBQVksSUFBWixDQUFpQixrQkFBakI7QUFDRDtBQUNGLE9BTE0sQ0FBUDtBQU1EOzs7Z0NBRVksSSxFQUFNLEUsRUFBSTtBQUFBOztBQUFBLFVBQ2YsU0FEZSxHQUNELEtBQUssTUFESixDQUNmLFNBRGU7O0FBRXJCLFVBQUksYUFBYSxLQUFLLE1BQUwsQ0FBWSxLQUFaLENBQXFCLElBQXJCLFlBQWpCO0FBQ0EsVUFBSSxZQUFZLEtBQUssTUFBTCxDQUFZLEtBQVosQ0FBcUIsSUFBckIsV0FBaEI7QUFDQSxhQUFPLFVBQUMsSUFBRCxFQUFPLElBQVAsRUFBZ0I7QUFD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LGlCQUFpQixTQUFqQixDQURxQzs7QUFBQTs7QUFBQSxZQUNqRCxJQURpRDtBQUFBLFlBQzNDLEVBRDJDOztBQUV0RCxZQUFJLE1BQU0saUJBQWlCLGVBQWpCLEVBQWtDLEVBQWxDLENBQVY7QUFDQSxlQUFPLElBQUksSUFBSixFQUFVLElBQVYsRUFBZ0IsVUFBaEIsQ0FBMkIsR0FBM0IsRUFBZ0MsRUFBRSxRQUFRLElBQVYsRUFBaEMsQ0FBUDtBQUNELE9BSk0sQ0FBUDtBQUtEOzs7OztBQUlILE9BQU8sT0FBUCxHQUFpQixhQUFqQiIsImZpbGUiOiJDb21tYW5kQmluZGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnXG5cbmNvbnN0IEV4ZWNJbmZvID0gcmVxdWlyZSgnLi9FeGVjSW5mbycpXG5jb25zdCBQcm9taXNlID0gcmVxdWlyZSgnYmx1ZWJpcmQnKVxuY29uc3QgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpXG5jb25zdCB7IGV4ZWNIb29rLCBsb2dFcnJvciwgcG9zc2libHlDYWxsYmFjaywgcmVzdWx0c1RyYW5zZm9ybSB9ID1cbiAgICAgICAgcmVxdWlyZSgnLi91dGlscycpXG5cbi8vIEltcGxlbWVudHMgY29tbWFuZCBpbXBsZW1lbnRhdGlvbiBmdW5jdGlvbnMgYmluZGluZyBhbmQgd3JhcHBpbmcuXG5jbGFzcyBDb21tYW5kQmluZGVyIHtcblxuICBjb25zdHJ1Y3RvciAoc2VydmVyLCB0cmFuc3BvcnQsIHVzZXJOYW1lKSB7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXJcbiAgICB0aGlzLnRyYW5zcG9ydCA9IHRyYW5zcG9ydFxuICAgIHRoaXMudXNlck5hbWUgPSB1c2VyTmFtZVxuICB9XG5cbiAgY29tbWFuZFdhdGNoZXIgKGlkLCBuYW1lKSB7XG4gICAgdGhpcy5zZXJ2ZXIucnVubmluZ0NvbW1hbmRzKytcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkuZGlzcG9zZXIoKCkgPT4ge1xuICAgICAgdGhpcy5zZXJ2ZXIucnVubmluZ0NvbW1hbmRzLS1cbiAgICAgIGlmICh0aGlzLnRyYW5zcG9ydC5jbG9zZWQgJiYgdGhpcy5zZXJ2ZXIucnVubmluZ0NvbW1hbmRzIDw9IDApIHtcbiAgICAgICAgdGhpcy5zZXJ2ZXIuZW1pdCgnY29tbWFuZHNGaW5pc2hlZCcpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIG1ha2VDb21tYW5kIChuYW1lLCBmbikge1xuICAgIGxldCB7IHZhbGlkYXRvciB9ID0gdGhpcy5zZXJ2ZXJcbiAgICBsZXQgYmVmb3JlSG9vayA9IHRoaXMuc2VydmVyLmhvb2tzW2Ake25hbWV9QmVmb3JlYF1cbiAgICBsZXQgYWZ0ZXJIb29rID0gdGhpcy5zZXJ2ZXIuaG9va3NbYCR7bmFtZX1BZnRlcmBdXG4gICAgcmV0dXJuIChhcmdzLCBpbmZvKSA9PiB7XG4gICAgICBsZXQgZXhlY0luZm8gPSBuZXcgRXhlY0luZm8oKVxuICAgICAgXy5hc3NpZ24oZXhlY0luZm8sIHsgc2VydmVyOiB0aGlzLnNlcnZlciwgdXNlck5hbWU6IHRoaXMudXNlck5hbWUgfSlcbiAgICAgIF8uYXNzaWduKGV4ZWNJbmZvLCBpbmZvKVxuICAgICAgXy5hc3NpZ24oZXhlY0luZm8sIHZhbGlkYXRvci5zcGxpdEFyZ3VtZW50cyhuYW1lLCBhcmdzKSlcbiAgICAgIHJldHVybiBQcm9taXNlLnVzaW5nKFxuICAgICAgICB0aGlzLmNvbW1hbmRXYXRjaGVyKGluZm8uaWQsIG5hbWUpLFxuICAgICAgICAoKSA9PiB2YWxpZGF0b3IuY2hlY2tBcmd1bWVudHMobmFtZSwgLi4uZXhlY0luZm8uYXJncylcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBpZiAoYmVmb3JlSG9vayAmJiAhZXhlY0luZm8uYnlwYXNzSG9va3MpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGV4ZWNIb29rKGJlZm9yZUhvb2ssIGV4ZWNJbmZvKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICB9IH0pXG4gICAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgICBpZiAocmVzdWx0cyAmJiByZXN1bHRzLmxlbmd0aCkgeyByZXR1cm4gcmVzdWx0cyB9XG4gICAgICAgICAgICByZXR1cm4gZm4oLi4uZXhlY0luZm8uYXJncywgZXhlY0luZm8pXG4gICAgICAgICAgICAgIC50aGVuKHJlc3VsdCA9PiB7IGV4ZWNJbmZvLnJlc3VsdHMgPSBbcmVzdWx0XSB9LFxuICAgICAgICAgICAgICAgICAgICBlcnJvciA9PiB7IGV4ZWNJbmZvLmVycm9yID0gZXJyb3IgfSlcbiAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChhZnRlckhvb2sgJiYgIWV4ZWNJbmZvLmJ5cGFzc0hvb2tzKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gZXhlY0hvb2soYWZ0ZXJIb29rLCBleGVjSW5mbylcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICAgICAgfSB9KVxuICAgICAgICAgICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0cyAmJiByZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdHNcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGV4ZWNJbmZvLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXhlY0luZm8uZXJyb3IpXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBleGVjSW5mby5yZXN1bHRzXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgIH0pKVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4gbG9nRXJyb3IoZXJyb3IpKVxuICAgIH1cbiAgfVxuXG4gIGJpbmREaXNjb25uZWN0IChpZCwgZm4pIHtcbiAgICBsZXQgc2VydmVyID0gdGhpcy5zZXJ2ZXJcbiAgICBsZXQgaG9vayA9IHRoaXMuc2VydmVyLmhvb2tzLm9uRGlzY29ubmVjdFxuICAgIHRoaXMudHJhbnNwb3J0LmJpbmRIYW5kbGVyKGlkLCAnZGlzY29ubmVjdCcsICgpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnVzaW5nKFxuICAgICAgICB0aGlzLmNvbW1hbmRXYXRjaGVyKGlkLCAnZGlzY29ubmVjdCcpLFxuICAgICAgICAoKSA9PiBmbihpZCkudGhlbigoKSA9PiBleGVjSG9vayhob29rLCBzZXJ2ZXIsIGlkKSkuY2F0Y2hSZXR1cm4oKSlcbiAgICB9KVxuICB9XG5cbiAgYmluZENvbW1hbmQgKGlkLCBuYW1lLCBmbikge1xuICAgIGxldCBjbWQgPSB0aGlzLm1ha2VDb21tYW5kKG5hbWUsIGZuKVxuICAgIGxldCB1c2VFcnJvck9iamVjdHMgPSB0aGlzLnNlcnZlci51c2VSYXdFcnJvck9iamVjdHNcbiAgICBsZXQgaW5mbyA9IHtpZH1cbiAgICByZXR1cm4gdGhpcy50cmFuc3BvcnQuYmluZEhhbmRsZXIoaWQsIG5hbWUsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBbYXJncywgY2JdID0gcG9zc2libHlDYWxsYmFjayhhcmd1bWVudHMpXG4gICAgICBsZXQgYWNrID0gcmVzdWx0c1RyYW5zZm9ybSh1c2VFcnJvck9iamVjdHMsIGNiKVxuICAgICAgcmV0dXJuIGNtZChhcmdzLCBpbmZvKS5hc0NhbGxiYWNrKGFjaywgeyBzcHJlYWQ6IHRydWUgfSlcbiAgICB9KVxuICB9XG5cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBDb21tYW5kQmluZGVyXG4iXX0= |
\ | No newline at end of file |