@wenbin_wb/dsh-bridge 2.0.1 → 2.0.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/README.md +10 -0
- package/README.zh-CN.md +10 -0
- package/client/client.js +59 -11
- package/client/index.js +62 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,16 @@ dsh plugin --profile web add @wenbin_wb/dsh-bridge@latest
|
|
|
95
95
|
|
|
96
96
|
> **Note**: `update --latest` may fail to reach the newest major version due to version constraints from already-installed dependencies. Use the `add @latest` command above to force-install the latest version (no need to know the exact version number).
|
|
97
97
|
|
|
98
|
+
#### Still on an old version after upgrading? (pnpm 11 new-version filtering)
|
|
99
|
+
|
|
100
|
+
If you upgrade right after a release, `add @latest` may still install an older version. This is caused by **pnpm 11's supply-chain safety mechanism `minimumReleaseAge`** (default: filters versions published less than 24 hours ago) — not a plugin issue.
|
|
101
|
+
|
|
102
|
+
**Solutions** (pick one):
|
|
103
|
+
|
|
104
|
+
1. **Add `minimumReleaseAge: 0` to your profile's `pnpm-workspace.yaml`**, then run `pnpm install` (recommended, permanent)
|
|
105
|
+
2. **Specify the exact version**: `dsh plugin --profile web add @wenbin_wb/dsh-bridge@2.0.2` (works immediately, no waiting)
|
|
106
|
+
3. **Wait 24 hours**: the protection lifts automatically after 1 day
|
|
107
|
+
|
|
98
108
|
After upgrading, restart DSH and **hard-refresh** the browser (Windows: `Ctrl+Shift+R`, macOS: `Cmd+Shift+R`) to clear the cache, then confirm the latest version is shown in settings.
|
|
99
109
|
|
|
100
110
|
---
|
package/README.zh-CN.md
CHANGED
|
@@ -95,6 +95,16 @@ dsh plugin --profile web add @wenbin_wb/dsh-bridge@latest
|
|
|
95
95
|
|
|
96
96
|
> **注意**:`update --latest` 可能因已安装依赖的版本约束而无法升级到最新版。用上面的 `add @latest` 命令即可强制安装最新版(无需知道具体版本号)。
|
|
97
97
|
|
|
98
|
+
#### 升级后仍是旧版本?(pnpm 11 新版本过滤)
|
|
99
|
+
|
|
100
|
+
如果你刚发布后立即升级,`add @latest` 可能仍然装到旧版本。这是 **pnpm 11 的供应链安全机制 `minimumReleaseAge`**(默认过滤发布不足 24 小时的新版本)导致的,不是插件问题。
|
|
101
|
+
|
|
102
|
+
**解决方法**(任选其一):
|
|
103
|
+
|
|
104
|
+
1. **在 profile 的 `pnpm-workspace.yaml` 添加 `minimumReleaseAge: 0`**,然后重新 `pnpm install`(推荐,一劳永逸)
|
|
105
|
+
2. **显式指定版本号**:`dsh plugin --profile web add @wenbin_wb/dsh-bridge@2.0.2`(立即生效,无需等待)
|
|
106
|
+
3. **等待 24 小时**:发布满 1 天后保护自动解除
|
|
107
|
+
|
|
98
108
|
升级完成后重启 DSH,并在浏览器**硬刷新**(Windows: `Ctrl+Shift+R`,macOS: `Cmd+Shift+R`)清除缓存,然后确认设置页显示最新版本号。
|
|
99
109
|
|
|
100
110
|
---
|
package/client/client.js
CHANGED
|
@@ -62,8 +62,10 @@ var BRIDGE_ENDPOINTS = {
|
|
|
62
62
|
|
|
63
63
|
// client/index.js
|
|
64
64
|
var GITHUB_URL = "https://github.com/wenbin-wb/dsh-bridge";
|
|
65
|
+
var RELEASES_URL = "https://github.com/wenbin-wb/dsh-bridge/releases";
|
|
65
66
|
var ISSUES_URL = "https://github.com/wenbin-wb/dsh-bridge/issues/new";
|
|
66
67
|
var TUNNEL_DOCS_URL = "https://github.com/wenbin-wb/dsh-bridge/blob/main/docs/custom-tunnel.md";
|
|
68
|
+
var UPGRADE_COMMAND = "dsh plugin --profile web add @wenbin_wb/dsh-bridge@latest";
|
|
67
69
|
var name = "dsh-bridge";
|
|
68
70
|
var inject = ["slots", "connection"];
|
|
69
71
|
function semverGt(a, b) {
|
|
@@ -95,6 +97,32 @@ var s = {
|
|
|
95
97
|
warn: { background: "var(--dsw-alias-state-warn-bg,#fffbeb)", border: "1px solid var(--dsw-alias-state-warn-border,#fde68a)", borderRadius: 8, padding: "10px 14px", fontSize: 12, color: "var(--dsw-alias-state-warn-primary,#92400e)", lineHeight: 1.6 },
|
|
96
98
|
tip: { background: "var(--dsw-alias-bg-layer-2,#f9fafb)", borderRadius: 8, padding: "10px 14px", fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)", lineHeight: 1.6 }
|
|
97
99
|
};
|
|
100
|
+
function useCopy() {
|
|
101
|
+
const [copied, setCopied] = React.useState(false);
|
|
102
|
+
const copy = React.useCallback((text) => {
|
|
103
|
+
const done = () => {
|
|
104
|
+
setCopied(true);
|
|
105
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
106
|
+
};
|
|
107
|
+
if (navigator.clipboard?.writeText) {
|
|
108
|
+
navigator.clipboard.writeText(text).then(done).catch(() => fallbackCopy());
|
|
109
|
+
} else {
|
|
110
|
+
fallbackCopy();
|
|
111
|
+
}
|
|
112
|
+
function fallbackCopy() {
|
|
113
|
+
const textarea = document.createElement("textarea");
|
|
114
|
+
textarea.value = text;
|
|
115
|
+
textarea.style.position = "fixed";
|
|
116
|
+
textarea.style.opacity = "0";
|
|
117
|
+
document.body.appendChild(textarea);
|
|
118
|
+
textarea.select();
|
|
119
|
+
const success = document.execCommand("copy");
|
|
120
|
+
document.body.removeChild(textarea);
|
|
121
|
+
if (success) done();
|
|
122
|
+
}
|
|
123
|
+
}, []);
|
|
124
|
+
return [copied, copy];
|
|
125
|
+
}
|
|
98
126
|
function StatusTag({ running }) {
|
|
99
127
|
return React.createElement("span", {
|
|
100
128
|
style: {
|
|
@@ -589,6 +617,7 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
589
617
|
function VersionBanner({ rpcCall }) {
|
|
590
618
|
const [info, setInfo] = React.useState(null);
|
|
591
619
|
const [loading, setLoading] = React.useState(false);
|
|
620
|
+
const [copied, copy] = useCopy();
|
|
592
621
|
const check = React.useCallback(async () => {
|
|
593
622
|
setLoading(true);
|
|
594
623
|
try {
|
|
@@ -604,13 +633,19 @@ function VersionBanner({ rpcCall }) {
|
|
|
604
633
|
const hasUpdate = info?.latest && info?.current && !info.error && semverGt(info.latest, info.current);
|
|
605
634
|
const links = React.createElement(
|
|
606
635
|
"div",
|
|
607
|
-
{ style: { display: "flex", gap: 12, alignItems: "center" } },
|
|
636
|
+
{ style: { display: "flex", gap: 12, alignItems: "center", flexWrap: "wrap" } },
|
|
608
637
|
React.createElement("a", {
|
|
609
638
|
href: GITHUB_URL,
|
|
610
639
|
target: "_blank",
|
|
611
640
|
rel: "noreferrer",
|
|
612
641
|
style: s.btnLink
|
|
613
642
|
}, "\u2B50 GitHub"),
|
|
643
|
+
React.createElement("a", {
|
|
644
|
+
href: RELEASES_URL,
|
|
645
|
+
target: "_blank",
|
|
646
|
+
rel: "noreferrer",
|
|
647
|
+
style: s.btnLink
|
|
648
|
+
}, "\u{1F4CB} \u66F4\u65B0\u65E5\u5FD7"),
|
|
614
649
|
React.createElement("a", {
|
|
615
650
|
href: ISSUES_URL,
|
|
616
651
|
target: "_blank",
|
|
@@ -639,23 +674,36 @@ function VersionBanner({ rpcCall }) {
|
|
|
639
674
|
React.createElement("span", { style: { fontSize: 20 } }, "\u{1F389}"),
|
|
640
675
|
React.createElement(
|
|
641
676
|
"div",
|
|
642
|
-
{ style: { flex: 1 } },
|
|
677
|
+
{ style: { flex: 1, minWidth: 0 } },
|
|
643
678
|
React.createElement("div", {
|
|
644
679
|
style: {
|
|
645
680
|
fontSize: 13,
|
|
646
681
|
fontWeight: 600,
|
|
647
682
|
color: "var(--dsw-alias-state-info-primary,#1e40af)",
|
|
648
|
-
marginBottom:
|
|
683
|
+
marginBottom: 6
|
|
649
684
|
}
|
|
650
685
|
}, `\u53D1\u73B0\u65B0\u7248\u672C v${info.latest}\uFF08\u5F53\u524D v${info.current}\uFF09`),
|
|
651
|
-
React.createElement(
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
686
|
+
React.createElement(
|
|
687
|
+
"div",
|
|
688
|
+
{
|
|
689
|
+
style: { display: "flex", alignItems: "center", gap: 8 }
|
|
690
|
+
},
|
|
691
|
+
React.createElement("code", {
|
|
692
|
+
style: {
|
|
693
|
+
...s.code,
|
|
694
|
+
fontSize: 11,
|
|
695
|
+
color: "var(--dsw-alias-label-secondary,#6b7280)",
|
|
696
|
+
flex: 1,
|
|
697
|
+
minWidth: 0,
|
|
698
|
+
wordBreak: "break-all"
|
|
699
|
+
}
|
|
700
|
+
}, UPGRADE_COMMAND),
|
|
701
|
+
React.createElement("button", {
|
|
702
|
+
style: { ...s.btnGhost, height: 26, padding: "0 10px", fontSize: 12, flexShrink: 0 },
|
|
703
|
+
onClick: () => copy(UPGRADE_COMMAND),
|
|
704
|
+
title: "\u590D\u5236\u5347\u7EA7\u547D\u4EE4"
|
|
705
|
+
}, copied ? "\u2713 \u5DF2\u590D\u5236" : "\u590D\u5236")
|
|
706
|
+
)
|
|
659
707
|
),
|
|
660
708
|
React.createElement("button", {
|
|
661
709
|
style: {
|
package/client/index.js
CHANGED
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
import { BRIDGE_RPC_CHANNEL, BRIDGE_ENDPOINTS } from '../lib/bridge-rpc-constants.js';
|
|
4
4
|
|
|
5
5
|
const GITHUB_URL = 'https://github.com/wenbin-wb/dsh-bridge';
|
|
6
|
+
const RELEASES_URL = 'https://github.com/wenbin-wb/dsh-bridge/releases';
|
|
6
7
|
const ISSUES_URL = 'https://github.com/wenbin-wb/dsh-bridge/issues/new';
|
|
7
8
|
const TUNNEL_DOCS_URL = 'https://github.com/wenbin-wb/dsh-bridge/blob/main/docs/custom-tunnel.md';
|
|
8
9
|
|
|
10
|
+
// 升级命令:用 add @latest 强制安装最新版(update --latest 受已安装依赖版本约束可能无法升级到最新版)
|
|
11
|
+
const UPGRADE_COMMAND = 'dsh plugin --profile web add @wenbin_wb/dsh-bridge@latest';
|
|
12
|
+
|
|
9
13
|
const name = 'dsh-bridge';
|
|
10
14
|
const inject = ['slots', 'connection'];
|
|
11
15
|
|
|
@@ -43,6 +47,35 @@ const s = {
|
|
|
43
47
|
|
|
44
48
|
// ---- 子组件 ----
|
|
45
49
|
|
|
50
|
+
// 通用复制 hook:返回 [copied, copy],copy(text) 复制文本并短暂显示成功状态
|
|
51
|
+
function useCopy() {
|
|
52
|
+
const [copied, setCopied] = React.useState(false);
|
|
53
|
+
const copy = React.useCallback((text) => {
|
|
54
|
+
const done = () => {
|
|
55
|
+
setCopied(true);
|
|
56
|
+
setTimeout(() => setCopied(false), 2000);
|
|
57
|
+
};
|
|
58
|
+
if (navigator.clipboard?.writeText) {
|
|
59
|
+
navigator.clipboard.writeText(text).then(done).catch(() => fallbackCopy());
|
|
60
|
+
} else {
|
|
61
|
+
fallbackCopy();
|
|
62
|
+
}
|
|
63
|
+
// 降级方案:使用 document.execCommand (HTTP 环境下 Clipboard API 不可用)
|
|
64
|
+
function fallbackCopy() {
|
|
65
|
+
const textarea = document.createElement('textarea');
|
|
66
|
+
textarea.value = text;
|
|
67
|
+
textarea.style.position = 'fixed';
|
|
68
|
+
textarea.style.opacity = '0';
|
|
69
|
+
document.body.appendChild(textarea);
|
|
70
|
+
textarea.select();
|
|
71
|
+
const success = document.execCommand('copy');
|
|
72
|
+
document.body.removeChild(textarea);
|
|
73
|
+
if (success) done();
|
|
74
|
+
}
|
|
75
|
+
}, []);
|
|
76
|
+
return [copied, copy];
|
|
77
|
+
}
|
|
78
|
+
|
|
46
79
|
function StatusTag({ running }) {
|
|
47
80
|
return React.createElement('span', {
|
|
48
81
|
style: {
|
|
@@ -507,8 +540,10 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
507
540
|
}
|
|
508
541
|
|
|
509
542
|
// 版本检查 + GitHub/反馈入口
|
|
510
|
-
function VersionBanner({ rpcCall }) {
|
|
543
|
+
function VersionBanner({ rpcCall }) {
|
|
544
|
+
const [info, setInfo] = React.useState(null);
|
|
511
545
|
const [loading, setLoading] = React.useState(false);
|
|
546
|
+
const [copied, copy] = useCopy();
|
|
512
547
|
|
|
513
548
|
const check = React.useCallback(async () => {
|
|
514
549
|
setLoading(true);
|
|
@@ -525,11 +560,14 @@ function VersionBanner({ rpcCall }) { const [info, setInfo] = React.useState(nu
|
|
|
525
560
|
// 只有 npm 上的版本严格大于当前版本才算有新版本
|
|
526
561
|
const hasUpdate = info?.latest && info?.current && !info.error && semverGt(info.latest, info.current);
|
|
527
562
|
|
|
528
|
-
// 链接按钮组:GitHub + 反馈 Bug
|
|
529
|
-
const links = React.createElement('div', { style: { display: 'flex', gap: 12, alignItems: 'center' } },
|
|
563
|
+
// 链接按钮组:GitHub + 更新日志 + 反馈 Bug
|
|
564
|
+
const links = React.createElement('div', { style: { display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' } },
|
|
530
565
|
React.createElement('a', {
|
|
531
566
|
href: GITHUB_URL, target: '_blank', rel: 'noreferrer', style: s.btnLink,
|
|
532
567
|
}, '⭐ GitHub'),
|
|
568
|
+
React.createElement('a', {
|
|
569
|
+
href: RELEASES_URL, target: '_blank', rel: 'noreferrer', style: s.btnLink,
|
|
570
|
+
}, '📋 更新日志'),
|
|
533
571
|
React.createElement('a', {
|
|
534
572
|
href: ISSUES_URL, target: '_blank', rel: 'noreferrer', style: s.btnLink,
|
|
535
573
|
}, '🐛 反馈 Bug'),
|
|
@@ -549,23 +587,34 @@ function VersionBanner({ rpcCall }) { const [info, setInfo] = React.useState(nu
|
|
|
549
587
|
},
|
|
550
588
|
React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 12 } },
|
|
551
589
|
React.createElement('span', { style: { fontSize: 20 } }, '🎉'),
|
|
552
|
-
React.createElement('div', { style: { flex: 1 } },
|
|
590
|
+
React.createElement('div', { style: { flex: 1, minWidth: 0 } },
|
|
553
591
|
React.createElement('div', {
|
|
554
592
|
style: {
|
|
555
593
|
fontSize: 13,
|
|
556
594
|
fontWeight: 600,
|
|
557
595
|
color: 'var(--dsw-alias-state-info-primary,#1e40af)',
|
|
558
|
-
marginBottom:
|
|
596
|
+
marginBottom: 6,
|
|
559
597
|
},
|
|
560
598
|
}, `发现新版本 v${info.latest}(当前 v${info.current})`),
|
|
561
|
-
React.createElement('
|
|
562
|
-
style: {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
599
|
+
React.createElement('div', {
|
|
600
|
+
style: { display: 'flex', alignItems: 'center', gap: 8 },
|
|
601
|
+
},
|
|
602
|
+
React.createElement('code', {
|
|
603
|
+
style: {
|
|
604
|
+
...s.code,
|
|
605
|
+
fontSize: 11,
|
|
606
|
+
color: 'var(--dsw-alias-label-secondary,#6b7280)',
|
|
607
|
+
flex: 1,
|
|
608
|
+
minWidth: 0,
|
|
609
|
+
wordBreak: 'break-all',
|
|
610
|
+
},
|
|
611
|
+
}, UPGRADE_COMMAND),
|
|
612
|
+
React.createElement('button', {
|
|
613
|
+
style: { ...s.btnGhost, height: 26, padding: '0 10px', fontSize: 12, flexShrink: 0 },
|
|
614
|
+
onClick: () => copy(UPGRADE_COMMAND),
|
|
615
|
+
title: '复制升级命令',
|
|
616
|
+
}, copied ? '✓ 已复制' : '复制'),
|
|
617
|
+
),
|
|
569
618
|
),
|
|
570
619
|
React.createElement('button', {
|
|
571
620
|
style: {
|
package/package.json
CHANGED