@hyzyn/dsh-docker 0.7.1 → 0.7.3
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/client-src/docker.css +13 -0
- package/client-src/index.js +18 -3
- package/client-src/session-target.js +30 -0
- package/client.js +30 -17
- package/lib/index.d.ts +13 -2
- package/lib/index.js +50 -30
- package/lib/index.js.map +1 -1
- package/package.json +13 -6
- package/scripts/route-smoke.mjs +30 -19
- package/scripts/smoke.mjs +7 -0
package/client-src/docker.css
CHANGED
|
@@ -1981,6 +1981,19 @@
|
|
|
1981
1981
|
/* 删除按钮靠右,不跟着列宽被拉长 */
|
|
1982
1982
|
.dk_targetRow > .dk_btnDanger { justify-self: end; }
|
|
1983
1983
|
|
|
1984
|
+
/*
|
|
1985
|
+
* 失效的连接簿引用(引用的条目名不在 tty 连接簿里):标黄整行 + 左侧色条。
|
|
1986
|
+
* 为什么必须可见:book 下拉的候选项来自 ttyBooks,失效的名字没有对应 option,
|
|
1987
|
+
* 下拉会渲染成**空白**——界面上看不出错,直到真去连才报「引用的连接簿条目不存在」。
|
|
1988
|
+
*/
|
|
1989
|
+
.dk_targetRow[data-stale] {
|
|
1990
|
+
border-color: var(--dk-warn);
|
|
1991
|
+
box-shadow: inset 2px 0 0 var(--dk-warn);
|
|
1992
|
+
}
|
|
1993
|
+
.dk_hintWarn {
|
|
1994
|
+
color: var(--dk-warn);
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1984
1997
|
.dk_targetInline {
|
|
1985
1998
|
display: grid;
|
|
1986
1999
|
grid-column: 1 / -1;
|
package/client-src/index.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* (宿主只回 passwordSet / passphraseSet 布尔)。
|
|
18
18
|
*/
|
|
19
19
|
import dockerCss from './docker.css'
|
|
20
|
-
import { bookSessionHost, pickTargetByHost, sessionHostPort } from './session-target.js'
|
|
20
|
+
import { bookSessionHost, pickTargetByHost, sessionHostPort, staleBookRef } from './session-target.js'
|
|
21
21
|
import { currentSessionIdOf } from './current-session.js'
|
|
22
22
|
|
|
23
23
|
const API = '/api/dsh-docker'
|
|
@@ -5958,7 +5958,15 @@ window.__ModuleLoader__.load({
|
|
|
5958
5958
|
jsx('span', { className: 'dk_hint', children: 'docker socket 等价于目标主机的 root 权限。开启后,浏览器面板与 agent 都能执行对应操作,请只在可信环境下打开。' }),
|
|
5959
5959
|
|
|
5960
5960
|
sectionTitle('目标'),
|
|
5961
|
-
...form.targets.map((item, index) =>
|
|
5961
|
+
...form.targets.map((item, index) => {
|
|
5962
|
+
/*
|
|
5963
|
+
* 失效引用(引用的条目名不在 tty 连接簿里):下拉会**渲染成空白**——没有任何
|
|
5964
|
+
* option 与 item.book 匹配,界面上看不出"这里引用错了",要等真去连才报错。
|
|
5965
|
+
* 这里两件事一起做:给那一行标记 data-stale(标黄),并把失效的名字补成一个
|
|
5966
|
+
* 显式 option,免得用户看到一个空白下拉、以为是"没选"。
|
|
5967
|
+
*/
|
|
5968
|
+
const stale = staleBookRef(item, form.ttyBooks)
|
|
5969
|
+
return jsxs('div', { className: 'dk_targetRow', 'data-stale': stale !== undefined ? '1' : undefined, children: [
|
|
5962
5970
|
jsx('input', { className: 'dk_input', value: item.name, placeholder: '目标名', onChange: (event) => patchTarget(index, { name: event.target.value }) }),
|
|
5963
5971
|
jsx('select', { className: 'dk_select', value: item.kind, onChange: (event) => patchTarget(index, { kind: event.target.value }), children: [
|
|
5964
5972
|
jsx('option', { value: 'local', children: '本机' }),
|
|
@@ -5971,11 +5979,17 @@ window.__ModuleLoader__.load({
|
|
|
5971
5979
|
className: 'dk_select',
|
|
5972
5980
|
value: item.book ?? '',
|
|
5973
5981
|
onChange: (event) => patchTarget(index, { book: event.target.value }),
|
|
5982
|
+
title: stale !== undefined ? `引用的连接簿条目「${stale}」不存在——请改选一个已有条目,或清空改为手填` : undefined,
|
|
5974
5983
|
children: [
|
|
5975
5984
|
jsx('option', { value: '', children: form.ttyBooks.length === 0 ? '(无 tty 连接簿,请填内联信息)' : '(不用连接簿,手填)' }),
|
|
5985
|
+
// 失效的名字排在最前并显式标注:否则它没有对应 option,下拉显示空白
|
|
5986
|
+
...(stale !== undefined ? [jsx('option', { value: stale, children: '⚠ 条目已不存在:' + stale }, stale)] : []),
|
|
5976
5987
|
...form.ttyBooks.map((name) => jsx('option', { value: name, children: '连接簿:' + name }, name)),
|
|
5977
5988
|
],
|
|
5978
5989
|
}),
|
|
5990
|
+
stale !== undefined
|
|
5991
|
+
? jsx('span', { className: 'dk_hint dk_hintWarn', children: `引用的条目「${stale}」不在 tty 连接簿里——请改选,或清空后手填` })
|
|
5992
|
+
: null,
|
|
5979
5993
|
] }),
|
|
5980
5994
|
jsx('button', { type: 'button', className: 'dk_btn dk_btnDanger', onClick: () => removeTarget(index), children: '删除' }),
|
|
5981
5995
|
/*
|
|
@@ -5995,7 +6009,8 @@ window.__ModuleLoader__.load({
|
|
|
5995
6009
|
(item.auth ?? 'agent') === 'password' ? jsx('input', { className: 'dk_input dk_credential', type: 'password', placeholder: item.passwordSet === true ? '(已设置,留空保持不变)' : 'env:SSH_PASSWORD', value: item.password ?? '', onChange: (event) => patchTarget(index, { password: event.target.value }) }) : null,
|
|
5996
6010
|
jsx('label', { className: 'dk_check', children: [jsx('input', { type: 'checkbox', checked: item.agentForward === true, onChange: (event) => patchTarget(index, { agentForward: event.target.checked }) }), 'agent forwarding'] }),
|
|
5997
6011
|
] }) : null,
|
|
5998
|
-
|
|
6012
|
+
] }, String(index))
|
|
6013
|
+
}),
|
|
5999
6014
|
jsxs('div', { className: 'dk_row', children: [
|
|
6000
6015
|
jsx('button', { type: 'button', className: 'dk_btn', onClick: addTarget, children: '添加目标' }),
|
|
6001
6016
|
jsx('span', { className: 'dk_hint', children: 'SSH 目标推荐直接选 tty 终端面板的连接簿条目(凭证只需维护一处);手填时密码 / 口令建议写 env:NAME(凭据引用:由官方凭据存储解析,缺失时退回环境变量)。' }),
|
|
@@ -90,3 +90,33 @@ export function bookSessionHost(bookName, rows) {
|
|
|
90
90
|
}
|
|
91
91
|
return undefined
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 目标引用的连接簿条目是否**已失效**(引用的名字在 tty 连接簿里不存在)。
|
|
96
|
+
*
|
|
97
|
+
* 为什么需要它:`book` 那个下拉的候选项来自 `ttyBooks`,一旦引用的名字不在其中,
|
|
98
|
+
* 下拉会**渲染成空白**(没有任何 option 与之匹配)——界面上完全看不出"这里引用错了",
|
|
99
|
+
* 直到真的去连才报「引用的连接簿条目不存在」。用户改了 tty 侧条目名(改名 / 重装 /
|
|
100
|
+
* 换机器)之后就会落到这个状态,且无从发现。
|
|
101
|
+
*
|
|
102
|
+
* 判定只针对 **ssh + 有 book** 的目标:本机目标不看连接簿;没填 book(走内联
|
|
103
|
+
* host/username)也不算失效——那是另一种合法配置。
|
|
104
|
+
*
|
|
105
|
+
* @param target 配置里的目标条目
|
|
106
|
+
* @param ttyBooks `/config.ttyBooks`:tty 连接簿的条目名数组
|
|
107
|
+
* @returns 引用的条目名(失效时),否则 undefined
|
|
108
|
+
*/
|
|
109
|
+
export function staleBookRef(target, ttyBooks) {
|
|
110
|
+
if (target === null || typeof target !== 'object') return undefined
|
|
111
|
+
if (target.kind !== 'ssh') return undefined
|
|
112
|
+
const book = typeof target.book === 'string' ? target.book.trim() : ''
|
|
113
|
+
if (book === '') return undefined
|
|
114
|
+
const books = Array.isArray(ttyBooks) ? ttyBooks : []
|
|
115
|
+
// tty 未安装 / 连接簿为空时**不算**引用失效:那是"宿主没装 tty"或"条目还没建",
|
|
116
|
+
// 与"引用了一个不存在的名字"是两回事,标黄会误导(此时整体提示已在卡片顶部给过)。
|
|
117
|
+
if (books.length === 0) return undefined
|
|
118
|
+
for (const name of books) {
|
|
119
|
+
if (name === book) return undefined
|
|
120
|
+
}
|
|
121
|
+
return book
|
|
122
|
+
}
|