1 | ;
|
2 |
|
3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4 |
|
5 | Object.defineProperty(exports, "__esModule", {
|
6 | value: true
|
7 | });
|
8 | exports["default"] = void 0;
|
9 |
|
10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
11 |
|
12 | var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
13 |
|
14 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
15 |
|
16 | var _express = _interopRequireDefault(require("express"));
|
17 |
|
18 | var _http = _interopRequireDefault(require("http"));
|
19 |
|
20 | var _net = _interopRequireDefault(require("net"));
|
21 |
|
22 | var _path = _interopRequireDefault(require("path"));
|
23 |
|
24 | var _socket = _interopRequireDefault(require("socket.io"));
|
25 |
|
26 | var _inputs = _interopRequireDefault(require("./inputs"));
|
27 |
|
28 | // File path to UI app build artifacts (static JS/CSS/HTML)
|
29 | var UI_BUILD_PATH = process.env.LOGIO_SERVER_UI_BUILD_PATH || _path["default"].resolve(__dirname, 'ui');
|
30 | /**
|
31 | * Broadcast an inbound message to socket.io channels
|
32 | */
|
33 |
|
34 |
|
35 | function handleNewMessage(_x, _x2, _x3, _x4) {
|
36 | return _handleNewMessage.apply(this, arguments);
|
37 | }
|
38 | /**
|
39 | * Broadcast a new input coming online to all browsers
|
40 | */
|
41 |
|
42 |
|
43 | function _handleNewMessage() {
|
44 | _handleNewMessage = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(config, inputs, io, msgParts) {
|
45 | var _msgParts$slice, _msgParts$slice2, mtype, stream, source, msg, inputName;
|
46 |
|
47 | return _regenerator["default"].wrap(function _callee$(_context) {
|
48 | while (1) {
|
49 | switch (_context.prev = _context.next) {
|
50 | case 0:
|
51 | _msgParts$slice = msgParts.slice(0, 3), _msgParts$slice2 = (0, _slicedToArray2["default"])(_msgParts$slice, 3), mtype = _msgParts$slice2[0], stream = _msgParts$slice2[1], source = _msgParts$slice2[2];
|
52 | msg = msgParts.slice(3).join('|');
|
53 | inputName = inputs.add(stream, source); // Broadcast message to input channel
|
54 |
|
55 | io.to(inputName).emit(mtype, {
|
56 | inputName: inputName,
|
57 | msg: msg,
|
58 | stream: stream,
|
59 | source: source
|
60 | }); // Broadcast ping to all browsers
|
61 |
|
62 | io.emit('+ping', {
|
63 | inputName: inputName,
|
64 | stream: stream,
|
65 | source: source
|
66 | });
|
67 |
|
68 | if (config.debug) {
|
69 | // eslint-disable-next-line no-console
|
70 | console.log(msgParts.join('|'));
|
71 | }
|
72 |
|
73 | case 6:
|
74 | case "end":
|
75 | return _context.stop();
|
76 | }
|
77 | }
|
78 | }, _callee);
|
79 | }));
|
80 | return _handleNewMessage.apply(this, arguments);
|
81 | }
|
82 |
|
83 | function handleRegisterInput(_x5, _x6, _x7, _x8) {
|
84 | return _handleRegisterInput.apply(this, arguments);
|
85 | }
|
86 | /**
|
87 | * Broadcast an input going offline to all browsers
|
88 | */
|
89 |
|
90 |
|
91 | function _handleRegisterInput() {
|
92 | _handleRegisterInput = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(config, inputs, io, msgParts) {
|
93 | var _msgParts$slice3, _msgParts$slice4, mtype, stream, source, inputName;
|
94 |
|
95 | return _regenerator["default"].wrap(function _callee2$(_context2) {
|
96 | while (1) {
|
97 | switch (_context2.prev = _context2.next) {
|
98 | case 0:
|
99 | _msgParts$slice3 = msgParts.slice(0, 3), _msgParts$slice4 = (0, _slicedToArray2["default"])(_msgParts$slice3, 3), mtype = _msgParts$slice4[0], stream = _msgParts$slice4[1], source = _msgParts$slice4[2];
|
100 | inputName = inputs.add(stream, source);
|
101 | io.emit(mtype, {
|
102 | stream: stream,
|
103 | source: source,
|
104 | inputName: inputName
|
105 | });
|
106 |
|
107 | case 3:
|
108 | case "end":
|
109 | return _context2.stop();
|
110 | }
|
111 | }
|
112 | }, _callee2);
|
113 | }));
|
114 | return _handleRegisterInput.apply(this, arguments);
|
115 | }
|
116 |
|
117 | function handleDeregisterInput(_x9, _x10, _x11, _x12) {
|
118 | return _handleDeregisterInput.apply(this, arguments);
|
119 | } // Maps TCP message prefix to handler function
|
120 |
|
121 |
|
122 | function _handleDeregisterInput() {
|
123 | _handleDeregisterInput = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(config, inputs, io, msgParts) {
|
124 | var _msgParts$slice5, _msgParts$slice6, mtype, stream, source, inputName;
|
125 |
|
126 | return _regenerator["default"].wrap(function _callee3$(_context3) {
|
127 | while (1) {
|
128 | switch (_context3.prev = _context3.next) {
|
129 | case 0:
|
130 | _msgParts$slice5 = msgParts.slice(0, 3), _msgParts$slice6 = (0, _slicedToArray2["default"])(_msgParts$slice5, 3), mtype = _msgParts$slice6[0], stream = _msgParts$slice6[1], source = _msgParts$slice6[2];
|
131 | inputName = inputs.remove(stream, source);
|
132 | io.emit(mtype, {
|
133 | stream: stream,
|
134 | source: source,
|
135 | inputName: inputName
|
136 | });
|
137 |
|
138 | case 3:
|
139 | case "end":
|
140 | return _context3.stop();
|
141 | }
|
142 | }
|
143 | }, _callee3);
|
144 | }));
|
145 | return _handleDeregisterInput.apply(this, arguments);
|
146 | }
|
147 |
|
148 | var messageHandlers = {
|
149 | '+msg': handleNewMessage,
|
150 | '+input': handleRegisterInput,
|
151 | '-input': handleDeregisterInput
|
152 | };
|
153 | /**
|
154 | * Broadcast an inbound message to socket.io channels
|
155 | */
|
156 |
|
157 | function broadcastMessage(_x13, _x14, _x15, _x16) {
|
158 | return _broadcastMessage.apply(this, arguments);
|
159 | }
|
160 | /**
|
161 | * Start message & web servers
|
162 | */
|
163 |
|
164 |
|
165 | function _broadcastMessage() {
|
166 | _broadcastMessage = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(config, inputs, io, data) {
|
167 | var msgs;
|
168 | return _regenerator["default"].wrap(function _callee5$(_context5) {
|
169 | while (1) {
|
170 | switch (_context5.prev = _context5.next) {
|
171 | case 0:
|
172 | // Parse raw message into parts
|
173 | // NOTE: After split on null termination character, last item will always
|
174 | // be either an empty string or a partial/incomplete message
|
175 | msgs = data.toString().split('\0').slice(0, -1).filter(function (msg) {
|
176 | return !!msg.trim();
|
177 | });
|
178 | msgs.forEach( /*#__PURE__*/function () {
|
179 | var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(msg) {
|
180 | var msgParts, messageHandler;
|
181 | return _regenerator["default"].wrap(function _callee4$(_context4) {
|
182 | while (1) {
|
183 | switch (_context4.prev = _context4.next) {
|
184 | case 0:
|
185 | msgParts = msg.split('|');
|
186 | messageHandler = messageHandlers[msgParts[0]];
|
187 |
|
188 | if (!messageHandler) {
|
189 | _context4.next = 7;
|
190 | break;
|
191 | }
|
192 |
|
193 | _context4.next = 5;
|
194 | return messageHandler(config, inputs, io, msgParts);
|
195 |
|
196 | case 5:
|
197 | _context4.next = 8;
|
198 | break;
|
199 |
|
200 | case 7:
|
201 | // eslint-disable-next-line no-console
|
202 | console.error("Unknown message type: ".concat(msgParts[0]));
|
203 |
|
204 | case 8:
|
205 | case "end":
|
206 | return _context4.stop();
|
207 | }
|
208 | }
|
209 | }, _callee4);
|
210 | }));
|
211 |
|
212 | return function (_x18) {
|
213 | return _ref.apply(this, arguments);
|
214 | };
|
215 | }());
|
216 |
|
217 | case 2:
|
218 | case "end":
|
219 | return _context5.stop();
|
220 | }
|
221 | }
|
222 | }, _callee5);
|
223 | }));
|
224 | return _broadcastMessage.apply(this, arguments);
|
225 | }
|
226 |
|
227 | function main(_x17) {
|
228 | return _main.apply(this, arguments);
|
229 | }
|
230 |
|
231 | function _main() {
|
232 | _main = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee9(config) {
|
233 | var server, httpServer, io, inputs, messageServer;
|
234 | return _regenerator["default"].wrap(function _callee9$(_context9) {
|
235 | while (1) {
|
236 | switch (_context9.prev = _context9.next) {
|
237 | case 0:
|
238 | // Create HTTP server w/ static file serving & socket.io bindings
|
239 | server = (0, _express["default"])();
|
240 | server.use('/', _express["default"]["static"](UI_BUILD_PATH));
|
241 | httpServer = new _http["default"].Server(server);
|
242 | io = (0, _socket["default"])(httpServer);
|
243 | inputs = new _inputs["default"](); // Create TCP message server
|
244 |
|
245 | messageServer = _net["default"].createServer( /*#__PURE__*/function () {
|
246 | var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee7(socket) {
|
247 | return _regenerator["default"].wrap(function _callee7$(_context7) {
|
248 | while (1) {
|
249 | switch (_context7.prev = _context7.next) {
|
250 | case 0:
|
251 | socket.on('data', /*#__PURE__*/function () {
|
252 | var _ref3 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(data) {
|
253 | return _regenerator["default"].wrap(function _callee6$(_context6) {
|
254 | while (1) {
|
255 | switch (_context6.prev = _context6.next) {
|
256 | case 0:
|
257 | _context6.next = 2;
|
258 | return broadcastMessage(config, inputs, io, data);
|
259 |
|
260 | case 2:
|
261 | case "end":
|
262 | return _context6.stop();
|
263 | }
|
264 | }
|
265 | }, _callee6);
|
266 | }));
|
267 |
|
268 | return function (_x20) {
|
269 | return _ref3.apply(this, arguments);
|
270 | };
|
271 | }());
|
272 |
|
273 | case 1:
|
274 | case "end":
|
275 | return _context7.stop();
|
276 | }
|
277 | }
|
278 | }, _callee7);
|
279 | }));
|
280 |
|
281 | return function (_x19) {
|
282 | return _ref2.apply(this, arguments);
|
283 | };
|
284 | }()); // When a new browser connects, register stream activation events
|
285 |
|
286 | io.on('connection', /*#__PURE__*/function () {
|
287 | var _ref4 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee8(socket) {
|
288 | return _regenerator["default"].wrap(function _callee8$(_context8) {
|
289 | while (1) {
|
290 | switch (_context8.prev = _context8.next) {
|
291 | case 0:
|
292 | // Send existing inputs to browser
|
293 | inputs.getInputs().forEach(function (input) {
|
294 | socket.emit('+input', input);
|
295 | }); // Register input activation events
|
296 |
|
297 | socket.on('+activate', function (inputName) {
|
298 | socket.join(inputName);
|
299 | });
|
300 | socket.on('-activate', function (inputName) {
|
301 | socket.leave(inputName);
|
302 | });
|
303 |
|
304 | case 3:
|
305 | case "end":
|
306 | return _context8.stop();
|
307 | }
|
308 | }
|
309 | }, _callee8);
|
310 | }));
|
311 |
|
312 | return function (_x21) {
|
313 | return _ref4.apply(this, arguments);
|
314 | };
|
315 | }()); // Start listening for requests
|
316 |
|
317 | messageServer.listen(config.messageServer.port, config.messageServer.host, function () {
|
318 | // eslint-disable-next-line no-console
|
319 | console.log("TCP message server listening on port ".concat(config.messageServer.port));
|
320 | });
|
321 | httpServer.listen(config.httpServer.port, config.httpServer.host, function () {
|
322 | // eslint-disable-next-line no-console
|
323 | console.log("HTTP server listening on port ".concat(config.httpServer.port));
|
324 | });
|
325 |
|
326 | case 9:
|
327 | case "end":
|
328 | return _context9.stop();
|
329 | }
|
330 | }
|
331 | }, _callee9);
|
332 | }));
|
333 | return _main.apply(this, arguments);
|
334 | }
|
335 |
|
336 | var _default = main;
|
337 | exports["default"] = _default;
|
338 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9zZXJ2ZXIudHMiXSwibmFtZXMiOlsiVUlfQlVJTERfUEFUSCIsInByb2Nlc3MiLCJlbnYiLCJMT0dJT19TRVJWRVJfVUlfQlVJTERfUEFUSCIsInBhdGgiLCJyZXNvbHZlIiwiX19kaXJuYW1lIiwiaGFuZGxlTmV3TWVzc2FnZSIsImNvbmZpZyIsImlucHV0cyIsImlvIiwibXNnUGFydHMiLCJzbGljZSIsIm10eXBlIiwic3RyZWFtIiwic291cmNlIiwibXNnIiwiam9pbiIsImlucHV0TmFtZSIsImFkZCIsInRvIiwiZW1pdCIsImRlYnVnIiwiY29uc29sZSIsImxvZyIsImhhbmRsZVJlZ2lzdGVySW5wdXQiLCJoYW5kbGVEZXJlZ2lzdGVySW5wdXQiLCJyZW1vdmUiLCJtZXNzYWdlSGFuZGxlcnMiLCJicm9hZGNhc3RNZXNzYWdlIiwiZGF0YSIsIm1zZ3MiLCJ0b1N0cmluZyIsInNwbGl0IiwiZmlsdGVyIiwidHJpbSIsImZvckVhY2giLCJtZXNzYWdlSGFuZGxlciIsImVycm9yIiwibWFpbiIsInNlcnZlciIsInVzZSIsImV4cHJlc3MiLCJodHRwU2VydmVyIiwiaHR0cCIsIlNlcnZlciIsIklucHV0UmVnaXN0cnkiLCJtZXNzYWdlU2VydmVyIiwibmV0IiwiY3JlYXRlU2VydmVyIiwic29ja2V0Iiwib24iLCJnZXRJbnB1dHMiLCJpbnB1dCIsImxlYXZlIiwibGlzdGVuIiwicG9ydCIsImhvc3QiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUdBO0FBQ0EsSUFBTUEsYUFBYSxHQUFHQyxPQUFPLENBQUNDLEdBQVIsQ0FBWUMsMEJBQVosSUFDakJDLGlCQUFLQyxPQUFMLENBQWFDLFNBQWIsRUFBd0IsSUFBeEIsQ0FETDtBQUdBOzs7OztTQUdlQyxnQjs7O0FBbUJmOzs7Ozs7b0dBbkJBLGlCQUNFQyxNQURGLEVBRUVDLE1BRkYsRUFHRUMsRUFIRixFQUlFQyxRQUpG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LHdCQUFBQSxNQUFNLENBQUNDLEVBQVAsQ0FBVSxXQUFWLEVBQXVCLFVBQUNqQyxTQUFELEVBQWU7QUFDcENnQywwQkFBQUEsTUFBTSxDQUFDSSxLQUFQLENBQWFwQyxTQUFiO0FBQ0QseUJBRkQ7O0FBVGtCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGVBQXBCOztBQUFBO0FBQUE7QUFBQTtBQUFBLGlCQWhCRixDQThCRTs7QUFDQTZCLFlBQUFBLGFBQWEsQ0FBQ1EsTUFBZCxDQUFxQi9DLE1BQU0sQ0FBQ3VDLGFBQVAsQ0FBcUJTLElBQTFDLEVBQWdEaEQsTUFBTSxDQUFDdUMsYUFBUCxDQUFxQlUsSUFBckUsRUFBMkUsWUFBTTtBQUMvRTtBQUNBbEMsY0FBQUEsT0FBTyxDQUFDQyxHQUFSLGdEQUFvRGhCLE1BQU0sQ0FBQ3VDLGFBQVAsQ0FBcUJTLElBQXpFO0FBQ0QsYUFIRDtBQUlBYixZQUFBQSxVQUFVLENBQUNZLE1BQVgsQ0FBa0IvQyxNQUFNLENBQUNtQyxVQUFQLENBQWtCYSxJQUFwQyxFQUEwQ2hELE1BQU0sQ0FBQ21DLFVBQVAsQ0FBa0JjLElBQTVELEVBQWtFLFlBQU07QUFDdEU7QUFDQWxDLGNBQUFBLE9BQU8sQ0FBQ0MsR0FBUix5Q0FBNkNoQixNQUFNLENBQUNtQyxVQUFQLENBQWtCYSxJQUEvRDtBQUNELGFBSEQ7O0FBbkNGO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEc7Ozs7ZUF5Q2VqQixJIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGV4cHJlc3MgZnJvbSAnZXhwcmVzcydcbmltcG9ydCBodHRwIGZyb20gJ2h0dHAnXG5pbXBvcnQgbmV0IGZyb20gJ25ldCdcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnXG5pbXBvcnQgc29ja2V0aW8gZnJvbSAnc29ja2V0LmlvJ1xuaW1wb3J0IElucHV0UmVnaXN0cnkgZnJvbSAnLi9pbnB1dHMnXG5pbXBvcnQgeyBNZXNzYWdlSGFuZGxlcnMsIFNlcnZlckNvbmZpZyB9IGZyb20gJy4vdHlwZXMnXG5cbi8vIEZpbGUgcGF0aCB0byBVSSBhcHAgYnVpbGQgYXJ0aWZhY3RzIChzdGF0aWMgSlMvQ1NTL0hUTUwpXG5jb25zdCBVSV9CVUlMRF9QQVRIID0gcHJvY2Vzcy5lbnYuTE9HSU9fU0VSVkVSX1VJX0JVSUxEX1BBVEhcbiAgfHwgcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJ3VpJylcblxuLyoqXG4gKiBCcm9hZGNhc3QgYW4gaW5ib3VuZCBtZXNzYWdlIHRvIHNvY2tldC5pbyBjaGFubmVsc1xuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVOZXdNZXNzYWdlKFxuICBjb25maWc6IFNlcnZlckNvbmZpZyxcbiAgaW5wdXRzOiBJbnB1dFJlZ2lzdHJ5LFxuICBpbzogU29ja2V0SU8uU2VydmVyLFxuICBtc2dQYXJ0czogQXJyYXk8c3RyaW5nPixcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBbbXR5cGUsIHN0cmVhbSwgc291cmNlXSA9IG1zZ1BhcnRzLnNsaWNlKDAsIDMpXG4gIGNvbnN0IG1zZyA9IG1zZ1BhcnRzLnNsaWNlKDMpLmpvaW4oJ3wnKVxuICBjb25zdCBpbnB1dE5hbWUgPSBpbnB1dHMuYWRkKHN0cmVhbSwgc291cmNlKVxuICAvLyBCcm9hZGNhc3QgbWVzc2FnZSB0byBpbnB1dCBjaGFubmVsXG4gIGlvLnRvKGlucHV0TmFtZSkuZW1pdChtdHlwZSwgeyBpbnB1dE5hbWUsIG1zZywgc3RyZWFtLCBzb3VyY2UgfSlcbiAgLy8gQnJvYWRjYXN0IHBpbmcgdG8gYWxsIGJyb3dzZXJzXG4gIGlvLmVtaXQoJytwaW5nJywgeyBpbnB1dE5hbWUsIHN0cmVhbSwgc291cmNlIH0pXG4gIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnNvbGUubG9nKG1zZ1BhcnRzLmpvaW4oJ3wnKSlcbiAgfVxufVxuXG4vKipcbiAqIEJyb2FkY2FzdCBhIG5ldyBpbnB1dCBjb21pbmcgb25saW5lIHRvIGFsbCBicm93c2Vyc1xuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVSZWdpc3RlcklucHV0KFxuICBjb25maWc6IFNlcnZlckNvbmZpZyxcbiAgaW5wdXRzOiBJbnB1dFJlZ2lzdHJ5LFxuICBpbzogU29ja2V0SU8uU2VydmVyLFxuICBtc2dQYXJ0czogQXJyYXk8c3RyaW5nPixcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBbbXR5cGUsIHN0cmVhbSwgc291cmNlXSA9IG1zZ1BhcnRzLnNsaWNlKDAsIDMpXG4gIGNvbnN0IGlucHV0TmFtZSA9IGlucHV0cy5hZGQoc3RyZWFtLCBzb3VyY2UpXG4gIGlvLmVtaXQobXR5cGUsIHsgc3RyZWFtLCBzb3VyY2UsIGlucHV0TmFtZSB9KVxufVxuXG4vKipcbiAqIEJyb2FkY2FzdCBhbiBpbnB1dCBnb2luZyBvZmZsaW5lIHRvIGFsbCBicm93c2Vyc1xuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVEZXJlZ2lzdGVySW5wdXQoXG4gIGNvbmZpZzogU2VydmVyQ29uZmlnLFxuICBpbnB1dHM6IElucHV0UmVnaXN0cnksXG4gIGlvOiBTb2NrZXRJTy5TZXJ2ZXIsXG4gIG1zZ1BhcnRzOiBBcnJheTxzdHJpbmc+LFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IFttdHlwZSwgc3RyZWFtLCBzb3VyY2VdID0gbXNnUGFydHMuc2xpY2UoMCwgMylcbiAgY29uc3QgaW5wdXROYW1lID0gaW5wdXRzLnJlbW92ZShzdHJlYW0sIHNvdXJjZSlcbiAgaW8uZW1pdChtdHlwZSwgeyBzdHJlYW0sIHNvdXJjZSwgaW5wdXROYW1lIH0pXG59XG5cbi8vIE1hcHMgVENQIG1lc3NhZ2UgcHJlZml4IHRvIGhhbmRsZXIgZnVuY3Rpb25cbmNvbnN0IG1lc3NhZ2VIYW5kbGVyczogTWVzc2FnZUhhbmRsZXJzID0ge1xuICAnK21zZyc6IGhhbmRsZU5ld01lc3NhZ2UsXG4gICcraW5wdXQnOiBoYW5kbGVSZWdpc3RlcklucHV0LFxuICAnLWlucHV0JzogaGFuZGxlRGVyZWdpc3RlcklucHV0LFxufVxuXG4vKipcbiAqIEJyb2FkY2FzdCBhbiBpbmJvdW5kIG1lc3NhZ2UgdG8gc29ja2V0LmlvIGNoYW5uZWxzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGJyb2FkY2FzdE1lc3NhZ2UoXG4gIGNvbmZpZzogU2VydmVyQ29uZmlnLFxuICBpbnB1dHM6IElucHV0UmVnaXN0cnksXG4gIGlvOiBTb2NrZXRJTy5TZXJ2ZXIsXG4gIGRhdGE6IEJ1ZmZlcixcbik6IFByb21pc2U8dm9pZD4ge1xuICAvLyBQYXJzZSByYXcgbWVzc2FnZSBpbnRvIHBhcnRzXG4gIC8vIE5PVEU6IEFmdGVyIHNwbGl0IG9uIG51bGwgdGVybWluYXRpb24gY2hhcmFjdGVyLCBsYXN0IGl0ZW0gd2lsbCBhbHdheXNcbiAgLy8gYmUgZWl0aGVyIGFuIGVtcHR5IHN0cmluZyBvciBhIHBhcnRpYWwvaW5jb21wbGV0ZSBtZXNzYWdlXG4gIGNvbnN0IG1zZ3MgPSBkYXRhLnRvU3RyaW5nKClcbiAgICAuc3BsaXQoJ1xcMCcpXG4gICAgLnNsaWNlKDAsIC0xKVxuICAgIC5maWx0ZXIobXNnID0+ICEhbXNnLnRyaW0oKSlcbiAgbXNncy5mb3JFYWNoKGFzeW5jIChtc2cpID0+IHtcbiAgICBjb25zdCBtc2dQYXJ0cyA9IG1zZy5zcGxpdCgnfCcpXG4gICAgY29uc3QgbWVzc2FnZUhhbmRsZXIgPSBtZXNzYWdlSGFuZGxlcnNbbXNnUGFydHNbMF1dXG4gICAgaWYgKG1lc3NhZ2VIYW5kbGVyKSB7XG4gICAgICBhd2FpdCBtZXNzYWdlSGFuZGxlcihjb25maWcsIGlucHV0cywgaW8sIG1zZ1BhcnRzKVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS5lcnJvcihgVW5rbm93biBtZXNzYWdlIHR5cGU6ICR7bXNnUGFydHNbMF19YClcbiAgICB9XG4gIH0pXG59XG5cbi8qKlxuICogU3RhcnQgbWVzc2FnZSAmIHdlYiBzZXJ2ZXJzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG1haW4oY29uZmlnOiBTZXJ2ZXJDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgLy8gQ3JlYXRlIEhUVFAgc2VydmVyIHcvIHN0YXRpYyBmaWxlIHNlcnZpbmcgJiBzb2NrZXQuaW8gYmluZGluZ3NcbiAgY29uc3Qgc2VydmVyID0gZXhwcmVzcygpXG4gIHNlcnZlci51c2UoJy8nLCBleHByZXNzLnN0YXRpYyhVSV9CVUlMRF9QQVRIKSlcbiAgY29uc3QgaHR0cFNlcnZlciA9IG5ldyBodHRwLlNlcnZlcihzZXJ2ZXIpXG4gIGNvbnN0IGlvID0gc29ja2V0aW8oaHR0cFNlcnZlcilcbiAgY29uc3QgaW5wdXRzID0gbmV3IElucHV0UmVnaXN0cnkoKVxuXG4gIC8vIENyZWF0ZSBUQ1AgbWVzc2FnZSBzZXJ2ZXJcbiAgY29uc3QgbWVzc2FnZVNlcnZlciA9IG5ldC5jcmVhdGVTZXJ2ZXIoYXN5bmMgKHNvY2tldDogbmV0LlNvY2tldCkgPT4ge1xuICAgIHNvY2tldC5vbignZGF0YScsIGFzeW5jIChkYXRhOiBCdWZmZXIpID0+IHtcbiAgICAgIGF3YWl0IGJyb2FkY2FzdE1lc3NhZ2UoY29uZmlnLCBpbnB1dHMsIGlvLCBkYXRhKVxuICAgIH0pXG4gIH0pXG5cbiAgLy8gV2hlbiBhIG5ldyBicm93c2VyIGNvbm5lY3RzLCByZWdpc3RlciBzdHJlYW0gYWN0aXZhdGlvbiBldmVudHNcbiAgaW8ub24oJ2Nvbm5lY3Rpb24nLCBhc3luYyAoc29ja2V0OiBTb2NrZXRJTy5Tb2NrZXQpID0+IHtcbiAgICAvLyBTZW5kIGV4aXN0aW5nIGlucHV0cyB0byBicm93c2VyXG4gICAgaW5wdXRzLmdldElucHV0cygpLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgICBzb2NrZXQuZW1pdCgnK2lucHV0JywgaW5wdXQpXG4gICAgfSlcbiAgICAvLyBSZWdpc3RlciBpbnB1dCBhY3RpdmF0aW9uIGV2ZW50c1xuICAgIHNvY2tldC5vbignK2FjdGl2YXRlJywgKGlucHV0TmFtZSkgPT4ge1xuICAgICAgc29ja2V0LmpvaW4oaW5wdXROYW1lKVxuICAgIH0pXG4gICAgc29ja2V0Lm9uKCctYWN0aXZhdGUnLCAoaW5wdXROYW1lKSA9PiB7XG4gICAgICBzb2NrZXQubGVhdmUoaW5wdXROYW1lKVxuICAgIH0pXG4gIH0pXG5cbiAgLy8gU3RhcnQgbGlzdGVuaW5nIGZvciByZXF1ZXN0c1xuICBtZXNzYWdlU2VydmVyLmxpc3Rlbihjb25maWcubWVzc2FnZVNlcnZlci5wb3J0LCBjb25maWcubWVzc2FnZVNlcnZlci5ob3N0LCAoKSA9PiB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmxvZyhgVENQIG1lc3NhZ2Ugc2VydmVyIGxpc3RlbmluZyBvbiBwb3J0ICR7Y29uZmlnLm1lc3NhZ2VTZXJ2ZXIucG9ydH1gKVxuICB9KVxuICBodHRwU2VydmVyLmxpc3Rlbihjb25maWcuaHR0cFNlcnZlci5wb3J0LCBjb25maWcuaHR0cFNlcnZlci5ob3N0LCAoKSA9PiB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmxvZyhgSFRUUCBzZXJ2ZXIgbGlzdGVuaW5nIG9uIHBvcnQgJHtjb25maWcuaHR0cFNlcnZlci5wb3J0fWApXG4gIH0pXG59XG5cbmV4cG9ydCBkZWZhdWx0IG1haW5cbiJdfQ== |
\ | No newline at end of file |