ttyd-mux 0.3.1 → 0.4.1
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 +114 -64
- package/dist/caddy/client.d.ts +3 -78
- package/dist/caddy/client.d.ts.map +1 -1
- package/dist/caddy/client.js +0 -170
- package/dist/caddy/client.js.map +1 -1
- package/dist/caddy/route-builder.d.ts +49 -0
- package/dist/caddy/route-builder.d.ts.map +1 -0
- package/dist/caddy/route-builder.js +175 -0
- package/dist/caddy/route-builder.js.map +1 -0
- package/dist/caddy/types.d.ts +27 -0
- package/dist/caddy/types.d.ts.map +1 -0
- package/dist/caddy/types.js +3 -0
- package/dist/caddy/types.js.map +1 -0
- package/dist/client/api-client.d.ts +33 -0
- package/dist/client/api-client.d.ts.map +1 -0
- package/dist/client/api-client.js +63 -0
- package/dist/client/api-client.js.map +1 -0
- package/dist/client/daemon-client.d.ts +58 -0
- package/dist/client/daemon-client.d.ts.map +1 -0
- package/dist/client/daemon-client.js +241 -0
- package/dist/client/daemon-client.js.map +1 -0
- package/dist/client/index.d.ts +2 -10
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +4 -149
- package/dist/client/index.js.map +1 -1
- package/dist/commands/attach.js +3 -4
- package/dist/commands/attach.js.map +1 -1
- package/dist/commands/caddy.d.ts.map +1 -1
- package/dist/commands/caddy.js +74 -109
- package/dist/commands/caddy.js.map +1 -1
- package/dist/commands/daemon.d.ts +2 -0
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +72 -3
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +3 -8
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +180 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/down.d.ts +1 -0
- package/dist/commands/down.d.ts.map +1 -1
- package/dist/commands/down.js +24 -3
- package/dist/commands/down.js.map +1 -1
- package/dist/commands/list.d.ts +7 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +31 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/reload.d.ts +14 -0
- package/dist/commands/reload.d.ts.map +1 -0
- package/dist/commands/reload.js +50 -0
- package/dist/commands/reload.js.map +1 -0
- package/dist/commands/restart.d.ts +5 -0
- package/dist/commands/restart.d.ts.map +1 -0
- package/dist/commands/restart.js +19 -0
- package/dist/commands/restart.js.map +1 -0
- package/dist/commands/shutdown.d.ts +3 -1
- package/dist/commands/shutdown.d.ts.map +1 -1
- package/dist/commands/shutdown.js +14 -2
- package/dist/commands/shutdown.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +16 -3
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/stop.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +0 -4
- package/dist/commands/up.js.map +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +9 -2
- package/dist/config/config.js.map +1 -1
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +6 -3
- package/dist/config/index.js.map +1 -1
- package/dist/config/state-store.d.ts +27 -0
- package/dist/config/state-store.d.ts.map +1 -0
- package/dist/config/state-store.js +55 -0
- package/dist/config/state-store.js.map +1 -0
- package/dist/config/state.d.ts +6 -0
- package/dist/config/state.d.ts.map +1 -1
- package/dist/config/state.js +49 -14
- package/dist/config/state.js.map +1 -1
- package/dist/config/types.d.ts +29 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +20 -1
- package/dist/config/types.js.map +1 -1
- package/dist/daemon/api-handler.d.ts +5 -0
- package/dist/daemon/api-handler.d.ts.map +1 -0
- package/dist/daemon/api-handler.js +110 -0
- package/dist/daemon/api-handler.js.map +1 -0
- package/dist/daemon/config-manager.d.ts +43 -0
- package/dist/daemon/config-manager.d.ts.map +1 -0
- package/dist/daemon/config-manager.js +154 -0
- package/dist/daemon/config-manager.js.map +1 -0
- package/dist/daemon/http-proxy.d.ts +27 -0
- package/dist/daemon/http-proxy.d.ts.map +1 -0
- package/dist/daemon/http-proxy.js +110 -0
- package/dist/daemon/http-proxy.js.map +1 -0
- package/dist/daemon/ime-helper.d.ts +1 -1
- package/dist/daemon/ime-helper.d.ts.map +1 -1
- package/dist/daemon/ime-helper.js +24 -53
- package/dist/daemon/ime-helper.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +139 -30
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/portal-utils.d.ts +20 -0
- package/dist/daemon/portal-utils.d.ts.map +1 -0
- package/dist/daemon/portal-utils.js +109 -0
- package/dist/daemon/portal-utils.js.map +1 -0
- package/dist/daemon/portal.d.ts.map +1 -1
- package/dist/daemon/portal.js +20 -77
- package/dist/daemon/portal.js.map +1 -1
- package/dist/daemon/pwa.d.ts +52 -0
- package/dist/daemon/pwa.d.ts.map +1 -0
- package/dist/daemon/pwa.js +229 -0
- package/dist/daemon/pwa.js.map +1 -0
- package/dist/daemon/router.d.ts +15 -0
- package/dist/daemon/router.d.ts.map +1 -0
- package/dist/daemon/router.js +164 -0
- package/dist/daemon/router.js.map +1 -0
- package/dist/daemon/server.d.ts +15 -3
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +23 -271
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/session-manager.d.ts +50 -12
- package/dist/daemon/session-manager.d.ts.map +1 -1
- package/dist/daemon/session-manager.js +138 -53
- package/dist/daemon/session-manager.js.map +1 -1
- package/dist/daemon/session-resolver.d.ts +1 -1
- package/dist/daemon/session-resolver.d.ts.map +1 -1
- package/dist/daemon/session-resolver.js.map +1 -1
- package/dist/daemon/toolbar/config.d.ts +13 -0
- package/dist/daemon/toolbar/config.d.ts.map +1 -0
- package/dist/daemon/toolbar/config.js +13 -0
- package/dist/daemon/toolbar/config.js.map +1 -0
- package/dist/daemon/toolbar/index.d.ts +43 -0
- package/dist/daemon/toolbar/index.d.ts.map +1 -0
- package/dist/daemon/toolbar/index.js +835 -0
- package/dist/daemon/toolbar/index.js.map +1 -0
- package/dist/daemon/toolbar/styles.d.ts +5 -0
- package/dist/daemon/toolbar/styles.d.ts.map +1 -0
- package/dist/daemon/toolbar/styles.js +278 -0
- package/dist/daemon/toolbar/styles.js.map +1 -0
- package/dist/daemon/toolbar/template.d.ts +6 -0
- package/dist/daemon/toolbar/template.d.ts.map +1 -0
- package/dist/daemon/toolbar/template.js +45 -0
- package/dist/daemon/toolbar/template.js.map +1 -0
- package/dist/daemon/ws-proxy.d.ts +17 -0
- package/dist/daemon/ws-proxy.d.ts.map +1 -0
- package/dist/daemon/ws-proxy.js +95 -0
- package/dist/daemon/ws-proxy.js.map +1 -0
- package/dist/deploy/caddyfile.d.ts.map +1 -1
- package/dist/deploy/caddyfile.js.map +1 -1
- package/dist/deploy/deploy-script.d.ts.map +1 -1
- package/dist/deploy/static-portal.d.ts.map +1 -1
- package/dist/deploy/static-portal.js +6 -77
- package/dist/deploy/static-portal.js.map +1 -1
- package/dist/index.js +60 -31
- package/dist/index.js.map +1 -1
- package/dist/test-setup.d.ts +19 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +33 -0
- package/dist/test-setup.js.map +1 -0
- package/dist/tmux.d.ts +28 -1
- package/dist/tmux.d.ts.map +1 -1
- package/dist/tmux.js +37 -32
- package/dist/tmux.js.map +1 -1
- package/dist/ui.d.ts +2 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +16 -9
- package/dist/ui.js.map +1 -1
- package/dist/utils/errors.d.ts +4 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +9 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +53 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/process-runner.d.ts +50 -0
- package/dist/utils/process-runner.d.ts.map +1 -0
- package/dist/utils/process-runner.js +73 -0
- package/dist/utils/process-runner.js.map +1 -0
- package/dist/utils/socket-client.d.ts +24 -0
- package/dist/utils/socket-client.d.ts.map +1 -0
- package/dist/utils/socket-client.js +30 -0
- package/dist/utils/socket-client.js.map +1 -0
- package/dist/utils/tmux-client.d.ts +61 -0
- package/dist/utils/tmux-client.d.ts.map +1 -0
- package/dist/utils/tmux-client.js +127 -0
- package/dist/utils/tmux-client.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/package.json +7 -2
- package/dist/daemon/proxy.d.ts +0 -7
- package/dist/daemon/proxy.d.ts.map +0 -1
- package/dist/daemon/proxy.js +0 -17
- package/dist/daemon/proxy.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# ttyd-mux
|
|
2
2
|
|
|
3
|
+
[](https://github.com/cuzic/ttyd-mux/actions/workflows/ci.yml)
|
|
4
|
+

|
|
5
|
+
|
|
3
6
|
A CLI tool for managing multiple ttyd+tmux web terminal sessions.
|
|
4
7
|
|
|
5
8
|
複数の ttyd+tmux Web ターミナルセッションを管理する CLI ツール。
|
|
@@ -60,11 +63,20 @@ sudo apt install ttyd tmux
|
|
|
60
63
|
brew install ttyd tmux
|
|
61
64
|
```
|
|
62
65
|
|
|
63
|
-
##
|
|
66
|
+
## Usage Patterns / 使い方
|
|
67
|
+
|
|
68
|
+
ttyd-mux has two main usage patterns:
|
|
69
|
+
|
|
70
|
+
ttyd-mux には2つの利用パターンがあります:
|
|
71
|
+
|
|
72
|
+
### Dynamic Usage (Ad-hoc Sessions) / 動的利用
|
|
73
|
+
|
|
74
|
+
Start sessions on-demand in any directory. No configuration needed.
|
|
75
|
+
|
|
76
|
+
設定不要で、任意のディレクトリでその場でセッションを起動。
|
|
64
77
|
|
|
65
78
|
```bash
|
|
66
|
-
# Start in your project directory
|
|
67
|
-
# プロジェクトディレクトリで起動
|
|
79
|
+
# Start in your project directory / プロジェクトディレクトリで起動
|
|
68
80
|
cd ~/my-project
|
|
69
81
|
ttyd-mux up
|
|
70
82
|
|
|
@@ -78,38 +90,60 @@ ttyd-mux status
|
|
|
78
90
|
ttyd-mux down
|
|
79
91
|
```
|
|
80
92
|
|
|
81
|
-
|
|
93
|
+
### Static Usage (Predefined Sessions) / 静的利用
|
|
82
94
|
|
|
83
|
-
|
|
95
|
+
Define sessions in config.yaml and start them all at once. Ideal for servers.
|
|
96
|
+
|
|
97
|
+
config.yaml にセッションを定義し、一括起動。サーバー運用に最適。
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
# ~/.config/ttyd-mux/config.yaml
|
|
101
|
+
sessions:
|
|
102
|
+
- name: project-a
|
|
103
|
+
dir: /home/user/project-a
|
|
104
|
+
- name: project-b
|
|
105
|
+
dir: /home/user/project-b
|
|
106
|
+
```
|
|
84
107
|
|
|
85
108
|
```bash
|
|
86
|
-
|
|
87
|
-
ttyd-mux
|
|
88
|
-
|
|
109
|
+
# Start daemon + all predefined sessions / デーモンと全セッションを起動
|
|
110
|
+
ttyd-mux daemon start --sessions
|
|
111
|
+
|
|
112
|
+
# Or select sessions interactively / またはインタラクティブに選択
|
|
113
|
+
ttyd-mux daemon start -s
|
|
114
|
+
|
|
115
|
+
# Stop daemon + all sessions / デーモンと全セッションを停止
|
|
116
|
+
ttyd-mux daemon stop --stop-sessions
|
|
89
117
|
```
|
|
90
118
|
|
|
91
|
-
|
|
119
|
+
## Commands / コマンド
|
|
120
|
+
|
|
121
|
+
### Session Commands / セッションコマンド
|
|
92
122
|
|
|
93
123
|
```bash
|
|
94
|
-
ttyd-mux
|
|
95
|
-
ttyd-mux
|
|
96
|
-
ttyd-mux
|
|
97
|
-
ttyd-mux
|
|
98
|
-
ttyd-mux status # Show status / 状態表示
|
|
124
|
+
ttyd-mux up # Start session for current directory
|
|
125
|
+
ttyd-mux down # Stop session for current directory
|
|
126
|
+
ttyd-mux status # Show status
|
|
127
|
+
ttyd-mux attach [name] # Attach to tmux session directly
|
|
99
128
|
```
|
|
100
129
|
|
|
101
|
-
###
|
|
130
|
+
### Daemon Control / デーモン制御
|
|
102
131
|
|
|
103
132
|
```bash
|
|
104
|
-
ttyd-mux
|
|
133
|
+
ttyd-mux daemon start # Start daemon only
|
|
134
|
+
ttyd-mux daemon start --sessions # Start daemon + all predefined sessions
|
|
135
|
+
ttyd-mux daemon start -s # Start daemon + select sessions interactively
|
|
136
|
+
ttyd-mux daemon start -f # Start in foreground (debug)
|
|
137
|
+
ttyd-mux daemon stop # Stop daemon
|
|
138
|
+
ttyd-mux daemon stop --stop-sessions # Stop all sessions + daemon
|
|
139
|
+
ttyd-mux daemon reload # Reload config (hot-reload)
|
|
140
|
+
ttyd-mux daemon restart # Restart daemon (apply code updates)
|
|
105
141
|
```
|
|
106
142
|
|
|
107
|
-
###
|
|
143
|
+
### Diagnostics / 診断
|
|
108
144
|
|
|
109
145
|
```bash
|
|
110
|
-
ttyd-mux
|
|
111
|
-
ttyd-mux daemon -f # Start in foreground (debug) / フォアグラウンドで起動(デバッグ用)
|
|
112
|
-
ttyd-mux shutdown # Stop daemon / デーモン終了
|
|
146
|
+
ttyd-mux doctor # Check dependencies and configuration
|
|
113
147
|
```
|
|
114
148
|
|
|
115
149
|
## Configuration / 設定
|
|
@@ -137,40 +171,24 @@ base_port: 7600
|
|
|
137
171
|
daemon_port: 7680
|
|
138
172
|
|
|
139
173
|
# Listen addresses (default: IPv4 + IPv6 localhost)
|
|
140
|
-
# リッスンアドレス(デフォルト: IPv4 + IPv6 localhost)
|
|
141
174
|
listen_addresses:
|
|
142
175
|
- "127.0.0.1"
|
|
143
176
|
- "::1"
|
|
144
|
-
# - "0.0.0.0" # Allow external access / 外部からのアクセスを許可する場合
|
|
145
|
-
|
|
146
|
-
# Auto-attach to tmux on session start (default: true)
|
|
147
|
-
# セッション起動時に自動でtmuxにアタッチ(デフォルト: true)
|
|
148
|
-
auto_attach: true
|
|
149
177
|
|
|
150
178
|
# Proxy mode: "proxy" (default) or "static"
|
|
151
|
-
#
|
|
152
|
-
# -
|
|
153
|
-
# - static: Sessions are accessed directly via Caddy (lower latency)
|
|
179
|
+
# - proxy: All traffic goes through daemon (supports toolbar)
|
|
180
|
+
# - static: Sessions accessed directly via Caddy (lower latency)
|
|
154
181
|
proxy_mode: proxy
|
|
155
182
|
|
|
156
|
-
# Hostname for Caddy integration
|
|
157
|
-
# Caddy連携用のホスト名(caddy/deployコマンドで使用)
|
|
183
|
+
# Hostname for Caddy integration
|
|
158
184
|
hostname: example.com
|
|
159
185
|
|
|
160
|
-
#
|
|
161
|
-
caddy_admin_api: http://localhost:2019
|
|
162
|
-
|
|
163
|
-
# Predefined sessions (optional) / 事前定義セッション(オプション)
|
|
186
|
+
# Predefined sessions for static usage / 静的利用のためのセッション定義
|
|
164
187
|
sessions:
|
|
165
188
|
- name: project-a
|
|
166
189
|
dir: /home/user/project-a
|
|
167
|
-
path: /project-a
|
|
168
|
-
port_offset: 1
|
|
169
|
-
|
|
170
190
|
- name: project-b
|
|
171
191
|
dir: /home/user/project-b
|
|
172
|
-
path: /project-b
|
|
173
|
-
port_offset: 2
|
|
174
192
|
```
|
|
175
193
|
|
|
176
194
|
## Architecture / アーキテクチャ
|
|
@@ -210,7 +228,61 @@ sessions:
|
|
|
210
228
|
|
|
211
229
|
- Lower latency (no intermediate proxy) / 低レイテンシ(中間プロキシなし)
|
|
212
230
|
- Static portal (no daemon needed at runtime) / 静的ポータル(実行時デーモン不要)
|
|
213
|
-
- No
|
|
231
|
+
- No toolbar support / ツールバー非対応
|
|
232
|
+
|
|
233
|
+
### Session Lifecycle / セッションのライフサイクル
|
|
234
|
+
|
|
235
|
+
Each session consists of three independent processes:
|
|
236
|
+
|
|
237
|
+
各セッションは3つの独立したプロセスで構成されています:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
ttyd-mux daemon (manages sessions)
|
|
241
|
+
│
|
|
242
|
+
└── ttyd (web terminal server)
|
|
243
|
+
│
|
|
244
|
+
└── tmux session (terminal multiplexer)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**What happens when stopping:**
|
|
248
|
+
|
|
249
|
+
**停止時の挙動:**
|
|
250
|
+
|
|
251
|
+
| Command | daemon | ttyd | tmux |
|
|
252
|
+
|---------|--------|------|------|
|
|
253
|
+
| `daemon stop` | Stops | Keeps running | Keeps running |
|
|
254
|
+
| `daemon stop -s` | Stops | Stops | **Keeps running** |
|
|
255
|
+
| `daemon stop -s --kill-tmux` | Stops | Stops | Stops |
|
|
256
|
+
| `down` | - | Stops | **Keeps running** |
|
|
257
|
+
| `down --kill-tmux` | - | Stops | Stops |
|
|
258
|
+
| `exit` in terminal | - | Stops | Stops |
|
|
259
|
+
|
|
260
|
+
- By default, tmux sessions persist even when ttyd or daemon is stopped
|
|
261
|
+
- Restarting with `ttyd-mux up` reconnects to existing tmux session
|
|
262
|
+
- Use `--kill-tmux` flag to fully terminate tmux sessions
|
|
263
|
+
|
|
264
|
+
- デフォルトでは tmux セッションは ttyd やデーモンを停止しても残ります
|
|
265
|
+
- `ttyd-mux up` で再起動すると既存の tmux セッションに再接続します
|
|
266
|
+
- `--kill-tmux` フラグで tmux セッションも完全に終了できます
|
|
267
|
+
|
|
268
|
+
## Toolbar Features / ツールバー機能
|
|
269
|
+
|
|
270
|
+
In proxy mode, ttyd-mux injects a toolbar for improved input experience:
|
|
271
|
+
|
|
272
|
+
プロキシモードでは、入力体験向上のためツールバーが注入されます:
|
|
273
|
+
|
|
274
|
+
### Mobile Support / モバイル対応
|
|
275
|
+
|
|
276
|
+
- **IME Input**: Virtual keyboard with Japanese IME support / 日本語 IME 対応
|
|
277
|
+
- **Touch Pinch Zoom**: Two-finger pinch to resize font / 2本指ピンチでフォントサイズ変更
|
|
278
|
+
- **Double-tap Enter**: Double-tap to send Enter key / ダブルタップで Enter 送信
|
|
279
|
+
- **Scroll Buttons**: PgUp/PgDn for scrolling / スクロール用ボタン
|
|
280
|
+
|
|
281
|
+
### PC Browser Support / PC ブラウザ対応
|
|
282
|
+
|
|
283
|
+
- **Ctrl+Scroll Zoom**: Mouse wheel with Ctrl key / Ctrl+マウスホイールでサイズ変更
|
|
284
|
+
- **Trackpad Pinch Zoom** (Mac): Two-finger pinch gesture / トラックパッドピンチ
|
|
285
|
+
- **Ctrl+J Toggle**: Show/hide toolbar / ツールバー表示切替
|
|
214
286
|
|
|
215
287
|
## Caddy Integration / Caddy との連携
|
|
216
288
|
|
|
@@ -240,29 +312,7 @@ handle /ttyd-mux/* {
|
|
|
240
312
|
}
|
|
241
313
|
```
|
|
242
314
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
For lower latency, use static mode where Caddy routes directly to ttyd:
|
|
246
|
-
|
|
247
|
-
低レイテンシのために、Caddy から ttyd に直接ルーティングするスタティックモード:
|
|
248
|
-
|
|
249
|
-
```yaml
|
|
250
|
-
# config.yaml
|
|
251
|
-
proxy_mode: static
|
|
252
|
-
hostname: example.com
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
# Generate static portal and Caddyfile snippet
|
|
257
|
-
# 静的ポータルと Caddyfile スニペットを生成
|
|
258
|
-
ttyd-mux deploy
|
|
259
|
-
|
|
260
|
-
# Sync routes after starting/stopping sessions
|
|
261
|
-
# セッション開始/停止後にルートを同期
|
|
262
|
-
ttyd-mux caddy sync
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
See [docs/caddy-setup.md](docs/caddy-setup.md) for details.
|
|
315
|
+
See [docs/caddy-setup.md](docs/caddy-setup.md) for details, including authentication setup.
|
|
266
316
|
|
|
267
317
|
## File Structure / ファイル構成
|
|
268
318
|
|
package/dist/caddy/client.d.ts
CHANGED
|
@@ -1,35 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
}
|
|
1
|
+
import type { CaddyConfig, CaddyRoute, CaddyServer } from './types.js';
|
|
2
|
+
export type { CaddyConfig, CaddyRoute, CaddyServer } from './types.js';
|
|
27
3
|
export declare const DEFAULT_ADMIN_API = "http://localhost:2019";
|
|
28
4
|
/**
|
|
29
5
|
* Client for Caddy Admin API
|
|
30
6
|
*/
|
|
31
7
|
export declare class CaddyClient {
|
|
32
|
-
private adminApi;
|
|
8
|
+
private readonly adminApi;
|
|
33
9
|
constructor(adminApi?: string);
|
|
34
10
|
/**
|
|
35
11
|
* Get current Caddy configuration
|
|
@@ -47,57 +23,6 @@ export declare class CaddyClient {
|
|
|
47
23
|
* Create a new server
|
|
48
24
|
*/
|
|
49
25
|
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
|
-
* Create a route for a specific session (static mode)
|
|
67
|
-
*/
|
|
68
|
-
createSessionRoute(hostname: string, sessionPath: string, port: number): CaddyRoute;
|
|
69
|
-
/**
|
|
70
|
-
* Create portal route (exact match for base path without trailing content)
|
|
71
|
-
*/
|
|
72
|
-
createPortalRoute(hostname: string, basePath: string, daemonPort: number): CaddyRoute;
|
|
73
|
-
/**
|
|
74
|
-
* Check if a session route exists
|
|
75
|
-
*/
|
|
76
|
-
sessionRouteExists(server: CaddyServer, hostname: string, sessionPath: string): boolean;
|
|
77
|
-
/**
|
|
78
|
-
* Get all ttyd-mux session routes from a server
|
|
79
|
-
*/
|
|
80
|
-
getSessionRoutes(server: CaddyServer, hostname: string, basePath: string): Array<{
|
|
81
|
-
path: string;
|
|
82
|
-
port: number;
|
|
83
|
-
}>;
|
|
84
|
-
/**
|
|
85
|
-
* Remove session routes that are no longer active
|
|
86
|
-
*/
|
|
87
|
-
filterOutSessionRoutes(routes: CaddyRoute[], hostname: string, basePath: string, keepPaths: Set<string>): CaddyRoute[];
|
|
88
|
-
/**
|
|
89
|
-
* Extract upstream from route handlers
|
|
90
|
-
*/
|
|
91
|
-
private extractUpstream;
|
|
92
|
-
/**
|
|
93
|
-
* Find ttyd-mux routes in all servers
|
|
94
|
-
*/
|
|
95
|
-
findTtydMuxRoutes(servers: Record<string, CaddyServer>, basePath: string): Array<{
|
|
96
|
-
serverName: string;
|
|
97
|
-
hosts: string[];
|
|
98
|
-
paths: string[];
|
|
99
|
-
upstream: string;
|
|
100
|
-
}>;
|
|
101
26
|
}
|
|
102
27
|
/**
|
|
103
28
|
* Connect to Caddy Admin API and return client
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/caddy/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/caddy/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGvE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvE,eAAO,MAAM,iBAAiB,0BAA0B,CAAC;AAEzD;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,GAAE,MAA0B;IAIhD;;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;CAY3E;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,QAAQ,GAAE,MAA0B,GAAG,OAAO,CAAC,WAAW,CAAC,CAS/F"}
|
package/dist/caddy/client.js
CHANGED
|
@@ -52,176 +52,6 @@ export class CaddyClient {
|
|
|
52
52
|
throw new Error(`Failed to create server: ${response.status} ${text}`);
|
|
53
53
|
}
|
|
54
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
|
-
* Create a route for a specific session (static mode)
|
|
103
|
-
*/
|
|
104
|
-
createSessionRoute(hostname, sessionPath, port) {
|
|
105
|
-
return {
|
|
106
|
-
match: [
|
|
107
|
-
{
|
|
108
|
-
host: [hostname],
|
|
109
|
-
path: [`${sessionPath}/*`]
|
|
110
|
-
}
|
|
111
|
-
],
|
|
112
|
-
handle: [
|
|
113
|
-
{
|
|
114
|
-
handler: 'reverse_proxy',
|
|
115
|
-
upstreams: [{ dial: `localhost:${port}` }]
|
|
116
|
-
}
|
|
117
|
-
]
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Create portal route (exact match for base path without trailing content)
|
|
122
|
-
*/
|
|
123
|
-
createPortalRoute(hostname, basePath, daemonPort) {
|
|
124
|
-
return {
|
|
125
|
-
match: [
|
|
126
|
-
{
|
|
127
|
-
host: [hostname],
|
|
128
|
-
path: [`${basePath}`, `${basePath}/`, `${basePath}/api/*`]
|
|
129
|
-
}
|
|
130
|
-
],
|
|
131
|
-
handle: [
|
|
132
|
-
{
|
|
133
|
-
handler: 'reverse_proxy',
|
|
134
|
-
upstreams: [{ dial: `localhost:${daemonPort}` }]
|
|
135
|
-
}
|
|
136
|
-
]
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Check if a session route exists
|
|
141
|
-
*/
|
|
142
|
-
sessionRouteExists(server, hostname, sessionPath) {
|
|
143
|
-
const routes = server.routes ?? [];
|
|
144
|
-
return routes.some((route) => {
|
|
145
|
-
const matches = route.match ?? [];
|
|
146
|
-
return matches.some((m) => m.host?.includes(hostname) && m.path?.some((p) => p === `${sessionPath}/*`));
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Get all ttyd-mux session routes from a server
|
|
151
|
-
*/
|
|
152
|
-
getSessionRoutes(server, hostname, basePath) {
|
|
153
|
-
const results = [];
|
|
154
|
-
const routes = server.routes ?? [];
|
|
155
|
-
for (const route of routes) {
|
|
156
|
-
const matches = route.match ?? [];
|
|
157
|
-
for (const match of matches) {
|
|
158
|
-
if (!match.host?.includes(hostname))
|
|
159
|
-
continue;
|
|
160
|
-
for (const path of match.path ?? []) {
|
|
161
|
-
// Match session paths like /ttyd-mux/session-name/*
|
|
162
|
-
if (path.startsWith(`${basePath}/`) && path.endsWith('/*')) {
|
|
163
|
-
const sessionPath = path.slice(0, -2); // Remove /*
|
|
164
|
-
const upstream = this.extractUpstream(route);
|
|
165
|
-
const portMatch = upstream.match(/:(\d+)$/);
|
|
166
|
-
if (portMatch?.[1]) {
|
|
167
|
-
results.push({ path: sessionPath, port: Number.parseInt(portMatch[1], 10) });
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return results;
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Remove session routes that are no longer active
|
|
177
|
-
*/
|
|
178
|
-
filterOutSessionRoutes(routes, hostname, basePath, keepPaths) {
|
|
179
|
-
return routes.filter((route) => {
|
|
180
|
-
const matches = route.match ?? [];
|
|
181
|
-
for (const match of matches) {
|
|
182
|
-
if (!match.host?.includes(hostname))
|
|
183
|
-
continue;
|
|
184
|
-
for (const path of match.path ?? []) {
|
|
185
|
-
// Check if this is a session route
|
|
186
|
-
if (path.startsWith(`${basePath}/`) && path.endsWith('/*')) {
|
|
187
|
-
const sessionPath = path.slice(0, -2);
|
|
188
|
-
// Keep only if in keepPaths
|
|
189
|
-
if (!keepPaths.has(sessionPath)) {
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
return true;
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Extract upstream from route handlers
|
|
200
|
-
*/
|
|
201
|
-
extractUpstream(route) {
|
|
202
|
-
const handlers = route.handle ?? [];
|
|
203
|
-
const proxyHandler = handlers.find((h) => h.handler === 'reverse_proxy');
|
|
204
|
-
return proxyHandler?.upstreams?.[0]?.dial ?? 'unknown';
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Find ttyd-mux routes in all servers
|
|
208
|
-
*/
|
|
209
|
-
findTtydMuxRoutes(servers, basePath) {
|
|
210
|
-
const results = [];
|
|
211
|
-
for (const [serverName, server] of Object.entries(servers)) {
|
|
212
|
-
for (const route of server.routes ?? []) {
|
|
213
|
-
for (const match of route.match ?? []) {
|
|
214
|
-
const paths = match.path ?? [];
|
|
215
|
-
if (paths.some((p) => p.startsWith(basePath))) {
|
|
216
|
-
const hosts = match.host ?? ['*'];
|
|
217
|
-
const upstream = this.extractUpstream(route);
|
|
218
|
-
results.push({ serverName, hosts, paths, upstream });
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return results;
|
|
224
|
-
}
|
|
225
55
|
}
|
|
226
56
|
/**
|
|
227
57
|
* Connect to Caddy Admin API and return client
|
package/dist/caddy/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/caddy/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/caddy/client.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,CAAC;AAEzD;;GAEG;AACH,MAAM,OAAO,WAAW;IACL,QAAQ,CAAS;IAElC,YAAY,WAAmB,iBAAiB;QAC9C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAgB,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,UAAkB,EAAE,MAAoB;QAC/D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,6BAA6B,UAAU,SAAS,EAAE;YAC7F,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,UAAkB,EAAE,MAAmB;QACxD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,6BAA6B,UAAU,EAAE,EAAE;YACtF,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB,iBAAiB;IACvE,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;IACzC,oCAAoC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,wCAAwC,QAAQ,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { CaddyRoute, CaddyServer } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a reverse proxy route
|
|
4
|
+
*/
|
|
5
|
+
export declare function createProxyRoute(hostname: string, basePath: string, upstream: string): CaddyRoute;
|
|
6
|
+
/**
|
|
7
|
+
* Create a route for a specific session (static mode)
|
|
8
|
+
*/
|
|
9
|
+
export declare function createSessionRoute(hostname: string, sessionPath: string, port: number): CaddyRoute;
|
|
10
|
+
/**
|
|
11
|
+
* Create portal route (exact match for base path without trailing content)
|
|
12
|
+
*/
|
|
13
|
+
export declare function createPortalRoute(hostname: string, basePath: string, daemonPort: number): CaddyRoute;
|
|
14
|
+
/**
|
|
15
|
+
* Find server that handles a specific hostname
|
|
16
|
+
*/
|
|
17
|
+
export declare function findServerForHost(servers: Record<string, CaddyServer>, hostname: string): {
|
|
18
|
+
name: string;
|
|
19
|
+
server: CaddyServer;
|
|
20
|
+
} | null;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a route exists for hostname and path
|
|
23
|
+
*/
|
|
24
|
+
export declare function routeExists(server: CaddyServer, hostname: string, basePath: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if a session route exists
|
|
27
|
+
*/
|
|
28
|
+
export declare function sessionRouteExists(server: CaddyServer, hostname: string, sessionPath: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Get all ttyd-mux session routes from a server
|
|
31
|
+
*/
|
|
32
|
+
export declare function getSessionRoutes(server: CaddyServer, hostname: string, basePath: string): Array<{
|
|
33
|
+
path: string;
|
|
34
|
+
port: number;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Remove session routes that are no longer active
|
|
38
|
+
*/
|
|
39
|
+
export declare function filterOutSessionRoutes(routes: CaddyRoute[], hostname: string, basePath: string, keepPaths: Set<string>): CaddyRoute[];
|
|
40
|
+
/**
|
|
41
|
+
* Find ttyd-mux routes in all servers
|
|
42
|
+
*/
|
|
43
|
+
export declare function findTtydMuxRoutes(servers: Record<string, CaddyServer>, basePath: string): Array<{
|
|
44
|
+
serverName: string;
|
|
45
|
+
hosts: string[];
|
|
46
|
+
paths: string[];
|
|
47
|
+
upstream: string;
|
|
48
|
+
}>;
|
|
49
|
+
//# sourceMappingURL=route-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-builder.d.ts","sourceRoot":"","sources":["../../src/caddy/route-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAKtE;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAejG;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,UAAU,CAeZ;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,UAAU,CAeZ;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACpC,QAAQ,EAAE,MAAM,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAAG,IAAI,CAW9C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAM5F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAMT;AAoDD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAMvC;AA6BD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,UAAU,EAAE,EACpB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GACrB,UAAU,EAAE,CAEd;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACpC,QAAQ,EAAE,MAAM,GACf,KAAK,CAAC;IACP,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAsBD"}
|