@difizen/libro-terminal 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/es/configuration.js +226 -0
- package/es/connection.d.ts +108 -0
- package/es/connection.d.ts.map +1 -0
- package/es/connection.js +385 -0
- package/es/index.d.ts +2 -0
- package/es/index.d.ts.map +1 -0
- package/es/index.js +1 -0
- package/es/manager.d.ts +104 -0
- package/es/manager.d.ts.map +1 -0
- package/es/manager.js +469 -0
- package/es/module.d.ts +3 -0
- package/es/module.d.ts.map +1 -0
- package/es/module.js +22 -0
- package/es/protocol.d.ts +87 -0
- package/es/protocol.d.ts.map +1 -0
- package/es/protocol.js +16 -0
- package/es/restapi.d.ts +11 -0
- package/es/restapi.d.ts.map +1 -0
- package/es/restapi.js +181 -0
- package/es/theme-service.js +183 -0
- package/es/view.d.ts +85 -0
- package/es/view.d.ts.map +1 -0
- package/es/view.js +317 -0
- package/package.json +63 -0
- package/src/configuration.ts +276 -0
- package/src/connection.ts +347 -0
- package/src/index.spec.ts +8 -0
- package/src/index.ts +1 -0
- package/src/manager.ts +280 -0
- package/src/module.ts +29 -0
- package/src/protocol.ts +102 -0
- package/src/restapi.ts +75 -0
- package/src/theme-service.ts +180 -0
- package/src/view.tsx +327 -0
package/es/connection.js
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
var _dec, _dec2, _class, _class2, _descriptor;
|
|
3
|
+
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
4
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
5
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
6
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
7
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
8
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
9
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
10
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
11
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
12
|
+
function _initializerDefineProperty(target, property, descriptor, context) { if (!descriptor) return; Object.defineProperty(target, property, { enumerable: descriptor.enumerable, configurable: descriptor.configurable, writable: descriptor.writable, value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); }
|
|
13
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
14
|
+
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, _toPropertyKey(descriptor.key), descriptor); } }
|
|
15
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
16
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
|
17
|
+
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
18
|
+
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; }
|
|
19
|
+
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'transform-class-properties is enabled and runs after the decorators transform.'); }
|
|
20
|
+
import { URL } from '@difizen/libro-common';
|
|
21
|
+
import { transient } from '@difizen/mana-app';
|
|
22
|
+
import { Deferred } from '@difizen/mana-app';
|
|
23
|
+
import { Emitter } from '@difizen/mana-app';
|
|
24
|
+
import { inject } from '@difizen/mana-app';
|
|
25
|
+
import { TerminalOption } from "./protocol.js";
|
|
26
|
+
import { TerminalRestAPI } from "./restapi.js";
|
|
27
|
+
export var TerminalConnection = (_dec = transient(), _dec2 = inject(TerminalRestAPI), _dec(_class = (_class2 = /*#__PURE__*/function () {
|
|
28
|
+
/**
|
|
29
|
+
* Construct a new terminal session.
|
|
30
|
+
*/
|
|
31
|
+
function TerminalConnection(options) {
|
|
32
|
+
var _this = this;
|
|
33
|
+
_classCallCheck(this, TerminalConnection);
|
|
34
|
+
this._onDisposed = new Emitter();
|
|
35
|
+
this._messageReceived = new Emitter();
|
|
36
|
+
this._connectionStatus = 'connecting';
|
|
37
|
+
this._connectionStatusChanged = new Emitter();
|
|
38
|
+
this._reconnectTimeout = undefined;
|
|
39
|
+
this._ws = undefined;
|
|
40
|
+
this._noOp = function () {
|
|
41
|
+
/* no-op */
|
|
42
|
+
};
|
|
43
|
+
this._reconnectLimit = 7;
|
|
44
|
+
this._reconnectAttempt = 0;
|
|
45
|
+
this._pendingMessages = [];
|
|
46
|
+
_initializerDefineProperty(this, "terminalRestAPI", _descriptor, this);
|
|
47
|
+
this.disposed = false;
|
|
48
|
+
/**
|
|
49
|
+
* Create the terminal websocket connection and add socket status handlers.
|
|
50
|
+
*
|
|
51
|
+
* #### Notes
|
|
52
|
+
* You are responsible for updating the connection status as appropriate.
|
|
53
|
+
*/
|
|
54
|
+
this._createSocket = function () {
|
|
55
|
+
_this._errorIfDisposed();
|
|
56
|
+
|
|
57
|
+
// Make sure the socket is clear
|
|
58
|
+
_this._clearSocket();
|
|
59
|
+
|
|
60
|
+
// Update the connection status to reflect opening a new connection.
|
|
61
|
+
_this._updateConnectionStatus('connecting');
|
|
62
|
+
var name = _this._name;
|
|
63
|
+
var settings = _this.serverSettings;
|
|
64
|
+
var url = URL.join(settings.wsUrl, 'terminals', 'websocket', encodeURIComponent(name));
|
|
65
|
+
|
|
66
|
+
// If token authentication is in use.
|
|
67
|
+
var token = settings.token;
|
|
68
|
+
if (settings.appendToken && token !== '') {
|
|
69
|
+
url = url + "?token=".concat(encodeURIComponent(token));
|
|
70
|
+
}
|
|
71
|
+
_this._ws = new settings.WebSocket(url);
|
|
72
|
+
_this._ws.onmessage = _this._onWSMessage;
|
|
73
|
+
_this._ws.onclose = _this._onWSClose;
|
|
74
|
+
_this._ws.onerror = _this._onWSClose;
|
|
75
|
+
};
|
|
76
|
+
// Websocket messages events are defined as variables to bind `this`
|
|
77
|
+
this._onWSMessage = function (event) {
|
|
78
|
+
if (_this.disposed) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
var data = JSON.parse(event.data);
|
|
82
|
+
|
|
83
|
+
// Handle a disconnect message.
|
|
84
|
+
if (data[0] === 'disconnect') {
|
|
85
|
+
_this.dispose();
|
|
86
|
+
}
|
|
87
|
+
if (_this._connectionStatus === 'connecting') {
|
|
88
|
+
if (data[0] === 'setup') {
|
|
89
|
+
_this._updateConnectionStatus('connected');
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
_this._messageReceived.fire({
|
|
94
|
+
type: data[0],
|
|
95
|
+
content: data.slice(1)
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
this._onWSClose = function (event) {
|
|
99
|
+
console.warn("Terminal websocket closed: ".concat(event.code));
|
|
100
|
+
if (!_this.disposed) {
|
|
101
|
+
_this._reconnect();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
this._name = options.name;
|
|
105
|
+
this._createSocket();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* A signal emitted when a message is received from the server.
|
|
110
|
+
*/
|
|
111
|
+
TerminalConnection = inject(TerminalOption)(TerminalConnection, undefined, 0) || TerminalConnection;
|
|
112
|
+
_createClass(TerminalConnection, [{
|
|
113
|
+
key: "messageReceived",
|
|
114
|
+
get: function get() {
|
|
115
|
+
return this._messageReceived.event;
|
|
116
|
+
}
|
|
117
|
+
}, {
|
|
118
|
+
key: "onDisposed",
|
|
119
|
+
get: function get() {
|
|
120
|
+
return this._onDisposed.event;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get the name of the terminal session.
|
|
125
|
+
*/
|
|
126
|
+
}, {
|
|
127
|
+
key: "name",
|
|
128
|
+
get: function get() {
|
|
129
|
+
return this._name;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get the model for the terminal session.
|
|
134
|
+
*/
|
|
135
|
+
}, {
|
|
136
|
+
key: "model",
|
|
137
|
+
get: function get() {
|
|
138
|
+
return {
|
|
139
|
+
name: this._name
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The server settings for the session.
|
|
145
|
+
*/
|
|
146
|
+
}, {
|
|
147
|
+
key: "dispose",
|
|
148
|
+
value:
|
|
149
|
+
/**
|
|
150
|
+
* Dispose of the resources held by the session.
|
|
151
|
+
*/
|
|
152
|
+
function dispose() {
|
|
153
|
+
if (this.disposed) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.disposed = true;
|
|
157
|
+
this._updateConnectionStatus('disconnected');
|
|
158
|
+
this._clearSocket();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Send a message to the terminal session.
|
|
163
|
+
*
|
|
164
|
+
* #### Notes
|
|
165
|
+
* If the connection is down, the message will be queued for sending when
|
|
166
|
+
* the connection comes back up.
|
|
167
|
+
*/
|
|
168
|
+
}, {
|
|
169
|
+
key: "send",
|
|
170
|
+
value: function send(message) {
|
|
171
|
+
this._sendMessage(message);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Send a message on the websocket, or possibly queue for later sending.
|
|
176
|
+
*
|
|
177
|
+
* @param queue - whether to queue the message if it cannot be sent
|
|
178
|
+
*/
|
|
179
|
+
}, {
|
|
180
|
+
key: "_sendMessage",
|
|
181
|
+
value: function _sendMessage(message) {
|
|
182
|
+
var queue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
183
|
+
if (this.disposed || !message.content) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (this.connectionStatus === 'connected' && this._ws) {
|
|
187
|
+
var msg = [message.type].concat(_toConsumableArray(message.content));
|
|
188
|
+
this._ws.send(JSON.stringify(msg));
|
|
189
|
+
} else if (queue) {
|
|
190
|
+
this._pendingMessages.push(message);
|
|
191
|
+
} else {
|
|
192
|
+
throw new Error("Could not send message: ".concat(JSON.stringify(message)));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Send pending messages to the kernel.
|
|
198
|
+
*/
|
|
199
|
+
}, {
|
|
200
|
+
key: "_sendPending",
|
|
201
|
+
value: function _sendPending() {
|
|
202
|
+
// We check to make sure we are still connected each time. For
|
|
203
|
+
// example, if a websocket buffer overflows, it may close, so we should
|
|
204
|
+
// stop sending messages.
|
|
205
|
+
while (this.connectionStatus === 'connected' && this._pendingMessages.length > 0) {
|
|
206
|
+
this._sendMessage(this._pendingMessages[0], false);
|
|
207
|
+
|
|
208
|
+
// We shift the message off the queue after the message is sent so that
|
|
209
|
+
// if there is an exception, the message is still pending.
|
|
210
|
+
this._pendingMessages.shift();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}, {
|
|
214
|
+
key: "reconnect",
|
|
215
|
+
value:
|
|
216
|
+
/**
|
|
217
|
+
* Reconnect to a terminal.
|
|
218
|
+
*/
|
|
219
|
+
function reconnect() {
|
|
220
|
+
var _this2 = this;
|
|
221
|
+
this._errorIfDisposed();
|
|
222
|
+
var result = new Deferred();
|
|
223
|
+
|
|
224
|
+
// Set up a listener for the connection status changing, which accepts or
|
|
225
|
+
// rejects after the retries are done.
|
|
226
|
+
var fulfill = function fulfill(status) {
|
|
227
|
+
if (status === 'connected') {
|
|
228
|
+
var _this2$toDisposeOnRec;
|
|
229
|
+
result.resolve();
|
|
230
|
+
(_this2$toDisposeOnRec = _this2.toDisposeOnReconnect) === null || _this2$toDisposeOnRec === void 0 || _this2$toDisposeOnRec.dispose();
|
|
231
|
+
} else if (status === 'disconnected') {
|
|
232
|
+
var _this2$toDisposeOnRec2;
|
|
233
|
+
result.reject(new Error('Terminal connection disconnected'));
|
|
234
|
+
(_this2$toDisposeOnRec2 = _this2.toDisposeOnReconnect) === null || _this2$toDisposeOnRec2 === void 0 || _this2$toDisposeOnRec2.dispose();
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
this.toDisposeOnReconnect = this.connectionStatusChanged(fulfill);
|
|
238
|
+
|
|
239
|
+
// Reset the reconnect limit so we start the connection attempts fresh
|
|
240
|
+
this._reconnectAttempt = 0;
|
|
241
|
+
|
|
242
|
+
// Start the reconnection process, which will also clear any existing
|
|
243
|
+
// connection.
|
|
244
|
+
this._reconnect();
|
|
245
|
+
|
|
246
|
+
// Return the promise that should resolve on connection or reject if the
|
|
247
|
+
// retries don't work.
|
|
248
|
+
return result.promise;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Attempt a connection if we have not exhausted connection attempts.
|
|
253
|
+
*/
|
|
254
|
+
}, {
|
|
255
|
+
key: "_reconnect",
|
|
256
|
+
value: function _reconnect() {
|
|
257
|
+
this._errorIfDisposed();
|
|
258
|
+
|
|
259
|
+
// Clear any existing reconnection attempt
|
|
260
|
+
clearTimeout(this._reconnectTimeout);
|
|
261
|
+
|
|
262
|
+
// Update the connection status and schedule a possible reconnection.
|
|
263
|
+
if (this._reconnectAttempt < this._reconnectLimit) {
|
|
264
|
+
this._updateConnectionStatus('connecting');
|
|
265
|
+
|
|
266
|
+
// The first reconnect attempt should happen immediately, and subsequent
|
|
267
|
+
// attempts should pick a random number in a growing range so that we
|
|
268
|
+
// don't overload the server with synchronized reconnection attempts
|
|
269
|
+
// across multiple kernels.
|
|
270
|
+
var timeout = getRandomIntInclusive(0, 1e3 * (Math.pow(2, this._reconnectAttempt) - 1));
|
|
271
|
+
console.error("Connection lost, reconnecting in ".concat(Math.floor(timeout / 1000), " seconds."));
|
|
272
|
+
this._reconnectTimeout = setTimeout(this._createSocket, timeout);
|
|
273
|
+
this._reconnectAttempt += 1;
|
|
274
|
+
} else {
|
|
275
|
+
this._updateConnectionStatus('disconnected');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Clear the websocket event handlers and the socket itself.
|
|
279
|
+
this._clearSocket();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Forcefully clear the socket state.
|
|
284
|
+
*
|
|
285
|
+
* #### Notes
|
|
286
|
+
* This will clear all socket state without calling any handlers and will
|
|
287
|
+
* not update the connection status. If you call this method, you are
|
|
288
|
+
* responsible for updating the connection status as needed and recreating
|
|
289
|
+
* the socket if you plan to reconnect.
|
|
290
|
+
*/
|
|
291
|
+
}, {
|
|
292
|
+
key: "_clearSocket",
|
|
293
|
+
value: function _clearSocket() {
|
|
294
|
+
if (this._ws) {
|
|
295
|
+
// Clear the websocket event handlers and the socket itself.
|
|
296
|
+
this._ws.onopen = this._noOp;
|
|
297
|
+
this._ws.onclose = this._noOp;
|
|
298
|
+
this._ws.onerror = this._noOp;
|
|
299
|
+
this._ws.onmessage = this._noOp;
|
|
300
|
+
this._ws.close();
|
|
301
|
+
this._ws = undefined;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Shut down the terminal session.
|
|
307
|
+
*/
|
|
308
|
+
}, {
|
|
309
|
+
key: "shutdown",
|
|
310
|
+
value: function () {
|
|
311
|
+
var _shutdown = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
312
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
313
|
+
while (1) switch (_context.prev = _context.next) {
|
|
314
|
+
case 0:
|
|
315
|
+
_context.next = 2;
|
|
316
|
+
return this.terminalRestAPI.shutdown(this.name, this.serverSettings);
|
|
317
|
+
case 2:
|
|
318
|
+
this.dispose();
|
|
319
|
+
case 3:
|
|
320
|
+
case "end":
|
|
321
|
+
return _context.stop();
|
|
322
|
+
}
|
|
323
|
+
}, _callee, this);
|
|
324
|
+
}));
|
|
325
|
+
function shutdown() {
|
|
326
|
+
return _shutdown.apply(this, arguments);
|
|
327
|
+
}
|
|
328
|
+
return shutdown;
|
|
329
|
+
}()
|
|
330
|
+
}, {
|
|
331
|
+
key: "_updateConnectionStatus",
|
|
332
|
+
value:
|
|
333
|
+
/**
|
|
334
|
+
* Handle connection status changes.
|
|
335
|
+
*/
|
|
336
|
+
function _updateConnectionStatus(connectionStatus) {
|
|
337
|
+
if (this._connectionStatus === connectionStatus) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
this._connectionStatus = connectionStatus;
|
|
341
|
+
|
|
342
|
+
// If we are not 'connecting', stop any reconnection attempts.
|
|
343
|
+
if (connectionStatus !== 'connecting') {
|
|
344
|
+
this._reconnectAttempt = 0;
|
|
345
|
+
clearTimeout(this._reconnectTimeout);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Send the pending messages if we just connected.
|
|
349
|
+
if (connectionStatus === 'connected') {
|
|
350
|
+
this._sendPending();
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Notify others that the connection status changed.
|
|
354
|
+
this._connectionStatusChanged.fire(connectionStatus);
|
|
355
|
+
}
|
|
356
|
+
}, {
|
|
357
|
+
key: "_errorIfDisposed",
|
|
358
|
+
value: function _errorIfDisposed() {
|
|
359
|
+
if (this.disposed) {
|
|
360
|
+
throw new Error('Terminal connection is disposed');
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}, {
|
|
364
|
+
key: "connectionStatusChanged",
|
|
365
|
+
get: function get() {
|
|
366
|
+
return this._connectionStatusChanged.event;
|
|
367
|
+
}
|
|
368
|
+
}, {
|
|
369
|
+
key: "connectionStatus",
|
|
370
|
+
get: function get() {
|
|
371
|
+
return this._connectionStatus;
|
|
372
|
+
}
|
|
373
|
+
}]);
|
|
374
|
+
return TerminalConnection;
|
|
375
|
+
}(), (_descriptor = _applyDecoratedDescriptor(_class2.prototype, "terminalRestAPI", [_dec2], {
|
|
376
|
+
configurable: true,
|
|
377
|
+
enumerable: true,
|
|
378
|
+
writable: true,
|
|
379
|
+
initializer: null
|
|
380
|
+
})), _class2)) || _class);
|
|
381
|
+
export function getRandomIntInclusive(min, max) {
|
|
382
|
+
min = Math.ceil(min);
|
|
383
|
+
max = Math.floor(max);
|
|
384
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
385
|
+
}
|
package/es/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
package/es/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./module.js";
|
package/es/manager.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Poll } from '@difizen/libro-common';
|
|
2
|
+
import type { ISettings } from '@difizen/libro-kernel';
|
|
3
|
+
import type { Disposable, Disposed, Event } from '@difizen/mana-app';
|
|
4
|
+
import { Emitter } from '@difizen/mana-app';
|
|
5
|
+
import type { TerminalConnection } from './connection.js';
|
|
6
|
+
import type { TerminalModel, TerminalOption } from './protocol.js';
|
|
7
|
+
import { TerminalConnectionFactory } from './protocol.js';
|
|
8
|
+
import { TerminalRestAPI } from './restapi.js';
|
|
9
|
+
export declare class TerminalManager implements Disposable, Disposed {
|
|
10
|
+
disposed: boolean;
|
|
11
|
+
protected _isReady: boolean;
|
|
12
|
+
protected _pollModels: Poll;
|
|
13
|
+
protected _terminalConnections: Set<TerminalConnection>;
|
|
14
|
+
protected _ready: Promise<void>;
|
|
15
|
+
protected _runningChanged: Emitter<TerminalModel[]>;
|
|
16
|
+
protected _connectionFailure: Emitter<Error>;
|
|
17
|
+
protected _names: string[];
|
|
18
|
+
protected get _models(): TerminalModel[];
|
|
19
|
+
terminalRestAPI: TerminalRestAPI;
|
|
20
|
+
terminalConnectionFactory: TerminalConnectionFactory;
|
|
21
|
+
/**
|
|
22
|
+
* Construct a new terminal manager.
|
|
23
|
+
*/
|
|
24
|
+
constructor();
|
|
25
|
+
/**
|
|
26
|
+
* The server settings of the manager.
|
|
27
|
+
*/
|
|
28
|
+
readonly serverSettings: ISettings;
|
|
29
|
+
/**
|
|
30
|
+
* Test whether the manager is ready.
|
|
31
|
+
*/
|
|
32
|
+
get isReady(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* A promise that fulfills when the manager is ready.
|
|
35
|
+
*/
|
|
36
|
+
get ready(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* A signal emitted when the running terminals change.
|
|
39
|
+
*/
|
|
40
|
+
get runningChanged(): Event<TerminalModel[]>;
|
|
41
|
+
/**
|
|
42
|
+
* A signal emitted when there is a connection failure.
|
|
43
|
+
*/
|
|
44
|
+
get connectionFailure(): Event<Error>;
|
|
45
|
+
/**
|
|
46
|
+
* Dispose of the resources used by the manager.
|
|
47
|
+
*/
|
|
48
|
+
dispose(): void;
|
|
49
|
+
connectTo(options: {
|
|
50
|
+
name: string;
|
|
51
|
+
}): TerminalConnection;
|
|
52
|
+
/**
|
|
53
|
+
* Create an iterator over the most recent running terminals.
|
|
54
|
+
*
|
|
55
|
+
* @returns A new iterator over the running terminals.
|
|
56
|
+
*/
|
|
57
|
+
running(): IterableIterator<TerminalModel>;
|
|
58
|
+
/**
|
|
59
|
+
* Force a refresh of the running terminals.
|
|
60
|
+
*
|
|
61
|
+
* @returns A promise that with the list of running terminals.
|
|
62
|
+
*
|
|
63
|
+
* #### Notes
|
|
64
|
+
* This is intended to be called only in response to a user action,
|
|
65
|
+
* since the manager maintains its internal state.
|
|
66
|
+
*/
|
|
67
|
+
refreshRunning(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Create a new terminal session.
|
|
70
|
+
*
|
|
71
|
+
* @param options - The options used to create the terminal.
|
|
72
|
+
*
|
|
73
|
+
* @returns A promise that resolves with the terminal connection instance.
|
|
74
|
+
*
|
|
75
|
+
* #### Notes
|
|
76
|
+
* The manager `serverSettings` will be used unless overridden in the
|
|
77
|
+
* options.
|
|
78
|
+
*/
|
|
79
|
+
startNew(options: TerminalOption): Promise<TerminalConnection>;
|
|
80
|
+
/**
|
|
81
|
+
* Shut down a terminal session by name.
|
|
82
|
+
*/
|
|
83
|
+
shutdown(name: string): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Shut down all terminal sessions.
|
|
86
|
+
*
|
|
87
|
+
* @returns A promise that resolves when all of the sessions are shut down.
|
|
88
|
+
*/
|
|
89
|
+
shutdownAll(): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Execute a request to the server to poll running terminals and update state.
|
|
92
|
+
*/
|
|
93
|
+
protected requestRunning(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Handle a session starting.
|
|
96
|
+
*/
|
|
97
|
+
protected _onStarted(terminalConnection: TerminalConnection): void;
|
|
98
|
+
/**
|
|
99
|
+
* Handle a session terminating.
|
|
100
|
+
*/
|
|
101
|
+
protected _onDisposed(terminalConnection: TerminalConnection): void;
|
|
102
|
+
getOrCreate: (options: TerminalOption) => Promise<TerminalConnection>;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,EAAE,OAAO,EAAU,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,qBACa,eAAgB,YAAW,UAAU,EAAE,QAAQ;IAC1D,QAAQ,UAAS;IACjB,SAAS,CAAC,QAAQ,UAAS;IAC3B,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC;IAC5B,SAAS,CAAC,oBAAoB,0BAAiC;IAC/D,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,SAAS,CAAC,eAAe,2BAAkC;IAC3D,SAAS,CAAC,kBAAkB,iBAAwB;IAEpD,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,CAAM;IAChC,SAAS,KAAK,OAAO,IAAI,aAAa,EAAE,CAIvC;IAEwB,eAAe,EAAE,eAAe,CAAC;IAE1D,yBAAyB,EAAE,yBAAyB,CAAC;IACrD;;OAEG;;IAuBH;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC;IAEnC;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC,CAE3C;IAED;;OAEG;IACH,IAAI,iBAAiB,IAAI,KAAK,CAAC,KAAK,CAAC,CAEpC;IAED;;OAEG;IACH,OAAO,IAAI,IAAI;IAoBf,SAAS,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,kBAAkB;IAaxD;;;;OAIG;IACH,OAAO,IAAI,gBAAgB,CAAC,aAAa,CAAC;IAI1C;;;;;;;;OAQG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrC;;;;;;;;;;OAUG;IACG,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAMpE;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3C;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAelC;;OAEG;cACa,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAqC/C;;OAEG;IACH,SAAS,CAAC,UAAU,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,IAAI;IAOlE;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,IAAI;IAQnE,WAAW,YAAmB,cAAc,iCAoB1C;CACH"}
|