ttyd-mux 0.3.1 → 0.4.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 +52 -1
- 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 +26 -0
- package/dist/client/api-client.d.ts.map +1 -0
- package/dist/client/api-client.js +62 -0
- package/dist/client/api-client.js.map +1 -0
- package/dist/client/daemon-client.d.ts +48 -0
- package/dist/client/daemon-client.d.ts.map +1 -0
- package/dist/client/daemon-client.js +205 -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 +73 -108
- package/dist/commands/caddy.js.map +1 -1
- 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.map +1 -1
- package/dist/commands/down.js +11 -0
- package/dist/commands/down.js.map +1 -1
- 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/shutdown.d.ts +2 -1
- package/dist/commands/shutdown.d.ts.map +1 -1
- package/dist/commands/shutdown.js +8 -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.map +1 -1
- package/dist/commands/stop.js.map +1 -1
- 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 +97 -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 +134 -29
- 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 +44 -10
- package/dist/daemon/session-manager.d.ts.map +1 -1
- package/dist/daemon/session-manager.js +125 -49
- 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 +16 -3
- 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 +57 -0
- package/dist/utils/tmux-client.d.ts.map +1 -0
- package/dist/utils/tmux-client.js +117 -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 +6 -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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/daemon/toolbar/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,sBAAsB,EAAsB,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5D,sDAAsD;AACtD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;AAE3D,8BAA8B;AAC9B,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;AAEtD,oCAAoC;AACpC,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAGlC;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAwB,sBAAsB;IAC7E,MAAM,EACJ,aAAa,EACb,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EACpB,gBAAgB,EACjB,GAAG,MAAM,CAAC;IAEX,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAmCiB,aAAa;0BACb,aAAa;yCACE,wBAAwB,MAAM,oBAAoB;mCACxD,WAAW;4BAClB,oBAAoB;kCACd,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAknBjB,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA+GvC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,SAAwB,sBAAsB;IACzE,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,QAAgB;IAC1D,MAAM,SAAS,GAAG;SACX,aAAa;EACpB,WAAW;EACX,cAAc,CAAC,OAAO,CAAC,8BAA8B,EAAE,mDAAmD,CAAC;eAC9F,QAAQ;CACtB,CAAC;IACA,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,SAAS,SAAS,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Toolbar CSS Styles
|
|
3
|
+
*/
|
|
4
|
+
export declare const toolbarStyles = "\n#ttyd-toolbar {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n background: #1e1e1e;\n border-top: 2px solid #007acc;\n padding: 8px;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n box-shadow: 0 -2px 10px rgba(0,0,0,0.3);\n}\n\n#ttyd-toolbar.hidden {\n display: none;\n}\n\n#ttyd-toolbar-buttons {\n display: flex;\n gap: 6px;\n margin-bottom: 8px;\n flex-wrap: wrap;\n}\n\n#ttyd-toolbar-buttons button {\n background: #3a3a3a;\n border: 1px solid #555;\n border-radius: 6px;\n color: #fff;\n cursor: pointer;\n font-size: 13px;\n padding: 8px 12px;\n min-height: 40px;\n min-width: 44px;\n touch-action: manipulation;\n flex-shrink: 0;\n}\n\n#ttyd-toolbar-buttons button:hover, #ttyd-toolbar-buttons button:active {\n background: #4a4a4a;\n}\n\n#ttyd-toolbar-buttons button.active {\n background: #007acc;\n border-color: #005a9e;\n}\n\n#ttyd-toolbar-buttons button.modifier {\n background: #2d2d2d;\n font-weight: bold;\n}\n\n#ttyd-toolbar-buttons button.modifier.active {\n background: #d9534f;\n border-color: #c9302c;\n}\n\n#ttyd-toolbar-send {\n background: #007acc !important;\n border-color: #005a9e !important;\n font-weight: bold;\n}\n\n#ttyd-toolbar-send:hover, #ttyd-toolbar-send:active {\n background: #005a9e !important;\n}\n\n#ttyd-toolbar-run {\n background: #28a745 !important;\n border-color: #1e7e34 !important;\n font-weight: bold;\n}\n\n#ttyd-toolbar-run:hover, #ttyd-toolbar-run:active {\n background: #1e7e34 !important;\n}\n\n#ttyd-toolbar-auto.active {\n background: #f0ad4e !important;\n border-color: #eea236 !important;\n color: #000;\n}\n\n#ttyd-toolbar-scroll.active {\n background: #17a2b8 !important;\n border-color: #138496 !important;\n}\n\n#ttyd-toolbar-input-row {\n display: flex;\n gap: 8px;\n align-items: flex-end;\n}\n\n#ttyd-toolbar-input {\n flex: 1;\n background: #2d2d2d;\n border: 1px solid #555;\n border-radius: 8px;\n color: #fff;\n font-family: monospace;\n font-size: 16px;\n padding: 12px;\n outline: none;\n resize: none;\n min-height: 44px;\n max-height: 120px;\n line-height: 1.4;\n}\n\n#ttyd-toolbar-input:focus {\n border-color: #007acc;\n}\n\n#ttyd-toolbar-input::placeholder {\n color: #888;\n}\n\n#ttyd-toolbar-toggle {\n position: fixed;\n bottom: 16px;\n right: 16px;\n background: #007acc;\n border: 2px solid #005a9e;\n border-radius: 50%;\n color: #fff;\n cursor: pointer;\n font-size: 20px;\n width: 56px;\n height: 56px;\n z-index: 10001;\n touch-action: manipulation;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n#ttyd-toolbar-toggle:hover, #ttyd-toolbar-toggle:active {\n background: #005a9e;\n transform: scale(1.05);\n}\n\n#ttyd-toolbar.hidden ~ #ttyd-toolbar-toggle {\n bottom: 16px;\n}\n\n/* Adjust terminal height when toolbar is visible */\nbody:has(#ttyd-toolbar:not(.hidden)) .xterm {\n height: calc(100vh - 140px) !important;\n}\n\n/* Minimized mode - compact toolbar with input only */\n#ttyd-toolbar.minimized #ttyd-toolbar-buttons {\n display: none;\n}\n\n#ttyd-toolbar.minimized {\n padding: 4px 8px;\n}\n\n#ttyd-toolbar-minimize {\n background: #555 !important;\n border-color: #666 !important;\n font-size: 10px;\n padding: 4px 8px;\n min-width: 32px;\n min-height: 32px;\n}\n\n/* Onboarding tooltip */\n#ttyd-toolbar-onboarding {\n position: fixed;\n bottom: 90px;\n right: 16px;\n background: #333;\n border: 1px solid #007acc;\n border-radius: 8px;\n padding: 12px 16px;\n color: #fff;\n font-size: 13px;\n max-width: 280px;\n z-index: 10002;\n box-shadow: 0 4px 12px rgba(0,0,0,0.4);\n line-height: 1.5;\n}\n\n#ttyd-toolbar-onboarding::after {\n content: '';\n position: absolute;\n bottom: -8px;\n right: 24px;\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid #333;\n}\n\n#ttyd-toolbar-onboarding-close {\n position: absolute;\n top: 4px;\n right: 8px;\n background: none;\n border: none;\n color: #888;\n font-size: 16px;\n cursor: pointer;\n padding: 4px;\n}\n\n#ttyd-toolbar-onboarding-close:hover {\n color: #fff;\n}\n\n#ttyd-toolbar-onboarding ul {\n margin: 8px 0 0 0;\n padding-left: 20px;\n}\n\n#ttyd-toolbar-onboarding li {\n margin: 4px 0;\n}\n\n#ttyd-toolbar-onboarding code {\n background: #444;\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n}\n\n/* Mobile optimizations */\n@media (max-width: 768px) {\n #ttyd-toolbar {\n padding: 6px;\n }\n\n #ttyd-toolbar-buttons {\n gap: 4px;\n margin-bottom: 6px;\n }\n\n #ttyd-toolbar-buttons button {\n font-size: 12px;\n padding: 6px 10px;\n min-height: 36px;\n min-width: 40px;\n }\n\n #ttyd-toolbar-input {\n font-size: 16px;\n padding: 10px;\n }\n\n #ttyd-toolbar-toggle {\n width: 64px;\n height: 64px;\n font-size: 24px;\n }\n\n body:has(#ttyd-toolbar:not(.hidden)) .xterm {\n height: calc(100vh - 130px) !important;\n }\n\n body:has(#ttyd-toolbar.minimized:not(.hidden)) .xterm {\n height: calc(100vh - 60px) !important;\n }\n\n #ttyd-toolbar-onboarding {\n left: 16px;\n right: 16px;\n max-width: none;\n }\n}\n";
|
|
5
|
+
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/daemon/toolbar/styles.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,aAAa,2pKAiRzB,CAAC"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Toolbar CSS Styles
|
|
3
|
+
*/
|
|
4
|
+
export const toolbarStyles = `
|
|
5
|
+
#ttyd-toolbar {
|
|
6
|
+
position: fixed;
|
|
7
|
+
bottom: 0;
|
|
8
|
+
left: 0;
|
|
9
|
+
right: 0;
|
|
10
|
+
background: #1e1e1e;
|
|
11
|
+
border-top: 2px solid #007acc;
|
|
12
|
+
padding: 8px;
|
|
13
|
+
z-index: 10000;
|
|
14
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
15
|
+
box-shadow: 0 -2px 10px rgba(0,0,0,0.3);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#ttyd-toolbar.hidden {
|
|
19
|
+
display: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#ttyd-toolbar-buttons {
|
|
23
|
+
display: flex;
|
|
24
|
+
gap: 6px;
|
|
25
|
+
margin-bottom: 8px;
|
|
26
|
+
flex-wrap: wrap;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#ttyd-toolbar-buttons button {
|
|
30
|
+
background: #3a3a3a;
|
|
31
|
+
border: 1px solid #555;
|
|
32
|
+
border-radius: 6px;
|
|
33
|
+
color: #fff;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
font-size: 13px;
|
|
36
|
+
padding: 8px 12px;
|
|
37
|
+
min-height: 40px;
|
|
38
|
+
min-width: 44px;
|
|
39
|
+
touch-action: manipulation;
|
|
40
|
+
flex-shrink: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
#ttyd-toolbar-buttons button:hover, #ttyd-toolbar-buttons button:active {
|
|
44
|
+
background: #4a4a4a;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#ttyd-toolbar-buttons button.active {
|
|
48
|
+
background: #007acc;
|
|
49
|
+
border-color: #005a9e;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#ttyd-toolbar-buttons button.modifier {
|
|
53
|
+
background: #2d2d2d;
|
|
54
|
+
font-weight: bold;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#ttyd-toolbar-buttons button.modifier.active {
|
|
58
|
+
background: #d9534f;
|
|
59
|
+
border-color: #c9302c;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#ttyd-toolbar-send {
|
|
63
|
+
background: #007acc !important;
|
|
64
|
+
border-color: #005a9e !important;
|
|
65
|
+
font-weight: bold;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#ttyd-toolbar-send:hover, #ttyd-toolbar-send:active {
|
|
69
|
+
background: #005a9e !important;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#ttyd-toolbar-run {
|
|
73
|
+
background: #28a745 !important;
|
|
74
|
+
border-color: #1e7e34 !important;
|
|
75
|
+
font-weight: bold;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
#ttyd-toolbar-run:hover, #ttyd-toolbar-run:active {
|
|
79
|
+
background: #1e7e34 !important;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#ttyd-toolbar-auto.active {
|
|
83
|
+
background: #f0ad4e !important;
|
|
84
|
+
border-color: #eea236 !important;
|
|
85
|
+
color: #000;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#ttyd-toolbar-scroll.active {
|
|
89
|
+
background: #17a2b8 !important;
|
|
90
|
+
border-color: #138496 !important;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#ttyd-toolbar-input-row {
|
|
94
|
+
display: flex;
|
|
95
|
+
gap: 8px;
|
|
96
|
+
align-items: flex-end;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#ttyd-toolbar-input {
|
|
100
|
+
flex: 1;
|
|
101
|
+
background: #2d2d2d;
|
|
102
|
+
border: 1px solid #555;
|
|
103
|
+
border-radius: 8px;
|
|
104
|
+
color: #fff;
|
|
105
|
+
font-family: monospace;
|
|
106
|
+
font-size: 16px;
|
|
107
|
+
padding: 12px;
|
|
108
|
+
outline: none;
|
|
109
|
+
resize: none;
|
|
110
|
+
min-height: 44px;
|
|
111
|
+
max-height: 120px;
|
|
112
|
+
line-height: 1.4;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
#ttyd-toolbar-input:focus {
|
|
116
|
+
border-color: #007acc;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#ttyd-toolbar-input::placeholder {
|
|
120
|
+
color: #888;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
#ttyd-toolbar-toggle {
|
|
124
|
+
position: fixed;
|
|
125
|
+
bottom: 16px;
|
|
126
|
+
right: 16px;
|
|
127
|
+
background: #007acc;
|
|
128
|
+
border: 2px solid #005a9e;
|
|
129
|
+
border-radius: 50%;
|
|
130
|
+
color: #fff;
|
|
131
|
+
cursor: pointer;
|
|
132
|
+
font-size: 20px;
|
|
133
|
+
width: 56px;
|
|
134
|
+
height: 56px;
|
|
135
|
+
z-index: 10001;
|
|
136
|
+
touch-action: manipulation;
|
|
137
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#ttyd-toolbar-toggle:hover, #ttyd-toolbar-toggle:active {
|
|
144
|
+
background: #005a9e;
|
|
145
|
+
transform: scale(1.05);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
#ttyd-toolbar.hidden ~ #ttyd-toolbar-toggle {
|
|
149
|
+
bottom: 16px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Adjust terminal height when toolbar is visible */
|
|
153
|
+
body:has(#ttyd-toolbar:not(.hidden)) .xterm {
|
|
154
|
+
height: calc(100vh - 140px) !important;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* Minimized mode - compact toolbar with input only */
|
|
158
|
+
#ttyd-toolbar.minimized #ttyd-toolbar-buttons {
|
|
159
|
+
display: none;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
#ttyd-toolbar.minimized {
|
|
163
|
+
padding: 4px 8px;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
#ttyd-toolbar-minimize {
|
|
167
|
+
background: #555 !important;
|
|
168
|
+
border-color: #666 !important;
|
|
169
|
+
font-size: 10px;
|
|
170
|
+
padding: 4px 8px;
|
|
171
|
+
min-width: 32px;
|
|
172
|
+
min-height: 32px;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Onboarding tooltip */
|
|
176
|
+
#ttyd-toolbar-onboarding {
|
|
177
|
+
position: fixed;
|
|
178
|
+
bottom: 90px;
|
|
179
|
+
right: 16px;
|
|
180
|
+
background: #333;
|
|
181
|
+
border: 1px solid #007acc;
|
|
182
|
+
border-radius: 8px;
|
|
183
|
+
padding: 12px 16px;
|
|
184
|
+
color: #fff;
|
|
185
|
+
font-size: 13px;
|
|
186
|
+
max-width: 280px;
|
|
187
|
+
z-index: 10002;
|
|
188
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.4);
|
|
189
|
+
line-height: 1.5;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
#ttyd-toolbar-onboarding::after {
|
|
193
|
+
content: '';
|
|
194
|
+
position: absolute;
|
|
195
|
+
bottom: -8px;
|
|
196
|
+
right: 24px;
|
|
197
|
+
border-left: 8px solid transparent;
|
|
198
|
+
border-right: 8px solid transparent;
|
|
199
|
+
border-top: 8px solid #333;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
#ttyd-toolbar-onboarding-close {
|
|
203
|
+
position: absolute;
|
|
204
|
+
top: 4px;
|
|
205
|
+
right: 8px;
|
|
206
|
+
background: none;
|
|
207
|
+
border: none;
|
|
208
|
+
color: #888;
|
|
209
|
+
font-size: 16px;
|
|
210
|
+
cursor: pointer;
|
|
211
|
+
padding: 4px;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#ttyd-toolbar-onboarding-close:hover {
|
|
215
|
+
color: #fff;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#ttyd-toolbar-onboarding ul {
|
|
219
|
+
margin: 8px 0 0 0;
|
|
220
|
+
padding-left: 20px;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#ttyd-toolbar-onboarding li {
|
|
224
|
+
margin: 4px 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
#ttyd-toolbar-onboarding code {
|
|
228
|
+
background: #444;
|
|
229
|
+
padding: 2px 6px;
|
|
230
|
+
border-radius: 4px;
|
|
231
|
+
font-family: monospace;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* Mobile optimizations */
|
|
235
|
+
@media (max-width: 768px) {
|
|
236
|
+
#ttyd-toolbar {
|
|
237
|
+
padding: 6px;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
#ttyd-toolbar-buttons {
|
|
241
|
+
gap: 4px;
|
|
242
|
+
margin-bottom: 6px;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
#ttyd-toolbar-buttons button {
|
|
246
|
+
font-size: 12px;
|
|
247
|
+
padding: 6px 10px;
|
|
248
|
+
min-height: 36px;
|
|
249
|
+
min-width: 40px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
#ttyd-toolbar-input {
|
|
253
|
+
font-size: 16px;
|
|
254
|
+
padding: 10px;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
#ttyd-toolbar-toggle {
|
|
258
|
+
width: 64px;
|
|
259
|
+
height: 64px;
|
|
260
|
+
font-size: 24px;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
body:has(#ttyd-toolbar:not(.hidden)) .xterm {
|
|
264
|
+
height: calc(100vh - 130px) !important;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
body:has(#ttyd-toolbar.minimized:not(.hidden)) .xterm {
|
|
268
|
+
height: calc(100vh - 60px) !important;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
#ttyd-toolbar-onboarding {
|
|
272
|
+
left: 16px;
|
|
273
|
+
right: 16px;
|
|
274
|
+
max-width: none;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
`;
|
|
278
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/daemon/toolbar/styles.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiR5B,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Toolbar HTML Template
|
|
3
|
+
*/
|
|
4
|
+
export declare const toolbarHtml = "\n<div id=\"ttyd-toolbar\" class=\"hidden\">\n <div id=\"ttyd-toolbar-buttons\">\n <button id=\"ttyd-toolbar-ctrl\" class=\"modifier\">Ctrl</button>\n <button id=\"ttyd-toolbar-alt\" class=\"modifier\">Alt</button>\n <button id=\"ttyd-toolbar-shift\" class=\"modifier\">Shift</button>\n <button id=\"ttyd-toolbar-scroll\" class=\"modifier\">Scroll</button>\n <button id=\"ttyd-toolbar-esc\">Esc</button>\n <button id=\"ttyd-toolbar-tab\">Tab</button>\n <button id=\"ttyd-toolbar-up\">\u2191</button>\n <button id=\"ttyd-toolbar-down\">\u2193</button>\n <button id=\"ttyd-toolbar-pageup\">PgUp</button>\n <button id=\"ttyd-toolbar-pagedown\">PgDn</button>\n <button id=\"ttyd-toolbar-enter\">Enter</button>\n <button id=\"ttyd-toolbar-zoomout\">A-</button>\n <button id=\"ttyd-toolbar-zoomin\">A+</button>\n <button id=\"ttyd-toolbar-copy\">Copy</button>\n <button id=\"ttyd-toolbar-copyall\">All</button>\n <button id=\"ttyd-toolbar-send\">Send</button>\n <button id=\"ttyd-toolbar-run\">Run</button>\n <button id=\"ttyd-toolbar-auto\" class=\"modifier\">Auto</button>\n <button id=\"ttyd-toolbar-minimize\">\u25BC</button>\n </div>\n <div id=\"ttyd-toolbar-input-row\">\n <textarea id=\"ttyd-toolbar-input\" rows=\"1\" placeholder=\"\u65E5\u672C\u8A9E\u5165\u529B (Enter: \u9001\u4FE1)\"></textarea>\n </div>\n</div>\n<button id=\"ttyd-toolbar-toggle\">\u2328</button>\n";
|
|
5
|
+
export declare const onboardingHtml = "\n<div id=\"ttyd-toolbar-onboarding\">\n <button id=\"ttyd-toolbar-onboarding-close\">\u00D7</button>\n <strong>Toolbar Tips</strong>\n <ul>\n <li><code>Ctrl+J</code> \u3067\u30C4\u30FC\u30EB\u30D0\u30FC\u8868\u793A/\u975E\u8868\u793A</li>\n <li>\u30D4\u30F3\u30C1\u64CD\u4F5C\u3067\u30D5\u30A9\u30F3\u30C8\u30B5\u30A4\u30BA\u5909\u66F4</li>\n <li>\u30C0\u30D6\u30EB\u30BF\u30C3\u30D7\u3067 Enter \u9001\u4FE1</li>\n <li><code>\u25BC</code> \u3067\u30B3\u30F3\u30D1\u30AF\u30C8\u8868\u793A</li>\n </ul>\n</div>\n";
|
|
6
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/daemon/toolbar/template.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,WAAW,g6CA4BvB,CAAC;AAEF,eAAO,MAAM,cAAc,qhBAW1B,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Toolbar HTML Template
|
|
3
|
+
*/
|
|
4
|
+
export const toolbarHtml = `
|
|
5
|
+
<div id="ttyd-toolbar" class="hidden">
|
|
6
|
+
<div id="ttyd-toolbar-buttons">
|
|
7
|
+
<button id="ttyd-toolbar-ctrl" class="modifier">Ctrl</button>
|
|
8
|
+
<button id="ttyd-toolbar-alt" class="modifier">Alt</button>
|
|
9
|
+
<button id="ttyd-toolbar-shift" class="modifier">Shift</button>
|
|
10
|
+
<button id="ttyd-toolbar-scroll" class="modifier">Scroll</button>
|
|
11
|
+
<button id="ttyd-toolbar-esc">Esc</button>
|
|
12
|
+
<button id="ttyd-toolbar-tab">Tab</button>
|
|
13
|
+
<button id="ttyd-toolbar-up">↑</button>
|
|
14
|
+
<button id="ttyd-toolbar-down">↓</button>
|
|
15
|
+
<button id="ttyd-toolbar-pageup">PgUp</button>
|
|
16
|
+
<button id="ttyd-toolbar-pagedown">PgDn</button>
|
|
17
|
+
<button id="ttyd-toolbar-enter">Enter</button>
|
|
18
|
+
<button id="ttyd-toolbar-zoomout">A-</button>
|
|
19
|
+
<button id="ttyd-toolbar-zoomin">A+</button>
|
|
20
|
+
<button id="ttyd-toolbar-copy">Copy</button>
|
|
21
|
+
<button id="ttyd-toolbar-copyall">All</button>
|
|
22
|
+
<button id="ttyd-toolbar-send">Send</button>
|
|
23
|
+
<button id="ttyd-toolbar-run">Run</button>
|
|
24
|
+
<button id="ttyd-toolbar-auto" class="modifier">Auto</button>
|
|
25
|
+
<button id="ttyd-toolbar-minimize">▼</button>
|
|
26
|
+
</div>
|
|
27
|
+
<div id="ttyd-toolbar-input-row">
|
|
28
|
+
<textarea id="ttyd-toolbar-input" rows="1" placeholder="日本語入力 (Enter: 送信)"></textarea>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<button id="ttyd-toolbar-toggle">⌨</button>
|
|
32
|
+
`;
|
|
33
|
+
export const onboardingHtml = `
|
|
34
|
+
<div id="ttyd-toolbar-onboarding">
|
|
35
|
+
<button id="ttyd-toolbar-onboarding-close">×</button>
|
|
36
|
+
<strong>Toolbar Tips</strong>
|
|
37
|
+
<ul>
|
|
38
|
+
<li><code>Ctrl+J</code> でツールバー表示/非表示</li>
|
|
39
|
+
<li>ピンチ操作でフォントサイズ変更</li>
|
|
40
|
+
<li>ダブルタップで Enter 送信</li>
|
|
41
|
+
<li><code>▼</code> でコンパクト表示</li>
|
|
42
|
+
</ul>
|
|
43
|
+
</div>
|
|
44
|
+
`;
|
|
45
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/daemon/toolbar/template.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4B1B,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;CAW7B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
2
|
+
import type { Socket } from 'node:net';
|
|
3
|
+
import type { Config } from '../config/types.js';
|
|
4
|
+
import WebSocket from 'ws';
|
|
5
|
+
/**
|
|
6
|
+
* Gracefully close a WebSocket connection
|
|
7
|
+
*/
|
|
8
|
+
export declare function closeWebSocket(ws: WebSocket, code: number, reason: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Setup bidirectional WebSocket forwarding
|
|
11
|
+
*/
|
|
12
|
+
export declare function setupWebSocketForwarding(clientWs: WebSocket, backendWs: WebSocket): void;
|
|
13
|
+
/**
|
|
14
|
+
* Handle WebSocket upgrade request
|
|
15
|
+
*/
|
|
16
|
+
export declare function handleUpgrade(config: Config, req: IncomingMessage, socket: Socket, head: Buffer): void;
|
|
17
|
+
//# sourceMappingURL=ws-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-proxy.d.ts","sourceRoot":"","sources":["../../src/daemon/ws-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,mBAAmB,CAAC;AAE9D,OAAO,SAA8B,MAAM,IAAI,CAAC;AAQhD;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAMhF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,CA4CxF;AAoCD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,IAAI,CAaN"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { createLogger } from '../utils/logger.js';
|
|
2
|
+
import WebSocket, { WebSocketServer } from 'ws';
|
|
3
|
+
import { findSessionForPath } from './router.js';
|
|
4
|
+
const log = createLogger('websocket');
|
|
5
|
+
// Create WebSocket server (noServer mode for manual upgrade handling)
|
|
6
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
7
|
+
/**
|
|
8
|
+
* Gracefully close a WebSocket connection
|
|
9
|
+
*/
|
|
10
|
+
export function closeWebSocket(ws, code, reason) {
|
|
11
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
12
|
+
ws.close(code, reason);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
ws.terminate();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Setup bidirectional WebSocket forwarding
|
|
20
|
+
*/
|
|
21
|
+
export function setupWebSocketForwarding(clientWs, backendWs) {
|
|
22
|
+
let closed = false;
|
|
23
|
+
const cleanup = (initiator, code, reason) => {
|
|
24
|
+
if (closed) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
closed = true;
|
|
28
|
+
log.debug(`WebSocket cleanup initiated by ${initiator}, code=${code}`);
|
|
29
|
+
const closeCode = code ?? 1000;
|
|
30
|
+
const closeReason = reason?.toString() ?? '';
|
|
31
|
+
const wsToClose = initiator === 'client' ? backendWs : clientWs;
|
|
32
|
+
closeWebSocket(wsToClose, closeCode, closeReason);
|
|
33
|
+
};
|
|
34
|
+
// Forward messages bidirectionally
|
|
35
|
+
clientWs.on('message', (data, isBinary) => {
|
|
36
|
+
if (backendWs.readyState === WebSocket.OPEN) {
|
|
37
|
+
backendWs.send(data, { binary: isBinary });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
backendWs.on('message', (data, isBinary) => {
|
|
41
|
+
if (clientWs.readyState === WebSocket.OPEN) {
|
|
42
|
+
clientWs.send(data, { binary: isBinary });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
// Handle close events
|
|
46
|
+
clientWs.on('close', (code, reason) => cleanup('client', code, reason));
|
|
47
|
+
backendWs.on('close', (code, reason) => cleanup('backend', code, reason));
|
|
48
|
+
// Handle errors - terminate to ensure cleanup
|
|
49
|
+
clientWs.on('error', (err) => {
|
|
50
|
+
log.error(`Client WebSocket error: ${err.message}`);
|
|
51
|
+
clientWs.terminate();
|
|
52
|
+
cleanup('client', 1006);
|
|
53
|
+
});
|
|
54
|
+
backendWs.on('error', (err) => {
|
|
55
|
+
log.error(`Backend WebSocket error: ${err.message}`);
|
|
56
|
+
backendWs.terminate();
|
|
57
|
+
cleanup('backend', 1006);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Connect to backend WebSocket and setup forwarding
|
|
62
|
+
*/
|
|
63
|
+
function connectToBackend(session, url, protocol, req, socket, head) {
|
|
64
|
+
const backendUrl = `ws://127.0.0.1:${session.port}${url}`;
|
|
65
|
+
log.debug(`Connecting to backend WebSocket: ${backendUrl}`);
|
|
66
|
+
const backendWs = new WebSocket(backendUrl, protocol ? protocol.split(',').map((p) => p.trim()) : []);
|
|
67
|
+
backendWs.on('open', () => {
|
|
68
|
+
log.debug(`Backend WebSocket connected: ${backendUrl}`);
|
|
69
|
+
// Upgrade client connection once backend is ready
|
|
70
|
+
wss.handleUpgrade(req, socket, head, (clientWs) => {
|
|
71
|
+
setupWebSocketForwarding(clientWs, backendWs);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
backendWs.on('error', (err) => {
|
|
75
|
+
log.error(`Backend WebSocket connection failed: ${backendUrl} - ${err.message}`);
|
|
76
|
+
backendWs.terminate();
|
|
77
|
+
socket.destroy();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Handle WebSocket upgrade request
|
|
82
|
+
*/
|
|
83
|
+
export function handleUpgrade(config, req, socket, head) {
|
|
84
|
+
const url = req.url ?? '/';
|
|
85
|
+
log.debug(`WebSocket upgrade request: ${url}`);
|
|
86
|
+
const session = findSessionForPath(config, url);
|
|
87
|
+
if (!session) {
|
|
88
|
+
log.warn(`WebSocket upgrade rejected - no session for: ${url}`);
|
|
89
|
+
socket.destroy();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const protocol = req.headers['sec-websocket-protocol'];
|
|
93
|
+
connectToBackend(session, url, protocol, req, socket, head);
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=ws-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-proxy.js","sourceRoot":"","sources":["../../src/daemon/ws-proxy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,SAAS,EAAE,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;AAEtC,sEAAsE;AACtE,MAAM,GAAG,GAAG,IAAI,eAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAa,EAAE,IAAY,EAAE,MAAc;IACxE,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;QACrC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,SAAS,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAmB,EAAE,SAAoB;IAChF,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,OAAO,GAAG,CAAC,SAA+B,EAAE,IAAa,EAAE,MAAe,EAAE,EAAE;QAClF,IAAI,MAAM,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QACD,MAAM,GAAG,IAAI,CAAC;QAEd,GAAG,CAAC,KAAK,CAAC,kCAAkC,SAAS,UAAU,IAAI,EAAE,CAAC,CAAC;QACvE,MAAM,SAAS,GAAG,IAAI,IAAI,IAAI,CAAC;QAC/B,MAAM,WAAW,GAAG,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAG,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;QAChE,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACpD,CAAC,CAAC;IAEF,mCAAmC;IACnC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE;QACxC,IAAI,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAC5C,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE;QACzC,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,sBAAsB;IACtB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACxE,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAE1E,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QAC3B,GAAG,CAAC,KAAK,CAAC,2BAA2B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,QAAQ,CAAC,SAAS,EAAE,CAAC;QACrB,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,KAAK,CAAC,4BAA4B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACrD,SAAS,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CACvB,OAAqB,EACrB,GAAW,EACX,QAA4B,EAC5B,GAAoB,EACpB,MAAc,EACd,IAAY;IAEZ,MAAM,UAAU,GAAG,kBAAkB,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,CAAC;IAC1D,GAAG,CAAC,KAAK,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;IAE5D,MAAM,SAAS,GAAG,IAAI,SAAS,CAC7B,UAAU,EACV,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CACzD,CAAC;IAEF,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACxB,GAAG,CAAC,KAAK,CAAC,gCAAgC,UAAU,EAAE,CAAC,CAAC;QACxD,kDAAkD;QAClD,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;YAChD,wBAAwB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,KAAK,CAAC,wCAAwC,UAAU,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACjF,SAAS,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,GAAoB,EACpB,MAAc,EACd,IAAY;IAEZ,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;IAC3B,GAAG,CAAC,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,gDAAgD,GAAG,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACvD,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"caddyfile.d.ts","sourceRoot":"","sources":["../../src/deploy/caddyfile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"caddyfile.d.ts","sourceRoot":"","sources":["../../src/deploy/caddyfile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAoCR;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,gBAAgB,GACxB,MAAM,CA8BR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"caddyfile.js","sourceRoot":"","sources":["../../src/deploy/caddyfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"caddyfile.js","sourceRoot":"","sources":["../../src/deploy/caddyfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAQjD,MAAM,UAAU,wBAAwB,CACtC,MAAc,EACd,QAAwB,EACxB,OAAyB;IAEzB,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC;IAElC,MAAM,KAAK,GAAa;QACtB,4CAA4C,QAAQ,EAAE;QACtD,kBAAkB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE;QAC5C,gDAAgD;QAChD,EAAE;QACF,6BAA6B;QAC7B,UAAU,QAAQ,IAAI;QACtB,2BAA2B;QAC3B,cAAc,SAAS,EAAE;QACzB,iBAAiB;QACjB,GAAG;QACH,EAAE;QACF,UAAU,QAAQ,KAAK;QACvB,2BAA2B;QAC3B,cAAc,SAAS,EAAE;QACzB,iBAAiB;QACjB,GAAG;KACJ,CAAC;IAEF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,mCAAmC,CAAC,CAAC;QAEpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YACnD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7C,KAAK,CAAC,IAAI,CAAC,UAAU,QAAQ,MAAM,CAAC,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,+BAA+B,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,QAAwB,EACxB,OAAyB;IAEzB,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC;IAElC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,gBAAgB;IAChB,MAAM,CAAC,IAAI,CAAC;QACV,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC/D,MAAM,EAAE;YACN,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE;YAC1C,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;SAC5C;KACF,CAAC,CAAC;IAEH,iBAAiB;IACjB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC;YACV,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,QAAQ,IAAI,CAAC,EAAE,CAAC;YACtD,MAAM,EAAE;gBACN;oBACE,OAAO,EAAE,eAAe;oBACxB,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;iBACnD;aACF;SACF,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-script.d.ts","sourceRoot":"","sources":["../../src/deploy/deploy-script.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"deploy-script.d.ts","sourceRoot":"","sources":["../../src/deploy/deploy-script.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAuEzF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-portal.d.ts","sourceRoot":"","sources":["../../src/deploy/static-portal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"static-portal.d.ts","sourceRoot":"","sources":["../../src/deploy/static-portal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAQ9D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CA2DzF"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { getFullPath } from '../config/config.js';
|
|
1
|
+
import { getFullPath, normalizeBasePath } from '../config/config.js';
|
|
2
|
+
import { escapeHtml, generatePwaHead, generateSwRegistration, portalStyles } from '../daemon/portal-utils.js';
|
|
2
3
|
export function generateStaticPortalHtml(config, sessions) {
|
|
4
|
+
const basePath = normalizeBasePath(config.base_path);
|
|
3
5
|
const sessionItems = sessions
|
|
4
6
|
.map((session) => {
|
|
5
7
|
const fullPath = getFullPath(config, session.path);
|
|
@@ -20,73 +22,8 @@ export function generateStaticPortalHtml(config, sessions) {
|
|
|
20
22
|
<head>
|
|
21
23
|
<meta charset="UTF-8">
|
|
22
24
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
23
|
-
<title>ttyd-mux</title
|
|
24
|
-
<style
|
|
25
|
-
* {
|
|
26
|
-
box-sizing: border-box;
|
|
27
|
-
}
|
|
28
|
-
body {
|
|
29
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
30
|
-
max-width: 800px;
|
|
31
|
-
margin: 0 auto;
|
|
32
|
-
padding: 2rem;
|
|
33
|
-
background: #1a1a2e;
|
|
34
|
-
color: #eee;
|
|
35
|
-
min-height: 100vh;
|
|
36
|
-
}
|
|
37
|
-
h1 {
|
|
38
|
-
color: #00d9ff;
|
|
39
|
-
margin-bottom: 0.5rem;
|
|
40
|
-
}
|
|
41
|
-
.subtitle {
|
|
42
|
-
color: #888;
|
|
43
|
-
margin-bottom: 2rem;
|
|
44
|
-
}
|
|
45
|
-
ul {
|
|
46
|
-
list-style: none;
|
|
47
|
-
padding: 0;
|
|
48
|
-
margin: 0;
|
|
49
|
-
}
|
|
50
|
-
.session {
|
|
51
|
-
margin: 0.5rem 0;
|
|
52
|
-
}
|
|
53
|
-
.session a {
|
|
54
|
-
display: block;
|
|
55
|
-
padding: 1rem;
|
|
56
|
-
background: #16213e;
|
|
57
|
-
border-radius: 8px;
|
|
58
|
-
text-decoration: none;
|
|
59
|
-
color: #eee;
|
|
60
|
-
transition: background 0.2s, transform 0.1s;
|
|
61
|
-
}
|
|
62
|
-
.session a:hover {
|
|
63
|
-
background: #1f3460;
|
|
64
|
-
transform: translateX(4px);
|
|
65
|
-
}
|
|
66
|
-
.name {
|
|
67
|
-
font-weight: 600;
|
|
68
|
-
font-size: 1.1rem;
|
|
69
|
-
color: #00d9ff;
|
|
70
|
-
}
|
|
71
|
-
.info {
|
|
72
|
-
display: block;
|
|
73
|
-
font-size: 0.85rem;
|
|
74
|
-
color: #888;
|
|
75
|
-
margin-top: 0.25rem;
|
|
76
|
-
}
|
|
77
|
-
.no-sessions {
|
|
78
|
-
color: #888;
|
|
79
|
-
padding: 2rem;
|
|
80
|
-
text-align: center;
|
|
81
|
-
background: #16213e;
|
|
82
|
-
border-radius: 8px;
|
|
83
|
-
}
|
|
84
|
-
code {
|
|
85
|
-
background: #0f0f23;
|
|
86
|
-
padding: 0.2rem 0.4rem;
|
|
87
|
-
border-radius: 4px;
|
|
88
|
-
font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
|
|
89
|
-
}
|
|
25
|
+
<title>ttyd-mux</title>${generatePwaHead(basePath)}
|
|
26
|
+
<style>${portalStyles}
|
|
90
27
|
.footer {
|
|
91
28
|
margin-top: 2rem;
|
|
92
29
|
text-align: center;
|
|
@@ -114,17 +51,9 @@ ${sessionItems}
|
|
|
114
51
|
<div class="footer">
|
|
115
52
|
<p>Static portal generated at ${generatedAt}</p>
|
|
116
53
|
<p>Run <code>ttyd-mux deploy</code> to update after session changes</p>
|
|
117
|
-
</div
|
|
54
|
+
</div>${generateSwRegistration(basePath)}
|
|
118
55
|
</body>
|
|
119
56
|
</html>
|
|
120
57
|
`;
|
|
121
58
|
}
|
|
122
|
-
function escapeHtml(str) {
|
|
123
|
-
return str
|
|
124
|
-
.replace(/&/g, '&')
|
|
125
|
-
.replace(/</g, '<')
|
|
126
|
-
.replace(/>/g, '>')
|
|
127
|
-
.replace(/"/g, '"')
|
|
128
|
-
.replace(/'/g, ''');
|
|
129
|
-
}
|
|
130
59
|
//# sourceMappingURL=static-portal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-portal.js","sourceRoot":"","sources":["../../src/deploy/static-portal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"static-portal.js","sourceRoot":"","sources":["../../src/deploy/static-portal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEpE,OAAO,EACL,UAAU,EACV,eAAe,EACf,sBAAsB,EACtB,YAAY,EACb,MAAM,0BAA0B,CAAC;AAElC,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,QAAwB;IAC/E,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,QAAQ;SAC1B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QACf,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACnD,OAAO;mBACM,QAAQ;+BACI,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;gCACvB,OAAO,CAAC,IAAI,MAAM,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC;;YAE7D,CAAC;IACT,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,UAAU,GACd,QAAQ,CAAC,MAAM,KAAK,CAAC;QACnB,CAAC,CAAC,wIAAwI;QAC1I,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE7C,OAAO;;;;;2BAKkB,eAAe,CAAC,QAAQ,CAAC;WACzC,YAAY;;;;;;;;;;;;;;;;;;;;;;EAsBrB,YAAY;;IAEV,UAAU;;oCAEsB,WAAW;;UAErC,sBAAsB,CAAC,QAAQ,CAAC;;;CAGzC,CAAC;AACF,CAAC"}
|