@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.
@@ -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,2 @@
1
+ export * from './module.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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";
@@ -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"}