yaport 0.1.0 → 0.1.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 +60 -6
- package/dist/client/assets/index-DQ_KWWqB.css +1 -0
- package/dist/client/assets/index-g0iLkETl.js +9 -0
- package/dist/client/index.html +2 -2
- package/dist/server/cli.js +482 -14
- package/package.json +1 -1
- package/dist/client/assets/index-Dss-tOs5.js +0 -9
- package/dist/client/assets/index-RIEF8eK4.css +0 -1
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ GUI 能添加机器,但大量机器用 CLI 更快。`add-machine` 是非交互
|
|
|
60
60
|
OpenSSH alias,等价于 `ssh erya`:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
yaport add-machine --
|
|
63
|
+
yaport add-machine --host erya --json
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
明确指定用户和端口:
|
|
@@ -114,9 +114,9 @@ yaport add-machine \
|
|
|
114
114
|
|
|
115
115
|
| 参数 | 说明 |
|
|
116
116
|
| --- | --- |
|
|
117
|
-
| `--name <name>` | UI
|
|
117
|
+
| `--name <name>` | UI 里展示的机器名称;留空时默认用 `user@host:port`。 |
|
|
118
118
|
| `--host <host>` | SSH host、IP 或 OpenSSH alias。 |
|
|
119
|
-
| `--user <user>` | SSH 用户。OpenSSH alias
|
|
119
|
+
| `--user <user>` | SSH 用户。OpenSSH alias 已配置时可以省略;`--host` 是 IP 地址时必须填写。 |
|
|
120
120
|
| `--port <port>` | SSH 端口。OpenSSH alias 已配置时可以省略。 |
|
|
121
121
|
| `--password-env <env>` | 从环境变量读取目标机器 SSH 密码。 |
|
|
122
122
|
| `--connect-timeout <seconds>` | SSH 连接超时。可选值:`8`、`15`、`30`、`60`。默认 `15`。 |
|
|
@@ -134,8 +134,31 @@ yaport add-machine \
|
|
|
134
134
|
- agent 和脚本优先使用 `--json`。
|
|
135
135
|
- 密码优先使用 `--password-env` 和 `--jumpN-password-env`,不要把密码直接放进命令参数。
|
|
136
136
|
- 使用 OpenSSH alias 时,`--user` 和 `--port` 可以留空。
|
|
137
|
+
- 使用 IP 地址连接目标机器或跳板机时,必须填写对应用户。
|
|
137
138
|
- 两层跳板或密码认证握手较慢时,建议使用 `--connect-timeout 30 --command-timeout 90`。
|
|
138
139
|
|
|
140
|
+
## 配置开机自启
|
|
141
|
+
|
|
142
|
+
丫口可以安装为当前用户的系统服务,不需要 sudo。macOS 使用 LaunchAgent,Linux 使用 systemd user service。服务启动时会带 `--no-open`,不会开机自动弹浏览器。
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
yaport service install --port 5173 --json
|
|
146
|
+
yaport service status
|
|
147
|
+
yaport service uninstall
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
常用参数:
|
|
151
|
+
|
|
152
|
+
| 参数 | 说明 |
|
|
153
|
+
| --- | --- |
|
|
154
|
+
| `install` | 写入并启动用户级服务。 |
|
|
155
|
+
| `uninstall` | 停止并移除用户级服务。 |
|
|
156
|
+
| `status` | 调用 `launchctl` 或 `systemctl --user` 查看状态。 |
|
|
157
|
+
| `--host <host>` | 服务监听地址,默认 `127.0.0.1`。 |
|
|
158
|
+
| `--port <port>` | 服务监听端口,默认 `5173`。 |
|
|
159
|
+
| `--data-file <path>` | 服务使用的机器配置文件;不传时仍按 `./.yaport`、`~/.yaport` 查找。 |
|
|
160
|
+
| `--json` | `install` / `uninstall` 输出稳定 JSON。 |
|
|
161
|
+
|
|
139
162
|
## 端口信息
|
|
140
163
|
|
|
141
164
|
丫口通过本机 OpenSSH 登录远程机器,并读取:
|
|
@@ -173,6 +196,10 @@ yaport add-machine \
|
|
|
173
196
|
|
|
174
197
|
- 添加机器表单默认折叠。
|
|
175
198
|
- 添加机器时可以选择“连接超时”和“命令超时”。
|
|
199
|
+
- 连接名称可选,留空时默认用主机信息;Host 是 IP 地址时用户必填,OpenSSH alias 可以留空。
|
|
200
|
+
- 机器卡片右侧可以打开本机 Terminal,并用该机器配置执行 `ssh`。已保存密码不会写入命令行。
|
|
201
|
+
- 左侧机器列表在页面滚动时固定在左侧,也可以折叠成窄栏。
|
|
202
|
+
- 右键机器卡片可以编辑或删除连接配置;编辑时密码框留空表示保留原密码。
|
|
176
203
|
- TCP / UDP 指标卡带开关,默认开启,用于过滤下方记录。
|
|
177
204
|
- “监听端口”指标卡可以按端口分组。
|
|
178
205
|
- “进程”指标卡可以按进程分组。
|
|
@@ -273,7 +300,7 @@ The GUI can add machines, but the CLI is faster for repeated setup. `add-machine
|
|
|
273
300
|
OpenSSH alias, same as `ssh erya`:
|
|
274
301
|
|
|
275
302
|
```bash
|
|
276
|
-
yaport add-machine --
|
|
303
|
+
yaport add-machine --host erya --json
|
|
277
304
|
```
|
|
278
305
|
|
|
279
306
|
Explicit user and port:
|
|
@@ -327,9 +354,9 @@ Common options:
|
|
|
327
354
|
|
|
328
355
|
| Option | Description |
|
|
329
356
|
| --- | --- |
|
|
330
|
-
| `--name <name>` | Display name in the UI. |
|
|
357
|
+
| `--name <name>` | Display name in the UI. When omitted, Yaport uses `user@host:port`. |
|
|
331
358
|
| `--host <host>` | SSH host, IP address, or OpenSSH alias. |
|
|
332
|
-
| `--user <user>` | SSH user. Omit it when an OpenSSH alias already defines `User
|
|
359
|
+
| `--user <user>` | SSH user. Omit it when an OpenSSH alias already defines `User`; required when `--host` is an IP address. |
|
|
333
360
|
| `--port <port>` | SSH port. Omit it when an OpenSSH alias already defines `Port`. |
|
|
334
361
|
| `--password-env <env>` | Read the target machine SSH password from an environment variable. |
|
|
335
362
|
| `--connect-timeout <seconds>` | SSH connection timeout. Choices: `8`, `15`, `30`, `60`. Default: `15`. |
|
|
@@ -347,8 +374,31 @@ Recommendations:
|
|
|
347
374
|
- Use `--json` from agents and scripts.
|
|
348
375
|
- Prefer `--password-env` and `--jumpN-password-env`; avoid putting passwords directly in process arguments.
|
|
349
376
|
- Omit `--user` and `--port` when `--host` is an OpenSSH alias.
|
|
377
|
+
- IP targets and IP jump hosts must include a user.
|
|
350
378
|
- For slow two-hop jump paths or password handshakes, use `--connect-timeout 30 --command-timeout 90`.
|
|
351
379
|
|
|
380
|
+
## Autostart Service
|
|
381
|
+
|
|
382
|
+
Yaport can install a user-level service without sudo. macOS uses LaunchAgent, and Linux uses a systemd user service. The installed service starts with `--no-open`, so it does not open a browser automatically after login.
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
yaport service install --port 5173 --json
|
|
386
|
+
yaport service status
|
|
387
|
+
yaport service uninstall
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Common options:
|
|
391
|
+
|
|
392
|
+
| Option | Description |
|
|
393
|
+
| --- | --- |
|
|
394
|
+
| `install` | Write and start the user-level service. |
|
|
395
|
+
| `uninstall` | Stop and remove the user-level service. |
|
|
396
|
+
| `status` | Show status through `launchctl` or `systemctl --user`. |
|
|
397
|
+
| `--host <host>` | Service bind host. Default: `127.0.0.1`. |
|
|
398
|
+
| `--port <port>` | Service bind port. Default: `5173`. |
|
|
399
|
+
| `--data-file <path>` | Machine config file used by the service. Without this, Yaport still checks `./.yaport`, then `~/.yaport`. |
|
|
400
|
+
| `--json` | Print deterministic JSON for `install` / `uninstall`. |
|
|
401
|
+
|
|
352
402
|
## Port Inventory
|
|
353
403
|
|
|
354
404
|
Yaport logs in through local OpenSSH and reads:
|
|
@@ -386,6 +436,10 @@ Rules:
|
|
|
386
436
|
|
|
387
437
|
- The add-machine form is collapsed by default.
|
|
388
438
|
- The add-machine form lets you choose connection timeout and command timeout.
|
|
439
|
+
- The connection name is optional. When omitted, Yaport uses the host information. IP hosts require a user; OpenSSH aliases can omit it.
|
|
440
|
+
- The right side of each machine card opens the local Terminal and runs `ssh` with that machine's connection settings. Stored passwords are not written into the command line.
|
|
441
|
+
- The left machine list stays fixed while the page scrolls and can collapse into a narrow rail.
|
|
442
|
+
- Right-click a machine card to edit or delete that connection config. During edits, leaving password fields blank keeps the existing password.
|
|
389
443
|
- TCP and UDP metric cards include switches, both enabled by default, to filter visible records.
|
|
390
444
|
- The listening-port metric card can group the table by port.
|
|
391
445
|
- The process metric card can group the table by process.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--ink:#12211d;--ink-soft:#42514b;--paper:#f7f5ec;--panel:#ebe7d7;--line:#c8cfbf;--rail:#d8e8dc;--teal:#128fa1;--teal-deep:#0b6370;--amber:#c48925;--brick:#a9473b;--white:#fffdf6;--shadow:0 14px 36px #19231e1f;color:var(--ink);background:var(--paper);font-synthesis:none;text-rendering:optimizelegibility;font-family:Aptos,Inter,Segoe UI,system-ui,sans-serif}*{box-sizing:border-box}body{background:linear-gradient(90deg, #12211d08 1px, transparent 1px), linear-gradient(#12211d08 1px, transparent 1px), var(--paper);background-size:24px 24px;min-width:320px;min-height:100vh;margin:0;font-size:14px;line-height:1.35}button,input,select{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed}button:focus-visible,input:focus-visible,select:focus-visible{outline-offset:2px;outline:3px solid #128fa159}.app-shell{grid-template-columns:minmax(280px,326px) 1fr;min-height:100vh;display:grid}.app-shell.sidebar-collapsed{grid-template-columns:64px 1fr}.machine-pane{background:var(--ink);height:100vh;min-height:0;color:var(--white);box-shadow:var(--shadow);flex-direction:column;gap:16px;padding:22px;display:flex;position:sticky;top:0;overflow:hidden}.machine-pane.collapsed{align-items:center;padding:16px 12px}.machine-pane-top{justify-content:space-between;align-items:center;gap:10px;display:flex}.machine-pane.collapsed .machine-pane-top{flex-direction:column}.machine-pane-content{flex-direction:column;flex:auto;gap:16px;min-height:0;padding-right:2px;display:flex;overflow:auto}.brand-block{align-items:center;gap:12px;display:flex}.brand-mark{background:#fffdf614;border:1px solid #fffdf642;border-radius:6px;flex:none;place-items:center;width:40px;height:40px;display:grid}.pane-collapse-button{color:#fffdf6c7;background:#fffdf612;border:1px solid #fffdf629;border-radius:6px;flex:none;place-items:center;width:32px;height:32px;display:inline-grid}.pane-collapse-button:hover{border-color:var(--amber);color:var(--white);background:#c4892529}.eyebrow,.section-label,.form-title,.metric-label{color:var(--ink-soft);letter-spacing:0;text-transform:uppercase;margin:0;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px;font-weight:700}.machine-pane .eyebrow,.machine-pane .section-label,.machine-pane .form-title{color:#fffdf69e}h1,h2{letter-spacing:0;margin:0;font-family:Arial Narrow,Aptos Display,Segoe UI,sans-serif;font-weight:800}h1{font-size:31px;line-height:1}h2{color:var(--ink);font-size:38px;line-height:1.02}.machine-form{gap:12px;padding-top:2px;display:grid}.add-machine-toggle{width:100%;min-height:40px;color:var(--white);text-align:left;background:#fffdf612;border:1px solid #fffdf629;border-radius:6px;justify-content:space-between;align-items:center;gap:10px;padding:0 12px;display:flex}.add-machine-toggle>span:first-child{align-items:center;gap:8px;font-weight:800;display:inline-flex}.add-machine-toggle:hover,.add-machine-toggle[aria-expanded=true]{border-color:var(--amber);background:#c4892529}.toggle-hint{color:#fffdf694;letter-spacing:0;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px;font-weight:800}.jump-hosts{gap:8px;padding-top:2px;display:grid}.jump-host-group{background:#fffdf60d;border:1px solid #fffdf624;border-radius:6px;gap:8px;margin:0;padding:10px;display:grid}.jump-host-group legend{color:#fffdf69e;letter-spacing:0;padding:0 5px;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px;font-weight:800}.form-title,.section-label,.rail-header{align-items:center;gap:7px;display:flex}label{color:#fffdf6b8;gap:6px;font-size:12px;font-weight:700;display:grid}input,select{width:100%;min-height:38px;color:var(--white);background:#fffdf617;border:1px solid #fffdf62e;border-radius:6px;padding:0 10px}select{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}input::placeholder{color:#fffdf657}.form-grid{grid-template-columns:1fr 96px;gap:10px;display:grid}.primary-button,.secondary-button{border:0;border-radius:6px;justify-content:center;align-items:center;gap:7px;min-height:38px;font-size:13px;font-weight:800;display:inline-flex}.primary-button{background:var(--amber);color:#21180a}.secondary-button{border:1px solid var(--line);background:var(--white);color:var(--ink);padding:0 12px}.primary-button:disabled,.secondary-button:disabled{opacity:.55}.machine-list{gap:8px;min-height:0;display:grid}.machine-item{width:100%;color:var(--white);background:#fffdf612;border:1px solid #fffdf624;border-radius:6px;grid-template-columns:minmax(0,1fr) 34px;align-items:center;display:grid;overflow:hidden}.machine-item:hover,.machine-item.active{border-color:var(--amber);background:#c489252e}.machine-select-button{min-width:0;color:inherit;text-align:left;background:0 0;border:0;gap:4px;padding:11px 10px 11px 12px;display:grid}.machine-terminal-button{color:#fffdf6b3;background:#fffdf614;border:1px solid #fffdf624;border-radius:6px;place-items:center;width:28px;height:28px;display:inline-grid}.machine-terminal-button:hover{border-color:var(--teal);color:var(--white);background:#128fa138}.machine-name{font-size:14px;font-weight:800}.machine-address,.target-line,.quiet-state{color:#fffdf694;letter-spacing:0;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px}.machine-address,.target-line{overflow-wrap:anywhere}.quiet-state{border:1px dashed #fffdf633;border-radius:6px;padding:12px}.machine-context-menu{z-index:30;border:1px solid var(--line);background:var(--white);border-radius:6px;min-width:132px;padding:4px;position:fixed;box-shadow:0 12px 28px #12211d2e}.machine-context-menu button{width:100%;min-height:30px;color:var(--ink);text-align:left;background:0 0;border:0;border-radius:4px;align-items:center;gap:7px;padding:0 9px;font-size:12px;font-weight:800;display:flex}.machine-context-menu button:hover{background:#12211d14}.machine-context-menu button.danger{color:var(--brick)}.machine-context-menu button.danger:hover{background:#a9473b1c}.inventory-pane{flex-direction:column;gap:14px;min-width:0;padding:22px 30px;display:flex}.inventory-header{justify-content:space-between;align-items:flex-start;gap:14px;display:flex}.inventory-header .target-line{color:var(--ink-soft);margin:6px 0 0}.error-strip{border-left:5px solid var(--brick);color:#5d211b;white-space:pre-wrap;background:#f2d8cf;padding:10px 12px;font-size:13px;font-weight:700}.signal-rail{border:1px solid var(--line);background:var(--rail);gap:10px;padding:12px;display:grid}.rail-header{color:var(--ink);letter-spacing:0;text-transform:uppercase;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px;font-weight:800}.port-grid{grid-template-columns:repeat(auto-fill,minmax(10px,1fr));align-items:stretch;gap:4px;min-height:38px;display:grid}.port-cell{background:var(--teal);border:1px solid #12211d38;min-height:13px;display:block}.port-cell.udp{background:var(--amber)}.empty-matrix{color:var(--ink-soft);grid-column:1/-1;align-self:center;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px}.summary-grid{grid-template-columns:repeat(5,minmax(106px,1fr));gap:10px;display:grid}.metric{border:1px solid var(--line);background:var(--white);gap:6px;min-height:72px;padding:10px 12px;display:grid}.metric-topline{justify-content:space-between;align-items:flex-start;gap:8px;min-width:0;display:flex}.metric.cyan{border-bottom:4px solid var(--teal)}.metric.amber{border-bottom:4px solid var(--amber)}.metric-label{align-items:center;gap:6px;min-width:0;display:inline-flex}.metric strong{align-self:end;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:28px;line-height:1}.metric-switch{border:1px solid var(--line);background:#e7e4d8;border-radius:999px;flex:none;align-items:center;width:36px;height:20px;padding:2px;display:inline-flex}.metric-switch span{background:var(--white);border-radius:999px;width:14px;height:14px;transition:transform .14s;display:block;box-shadow:0 1px 3px #12211d38}.metric-switch[aria-checked=true]{border-color:var(--teal);background:#128fa142}.metric-switch[aria-checked=true] span{background:var(--teal-deep);transform:translate(16px)}.table-wrap{border:1px solid var(--line);background:var(--white);overflow:auto}table{border-collapse:collapse;width:100%;min-width:920px}th,td{border-bottom:1px solid var(--line);text-align:left;padding:10px 12px}th{color:var(--ink-soft);letter-spacing:0;text-transform:uppercase;background:#e4eadf;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px}td{font-size:13px}tbody tr:hover{background:#f1f4eb}.group-row td{border-bottom:1px solid var(--line);background:#edf0e7;padding:7px 12px}.group-row-label{color:var(--ink-soft);justify-content:space-between;align-items:center;gap:12px;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px;font-weight:800;display:flex}.group-row-label span:first-child{overflow-wrap:anywhere;min-width:0}.group-row-label span:last-child{flex:none}.protocol-pill{min-width:44px;color:var(--teal-deep);background:#128fa129;border-radius:999px;justify-content:center;padding:3px 7px;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px;font-weight:800;display:inline-flex}.protocol-pill.udp{color:#734a08;background:#c4892533}.mono,.port-number{font-variant-numeric:tabular-nums;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace}.port-number{font-weight:800}.process-cell{overflow-wrap:anywhere;min-width:180px;max-width:300px;line-height:1.35}.route-list{flex-wrap:wrap;gap:6px;min-width:190px;display:flex}.route-chip{max-width:280px;color:var(--teal-deep);letter-spacing:0;background:linear-gradient(90deg,#128fa124,#d8e8dc70);border:1px solid #128fa147;border-radius:999px;align-items:center;gap:6px;padding:5px 8px;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px;font-weight:800;text-decoration:none;display:inline-flex}.route-source-badge{width:17px;height:17px;color:var(--white);flex:none;justify-content:center;align-items:center;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:10px;font-weight:900;line-height:1;display:inline-flex}.route-source-badge.nginx{clip-path:polygon(25% 4%,75% 4%,100% 50%,75% 96%,25% 96%,0 50%);background:#05924d;box-shadow:inset 0 -1px #12211d3d}.route-chip-url{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.route-chip:hover{border-color:var(--teal);background:#128fa12e}.route-empty{color:#42514b8a;font-family:SFMono-Regular,Cascadia Mono,Roboto Mono,monospace;font-size:11px}.table-empty{height:140px;color:var(--ink-soft);text-align:center;position:sticky;left:0}.spin{animation:.9s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;animation-duration:1ms!important;animation-iteration-count:1!important}}@media (width<=980px){.app-shell,.app-shell.sidebar-collapsed{grid-template-columns:1fr}.machine-pane{height:auto;min-height:auto;padding:20px;position:static}.machine-pane.collapsed{align-items:stretch}.machine-pane.collapsed .machine-pane-top{flex-direction:row}h1{font-size:30px}h2{font-size:34px}.summary-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.metric.wide{grid-column:span 2}}@media (width<=560px){.machine-pane,.inventory-pane{padding:16px}h1{font-size:28px}h2{font-size:30px}.inventory-header{flex-direction:column;align-items:stretch}.form-grid,.summary-grid{grid-template-columns:1fr}.metric.wide{grid-column:auto}.secondary-button{width:100%}}
|