sapbuddy-dsh 0.0.9 → 0.1.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 +7 -7
- package/dist/client.js +70 -10
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
在 DSH 的插件管理页添加:
|
|
11
11
|
|
|
12
12
|
```text
|
|
13
|
-
sapbuddy-dsh@0.0.
|
|
13
|
+
sapbuddy-dsh@0.0.10
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
也可以通过 DSH 命令行安装:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
dsh plugin --profile desktop add sapbuddy-dsh@0.0.
|
|
19
|
+
dsh plugin --profile desktop add sapbuddy-dsh@0.0.10
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
更新已安装插件后,完整退出并重新启动 DSH,再新建会话选择 **SapBuddy**。
|
|
@@ -34,16 +34,16 @@ dsh plugin --profile desktop add sapbuddy-dsh@0.0.9
|
|
|
34
34
|
|
|
35
35
|
## 连接配置与排查
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
在 **设置 → SAP 连接** 中填写主机地址时,必须带协议,且协议与端口一致:
|
|
38
38
|
|
|
39
39
|
| 端口 | 协议 | 示例 |
|
|
40
40
|
|---|---|---|
|
|
41
|
-
| ICM HTTP(常见 8000) | `http://` | `http
|
|
42
|
-
| ICM HTTPS(常见 44300) | `https://` | `https
|
|
41
|
+
| ICM HTTP(常见 8000) | `http://` | `http://<host>:8000` |
|
|
42
|
+
| ICM HTTPS(常见 44300) | `https://` | `https://<host>:44300` |
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
协议写错(例如 HTTP 端口却用 `https://`)会导致 TLS/连接失败。客户端号即登录用的 `sap-client`,必须与目标客户端一致,否则会返回 401。登录语言不确定时建议填 `EN`。内网自签名证书可勾选「允许自签名证书」。
|
|
45
45
|
|
|
46
|
-
设置页的 **测试**
|
|
46
|
+
设置页的 **测试** 与真实 SAP 工具使用同一套协议、客户端号与语言。返回 401 时核对客户端号、账号与语言;403/404 多为 ADT 未开通或权限不足。
|
|
47
47
|
|
|
48
48
|
## 连接切换与会话自愈
|
|
49
49
|
|
package/dist/client.js
CHANGED
|
@@ -4,7 +4,6 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
factory: (require) => {
|
|
5
5
|
var module = { exports: {} };
|
|
6
6
|
var exports = module.exports;
|
|
7
|
-
"use strict";
|
|
8
7
|
var __defProp = Object.defineProperty;
|
|
9
8
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
10
9
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -79,6 +78,20 @@ var S = {
|
|
|
79
78
|
hint: { margin: 0, fontSize: 12, lineHeight: "18px", color: "var(--dsw-alias-label-tertiary)" }
|
|
80
79
|
};
|
|
81
80
|
var EMPTY = { language: "ZH", authMethod: "basic", ssl: { allowSelfSigned: true } };
|
|
81
|
+
var DEFAULT_PORT = { https: "44300", http: "8000" };
|
|
82
|
+
var ADDRESS_HINT = "https://\u4E3B\u673A:44300";
|
|
83
|
+
function parseAddress(url) {
|
|
84
|
+
const m = /^\s*(https?):\/\/([^/:?#\s]+)(?::(\d+))?/i.exec(String(url ?? ""));
|
|
85
|
+
if (!m) return { protocol: "https", host: "", port: DEFAULT_PORT.https };
|
|
86
|
+
const protocol = m[1].toLowerCase();
|
|
87
|
+
return { protocol, host: m[2], port: m[3] || DEFAULT_PORT[protocol] };
|
|
88
|
+
}
|
|
89
|
+
function buildAddress(d) {
|
|
90
|
+
const protocol = d.protocol === "http" ? "http" : "https";
|
|
91
|
+
const host = String(d.host ?? "").trim().replace(/^https?:\/\//i, "").replace(/[/:?#].*$/, "");
|
|
92
|
+
const port = String(d.port ?? "").trim() || DEFAULT_PORT[protocol];
|
|
93
|
+
return host ? protocol + "://" + host + ":" + port : "";
|
|
94
|
+
}
|
|
82
95
|
function Section() {
|
|
83
96
|
const [conns, setConns] = useState([]);
|
|
84
97
|
const [mode, setMode] = useState(null);
|
|
@@ -105,7 +118,16 @@ function Section() {
|
|
|
105
118
|
const save = async () => {
|
|
106
119
|
setBusy(true);
|
|
107
120
|
try {
|
|
108
|
-
const
|
|
121
|
+
const { protocol, host, port, ...rest } = draft;
|
|
122
|
+
const url = buildAddress(draft);
|
|
123
|
+
if (!url) {
|
|
124
|
+
setErr("\u8BF7\u586B\u5199\u4E3B\u673A");
|
|
125
|
+
setMsg(null);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const connection = { ...rest, url };
|
|
129
|
+
if (protocol === "http") delete connection.ssl;
|
|
130
|
+
const r = await post(API, { connection });
|
|
109
131
|
if (!r.ok) {
|
|
110
132
|
setErr("\u4FDD\u5B58\u5931\u8D25: " + (r.error ?? "\u672A\u77E5\u9519\u8BEF"));
|
|
111
133
|
setMsg(null);
|
|
@@ -147,12 +169,50 @@ function Section() {
|
|
|
147
169
|
};
|
|
148
170
|
const startNew = () => {
|
|
149
171
|
setMode("new");
|
|
150
|
-
setDraft({ ...EMPTY });
|
|
172
|
+
setDraft({ ...EMPTY, protocol: "https", host: "", port: DEFAULT_PORT.https });
|
|
151
173
|
};
|
|
152
174
|
const startEdit = (c) => {
|
|
153
175
|
setMode(c.id);
|
|
154
|
-
setDraft({ ...c, password: "" });
|
|
176
|
+
setDraft({ ...c, password: "", ...parseAddress(c.url), ssl: c.ssl ?? { allowSelfSigned: true } });
|
|
177
|
+
};
|
|
178
|
+
const isHttp = draft.protocol === "http";
|
|
179
|
+
const changeProtocol = (evt) => {
|
|
180
|
+
const next = evt.target.value === "http" ? "http" : "https";
|
|
181
|
+
setDraft((d) => {
|
|
182
|
+
const prev = d.protocol === "http" ? "http" : "https";
|
|
183
|
+
const port = !d.port || d.port === DEFAULT_PORT[prev] ? DEFAULT_PORT[next] : d.port;
|
|
184
|
+
return { ...d, protocol: next, port };
|
|
185
|
+
});
|
|
155
186
|
};
|
|
187
|
+
const addressField = React.createElement("div", { key: "addr", style: S.field }, [
|
|
188
|
+
React.createElement("span", { key: "l", style: S.label }, "\u5730\u5740"),
|
|
189
|
+
React.createElement("div", { key: "r", style: { display: "flex", gap: 6, alignItems: "center" } }, [
|
|
190
|
+
React.createElement("select", {
|
|
191
|
+
key: "p",
|
|
192
|
+
style: { ...S.input, flex: "none", width: 92, padding: "0 6px" },
|
|
193
|
+
value: isHttp ? "http" : "https",
|
|
194
|
+
onChange: changeProtocol
|
|
195
|
+
}, [
|
|
196
|
+
React.createElement("option", { key: "s", value: "https" }, "HTTPS"),
|
|
197
|
+
React.createElement("option", { key: "h", value: "http" }, "HTTP")
|
|
198
|
+
]),
|
|
199
|
+
React.createElement("input", {
|
|
200
|
+
key: "h",
|
|
201
|
+
style: { ...S.input, flex: 1, minWidth: 0 },
|
|
202
|
+
value: draft.host ?? "",
|
|
203
|
+
placeholder: "\u4E3B\u673A",
|
|
204
|
+
onChange: set("host")
|
|
205
|
+
}),
|
|
206
|
+
React.createElement("input", {
|
|
207
|
+
key: "o",
|
|
208
|
+
style: { ...S.input, flex: "none", width: 80 },
|
|
209
|
+
value: draft.port ?? "",
|
|
210
|
+
placeholder: isHttp ? DEFAULT_PORT.http : DEFAULT_PORT.https,
|
|
211
|
+
onChange: set("port")
|
|
212
|
+
})
|
|
213
|
+
]),
|
|
214
|
+
React.createElement("span", { key: "hint", style: S.hint }, ADDRESS_HINT)
|
|
215
|
+
]);
|
|
156
216
|
const input = (key, label, ph) => React.createElement("label", { className: void 0, style: S.field }, [
|
|
157
217
|
React.createElement("span", { key: "l", style: S.label }, label),
|
|
158
218
|
React.createElement("input", {
|
|
@@ -185,11 +245,11 @@ function Section() {
|
|
|
185
245
|
React.createElement("div", { key: "g1", style: S.grid }, [
|
|
186
246
|
input("id", "\u8FDE\u63A5 ID\uFF08\u552F\u4E00\uFF0C\u5982 dev/prod\uFF09", "dev"),
|
|
187
247
|
input("name", "\u540D\u79F0", "\u5F00\u53D1\u7CFB\u7EDF"),
|
|
188
|
-
|
|
248
|
+
addressField,
|
|
189
249
|
input("client", "\u5BA2\u6237\u7AEF\u53F7\uFF083 \u4F4D\uFF0C\u5FC5\u987B\u4E0E\u7CFB\u7EDF\u4E00\u81F4\uFF09", "100")
|
|
190
250
|
]),
|
|
191
251
|
React.createElement("div", { key: "g2", style: S.grid }, [
|
|
192
|
-
input("username", "\u7528\u6237\u540D", "
|
|
252
|
+
input("username", "\u7528\u6237\u540D", "BC01"),
|
|
193
253
|
input("password", "\u5BC6\u7801\uFF08\u7F16\u8F91\u65F6\u7559\u7A7A\u4FDD\u6301\u539F\u5BC6\u7801\uFF09", "\u2022\u2022\u2022\u2022\u2022\u2022"),
|
|
194
254
|
input("language", "\u767B\u5F55\u8BED\u8A00\uFF08\u4E0D\u786E\u5B9A\u586B EN\uFF09", "ZH"),
|
|
195
255
|
input("authMethod", "\u8BA4\u8BC1\u65B9\u5F0F", "basic")
|
|
@@ -197,19 +257,19 @@ function Section() {
|
|
|
197
257
|
React.createElement("div", { key: "g3", style: S.grid }, [
|
|
198
258
|
input("description", "\u63CF\u8FF0", "\u5F00\u53D1\u7CFB\u7EDF")
|
|
199
259
|
]),
|
|
200
|
-
React.createElement("label", { key: "ssl", style: { ...S.field, flexDirection: "row", alignItems: "center", gap: 8 } }, [
|
|
260
|
+
isHttp ? null : React.createElement("label", { key: "ssl", style: { ...S.field, flexDirection: "row", alignItems: "center", gap: 8 } }, [
|
|
201
261
|
React.createElement("input", {
|
|
202
262
|
key: "i",
|
|
203
263
|
type: "checkbox",
|
|
204
|
-
checked:
|
|
205
|
-
onChange: (evt) => setDraft((d) => ({ ...d, ssl: { ...
|
|
264
|
+
checked: draft.ssl?.allowSelfSigned !== false,
|
|
265
|
+
onChange: (evt) => setDraft((d) => ({ ...d, ssl: { ...d.ssl ?? {}, allowSelfSigned: evt.target.checked } }))
|
|
206
266
|
}),
|
|
207
267
|
React.createElement("span", { key: "l", style: S.label }, "\u5141\u8BB8\u81EA\u7B7E\u540D\u8BC1\u4E66\uFF08\u5185\u90E8\u7CFB\u7EDF https \u7528\uFF09")
|
|
208
268
|
]),
|
|
209
269
|
React.createElement(
|
|
210
270
|
"p",
|
|
211
271
|
{ key: "hint", style: S.hint },
|
|
212
|
-
"\
|
|
272
|
+
"\u5BA2\u6237\u7AEF\u53F7\u5C31\u662F\u767B\u5F55\u5BA2\u6237\u7AEF\uFF08sap-client\uFF09\uFF0C\u586B\u9519\u4F1A\u8FD4\u56DE 401\uFF1B\u767B\u5F55\u8BED\u8A00\u4E0D\u786E\u5B9A\u65F6\u586B EN\u3002"
|
|
213
273
|
),
|
|
214
274
|
React.createElement("div", { key: "acts", style: { display: "flex", gap: 8, justifyContent: "flex-end" } }, [
|
|
215
275
|
React.createElement("button", { key: "c", style: S.btn, onClick: () => {
|
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ export function buildProbeRequest(conf) {
|
|
|
50
50
|
const raw = String(conf?.url ?? "").trim().replace(/\/+$/, "");
|
|
51
51
|
if (!/^https?:\/\//i.test(raw))
|
|
52
52
|
return { error: `连接地址要以 http:// 或 https:// 开头(当前是 "${raw || "(空)"}")。` +
|
|
53
|
-
`例如 http
|
|
53
|
+
`例如 http://<host>:8000(ICM HTTP 端口)或 https://<host>:44300(HTTPS 端口)` };
|
|
54
54
|
let url;
|
|
55
55
|
try {
|
|
56
56
|
url = new URL(`${raw}/sap/bc/adt/compatibility/graph`);
|
package/package.json
CHANGED