nikcli-remote 1.0.8 → 1.0.10

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/dist/index.cjs CHANGED
@@ -83,1887 +83,1532 @@ var init_types = __esm({
83
83
  }
84
84
  });
85
85
 
86
- // node_modules/node-pty/lib/utils.js
87
- var require_utils = __commonJS({
88
- "node_modules/node-pty/lib/utils.js"(exports2) {
89
- "use strict";
90
- Object.defineProperty(exports2, "__esModule", { value: true });
91
- exports2.loadNativeModule = exports2.assign = void 0;
92
- function assign(target) {
93
- var sources = [];
94
- for (var _i = 1; _i < arguments.length; _i++) {
95
- sources[_i - 1] = arguments[_i];
96
- }
97
- sources.forEach(function(source) {
98
- return Object.keys(source).forEach(function(key) {
99
- return target[key] = source[key];
100
- });
101
- });
102
- return target;
103
- }
104
- exports2.assign = assign;
105
- function loadNativeModule(name) {
106
- var dirs = ["build/Release", "build/Debug", "prebuilds/" + process.platform + "-" + process.arch];
107
- var relative = ["..", "."];
108
- var lastError;
109
- for (var _i = 0, dirs_1 = dirs; _i < dirs_1.length; _i++) {
110
- var d = dirs_1[_i];
111
- for (var _a = 0, relative_1 = relative; _a < relative_1.length; _a++) {
112
- var r = relative_1[_a];
113
- var dir = r + "/" + d + "/";
114
- try {
115
- return { dir, module: require(dir + "/" + name + ".node") };
116
- } catch (e) {
117
- lastError = e;
118
- }
119
- }
86
+ // src/web-client.ts
87
+ var web_client_exports = {};
88
+ __export(web_client_exports, {
89
+ getWebClient: () => getWebClient
90
+ });
91
+ function getWebClient() {
92
+ return `<!DOCTYPE html>
93
+ <html lang="en">
94
+ <head>
95
+ <meta charset="UTF-8">
96
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
97
+ <meta name="apple-mobile-web-app-capable" content="yes">
98
+ <meta name="mobile-web-app-capable" content="yes">
99
+ <meta name="theme-color" content="#0d1117">
100
+ <title>NikCLI Remote</title>
101
+ <style>
102
+ :root {
103
+ --bg: #0d1117;
104
+ --bg-secondary: #161b22;
105
+ --fg: #e6edf3;
106
+ --fg-muted: #8b949e;
107
+ --accent: #58a6ff;
108
+ --success: #3fb950;
109
+ --warning: #d29922;
110
+ --error: #f85149;
111
+ --border: #30363d;
112
+ --font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;
113
+ }
114
+
115
+ * {
116
+ box-sizing: border-box;
117
+ margin: 0;
118
+ padding: 0;
119
+ -webkit-tap-highlight-color: transparent;
120
+ }
121
+
122
+ html, body {
123
+ height: 100%;
124
+ background: var(--bg);
125
+ color: var(--fg);
126
+ font-family: var(--font-mono);
127
+ font-size: 14px;
128
+ overflow: hidden;
129
+ touch-action: manipulation;
130
+ }
131
+
132
+ #app {
133
+ display: flex;
134
+ flex-direction: column;
135
+ height: 100%;
136
+ height: 100dvh;
137
+ }
138
+
139
+ /* Header */
140
+ #header {
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: space-between;
144
+ padding: 12px 16px;
145
+ background: var(--bg-secondary);
146
+ border-bottom: 1px solid var(--border);
147
+ flex-shrink: 0;
148
+ }
149
+
150
+ #header h1 {
151
+ font-size: 16px;
152
+ font-weight: 600;
153
+ color: var(--accent);
154
+ display: flex;
155
+ align-items: center;
156
+ gap: 8px;
157
+ }
158
+
159
+ #header h1::before {
160
+ content: '';
161
+ width: 10px;
162
+ height: 10px;
163
+ background: var(--accent);
164
+ border-radius: 2px;
165
+ }
166
+
167
+ #status {
168
+ display: flex;
169
+ align-items: center;
170
+ gap: 6px;
171
+ font-size: 12px;
172
+ color: var(--fg-muted);
173
+ }
174
+
175
+ #status-dot {
176
+ width: 8px;
177
+ height: 8px;
178
+ border-radius: 50%;
179
+ background: var(--error);
180
+ transition: background 0.3s;
181
+ }
182
+
183
+ #status-dot.connected {
184
+ background: var(--success);
185
+ }
186
+
187
+ #status-dot.connecting {
188
+ background: var(--warning);
189
+ animation: pulse 1s infinite;
190
+ }
191
+
192
+ @keyframes pulse {
193
+ 0%, 100% { opacity: 1; }
194
+ 50% { opacity: 0.5; }
195
+ }
196
+
197
+ /* Terminal */
198
+ #terminal-container {
199
+ flex: 1;
200
+ overflow: hidden;
201
+ position: relative;
202
+ }
203
+
204
+ #terminal {
205
+ height: 100%;
206
+ padding: 12px;
207
+ overflow-y: auto;
208
+ overflow-x: hidden;
209
+ font-size: 13px;
210
+ line-height: 1.5;
211
+ white-space: pre-wrap;
212
+ word-break: break-all;
213
+ -webkit-overflow-scrolling: touch;
214
+ }
215
+
216
+ #terminal::-webkit-scrollbar {
217
+ width: 6px;
218
+ }
219
+
220
+ #terminal::-webkit-scrollbar-track {
221
+ background: var(--bg);
222
+ }
223
+
224
+ #terminal::-webkit-scrollbar-thumb {
225
+ background: var(--border);
226
+ border-radius: 3px;
227
+ }
228
+
229
+ .cursor {
230
+ display: inline-block;
231
+ width: 8px;
232
+ height: 16px;
233
+ background: var(--fg);
234
+ animation: blink 1s step-end infinite;
235
+ vertical-align: text-bottom;
236
+ }
237
+
238
+ @keyframes blink {
239
+ 50% { opacity: 0; }
240
+ }
241
+
242
+ /* Notifications */
243
+ #notifications {
244
+ position: fixed;
245
+ top: 60px;
246
+ left: 12px;
247
+ right: 12px;
248
+ z-index: 1000;
249
+ pointer-events: none;
250
+ }
251
+
252
+ .notification {
253
+ background: var(--bg-secondary);
254
+ border: 1px solid var(--border);
255
+ border-radius: 8px;
256
+ padding: 12px 16px;
257
+ margin-bottom: 8px;
258
+ animation: slideIn 0.3s ease;
259
+ pointer-events: auto;
260
+ box-shadow: 0 4px 12px rgba(0,0,0,0.4);
261
+ }
262
+
263
+ .notification.success { border-left: 3px solid var(--success); }
264
+ .notification.error { border-left: 3px solid var(--error); }
265
+ .notification.warning { border-left: 3px solid var(--warning); }
266
+ .notification.info { border-left: 3px solid var(--accent); }
267
+
268
+ .notification h4 {
269
+ font-size: 14px;
270
+ font-weight: 600;
271
+ margin-bottom: 4px;
272
+ }
273
+
274
+ .notification p {
275
+ font-size: 12px;
276
+ color: var(--fg-muted);
277
+ }
278
+
279
+ @keyframes slideIn {
280
+ from { transform: translateY(-20px); opacity: 0; }
281
+ to { transform: translateY(0); opacity: 1; }
282
+ }
283
+
284
+ /* Quick Keys */
285
+ #quickkeys {
286
+ display: grid;
287
+ grid-template-columns: repeat(6, 1fr);
288
+ gap: 6px;
289
+ padding: 8px 12px;
290
+ background: var(--bg-secondary);
291
+ border-top: 1px solid var(--border);
292
+ flex-shrink: 0;
293
+ }
294
+
295
+ .qkey {
296
+ background: var(--bg);
297
+ border: 1px solid var(--border);
298
+ border-radius: 6px;
299
+ padding: 10px 4px;
300
+ color: var(--fg);
301
+ font-size: 11px;
302
+ font-family: var(--font-mono);
303
+ text-align: center;
304
+ cursor: pointer;
305
+ user-select: none;
306
+ transition: background 0.1s, transform 0.1s;
307
+ }
308
+
309
+ .qkey:active {
310
+ background: var(--border);
311
+ transform: scale(0.95);
312
+ }
313
+
314
+ .qkey.wide {
315
+ grid-column: span 2;
316
+ }
317
+
318
+ .qkey.accent {
319
+ background: var(--accent);
320
+ border-color: var(--accent);
321
+ color: #fff;
322
+ }
323
+
324
+ /* Input */
325
+ #input-container {
326
+ padding: 12px;
327
+ background: var(--bg-secondary);
328
+ border-top: 1px solid var(--border);
329
+ flex-shrink: 0;
330
+ }
331
+
332
+ #input-row {
333
+ display: flex;
334
+ gap: 8px;
335
+ }
336
+
337
+ #input {
338
+ flex: 1;
339
+ background: var(--bg);
340
+ border: 1px solid var(--border);
341
+ border-radius: 8px;
342
+ padding: 12px 14px;
343
+ color: var(--fg);
344
+ font-family: var(--font-mono);
345
+ font-size: 16px;
346
+ outline: none;
347
+ transition: border-color 0.2s;
348
+ }
349
+
350
+ #input:focus {
351
+ border-color: var(--accent);
352
+ }
353
+
354
+ #input::placeholder {
355
+ color: var(--fg-muted);
356
+ }
357
+
358
+ #send {
359
+ background: var(--accent);
360
+ color: #fff;
361
+ border: none;
362
+ border-radius: 8px;
363
+ padding: 12px 20px;
364
+ font-size: 14px;
365
+ font-weight: 600;
366
+ font-family: var(--font-mono);
367
+ cursor: pointer;
368
+ transition: opacity 0.2s, transform 0.1s;
369
+ }
370
+
371
+ #send:active {
372
+ opacity: 0.8;
373
+ transform: scale(0.98);
374
+ }
375
+
376
+ /* Auth Screen */
377
+ #auth-screen {
378
+ position: fixed;
379
+ inset: 0;
380
+ background: var(--bg);
381
+ display: flex;
382
+ flex-direction: column;
383
+ align-items: center;
384
+ justify-content: center;
385
+ gap: 20px;
386
+ z-index: 2000;
387
+ }
388
+
389
+ #auth-screen.hidden {
390
+ display: none;
391
+ }
392
+
393
+ .spinner {
394
+ width: 40px;
395
+ height: 40px;
396
+ border: 3px solid var(--border);
397
+ border-top-color: var(--accent);
398
+ border-radius: 50%;
399
+ animation: spin 1s linear infinite;
400
+ }
401
+
402
+ @keyframes spin {
403
+ to { transform: rotate(360deg); }
404
+ }
405
+
406
+ #auth-screen p {
407
+ color: var(--fg-muted);
408
+ font-size: 14px;
409
+ }
410
+
411
+ #auth-screen .error {
412
+ color: var(--error);
413
+ }
414
+
415
+ /* Safe area padding for notched devices */
416
+ @supports (padding: env(safe-area-inset-bottom)) {
417
+ #input-container {
418
+ padding-bottom: calc(12px + env(safe-area-inset-bottom));
120
419
  }
121
- throw new Error("Failed to load native module: " + name + ".node, checked: " + dirs.join(", ") + ": " + lastError);
122
420
  }
123
- exports2.loadNativeModule = loadNativeModule;
124
- }
125
- });
126
421
 
127
- // node_modules/node-pty/lib/eventEmitter2.js
128
- var require_eventEmitter2 = __commonJS({
129
- "node_modules/node-pty/lib/eventEmitter2.js"(exports2) {
130
- "use strict";
131
- Object.defineProperty(exports2, "__esModule", { value: true });
132
- exports2.EventEmitter2 = void 0;
133
- var EventEmitter22 = (
134
- /** @class */
135
- (function() {
136
- function EventEmitter23() {
137
- this._listeners = [];
138
- }
139
- Object.defineProperty(EventEmitter23.prototype, "event", {
140
- get: function() {
141
- var _this = this;
142
- if (!this._event) {
143
- this._event = function(listener) {
144
- _this._listeners.push(listener);
145
- var disposable = {
146
- dispose: function() {
147
- for (var i = 0; i < _this._listeners.length; i++) {
148
- if (_this._listeners[i] === listener) {
149
- _this._listeners.splice(i, 1);
150
- return;
151
- }
152
- }
153
- }
154
- };
155
- return disposable;
156
- };
157
- }
158
- return this._event;
159
- },
160
- enumerable: false,
161
- configurable: true
162
- });
163
- EventEmitter23.prototype.fire = function(data) {
164
- var queue = [];
165
- for (var i = 0; i < this._listeners.length; i++) {
166
- queue.push(this._listeners[i]);
167
- }
168
- for (var i = 0; i < queue.length; i++) {
169
- queue[i].call(void 0, data);
422
+ /* Landscape adjustments */
423
+ @media (max-height: 500px) {
424
+ #quickkeys {
425
+ grid-template-columns: repeat(12, 1fr);
426
+ padding: 6px 8px;
427
+ }
428
+ .qkey {
429
+ padding: 8px 2px;
430
+ font-size: 10px;
431
+ }
432
+ #terminal {
433
+ font-size: 12px;
434
+ }
435
+ }
436
+ </style>
437
+ </head>
438
+ <body>
439
+ <div id="app">
440
+ <div id="auth-screen">
441
+ <div class="spinner"></div>
442
+ <p id="auth-status">Connecting to NikCLI...</p>
443
+ </div>
444
+
445
+ <header id="header">
446
+ <h1>NikCLI Remote</h1>
447
+ <div id="status">
448
+ <span id="status-dot" class="connecting"></span>
449
+ <span id="status-text">Connecting</span>
450
+ </div>
451
+ </header>
452
+
453
+ <div id="terminal-container">
454
+ <div id="terminal"></div>
455
+ </div>
456
+
457
+ <div id="notifications"></div>
458
+
459
+ <div id="quickkeys">
460
+ <button class="qkey" data-key="\\t">Tab</button>
461
+ <button class="qkey" data-key="\\x1b[A">\u2191</button>
462
+ <button class="qkey" data-key="\\x1b[B">\u2193</button>
463
+ <button class="qkey" data-key="\\x1b[D">\u2190</button>
464
+ <button class="qkey" data-key="\\x1b[C">\u2192</button>
465
+ <button class="qkey" data-key="\\x1b">Esc</button>
466
+ <button class="qkey" data-key="\\x03">^C</button>
467
+ <button class="qkey" data-key="\\x04">^D</button>
468
+ <button class="qkey" data-key="\\x1a">^Z</button>
469
+ <button class="qkey" data-key="\\x0c">^L</button>
470
+ <button class="qkey wide accent" data-key="\\r">Enter \u23CE</button>
471
+ </div>
472
+
473
+ <div id="input-container">
474
+ <div id="input-row">
475
+ <input type="text" id="input" placeholder="Type command..." autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
476
+ <button id="send">Send</button>
477
+ </div>
478
+ </div>
479
+ </div>
480
+
481
+ <script>
482
+ (function() {
483
+ 'use strict';
484
+
485
+ // Parse URL params
486
+ const params = new URLSearchParams(location.search);
487
+ const token = params.get('t');
488
+ const sessionId = params.get('s');
489
+
490
+ // DOM elements
491
+ const terminal = document.getElementById('terminal');
492
+ const input = document.getElementById('input');
493
+ const sendBtn = document.getElementById('send');
494
+ const statusDot = document.getElementById('status-dot');
495
+ const statusText = document.getElementById('status-text');
496
+ const authScreen = document.getElementById('auth-screen');
497
+ const authStatus = document.getElementById('auth-status');
498
+ const notifications = document.getElementById('notifications');
499
+
500
+ // State
501
+ let ws = null;
502
+ let reconnectAttempts = 0;
503
+ const maxReconnectAttempts = 5;
504
+ let terminalEnabled = true;
505
+
506
+ // Connect to WebSocket
507
+ function connect() {
508
+ const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
509
+ ws = new WebSocket(protocol + '//' + location.host);
510
+
511
+ ws.onopen = function() {
512
+ setStatus('connecting', 'Authenticating...');
513
+ ws.send(JSON.stringify({ type: 'auth', token: token }));
514
+ };
515
+
516
+ ws.onmessage = function(event) {
517
+ try {
518
+ const msg = JSON.parse(event.data);
519
+ handleMessage(msg);
520
+ } catch (e) {
521
+ console.error('Parse error:', e);
170
522
  }
171
523
  };
172
- return EventEmitter23;
173
- })()
174
- );
175
- exports2.EventEmitter2 = EventEmitter22;
176
- }
177
- });
178
524
 
179
- // node_modules/node-pty/lib/terminal.js
180
- var require_terminal = __commonJS({
181
- "node_modules/node-pty/lib/terminal.js"(exports2) {
182
- "use strict";
183
- Object.defineProperty(exports2, "__esModule", { value: true });
184
- exports2.Terminal = exports2.DEFAULT_ROWS = exports2.DEFAULT_COLS = void 0;
185
- var events_1 = require("events");
186
- var eventEmitter2_1 = require_eventEmitter2();
187
- exports2.DEFAULT_COLS = 80;
188
- exports2.DEFAULT_ROWS = 24;
189
- var FLOW_CONTROL_PAUSE = "";
190
- var FLOW_CONTROL_RESUME = "";
191
- var Terminal = (
192
- /** @class */
193
- (function() {
194
- function Terminal2(opt) {
195
- this._pid = 0;
196
- this._fd = 0;
197
- this._cols = 0;
198
- this._rows = 0;
199
- this._readable = false;
200
- this._writable = false;
201
- this._onData = new eventEmitter2_1.EventEmitter2();
202
- this._onExit = new eventEmitter2_1.EventEmitter2();
203
- this._internalee = new events_1.EventEmitter();
204
- this.handleFlowControl = !!(opt === null || opt === void 0 ? void 0 : opt.handleFlowControl);
205
- this._flowControlPause = (opt === null || opt === void 0 ? void 0 : opt.flowControlPause) || FLOW_CONTROL_PAUSE;
206
- this._flowControlResume = (opt === null || opt === void 0 ? void 0 : opt.flowControlResume) || FLOW_CONTROL_RESUME;
207
- if (!opt) {
208
- return;
525
+ ws.onclose = function() {
526
+ setStatus('disconnected', 'Disconnected');
527
+ if (reconnectAttempts < maxReconnectAttempts) {
528
+ reconnectAttempts++;
529
+ const delay = Math.min(2000 * reconnectAttempts, 10000);
530
+ setTimeout(connect, delay);
531
+ } else {
532
+ authStatus.textContent = 'Connection failed. Refresh to retry.';
533
+ authStatus.classList.add('error');
534
+ authScreen.classList.remove('hidden');
209
535
  }
210
- this._checkType("name", opt.name ? opt.name : void 0, "string");
211
- this._checkType("cols", opt.cols ? opt.cols : void 0, "number");
212
- this._checkType("rows", opt.rows ? opt.rows : void 0, "number");
213
- this._checkType("cwd", opt.cwd ? opt.cwd : void 0, "string");
214
- this._checkType("env", opt.env ? opt.env : void 0, "object");
215
- this._checkType("uid", opt.uid ? opt.uid : void 0, "number");
216
- this._checkType("gid", opt.gid ? opt.gid : void 0, "number");
217
- this._checkType("encoding", opt.encoding ? opt.encoding : void 0, "string");
218
- }
219
- Object.defineProperty(Terminal2.prototype, "onData", {
220
- get: function() {
221
- return this._onData.event;
222
- },
223
- enumerable: false,
224
- configurable: true
225
- });
226
- Object.defineProperty(Terminal2.prototype, "onExit", {
227
- get: function() {
228
- return this._onExit.event;
229
- },
230
- enumerable: false,
231
- configurable: true
232
- });
233
- Object.defineProperty(Terminal2.prototype, "pid", {
234
- get: function() {
235
- return this._pid;
236
- },
237
- enumerable: false,
238
- configurable: true
239
- });
240
- Object.defineProperty(Terminal2.prototype, "cols", {
241
- get: function() {
242
- return this._cols;
243
- },
244
- enumerable: false,
245
- configurable: true
246
- });
247
- Object.defineProperty(Terminal2.prototype, "rows", {
248
- get: function() {
249
- return this._rows;
250
- },
251
- enumerable: false,
252
- configurable: true
253
- });
254
- Terminal2.prototype.write = function(data) {
255
- if (this.handleFlowControl) {
256
- if (data === this._flowControlPause) {
257
- this.pause();
258
- return;
536
+ };
537
+
538
+ ws.onerror = function() {
539
+ console.error('WebSocket error');
540
+ };
541
+ }
542
+
543
+ // Handle incoming message
544
+ function handleMessage(msg) {
545
+ switch (msg.type) {
546
+ case 'auth:required':
547
+ // Already sent auth on open
548
+ break;
549
+
550
+ case 'auth:success':
551
+ authScreen.classList.add('hidden');
552
+ setStatus('connected', 'Connected');
553
+ reconnectAttempts = 0;
554
+ terminalEnabled = msg.payload?.terminalEnabled !== false;
555
+ if (terminalEnabled) {
556
+ appendOutput('\\x1b[32mConnected to NikCLI\\x1b[0m\\n\\n');
259
557
  }
260
- if (data === this._flowControlResume) {
261
- this.resume();
262
- return;
558
+ break;
559
+
560
+ case 'auth:failed':
561
+ authStatus.textContent = 'Authentication failed';
562
+ authStatus.classList.add('error');
563
+ break;
564
+
565
+ case 'terminal:output':
566
+ if (msg.payload?.data) {
567
+ appendOutput(msg.payload.data);
263
568
  }
264
- }
265
- this._write(data);
266
- };
267
- Terminal2.prototype._forwardEvents = function() {
268
- var _this = this;
269
- this.on("data", function(e) {
270
- return _this._onData.fire(e);
271
- });
272
- this.on("exit", function(exitCode, signal) {
273
- return _this._onExit.fire({ exitCode, signal });
274
- });
569
+ break;
570
+
571
+ case 'terminal:exit':
572
+ appendOutput('\\n\\x1b[33m[Process exited with code ' + (msg.payload?.code || 0) + ']\\x1b[0m\\n');
573
+ break;
574
+
575
+ case 'notification':
576
+ showNotification(msg.payload);
577
+ break;
578
+
579
+ case 'session:end':
580
+ appendOutput('\\n\\x1b[31m[Session ended]\\x1b[0m\\n');
581
+ setStatus('disconnected', 'Session ended');
582
+ break;
583
+
584
+ case 'pong':
585
+ // Heartbeat response
586
+ break;
587
+
588
+ default:
589
+ console.log('Unknown message:', msg.type);
590
+ }
591
+ }
592
+
593
+ // Append text to terminal with ANSI support
594
+ function appendOutput(text) {
595
+ // Simple ANSI to HTML conversion
596
+ const html = ansiToHtml(text);
597
+ terminal.innerHTML += html;
598
+ terminal.scrollTop = terminal.scrollHeight;
599
+ }
600
+
601
+ // Basic ANSI to HTML
602
+ function ansiToHtml(text) {
603
+ const ansiColors = {
604
+ '30': '#6e7681', '31': '#f85149', '32': '#3fb950', '33': '#d29922',
605
+ '34': '#58a6ff', '35': '#bc8cff', '36': '#76e3ea', '37': '#e6edf3',
606
+ '90': '#6e7681', '91': '#f85149', '92': '#3fb950', '93': '#d29922',
607
+ '94': '#58a6ff', '95': '#bc8cff', '96': '#76e3ea', '97': '#ffffff'
275
608
  };
276
- Terminal2.prototype._checkType = function(name, value, type, allowArray) {
277
- if (allowArray === void 0) {
278
- allowArray = false;
279
- }
280
- if (value === void 0) {
281
- return;
282
- }
283
- if (allowArray) {
284
- if (Array.isArray(value)) {
285
- value.forEach(function(v, i) {
286
- if (typeof v !== type) {
287
- throw new Error(name + "[" + i + "] must be a " + type + " (not a " + typeof v[i] + ")");
609
+
610
+ let result = '';
611
+ let currentStyle = '';
612
+
613
+ const parts = text.split(/\\x1b\\[([0-9;]+)m/);
614
+ for (let i = 0; i < parts.length; i++) {
615
+ if (i % 2 === 0) {
616
+ // Text content
617
+ result += escapeHtml(parts[i]);
618
+ } else {
619
+ // ANSI code
620
+ const codes = parts[i].split(';');
621
+ for (const code of codes) {
622
+ if (code === '0') {
623
+ if (currentStyle) {
624
+ result += '</span>';
625
+ currentStyle = '';
288
626
  }
289
- });
290
- return;
627
+ } else if (code === '1') {
628
+ currentStyle = 'font-weight:bold;';
629
+ result += '<span style="' + currentStyle + '">';
630
+ } else if (ansiColors[code]) {
631
+ if (currentStyle) result += '</span>';
632
+ currentStyle = 'color:' + ansiColors[code] + ';';
633
+ result += '<span style="' + currentStyle + '">';
634
+ }
291
635
  }
292
636
  }
293
- if (typeof value !== type) {
294
- throw new Error(name + " must be a " + type + " (not a " + typeof value + ")");
295
- }
296
- };
297
- Terminal2.prototype.end = function(data) {
298
- this._socket.end(data);
299
- };
300
- Terminal2.prototype.pipe = function(dest, options) {
301
- return this._socket.pipe(dest, options);
302
- };
303
- Terminal2.prototype.pause = function() {
304
- return this._socket.pause();
305
- };
306
- Terminal2.prototype.resume = function() {
307
- return this._socket.resume();
308
- };
309
- Terminal2.prototype.setEncoding = function(encoding) {
310
- if (this._socket._decoder) {
311
- delete this._socket._decoder;
312
- }
313
- if (encoding) {
314
- this._socket.setEncoding(encoding);
315
- }
316
- };
317
- Terminal2.prototype.addListener = function(eventName, listener) {
318
- this.on(eventName, listener);
319
- };
320
- Terminal2.prototype.on = function(eventName, listener) {
321
- if (eventName === "close") {
322
- this._internalee.on("close", listener);
323
- return;
324
- }
325
- this._socket.on(eventName, listener);
326
- };
327
- Terminal2.prototype.emit = function(eventName) {
328
- var args = [];
329
- for (var _i = 1; _i < arguments.length; _i++) {
330
- args[_i - 1] = arguments[_i];
331
- }
332
- if (eventName === "close") {
333
- return this._internalee.emit.apply(this._internalee, arguments);
334
- }
335
- return this._socket.emit.apply(this._socket, arguments);
336
- };
337
- Terminal2.prototype.listeners = function(eventName) {
338
- return this._socket.listeners(eventName);
339
- };
340
- Terminal2.prototype.removeListener = function(eventName, listener) {
341
- this._socket.removeListener(eventName, listener);
342
- };
343
- Terminal2.prototype.removeAllListeners = function(eventName) {
344
- this._socket.removeAllListeners(eventName);
345
- };
346
- Terminal2.prototype.once = function(eventName, listener) {
347
- this._socket.once(eventName, listener);
348
- };
349
- Terminal2.prototype._close = function() {
350
- this._socket.readable = false;
351
- this.write = function() {
352
- };
353
- this.end = function() {
354
- };
355
- this._writable = false;
356
- this._readable = false;
357
- };
358
- Terminal2.prototype._parseEnv = function(env) {
359
- var keys = Object.keys(env || {});
360
- var pairs = [];
361
- for (var i = 0; i < keys.length; i++) {
362
- if (keys[i] === void 0) {
363
- continue;
364
- }
365
- pairs.push(keys[i] + "=" + env[keys[i]]);
366
- }
367
- return pairs;
368
- };
369
- return Terminal2;
370
- })()
371
- );
372
- exports2.Terminal = Terminal;
373
- }
374
- });
637
+ }
375
638
 
376
- // node_modules/node-pty/lib/shared/conout.js
377
- var require_conout = __commonJS({
378
- "node_modules/node-pty/lib/shared/conout.js"(exports2) {
379
- "use strict";
380
- Object.defineProperty(exports2, "__esModule", { value: true });
381
- exports2.getWorkerPipeName = void 0;
382
- function getWorkerPipeName(conoutPipeName) {
383
- return conoutPipeName + "-worker";
384
- }
385
- exports2.getWorkerPipeName = getWorkerPipeName;
386
- }
387
- });
639
+ if (currentStyle) result += '</span>';
640
+ return result;
641
+ }
388
642
 
389
- // node_modules/node-pty/lib/windowsConoutConnection.js
390
- var require_windowsConoutConnection = __commonJS({
391
- "node_modules/node-pty/lib/windowsConoutConnection.js"(exports2) {
392
- "use strict";
393
- var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) {
394
- function adopt(value) {
395
- return value instanceof P ? value : new P(function(resolve) {
396
- resolve(value);
397
- });
643
+ // Escape HTML
644
+ function escapeHtml(text) {
645
+ return text
646
+ .replace(/&/g, '&amp;')
647
+ .replace(/</g, '&lt;')
648
+ .replace(/>/g, '&gt;')
649
+ .replace(/"/g, '&quot;')
650
+ .replace(/\\n/g, '<br>')
651
+ .replace(/ /g, '&nbsp;');
398
652
  }
399
- return new (P || (P = Promise))(function(resolve, reject) {
400
- function fulfilled(value) {
401
- try {
402
- step(generator.next(value));
403
- } catch (e) {
404
- reject(e);
405
- }
406
- }
407
- function rejected(value) {
408
- try {
409
- step(generator["throw"](value));
410
- } catch (e) {
411
- reject(e);
412
- }
413
- }
414
- function step(result) {
415
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
416
- }
417
- step((generator = generator.apply(thisArg, _arguments || [])).next());
418
- });
419
- };
420
- var __generator = exports2 && exports2.__generator || function(thisArg, body) {
421
- var _ = { label: 0, sent: function() {
422
- if (t[0] & 1) throw t[1];
423
- return t[1];
424
- }, trys: [], ops: [] }, f, y, t, g;
425
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
426
- return this;
427
- }), g;
428
- function verb(n) {
429
- return function(v) {
430
- return step([n, v]);
431
- };
653
+
654
+ // Set connection status
655
+ function setStatus(state, text) {
656
+ statusDot.className = state === 'connected' ? 'connected' :
657
+ state === 'connecting' ? 'connecting' : '';
658
+ statusText.textContent = text;
432
659
  }
433
- function step(op) {
434
- if (f) throw new TypeError("Generator is already executing.");
435
- while (_) try {
436
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
437
- if (y = 0, t) op = [op[0] & 2, t.value];
438
- switch (op[0]) {
439
- case 0:
440
- case 1:
441
- t = op;
442
- break;
443
- case 4:
444
- _.label++;
445
- return { value: op[1], done: false };
446
- case 5:
447
- _.label++;
448
- y = op[1];
449
- op = [0];
450
- continue;
451
- case 7:
452
- op = _.ops.pop();
453
- _.trys.pop();
454
- continue;
455
- default:
456
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
457
- _ = 0;
458
- continue;
459
- }
460
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
461
- _.label = op[1];
462
- break;
463
- }
464
- if (op[0] === 6 && _.label < t[1]) {
465
- _.label = t[1];
466
- t = op;
467
- break;
468
- }
469
- if (t && _.label < t[2]) {
470
- _.label = t[2];
471
- _.ops.push(op);
472
- break;
473
- }
474
- if (t[2]) _.ops.pop();
475
- _.trys.pop();
476
- continue;
477
- }
478
- op = body.call(thisArg, _);
479
- } catch (e) {
480
- op = [6, e];
481
- y = 0;
482
- } finally {
483
- f = t = 0;
660
+
661
+ // Send data to terminal
662
+ function send(data) {
663
+ if (ws && ws.readyState === WebSocket.OPEN) {
664
+ ws.send(JSON.stringify({ type: 'terminal:input', data: data }));
484
665
  }
485
- if (op[0] & 5) throw op[1];
486
- return { value: op[0] ? op[1] : void 0, done: true };
487
666
  }
488
- };
489
- Object.defineProperty(exports2, "__esModule", { value: true });
490
- exports2.ConoutConnection = void 0;
491
- var worker_threads_1 = require("worker_threads");
492
- var conout_1 = require_conout();
493
- var path_1 = require("path");
494
- var eventEmitter2_1 = require_eventEmitter2();
495
- var FLUSH_DATA_INTERVAL = 1e3;
496
- var ConoutConnection = (
497
- /** @class */
498
- (function() {
499
- function ConoutConnection2(_conoutPipeName, _useConptyDll) {
500
- var _this = this;
501
- this._conoutPipeName = _conoutPipeName;
502
- this._useConptyDll = _useConptyDll;
503
- this._isDisposed = false;
504
- this._onReady = new eventEmitter2_1.EventEmitter2();
505
- var workerData = {
506
- conoutPipeName: _conoutPipeName
507
- };
508
- var scriptPath = __dirname.replace("node_modules.asar", "node_modules.asar.unpacked");
509
- this._worker = new worker_threads_1.Worker(path_1.join(scriptPath, "worker/conoutSocketWorker.js"), { workerData });
510
- this._worker.on("message", function(message) {
511
- switch (message) {
512
- case 1:
513
- _this._onReady.fire();
514
- return;
515
- default:
516
- console.warn("Unexpected ConoutWorkerMessage", message);
517
- }
518
- });
667
+
668
+ // Show notification
669
+ function showNotification(n) {
670
+ if (!n) return;
671
+ const el = document.createElement('div');
672
+ el.className = 'notification ' + (n.type || 'info');
673
+ el.innerHTML = '<h4>' + escapeHtml(n.title || 'Notification') + '</h4>' +
674
+ '<p>' + escapeHtml(n.body || '') + '</p>';
675
+ notifications.appendChild(el);
676
+ setTimeout(function() { el.remove(); }, 5000);
677
+ }
678
+
679
+ // Event: Send button
680
+ sendBtn.onclick = function() {
681
+ if (input.value) {
682
+ send(input.value + '\\r');
683
+ input.value = '';
519
684
  }
520
- Object.defineProperty(ConoutConnection2.prototype, "onReady", {
521
- get: function() {
522
- return this._onReady.event;
523
- },
524
- enumerable: false,
525
- configurable: true
526
- });
527
- ConoutConnection2.prototype.dispose = function() {
528
- if (!this._useConptyDll && this._isDisposed) {
529
- return;
530
- }
531
- this._isDisposed = true;
532
- this._drainDataAndClose();
533
- };
534
- ConoutConnection2.prototype.connectSocket = function(socket) {
535
- socket.connect(conout_1.getWorkerPipeName(this._conoutPipeName));
536
- };
537
- ConoutConnection2.prototype._drainDataAndClose = function() {
538
- var _this = this;
539
- if (this._drainTimeout) {
540
- clearTimeout(this._drainTimeout);
541
- }
542
- this._drainTimeout = setTimeout(function() {
543
- return _this._destroySocket();
544
- }, FLUSH_DATA_INTERVAL);
545
- };
546
- ConoutConnection2.prototype._destroySocket = function() {
547
- return __awaiter(this, void 0, void 0, function() {
548
- return __generator(this, function(_a) {
549
- switch (_a.label) {
550
- case 0:
551
- return [4, this._worker.terminate()];
552
- case 1:
553
- _a.sent();
554
- return [
555
- 2
556
- /*return*/
557
- ];
558
- }
559
- });
560
- });
561
- };
562
- return ConoutConnection2;
563
- })()
564
- );
565
- exports2.ConoutConnection = ConoutConnection;
566
- }
567
- });
685
+ input.focus();
686
+ };
568
687
 
569
- // node_modules/node-pty/lib/windowsPtyAgent.js
570
- var require_windowsPtyAgent = __commonJS({
571
- "node_modules/node-pty/lib/windowsPtyAgent.js"(exports2) {
572
- "use strict";
573
- Object.defineProperty(exports2, "__esModule", { value: true });
574
- exports2.argsToCommandLine = exports2.WindowsPtyAgent = void 0;
575
- var fs = require("fs");
576
- var os2 = require("os");
577
- var path = require("path");
578
- var child_process_1 = require("child_process");
579
- var net_1 = require("net");
580
- var windowsConoutConnection_1 = require_windowsConoutConnection();
581
- var utils_1 = require_utils();
582
- var conptyNative;
583
- var winptyNative;
584
- var FLUSH_DATA_INTERVAL = 1e3;
585
- var WindowsPtyAgent = (
586
- /** @class */
587
- (function() {
588
- function WindowsPtyAgent2(file, args, env, cwd, cols, rows, debug, _useConpty, _useConptyDll, conptyInheritCursor) {
589
- var _this = this;
590
- if (_useConptyDll === void 0) {
591
- _useConptyDll = false;
592
- }
593
- if (conptyInheritCursor === void 0) {
594
- conptyInheritCursor = false;
595
- }
596
- this._useConpty = _useConpty;
597
- this._useConptyDll = _useConptyDll;
598
- this._pid = 0;
599
- this._innerPid = 0;
600
- if (this._useConpty === void 0 || this._useConpty === true) {
601
- this._useConpty = this._getWindowsBuildNumber() >= 18309;
602
- }
603
- if (this._useConpty) {
604
- if (!conptyNative) {
605
- conptyNative = utils_1.loadNativeModule("conpty").module;
606
- }
607
- } else {
608
- if (!winptyNative) {
609
- winptyNative = utils_1.loadNativeModule("pty").module;
610
- }
611
- }
612
- this._ptyNative = this._useConpty ? conptyNative : winptyNative;
613
- cwd = path.resolve(cwd);
614
- var commandLine = argsToCommandLine(file, args);
615
- var term;
616
- if (this._useConpty) {
617
- term = this._ptyNative.startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor, this._useConptyDll);
618
- } else {
619
- term = this._ptyNative.startProcess(file, commandLine, env, cwd, cols, rows, debug);
620
- this._pid = term.pid;
621
- this._innerPid = term.innerPid;
622
- }
623
- this._fd = term.fd;
624
- this._pty = term.pty;
625
- this._outSocket = new net_1.Socket();
626
- this._outSocket.setEncoding("utf8");
627
- this._conoutSocketWorker = new windowsConoutConnection_1.ConoutConnection(term.conout, this._useConptyDll);
628
- this._conoutSocketWorker.onReady(function() {
629
- _this._conoutSocketWorker.connectSocket(_this._outSocket);
630
- });
631
- this._outSocket.on("connect", function() {
632
- _this._outSocket.emit("ready_datapipe");
633
- });
634
- var inSocketFD = fs.openSync(term.conin, "w");
635
- this._inSocket = new net_1.Socket({
636
- fd: inSocketFD,
637
- readable: false,
638
- writable: true
639
- });
640
- this._inSocket.setEncoding("utf8");
641
- if (this._useConpty) {
642
- var connect = this._ptyNative.connect(this._pty, commandLine, cwd, env, this._useConptyDll, function(c) {
643
- return _this._$onProcessExit(c);
644
- });
645
- this._innerPid = connect.pid;
646
- }
688
+ // Event: Enter key in input
689
+ input.onkeydown = function(e) {
690
+ if (e.key === 'Enter') {
691
+ e.preventDefault();
692
+ sendBtn.click();
647
693
  }
648
- Object.defineProperty(WindowsPtyAgent2.prototype, "inSocket", {
649
- get: function() {
650
- return this._inSocket;
651
- },
652
- enumerable: false,
653
- configurable: true
654
- });
655
- Object.defineProperty(WindowsPtyAgent2.prototype, "outSocket", {
656
- get: function() {
657
- return this._outSocket;
658
- },
659
- enumerable: false,
660
- configurable: true
661
- });
662
- Object.defineProperty(WindowsPtyAgent2.prototype, "fd", {
663
- get: function() {
664
- return this._fd;
665
- },
666
- enumerable: false,
667
- configurable: true
668
- });
669
- Object.defineProperty(WindowsPtyAgent2.prototype, "innerPid", {
670
- get: function() {
671
- return this._innerPid;
672
- },
673
- enumerable: false,
674
- configurable: true
675
- });
676
- Object.defineProperty(WindowsPtyAgent2.prototype, "pty", {
677
- get: function() {
678
- return this._pty;
679
- },
680
- enumerable: false,
681
- configurable: true
682
- });
683
- WindowsPtyAgent2.prototype.resize = function(cols, rows) {
684
- if (this._useConpty) {
685
- if (this._exitCode !== void 0) {
686
- throw new Error("Cannot resize a pty that has already exited");
687
- }
688
- this._ptyNative.resize(this._pty, cols, rows, this._useConptyDll);
689
- return;
690
- }
691
- this._ptyNative.resize(this._pid, cols, rows);
692
- };
693
- WindowsPtyAgent2.prototype.clear = function() {
694
- if (this._useConpty) {
695
- this._ptyNative.clear(this._pty, this._useConptyDll);
696
- }
697
- };
698
- WindowsPtyAgent2.prototype.kill = function() {
699
- var _this = this;
700
- if (this._useConpty) {
701
- if (!this._useConptyDll) {
702
- this._inSocket.readable = false;
703
- this._outSocket.readable = false;
704
- this._getConsoleProcessList().then(function(consoleProcessList) {
705
- consoleProcessList.forEach(function(pid) {
706
- try {
707
- process.kill(pid);
708
- } catch (e) {
709
- }
710
- });
711
- });
712
- this._ptyNative.kill(this._pty, this._useConptyDll);
713
- this._conoutSocketWorker.dispose();
714
- } else {
715
- this._inSocket.destroy();
716
- this._ptyNative.kill(this._pty, this._useConptyDll);
717
- this._outSocket.on("data", function() {
718
- _this._conoutSocketWorker.dispose();
719
- });
720
- }
721
- } else {
722
- var processList = this._ptyNative.getProcessList(this._pid);
723
- this._ptyNative.kill(this._pid, this._innerPid);
724
- processList.forEach(function(pid) {
725
- try {
726
- process.kill(pid);
727
- } catch (e) {
728
- }
729
- });
730
- }
731
- };
732
- WindowsPtyAgent2.prototype._getConsoleProcessList = function() {
733
- var _this = this;
734
- return new Promise(function(resolve) {
735
- var agent = child_process_1.fork(path.join(__dirname, "conpty_console_list_agent"), [_this._innerPid.toString()]);
736
- agent.on("message", function(message) {
737
- clearTimeout(timeout);
738
- resolve(message.consoleProcessList);
739
- });
740
- var timeout = setTimeout(function() {
741
- agent.kill();
742
- resolve([_this._innerPid]);
743
- }, 5e3);
744
- });
745
- };
746
- Object.defineProperty(WindowsPtyAgent2.prototype, "exitCode", {
747
- get: function() {
748
- if (this._useConpty) {
749
- return this._exitCode;
750
- }
751
- var winptyExitCode = this._ptyNative.getExitCode(this._innerPid);
752
- return winptyExitCode === -1 ? void 0 : winptyExitCode;
753
- },
754
- enumerable: false,
755
- configurable: true
756
- });
757
- WindowsPtyAgent2.prototype._getWindowsBuildNumber = function() {
758
- var osVersion = /(\d+)\.(\d+)\.(\d+)/g.exec(os2.release());
759
- var buildNumber = 0;
760
- if (osVersion && osVersion.length === 4) {
761
- buildNumber = parseInt(osVersion[3]);
762
- }
763
- return buildNumber;
764
- };
765
- WindowsPtyAgent2.prototype._generatePipeName = function() {
766
- return "conpty-" + Math.random() * 1e7;
767
- };
768
- WindowsPtyAgent2.prototype._$onProcessExit = function(exitCode) {
769
- var _this = this;
770
- this._exitCode = exitCode;
771
- if (!this._useConptyDll) {
772
- this._flushDataAndCleanUp();
773
- this._outSocket.on("data", function() {
774
- return _this._flushDataAndCleanUp();
775
- });
776
- }
777
- };
778
- WindowsPtyAgent2.prototype._flushDataAndCleanUp = function() {
779
- var _this = this;
780
- if (this._useConptyDll) {
781
- return;
782
- }
783
- if (this._closeTimeout) {
784
- clearTimeout(this._closeTimeout);
785
- }
786
- this._closeTimeout = setTimeout(function() {
787
- return _this._cleanUpProcess();
788
- }, FLUSH_DATA_INTERVAL);
789
- };
790
- WindowsPtyAgent2.prototype._cleanUpProcess = function() {
791
- if (this._useConptyDll) {
792
- return;
793
- }
794
- this._inSocket.readable = false;
795
- this._outSocket.readable = false;
796
- this._outSocket.destroy();
694
+ };
695
+
696
+ // Event: Quick keys
697
+ document.querySelectorAll('.qkey').forEach(function(btn) {
698
+ btn.onclick = function() {
699
+ const key = btn.dataset.key;
700
+ const decoded = key
701
+ .replace(/\\\\x([0-9a-f]{2})/gi, function(_, hex) {
702
+ return String.fromCharCode(parseInt(hex, 16));
703
+ })
704
+ .replace(/\\\\t/g, '\\t')
705
+ .replace(/\\\\r/g, '\\r')
706
+ .replace(/\\\\n/g, '\\n');
707
+ send(decoded);
708
+ input.focus();
797
709
  };
798
- return WindowsPtyAgent2;
799
- })()
800
- );
801
- exports2.WindowsPtyAgent = WindowsPtyAgent;
802
- function argsToCommandLine(file, args) {
803
- if (isCommandLine(args)) {
804
- if (args.length === 0) {
805
- return file;
806
- }
807
- return argsToCommandLine(file, []) + " " + args;
808
- }
809
- var argv = [file];
810
- Array.prototype.push.apply(argv, args);
811
- var result = "";
812
- for (var argIndex = 0; argIndex < argv.length; argIndex++) {
813
- if (argIndex > 0) {
814
- result += " ";
815
- }
816
- var arg = argv[argIndex];
817
- var hasLopsidedEnclosingQuote = xOr(arg[0] !== '"', arg[arg.length - 1] !== '"');
818
- var hasNoEnclosingQuotes = arg[0] !== '"' && arg[arg.length - 1] !== '"';
819
- var quote = arg === "" || (arg.indexOf(" ") !== -1 || arg.indexOf(" ") !== -1) && (arg.length > 1 && (hasLopsidedEnclosingQuote || hasNoEnclosingQuotes));
820
- if (quote) {
821
- result += '"';
822
- }
823
- var bsCount = 0;
824
- for (var i = 0; i < arg.length; i++) {
825
- var p = arg[i];
826
- if (p === "\\") {
827
- bsCount++;
828
- } else if (p === '"') {
829
- result += repeatText("\\", bsCount * 2 + 1);
830
- result += '"';
831
- bsCount = 0;
832
- } else {
833
- result += repeatText("\\", bsCount);
834
- bsCount = 0;
835
- result += p;
836
- }
710
+ });
711
+
712
+ // Heartbeat
713
+ setInterval(function() {
714
+ if (ws && ws.readyState === WebSocket.OPEN) {
715
+ ws.send(JSON.stringify({ type: 'ping' }));
837
716
  }
838
- if (quote) {
839
- result += repeatText("\\", bsCount * 2);
840
- result += '"';
841
- } else {
842
- result += repeatText("\\", bsCount);
717
+ }, 25000);
718
+
719
+ // Handle resize
720
+ function sendResize() {
721
+ if (ws && ws.readyState === WebSocket.OPEN) {
722
+ const cols = Math.floor(terminal.clientWidth / 8);
723
+ const rows = Math.floor(terminal.clientHeight / 18);
724
+ ws.send(JSON.stringify({ type: 'terminal:resize', cols: cols, rows: rows }));
843
725
  }
844
726
  }
845
- return result;
846
- }
847
- exports2.argsToCommandLine = argsToCommandLine;
848
- function isCommandLine(args) {
849
- return typeof args === "string";
850
- }
851
- function repeatText(text, count) {
852
- var result = "";
853
- for (var i = 0; i < count; i++) {
854
- result += text;
727
+
728
+ window.addEventListener('resize', sendResize);
729
+ setTimeout(sendResize, 1000);
730
+
731
+ // Start connection
732
+ if (token) {
733
+ connect();
734
+ } else {
735
+ authStatus.textContent = 'Invalid session URL';
736
+ authStatus.classList.add('error');
855
737
  }
856
- return result;
857
- }
858
- function xOr(arg1, arg2) {
859
- return arg1 && !arg2 || !arg1 && arg2;
860
- }
738
+ })();
739
+ </script>
740
+ </body>
741
+ </html>`;
742
+ }
743
+ var init_web_client = __esm({
744
+ "src/web-client.ts"() {
745
+ "use strict";
861
746
  }
862
747
  });
863
748
 
864
- // node_modules/node-pty/lib/windowsTerminal.js
865
- var require_windowsTerminal = __commonJS({
866
- "node_modules/node-pty/lib/windowsTerminal.js"(exports2) {
749
+ // src/server.ts
750
+ var server_exports = {};
751
+ __export(server_exports, {
752
+ RemoteServer: () => RemoteServer
753
+ });
754
+ var import_node_events, import_node_http, import_ws, import_node_crypto, import_node_os, RemoteServer;
755
+ var init_server = __esm({
756
+ "src/server.ts"() {
867
757
  "use strict";
868
- var __extends = exports2 && exports2.__extends || /* @__PURE__ */ (function() {
869
- var extendStatics = function(d, b) {
870
- extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
871
- d2.__proto__ = b2;
872
- } || function(d2, b2) {
873
- for (var p in b2) if (b2.hasOwnProperty(p)) d2[p] = b2[p];
758
+ import_node_events = require("events");
759
+ import_node_http = require("http");
760
+ import_ws = require("ws");
761
+ import_node_crypto = __toESM(require("crypto"), 1);
762
+ import_node_os = __toESM(require("os"), 1);
763
+ init_types();
764
+ RemoteServer = class extends import_node_events.EventEmitter {
765
+ config;
766
+ httpServer = null;
767
+ wss = null;
768
+ clients = /* @__PURE__ */ new Map();
769
+ session = null;
770
+ heartbeatTimer = null;
771
+ sessionTimeoutTimer = null;
772
+ isRunning = false;
773
+ sessionSecret;
774
+ // stdin/stdout proxy state
775
+ originalStdoutWrite = null;
776
+ originalStdinOn = null;
777
+ constructor(config = {}) {
778
+ super();
779
+ this.config = { ...DEFAULT_CONFIG, ...config };
780
+ this.sessionSecret = config.sessionSecret || this.generateSecret();
781
+ }
782
+ /**
783
+ * Generate a random secret
784
+ */
785
+ generateSecret() {
786
+ return import_node_crypto.default.randomBytes(16).toString("hex");
787
+ }
788
+ /**
789
+ * Start the remote server - creates WebSocket server that proxies stdin/stdout
790
+ */
791
+ async start(options = {}) {
792
+ if (this.isRunning) {
793
+ throw new Error("Server already running");
794
+ }
795
+ const sessionId = this.generateSessionId();
796
+ this.httpServer = (0, import_node_http.createServer)((req, res) => this.handleHttpRequest(req, res));
797
+ this.wss = new import_ws.WebSocketServer({ server: this.httpServer });
798
+ this.setupWebSocketHandlers();
799
+ const port = await new Promise((resolve, reject) => {
800
+ this.httpServer.listen(this.config.port, this.config.host, () => {
801
+ const addr = this.httpServer.address();
802
+ resolve(typeof addr === "object" ? addr?.port || 0 : 0);
803
+ });
804
+ this.httpServer.on("error", reject);
805
+ });
806
+ const localIp = this.getLocalIP();
807
+ const localUrl = `http://${localIp}:${port}`;
808
+ this.session = {
809
+ id: sessionId,
810
+ name: options.name || `nikcli-${sessionId}`,
811
+ qrCode: "",
812
+ qrUrl: `${localUrl}?s=${sessionId}&t=${this.sessionSecret}`,
813
+ localUrl,
814
+ status: "waiting",
815
+ connectedDevices: [],
816
+ startedAt: /* @__PURE__ */ new Date(),
817
+ lastActivity: /* @__PURE__ */ new Date(),
818
+ port
874
819
  };
875
- return extendStatics(d, b);
876
- };
877
- return function(d, b) {
878
- extendStatics(d, b);
879
- function __() {
880
- this.constructor = d;
820
+ if (options.processForStreaming) {
821
+ this.setupStdioProxy(options.processForStreaming.stdout, options.processForStreaming.stdin);
881
822
  }
882
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
883
- };
884
- })();
885
- Object.defineProperty(exports2, "__esModule", { value: true });
886
- exports2.WindowsTerminal = void 0;
887
- var terminal_1 = require_terminal();
888
- var windowsPtyAgent_1 = require_windowsPtyAgent();
889
- var utils_1 = require_utils();
890
- var DEFAULT_FILE = "cmd.exe";
891
- var DEFAULT_NAME = "Windows Shell";
892
- var WindowsTerminal = (
893
- /** @class */
894
- (function(_super) {
895
- __extends(WindowsTerminal2, _super);
896
- function WindowsTerminal2(file, args, opt) {
897
- var _this = _super.call(this, opt) || this;
898
- _this._checkType("args", args, "string", true);
899
- args = args || [];
900
- file = file || DEFAULT_FILE;
901
- opt = opt || {};
902
- opt.env = opt.env || process.env;
903
- if (opt.encoding) {
904
- console.warn("Setting encoding on Windows is not supported");
905
- }
906
- var env = utils_1.assign({}, opt.env);
907
- _this._cols = opt.cols || terminal_1.DEFAULT_COLS;
908
- _this._rows = opt.rows || terminal_1.DEFAULT_ROWS;
909
- var cwd = opt.cwd || process.cwd();
910
- var name = opt.name || env.TERM || DEFAULT_NAME;
911
- var parsedEnv = _this._parseEnv(env);
912
- _this._isReady = false;
913
- _this._deferreds = [];
914
- _this._agent = new windowsPtyAgent_1.WindowsPtyAgent(file, args, parsedEnv, cwd, _this._cols, _this._rows, false, opt.useConpty, opt.useConptyDll, opt.conptyInheritCursor);
915
- _this._socket = _this._agent.outSocket;
916
- _this._pid = _this._agent.innerPid;
917
- _this._fd = _this._agent.fd;
918
- _this._pty = _this._agent.pty;
919
- _this._socket.on("ready_datapipe", function() {
920
- _this._socket.once("data", function() {
921
- if (!_this._isReady) {
922
- _this._isReady = true;
923
- _this._deferreds.forEach(function(fn) {
924
- fn.run();
925
- });
926
- _this._deferreds = [];
927
- }
928
- });
929
- _this._socket.on("error", function(err) {
930
- _this._close();
931
- if (err.code) {
932
- if (~err.code.indexOf("errno 5") || ~err.code.indexOf("EIO"))
933
- return;
934
- }
935
- if (_this.listeners("error").length < 2) {
936
- throw err;
823
+ this.startHeartbeat();
824
+ if (this.config.sessionTimeout > 0) {
825
+ this.startSessionTimeout();
826
+ }
827
+ this.session.status = "waiting";
828
+ this.isRunning = true;
829
+ this.emit("started", this.session);
830
+ return this.session;
831
+ }
832
+ /**
833
+ * Setup stdin/stdout proxy to forward to WebSocket clients
834
+ */
835
+ setupStdioProxy(stdout, stdin) {
836
+ const originalWrite = stdout.write.bind(stdout);
837
+ stdout.write = ((data, encoding, cb) => {
838
+ const result = originalWrite(data, encoding, cb);
839
+ const text = data instanceof Buffer ? data.toString() : data;
840
+ this.broadcastToAll({ type: MessageTypes.TERMINAL_OUTPUT, payload: { data: text } });
841
+ return result;
842
+ });
843
+ this.wss?.on("connection", (ws) => {
844
+ ws.on("message", (rawData) => {
845
+ try {
846
+ const msg = JSON.parse(rawData.toString());
847
+ if (msg.type === MessageTypes.TERMINAL_INPUT && msg.data) {
848
+ const inputData = Buffer.from(msg.data);
849
+ stdin.emit("data", inputData);
937
850
  }
938
- });
939
- _this._socket.on("close", function() {
940
- _this.emit("exit", _this._agent.exitCode);
941
- _this._close();
942
- });
851
+ } catch {
852
+ }
943
853
  });
944
- _this._file = file;
945
- _this._name = name;
946
- _this._readable = true;
947
- _this._writable = true;
948
- _this._forwardEvents();
949
- return _this;
950
- }
951
- WindowsTerminal2.prototype._write = function(data) {
952
- this._defer(this._doWrite, data);
953
- };
954
- WindowsTerminal2.prototype._doWrite = function(data) {
955
- this._agent.inSocket.write(data);
956
- };
957
- WindowsTerminal2.open = function(options) {
958
- throw new Error("open() not supported on windows, use Fork() instead.");
959
- };
960
- WindowsTerminal2.prototype.resize = function(cols, rows) {
961
- var _this = this;
962
- if (cols <= 0 || rows <= 0 || isNaN(cols) || isNaN(rows) || cols === Infinity || rows === Infinity) {
963
- throw new Error("resizing must be done using positive cols and rows");
964
- }
965
- this._deferNoArgs(function() {
966
- _this._agent.resize(cols, rows);
967
- _this._cols = cols;
968
- _this._rows = rows;
969
- });
970
- };
971
- WindowsTerminal2.prototype.clear = function() {
972
- var _this = this;
973
- this._deferNoArgs(function() {
974
- _this._agent.clear();
975
- });
976
- };
977
- WindowsTerminal2.prototype.destroy = function() {
978
- var _this = this;
979
- this._deferNoArgs(function() {
980
- _this.kill();
981
- });
982
- };
983
- WindowsTerminal2.prototype.kill = function(signal) {
984
- var _this = this;
985
- this._deferNoArgs(function() {
986
- if (signal) {
987
- throw new Error("Signals not supported on windows.");
988
- }
989
- _this._close();
990
- _this._agent.kill();
991
- });
992
- };
993
- WindowsTerminal2.prototype._deferNoArgs = function(deferredFn) {
994
- var _this = this;
995
- if (this._isReady) {
996
- deferredFn.call(this);
997
- return;
998
- }
999
- this._deferreds.push({
1000
- run: function() {
1001
- return deferredFn.call(_this);
1002
- }
1003
- });
1004
- };
1005
- WindowsTerminal2.prototype._defer = function(deferredFn, arg) {
1006
- var _this = this;
1007
- if (this._isReady) {
1008
- deferredFn.call(this, arg);
1009
- return;
1010
- }
1011
- this._deferreds.push({
1012
- run: function() {
1013
- return deferredFn.call(_this, arg);
1014
- }
1015
- });
1016
- };
1017
- Object.defineProperty(WindowsTerminal2.prototype, "process", {
1018
- get: function() {
1019
- return this._name;
1020
- },
1021
- enumerable: false,
1022
- configurable: true
1023
- });
1024
- Object.defineProperty(WindowsTerminal2.prototype, "master", {
1025
- get: function() {
1026
- throw new Error("master is not supported on Windows");
1027
- },
1028
- enumerable: false,
1029
- configurable: true
1030
- });
1031
- Object.defineProperty(WindowsTerminal2.prototype, "slave", {
1032
- get: function() {
1033
- throw new Error("slave is not supported on Windows");
1034
- },
1035
- enumerable: false,
1036
- configurable: true
1037
854
  });
1038
- return WindowsTerminal2;
1039
- })(terminal_1.Terminal)
1040
- );
1041
- exports2.WindowsTerminal = WindowsTerminal;
1042
- }
1043
- });
1044
-
1045
- // node_modules/node-pty/lib/unixTerminal.js
1046
- var require_unixTerminal = __commonJS({
1047
- "node_modules/node-pty/lib/unixTerminal.js"(exports2) {
1048
- "use strict";
1049
- var __extends = exports2 && exports2.__extends || /* @__PURE__ */ (function() {
1050
- var extendStatics = function(d, b) {
1051
- extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
1052
- d2.__proto__ = b2;
1053
- } || function(d2, b2) {
1054
- for (var p in b2) if (b2.hasOwnProperty(p)) d2[p] = b2[p];
1055
- };
1056
- return extendStatics(d, b);
1057
- };
1058
- return function(d, b) {
1059
- extendStatics(d, b);
1060
- function __() {
1061
- this.constructor = d;
855
+ }
856
+ /**
857
+ * Stop the server
858
+ */
859
+ async stop() {
860
+ if (!this.isRunning) return;
861
+ this.isRunning = false;
862
+ if (this.originalStdoutWrite && this.session) {
1062
863
  }
1063
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1064
- };
1065
- })();
1066
- Object.defineProperty(exports2, "__esModule", { value: true });
1067
- exports2.UnixTerminal = void 0;
1068
- var fs = require("fs");
1069
- var path = require("path");
1070
- var tty = require("tty");
1071
- var terminal_1 = require_terminal();
1072
- var utils_1 = require_utils();
1073
- var native = utils_1.loadNativeModule("pty");
1074
- var pty2 = native.module;
1075
- var helperPath = native.dir + "/spawn-helper";
1076
- helperPath = path.resolve(__dirname, helperPath);
1077
- helperPath = helperPath.replace("app.asar", "app.asar.unpacked");
1078
- helperPath = helperPath.replace("node_modules.asar", "node_modules.asar.unpacked");
1079
- var DEFAULT_FILE = "sh";
1080
- var DEFAULT_NAME = "xterm";
1081
- var DESTROY_SOCKET_TIMEOUT_MS = 200;
1082
- var UnixTerminal = (
1083
- /** @class */
1084
- (function(_super) {
1085
- __extends(UnixTerminal2, _super);
1086
- function UnixTerminal2(file, args, opt) {
1087
- var _a, _b;
1088
- var _this = _super.call(this, opt) || this;
1089
- _this._boundClose = false;
1090
- _this._emittedClose = false;
1091
- if (typeof args === "string") {
1092
- throw new Error("args as a string is not supported on unix.");
1093
- }
1094
- args = args || [];
1095
- file = file || DEFAULT_FILE;
1096
- opt = opt || {};
1097
- opt.env = opt.env || process.env;
1098
- _this._cols = opt.cols || terminal_1.DEFAULT_COLS;
1099
- _this._rows = opt.rows || terminal_1.DEFAULT_ROWS;
1100
- var uid = (_a = opt.uid) !== null && _a !== void 0 ? _a : -1;
1101
- var gid = (_b = opt.gid) !== null && _b !== void 0 ? _b : -1;
1102
- var env = utils_1.assign({}, opt.env);
1103
- if (opt.env === process.env) {
1104
- _this._sanitizeEnv(env);
1105
- }
1106
- var cwd = opt.cwd || process.cwd();
1107
- env.PWD = cwd;
1108
- var name = opt.name || env.TERM || DEFAULT_NAME;
1109
- env.TERM = name;
1110
- var parsedEnv = _this._parseEnv(env);
1111
- var encoding = opt.encoding === void 0 ? "utf8" : opt.encoding;
1112
- var onexit = function(code, signal) {
1113
- if (!_this._emittedClose) {
1114
- if (_this._boundClose) {
1115
- return;
1116
- }
1117
- _this._boundClose = true;
1118
- var timeout_1 = setTimeout(function() {
1119
- timeout_1 = null;
1120
- _this._socket.destroy();
1121
- }, DESTROY_SOCKET_TIMEOUT_MS);
1122
- _this.once("close", function() {
1123
- if (timeout_1 !== null) {
1124
- clearTimeout(timeout_1);
1125
- }
1126
- _this.emit("exit", code, signal);
1127
- });
1128
- return;
1129
- }
1130
- _this.emit("exit", code, signal);
1131
- };
1132
- var term = pty2.fork(file, args, parsedEnv, cwd, _this._cols, _this._rows, uid, gid, encoding === "utf8", helperPath, onexit);
1133
- _this._socket = new tty.ReadStream(term.fd);
1134
- if (encoding !== null) {
1135
- _this._socket.setEncoding(encoding);
1136
- }
1137
- _this._writeStream = new CustomWriteStream(term.fd, encoding || void 0);
1138
- _this._socket.on("error", function(err) {
1139
- if (err.code) {
1140
- if (~err.code.indexOf("EAGAIN")) {
1141
- return;
1142
- }
1143
- }
1144
- _this._close();
1145
- if (!_this._emittedClose) {
1146
- _this._emittedClose = true;
1147
- _this.emit("close");
1148
- }
1149
- if (err.code) {
1150
- if (~err.code.indexOf("errno 5") || ~err.code.indexOf("EIO")) {
1151
- return;
1152
- }
1153
- }
1154
- if (_this.listeners("error").length < 2) {
1155
- throw err;
1156
- }
1157
- });
1158
- _this._pid = term.pid;
1159
- _this._fd = term.fd;
1160
- _this._pty = term.pty;
1161
- _this._file = file;
1162
- _this._name = name;
1163
- _this._readable = true;
1164
- _this._writable = true;
1165
- _this._socket.on("close", function() {
1166
- if (_this._emittedClose) {
1167
- return;
1168
- }
1169
- _this._emittedClose = true;
1170
- _this._close();
1171
- _this.emit("close");
1172
- });
1173
- _this._forwardEvents();
1174
- return _this;
864
+ if (this.heartbeatTimer) {
865
+ clearInterval(this.heartbeatTimer);
866
+ this.heartbeatTimer = null;
1175
867
  }
1176
- Object.defineProperty(UnixTerminal2.prototype, "master", {
1177
- get: function() {
1178
- return this._master;
1179
- },
1180
- enumerable: false,
1181
- configurable: true
1182
- });
1183
- Object.defineProperty(UnixTerminal2.prototype, "slave", {
1184
- get: function() {
1185
- return this._slave;
1186
- },
1187
- enumerable: false,
1188
- configurable: true
1189
- });
1190
- UnixTerminal2.prototype._write = function(data) {
1191
- this._writeStream.write(data);
1192
- };
1193
- Object.defineProperty(UnixTerminal2.prototype, "fd", {
1194
- /* Accessors */
1195
- get: function() {
1196
- return this._fd;
1197
- },
1198
- enumerable: false,
1199
- configurable: true
1200
- });
1201
- Object.defineProperty(UnixTerminal2.prototype, "ptsName", {
1202
- get: function() {
1203
- return this._pty;
1204
- },
1205
- enumerable: false,
1206
- configurable: true
1207
- });
1208
- UnixTerminal2.open = function(opt) {
1209
- var self = Object.create(UnixTerminal2.prototype);
1210
- opt = opt || {};
1211
- if (arguments.length > 1) {
1212
- opt = {
1213
- cols: arguments[1],
1214
- rows: arguments[2]
1215
- };
1216
- }
1217
- var cols = opt.cols || terminal_1.DEFAULT_COLS;
1218
- var rows = opt.rows || terminal_1.DEFAULT_ROWS;
1219
- var encoding = opt.encoding === void 0 ? "utf8" : opt.encoding;
1220
- var term = pty2.open(cols, rows);
1221
- self._master = new tty.ReadStream(term.master);
1222
- if (encoding !== null) {
1223
- self._master.setEncoding(encoding);
1224
- }
1225
- self._master.resume();
1226
- self._slave = new tty.ReadStream(term.slave);
1227
- if (encoding !== null) {
1228
- self._slave.setEncoding(encoding);
1229
- }
1230
- self._slave.resume();
1231
- self._socket = self._master;
1232
- self._pid = -1;
1233
- self._fd = term.master;
1234
- self._pty = term.pty;
1235
- self._file = process.argv[0] || "node";
1236
- self._name = process.env.TERM || "";
1237
- self._readable = true;
1238
- self._writable = true;
1239
- self._socket.on("error", function(err) {
1240
- self._close();
1241
- if (self.listeners("error").length < 2) {
1242
- throw err;
1243
- }
1244
- });
1245
- self._socket.on("close", function() {
1246
- self._close();
1247
- });
1248
- return self;
1249
- };
1250
- UnixTerminal2.prototype.destroy = function() {
1251
- var _this = this;
1252
- this._close();
1253
- this._socket.once("close", function() {
1254
- _this.kill("SIGHUP");
1255
- });
1256
- this._socket.destroy();
1257
- this._writeStream.dispose();
1258
- };
1259
- UnixTerminal2.prototype.kill = function(signal) {
1260
- try {
1261
- process.kill(this.pid, signal || "SIGHUP");
1262
- } catch (e) {
1263
- }
1264
- };
1265
- Object.defineProperty(UnixTerminal2.prototype, "process", {
1266
- /**
1267
- * Gets the name of the process.
1268
- */
1269
- get: function() {
1270
- if (process.platform === "darwin") {
1271
- var title = pty2.process(this._fd);
1272
- return title !== "kernel_task" ? title : this._file;
1273
- }
1274
- return pty2.process(this._fd, this._pty) || this._file;
1275
- },
1276
- enumerable: false,
1277
- configurable: true
1278
- });
1279
- UnixTerminal2.prototype.resize = function(cols, rows) {
1280
- if (cols <= 0 || rows <= 0 || isNaN(cols) || isNaN(rows) || cols === Infinity || rows === Infinity) {
1281
- throw new Error("resizing must be done using positive cols and rows");
1282
- }
1283
- pty2.resize(this._fd, cols, rows);
1284
- this._cols = cols;
1285
- this._rows = rows;
1286
- };
1287
- UnixTerminal2.prototype.clear = function() {
1288
- };
1289
- UnixTerminal2.prototype._sanitizeEnv = function(env) {
1290
- delete env["TMUX"];
1291
- delete env["TMUX_PANE"];
1292
- delete env["STY"];
1293
- delete env["WINDOW"];
1294
- delete env["WINDOWID"];
1295
- delete env["TERMCAP"];
1296
- delete env["COLUMNS"];
1297
- delete env["LINES"];
1298
- };
1299
- return UnixTerminal2;
1300
- })(terminal_1.Terminal)
1301
- );
1302
- exports2.UnixTerminal = UnixTerminal;
1303
- var CustomWriteStream = (
1304
- /** @class */
1305
- (function() {
1306
- function CustomWriteStream2(_fd, _encoding) {
1307
- this._fd = _fd;
1308
- this._encoding = _encoding;
1309
- this._writeQueue = [];
1310
- }
1311
- CustomWriteStream2.prototype.dispose = function() {
1312
- clearImmediate(this._writeImmediate);
1313
- this._writeImmediate = void 0;
1314
- };
1315
- CustomWriteStream2.prototype.write = function(data) {
1316
- var buffer = typeof data === "string" ? Buffer.from(data, this._encoding) : Buffer.from(data);
1317
- if (buffer.byteLength !== 0) {
1318
- this._writeQueue.push({ buffer, offset: 0 });
1319
- if (this._writeQueue.length === 1) {
1320
- this._processWriteQueue();
1321
- }
1322
- }
1323
- };
1324
- CustomWriteStream2.prototype._processWriteQueue = function() {
1325
- var _this = this;
1326
- this._writeImmediate = void 0;
1327
- if (this._writeQueue.length === 0) {
1328
- return;
1329
- }
1330
- var task = this._writeQueue[0];
1331
- fs.write(this._fd, task.buffer, task.offset, function(err, written) {
1332
- if (err) {
1333
- if ("code" in err && err.code === "EAGAIN") {
1334
- _this._writeImmediate = setImmediate(function() {
1335
- return _this._processWriteQueue();
1336
- });
1337
- } else {
1338
- _this._writeQueue.length = 0;
1339
- console.error("Unhandled pty write error", err);
1340
- }
1341
- return;
1342
- }
1343
- task.offset += written;
1344
- if (task.offset >= task.buffer.byteLength) {
1345
- _this._writeQueue.shift();
1346
- }
1347
- _this._processWriteQueue();
868
+ if (this.sessionTimeoutTimer) {
869
+ clearTimeout(this.sessionTimeoutTimer);
870
+ this.sessionTimeoutTimer = null;
871
+ }
872
+ this.broadcastToAll({ type: MessageTypes.SESSION_END, payload: {} });
873
+ for (const client of this.clients.values()) {
874
+ client.ws.close(1e3, "Server shutting down");
875
+ }
876
+ this.clients.clear();
877
+ if (this.wss) {
878
+ this.wss.close();
879
+ this.wss = null;
880
+ }
881
+ if (this.httpServer) {
882
+ await new Promise((resolve) => {
883
+ this.httpServer.close(() => resolve());
1348
884
  });
1349
- };
1350
- return CustomWriteStream2;
1351
- })()
1352
- );
1353
- }
1354
- });
1355
-
1356
- // node_modules/node-pty/lib/index.js
1357
- var require_lib = __commonJS({
1358
- "node_modules/node-pty/lib/index.js"(exports2) {
1359
- "use strict";
1360
- Object.defineProperty(exports2, "__esModule", { value: true });
1361
- exports2.native = exports2.open = exports2.createTerminal = exports2.fork = exports2.spawn = void 0;
1362
- var utils_1 = require_utils();
1363
- var terminalCtor;
1364
- if (process.platform === "win32") {
1365
- terminalCtor = require_windowsTerminal().WindowsTerminal;
1366
- } else {
1367
- terminalCtor = require_unixTerminal().UnixTerminal;
1368
- }
1369
- function spawn3(file, args, opt) {
1370
- return new terminalCtor(file, args, opt);
1371
- }
1372
- exports2.spawn = spawn3;
1373
- function fork(file, args, opt) {
1374
- return new terminalCtor(file, args, opt);
1375
- }
1376
- exports2.fork = fork;
1377
- function createTerminal(file, args, opt) {
1378
- return new terminalCtor(file, args, opt);
1379
- }
1380
- exports2.createTerminal = createTerminal;
1381
- function open(options) {
1382
- return terminalCtor.open(options);
1383
- }
1384
- exports2.open = open;
1385
- exports2.native = process.platform !== "win32" ? utils_1.loadNativeModule("pty").module : null;
1386
- }
1387
- });
1388
-
1389
- // src/terminal.ts
1390
- var import_node_events, import_node_child_process, pty, TerminalManager;
1391
- var init_terminal = __esm({
1392
- "src/terminal.ts"() {
1393
- "use strict";
1394
- import_node_events = require("events");
1395
- import_node_child_process = require("child_process");
1396
- pty = null;
1397
- try {
1398
- pty = require_lib();
1399
- } catch {
1400
- }
1401
- TerminalManager = class extends import_node_events.EventEmitter {
1402
- config;
1403
- ptyProcess = null;
1404
- process = null;
1405
- running = false;
1406
- constructor(config) {
1407
- super();
1408
- this.config = config;
885
+ this.httpServer = null;
886
+ }
887
+ if (this.session) {
888
+ this.session.status = "stopped";
889
+ }
890
+ this.emit("stopped");
1409
891
  }
1410
892
  /**
1411
- * Start the terminal
893
+ * Broadcast message to all authenticated clients
1412
894
  */
1413
- start() {
1414
- if (this.running) return;
1415
- const { shell, cols, rows, cwd, env } = this.config;
1416
- const termEnv = {
1417
- ...process.env,
1418
- ...env,
1419
- TERM: "xterm-256color",
1420
- COLORTERM: "truecolor"
1421
- };
1422
- if (pty) {
1423
- try {
1424
- this.ptyProcess = pty.spawn(shell, [], {
1425
- name: "xterm-256color",
1426
- cols,
1427
- rows,
1428
- cwd: cwd || process.cwd(),
1429
- env: termEnv
1430
- });
1431
- this.ptyProcess.onData((data) => {
1432
- this.emit("data", data);
1433
- });
1434
- this.ptyProcess.onExit(({ exitCode }) => {
1435
- this.running = false;
1436
- this.emit("exit", exitCode);
1437
- });
1438
- this.running = true;
1439
- return;
1440
- } catch (error) {
1441
- console.warn("node-pty failed, using fallback:", error.message);
895
+ broadcastToAll(message) {
896
+ const data = JSON.stringify({
897
+ type: message.type,
898
+ payload: message.payload,
899
+ timestamp: message.timestamp || Date.now()
900
+ });
901
+ for (const client of this.clients.values()) {
902
+ if (client.authenticated && client.ws.readyState === import_ws.WebSocket.OPEN) {
903
+ client.ws.send(data);
1442
904
  }
1443
905
  }
1444
- this.process = (0, import_node_child_process.spawn)(shell, [], {
1445
- cwd: cwd || process.cwd(),
1446
- env: termEnv,
1447
- stdio: ["pipe", "pipe", "pipe"],
1448
- shell: true
1449
- });
1450
- this.process.stdout?.on("data", (data) => {
1451
- this.emit("data", data.toString());
1452
- });
1453
- this.process.stderr?.on("data", (data) => {
1454
- this.emit("data", data.toString());
1455
- });
1456
- this.process.on("exit", (code) => {
1457
- this.running = false;
1458
- this.emit("exit", code || 0);
1459
- });
1460
- this.process.on("error", (error) => {
1461
- this.emit("error", error);
1462
- });
1463
- this.running = true;
1464
906
  }
1465
907
  /**
1466
- * Write data to terminal
908
+ * Send notification to clients
1467
909
  */
1468
- write(data) {
1469
- if (this.ptyProcess) {
1470
- this.ptyProcess.write(data);
1471
- } else if (this.process?.stdin) {
1472
- this.process.stdin.write(data);
1473
- }
910
+ notify(notification) {
911
+ this.broadcastToAll({
912
+ type: MessageTypes.NOTIFICATION,
913
+ payload: notification
914
+ });
1474
915
  }
1475
916
  /**
1476
- * Resize terminal
917
+ * Get current session
1477
918
  */
1478
- resize(cols, rows) {
1479
- if (this.ptyProcess) {
1480
- this.ptyProcess.resize(cols, rows);
1481
- }
919
+ getSession() {
920
+ return this.session;
1482
921
  }
1483
922
  /**
1484
- * Clear terminal
923
+ * Check if server is running
1485
924
  */
1486
- clear() {
1487
- this.emit("data", "\x1B[2J\x1B[H");
925
+ isActive() {
926
+ return this.isRunning && this.session?.status !== "stopped";
1488
927
  }
1489
928
  /**
1490
- * Kill terminal process
929
+ * Get connected client count
1491
930
  */
1492
- destroy() {
1493
- this.running = false;
1494
- if (this.ptyProcess) {
1495
- this.ptyProcess.kill();
1496
- this.ptyProcess = null;
1497
- }
1498
- if (this.process) {
1499
- this.process.kill();
1500
- this.process = null;
931
+ getConnectedCount() {
932
+ let count = 0;
933
+ for (const client of this.clients.values()) {
934
+ if (client.authenticated) count++;
1501
935
  }
936
+ return count;
1502
937
  }
1503
938
  /**
1504
- * Check if terminal is running
939
+ * Write data to all connected clients (for manual output streaming)
1505
940
  */
1506
- isRunning() {
1507
- return this.running;
941
+ writeToClients(data) {
942
+ this.broadcastToAll({ type: MessageTypes.TERMINAL_OUTPUT, payload: { data } });
1508
943
  }
1509
944
  /**
1510
- * Check if using PTY
945
+ * Alias for writeToClients - for compatibility
1511
946
  */
1512
- hasPty() {
1513
- return this.ptyProcess !== null;
1514
- }
1515
- };
1516
- }
1517
- });
1518
-
1519
- // node_modules/axios/lib/helpers/bind.js
1520
- var require_bind = __commonJS({
1521
- "node_modules/axios/lib/helpers/bind.js"(exports2, module2) {
1522
- "use strict";
1523
- module2.exports = function bind(fn, thisArg) {
1524
- return function wrap() {
1525
- var args = new Array(arguments.length);
1526
- for (var i = 0; i < args.length; i++) {
1527
- args[i] = arguments[i];
1528
- }
1529
- return fn.apply(thisArg, args);
1530
- };
1531
- };
1532
- }
1533
- });
1534
-
1535
- // node_modules/axios/lib/utils.js
1536
- var require_utils2 = __commonJS({
1537
- "node_modules/axios/lib/utils.js"(exports2, module2) {
1538
- "use strict";
1539
- var bind = require_bind();
1540
- var toString = Object.prototype.toString;
1541
- function isArray(val) {
1542
- return toString.call(val) === "[object Array]";
1543
- }
1544
- function isUndefined(val) {
1545
- return typeof val === "undefined";
1546
- }
1547
- function isBuffer(val) {
1548
- return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) && typeof val.constructor.isBuffer === "function" && val.constructor.isBuffer(val);
1549
- }
1550
- function isArrayBuffer(val) {
1551
- return toString.call(val) === "[object ArrayBuffer]";
1552
- }
1553
- function isFormData(val) {
1554
- return typeof FormData !== "undefined" && val instanceof FormData;
1555
- }
1556
- function isArrayBufferView(val) {
1557
- var result;
1558
- if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView) {
1559
- result = ArrayBuffer.isView(val);
1560
- } else {
1561
- result = val && val.buffer && val.buffer instanceof ArrayBuffer;
1562
- }
1563
- return result;
1564
- }
1565
- function isString(val) {
1566
- return typeof val === "string";
1567
- }
1568
- function isNumber(val) {
1569
- return typeof val === "number";
1570
- }
1571
- function isObject(val) {
1572
- return val !== null && typeof val === "object";
1573
- }
1574
- function isPlainObject(val) {
1575
- if (toString.call(val) !== "[object Object]") {
1576
- return false;
947
+ writeToTerminal(data) {
948
+ this.writeToClients(data);
1577
949
  }
1578
- var prototype = Object.getPrototypeOf(val);
1579
- return prototype === null || prototype === Object.prototype;
1580
- }
1581
- function isDate(val) {
1582
- return toString.call(val) === "[object Date]";
1583
- }
1584
- function isFile(val) {
1585
- return toString.call(val) === "[object File]";
1586
- }
1587
- function isBlob(val) {
1588
- return toString.call(val) === "[object Blob]";
1589
- }
1590
- function isFunction(val) {
1591
- return toString.call(val) === "[object Function]";
1592
- }
1593
- function isStream(val) {
1594
- return isObject(val) && isFunction(val.pipe);
1595
- }
1596
- function isURLSearchParams(val) {
1597
- return typeof URLSearchParams !== "undefined" && val instanceof URLSearchParams;
1598
- }
1599
- function trim(str) {
1600
- return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, "");
1601
- }
1602
- function isStandardBrowserEnv() {
1603
- if (typeof navigator !== "undefined" && (navigator.product === "ReactNative" || navigator.product === "NativeScript" || navigator.product === "NS")) {
1604
- return false;
1605
- }
1606
- return typeof window !== "undefined" && typeof document !== "undefined";
1607
- }
1608
- function forEach(obj, fn) {
1609
- if (obj === null || typeof obj === "undefined") {
1610
- return;
1611
- }
1612
- if (typeof obj !== "object") {
1613
- obj = [obj];
950
+ /**
951
+ * Setup WebSocket handlers
952
+ */
953
+ setupWebSocketHandlers() {
954
+ this.wss.on("connection", (ws, req) => {
955
+ const clientId = this.generateClientId();
956
+ const client = {
957
+ id: clientId,
958
+ ws,
959
+ authenticated: false,
960
+ device: {
961
+ id: clientId,
962
+ userAgent: req.headers["user-agent"],
963
+ ip: req.socket.remoteAddress,
964
+ connectedAt: /* @__PURE__ */ new Date(),
965
+ lastActivity: /* @__PURE__ */ new Date()
966
+ },
967
+ lastPing: Date.now()
968
+ };
969
+ if (this.clients.size >= this.config.maxConnections) {
970
+ ws.close(1013, "Max connections reached");
971
+ return;
972
+ }
973
+ this.clients.set(clientId, client);
974
+ ws.send(JSON.stringify({ type: MessageTypes.AUTH_REQUIRED, timestamp: Date.now() }));
975
+ ws.on("message", (data) => {
976
+ try {
977
+ const message = JSON.parse(data.toString());
978
+ this.handleClientMessage(client, message);
979
+ } catch {
980
+ }
981
+ });
982
+ ws.on("close", () => {
983
+ this.clients.delete(clientId);
984
+ if (this.session && client.authenticated) {
985
+ this.session.connectedDevices = this.session.connectedDevices.filter(
986
+ (d) => d.id !== clientId
987
+ );
988
+ if (this.session.connectedDevices.length === 0) {
989
+ this.session.status = "waiting";
990
+ }
991
+ this.emit("client:disconnected", client.device);
992
+ }
993
+ });
994
+ ws.on("error", (error) => {
995
+ this.emit("client:error", clientId, error);
996
+ });
997
+ ws.on("pong", () => {
998
+ client.lastPing = Date.now();
999
+ });
1000
+ });
1614
1001
  }
1615
- if (isArray(obj)) {
1616
- for (var i = 0, l = obj.length; i < l; i++) {
1617
- fn.call(null, obj[i], i, obj);
1002
+ /**
1003
+ * Handle client message
1004
+ */
1005
+ handleClientMessage(client, message) {
1006
+ client.device.lastActivity = /* @__PURE__ */ new Date();
1007
+ if (this.session) {
1008
+ this.session.lastActivity = /* @__PURE__ */ new Date();
1618
1009
  }
1619
- } else {
1620
- for (var key in obj) {
1621
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
1622
- fn.call(null, obj[key], key, obj);
1623
- }
1010
+ if (this.config.sessionTimeout > 0) {
1011
+ this.resetSessionTimeout();
1624
1012
  }
1625
- }
1626
- }
1627
- function merge() {
1628
- var result = {};
1629
- function assignValue(val, key) {
1630
- if (isPlainObject(result[key]) && isPlainObject(val)) {
1631
- result[key] = merge(result[key], val);
1632
- } else if (isPlainObject(val)) {
1633
- result[key] = merge({}, val);
1634
- } else if (isArray(val)) {
1635
- result[key] = val.slice();
1636
- } else {
1637
- result[key] = val;
1013
+ switch (message.type) {
1014
+ case MessageTypes.AUTH:
1015
+ this.handleAuth(client, message.token);
1016
+ break;
1017
+ case MessageTypes.TERMINAL_INPUT:
1018
+ break;
1019
+ case MessageTypes.TERMINAL_RESIZE:
1020
+ this.emit("message", client, message);
1021
+ break;
1022
+ case MessageTypes.PING:
1023
+ client.ws.send(JSON.stringify({ type: MessageTypes.PONG, timestamp: Date.now() }));
1024
+ break;
1025
+ default:
1026
+ this.emit("message", client, message);
1638
1027
  }
1639
1028
  }
1640
- for (var i = 0, l = arguments.length; i < l; i++) {
1641
- forEach(arguments[i], assignValue);
1642
- }
1643
- return result;
1644
- }
1645
- function extend(a, b, thisArg) {
1646
- forEach(b, function assignValue(val, key) {
1647
- if (thisArg && typeof val === "function") {
1648
- a[key] = bind(val, thisArg);
1029
+ /**
1030
+ * Handle authentication
1031
+ */
1032
+ handleAuth(client, token) {
1033
+ if (token === this.sessionSecret) {
1034
+ client.authenticated = true;
1035
+ if (this.session) {
1036
+ this.session.connectedDevices.push(client.device);
1037
+ this.session.status = "connected";
1038
+ }
1039
+ client.ws.send(
1040
+ JSON.stringify({
1041
+ type: MessageTypes.AUTH_SUCCESS,
1042
+ payload: {
1043
+ sessionId: this.session?.id
1044
+ },
1045
+ timestamp: Date.now()
1046
+ })
1047
+ );
1048
+ this.emit("client:connected", client.device);
1649
1049
  } else {
1650
- a[key] = val;
1050
+ client.ws.send(JSON.stringify({ type: MessageTypes.AUTH_FAILED, timestamp: Date.now() }));
1051
+ setTimeout(() => client.ws.close(1008, "Authentication failed"), 100);
1651
1052
  }
1652
- });
1653
- return a;
1654
- }
1655
- function stripBOM(content) {
1656
- if (content.charCodeAt(0) === 65279) {
1657
- content = content.slice(1);
1658
- }
1659
- return content;
1660
- }
1661
- module2.exports = {
1662
- isArray,
1663
- isArrayBuffer,
1664
- isBuffer,
1665
- isFormData,
1666
- isArrayBufferView,
1667
- isString,
1668
- isNumber,
1669
- isObject,
1670
- isPlainObject,
1671
- isUndefined,
1672
- isDate,
1673
- isFile,
1674
- isBlob,
1675
- isFunction,
1676
- isStream,
1677
- isURLSearchParams,
1678
- isStandardBrowserEnv,
1679
- forEach,
1680
- merge,
1681
- extend,
1682
- trim,
1683
- stripBOM
1684
- };
1685
- }
1686
- });
1687
-
1688
- // node_modules/axios/lib/helpers/buildURL.js
1689
- var require_buildURL = __commonJS({
1690
- "node_modules/axios/lib/helpers/buildURL.js"(exports2, module2) {
1691
- "use strict";
1692
- var utils = require_utils2();
1693
- function encode(val) {
1694
- return encodeURIComponent(val).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+").replace(/%5B/gi, "[").replace(/%5D/gi, "]");
1695
- }
1696
- module2.exports = function buildURL(url, params, paramsSerializer) {
1697
- if (!params) {
1698
- return url;
1699
1053
  }
1700
- var serializedParams;
1701
- if (paramsSerializer) {
1702
- serializedParams = paramsSerializer(params);
1703
- } else if (utils.isURLSearchParams(params)) {
1704
- serializedParams = params.toString();
1705
- } else {
1706
- var parts = [];
1707
- utils.forEach(params, function serialize(val, key) {
1708
- if (val === null || typeof val === "undefined") {
1709
- return;
1710
- }
1711
- if (utils.isArray(val)) {
1712
- key = key + "[]";
1713
- } else {
1714
- val = [val];
1715
- }
1716
- utils.forEach(val, function parseValue(v) {
1717
- if (utils.isDate(v)) {
1718
- v = v.toISOString();
1719
- } else if (utils.isObject(v)) {
1720
- v = JSON.stringify(v);
1721
- }
1722
- parts.push(encode(key) + "=" + encode(v));
1054
+ /**
1055
+ * Handle HTTP request
1056
+ */
1057
+ handleHttpRequest(req, res) {
1058
+ const url = new URL(req.url || "/", `http://${req.headers.host}`);
1059
+ const path = url.pathname;
1060
+ res.setHeader("Access-Control-Allow-Origin", "*");
1061
+ res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
1062
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
1063
+ if (req.method === "OPTIONS") {
1064
+ res.writeHead(204);
1065
+ res.end();
1066
+ return;
1067
+ }
1068
+ if (path === "/" || path === "/index.html") {
1069
+ const { getWebClient: getWebClient2 } = (init_web_client(), __toCommonJS(web_client_exports));
1070
+ res.writeHead(200, {
1071
+ "Content-Type": "text/html; charset=utf-8",
1072
+ "Content-Security-Policy": "default-src 'self' 'unsafe-inline' 'unsafe-eval' https: data: ws: wss:"
1723
1073
  });
1724
- });
1725
- serializedParams = parts.join("&");
1726
- }
1727
- if (serializedParams) {
1728
- var hashmarkIndex = url.indexOf("#");
1729
- if (hashmarkIndex !== -1) {
1730
- url = url.slice(0, hashmarkIndex);
1074
+ res.end(getWebClient2());
1075
+ return;
1731
1076
  }
1732
- url += (url.indexOf("?") === -1 ? "?" : "&") + serializedParams;
1733
- }
1734
- return url;
1735
- };
1736
- }
1737
- });
1738
-
1739
- // node_modules/axios/lib/core/InterceptorManager.js
1740
- var require_InterceptorManager = __commonJS({
1741
- "node_modules/axios/lib/core/InterceptorManager.js"(exports2, module2) {
1742
- "use strict";
1743
- var utils = require_utils2();
1744
- function InterceptorManager() {
1745
- this.handlers = [];
1746
- }
1747
- InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
1748
- this.handlers.push({
1749
- fulfilled,
1750
- rejected,
1751
- synchronous: options ? options.synchronous : false,
1752
- runWhen: options ? options.runWhen : null
1753
- });
1754
- return this.handlers.length - 1;
1755
- };
1756
- InterceptorManager.prototype.eject = function eject(id) {
1757
- if (this.handlers[id]) {
1758
- this.handlers[id] = null;
1077
+ if (path === "/health") {
1078
+ res.writeHead(200, { "Content-Type": "application/json" });
1079
+ res.end(JSON.stringify({ status: "ok", session: this.session?.id }));
1080
+ return;
1081
+ }
1082
+ if (path === "/api/session") {
1083
+ res.writeHead(200, { "Content-Type": "application/json" });
1084
+ res.end(
1085
+ JSON.stringify({
1086
+ id: this.session?.id,
1087
+ name: this.session?.name,
1088
+ status: this.session?.status,
1089
+ connectedDevices: this.session?.connectedDevices.length
1090
+ })
1091
+ );
1092
+ return;
1093
+ }
1094
+ res.writeHead(404, { "Content-Type": "text/plain" });
1095
+ res.end("Not Found");
1759
1096
  }
1760
- };
1761
- InterceptorManager.prototype.forEach = function forEach(fn) {
1762
- utils.forEach(this.handlers, function forEachHandler(h) {
1763
- if (h !== null) {
1764
- fn(h);
1097
+ /**
1098
+ * Start heartbeat
1099
+ */
1100
+ startHeartbeat() {
1101
+ this.heartbeatTimer = setInterval(() => {
1102
+ const now = Date.now();
1103
+ for (const [id, client] of this.clients) {
1104
+ if (now - client.lastPing > this.config.heartbeatInterval * 2) {
1105
+ client.ws.terminate();
1106
+ this.clients.delete(id);
1107
+ } else if (client.ws.readyState === import_ws.WebSocket.OPEN) {
1108
+ client.ws.ping();
1109
+ }
1110
+ }
1111
+ }, this.config.heartbeatInterval);
1112
+ }
1113
+ /**
1114
+ * Start session timeout
1115
+ */
1116
+ startSessionTimeout() {
1117
+ this.sessionTimeoutTimer = setTimeout(() => {
1118
+ if (this.session?.connectedDevices.length === 0) {
1119
+ this.stop();
1120
+ }
1121
+ }, this.config.sessionTimeout);
1122
+ }
1123
+ /**
1124
+ * Reset session timeout
1125
+ */
1126
+ resetSessionTimeout() {
1127
+ if (this.sessionTimeoutTimer) {
1128
+ clearTimeout(this.sessionTimeoutTimer);
1765
1129
  }
1766
- });
1767
- };
1768
- module2.exports = InterceptorManager;
1769
- }
1770
- });
1771
-
1772
- // node_modules/axios/lib/helpers/normalizeHeaderName.js
1773
- var require_normalizeHeaderName = __commonJS({
1774
- "node_modules/axios/lib/helpers/normalizeHeaderName.js"(exports2, module2) {
1775
- "use strict";
1776
- var utils = require_utils2();
1777
- module2.exports = function normalizeHeaderName(headers, normalizedName) {
1778
- utils.forEach(headers, function processHeader(value, name) {
1779
- if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
1780
- headers[normalizedName] = value;
1781
- delete headers[name];
1130
+ if (this.config.sessionTimeout > 0) {
1131
+ this.startSessionTimeout();
1782
1132
  }
1783
- });
1784
- };
1785
- }
1786
- });
1787
-
1788
- // node_modules/axios/lib/core/enhanceError.js
1789
- var require_enhanceError = __commonJS({
1790
- "node_modules/axios/lib/core/enhanceError.js"(exports2, module2) {
1791
- "use strict";
1792
- module2.exports = function enhanceError(error, config, code, request, response) {
1793
- error.config = config;
1794
- if (code) {
1795
- error.code = code;
1796
1133
  }
1797
- error.request = request;
1798
- error.response = response;
1799
- error.isAxiosError = true;
1800
- error.toJSON = function toJSON() {
1801
- return {
1802
- // Standard
1803
- message: this.message,
1804
- name: this.name,
1805
- // Microsoft
1806
- description: this.description,
1807
- number: this.number,
1808
- // Mozilla
1809
- fileName: this.fileName,
1810
- lineNumber: this.lineNumber,
1811
- columnNumber: this.columnNumber,
1812
- stack: this.stack,
1813
- // Axios
1814
- config: this.config,
1815
- code: this.code
1816
- };
1817
- };
1818
- return error;
1134
+ /**
1135
+ * Get local IP
1136
+ */
1137
+ getLocalIP() {
1138
+ const interfaces = import_node_os.default.networkInterfaces();
1139
+ for (const name of Object.keys(interfaces)) {
1140
+ for (const iface of interfaces[name] || []) {
1141
+ if (iface.family === "IPv4" && !iface.internal) {
1142
+ return iface.address;
1143
+ }
1144
+ }
1145
+ }
1146
+ return "127.0.0.1";
1147
+ }
1148
+ /**
1149
+ * Generate session ID
1150
+ */
1151
+ generateSessionId() {
1152
+ return import_node_crypto.default.randomBytes(4).toString("hex");
1153
+ }
1154
+ /**
1155
+ * Generate client ID
1156
+ */
1157
+ generateClientId() {
1158
+ return "c_" + import_node_crypto.default.randomBytes(4).toString("hex");
1159
+ }
1819
1160
  };
1820
1161
  }
1821
1162
  });
1822
1163
 
1823
- // node_modules/axios/lib/core/createError.js
1824
- var require_createError = __commonJS({
1825
- "node_modules/axios/lib/core/createError.js"(exports2, module2) {
1164
+ // node_modules/axios/lib/helpers/bind.js
1165
+ var require_bind = __commonJS({
1166
+ "node_modules/axios/lib/helpers/bind.js"(exports2, module2) {
1826
1167
  "use strict";
1827
- var enhanceError = require_enhanceError();
1828
- module2.exports = function createError(message, config, code, request, response) {
1829
- var error = new Error(message);
1830
- return enhanceError(error, config, code, request, response);
1168
+ module2.exports = function bind(fn, thisArg) {
1169
+ return function wrap() {
1170
+ var args = new Array(arguments.length);
1171
+ for (var i = 0; i < args.length; i++) {
1172
+ args[i] = arguments[i];
1173
+ }
1174
+ return fn.apply(thisArg, args);
1175
+ };
1831
1176
  };
1832
1177
  }
1833
1178
  });
1834
1179
 
1835
- // node_modules/axios/lib/core/settle.js
1836
- var require_settle = __commonJS({
1837
- "node_modules/axios/lib/core/settle.js"(exports2, module2) {
1180
+ // node_modules/axios/lib/utils.js
1181
+ var require_utils = __commonJS({
1182
+ "node_modules/axios/lib/utils.js"(exports2, module2) {
1838
1183
  "use strict";
1839
- var createError = require_createError();
1840
- module2.exports = function settle(resolve, reject, response) {
1841
- var validateStatus = response.config.validateStatus;
1842
- if (!response.status || !validateStatus || validateStatus(response.status)) {
1843
- resolve(response);
1184
+ var bind = require_bind();
1185
+ var toString = Object.prototype.toString;
1186
+ function isArray(val) {
1187
+ return toString.call(val) === "[object Array]";
1188
+ }
1189
+ function isUndefined(val) {
1190
+ return typeof val === "undefined";
1191
+ }
1192
+ function isBuffer(val) {
1193
+ return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) && typeof val.constructor.isBuffer === "function" && val.constructor.isBuffer(val);
1194
+ }
1195
+ function isArrayBuffer(val) {
1196
+ return toString.call(val) === "[object ArrayBuffer]";
1197
+ }
1198
+ function isFormData(val) {
1199
+ return typeof FormData !== "undefined" && val instanceof FormData;
1200
+ }
1201
+ function isArrayBufferView(val) {
1202
+ var result;
1203
+ if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView) {
1204
+ result = ArrayBuffer.isView(val);
1844
1205
  } else {
1845
- reject(createError(
1846
- "Request failed with status code " + response.status,
1847
- response.config,
1848
- null,
1849
- response.request,
1850
- response
1851
- ));
1206
+ result = val && val.buffer && val.buffer instanceof ArrayBuffer;
1852
1207
  }
1853
- };
1854
- }
1855
- });
1856
-
1857
- // node_modules/axios/lib/helpers/cookies.js
1858
- var require_cookies = __commonJS({
1859
- "node_modules/axios/lib/helpers/cookies.js"(exports2, module2) {
1860
- "use strict";
1861
- var utils = require_utils2();
1862
- module2.exports = utils.isStandardBrowserEnv() ? (
1863
- // Standard browser envs support document.cookie
1864
- /* @__PURE__ */ (function standardBrowserEnv() {
1865
- return {
1866
- write: function write(name, value, expires, path, domain, secure) {
1867
- var cookie = [];
1868
- cookie.push(name + "=" + encodeURIComponent(value));
1869
- if (utils.isNumber(expires)) {
1870
- cookie.push("expires=" + new Date(expires).toGMTString());
1871
- }
1872
- if (utils.isString(path)) {
1873
- cookie.push("path=" + path);
1874
- }
1875
- if (utils.isString(domain)) {
1876
- cookie.push("domain=" + domain);
1877
- }
1878
- if (secure === true) {
1879
- cookie.push("secure");
1880
- }
1881
- document.cookie = cookie.join("; ");
1882
- },
1883
- read: function read(name) {
1884
- var match = document.cookie.match(new RegExp("(^|;\\s*)(" + name + ")=([^;]*)"));
1885
- return match ? decodeURIComponent(match[3]) : null;
1886
- },
1887
- remove: function remove(name) {
1888
- this.write(name, "", Date.now() - 864e5);
1889
- }
1890
- };
1891
- })()
1892
- ) : (
1893
- // Non standard browser env (web workers, react-native) lack needed support.
1894
- /* @__PURE__ */ (function nonStandardBrowserEnv() {
1895
- return {
1896
- write: function write() {
1897
- },
1898
- read: function read() {
1899
- return null;
1900
- },
1901
- remove: function remove() {
1208
+ return result;
1209
+ }
1210
+ function isString(val) {
1211
+ return typeof val === "string";
1212
+ }
1213
+ function isNumber(val) {
1214
+ return typeof val === "number";
1215
+ }
1216
+ function isObject(val) {
1217
+ return val !== null && typeof val === "object";
1218
+ }
1219
+ function isPlainObject(val) {
1220
+ if (toString.call(val) !== "[object Object]") {
1221
+ return false;
1222
+ }
1223
+ var prototype = Object.getPrototypeOf(val);
1224
+ return prototype === null || prototype === Object.prototype;
1225
+ }
1226
+ function isDate(val) {
1227
+ return toString.call(val) === "[object Date]";
1228
+ }
1229
+ function isFile(val) {
1230
+ return toString.call(val) === "[object File]";
1231
+ }
1232
+ function isBlob(val) {
1233
+ return toString.call(val) === "[object Blob]";
1234
+ }
1235
+ function isFunction(val) {
1236
+ return toString.call(val) === "[object Function]";
1237
+ }
1238
+ function isStream(val) {
1239
+ return isObject(val) && isFunction(val.pipe);
1240
+ }
1241
+ function isURLSearchParams(val) {
1242
+ return typeof URLSearchParams !== "undefined" && val instanceof URLSearchParams;
1243
+ }
1244
+ function trim(str) {
1245
+ return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, "");
1246
+ }
1247
+ function isStandardBrowserEnv() {
1248
+ if (typeof navigator !== "undefined" && (navigator.product === "ReactNative" || navigator.product === "NativeScript" || navigator.product === "NS")) {
1249
+ return false;
1250
+ }
1251
+ return typeof window !== "undefined" && typeof document !== "undefined";
1252
+ }
1253
+ function forEach(obj, fn) {
1254
+ if (obj === null || typeof obj === "undefined") {
1255
+ return;
1256
+ }
1257
+ if (typeof obj !== "object") {
1258
+ obj = [obj];
1259
+ }
1260
+ if (isArray(obj)) {
1261
+ for (var i = 0, l = obj.length; i < l; i++) {
1262
+ fn.call(null, obj[i], i, obj);
1263
+ }
1264
+ } else {
1265
+ for (var key in obj) {
1266
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
1267
+ fn.call(null, obj[key], key, obj);
1902
1268
  }
1903
- };
1904
- })()
1905
- );
1269
+ }
1270
+ }
1271
+ }
1272
+ function merge() {
1273
+ var result = {};
1274
+ function assignValue(val, key) {
1275
+ if (isPlainObject(result[key]) && isPlainObject(val)) {
1276
+ result[key] = merge(result[key], val);
1277
+ } else if (isPlainObject(val)) {
1278
+ result[key] = merge({}, val);
1279
+ } else if (isArray(val)) {
1280
+ result[key] = val.slice();
1281
+ } else {
1282
+ result[key] = val;
1283
+ }
1284
+ }
1285
+ for (var i = 0, l = arguments.length; i < l; i++) {
1286
+ forEach(arguments[i], assignValue);
1287
+ }
1288
+ return result;
1289
+ }
1290
+ function extend(a, b, thisArg) {
1291
+ forEach(b, function assignValue(val, key) {
1292
+ if (thisArg && typeof val === "function") {
1293
+ a[key] = bind(val, thisArg);
1294
+ } else {
1295
+ a[key] = val;
1296
+ }
1297
+ });
1298
+ return a;
1299
+ }
1300
+ function stripBOM(content) {
1301
+ if (content.charCodeAt(0) === 65279) {
1302
+ content = content.slice(1);
1303
+ }
1304
+ return content;
1305
+ }
1306
+ module2.exports = {
1307
+ isArray,
1308
+ isArrayBuffer,
1309
+ isBuffer,
1310
+ isFormData,
1311
+ isArrayBufferView,
1312
+ isString,
1313
+ isNumber,
1314
+ isObject,
1315
+ isPlainObject,
1316
+ isUndefined,
1317
+ isDate,
1318
+ isFile,
1319
+ isBlob,
1320
+ isFunction,
1321
+ isStream,
1322
+ isURLSearchParams,
1323
+ isStandardBrowserEnv,
1324
+ forEach,
1325
+ merge,
1326
+ extend,
1327
+ trim,
1328
+ stripBOM
1329
+ };
1906
1330
  }
1907
1331
  });
1908
1332
 
1909
- // node_modules/axios/lib/helpers/isAbsoluteURL.js
1910
- var require_isAbsoluteURL = __commonJS({
1911
- "node_modules/axios/lib/helpers/isAbsoluteURL.js"(exports2, module2) {
1333
+ // node_modules/axios/lib/helpers/buildURL.js
1334
+ var require_buildURL = __commonJS({
1335
+ "node_modules/axios/lib/helpers/buildURL.js"(exports2, module2) {
1912
1336
  "use strict";
1913
- module2.exports = function isAbsoluteURL(url) {
1914
- return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
1337
+ var utils = require_utils();
1338
+ function encode(val) {
1339
+ return encodeURIComponent(val).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+").replace(/%5B/gi, "[").replace(/%5D/gi, "]");
1340
+ }
1341
+ module2.exports = function buildURL(url, params, paramsSerializer) {
1342
+ if (!params) {
1343
+ return url;
1344
+ }
1345
+ var serializedParams;
1346
+ if (paramsSerializer) {
1347
+ serializedParams = paramsSerializer(params);
1348
+ } else if (utils.isURLSearchParams(params)) {
1349
+ serializedParams = params.toString();
1350
+ } else {
1351
+ var parts = [];
1352
+ utils.forEach(params, function serialize(val, key) {
1353
+ if (val === null || typeof val === "undefined") {
1354
+ return;
1355
+ }
1356
+ if (utils.isArray(val)) {
1357
+ key = key + "[]";
1358
+ } else {
1359
+ val = [val];
1360
+ }
1361
+ utils.forEach(val, function parseValue(v) {
1362
+ if (utils.isDate(v)) {
1363
+ v = v.toISOString();
1364
+ } else if (utils.isObject(v)) {
1365
+ v = JSON.stringify(v);
1366
+ }
1367
+ parts.push(encode(key) + "=" + encode(v));
1368
+ });
1369
+ });
1370
+ serializedParams = parts.join("&");
1371
+ }
1372
+ if (serializedParams) {
1373
+ var hashmarkIndex = url.indexOf("#");
1374
+ if (hashmarkIndex !== -1) {
1375
+ url = url.slice(0, hashmarkIndex);
1376
+ }
1377
+ url += (url.indexOf("?") === -1 ? "?" : "&") + serializedParams;
1378
+ }
1379
+ return url;
1915
1380
  };
1916
1381
  }
1917
1382
  });
1918
1383
 
1919
- // node_modules/axios/lib/helpers/combineURLs.js
1920
- var require_combineURLs = __commonJS({
1921
- "node_modules/axios/lib/helpers/combineURLs.js"(exports2, module2) {
1384
+ // node_modules/axios/lib/core/InterceptorManager.js
1385
+ var require_InterceptorManager = __commonJS({
1386
+ "node_modules/axios/lib/core/InterceptorManager.js"(exports2, module2) {
1922
1387
  "use strict";
1923
- module2.exports = function combineURLs(baseURL, relativeURL) {
1924
- return relativeURL ? baseURL.replace(/\/+$/, "") + "/" + relativeURL.replace(/^\/+/, "") : baseURL;
1388
+ var utils = require_utils();
1389
+ function InterceptorManager() {
1390
+ this.handlers = [];
1391
+ }
1392
+ InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
1393
+ this.handlers.push({
1394
+ fulfilled,
1395
+ rejected,
1396
+ synchronous: options ? options.synchronous : false,
1397
+ runWhen: options ? options.runWhen : null
1398
+ });
1399
+ return this.handlers.length - 1;
1400
+ };
1401
+ InterceptorManager.prototype.eject = function eject(id) {
1402
+ if (this.handlers[id]) {
1403
+ this.handlers[id] = null;
1404
+ }
1405
+ };
1406
+ InterceptorManager.prototype.forEach = function forEach(fn) {
1407
+ utils.forEach(this.handlers, function forEachHandler(h) {
1408
+ if (h !== null) {
1409
+ fn(h);
1410
+ }
1411
+ });
1925
1412
  };
1413
+ module2.exports = InterceptorManager;
1926
1414
  }
1927
1415
  });
1928
1416
 
1929
- // node_modules/axios/lib/core/buildFullPath.js
1930
- var require_buildFullPath = __commonJS({
1931
- "node_modules/axios/lib/core/buildFullPath.js"(exports2, module2) {
1417
+ // node_modules/axios/lib/helpers/normalizeHeaderName.js
1418
+ var require_normalizeHeaderName = __commonJS({
1419
+ "node_modules/axios/lib/helpers/normalizeHeaderName.js"(exports2, module2) {
1932
1420
  "use strict";
1933
- var isAbsoluteURL = require_isAbsoluteURL();
1934
- var combineURLs = require_combineURLs();
1935
- module2.exports = function buildFullPath(baseURL, requestedURL) {
1936
- if (baseURL && !isAbsoluteURL(requestedURL)) {
1937
- return combineURLs(baseURL, requestedURL);
1938
- }
1939
- return requestedURL;
1421
+ var utils = require_utils();
1422
+ module2.exports = function normalizeHeaderName(headers, normalizedName) {
1423
+ utils.forEach(headers, function processHeader(value, name) {
1424
+ if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
1425
+ headers[normalizedName] = value;
1426
+ delete headers[name];
1427
+ }
1428
+ });
1940
1429
  };
1941
1430
  }
1942
1431
  });
1943
1432
 
1944
- // node_modules/axios/lib/helpers/parseHeaders.js
1945
- var require_parseHeaders = __commonJS({
1946
- "node_modules/axios/lib/helpers/parseHeaders.js"(exports2, module2) {
1433
+ // node_modules/axios/lib/core/enhanceError.js
1434
+ var require_enhanceError = __commonJS({
1435
+ "node_modules/axios/lib/core/enhanceError.js"(exports2, module2) {
1947
1436
  "use strict";
1948
- var utils = require_utils2();
1949
- var ignoreDuplicateOf = [
1950
- "age",
1951
- "authorization",
1952
- "content-length",
1953
- "content-type",
1954
- "etag",
1955
- "expires",
1956
- "from",
1957
- "host",
1958
- "if-modified-since",
1959
- "if-unmodified-since",
1960
- "last-modified",
1961
- "location",
1962
- "max-forwards",
1963
- "proxy-authorization",
1964
- "referer",
1965
- "retry-after",
1966
- "user-agent"
1437
+ module2.exports = function enhanceError(error, config, code, request, response) {
1438
+ error.config = config;
1439
+ if (code) {
1440
+ error.code = code;
1441
+ }
1442
+ error.request = request;
1443
+ error.response = response;
1444
+ error.isAxiosError = true;
1445
+ error.toJSON = function toJSON() {
1446
+ return {
1447
+ // Standard
1448
+ message: this.message,
1449
+ name: this.name,
1450
+ // Microsoft
1451
+ description: this.description,
1452
+ number: this.number,
1453
+ // Mozilla
1454
+ fileName: this.fileName,
1455
+ lineNumber: this.lineNumber,
1456
+ columnNumber: this.columnNumber,
1457
+ stack: this.stack,
1458
+ // Axios
1459
+ config: this.config,
1460
+ code: this.code
1461
+ };
1462
+ };
1463
+ return error;
1464
+ };
1465
+ }
1466
+ });
1467
+
1468
+ // node_modules/axios/lib/core/createError.js
1469
+ var require_createError = __commonJS({
1470
+ "node_modules/axios/lib/core/createError.js"(exports2, module2) {
1471
+ "use strict";
1472
+ var enhanceError = require_enhanceError();
1473
+ module2.exports = function createError(message, config, code, request, response) {
1474
+ var error = new Error(message);
1475
+ return enhanceError(error, config, code, request, response);
1476
+ };
1477
+ }
1478
+ });
1479
+
1480
+ // node_modules/axios/lib/core/settle.js
1481
+ var require_settle = __commonJS({
1482
+ "node_modules/axios/lib/core/settle.js"(exports2, module2) {
1483
+ "use strict";
1484
+ var createError = require_createError();
1485
+ module2.exports = function settle(resolve, reject, response) {
1486
+ var validateStatus = response.config.validateStatus;
1487
+ if (!response.status || !validateStatus || validateStatus(response.status)) {
1488
+ resolve(response);
1489
+ } else {
1490
+ reject(createError(
1491
+ "Request failed with status code " + response.status,
1492
+ response.config,
1493
+ null,
1494
+ response.request,
1495
+ response
1496
+ ));
1497
+ }
1498
+ };
1499
+ }
1500
+ });
1501
+
1502
+ // node_modules/axios/lib/helpers/cookies.js
1503
+ var require_cookies = __commonJS({
1504
+ "node_modules/axios/lib/helpers/cookies.js"(exports2, module2) {
1505
+ "use strict";
1506
+ var utils = require_utils();
1507
+ module2.exports = utils.isStandardBrowserEnv() ? (
1508
+ // Standard browser envs support document.cookie
1509
+ /* @__PURE__ */ (function standardBrowserEnv() {
1510
+ return {
1511
+ write: function write(name, value, expires, path, domain, secure) {
1512
+ var cookie = [];
1513
+ cookie.push(name + "=" + encodeURIComponent(value));
1514
+ if (utils.isNumber(expires)) {
1515
+ cookie.push("expires=" + new Date(expires).toGMTString());
1516
+ }
1517
+ if (utils.isString(path)) {
1518
+ cookie.push("path=" + path);
1519
+ }
1520
+ if (utils.isString(domain)) {
1521
+ cookie.push("domain=" + domain);
1522
+ }
1523
+ if (secure === true) {
1524
+ cookie.push("secure");
1525
+ }
1526
+ document.cookie = cookie.join("; ");
1527
+ },
1528
+ read: function read(name) {
1529
+ var match = document.cookie.match(new RegExp("(^|;\\s*)(" + name + ")=([^;]*)"));
1530
+ return match ? decodeURIComponent(match[3]) : null;
1531
+ },
1532
+ remove: function remove(name) {
1533
+ this.write(name, "", Date.now() - 864e5);
1534
+ }
1535
+ };
1536
+ })()
1537
+ ) : (
1538
+ // Non standard browser env (web workers, react-native) lack needed support.
1539
+ /* @__PURE__ */ (function nonStandardBrowserEnv() {
1540
+ return {
1541
+ write: function write() {
1542
+ },
1543
+ read: function read() {
1544
+ return null;
1545
+ },
1546
+ remove: function remove() {
1547
+ }
1548
+ };
1549
+ })()
1550
+ );
1551
+ }
1552
+ });
1553
+
1554
+ // node_modules/axios/lib/helpers/isAbsoluteURL.js
1555
+ var require_isAbsoluteURL = __commonJS({
1556
+ "node_modules/axios/lib/helpers/isAbsoluteURL.js"(exports2, module2) {
1557
+ "use strict";
1558
+ module2.exports = function isAbsoluteURL(url) {
1559
+ return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
1560
+ };
1561
+ }
1562
+ });
1563
+
1564
+ // node_modules/axios/lib/helpers/combineURLs.js
1565
+ var require_combineURLs = __commonJS({
1566
+ "node_modules/axios/lib/helpers/combineURLs.js"(exports2, module2) {
1567
+ "use strict";
1568
+ module2.exports = function combineURLs(baseURL, relativeURL) {
1569
+ return relativeURL ? baseURL.replace(/\/+$/, "") + "/" + relativeURL.replace(/^\/+/, "") : baseURL;
1570
+ };
1571
+ }
1572
+ });
1573
+
1574
+ // node_modules/axios/lib/core/buildFullPath.js
1575
+ var require_buildFullPath = __commonJS({
1576
+ "node_modules/axios/lib/core/buildFullPath.js"(exports2, module2) {
1577
+ "use strict";
1578
+ var isAbsoluteURL = require_isAbsoluteURL();
1579
+ var combineURLs = require_combineURLs();
1580
+ module2.exports = function buildFullPath(baseURL, requestedURL) {
1581
+ if (baseURL && !isAbsoluteURL(requestedURL)) {
1582
+ return combineURLs(baseURL, requestedURL);
1583
+ }
1584
+ return requestedURL;
1585
+ };
1586
+ }
1587
+ });
1588
+
1589
+ // node_modules/axios/lib/helpers/parseHeaders.js
1590
+ var require_parseHeaders = __commonJS({
1591
+ "node_modules/axios/lib/helpers/parseHeaders.js"(exports2, module2) {
1592
+ "use strict";
1593
+ var utils = require_utils();
1594
+ var ignoreDuplicateOf = [
1595
+ "age",
1596
+ "authorization",
1597
+ "content-length",
1598
+ "content-type",
1599
+ "etag",
1600
+ "expires",
1601
+ "from",
1602
+ "host",
1603
+ "if-modified-since",
1604
+ "if-unmodified-since",
1605
+ "last-modified",
1606
+ "location",
1607
+ "max-forwards",
1608
+ "proxy-authorization",
1609
+ "referer",
1610
+ "retry-after",
1611
+ "user-agent"
1967
1612
  ];
1968
1613
  module2.exports = function parseHeaders(headers) {
1969
1614
  var parsed = {};
@@ -1997,7 +1642,7 @@ var require_parseHeaders = __commonJS({
1997
1642
  var require_isURLSameOrigin = __commonJS({
1998
1643
  "node_modules/axios/lib/helpers/isURLSameOrigin.js"(exports2, module2) {
1999
1644
  "use strict";
2000
- var utils = require_utils2();
1645
+ var utils = require_utils();
2001
1646
  module2.exports = utils.isStandardBrowserEnv() ? (
2002
1647
  // Standard browser envs have full support of the APIs needed to test
2003
1648
  // whether the request URL is of the same origin as current location.
@@ -2044,7 +1689,7 @@ var require_isURLSameOrigin = __commonJS({
2044
1689
  var require_xhr = __commonJS({
2045
1690
  "node_modules/axios/lib/adapters/xhr.js"(exports2, module2) {
2046
1691
  "use strict";
2047
- var utils = require_utils2();
1692
+ var utils = require_utils();
2048
1693
  var settle = require_settle();
2049
1694
  var cookies = require_cookies();
2050
1695
  var buildURL = require_buildURL();
@@ -3549,7 +3194,7 @@ var require_package = __commonJS({
3549
3194
  var require_http = __commonJS({
3550
3195
  "node_modules/axios/lib/adapters/http.js"(exports2, module2) {
3551
3196
  "use strict";
3552
- var utils = require_utils2();
3197
+ var utils = require_utils();
3553
3198
  var settle = require_settle();
3554
3199
  var buildFullPath = require_buildFullPath();
3555
3200
  var buildURL = require_buildURL();
@@ -3809,7 +3454,7 @@ var require_http = __commonJS({
3809
3454
  var require_defaults = __commonJS({
3810
3455
  "node_modules/axios/lib/defaults.js"(exports2, module2) {
3811
3456
  "use strict";
3812
- var utils = require_utils2();
3457
+ var utils = require_utils();
3813
3458
  var normalizeHeaderName = require_normalizeHeaderName();
3814
3459
  var enhanceError = require_enhanceError();
3815
3460
  var DEFAULT_CONTENT_TYPE = {
@@ -3919,7 +3564,7 @@ var require_defaults = __commonJS({
3919
3564
  var require_transformData = __commonJS({
3920
3565
  "node_modules/axios/lib/core/transformData.js"(exports2, module2) {
3921
3566
  "use strict";
3922
- var utils = require_utils2();
3567
+ var utils = require_utils();
3923
3568
  var defaults = require_defaults();
3924
3569
  module2.exports = function transformData(data, headers, fns) {
3925
3570
  var context = this || defaults;
@@ -3945,7 +3590,7 @@ var require_isCancel = __commonJS({
3945
3590
  var require_dispatchRequest = __commonJS({
3946
3591
  "node_modules/axios/lib/core/dispatchRequest.js"(exports2, module2) {
3947
3592
  "use strict";
3948
- var utils = require_utils2();
3593
+ var utils = require_utils();
3949
3594
  var transformData = require_transformData();
3950
3595
  var isCancel = require_isCancel();
3951
3596
  var defaults = require_defaults();
@@ -4006,7 +3651,7 @@ var require_dispatchRequest = __commonJS({
4006
3651
  var require_mergeConfig = __commonJS({
4007
3652
  "node_modules/axios/lib/core/mergeConfig.js"(exports2, module2) {
4008
3653
  "use strict";
4009
- var utils = require_utils2();
3654
+ var utils = require_utils();
4010
3655
  module2.exports = function mergeConfig(config1, config2) {
4011
3656
  config2 = config2 || {};
4012
3657
  var config = {};
@@ -4165,7 +3810,7 @@ var require_validator = __commonJS({
4165
3810
  var require_Axios = __commonJS({
4166
3811
  "node_modules/axios/lib/core/Axios.js"(exports2, module2) {
4167
3812
  "use strict";
4168
- var utils = require_utils2();
3813
+ var utils = require_utils();
4169
3814
  var buildURL = require_buildURL();
4170
3815
  var InterceptorManager = require_InterceptorManager();
4171
3816
  var dispatchRequest = require_dispatchRequest();
@@ -4355,7 +4000,7 @@ var require_isAxiosError = __commonJS({
4355
4000
  var require_axios = __commonJS({
4356
4001
  "node_modules/axios/lib/axios.js"(exports2, module2) {
4357
4002
  "use strict";
4358
- var utils = require_utils2();
4003
+ var utils = require_utils();
4359
4004
  var bind = require_bind();
4360
4005
  var Axios = require_Axios();
4361
4006
  var mergeConfig = require_mergeConfig();
@@ -5060,13 +4705,13 @@ var require_HeaderHostTransformer = __commonJS({
5060
4705
  var require_TunnelCluster = __commonJS({
5061
4706
  "node_modules/localtunnel/lib/TunnelCluster.js"(exports2, module2) {
5062
4707
  "use strict";
5063
- var { EventEmitter: EventEmitter3 } = require("events");
4708
+ var { EventEmitter: EventEmitter2 } = require("events");
5064
4709
  var debug = require_src2()("localtunnel:client");
5065
4710
  var fs = require("fs");
5066
4711
  var net = require("net");
5067
4712
  var tls = require("tls");
5068
4713
  var HeaderHostTransformer = require_HeaderHostTransformer();
5069
- module2.exports = class TunnelCluster extends EventEmitter3 {
4714
+ module2.exports = class TunnelCluster extends EventEmitter2 {
5070
4715
  constructor(opts = {}) {
5071
4716
  super(opts);
5072
4717
  this.opts = opts;
@@ -5138,1111 +4783,181 @@ var require_TunnelCluster = __commonJS({
5138
4783
  });
5139
4784
  local.once("connect", () => {
5140
4785
  debug("connected locally");
5141
- remote.resume();
5142
- let stream = remote;
5143
- if (opt.local_host) {
5144
- debug("transform Host header to %s", opt.local_host);
5145
- stream = remote.pipe(new HeaderHostTransformer({ host: opt.local_host }));
5146
- }
5147
- stream.pipe(local).pipe(remote);
5148
- local.once("close", (hadError) => {
5149
- debug("local connection closed [%s]", hadError);
5150
- });
5151
- });
5152
- };
5153
- remote.on("data", (data) => {
5154
- const match = data.toString().match(/^(\w+) (\S+)/);
5155
- if (match) {
5156
- this.emit("request", {
5157
- method: match[1],
5158
- path: match[2]
5159
- });
5160
- }
5161
- });
5162
- remote.once("connect", () => {
5163
- this.emit("open", remote);
5164
- connLocal();
5165
- });
5166
- }
5167
- };
5168
- }
5169
- });
5170
-
5171
- // node_modules/localtunnel/lib/Tunnel.js
5172
- var require_Tunnel = __commonJS({
5173
- "node_modules/localtunnel/lib/Tunnel.js"(exports2, module2) {
5174
- "use strict";
5175
- var { parse } = require("url");
5176
- var { EventEmitter: EventEmitter3 } = require("events");
5177
- var axios = require_axios2();
5178
- var debug = require_src2()("localtunnel:client");
5179
- var TunnelCluster = require_TunnelCluster();
5180
- module2.exports = class Tunnel extends EventEmitter3 {
5181
- constructor(opts = {}) {
5182
- super(opts);
5183
- this.opts = opts;
5184
- this.closed = false;
5185
- if (!this.opts.host) {
5186
- this.opts.host = "https://localtunnel.me";
5187
- }
5188
- }
5189
- _getInfo(body) {
5190
- const { id, ip, port, url, cached_url, max_conn_count } = body;
5191
- const { host, port: local_port, local_host } = this.opts;
5192
- const { local_https, local_cert, local_key, local_ca, allow_invalid_cert } = this.opts;
5193
- return {
5194
- name: id,
5195
- url,
5196
- cached_url,
5197
- max_conn: max_conn_count || 1,
5198
- remote_host: parse(host).hostname,
5199
- remote_ip: ip,
5200
- remote_port: port,
5201
- local_port,
5202
- local_host,
5203
- local_https,
5204
- local_cert,
5205
- local_key,
5206
- local_ca,
5207
- allow_invalid_cert
5208
- };
5209
- }
5210
- // initialize connection
5211
- // callback with connection info
5212
- _init(cb) {
5213
- const opt = this.opts;
5214
- const getInfo = this._getInfo.bind(this);
5215
- const params = {
5216
- responseType: "json"
5217
- };
5218
- const baseUri = `${opt.host}/`;
5219
- const assignedDomain = opt.subdomain;
5220
- const uri = baseUri + (assignedDomain || "?new");
5221
- (function getUrl() {
5222
- axios.get(uri, params).then((res) => {
5223
- const body = res.data;
5224
- debug("got tunnel information", res.data);
5225
- if (res.status !== 200) {
5226
- const err = new Error(
5227
- body && body.message || "localtunnel server returned an error, please try again"
5228
- );
5229
- return cb(err);
5230
- }
5231
- cb(null, getInfo(body));
5232
- }).catch((err) => {
5233
- debug(`tunnel server offline: ${err.message}, retry 1s`);
5234
- return setTimeout(getUrl, 1e3);
5235
- });
5236
- })();
5237
- }
5238
- _establish(info) {
5239
- this.setMaxListeners(info.max_conn + (EventEmitter3.defaultMaxListeners || 10));
5240
- this.tunnelCluster = new TunnelCluster(info);
5241
- this.tunnelCluster.once("open", () => {
5242
- this.emit("url", info.url);
5243
- });
5244
- this.tunnelCluster.on("error", (err) => {
5245
- debug("got socket error", err.message);
5246
- this.emit("error", err);
5247
- });
5248
- let tunnelCount = 0;
5249
- this.tunnelCluster.on("open", (tunnel) => {
5250
- tunnelCount++;
5251
- debug("tunnel open [total: %d]", tunnelCount);
5252
- const closeHandler = () => {
5253
- tunnel.destroy();
5254
- };
5255
- if (this.closed) {
5256
- return closeHandler();
5257
- }
5258
- this.once("close", closeHandler);
5259
- tunnel.once("close", () => {
5260
- this.removeListener("close", closeHandler);
5261
- });
5262
- });
5263
- this.tunnelCluster.on("dead", () => {
5264
- tunnelCount--;
5265
- debug("tunnel dead [total: %d]", tunnelCount);
5266
- if (this.closed) {
5267
- return;
5268
- }
5269
- this.tunnelCluster.open();
5270
- });
5271
- this.tunnelCluster.on("request", (req) => {
5272
- this.emit("request", req);
5273
- });
5274
- for (let count = 0; count < info.max_conn; ++count) {
5275
- this.tunnelCluster.open();
5276
- }
5277
- }
5278
- open(cb) {
5279
- this._init((err, info) => {
5280
- if (err) {
5281
- return cb(err);
5282
- }
5283
- this.clientId = info.name;
5284
- this.url = info.url;
5285
- if (info.cached_url) {
5286
- this.cachedUrl = info.cached_url;
5287
- }
5288
- this._establish(info);
5289
- cb();
5290
- });
5291
- }
5292
- close() {
5293
- this.closed = true;
5294
- this.emit("close");
5295
- }
5296
- };
5297
- }
5298
- });
5299
-
5300
- // node_modules/localtunnel/localtunnel.js
5301
- var require_localtunnel = __commonJS({
5302
- "node_modules/localtunnel/localtunnel.js"(exports2, module2) {
5303
- "use strict";
5304
- var Tunnel = require_Tunnel();
5305
- module2.exports = function localtunnel(arg1, arg2, arg3) {
5306
- const options = typeof arg1 === "object" ? arg1 : { ...arg2, port: arg1 };
5307
- const callback = typeof arg1 === "object" ? arg2 : arg3;
5308
- const client = new Tunnel(options);
5309
- if (callback) {
5310
- client.open((err) => err ? callback(err) : callback(null, client));
5311
- return client;
5312
- }
5313
- return new Promise(
5314
- (resolve, reject) => client.open((err) => err ? reject(err) : resolve(client))
5315
- );
5316
- };
5317
- }
5318
- });
5319
-
5320
- // src/tunnel.ts
5321
- var import_node_child_process2, TunnelManager;
5322
- var init_tunnel = __esm({
5323
- "src/tunnel.ts"() {
5324
- "use strict";
5325
- import_node_child_process2 = require("child_process");
5326
- TunnelManager = class {
5327
- provider;
5328
- process = null;
5329
- url = null;
5330
- tunnelInstance = null;
5331
- constructor(provider) {
5332
- this.provider = provider;
5333
- }
5334
- /**
5335
- * Create tunnel and return public URL
5336
- */
5337
- async create(port) {
5338
- switch (this.provider) {
5339
- case "localtunnel":
5340
- return this.createLocaltunnel(port);
5341
- case "cloudflared":
5342
- return this.createCloudflared(port);
5343
- case "ngrok":
5344
- return this.createNgrok(port);
5345
- default:
5346
- throw new Error(`Unknown tunnel provider: ${this.provider}`);
5347
- }
5348
- }
5349
- /**
5350
- * Close tunnel
5351
- */
5352
- async close() {
5353
- if (this.tunnelInstance?.close) {
5354
- this.tunnelInstance.close();
5355
- this.tunnelInstance = null;
5356
- }
5357
- if (this.process) {
5358
- this.process.kill();
5359
- this.process = null;
5360
- }
5361
- this.url = null;
5362
- }
5363
- /**
5364
- * Get tunnel URL
5365
- */
5366
- getUrl() {
5367
- return this.url;
5368
- }
5369
- /**
5370
- * Create localtunnel
5371
- */
5372
- async createLocaltunnel(port) {
5373
- try {
5374
- const localtunnel = await Promise.resolve().then(() => __toESM(require_localtunnel(), 1));
5375
- const tunnel = await localtunnel.default({ port });
5376
- this.tunnelInstance = tunnel;
5377
- this.url = tunnel.url;
5378
- tunnel.on("close", () => {
5379
- this.url = null;
5380
- });
5381
- return tunnel.url;
5382
- } catch {
5383
- return this.createLocaltunnelCli(port);
5384
- }
5385
- }
5386
- /**
5387
- * Create localtunnel via CLI
5388
- */
5389
- createLocaltunnelCli(port) {
5390
- return new Promise((resolve, reject) => {
5391
- this.process = (0, import_node_child_process2.spawn)("npx", ["localtunnel", "--port", port.toString(), "--print-requests", "false"], {
5392
- stdio: ["pipe", "pipe", "pipe"],
5393
- shell: true
5394
- });
5395
- let output = "";
5396
- const timeout = setTimeout(() => {
5397
- reject(new Error("Localtunnel timeout"));
5398
- }, 3e4);
5399
- this.process.stdout?.on("data", (data) => {
5400
- output += data.toString();
5401
- const match = output.match(/your url is:\s*(https?:\/\/[^\s]+)/i);
5402
- if (match) {
5403
- clearTimeout(timeout);
5404
- this.url = match[1];
5405
- resolve(match[1]);
5406
- }
5407
- });
5408
- this.process.stderr?.on("data", () => {
5409
- });
5410
- this.process.on("error", (error) => {
5411
- clearTimeout(timeout);
5412
- reject(error);
5413
- });
5414
- this.process.on("exit", (code) => {
5415
- if (code !== 0 && !this.url) {
5416
- clearTimeout(timeout);
5417
- reject(new Error(`Localtunnel exited with code ${code}`));
5418
- }
5419
- });
5420
- });
5421
- }
5422
- /**
5423
- * Create cloudflared tunnel
5424
- */
5425
- createCloudflared(port) {
5426
- return new Promise((resolve, reject) => {
5427
- this.process = (0, import_node_child_process2.spawn)(
5428
- "cloudflared",
5429
- ["tunnel", "--url", `http://localhost:${port}`, "--metrics", "localhost:0"],
5430
- {
5431
- stdio: ["pipe", "pipe", "pipe"]
5432
- }
5433
- );
5434
- let output = "";
5435
- const timeout = setTimeout(() => {
5436
- reject(new Error("Cloudflared timeout"));
5437
- }, 3e4);
5438
- const handleData = (data) => {
5439
- output += data.toString();
5440
- const match = output.match(/(https:\/\/[^\s]+\.trycloudflare\.com)/i);
5441
- if (match) {
5442
- clearTimeout(timeout);
5443
- this.url = match[1];
5444
- resolve(match[1]);
5445
- }
5446
- };
5447
- this.process.stdout?.on("data", handleData);
5448
- this.process.stderr?.on("data", handleData);
5449
- this.process.on("error", (error) => {
5450
- clearTimeout(timeout);
5451
- reject(error);
5452
- });
5453
- this.process.on("exit", (code) => {
5454
- if (code !== 0 && !this.url) {
5455
- clearTimeout(timeout);
5456
- reject(new Error(`Cloudflared exited with code ${code}`));
5457
- }
5458
- });
5459
- });
5460
- }
5461
- /**
5462
- * Create ngrok tunnel
5463
- */
5464
- createNgrok(port) {
5465
- return new Promise((resolve, reject) => {
5466
- this.process = (0, import_node_child_process2.spawn)("ngrok", ["http", port.toString(), "--log=stdout", "--log-level=info"], {
5467
- stdio: ["pipe", "pipe", "pipe"]
5468
- });
5469
- let output = "";
5470
- const timeout = setTimeout(() => {
5471
- reject(new Error("Ngrok timeout"));
5472
- }, 3e4);
5473
- this.process.stdout?.on("data", (data) => {
5474
- output += data.toString();
5475
- const match = output.match(/url=(https?:\/\/[^\s]+)/i);
5476
- if (match) {
5477
- clearTimeout(timeout);
5478
- this.url = match[1];
5479
- resolve(match[1]);
5480
- }
5481
- });
5482
- this.process.stderr?.on("data", () => {
5483
- });
5484
- this.process.on("error", (error) => {
5485
- clearTimeout(timeout);
5486
- reject(error);
5487
- });
5488
- this.process.on("exit", (code) => {
5489
- if (code !== 0 && !this.url) {
5490
- clearTimeout(timeout);
5491
- reject(new Error(`Ngrok exited with code ${code}`));
5492
- }
5493
- });
5494
- });
5495
- }
5496
- };
5497
- }
5498
- });
5499
-
5500
- // src/web-client.ts
5501
- function getWebClient() {
5502
- return `<!DOCTYPE html>
5503
- <html lang="en">
5504
- <head>
5505
- <meta charset="UTF-8">
5506
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
5507
- <meta name="apple-mobile-web-app-capable" content="yes">
5508
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
5509
- <title>NikCLI Remote</title>
5510
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" />
5511
- <style>
5512
- * { box-sizing: border-box; margin: 0; padding: 0; }
5513
- :root {
5514
- --bg-primary: #0d1117;
5515
- --bg-secondary: #161b22;
5516
- --accent: #58a6ff;
5517
- --success: #3fb950;
5518
- --border: #30363d;
5519
- }
5520
- html, body { height: 100%; overflow: hidden; touch-action: manipulation; }
5521
- body {
5522
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
5523
- background: var(--bg-primary);
5524
- color: #e6edf3;
5525
- display: flex;
5526
- flex-direction: column;
5527
- }
5528
- #terminal { flex: 1; overflow: hidden; background: var(--bg-primary); padding: 8px; }
5529
- #input-area {
5530
- background: var(--bg-secondary);
5531
- border-top: 1px solid var(--border);
5532
- padding: 12px 16px;
5533
- flex-shrink: 0;
5534
- padding-bottom: env(safe-area-inset-bottom, 12px);
5535
- }
5536
- .input-row { display: flex; gap: 8px; align-items: center; }
5537
- .prompt { color: var(--success); font-family: 'SF Mono', Monaco, monospace; font-size: 14px; white-space: nowrap; }
5538
- #cmd-input {
5539
- flex: 1;
5540
- background: #21262d;
5541
- border: 1px solid var(--border);
5542
- border-radius: 12px;
5543
- padding: 12px 16px;
5544
- color: #e6edf3;
5545
- font-size: 16px;
5546
- font-family: 'SF Mono', Monaco, monospace;
5547
- outline: none;
5548
- -webkit-appearance: none;
5549
- }
5550
- #cmd-input:focus { border-color: var(--accent); }
5551
- #send-btn {
5552
- background: var(--accent);
5553
- color: white;
5554
- border: none;
5555
- border-radius: 12px;
5556
- padding: 12px 24px;
5557
- font-size: 16px;
5558
- font-weight: 600;
5559
- cursor: pointer;
5560
- -webkit-tap-highlight-color: transparent;
5561
- }
5562
- #send-btn:active { opacity: 0.7; }
5563
- #status-bar {
5564
- background: var(--bg-secondary);
5565
- border-bottom: 1px solid var(--border);
5566
- padding: 8px 16px;
5567
- display: flex;
5568
- justify-content: space-between;
5569
- align-items: center;
5570
- font-size: 12px;
5571
- padding-top: env(safe-area-inset-top, 8px);
5572
- }
5573
- .status-row { display: flex; align-items: center; gap: 8px; }
5574
- .status-dot { width: 8px; height: 8px; border-radius: 50%; background: #8b949e; }
5575
- .status-dot.connected { background: var(--success); box-shadow: 0 0 8px var(--success); }
5576
- .status-dot.connecting { background: var(--accent); animation: pulse 1s infinite; }
5577
- .status-dot.disconnected { background: #f85149; }
5578
- @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
5579
- #auth-overlay {
5580
- position: fixed; inset: 0; background: var(--bg-primary);
5581
- display: flex; flex-direction: column; align-items: center; justify-content: center;
5582
- padding: 20px; z-index: 100;
5583
- }
5584
- #auth-overlay.hidden { display: none; }
5585
- .auth-title { font-size: 28px; font-weight: 700; margin-bottom: 8px; }
5586
- .auth-subtitle { color: #8b949e; font-size: 16px; margin-bottom: 24px; }
5587
- .auth-msg {
5588
- background: var(--bg-secondary); padding: 20px 28px;
5589
- border-radius: 16px; border: 1px solid var(--border); text-align: center;
5590
- }
5591
- .auth-msg.error { color: #f85149; border-color: #f85149; }
5592
- .quick-btns {
5593
- display: flex; gap: 8px; margin-top: 20px; flex-wrap: wrap; justify-content: center;
5594
- }
5595
- .quick-btn {
5596
- background: #21262d; border: 1px solid var(--border); color: #e6edf3;
5597
- padding: 10px 16px; border-radius: 8px; font-size: 14px;
5598
- font-family: 'SF Mono', Monaco, monospace; cursor: pointer;
5599
- }
5600
- .quick-btn:active { background: #30363d; }
5601
- .hint { font-size: 12px; color: #8b949e; margin-top: 12px; }
5602
- @media (max-width: 600px) {
5603
- #input-area { padding: 10px 12px; }
5604
- .quick-btn { padding: 8px 12px; font-size: 12px; }
5605
- }
5606
- </style>
5607
- </head>
5608
- <body>
5609
- <div id="auth-overlay">
5610
- <div class="auth-title">\u{1F4F1} NikCLI Remote</div>
5611
- <div class="auth-subtitle">Full terminal emulation</div>
5612
- <div id="auth-msg" class="auth-msg">
5613
- <div id="auth-text">Connecting...</div>
5614
- </div>
5615
- <div class="quick-btns">
5616
- <button class="quick-btn" onclick="send('help')">/help</button>
5617
- <button class="quick-btn" onclick="send('ls -la')">ls -la</button>
5618
- <button class="quick-btn" onclick="send('pwd')">pwd</button>
5619
- <button class="quick-btn" onclick="send('whoami')">whoami</button>
5620
- <button class="quick-btn" onclick="send('clear')">clear</button>
5621
- </div>
5622
- <div class="hint">Mobile keyboard to type commands</div>
5623
- </div>
5624
-
5625
- <div id="status-bar">
5626
- <div class="status-row">
5627
- <span class="status-dot" id="status-dot"></span>
5628
- <span id="status-text">Disconnected</span>
5629
- </div>
5630
- <span id="session-id" style="color: #8b949e;"></span>
5631
- </div>
5632
-
5633
- <div id="terminal"></div>
5634
-
5635
- <div id="input-area">
5636
- <form class="input-row" onsubmit="return handleSubmit(event)">
5637
- <span class="prompt">$</span>
5638
- <input type="text" id="cmd-input" placeholder="Type command..." autocomplete="off" enterkeyhint="send" inputmode="text">
5639
- <button type="submit" id="send-btn">Send</button>
5640
- </form>
5641
- </div>
5642
-
5643
- <script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script>
5644
- <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script>
5645
- <script>
5646
- let ws = null, term = null, fitAddon = null, connected = false, reconnectAttempts = 0;
5647
- const token = new URLSearchParams(location.search).get('t') || '';
5648
- const sessionId = new URLSearchParams(location.search).get('s') || '';
5649
-
5650
- const authOverlay = document.getElementById('auth-overlay');
5651
- const authMsg = document.getElementById('auth-msg');
5652
- const authText = document.getElementById('auth-text');
5653
- const statusDot = document.getElementById('status-dot');
5654
- const statusText = document.getElementById('status-text');
5655
- const sessionSpan = document.getElementById('session-id');
5656
- const cmdInput = document.getElementById('cmd-input');
5657
-
5658
- // Initialize xterm.js
5659
- term = new Terminal({
5660
- cursorBlink: true,
5661
- fontSize: 14,
5662
- fontFamily: '"SF Mono", Monaco, Consolas, monospace',
5663
- theme: {
5664
- background: '#0d1117',
5665
- foreground: '#e6edf3',
5666
- cursor: '#3fb950',
5667
- selectionBackground: '#264f78',
5668
- black: '#484f58',
5669
- red: '#f85149',
5670
- green: '#3fb950',
5671
- yellow: '#d29922',
5672
- blue: '#58a6ff',
5673
- magenta: '#a371f7',
5674
- cyan: '#39c5cf',
5675
- white: '#e6edf3',
5676
- brightBlack: '#6e7681',
5677
- brightRed: '#ffa198',
5678
- brightGreen: '#7ee787',
5679
- brightYellow: '#f0883e',
5680
- brightBlue: '#79c0ff',
5681
- brightMagenta: '#d2a8ff',
5682
- brightCyan: '#56d4db',
5683
- brightWhite: '#f0f6fc'
5684
- },
5685
- convertEol: true
5686
- });
5687
-
5688
- fitAddon = new FitAddon.FitAddon();
5689
- term.loadAddon(fitAddon);
5690
- term.open(document.getElementById('terminal'));
5691
- fitAddon.fit();
5692
- term.writeln('Initializing NikCLI Remote...');
5693
- term.writeln('Type commands below');
5694
-
5695
- // Resize handler
5696
- window.addEventListener('resize', () => {
5697
- clearTimeout(window.resizeTimer);
5698
- window.resizeTimer = setTimeout(() => fitAddon.fit(), 100);
5699
- });
5700
-
5701
- // Visual viewport for mobile keyboard
5702
- if (window.visualViewport) {
5703
- window.visualViewport.addEventListener('resize', () => {
5704
- clearTimeout(window.resizeTimer);
5705
- window.resizeTimer = setTimeout(() => fitAddon.fit(), 100);
5706
- });
5707
- }
5708
-
5709
- function connect() {
5710
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
5711
- ws = new WebSocket(protocol + '//' + location.host + '/ws');
5712
-
5713
- ws.onopen = () => {
5714
- setStatus('connecting', 'Authenticating...');
5715
- ws.send(JSON.stringify({ type: 'auth', token }));
5716
- reconnectAttempts = 0;
5717
- };
5718
-
5719
- ws.onmessage = (e) => {
5720
- try { handleMessage(JSON.parse(e.data)); } catch (err) { console.error(err); }
5721
- };
5722
-
5723
- ws.onclose = () => {
5724
- setStatus('disconnected', 'Disconnected');
5725
- connected = false;
5726
- reconnectAttempts++;
5727
- setTimeout(connect, Math.min(3000, reconnectAttempts * 500));
5728
- };
5729
-
5730
- ws.onerror = () => setStatus('disconnected', 'Connection error');
5731
- }
5732
-
5733
- function handleMessage(msg) {
5734
- switch (msg.type) {
5735
- case 'auth:required':
5736
- ws.send(JSON.stringify({ type: 'auth', token }));
5737
- break;
5738
- case 'auth:success':
5739
- connected = true;
5740
- authOverlay.classList.add('hidden');
5741
- setStatus('connected', 'Connected');
5742
- sessionSpan.textContent = sessionId ? 'Session: ' + sessionId : '';
5743
- term.writeln('\u2713 Connected to NikCLI');
5744
- break;
5745
- case 'auth:failed':
5746
- authMsg.classList.add('error');
5747
- authText.textContent = 'Authentication failed';
5748
- break;
5749
- case 'terminal:output':
5750
- if (msg.payload?.data) term.write(msg.payload.data);
5751
- break;
5752
- case 'terminal:exit':
5753
- term.writeln('Process exited: ' + (msg.payload?.code || 0) + '');
5754
- break;
5755
- }
5756
- }
5757
-
5758
- function setStatus(state, text) {
5759
- statusDot.className = 'status-dot ' + state;
5760
- statusText.textContent = text;
5761
- }
5762
-
5763
- function handleSubmit(e) {
5764
- if (e) e.preventDefault();
5765
- const value = cmdInput.value.trim();
5766
- if (!value || !connected) return;
5767
- cmdInput.value = '';
5768
- term.write('$ ' + value );
5769
- ws.send(JSON.stringify({ type: 'terminal:input', data: value + '\r' }));
5770
- setTimeout(() => cmdInput.focus(), 50);
5771
- return false;
5772
- }
5773
-
5774
- function send(cmd) {
5775
- if (!connected) return;
5776
- term.write('$ ' + cmd + );
5777
- ws.send(JSON.stringify({ type: 'terminal:input', data: cmd + '\r' }));
5778
- }
5779
-
5780
- cmdInput.addEventListener('keydown', (e) => {
5781
- if (e.key === 'Enter' && !e.shiftKey) {
5782
- e.preventDefault();
5783
- handleSubmit();
5784
- }
5785
- });
5786
-
5787
- document.getElementById('terminal')?.addEventListener('click', () => {
5788
- if (connected) cmdInput.focus();
5789
- });
5790
-
5791
- connect();
5792
- </script>
5793
- </body>
5794
- </html>`;
5795
- }
5796
- var init_web_client = __esm({
5797
- "src/web-client.ts"() {
5798
- "use strict";
5799
- }
5800
- });
5801
-
5802
- // src/server.ts
5803
- var server_exports = {};
5804
- __export(server_exports, {
5805
- RemoteServer: () => RemoteServer
5806
- });
5807
- var import_node_events2, import_node_http, import_ws, import_node_crypto, import_node_os, RemoteServer;
5808
- var init_server = __esm({
5809
- "src/server.ts"() {
5810
- "use strict";
5811
- import_node_events2 = require("events");
5812
- import_node_http = require("http");
5813
- import_ws = require("ws");
5814
- import_node_crypto = __toESM(require("crypto"), 1);
5815
- import_node_os = __toESM(require("os"), 1);
5816
- init_types();
5817
- init_terminal();
5818
- init_tunnel();
5819
- init_web_client();
5820
- RemoteServer = class extends import_node_events2.EventEmitter {
5821
- config;
5822
- httpServer = null;
5823
- wss = null;
5824
- clients = /* @__PURE__ */ new Map();
5825
- session = null;
5826
- terminal = null;
5827
- tunnel = null;
5828
- heartbeatTimer = null;
5829
- sessionTimeoutTimer = null;
5830
- isRunning = false;
5831
- sessionSecret;
5832
- constructor(config = {}) {
5833
- super();
5834
- this.config = { ...DEFAULT_CONFIG, ...config };
5835
- this.sessionSecret = config.sessionSecret || this.generateSecret();
5836
- }
5837
- /**
5838
- * Start the remote server
5839
- */
5840
- async start(options = {}) {
5841
- if (this.isRunning) {
5842
- throw new Error("Server already running");
5843
- }
5844
- const sessionId = this.generateSessionId();
5845
- this.httpServer = (0, import_node_http.createServer)((req, res) => this.handleHttpRequest(req, res));
5846
- this.wss = new import_ws.WebSocketServer({ server: this.httpServer });
5847
- this.setupWebSocketHandlers();
5848
- const port = await new Promise((resolve, reject) => {
5849
- this.httpServer.listen(this.config.port, this.config.host, () => {
5850
- const addr = this.httpServer.address();
5851
- resolve(typeof addr === "object" ? addr?.port || 0 : 0);
5852
- });
5853
- this.httpServer.on("error", reject);
5854
- });
5855
- const localIp = this.getLocalIP();
5856
- const localUrl = `http://${localIp}:${port}`;
5857
- this.session = {
5858
- id: sessionId,
5859
- name: options.name || `nikcli-${sessionId}`,
5860
- qrCode: "",
5861
- qrUrl: localUrl,
5862
- localUrl,
5863
- status: "starting",
5864
- connectedDevices: [],
5865
- startedAt: /* @__PURE__ */ new Date(),
5866
- lastActivity: /* @__PURE__ */ new Date(),
5867
- port
5868
- };
5869
- if (this.config.enableTunnel && this.config.tunnelProvider !== "none") {
5870
- try {
5871
- this.tunnel = new TunnelManager(this.config.tunnelProvider);
5872
- const tunnelUrl = await this.tunnel.create(port);
5873
- this.session.tunnelUrl = tunnelUrl;
5874
- this.session.qrUrl = `${tunnelUrl}?s=${sessionId}&t=${this.sessionSecret}`;
5875
- this.emit("tunnel:connected", tunnelUrl);
5876
- } catch (error) {
5877
- this.emit("tunnel:error", error);
5878
- this.session.qrUrl = `${localUrl}?s=${sessionId}&t=${this.sessionSecret}`;
5879
- }
5880
- } else {
5881
- this.session.qrUrl = `${localUrl}?s=${sessionId}&t=${this.sessionSecret}`;
5882
- }
5883
- if (this.config.enableTerminal) {
5884
- this.terminal = new TerminalManager({
5885
- shell: this.config.shell,
5886
- cols: this.config.cols,
5887
- rows: this.config.rows,
5888
- cwd: this.config.cwd,
5889
- env: this.config.env
5890
- });
5891
- this.terminal.on("data", (data) => {
5892
- this.broadcast({ type: MessageTypes.TERMINAL_OUTPUT, payload: { data } });
5893
- this.emit("terminal:output", data);
5894
- });
5895
- this.terminal.on("exit", (code) => {
5896
- this.broadcast({ type: MessageTypes.TERMINAL_EXIT, payload: { code } });
5897
- });
5898
- }
5899
- this.startHeartbeat();
5900
- if (this.config.sessionTimeout > 0) {
5901
- this.startSessionTimeout();
5902
- }
5903
- this.session.status = "waiting";
5904
- this.isRunning = true;
5905
- this.emit("started", this.session);
5906
- return this.session;
5907
- }
5908
- /**
5909
- * Stop the server
5910
- */
5911
- async stop() {
5912
- if (!this.isRunning) return;
5913
- this.isRunning = false;
5914
- if (this.heartbeatTimer) {
5915
- clearInterval(this.heartbeatTimer);
5916
- this.heartbeatTimer = null;
5917
- }
5918
- if (this.sessionTimeoutTimer) {
5919
- clearTimeout(this.sessionTimeoutTimer);
5920
- this.sessionTimeoutTimer = null;
5921
- }
5922
- this.broadcast({ type: MessageTypes.SESSION_END, payload: {} });
5923
- for (const client of this.clients.values()) {
5924
- client.ws.close(1e3, "Server shutting down");
5925
- }
5926
- this.clients.clear();
5927
- if (this.terminal) {
5928
- this.terminal.destroy();
5929
- this.terminal = null;
5930
- }
5931
- if (this.tunnel) {
5932
- await this.tunnel.close();
5933
- this.tunnel = null;
5934
- }
5935
- if (this.wss) {
5936
- this.wss.close();
5937
- this.wss = null;
5938
- }
5939
- if (this.httpServer) {
5940
- await new Promise((resolve) => {
5941
- this.httpServer.close(() => resolve());
5942
- });
5943
- this.httpServer = null;
5944
- }
5945
- if (this.session) {
5946
- this.session.status = "stopped";
5947
- }
5948
- this.emit("stopped");
5949
- }
5950
- /**
5951
- * Broadcast message to all authenticated clients
5952
- */
5953
- broadcast(message) {
5954
- const data = JSON.stringify({
5955
- type: message.type,
5956
- payload: message.payload,
5957
- timestamp: message.timestamp || Date.now()
5958
- });
5959
- for (const client of this.clients.values()) {
5960
- if (client.authenticated && client.ws.readyState === import_ws.WebSocket.OPEN) {
5961
- client.ws.send(data);
5962
- }
5963
- }
5964
- }
5965
- /**
5966
- * Send notification to clients
5967
- */
5968
- notify(notification) {
5969
- this.broadcast({
5970
- type: MessageTypes.NOTIFICATION,
5971
- payload: notification
5972
- });
5973
- }
5974
- /**
5975
- * Get current session
5976
- */
5977
- getSession() {
5978
- return this.session;
5979
- }
5980
- /**
5981
- * Check if server is running
5982
- */
5983
- isActive() {
5984
- return this.isRunning && this.session?.status !== "stopped";
5985
- }
5986
- /**
5987
- * Get connected client count
5988
- */
5989
- getConnectedCount() {
5990
- let count = 0;
5991
- for (const client of this.clients.values()) {
5992
- if (client.authenticated) count++;
5993
- }
5994
- return count;
5995
- }
5996
- /**
5997
- * Write to terminal
5998
- */
5999
- writeToTerminal(data) {
6000
- this.terminal?.write(data);
6001
- }
6002
- /**
6003
- * Resize terminal
6004
- */
6005
- resizeTerminal(cols, rows) {
6006
- this.terminal?.resize(cols, rows);
6007
- }
6008
- /**
6009
- * Setup WebSocket handlers
6010
- */
6011
- setupWebSocketHandlers() {
6012
- this.wss.on("connection", (ws, req) => {
6013
- const clientId = this.generateClientId();
6014
- const client = {
6015
- id: clientId,
6016
- ws,
6017
- authenticated: false,
6018
- device: {
6019
- id: clientId,
6020
- userAgent: req.headers["user-agent"],
6021
- ip: req.socket.remoteAddress,
6022
- connectedAt: /* @__PURE__ */ new Date(),
6023
- lastActivity: /* @__PURE__ */ new Date()
6024
- },
6025
- lastPing: Date.now()
6026
- };
6027
- if (this.clients.size >= this.config.maxConnections) {
6028
- ws.close(1013, "Max connections reached");
6029
- return;
6030
- }
6031
- this.clients.set(clientId, client);
6032
- ws.send(JSON.stringify({ type: MessageTypes.AUTH_REQUIRED, timestamp: Date.now() }));
6033
- ws.on("message", (data) => {
6034
- try {
6035
- const message = JSON.parse(data.toString());
6036
- this.handleClientMessage(client, message);
6037
- } catch {
6038
- }
6039
- });
6040
- ws.on("close", () => {
6041
- this.clients.delete(clientId);
6042
- if (this.session && client.authenticated) {
6043
- this.session.connectedDevices = this.session.connectedDevices.filter(
6044
- (d) => d.id !== clientId
6045
- );
6046
- if (this.session.connectedDevices.length === 0) {
6047
- this.session.status = "waiting";
6048
- }
6049
- this.emit("client:disconnected", client.device);
6050
- }
6051
- });
6052
- ws.on("error", (error) => {
6053
- this.emit("client:error", clientId, error);
6054
- });
6055
- ws.on("pong", () => {
6056
- client.lastPing = Date.now();
6057
- });
6058
- });
6059
- }
6060
- /**
6061
- * Handle client message
6062
- */
6063
- handleClientMessage(client, message) {
6064
- client.device.lastActivity = /* @__PURE__ */ new Date();
6065
- if (this.session) {
6066
- this.session.lastActivity = /* @__PURE__ */ new Date();
6067
- }
6068
- if (this.config.sessionTimeout > 0) {
6069
- this.resetSessionTimeout();
6070
- }
6071
- switch (message.type) {
6072
- case MessageTypes.AUTH:
6073
- this.handleAuth(client, message.token);
6074
- break;
6075
- case MessageTypes.TERMINAL_INPUT:
6076
- if (client.authenticated && message.data) {
6077
- this.terminal?.write(message.data);
6078
- }
6079
- break;
6080
- case MessageTypes.TERMINAL_RESIZE:
6081
- if (client.authenticated && message.cols && message.rows) {
6082
- this.terminal?.resize(message.cols, message.rows);
6083
- }
6084
- break;
6085
- case MessageTypes.TERMINAL_CLEAR:
6086
- if (client.authenticated) {
6087
- this.terminal?.clear();
6088
- }
6089
- break;
6090
- case MessageTypes.PING:
6091
- client.ws.send(JSON.stringify({ type: MessageTypes.PONG, timestamp: Date.now() }));
6092
- break;
6093
- case MessageTypes.COMMAND:
6094
- if (client.authenticated) {
6095
- this.emit("command", {
6096
- clientId: client.id,
6097
- command: message.command,
6098
- args: message.args
6099
- });
6100
- }
6101
- break;
6102
- default:
6103
- this.emit("message", client, message);
6104
- }
6105
- }
6106
- /**
6107
- * Handle authentication
6108
- */
6109
- handleAuth(client, token) {
6110
- if (token === this.sessionSecret) {
6111
- client.authenticated = true;
6112
- if (this.session) {
6113
- this.session.connectedDevices.push(client.device);
6114
- this.session.status = "connected";
6115
- }
6116
- client.ws.send(
6117
- JSON.stringify({
6118
- type: MessageTypes.AUTH_SUCCESS,
6119
- payload: {
6120
- sessionId: this.session?.id,
6121
- terminalEnabled: this.config.enableTerminal
6122
- },
6123
- timestamp: Date.now()
6124
- })
6125
- );
6126
- if (this.config.enableTerminal && !this.terminal?.isRunning()) {
6127
- this.terminal?.start();
6128
- }
6129
- this.emit("client:connected", client.device);
6130
- } else {
6131
- client.ws.send(JSON.stringify({ type: MessageTypes.AUTH_FAILED, timestamp: Date.now() }));
6132
- setTimeout(() => client.ws.close(1008, "Authentication failed"), 100);
6133
- }
6134
- }
6135
- /**
6136
- * Handle HTTP request
6137
- */
6138
- handleHttpRequest(req, res) {
6139
- const url = new URL(req.url || "/", `http://${req.headers.host}`);
6140
- const path = url.pathname;
6141
- res.setHeader("Access-Control-Allow-Origin", "*");
6142
- res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
6143
- res.setHeader("Access-Control-Allow-Headers", "Content-Type");
6144
- if (req.method === "OPTIONS") {
6145
- res.writeHead(204);
6146
- res.end();
6147
- return;
6148
- }
6149
- if (path === "/" || path === "/index.html") {
6150
- res.writeHead(200, {
6151
- "Content-Type": "text/html; charset=utf-8",
6152
- "Content-Security-Policy": "default-src 'self' 'unsafe-inline' 'unsafe-eval' https: data: ws: wss:"
6153
- });
6154
- res.end(getWebClient());
6155
- return;
6156
- }
6157
- if (path === "/health") {
6158
- res.writeHead(200, { "Content-Type": "application/json" });
6159
- res.end(JSON.stringify({ status: "ok", session: this.session?.id }));
6160
- return;
6161
- }
6162
- if (path === "/api/session") {
6163
- res.writeHead(200, { "Content-Type": "application/json" });
6164
- res.end(
6165
- JSON.stringify({
6166
- id: this.session?.id,
6167
- name: this.session?.name,
6168
- status: this.session?.status,
6169
- connectedDevices: this.session?.connectedDevices.length
6170
- })
6171
- );
6172
- return;
6173
- }
6174
- res.writeHead(404, { "Content-Type": "text/plain" });
6175
- res.end("Not Found");
6176
- }
6177
- /**
6178
- * Start heartbeat
6179
- */
6180
- startHeartbeat() {
6181
- this.heartbeatTimer = setInterval(() => {
6182
- const now = Date.now();
6183
- for (const [id, client] of this.clients) {
6184
- if (now - client.lastPing > this.config.heartbeatInterval * 2) {
6185
- client.ws.terminate();
6186
- this.clients.delete(id);
6187
- } else if (client.ws.readyState === import_ws.WebSocket.OPEN) {
6188
- client.ws.ping();
6189
- }
6190
- }
6191
- }, this.config.heartbeatInterval);
6192
- }
6193
- /**
6194
- * Start session timeout
6195
- */
6196
- startSessionTimeout() {
6197
- this.sessionTimeoutTimer = setTimeout(() => {
6198
- if (this.session?.connectedDevices.length === 0) {
6199
- this.stop();
4786
+ remote.resume();
4787
+ let stream = remote;
4788
+ if (opt.local_host) {
4789
+ debug("transform Host header to %s", opt.local_host);
4790
+ stream = remote.pipe(new HeaderHostTransformer({ host: opt.local_host }));
4791
+ }
4792
+ stream.pipe(local).pipe(remote);
4793
+ local.once("close", (hadError) => {
4794
+ debug("local connection closed [%s]", hadError);
4795
+ });
4796
+ });
4797
+ };
4798
+ remote.on("data", (data) => {
4799
+ const match = data.toString().match(/^(\w+) (\S+)/);
4800
+ if (match) {
4801
+ this.emit("request", {
4802
+ method: match[1],
4803
+ path: match[2]
4804
+ });
6200
4805
  }
6201
- }, this.config.sessionTimeout);
4806
+ });
4807
+ remote.once("connect", () => {
4808
+ this.emit("open", remote);
4809
+ connLocal();
4810
+ });
6202
4811
  }
6203
- /**
6204
- * Reset session timeout
6205
- */
6206
- resetSessionTimeout() {
6207
- if (this.sessionTimeoutTimer) {
6208
- clearTimeout(this.sessionTimeoutTimer);
6209
- }
6210
- if (this.config.sessionTimeout > 0) {
6211
- this.startSessionTimeout();
4812
+ };
4813
+ }
4814
+ });
4815
+
4816
+ // node_modules/localtunnel/lib/Tunnel.js
4817
+ var require_Tunnel = __commonJS({
4818
+ "node_modules/localtunnel/lib/Tunnel.js"(exports2, module2) {
4819
+ "use strict";
4820
+ var { parse } = require("url");
4821
+ var { EventEmitter: EventEmitter2 } = require("events");
4822
+ var axios = require_axios2();
4823
+ var debug = require_src2()("localtunnel:client");
4824
+ var TunnelCluster = require_TunnelCluster();
4825
+ module2.exports = class Tunnel extends EventEmitter2 {
4826
+ constructor(opts = {}) {
4827
+ super(opts);
4828
+ this.opts = opts;
4829
+ this.closed = false;
4830
+ if (!this.opts.host) {
4831
+ this.opts.host = "https://localtunnel.me";
6212
4832
  }
6213
4833
  }
6214
- /**
6215
- * Get local IP
6216
- */
6217
- getLocalIP() {
6218
- const interfaces = import_node_os.default.networkInterfaces();
6219
- for (const name of Object.keys(interfaces)) {
6220
- for (const iface of interfaces[name] || []) {
6221
- if (iface.family === "IPv4" && !iface.internal) {
6222
- return iface.address;
4834
+ _getInfo(body) {
4835
+ const { id, ip, port, url, cached_url, max_conn_count } = body;
4836
+ const { host, port: local_port, local_host } = this.opts;
4837
+ const { local_https, local_cert, local_key, local_ca, allow_invalid_cert } = this.opts;
4838
+ return {
4839
+ name: id,
4840
+ url,
4841
+ cached_url,
4842
+ max_conn: max_conn_count || 1,
4843
+ remote_host: parse(host).hostname,
4844
+ remote_ip: ip,
4845
+ remote_port: port,
4846
+ local_port,
4847
+ local_host,
4848
+ local_https,
4849
+ local_cert,
4850
+ local_key,
4851
+ local_ca,
4852
+ allow_invalid_cert
4853
+ };
4854
+ }
4855
+ // initialize connection
4856
+ // callback with connection info
4857
+ _init(cb) {
4858
+ const opt = this.opts;
4859
+ const getInfo = this._getInfo.bind(this);
4860
+ const params = {
4861
+ responseType: "json"
4862
+ };
4863
+ const baseUri = `${opt.host}/`;
4864
+ const assignedDomain = opt.subdomain;
4865
+ const uri = baseUri + (assignedDomain || "?new");
4866
+ (function getUrl() {
4867
+ axios.get(uri, params).then((res) => {
4868
+ const body = res.data;
4869
+ debug("got tunnel information", res.data);
4870
+ if (res.status !== 200) {
4871
+ const err = new Error(
4872
+ body && body.message || "localtunnel server returned an error, please try again"
4873
+ );
4874
+ return cb(err);
6223
4875
  }
4876
+ cb(null, getInfo(body));
4877
+ }).catch((err) => {
4878
+ debug(`tunnel server offline: ${err.message}, retry 1s`);
4879
+ return setTimeout(getUrl, 1e3);
4880
+ });
4881
+ })();
4882
+ }
4883
+ _establish(info) {
4884
+ this.setMaxListeners(info.max_conn + (EventEmitter2.defaultMaxListeners || 10));
4885
+ this.tunnelCluster = new TunnelCluster(info);
4886
+ this.tunnelCluster.once("open", () => {
4887
+ this.emit("url", info.url);
4888
+ });
4889
+ this.tunnelCluster.on("error", (err) => {
4890
+ debug("got socket error", err.message);
4891
+ this.emit("error", err);
4892
+ });
4893
+ let tunnelCount = 0;
4894
+ this.tunnelCluster.on("open", (tunnel) => {
4895
+ tunnelCount++;
4896
+ debug("tunnel open [total: %d]", tunnelCount);
4897
+ const closeHandler = () => {
4898
+ tunnel.destroy();
4899
+ };
4900
+ if (this.closed) {
4901
+ return closeHandler();
4902
+ }
4903
+ this.once("close", closeHandler);
4904
+ tunnel.once("close", () => {
4905
+ this.removeListener("close", closeHandler);
4906
+ });
4907
+ });
4908
+ this.tunnelCluster.on("dead", () => {
4909
+ tunnelCount--;
4910
+ debug("tunnel dead [total: %d]", tunnelCount);
4911
+ if (this.closed) {
4912
+ return;
6224
4913
  }
4914
+ this.tunnelCluster.open();
4915
+ });
4916
+ this.tunnelCluster.on("request", (req) => {
4917
+ this.emit("request", req);
4918
+ });
4919
+ for (let count = 0; count < info.max_conn; ++count) {
4920
+ this.tunnelCluster.open();
6225
4921
  }
6226
- return "127.0.0.1";
6227
4922
  }
6228
- /**
6229
- * Generate session ID
6230
- */
6231
- generateSessionId() {
6232
- return import_node_crypto.default.randomBytes(4).toString("hex");
4923
+ open(cb) {
4924
+ this._init((err, info) => {
4925
+ if (err) {
4926
+ return cb(err);
4927
+ }
4928
+ this.clientId = info.name;
4929
+ this.url = info.url;
4930
+ if (info.cached_url) {
4931
+ this.cachedUrl = info.cached_url;
4932
+ }
4933
+ this._establish(info);
4934
+ cb();
4935
+ });
6233
4936
  }
6234
- /**
6235
- * Generate client ID
6236
- */
6237
- generateClientId() {
6238
- return "c_" + import_node_crypto.default.randomBytes(4).toString("hex");
4937
+ close() {
4938
+ this.closed = true;
4939
+ this.emit("close");
6239
4940
  }
6240
- /**
6241
- * Generate secret
6242
- */
6243
- generateSecret() {
6244
- return import_node_crypto.default.randomBytes(16).toString("hex");
4941
+ };
4942
+ }
4943
+ });
4944
+
4945
+ // node_modules/localtunnel/localtunnel.js
4946
+ var require_localtunnel = __commonJS({
4947
+ "node_modules/localtunnel/localtunnel.js"(exports2, module2) {
4948
+ "use strict";
4949
+ var Tunnel = require_Tunnel();
4950
+ module2.exports = function localtunnel(arg1, arg2, arg3) {
4951
+ const options = typeof arg1 === "object" ? arg1 : { ...arg2, port: arg1 };
4952
+ const callback = typeof arg1 === "object" ? arg2 : arg3;
4953
+ const client = new Tunnel(options);
4954
+ if (callback) {
4955
+ client.open((err) => err ? callback(err) : callback(null, client));
4956
+ return client;
6245
4957
  }
4958
+ return new Promise(
4959
+ (resolve, reject) => client.open((err) => err ? reject(err) : resolve(client))
4960
+ );
6246
4961
  };
6247
4962
  }
6248
4963
  });
@@ -6253,18 +4968,239 @@ __export(index_exports, {
6253
4968
  DEFAULT_CONFIG: () => DEFAULT_CONFIG,
6254
4969
  MessageTypes: () => MessageTypes,
6255
4970
  RemoteServer: () => RemoteServer,
6256
- TerminalManager: () => TerminalManager,
4971
+ TunnelManager: () => TunnelManager,
4972
+ checkTunnelAvailability: () => checkTunnelAvailability,
6257
4973
  createRemoteServer: () => createRemoteServer,
4974
+ createTunnel: () => createTunnel,
4975
+ findAvailableTunnel: () => findAvailableTunnel,
6258
4976
  getWebClient: () => getWebClient
6259
4977
  });
6260
4978
  module.exports = __toCommonJS(index_exports);
6261
4979
  init_server();
6262
- init_terminal();
4980
+
4981
+ // src/tunnel.ts
4982
+ var import_node_child_process = require("child_process");
4983
+ async function createTunnel(port, provider = "cloudflared") {
4984
+ const manager = new TunnelManager(provider);
4985
+ const url = await manager.create(port);
4986
+ return {
4987
+ url,
4988
+ provider,
4989
+ close: () => manager.close()
4990
+ };
4991
+ }
4992
+ var TunnelManager = class {
4993
+ provider;
4994
+ process = null;
4995
+ url = null;
4996
+ tunnelInstance = null;
4997
+ constructor(provider) {
4998
+ this.provider = provider;
4999
+ }
5000
+ /**
5001
+ * Create tunnel and return public URL
5002
+ */
5003
+ async create(port) {
5004
+ switch (this.provider) {
5005
+ case "localtunnel":
5006
+ return this.createLocaltunnel(port);
5007
+ case "cloudflared":
5008
+ return this.createCloudflared(port);
5009
+ case "ngrok":
5010
+ return this.createNgrok(port);
5011
+ default:
5012
+ throw new Error(`Unknown tunnel provider: ${this.provider}`);
5013
+ }
5014
+ }
5015
+ /**
5016
+ * Close tunnel
5017
+ */
5018
+ async close() {
5019
+ if (this.tunnelInstance?.close) {
5020
+ this.tunnelInstance.close();
5021
+ this.tunnelInstance = null;
5022
+ }
5023
+ if (this.process) {
5024
+ this.process.kill();
5025
+ this.process = null;
5026
+ }
5027
+ this.url = null;
5028
+ }
5029
+ /**
5030
+ * Get tunnel URL
5031
+ */
5032
+ getUrl() {
5033
+ return this.url;
5034
+ }
5035
+ /**
5036
+ * Create localtunnel
5037
+ */
5038
+ async createLocaltunnel(port) {
5039
+ try {
5040
+ const localtunnel = await Promise.resolve().then(() => __toESM(require_localtunnel(), 1));
5041
+ const tunnel = await localtunnel.default({ port });
5042
+ this.tunnelInstance = tunnel;
5043
+ this.url = tunnel.url;
5044
+ tunnel.on("close", () => {
5045
+ this.url = null;
5046
+ });
5047
+ return tunnel.url;
5048
+ } catch {
5049
+ return this.createLocaltunnelCli(port);
5050
+ }
5051
+ }
5052
+ /**
5053
+ * Create localtunnel via CLI
5054
+ */
5055
+ createLocaltunnelCli(port) {
5056
+ return new Promise((resolve, reject) => {
5057
+ this.process = (0, import_node_child_process.spawn)("npx", ["localtunnel", "--port", port.toString(), "--print-requests", "false"], {
5058
+ stdio: ["pipe", "pipe", "pipe"],
5059
+ shell: true
5060
+ });
5061
+ let output = "";
5062
+ const timeout = setTimeout(() => {
5063
+ reject(new Error("Localtunnel timeout"));
5064
+ }, 3e4);
5065
+ this.process.stdout?.on("data", (data) => {
5066
+ output += data.toString();
5067
+ const match = output.match(/your url is:\s*(https?:\/\/[^\s]+)/i);
5068
+ if (match) {
5069
+ clearTimeout(timeout);
5070
+ this.url = match[1];
5071
+ resolve(match[1]);
5072
+ }
5073
+ });
5074
+ this.process.stderr?.on("data", () => {
5075
+ });
5076
+ this.process.on("error", (error) => {
5077
+ clearTimeout(timeout);
5078
+ reject(error);
5079
+ });
5080
+ this.process.on("exit", (code) => {
5081
+ if (code !== 0 && !this.url) {
5082
+ clearTimeout(timeout);
5083
+ reject(new Error(`Localtunnel exited with code ${code}`));
5084
+ }
5085
+ });
5086
+ });
5087
+ }
5088
+ /**
5089
+ * Create cloudflared tunnel
5090
+ */
5091
+ createCloudflared(port) {
5092
+ return new Promise((resolve, reject) => {
5093
+ this.process = (0, import_node_child_process.spawn)(
5094
+ "cloudflared",
5095
+ ["tunnel", "--url", `http://localhost:${port}`, "--metrics", "localhost:0"],
5096
+ {
5097
+ stdio: ["pipe", "pipe", "pipe"]
5098
+ }
5099
+ );
5100
+ let output = "";
5101
+ const timeout = setTimeout(() => {
5102
+ reject(new Error("Cloudflared timeout"));
5103
+ }, 3e4);
5104
+ const handleData = (data) => {
5105
+ output += data.toString();
5106
+ const match = output.match(/(https:\/\/[^\s]+\.trycloudflare\.com)/i);
5107
+ if (match) {
5108
+ clearTimeout(timeout);
5109
+ this.url = match[1];
5110
+ resolve(match[1]);
5111
+ }
5112
+ };
5113
+ this.process.stdout?.on("data", handleData);
5114
+ this.process.stderr?.on("data", handleData);
5115
+ this.process.on("error", (error) => {
5116
+ clearTimeout(timeout);
5117
+ reject(error);
5118
+ });
5119
+ this.process.on("exit", (code) => {
5120
+ if (code !== 0 && !this.url) {
5121
+ clearTimeout(timeout);
5122
+ reject(new Error(`Cloudflared exited with code ${code}`));
5123
+ }
5124
+ });
5125
+ });
5126
+ }
5127
+ /**
5128
+ * Create ngrok tunnel
5129
+ */
5130
+ createNgrok(port) {
5131
+ return new Promise((resolve, reject) => {
5132
+ this.process = (0, import_node_child_process.spawn)("ngrok", ["http", port.toString(), "--log=stdout", "--log-level=info"], {
5133
+ stdio: ["pipe", "pipe", "pipe"]
5134
+ });
5135
+ let output = "";
5136
+ const timeout = setTimeout(() => {
5137
+ reject(new Error("Ngrok timeout"));
5138
+ }, 3e4);
5139
+ this.process.stdout?.on("data", (data) => {
5140
+ output += data.toString();
5141
+ const match = output.match(/url=(https?:\/\/[^\s]+)/i);
5142
+ if (match) {
5143
+ clearTimeout(timeout);
5144
+ this.url = match[1];
5145
+ resolve(match[1]);
5146
+ }
5147
+ });
5148
+ this.process.stderr?.on("data", () => {
5149
+ });
5150
+ this.process.on("error", (error) => {
5151
+ clearTimeout(timeout);
5152
+ reject(error);
5153
+ });
5154
+ this.process.on("exit", (code) => {
5155
+ if (code !== 0 && !this.url) {
5156
+ clearTimeout(timeout);
5157
+ reject(new Error(`Ngrok exited with code ${code}`));
5158
+ }
5159
+ });
5160
+ });
5161
+ }
5162
+ };
5163
+ async function checkTunnelAvailability(provider) {
5164
+ try {
5165
+ const { execSync } = await import("child_process");
5166
+ switch (provider) {
5167
+ case "localtunnel":
5168
+ try {
5169
+ await Promise.resolve().then(() => __toESM(require_localtunnel(), 1));
5170
+ return true;
5171
+ } catch {
5172
+ execSync("npx localtunnel --version", { stdio: "pipe" });
5173
+ return true;
5174
+ }
5175
+ case "cloudflared":
5176
+ execSync("cloudflared --version", { stdio: "pipe" });
5177
+ return true;
5178
+ case "ngrok":
5179
+ execSync("ngrok version", { stdio: "pipe" });
5180
+ return true;
5181
+ default:
5182
+ return false;
5183
+ }
5184
+ } catch {
5185
+ return false;
5186
+ }
5187
+ }
5188
+ async function findAvailableTunnel() {
5189
+ const providers = ["localtunnel", "cloudflared", "ngrok"];
5190
+ for (const provider of providers) {
5191
+ if (await checkTunnelAvailability(provider)) {
5192
+ return provider;
5193
+ }
5194
+ }
5195
+ return null;
5196
+ }
5197
+
5198
+ // src/index.ts
6263
5199
  init_web_client();
6264
5200
  init_types();
6265
5201
  async function createRemoteServer(config = {}) {
6266
- const { RemoteServer: RemoteServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
6267
- const server = new RemoteServer2(config);
5202
+ const { RemoteServer: RemoteServerCls } = await Promise.resolve().then(() => (init_server(), server_exports));
5203
+ const server = new RemoteServerCls(config);
6268
5204
  const session = await server.start();
6269
5205
  return { server, session };
6270
5206
  }
@@ -6273,7 +5209,10 @@ async function createRemoteServer(config = {}) {
6273
5209
  DEFAULT_CONFIG,
6274
5210
  MessageTypes,
6275
5211
  RemoteServer,
6276
- TerminalManager,
5212
+ TunnelManager,
5213
+ checkTunnelAvailability,
6277
5214
  createRemoteServer,
5215
+ createTunnel,
5216
+ findAvailableTunnel,
6278
5217
  getWebClient
6279
5218
  });