@linxin666/dsh-ssh 0.3.2 → 0.3.4
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.i18n.yaml +2 -2
- package/README.md +7 -3
- package/README.zh.md +7 -3
- package/lib/client.js +71 -0
- package/lib/client.js.map +1 -1
- package/lib/index.js +12 -7
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/telemetry.d.ts +26 -0
- package/lib/types/http.d.ts +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/loopback.d.ts +1 -1
- package/lib/types/mount-once.d.ts +1 -1
- package/package.json +2 -2
- package/src/client/index.ts +6 -1
- package/src/client/panel/SshPanel.tsx +1 -1
- package/src/client/telemetry.ts +105 -0
- package/src/dsh-home.ts +9 -3
- package/src/engine/sftp.ts +1 -1
- package/src/http.ts +1 -1
- package/src/index.ts +1 -1
- package/src/loopback.ts +1 -1
- package/src/mount-once.ts +2 -2
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# node scripts/verify-docs.mjs --write <dir>
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: bf12f2cd3c82e9f12800c74f1d907f8cf08370f2
|
|
6
|
+
README.zh.md: c404cbbf891f1d004ff23dc52c95d1e67d665450
|
package/README.md
CHANGED
|
@@ -32,15 +32,15 @@ Built on the capability list of [badseal/ssh-skill](https://github.com/badseal/s
|
|
|
32
32
|
|
|
33
33
|
## Install
|
|
34
34
|
|
|
35
|
-
Install the family aggregate package `@linxin666/dsh-web-
|
|
35
|
+
Install the family aggregate package `@linxin666/dsh-web-all` (all plugins and skins in one) or this plugin alone:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
38
|
### From npm (recommended)
|
|
39
39
|
dsh plugin --profile web add @linxin666/dsh-ssh@latest
|
|
40
40
|
|
|
41
41
|
### From the repository (development)
|
|
42
|
-
git clone https://github.com/zhu1090093659/dsh-web
|
|
43
|
-
cd dsh-web
|
|
42
|
+
git clone https://github.com/zhu1090093659/dsh-web.git
|
|
43
|
+
cd dsh-web
|
|
44
44
|
pnpm install && pnpm -r build
|
|
45
45
|
dsh plugin --profile web add link:$(pwd)/packages/dsh-ssh
|
|
46
46
|
|
|
@@ -73,3 +73,7 @@ pnpm --filter @linxin666/dsh-ssh build # tsc types + tsdown dual-half artifact
|
|
|
73
73
|
- Every hop of a ProxyJump jump host must be a host alias already configured in this plugin.
|
|
74
74
|
- Resume (broken-transfer continuation) is not implemented yet.
|
|
75
75
|
- The transfer of Agent tools is a host-machine local path (same semantics as ssh-skill).
|
|
76
|
+
|
|
77
|
+
## Telemetry
|
|
78
|
+
|
|
79
|
+
The browser half sends one anonymous install heartbeat per UTC day to dsh-market.com: a random localStorage id plus this package's name, nothing else. The server stores only a salted hash of that id, never IP addresses, and exposes aggregate counts only. See [docs/telemetry.md](../../docs/telemetry.md) for the full contract.
|
package/README.zh.md
CHANGED
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
|
|
33
33
|
## 安装
|
|
34
34
|
|
|
35
|
-
推荐直接安装全家桶聚合包 `@linxin666/dsh-web-
|
|
35
|
+
推荐直接安装全家桶聚合包 `@linxin666/dsh-web-all`(一个包装齐全部功能插件与皮肤),或单独安装本插件:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
38
|
### 从 npm 安装(推荐)
|
|
39
39
|
dsh plugin --profile web add @linxin666/dsh-ssh@latest
|
|
40
40
|
|
|
41
41
|
### 从仓库安装(开发调试)
|
|
42
|
-
git clone https://github.com/zhu1090093659/dsh-web
|
|
43
|
-
cd dsh-web
|
|
42
|
+
git clone https://github.com/zhu1090093659/dsh-web.git
|
|
43
|
+
cd dsh-web
|
|
44
44
|
pnpm install && pnpm -r build
|
|
45
45
|
dsh plugin --profile web add link:$(pwd)/packages/dsh-ssh
|
|
46
46
|
|
|
@@ -73,3 +73,7 @@ pnpm --filter @linxin666/dsh-ssh build # tsc 类型 + tsdown 双半区产物
|
|
|
73
73
|
- 跳板机 ProxyJump 的每一跳必须是本插件已配置的主机别名。
|
|
74
74
|
- 断点续传(resume)暂未实现。
|
|
75
75
|
- Agent 工具的传输为宿主机器本地路径(与 ssh-skill 相同的语义)。
|
|
76
|
+
|
|
77
|
+
## 数据遥测
|
|
78
|
+
|
|
79
|
+
浏览器半区每个 UTC 日向 dsh-market.com 发送一次匿名安装心跳:仅含一个 localStorage 随机 ID 与本包名,无其他数据。服务端只存储该 ID 的加盐哈希,不存 IP,且只暴露聚合计数。完整契约见 [docs/telemetry.md](../../docs/telemetry.md)。
|
package/lib/client.js
CHANGED
|
@@ -15975,6 +15975,76 @@ window.__ModuleLoader__.load({
|
|
|
15975
15975
|
});
|
|
15976
15976
|
}
|
|
15977
15977
|
//#endregion
|
|
15978
|
+
//#region src/client/telemetry.ts
|
|
15979
|
+
const VISITOR_KEY = "dsh-web-ui-telemetry-visitor";
|
|
15980
|
+
const DAY_KEY_PREFIX = "dsh-web-ui-telemetry-day:";
|
|
15981
|
+
const ENDPOINT = "https://dsh-market.com/api/telemetry/event";
|
|
15982
|
+
/** The building package's version, when the bundle carries it. */
|
|
15983
|
+
function bakedVersion() {
|
|
15984
|
+
try {
|
|
15985
|
+
return "0.3.4";
|
|
15986
|
+
} catch {
|
|
15987
|
+
return;
|
|
15988
|
+
}
|
|
15989
|
+
}
|
|
15990
|
+
/** Read or lazily create the anonymous visitor id; null when storage is unavailable. */
|
|
15991
|
+
function visitorId() {
|
|
15992
|
+
try {
|
|
15993
|
+
const existing = localStorage.getItem(VISITOR_KEY);
|
|
15994
|
+
if (existing && /^[A-Za-z0-9_-]{16,64}$/.test(existing)) return existing;
|
|
15995
|
+
const fresh = crypto.randomUUID().replaceAll("-", "");
|
|
15996
|
+
localStorage.setItem(VISITOR_KEY, fresh);
|
|
15997
|
+
return fresh;
|
|
15998
|
+
} catch {
|
|
15999
|
+
return null;
|
|
16000
|
+
}
|
|
16001
|
+
}
|
|
16002
|
+
/** Drop stale per-day dedup keys so localStorage does not grow forever. */
|
|
16003
|
+
function pruneDayKeys(today) {
|
|
16004
|
+
try {
|
|
16005
|
+
for (let index = localStorage.length - 1; index >= 0; index -= 1) {
|
|
16006
|
+
const key = localStorage.key(index);
|
|
16007
|
+
if (key !== null && key.startsWith(DAY_KEY_PREFIX) && key !== DAY_KEY_PREFIX + today) localStorage.removeItem(key);
|
|
16008
|
+
}
|
|
16009
|
+
} catch {}
|
|
16010
|
+
}
|
|
16011
|
+
/**
|
|
16012
|
+
* Fire the daily heartbeat for the given items at most once per UTC day per
|
|
16013
|
+
* browser. Never throws and never blocks the caller. Items without an explicit
|
|
16014
|
+
* version inherit the bundle's baked build version.
|
|
16015
|
+
*/
|
|
16016
|
+
function reportDailyHeartbeat(items) {
|
|
16017
|
+
try {
|
|
16018
|
+
if (items.length === 0) return;
|
|
16019
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
16020
|
+
if (navigator.webdriver) return;
|
|
16021
|
+
if (localStorage.getItem(DAY_KEY_PREFIX + today) !== null) return;
|
|
16022
|
+
const visitor = visitorId();
|
|
16023
|
+
if (visitor === null) return;
|
|
16024
|
+
pruneDayKeys(today);
|
|
16025
|
+
const payloadItems = items.map((item) => {
|
|
16026
|
+
const out = { name: item.name };
|
|
16027
|
+
const version = item.version ?? bakedVersion();
|
|
16028
|
+
if (version !== void 0) out.version = version;
|
|
16029
|
+
if (item.channel !== void 0) out.channel = item.channel;
|
|
16030
|
+
return out;
|
|
16031
|
+
});
|
|
16032
|
+
const body = JSON.stringify({
|
|
16033
|
+
kind: "heartbeat",
|
|
16034
|
+
visitor,
|
|
16035
|
+
items: payloadItems
|
|
16036
|
+
});
|
|
16037
|
+
fetch(ENDPOINT, {
|
|
16038
|
+
method: "POST",
|
|
16039
|
+
headers: { "content-type": "application/json" },
|
|
16040
|
+
body,
|
|
16041
|
+
keepalive: true
|
|
16042
|
+
}).then((response) => {
|
|
16043
|
+
if (response.ok) localStorage.setItem(DAY_KEY_PREFIX + today, "1");
|
|
16044
|
+
}).catch(() => {});
|
|
16045
|
+
} catch {}
|
|
16046
|
+
}
|
|
16047
|
+
//#endregion
|
|
15978
16048
|
//#region src/client/index.ts
|
|
15979
16049
|
/** Locale namespace this plugin owns. */
|
|
15980
16050
|
const NS = "dsh-ssh";
|
|
@@ -15991,6 +16061,7 @@ window.__ModuleLoader__.load({
|
|
|
15991
16061
|
* @param ctx - client root context (locale service).
|
|
15992
16062
|
*/
|
|
15993
16063
|
function apply(ctx) {
|
|
16064
|
+
reportDailyHeartbeat([{ name: "@linxin666/dsh-ssh" }]);
|
|
15994
16065
|
ctx.effect(() => {
|
|
15995
16066
|
try {
|
|
15996
16067
|
return ctx.locale.register(NS, {
|