ttyd-mux 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +222 -0
- package/dist/caddy/client.d.ts +84 -0
- package/dist/caddy/client.d.ts.map +1 -0
- package/dist/caddy/client.js +144 -0
- package/dist/caddy/client.js.map +1 -0
- package/dist/client/index.d.ts +11 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +124 -0
- package/dist/client/index.js.map +1 -0
- package/dist/commands/attach.d.ts +5 -0
- package/dist/commands/attach.d.ts.map +1 -0
- package/dist/commands/attach.js +100 -0
- package/dist/commands/attach.js.map +1 -0
- package/dist/commands/caddy.d.ts +10 -0
- package/dist/commands/caddy.d.ts.map +1 -0
- package/dist/commands/caddy.js +151 -0
- package/dist/commands/caddy.js.map +1 -0
- package/dist/commands/daemon.d.ts +6 -0
- package/dist/commands/daemon.d.ts.map +1 -0
- package/dist/commands/daemon.js +24 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/down.d.ts +5 -0
- package/dist/commands/down.d.ts.map +1 -0
- package/dist/commands/down.js +25 -0
- package/dist/commands/down.js.map +1 -0
- package/dist/commands/shutdown.d.ts +5 -0
- package/dist/commands/shutdown.d.ts.map +1 -0
- package/dist/commands/shutdown.js +10 -0
- package/dist/commands/shutdown.js.map +1 -0
- package/dist/commands/start.d.ts +6 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +59 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +38 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +6 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +39 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/up.d.ts +8 -0
- package/dist/commands/up.d.ts.map +1 -0
- package/dist/commands/up.js +48 -0
- package/dist/commands/up.js.map +1 -0
- package/dist/config/config.d.ts +13 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +53 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +4 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/state.d.ts +20 -0
- package/dist/config/state.d.ts.map +1 -0
- package/dist/config/state.js +119 -0
- package/dist/config/state.js.map +1 -0
- package/dist/config/types.d.ts +70 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +17 -0
- package/dist/config/types.js.map +1 -0
- package/dist/daemon/index.d.ts +6 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +103 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/portal.d.ts +4 -0
- package/dist/daemon/portal.d.ts.map +1 -0
- package/dist/daemon/portal.js +127 -0
- package/dist/daemon/portal.js.map +1 -0
- package/dist/daemon/proxy.d.ts +7 -0
- package/dist/daemon/proxy.d.ts.map +1 -0
- package/dist/daemon/proxy.js +17 -0
- package/dist/daemon/proxy.js.map +1 -0
- package/dist/daemon/server.d.ts +5 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +172 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/session-manager.d.ts +37 -0
- package/dist/daemon/session-manager.d.ts.map +1 -0
- package/dist/daemon/session-manager.js +131 -0
- package/dist/daemon/session-manager.js.map +1 -0
- package/dist/daemon/session-resolver.d.ts +41 -0
- package/dist/daemon/session-resolver.d.ts.map +1 -0
- package/dist/daemon/session-resolver.js +68 -0
- package/dist/daemon/session-resolver.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/tmux.d.ts +8 -0
- package/dist/tmux.d.ts.map +1 -0
- package/dist/tmux.js +65 -0
- package/dist/tmux.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui.d.ts +25 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +118 -0
- package/dist/ui.js.map +1 -0
- package/dist/utils/errors.d.ts +25 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +52 -0
- package/dist/utils/errors.js.map +1 -0
- package/package.json +69 -0
package/dist/tmux.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TmuxSession } from './types.js';
|
|
2
|
+
export declare function isInsideTmux(): boolean;
|
|
3
|
+
export declare function isTmuxInstalled(): boolean;
|
|
4
|
+
export declare function listSessions(): TmuxSession[];
|
|
5
|
+
export declare function attachSession(sessionName: string): Promise<number>;
|
|
6
|
+
export declare function getCwdSessionName(): string;
|
|
7
|
+
export declare function createSessionFromCwd(): Promise<number>;
|
|
8
|
+
//# sourceMappingURL=tmux.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux.d.ts","sourceRoot":"","sources":["../src/tmux.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,wBAAgB,eAAe,IAAI,OAAO,CAQzC;AAcD,wBAAgB,YAAY,IAAI,WAAW,EAAE,CAY5C;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYlE;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CAYtD"}
|
package/dist/tmux.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { execSync, spawn } from 'node:child_process';
|
|
2
|
+
import { basename } from 'node:path';
|
|
3
|
+
export function isInsideTmux() {
|
|
4
|
+
return !!process.env['TMUX'];
|
|
5
|
+
}
|
|
6
|
+
export function isTmuxInstalled() {
|
|
7
|
+
try {
|
|
8
|
+
execSync('which tmux', { stdio: 'ignore' });
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Expected: tmux is not installed
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const SESSION_FORMAT = '#{session_name}|#{session_windows}|#{session_created}|#{session_attached}';
|
|
17
|
+
function parseSessionLine(line) {
|
|
18
|
+
const [name = '', windows = '0', created = '0', attached] = line.split('|');
|
|
19
|
+
return {
|
|
20
|
+
name,
|
|
21
|
+
windows: Number.parseInt(windows, 10),
|
|
22
|
+
created: new Date(Number.parseInt(created, 10) * 1000),
|
|
23
|
+
attached: attached === '1'
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function listSessions() {
|
|
27
|
+
try {
|
|
28
|
+
const output = execSync(`tmux list-sessions -F "${SESSION_FORMAT}"`, { encoding: 'utf-8' });
|
|
29
|
+
return output
|
|
30
|
+
.trim()
|
|
31
|
+
.split('\n')
|
|
32
|
+
.filter((line) => line.length > 0)
|
|
33
|
+
.map(parseSessionLine);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Expected: no tmux server running or no sessions
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function attachSession(sessionName) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
const command = isInsideTmux() ? 'switch-client' : 'attach-session';
|
|
43
|
+
const tmux = spawn('tmux', [command, '-t', sessionName], {
|
|
44
|
+
stdio: 'inherit'
|
|
45
|
+
});
|
|
46
|
+
tmux.on('close', (code) => {
|
|
47
|
+
resolve(code ?? 0);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
export function getCwdSessionName() {
|
|
52
|
+
return basename(process.cwd());
|
|
53
|
+
}
|
|
54
|
+
export function createSessionFromCwd() {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
const sessionName = getCwdSessionName();
|
|
57
|
+
const tmux = spawn('tmux', ['new', '-A', '-s', sessionName], {
|
|
58
|
+
stdio: 'inherit'
|
|
59
|
+
});
|
|
60
|
+
tmux.on('close', (code) => {
|
|
61
|
+
resolve(code ?? 0);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=tmux.js.map
|
package/dist/tmux.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux.js","sourceRoot":"","sources":["../src/tmux.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CACnB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/ui.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TmuxSession } from './types.js';
|
|
2
|
+
export declare function formatDate(date: Date): string;
|
|
3
|
+
export interface SelectResult {
|
|
4
|
+
action: 'attach' | 'quit';
|
|
5
|
+
session?: TmuxSession;
|
|
6
|
+
}
|
|
7
|
+
export type KeyAction = {
|
|
8
|
+
type: 'quit';
|
|
9
|
+
} | {
|
|
10
|
+
type: 'select';
|
|
11
|
+
index: number;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'move';
|
|
14
|
+
direction: 'up' | 'down';
|
|
15
|
+
} | {
|
|
16
|
+
type: 'none';
|
|
17
|
+
};
|
|
18
|
+
export declare function handleKeypress(key: {
|
|
19
|
+
name?: string;
|
|
20
|
+
ctrl?: boolean;
|
|
21
|
+
} | undefined, sessionsCount: number): KeyAction;
|
|
22
|
+
export declare function findInitialIndex(sessions: TmuxSession[]): number;
|
|
23
|
+
export declare function calculateNewIndex(currentIndex: number, direction: 'up' | 'down', maxIndex: number): number;
|
|
24
|
+
export declare function selectSession(sessions: TmuxSession[]): Promise<SelectResult>;
|
|
25
|
+
//# sourceMappingURL=ui.d.ts.map
|
package/dist/ui.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiB9C,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAM7C;AA2BD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAWrB,wBAAgB,cAAc,CAC5B,GAAG,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EAClD,aAAa,EAAE,MAAM,GACpB,SAAS,CAgBX;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAGhE;AAED,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,IAAI,GAAG,MAAM,EACxB,QAAQ,EAAE,MAAM,GACf,MAAM,CAER;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAoD5E"}
|
package/dist/ui.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as readline from 'node:readline';
|
|
2
|
+
// ANSI escape codes
|
|
3
|
+
const ansi = {
|
|
4
|
+
clearScreen: '\x1b[2J\x1b[H',
|
|
5
|
+
hideCursor: '\x1b[?25l',
|
|
6
|
+
showCursor: '\x1b[?25h',
|
|
7
|
+
bold: '\x1b[1m',
|
|
8
|
+
dim: '\x1b[2m',
|
|
9
|
+
reset: '\x1b[0m',
|
|
10
|
+
cyan: '\x1b[36m',
|
|
11
|
+
yellow: '\x1b[33m',
|
|
12
|
+
green: '\x1b[32m'
|
|
13
|
+
};
|
|
14
|
+
const pad2 = (n) => String(n).padStart(2, '0');
|
|
15
|
+
export function formatDate(date) {
|
|
16
|
+
const month = pad2(date.getMonth() + 1);
|
|
17
|
+
const day = pad2(date.getDate());
|
|
18
|
+
const hours = pad2(date.getHours());
|
|
19
|
+
const minutes = pad2(date.getMinutes());
|
|
20
|
+
return `${month}/${day} ${hours}:${minutes}`;
|
|
21
|
+
}
|
|
22
|
+
function formatSessionLine(session, index, isSelected) {
|
|
23
|
+
const prefix = isSelected ? `${ansi.cyan}>${ansi.reset}` : ' ';
|
|
24
|
+
const num = `${ansi.yellow}[${index + 1}]${ansi.reset}`;
|
|
25
|
+
const name = isSelected
|
|
26
|
+
? `${ansi.cyan}${ansi.bold}${session.name}${ansi.reset}`
|
|
27
|
+
: `${ansi.bold}${session.name}${ansi.reset}`;
|
|
28
|
+
const windowLabel = session.windows === 1 ? 'window' : 'windows';
|
|
29
|
+
const windows = `${ansi.dim}${session.windows} ${windowLabel}${ansi.reset}`;
|
|
30
|
+
const created = `${ansi.dim}(${formatDate(session.created)})${ansi.reset}`;
|
|
31
|
+
const attached = session.attached ? ` ${ansi.green}*attached*${ansi.reset}` : '';
|
|
32
|
+
return `${prefix} ${num} ${name.padEnd(20)} ${windows} ${created}${attached}`;
|
|
33
|
+
}
|
|
34
|
+
function renderSessions(sessions, selectedIndex) {
|
|
35
|
+
process.stdout.write(ansi.clearScreen);
|
|
36
|
+
console.log(`${ansi.bold}tmux sessions:${ansi.reset}\n`);
|
|
37
|
+
for (const [index, session] of sessions.entries()) {
|
|
38
|
+
console.log(formatSessionLine(session, index, index === selectedIndex));
|
|
39
|
+
}
|
|
40
|
+
console.log(`\n${ansi.dim}↑↓/jk: move 1-9: quick select Enter: attach q: quit${ansi.reset}`);
|
|
41
|
+
}
|
|
42
|
+
const keyBindings = {
|
|
43
|
+
q: { type: 'quit' },
|
|
44
|
+
up: { type: 'move', direction: 'up' },
|
|
45
|
+
k: { type: 'move', direction: 'up' },
|
|
46
|
+
down: { type: 'move', direction: 'down' },
|
|
47
|
+
j: { type: 'move', direction: 'down' },
|
|
48
|
+
return: { type: 'select', index: -1 }
|
|
49
|
+
};
|
|
50
|
+
export function handleKeypress(key, sessionsCount) {
|
|
51
|
+
if (!key?.name)
|
|
52
|
+
return { type: 'none' };
|
|
53
|
+
if (key.ctrl && key.name === 'c') {
|
|
54
|
+
return { type: 'quit' };
|
|
55
|
+
}
|
|
56
|
+
const binding = keyBindings[key.name];
|
|
57
|
+
if (binding)
|
|
58
|
+
return binding;
|
|
59
|
+
const num = Number.parseInt(key.name, 10);
|
|
60
|
+
if (num >= 1 && num <= 9 && num <= sessionsCount) {
|
|
61
|
+
return { type: 'select', index: num - 1 };
|
|
62
|
+
}
|
|
63
|
+
return { type: 'none' };
|
|
64
|
+
}
|
|
65
|
+
export function findInitialIndex(sessions) {
|
|
66
|
+
const attachedIndex = sessions.findIndex((s) => s.attached);
|
|
67
|
+
return attachedIndex !== -1 ? attachedIndex : 0;
|
|
68
|
+
}
|
|
69
|
+
export function calculateNewIndex(currentIndex, direction, maxIndex) {
|
|
70
|
+
return direction === 'up' ? Math.max(0, currentIndex - 1) : Math.min(maxIndex, currentIndex + 1);
|
|
71
|
+
}
|
|
72
|
+
export function selectSession(sessions) {
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
if (sessions.length === 0) {
|
|
75
|
+
console.log('No tmux sessions found.');
|
|
76
|
+
resolve({ action: 'quit' });
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let selectedIndex = findInitialIndex(sessions);
|
|
80
|
+
process.stdout.write(ansi.hideCursor);
|
|
81
|
+
renderSessions(sessions, selectedIndex);
|
|
82
|
+
readline.emitKeypressEvents(process.stdin);
|
|
83
|
+
if (process.stdin.isTTY) {
|
|
84
|
+
process.stdin.setRawMode(true);
|
|
85
|
+
}
|
|
86
|
+
const cleanupAndResolve = (result) => {
|
|
87
|
+
process.stdout.write(ansi.showCursor);
|
|
88
|
+
if (process.stdin.isTTY) {
|
|
89
|
+
process.stdin.setRawMode(false);
|
|
90
|
+
}
|
|
91
|
+
process.stdin.removeListener('keypress', onKeypress);
|
|
92
|
+
process.stdout.write(ansi.clearScreen);
|
|
93
|
+
resolve(result);
|
|
94
|
+
};
|
|
95
|
+
const onKeypress = (_str, key) => {
|
|
96
|
+
const action = handleKeypress(key, sessions.length);
|
|
97
|
+
switch (action.type) {
|
|
98
|
+
case 'quit':
|
|
99
|
+
cleanupAndResolve({ action: 'quit' });
|
|
100
|
+
break;
|
|
101
|
+
case 'move':
|
|
102
|
+
selectedIndex = calculateNewIndex(selectedIndex, action.direction, sessions.length - 1);
|
|
103
|
+
renderSessions(sessions, selectedIndex);
|
|
104
|
+
break;
|
|
105
|
+
case 'select':
|
|
106
|
+
cleanupAndResolve({
|
|
107
|
+
action: 'attach',
|
|
108
|
+
session: sessions[action.index === -1 ? selectedIndex : action.index]
|
|
109
|
+
});
|
|
110
|
+
break;
|
|
111
|
+
case 'none':
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
process.stdin.on('keypress', onKeypress);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=ui.js.map
|
package/dist/ui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application-specific error class with structured error information
|
|
3
|
+
*/
|
|
4
|
+
export declare class AppError extends Error {
|
|
5
|
+
readonly code?: string;
|
|
6
|
+
constructor(message: string, code?: string, cause?: unknown);
|
|
7
|
+
static wrap(error: unknown, message: string, code?: string): AppError;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Extract error message from unknown error type
|
|
11
|
+
*/
|
|
12
|
+
export declare function getErrorMessage(error: unknown): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format error for CLI output
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatCliError(prefix: string, error: unknown): string;
|
|
17
|
+
/**
|
|
18
|
+
* Handle CLI command errors consistently
|
|
19
|
+
*/
|
|
20
|
+
export declare function handleCliError(prefix: string, error: unknown): void;
|
|
21
|
+
/**
|
|
22
|
+
* Wrap a function with error handling
|
|
23
|
+
*/
|
|
24
|
+
export declare function withErrorHandling<T>(fn: () => Promise<T>, errorPrefix: string): Promise<T | null>;
|
|
25
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;gBAElB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;IAM3D,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ;CAGtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQtD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAErE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGnE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAOnB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application-specific error class with structured error information
|
|
3
|
+
*/
|
|
4
|
+
export class AppError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
constructor(message, code, cause) {
|
|
7
|
+
super(message, { cause });
|
|
8
|
+
this.name = 'AppError';
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
static wrap(error, message, code) {
|
|
12
|
+
return new AppError(message, code, error);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract error message from unknown error type
|
|
17
|
+
*/
|
|
18
|
+
export function getErrorMessage(error) {
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
return error.message;
|
|
21
|
+
}
|
|
22
|
+
if (typeof error === 'string') {
|
|
23
|
+
return error;
|
|
24
|
+
}
|
|
25
|
+
return 'Unknown error';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Format error for CLI output
|
|
29
|
+
*/
|
|
30
|
+
export function formatCliError(prefix, error) {
|
|
31
|
+
return `${prefix}: ${getErrorMessage(error)}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Handle CLI command errors consistently
|
|
35
|
+
*/
|
|
36
|
+
export function handleCliError(prefix, error) {
|
|
37
|
+
// biome-ignore lint/suspicious/noConsole: CLI error output is intentional
|
|
38
|
+
console.error(formatCliError(prefix, error));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Wrap a function with error handling
|
|
42
|
+
*/
|
|
43
|
+
export async function withErrorHandling(fn, errorPrefix) {
|
|
44
|
+
try {
|
|
45
|
+
return await fn();
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
handleCliError(errorPrefix, error);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjB,IAAI,CAAU;IAE9B,YAAY,OAAe,EAAE,IAAa,EAAE,KAAe;QACzD,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,KAAc,EAAE,OAAe,EAAE,IAAa;QACxD,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,KAAc;IAC3D,OAAO,GAAG,MAAM,KAAK,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,KAAc;IAC3D,0EAA0E;IAC1E,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,EAAoB,EACpB,WAAmB;IAEnB,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,cAAc,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ttyd-mux",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "ttyd session multiplexer - manage multiple ttyd+tmux sessions",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"ttyd-mux": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"dev": "bun run src/index.ts",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
14
|
+
"check": "biome check ./src",
|
|
15
|
+
"check:fix": "biome check ./src --write",
|
|
16
|
+
"format": "biome format ./src --write",
|
|
17
|
+
"test": "bun test src/",
|
|
18
|
+
"test:watch": "bun test src/ --watch",
|
|
19
|
+
"test:e2e": "bunx playwright test",
|
|
20
|
+
"test:e2e:headed": "bunx playwright test --headed",
|
|
21
|
+
"test:e2e:debug": "bunx playwright test --debug",
|
|
22
|
+
"validate": "bun run typecheck && bun run check && bun run test",
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"build:binary": "bun build src/index.ts --compile --outfile ttyd-mux",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@biomejs/biome": "^1.9.0",
|
|
29
|
+
"@playwright/test": "^1.58.2",
|
|
30
|
+
"@types/bun": "latest",
|
|
31
|
+
"@types/http-proxy": "^1.17.14",
|
|
32
|
+
"@types/node": "^22.0.0",
|
|
33
|
+
"@types/proper-lockfile": "^4.1.4",
|
|
34
|
+
"playwright": "^1.58.2",
|
|
35
|
+
"typescript": "^5.6.0"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"ttyd",
|
|
45
|
+
"tmux",
|
|
46
|
+
"terminal",
|
|
47
|
+
"multiplexer",
|
|
48
|
+
"cli",
|
|
49
|
+
"web-terminal",
|
|
50
|
+
"session-manager"
|
|
51
|
+
],
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/cuzic/ttyd-mux.git"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/cuzic/ttyd-mux#readme",
|
|
58
|
+
"bugs": {
|
|
59
|
+
"url": "https://github.com/cuzic/ttyd-mux/issues"
|
|
60
|
+
},
|
|
61
|
+
"author": "cuzic",
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"commander": "^14.0.2",
|
|
64
|
+
"http-proxy": "^1.18.1",
|
|
65
|
+
"proper-lockfile": "^4.1.2",
|
|
66
|
+
"yaml": "^2.6.0",
|
|
67
|
+
"zod": "^4.3.6"
|
|
68
|
+
}
|
|
69
|
+
}
|