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.
Files changed (106) hide show
  1. package/README.md +222 -0
  2. package/dist/caddy/client.d.ts +84 -0
  3. package/dist/caddy/client.d.ts.map +1 -0
  4. package/dist/caddy/client.js +144 -0
  5. package/dist/caddy/client.js.map +1 -0
  6. package/dist/client/index.d.ts +11 -0
  7. package/dist/client/index.d.ts.map +1 -0
  8. package/dist/client/index.js +124 -0
  9. package/dist/client/index.js.map +1 -0
  10. package/dist/commands/attach.d.ts +5 -0
  11. package/dist/commands/attach.d.ts.map +1 -0
  12. package/dist/commands/attach.js +100 -0
  13. package/dist/commands/attach.js.map +1 -0
  14. package/dist/commands/caddy.d.ts +10 -0
  15. package/dist/commands/caddy.d.ts.map +1 -0
  16. package/dist/commands/caddy.js +151 -0
  17. package/dist/commands/caddy.js.map +1 -0
  18. package/dist/commands/daemon.d.ts +6 -0
  19. package/dist/commands/daemon.d.ts.map +1 -0
  20. package/dist/commands/daemon.js +24 -0
  21. package/dist/commands/daemon.js.map +1 -0
  22. package/dist/commands/down.d.ts +5 -0
  23. package/dist/commands/down.d.ts.map +1 -0
  24. package/dist/commands/down.js +25 -0
  25. package/dist/commands/down.js.map +1 -0
  26. package/dist/commands/shutdown.d.ts +5 -0
  27. package/dist/commands/shutdown.d.ts.map +1 -0
  28. package/dist/commands/shutdown.js +10 -0
  29. package/dist/commands/shutdown.js.map +1 -0
  30. package/dist/commands/start.d.ts +6 -0
  31. package/dist/commands/start.d.ts.map +1 -0
  32. package/dist/commands/start.js +59 -0
  33. package/dist/commands/start.js.map +1 -0
  34. package/dist/commands/status.d.ts +5 -0
  35. package/dist/commands/status.d.ts.map +1 -0
  36. package/dist/commands/status.js +38 -0
  37. package/dist/commands/status.js.map +1 -0
  38. package/dist/commands/stop.d.ts +6 -0
  39. package/dist/commands/stop.d.ts.map +1 -0
  40. package/dist/commands/stop.js +39 -0
  41. package/dist/commands/stop.js.map +1 -0
  42. package/dist/commands/up.d.ts +8 -0
  43. package/dist/commands/up.d.ts.map +1 -0
  44. package/dist/commands/up.js +48 -0
  45. package/dist/commands/up.js.map +1 -0
  46. package/dist/config/config.d.ts +13 -0
  47. package/dist/config/config.d.ts.map +1 -0
  48. package/dist/config/config.js +53 -0
  49. package/dist/config/config.js.map +1 -0
  50. package/dist/config/index.d.ts +4 -0
  51. package/dist/config/index.d.ts.map +1 -0
  52. package/dist/config/index.js +4 -0
  53. package/dist/config/index.js.map +1 -0
  54. package/dist/config/state.d.ts +20 -0
  55. package/dist/config/state.d.ts.map +1 -0
  56. package/dist/config/state.js +119 -0
  57. package/dist/config/state.js.map +1 -0
  58. package/dist/config/types.d.ts +70 -0
  59. package/dist/config/types.d.ts.map +1 -0
  60. package/dist/config/types.js +17 -0
  61. package/dist/config/types.js.map +1 -0
  62. package/dist/daemon/index.d.ts +6 -0
  63. package/dist/daemon/index.d.ts.map +1 -0
  64. package/dist/daemon/index.js +103 -0
  65. package/dist/daemon/index.js.map +1 -0
  66. package/dist/daemon/portal.d.ts +4 -0
  67. package/dist/daemon/portal.d.ts.map +1 -0
  68. package/dist/daemon/portal.js +127 -0
  69. package/dist/daemon/portal.js.map +1 -0
  70. package/dist/daemon/proxy.d.ts +7 -0
  71. package/dist/daemon/proxy.d.ts.map +1 -0
  72. package/dist/daemon/proxy.js +17 -0
  73. package/dist/daemon/proxy.js.map +1 -0
  74. package/dist/daemon/server.d.ts +5 -0
  75. package/dist/daemon/server.d.ts.map +1 -0
  76. package/dist/daemon/server.js +172 -0
  77. package/dist/daemon/server.js.map +1 -0
  78. package/dist/daemon/session-manager.d.ts +37 -0
  79. package/dist/daemon/session-manager.d.ts.map +1 -0
  80. package/dist/daemon/session-manager.js +131 -0
  81. package/dist/daemon/session-manager.js.map +1 -0
  82. package/dist/daemon/session-resolver.d.ts +41 -0
  83. package/dist/daemon/session-resolver.d.ts.map +1 -0
  84. package/dist/daemon/session-resolver.js +68 -0
  85. package/dist/daemon/session-resolver.js.map +1 -0
  86. package/dist/index.d.ts +3 -0
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +95 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/tmux.d.ts +8 -0
  91. package/dist/tmux.d.ts.map +1 -0
  92. package/dist/tmux.js +65 -0
  93. package/dist/tmux.js.map +1 -0
  94. package/dist/types.d.ts +7 -0
  95. package/dist/types.d.ts.map +1 -0
  96. package/dist/types.js +2 -0
  97. package/dist/types.js.map +1 -0
  98. package/dist/ui.d.ts +25 -0
  99. package/dist/ui.d.ts.map +1 -0
  100. package/dist/ui.js +118 -0
  101. package/dist/ui.js.map +1 -0
  102. package/dist/utils/errors.d.ts +25 -0
  103. package/dist/utils/errors.d.ts.map +1 -0
  104. package/dist/utils/errors.js +52 -0
  105. package/dist/utils/errors.js.map +1 -0
  106. package/package.json +69 -0
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # ttyd-mux
2
+
3
+ ttyd session multiplexer - 複数の ttyd+tmux セッションを管理するCLIツール
4
+
5
+ ## 概要
6
+
7
+ ttyd-mux は、複数の Web ターミナル(ttyd)セッションを簡単に管理するためのツールです。
8
+
9
+ - カレントディレクトリで `ttyd-mux up` するだけでブラウザアクセス可能なターミナルを起動
10
+ - 複数セッションを一元管理するポータルページを提供
11
+ - Caddy などのリバースプロキシと連携して外部公開
12
+
13
+ ## インストール
14
+
15
+ ```bash
16
+ # npm でグローバルインストール
17
+ npm install -g ttyd-mux
18
+
19
+ # または npx で直接実行
20
+ npx ttyd-mux up
21
+ ```
22
+
23
+ ### 必要な依存関係
24
+
25
+ - **Node.js** 18 以上(または Bun)
26
+ - **ttyd**: https://github.com/tsl0922/ttyd
27
+ - **tmux**: ターミナルマルチプレクサ
28
+
29
+ ```bash
30
+ # Ubuntu/Debian
31
+ sudo apt install ttyd tmux
32
+
33
+ # macOS (Homebrew)
34
+ brew install ttyd tmux
35
+ ```
36
+
37
+ ## クイックスタート
38
+
39
+ ```bash
40
+ # プロジェクトディレクトリで起動
41
+ cd ~/my-project
42
+ ttyd-mux up
43
+
44
+ # ブラウザでアクセス
45
+ # http://localhost:7680/ttyd-mux/my-project/
46
+
47
+ # 状態確認
48
+ ttyd-mux status
49
+
50
+ # 停止
51
+ ttyd-mux down
52
+ ```
53
+
54
+ ## コマンド
55
+
56
+ ### メインコマンド
57
+
58
+ ```bash
59
+ ttyd-mux up [--name <name>] # セッション起動 → 自動アタッチ
60
+ ttyd-mux up --detach # セッション起動のみ(アタッチしない)
61
+ ttyd-mux down # カレントディレクトリのセッション停止
62
+ ```
63
+
64
+ ### セッション管理
65
+
66
+ ```bash
67
+ ttyd-mux start <name> # 事前定義セッションを起動
68
+ ttyd-mux start --all # 全ての事前定義セッションを起動
69
+ ttyd-mux stop <name> # セッション停止
70
+ ttyd-mux stop --all # 全セッション停止
71
+ ttyd-mux status # 状態表示
72
+ ```
73
+
74
+ ### 直接アクセス
75
+
76
+ ```bash
77
+ ttyd-mux attach [name] # tmuxセッションに直接アタッチ
78
+ ```
79
+
80
+ ### デーモン制御
81
+
82
+ ```bash
83
+ ttyd-mux daemon # デーモン起動
84
+ ttyd-mux daemon -f # フォアグラウンドで起動(デバッグ用)
85
+ ttyd-mux shutdown # デーモン終了
86
+ ```
87
+
88
+ ### 設定生成
89
+
90
+ ```bash
91
+ ttyd-mux generate caddy # Caddyfile生成
92
+ ttyd-mux generate caddy -o Caddyfile --hostname example.com
93
+ ```
94
+
95
+ ## 設定
96
+
97
+ 設定ファイルは以下の順序で検索されます:
98
+
99
+ 1. `./ttyd-mux.yaml`
100
+ 2. `./.ttyd-mux.yaml`
101
+ 3. `~/.config/ttyd-mux/config.yaml`
102
+
103
+ ### 設定例
104
+
105
+ ```yaml
106
+ # ~/.config/ttyd-mux/config.yaml
107
+
108
+ # URLパスのプレフィックス
109
+ base_path: /ttyd-mux
110
+
111
+ # ttydセッションのベースポート
112
+ base_port: 7600
113
+
114
+ # デーモンのHTTPポート
115
+ daemon_port: 7680
116
+
117
+ # リッスンアドレス(デフォルト: IPv4 + IPv6 localhost)
118
+ listen_addresses:
119
+ - "127.0.0.1"
120
+ - "::1"
121
+ # - "0.0.0.0" # 外部からのアクセスを許可する場合
122
+
123
+ # セッション起動時に自動でtmuxにアタッチ(デフォルト: true)
124
+ auto_attach: true
125
+
126
+ # 事前定義セッション(オプション)
127
+ sessions:
128
+ - name: project-a
129
+ dir: /home/user/project-a
130
+ path: /project-a
131
+ port_offset: 1
132
+
133
+ - name: project-b
134
+ dir: /home/user/project-b
135
+ path: /project-b
136
+ port_offset: 2
137
+ ```
138
+
139
+ ## アーキテクチャ
140
+
141
+ ```
142
+ ┌─────────────────┐
143
+ │ ttyd :7601 │
144
+ │ (-b /ttyd-mux/ │
145
+ ┌─────────┐ ┌──────────────┐ │ project-a) │
146
+ │ Caddy │──────│ ttyd-mux │───┼─────────────────┤
147
+ │ │ │ daemon │ │ ttyd :7602 │
148
+ │ :443 │ │ :7680 │ │ (-b /ttyd-mux/ │
149
+ └─────────┘ │ │ │ project-b) │
150
+ │ - Portal │ └─────────────────┘
151
+ │ - Proxy │
152
+ │ - API │
153
+ └──────────────┘
154
+ ```
155
+
156
+ - **Caddy**: 外部からのリクエストを ttyd-mux に転送
157
+ - **ttyd-mux daemon**: ポータル表示 + ttyd へのリバースプロキシ
158
+ - **ttyd**: 各セッションの Web ターミナル(tmux を起動)
159
+
160
+ ## Caddy との連携
161
+
162
+ ### Admin API で設定(推奨)
163
+
164
+ ```bash
165
+ # ルートを追加
166
+ ttyd-mux caddy setup --hostname example.com
167
+
168
+ # 設定を確認
169
+ ttyd-mux caddy status
170
+
171
+ # ルートを削除
172
+ ttyd-mux caddy remove --hostname example.com
173
+ ```
174
+
175
+ ### Caddyfile 手動編集
176
+
177
+ ```bash
178
+ # コピペ用スニペットを表示
179
+ ttyd-mux caddy snippet
180
+ ```
181
+
182
+ ```caddyfile
183
+ handle /ttyd-mux/* {
184
+ reverse_proxy 127.0.0.1:7680
185
+ }
186
+ ```
187
+
188
+ 詳細は [docs/caddy-setup.md](docs/caddy-setup.md) を参照。
189
+
190
+ ## ファイル構成
191
+
192
+ ```
193
+ ~/.config/ttyd-mux/
194
+ config.yaml # 設定ファイル
195
+
196
+ ~/.local/state/ttyd-mux/
197
+ state.json # 実行中セッションの状態
198
+ ttyd-mux.sock # デーモン通信用ソケット
199
+ ```
200
+
201
+ ## 開発
202
+
203
+ ```bash
204
+ # 開発実行
205
+ bun run src/index.ts <command>
206
+
207
+ # テスト
208
+ bun test
209
+
210
+ # 型チェック
211
+ bun run typecheck
212
+
213
+ # リント
214
+ bun run check
215
+
216
+ # ビルド(単一実行ファイル)
217
+ bun build src/index.ts --compile --outfile ttyd-mux
218
+ ```
219
+
220
+ ## ライセンス
221
+
222
+ MIT
@@ -0,0 +1,84 @@
1
+ export interface CaddyConfig {
2
+ apps?: {
3
+ http?: {
4
+ servers?: Record<string, CaddyServer>;
5
+ };
6
+ };
7
+ }
8
+ export interface CaddyServer {
9
+ listen?: string[];
10
+ routes?: CaddyRoute[];
11
+ }
12
+ export interface CaddyRoute {
13
+ match?: CaddyMatch[];
14
+ handle?: CaddyHandler[];
15
+ }
16
+ export interface CaddyMatch {
17
+ host?: string[];
18
+ path?: string[];
19
+ }
20
+ export interface CaddyHandler {
21
+ handler: string;
22
+ upstreams?: Array<{
23
+ dial: string;
24
+ }>;
25
+ body?: string;
26
+ }
27
+ export declare const DEFAULT_ADMIN_API = "http://localhost:2019";
28
+ /**
29
+ * Client for Caddy Admin API
30
+ */
31
+ export declare class CaddyClient {
32
+ private adminApi;
33
+ constructor(adminApi?: string);
34
+ /**
35
+ * Get current Caddy configuration
36
+ */
37
+ getConfig(): Promise<CaddyConfig>;
38
+ /**
39
+ * Get all HTTP servers
40
+ */
41
+ getServers(): Promise<Record<string, CaddyServer>>;
42
+ /**
43
+ * Update routes for a server
44
+ */
45
+ updateServerRoutes(serverName: string, routes: CaddyRoute[]): Promise<void>;
46
+ /**
47
+ * Create a new server
48
+ */
49
+ createServer(serverName: string, server: CaddyServer): Promise<void>;
50
+ /**
51
+ * Find server that handles a specific hostname
52
+ */
53
+ findServerForHost(servers: Record<string, CaddyServer>, hostname: string): {
54
+ name: string;
55
+ server: CaddyServer;
56
+ } | null;
57
+ /**
58
+ * Check if a route exists for hostname and path
59
+ */
60
+ routeExists(server: CaddyServer, hostname: string, basePath: string): boolean;
61
+ /**
62
+ * Create a reverse proxy route
63
+ */
64
+ createProxyRoute(hostname: string, basePath: string, upstream: string): CaddyRoute;
65
+ /**
66
+ * Extract upstream from route handlers
67
+ */
68
+ private extractUpstream;
69
+ /**
70
+ * Find ttyd-mux routes in all servers
71
+ */
72
+ findTtydMuxRoutes(servers: Record<string, CaddyServer>, basePath: string): Array<{
73
+ serverName: string;
74
+ hosts: string[];
75
+ paths: string[];
76
+ upstream: string;
77
+ }>;
78
+ }
79
+ /**
80
+ * Connect to Caddy Admin API and return client
81
+ * Throws error if connection fails
82
+ */
83
+ export declare function connectToCaddy(adminApi?: string): Promise<CaddyClient>;
84
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/caddy/client.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE;QACL,IAAI,CAAC,EAAE;YACL,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;SACvC,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,iBAAiB,0BAA0B,CAAC;AAEzD;;GAEG;AACH,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ;gBAAR,QAAQ,GAAE,MAA0B;IAExD;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC;IAQvC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAKxD;;OAEG;IACG,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAajF;;OAEG;IACG,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1E;;OAEG;IACH,iBAAiB,CACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACpC,QAAQ,EAAE,MAAM,GACf;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI;IAe/C;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAU7E;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU;IAiBlF;;OAEG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,iBAAiB,CACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACpC,QAAQ,EAAE,MAAM,GACf,KAAK,CAAC;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CAuBH;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,QAAQ,GAAE,MAA0B,GAAG,OAAO,CAAC,WAAW,CAAC,CAS/F"}
@@ -0,0 +1,144 @@
1
+ export const DEFAULT_ADMIN_API = 'http://localhost:2019';
2
+ /**
3
+ * Client for Caddy Admin API
4
+ */
5
+ export class CaddyClient {
6
+ adminApi;
7
+ constructor(adminApi = DEFAULT_ADMIN_API) {
8
+ this.adminApi = adminApi;
9
+ }
10
+ /**
11
+ * Get current Caddy configuration
12
+ */
13
+ async getConfig() {
14
+ const response = await fetch(`${this.adminApi}/config/`);
15
+ if (!response.ok) {
16
+ throw new Error(`Failed to get config: ${response.status}`);
17
+ }
18
+ return (await response.json());
19
+ }
20
+ /**
21
+ * Get all HTTP servers
22
+ */
23
+ async getServers() {
24
+ const config = await this.getConfig();
25
+ return config.apps?.http?.servers ?? {};
26
+ }
27
+ /**
28
+ * Update routes for a server
29
+ */
30
+ async updateServerRoutes(serverName, routes) {
31
+ const response = await fetch(`${this.adminApi}/config/apps/http/servers/${serverName}/routes`, {
32
+ method: 'PUT',
33
+ headers: { 'Content-Type': 'application/json' },
34
+ body: JSON.stringify(routes)
35
+ });
36
+ if (!response.ok) {
37
+ const text = await response.text();
38
+ throw new Error(`Failed to update routes: ${response.status} ${text}`);
39
+ }
40
+ }
41
+ /**
42
+ * Create a new server
43
+ */
44
+ async createServer(serverName, server) {
45
+ const response = await fetch(`${this.adminApi}/config/apps/http/servers/${serverName}`, {
46
+ method: 'PUT',
47
+ headers: { 'Content-Type': 'application/json' },
48
+ body: JSON.stringify(server)
49
+ });
50
+ if (!response.ok) {
51
+ const text = await response.text();
52
+ throw new Error(`Failed to create server: ${response.status} ${text}`);
53
+ }
54
+ }
55
+ /**
56
+ * Find server that handles a specific hostname
57
+ */
58
+ findServerForHost(servers, hostname) {
59
+ for (const [name, server] of Object.entries(servers)) {
60
+ const routes = server.routes ?? [];
61
+ for (const route of routes) {
62
+ const matches = route.match ?? [];
63
+ for (const match of matches) {
64
+ if (match.host?.includes(hostname)) {
65
+ return { name, server };
66
+ }
67
+ }
68
+ }
69
+ }
70
+ return null;
71
+ }
72
+ /**
73
+ * Check if a route exists for hostname and path
74
+ */
75
+ routeExists(server, hostname, basePath) {
76
+ const routes = server.routes ?? [];
77
+ return routes.some((route) => {
78
+ const matches = route.match ?? [];
79
+ return matches.some((m) => m.host?.includes(hostname) && m.path?.some((p) => p.startsWith(basePath)));
80
+ });
81
+ }
82
+ /**
83
+ * Create a reverse proxy route
84
+ */
85
+ createProxyRoute(hostname, basePath, upstream) {
86
+ return {
87
+ match: [
88
+ {
89
+ host: [hostname],
90
+ path: [`${basePath}/*`]
91
+ }
92
+ ],
93
+ handle: [
94
+ {
95
+ handler: 'reverse_proxy',
96
+ upstreams: [{ dial: upstream }]
97
+ }
98
+ ]
99
+ };
100
+ }
101
+ /**
102
+ * Extract upstream from route handlers
103
+ */
104
+ extractUpstream(route) {
105
+ const handlers = route.handle ?? [];
106
+ const proxyHandler = handlers.find((h) => h.handler === 'reverse_proxy');
107
+ return proxyHandler?.upstreams?.[0]?.dial ?? 'unknown';
108
+ }
109
+ /**
110
+ * Find ttyd-mux routes in all servers
111
+ */
112
+ findTtydMuxRoutes(servers, basePath) {
113
+ const results = [];
114
+ for (const [serverName, server] of Object.entries(servers)) {
115
+ for (const route of server.routes ?? []) {
116
+ for (const match of route.match ?? []) {
117
+ const paths = match.path ?? [];
118
+ if (paths.some((p) => p.startsWith(basePath))) {
119
+ const hosts = match.host ?? ['*'];
120
+ const upstream = this.extractUpstream(route);
121
+ results.push({ serverName, hosts, paths, upstream });
122
+ }
123
+ }
124
+ }
125
+ }
126
+ return results;
127
+ }
128
+ }
129
+ /**
130
+ * Connect to Caddy Admin API and return client
131
+ * Throws error if connection fails
132
+ */
133
+ export async function connectToCaddy(adminApi = DEFAULT_ADMIN_API) {
134
+ const client = new CaddyClient(adminApi);
135
+ // Test connection by getting config
136
+ try {
137
+ await client.getConfig();
138
+ }
139
+ catch {
140
+ throw new Error(`Cannot connect to Caddy Admin API at ${adminApi}`);
141
+ }
142
+ return client;
143
+ }
144
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/caddy/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Config, SessionResponse, StartSessionRequest, StatusResponse } from '../config/types.js';
2
+ export declare function isDaemonRunning(): Promise<boolean>;
3
+ export declare function ensureDaemon(configPath?: string): Promise<void>;
4
+ export declare function shutdownDaemon(): Promise<void>;
5
+ export declare function apiRequest<T>(config: Config, method: string, path: string, body?: unknown): Promise<T>;
6
+ export declare function getStatus(config: Config): Promise<StatusResponse>;
7
+ export declare function getSessions(config: Config): Promise<SessionResponse[]>;
8
+ export declare function startSession(config: Config, request: StartSessionRequest): Promise<SessionResponse>;
9
+ export declare function stopSession(config: Config, name: string): Promise<void>;
10
+ export declare function requestShutdown(config: Config): Promise<void>;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,mBAAmB,EACnB,cAAc,EACf,MAAM,oBAAoB,CAAC;AAK5B,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CA6BxD;AAED,wBAAsB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BrE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA4BpD;AAUD,wBAAsB,UAAU,CAAC,CAAC,EAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAEvE;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAE5E;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAE1B;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnE"}
@@ -0,0 +1,124 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { connect } from 'node:net';
4
+ import { getDaemonState, getSocketPath } from '../config/state.js';
5
+ const DAEMON_START_TIMEOUT = 5000;
6
+ const DAEMON_CHECK_INTERVAL = 100;
7
+ export async function isDaemonRunning() {
8
+ const socketPath = getSocketPath();
9
+ if (!existsSync(socketPath)) {
10
+ return false;
11
+ }
12
+ return new Promise((resolve) => {
13
+ const socket = connect(socketPath);
14
+ socket.on('connect', () => {
15
+ socket.write('ping');
16
+ });
17
+ socket.on('data', (data) => {
18
+ const response = data.toString().trim();
19
+ socket.end();
20
+ resolve(response === 'pong');
21
+ });
22
+ socket.on('error', () => {
23
+ resolve(false);
24
+ });
25
+ socket.setTimeout(1000, () => {
26
+ socket.destroy();
27
+ resolve(false);
28
+ });
29
+ });
30
+ }
31
+ export async function ensureDaemon(configPath) {
32
+ if (await isDaemonRunning()) {
33
+ return;
34
+ }
35
+ // Find the path to the daemon script
36
+ const daemonScript = new URL('../daemon/index.js', import.meta.url).pathname;
37
+ // Spawn daemon in background (use same runtime as current process)
38
+ const child = spawn(process.execPath, [daemonScript], {
39
+ detached: true,
40
+ stdio: 'ignore',
41
+ env: {
42
+ ...process.env,
43
+ TTYD_MUX_CONFIG: configPath ?? ''
44
+ }
45
+ });
46
+ child.unref();
47
+ // Wait for daemon to be ready
48
+ const startTime = Date.now();
49
+ while (Date.now() - startTime < DAEMON_START_TIMEOUT) {
50
+ if (await isDaemonRunning()) {
51
+ return;
52
+ }
53
+ await sleep(DAEMON_CHECK_INTERVAL);
54
+ }
55
+ throw new Error('Failed to start daemon: timeout');
56
+ }
57
+ export async function shutdownDaemon() {
58
+ const socketPath = getSocketPath();
59
+ if (!existsSync(socketPath)) {
60
+ return;
61
+ }
62
+ return new Promise((resolve, reject) => {
63
+ const socket = connect(socketPath);
64
+ socket.on('connect', () => {
65
+ socket.write('shutdown');
66
+ });
67
+ socket.on('data', (data) => {
68
+ const response = data.toString().trim();
69
+ socket.end();
70
+ if (response === 'ok') {
71
+ resolve();
72
+ }
73
+ else {
74
+ reject(new Error('Unexpected response'));
75
+ }
76
+ });
77
+ socket.on('error', (err) => {
78
+ reject(err);
79
+ });
80
+ });
81
+ }
82
+ // === HTTP API Client ===
83
+ function getDaemonUrl(config) {
84
+ const daemon = getDaemonState();
85
+ const port = daemon?.port ?? config.daemon_port;
86
+ return `http://localhost:${port}`;
87
+ }
88
+ export async function apiRequest(config, method, path, body) {
89
+ const url = `${getDaemonUrl(config)}${config.base_path}${path}`;
90
+ const response = await fetch(url, {
91
+ method,
92
+ headers: body ? { 'Content-Type': 'application/json' } : undefined,
93
+ body: body ? JSON.stringify(body) : undefined
94
+ });
95
+ const data = await response.json();
96
+ if (!response.ok) {
97
+ throw new Error(data.error ?? 'Request failed');
98
+ }
99
+ return data;
100
+ }
101
+ export async function getStatus(config) {
102
+ return apiRequest(config, 'GET', '/api/status');
103
+ }
104
+ export async function getSessions(config) {
105
+ return apiRequest(config, 'GET', '/api/sessions');
106
+ }
107
+ export async function startSession(config, request) {
108
+ return apiRequest(config, 'POST', '/api/sessions', request);
109
+ }
110
+ export async function stopSession(config, name) {
111
+ await apiRequest(config, 'DELETE', `/api/sessions/${encodeURIComponent(name)}`);
112
+ }
113
+ export async function requestShutdown(config) {
114
+ try {
115
+ await apiRequest(config, 'POST', '/api/shutdown');
116
+ }
117
+ catch {
118
+ // Server will shut down, so connection may be lost
119
+ }
120
+ }
121
+ function sleep(ms) {
122
+ return new Promise((resolve) => setTimeout(resolve, ms));
123
+ }
124
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export interface AttachOptions {
2
+ config?: string;
3
+ }
4
+ export declare function attachCommand(name: string | undefined, options: AttachOptions): Promise<void>;
5
+ //# sourceMappingURL=attach.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.d.ts","sourceRoot":"","sources":["../../src/commands/attach.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CASf"}