@wenbin_wb/dsh-bridge 2.10.13 → 2.10.14
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/CHANGELOG.md +23 -0
- package/client/client.js +411 -18
- package/client/index.js +163 -3
- package/client/mobile-styles.js +303 -13
- package/lib/cloudflared-manager.mjs +19 -6
- package/lib/feishu/lark-bundled.mjs +230 -76
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawn,
|
|
1
|
+
import { spawn, execFileSync } from 'node:child_process';
|
|
2
2
|
import { createWriteStream, createReadStream, existsSync, mkdirSync, readFileSync, statSync, renameSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { chmod, stat, unlink, rename } from 'node:fs/promises';
|
|
4
4
|
import { homedir, platform, arch } from 'node:os';
|
|
@@ -8,6 +8,19 @@ import { createHash } from 'node:crypto';
|
|
|
8
8
|
import { get as httpsGet } from 'node:https';
|
|
9
9
|
import { get as httpGet } from 'node:http';
|
|
10
10
|
|
|
11
|
+
// 参数化执行外部命令,替代原先的 execSync(`"${path}" --version`) 字符串拼接
|
|
12
|
+
// (CodeQL js/shell-command-constructed-from-input)。execFileSync 不经过 shell,
|
|
13
|
+
// 参数以数组传递,路径里的引号 / $( ) / 反引号不再具备注入语义。
|
|
14
|
+
//
|
|
15
|
+
// Windows 例外:.cmd / .bat 无法被 execFileSync 直接执行(Node 要求经 shell),
|
|
16
|
+
// 官方 cloudflared 在 Windows 是 .exe 走参数化路径,只有测试注入的假二进制是
|
|
17
|
+
// .cmd,故按扩展名决定是否需要 shell。macOS / Linux 恒为 false。
|
|
18
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
19
|
+
function execBinSync(bin, args, options) {
|
|
20
|
+
const needsShell = IS_WINDOWS && /\.(cmd|bat)$/i.test(bin);
|
|
21
|
+
return execFileSync(bin, args, { ...options, shell: needsShell });
|
|
22
|
+
}
|
|
23
|
+
|
|
11
24
|
const CLOUDFLARED_VERSION = '2024.10.0';
|
|
12
25
|
const DOWNLOAD_TIMEOUT = 5 * 60 * 1000; // 5 分钟
|
|
13
26
|
const MIN_BINARY_SIZE = 5 * 1024 * 1024; // 最小 5MB,防止下到 HTML 错误页
|
|
@@ -158,7 +171,7 @@ function findSystemCloudflared() {
|
|
|
158
171
|
if (bin.includes('/') || bin.includes('\\')) {
|
|
159
172
|
if (!existsSync(bin)) continue;
|
|
160
173
|
}
|
|
161
|
-
|
|
174
|
+
execBinSync(bin, ['--version'], { stdio: 'ignore', timeout: 3000 });
|
|
162
175
|
return bin;
|
|
163
176
|
} catch {}
|
|
164
177
|
}
|
|
@@ -356,7 +369,7 @@ export class CloudflaredManager {
|
|
|
356
369
|
// 校验自管理二进制是否匹配期望版本;系统级二进制不校验(尊重用户安装)
|
|
357
370
|
_checkManagedBinaryVersion(binPath) {
|
|
358
371
|
try {
|
|
359
|
-
const out =
|
|
372
|
+
const out = execBinSync(binPath, ['--version'], { encoding: 'utf8', timeout: 3000 });
|
|
360
373
|
const ver = parseCloudflaredVersion(out);
|
|
361
374
|
if (!ver) return { ok: false, reason: `无法解析版本输出: ${(out || '').trim().slice(0, 80)}` };
|
|
362
375
|
if (ver !== this.binaryVersion) {
|
|
@@ -404,7 +417,7 @@ export class CloudflaredManager {
|
|
|
404
417
|
if (platform() !== 'win32') {
|
|
405
418
|
await chmod(binPath, 0o755).catch(() => {});
|
|
406
419
|
if (platform() === 'darwin') {
|
|
407
|
-
try {
|
|
420
|
+
try { execBinSync('xattr', ['-d', 'com.apple.quarantine', binPath], { stdio: 'ignore' }); } catch {}
|
|
408
421
|
}
|
|
409
422
|
}
|
|
410
423
|
// 版本钉死校验:cloudflared autoupdate 可能已把钉死的版本自替换成新版,
|
|
@@ -440,7 +453,7 @@ export class CloudflaredManager {
|
|
|
440
453
|
|
|
441
454
|
if (url.endsWith('.tgz') || url.endsWith('.tar.gz')) {
|
|
442
455
|
try {
|
|
443
|
-
|
|
456
|
+
execBinSync('tar', ['-xzf', tempPath, '-C', binDir]);
|
|
444
457
|
await unlink(tempPath).catch(() => {});
|
|
445
458
|
} catch (tarErr) {
|
|
446
459
|
this.logger?.error('解压 cloudflared 压缩包失败: %s', tarErr.message);
|
|
@@ -454,7 +467,7 @@ export class CloudflaredManager {
|
|
|
454
467
|
if (platform() !== 'win32') {
|
|
455
468
|
await chmod(binPath, 0o755).catch(() => {});
|
|
456
469
|
if (platform() === 'darwin') {
|
|
457
|
-
try {
|
|
470
|
+
try { execBinSync('xattr', ['-d', 'com.apple.quarantine', binPath], { stdio: 'ignore' }); } catch {}
|
|
458
471
|
}
|
|
459
472
|
}
|
|
460
473
|
|
|
@@ -14,7 +14,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
14
14
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
15
15
|
});
|
|
16
16
|
var __commonJS = (cb, mod) => function __require2() {
|
|
17
|
-
|
|
17
|
+
try {
|
|
18
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
throw mod = 0, e;
|
|
21
|
+
}
|
|
18
22
|
};
|
|
19
23
|
|
|
20
24
|
// node_modules/delayed-stream/lib/delayed_stream.js
|
|
@@ -9296,7 +9300,7 @@ var require_shams = __commonJS({
|
|
|
9296
9300
|
return true;
|
|
9297
9301
|
}
|
|
9298
9302
|
var obj = {};
|
|
9299
|
-
var sym = Symbol("test");
|
|
9303
|
+
var sym = /* @__PURE__ */ Symbol("test");
|
|
9300
9304
|
var symObj = Object(sym);
|
|
9301
9305
|
if (typeof sym === "string") {
|
|
9302
9306
|
return false;
|
|
@@ -9355,7 +9359,7 @@ var require_has_symbols = __commonJS({
|
|
|
9355
9359
|
if (typeof origSymbol("foo") !== "symbol") {
|
|
9356
9360
|
return false;
|
|
9357
9361
|
}
|
|
9358
|
-
if (typeof Symbol("bar") !== "symbol") {
|
|
9362
|
+
if (typeof /* @__PURE__ */ Symbol("bar") !== "symbol") {
|
|
9359
9363
|
return false;
|
|
9360
9364
|
}
|
|
9361
9365
|
return hasSymbolSham();
|
|
@@ -12499,7 +12503,7 @@ var require_axios = __commonJS({
|
|
|
12499
12503
|
});
|
|
12500
12504
|
return byteStringHeaders;
|
|
12501
12505
|
}
|
|
12502
|
-
var $internals = Symbol("internals");
|
|
12506
|
+
var $internals = /* @__PURE__ */ Symbol("internals");
|
|
12503
12507
|
function normalizeHeader(header) {
|
|
12504
12508
|
return header && String(header).trim().toLowerCase();
|
|
12505
12509
|
}
|
|
@@ -13709,7 +13713,7 @@ var require_axios = __commonJS({
|
|
|
13709
13713
|
}
|
|
13710
13714
|
});
|
|
13711
13715
|
}
|
|
13712
|
-
var kInternals = Symbol("internals");
|
|
13716
|
+
var kInternals = /* @__PURE__ */ Symbol("internals");
|
|
13713
13717
|
var AxiosTransformStream = class extends stream.Transform {
|
|
13714
13718
|
constructor(options) {
|
|
13715
13719
|
options = utils$1.toFlatObject(options, {
|
|
@@ -14440,9 +14444,9 @@ var require_axios = __commonJS({
|
|
|
14440
14444
|
https: httpsFollow
|
|
14441
14445
|
} = followRedirects;
|
|
14442
14446
|
var isHttps = /https:?/;
|
|
14443
|
-
var kAxiosSocketListener = Symbol("axios.http.socketListener");
|
|
14444
|
-
var kAxiosCurrentReq = Symbol("axios.http.currentReq");
|
|
14445
|
-
var kAxiosInstalledTunnel = Symbol("axios.http.installedTunnel");
|
|
14447
|
+
var kAxiosSocketListener = /* @__PURE__ */ Symbol("axios.http.socketListener");
|
|
14448
|
+
var kAxiosCurrentReq = /* @__PURE__ */ Symbol("axios.http.currentReq");
|
|
14449
|
+
var kAxiosInstalledTunnel = /* @__PURE__ */ Symbol("axios.http.installedTunnel");
|
|
14446
14450
|
var tunnelingAgentCache = /* @__PURE__ */ new Map();
|
|
14447
14451
|
var tunnelingAgentCacheUser = /* @__PURE__ */ new WeakMap();
|
|
14448
14452
|
var NODE_NATIVE_ENV_PROXY_SUPPORT = {
|
|
@@ -20103,10 +20107,10 @@ var require_constants = __commonJS({
|
|
|
20103
20107
|
EMPTY_BUFFER: Buffer.alloc(0),
|
|
20104
20108
|
GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
|
|
20105
20109
|
hasBlob,
|
|
20106
|
-
kForOnEventAttribute: Symbol("kIsForOnEventAttribute"),
|
|
20107
|
-
kListener: Symbol("kListener"),
|
|
20108
|
-
kStatusCode: Symbol("status-code"),
|
|
20109
|
-
kWebSocket: Symbol("websocket"),
|
|
20110
|
+
kForOnEventAttribute: /* @__PURE__ */ Symbol("kIsForOnEventAttribute"),
|
|
20111
|
+
kListener: /* @__PURE__ */ Symbol("kListener"),
|
|
20112
|
+
kStatusCode: /* @__PURE__ */ Symbol("status-code"),
|
|
20113
|
+
kWebSocket: /* @__PURE__ */ Symbol("websocket"),
|
|
20110
20114
|
NOOP: () => {
|
|
20111
20115
|
}
|
|
20112
20116
|
};
|
|
@@ -20192,8 +20196,8 @@ var require_buffer_util = __commonJS({
|
|
|
20192
20196
|
var require_limiter = __commonJS({
|
|
20193
20197
|
"node_modules/ws/lib/limiter.js"(exports, module) {
|
|
20194
20198
|
"use strict";
|
|
20195
|
-
var kDone = Symbol("kDone");
|
|
20196
|
-
var kRun = Symbol("kRun");
|
|
20199
|
+
var kDone = /* @__PURE__ */ Symbol("kDone");
|
|
20200
|
+
var kRun = /* @__PURE__ */ Symbol("kRun");
|
|
20197
20201
|
var Limiter = class {
|
|
20198
20202
|
/**
|
|
20199
20203
|
* Creates a new `Limiter`.
|
|
@@ -20248,11 +20252,11 @@ var require_permessage_deflate = __commonJS({
|
|
|
20248
20252
|
var { kStatusCode } = require_constants();
|
|
20249
20253
|
var FastBuffer = Buffer[Symbol.species];
|
|
20250
20254
|
var TRAILER = Buffer.from([0, 0, 255, 255]);
|
|
20251
|
-
var kPerMessageDeflate = Symbol("permessage-deflate");
|
|
20252
|
-
var kTotalLength = Symbol("total-length");
|
|
20253
|
-
var kCallback = Symbol("callback");
|
|
20254
|
-
var kBuffers = Symbol("buffers");
|
|
20255
|
-
var kError = Symbol("error");
|
|
20255
|
+
var kPerMessageDeflate = /* @__PURE__ */ Symbol("permessage-deflate");
|
|
20256
|
+
var kTotalLength = /* @__PURE__ */ Symbol("total-length");
|
|
20257
|
+
var kCallback = /* @__PURE__ */ Symbol("callback");
|
|
20258
|
+
var kBuffers = /* @__PURE__ */ Symbol("buffers");
|
|
20259
|
+
var kError = /* @__PURE__ */ Symbol("error");
|
|
20256
20260
|
var zlibLimiter;
|
|
20257
20261
|
var PerMessageDeflate = class {
|
|
20258
20262
|
/**
|
|
@@ -21458,7 +21462,7 @@ var require_sender = __commonJS({
|
|
|
21458
21462
|
var { EMPTY_BUFFER, kWebSocket, NOOP } = require_constants();
|
|
21459
21463
|
var { isBlob, isValidStatusCode } = require_validation();
|
|
21460
21464
|
var { mask: applyMask, toBuffer } = require_buffer_util();
|
|
21461
|
-
var kByteLength = Symbol("kByteLength");
|
|
21465
|
+
var kByteLength = /* @__PURE__ */ Symbol("kByteLength");
|
|
21462
21466
|
var maskBuffer = Buffer.alloc(4);
|
|
21463
21467
|
var RANDOM_POOL_SIZE = 8 * 1024;
|
|
21464
21468
|
var randomPool;
|
|
@@ -21943,14 +21947,14 @@ var require_event_target = __commonJS({
|
|
|
21943
21947
|
"node_modules/ws/lib/event-target.js"(exports, module) {
|
|
21944
21948
|
"use strict";
|
|
21945
21949
|
var { kForOnEventAttribute, kListener } = require_constants();
|
|
21946
|
-
var kCode = Symbol("kCode");
|
|
21947
|
-
var kData = Symbol("kData");
|
|
21948
|
-
var kError = Symbol("kError");
|
|
21949
|
-
var kMessage = Symbol("kMessage");
|
|
21950
|
-
var kReason = Symbol("kReason");
|
|
21951
|
-
var kTarget = Symbol("kTarget");
|
|
21952
|
-
var kType = Symbol("kType");
|
|
21953
|
-
var kWasClean = Symbol("kWasClean");
|
|
21950
|
+
var kCode = /* @__PURE__ */ Symbol("kCode");
|
|
21951
|
+
var kData = /* @__PURE__ */ Symbol("kData");
|
|
21952
|
+
var kError = /* @__PURE__ */ Symbol("kError");
|
|
21953
|
+
var kMessage = /* @__PURE__ */ Symbol("kMessage");
|
|
21954
|
+
var kReason = /* @__PURE__ */ Symbol("kReason");
|
|
21955
|
+
var kTarget = /* @__PURE__ */ Symbol("kTarget");
|
|
21956
|
+
var kType = /* @__PURE__ */ Symbol("kType");
|
|
21957
|
+
var kWasClean = /* @__PURE__ */ Symbol("kWasClean");
|
|
21954
21958
|
var Event = class {
|
|
21955
21959
|
/**
|
|
21956
21960
|
* Create a new `Event`.
|
|
@@ -22352,7 +22356,7 @@ var require_websocket = __commonJS({
|
|
|
22352
22356
|
} = require_event_target();
|
|
22353
22357
|
var { format, parse } = require_extension();
|
|
22354
22358
|
var { toBuffer } = require_buffer_util();
|
|
22355
|
-
var kAborted = Symbol("kAborted");
|
|
22359
|
+
var kAborted = /* @__PURE__ */ Symbol("kAborted");
|
|
22356
22360
|
var protocolVersions = [8, 13];
|
|
22357
22361
|
var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
|
|
22358
22362
|
var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
|
@@ -26384,14 +26388,14 @@ var require_index = __commonJS({
|
|
|
26384
26388
|
LoggerLevel[LoggerLevel["debug"] = 4] = "debug";
|
|
26385
26389
|
LoggerLevel[LoggerLevel["trace"] = 5] = "trace";
|
|
26386
26390
|
})(exports.LoggerLevel || (exports.LoggerLevel = {}));
|
|
26387
|
-
var CEventType = Symbol("event-type");
|
|
26388
|
-
var CTenantKey = Symbol("tenant-key");
|
|
26389
|
-
var CAppTicket = Symbol("app-ticket");
|
|
26390
|
-
var CTenantAccessToken = Symbol("tenant-access-token");
|
|
26391
|
-
var CWithHelpdeskAuthorization = Symbol("with-helpdesk-authorization");
|
|
26392
|
-
var CWithUserAccessToken = Symbol("with-user-access-token");
|
|
26393
|
-
var CUserAccessToken = Symbol("user-access-token");
|
|
26394
|
-
var CAilySessionRecord = Symbol("aily-session-record");
|
|
26391
|
+
var CEventType = /* @__PURE__ */ Symbol("event-type");
|
|
26392
|
+
var CTenantKey = /* @__PURE__ */ Symbol("tenant-key");
|
|
26393
|
+
var CAppTicket = /* @__PURE__ */ Symbol("app-ticket");
|
|
26394
|
+
var CTenantAccessToken = /* @__PURE__ */ Symbol("tenant-access-token");
|
|
26395
|
+
var CWithHelpdeskAuthorization = /* @__PURE__ */ Symbol("with-helpdesk-authorization");
|
|
26396
|
+
var CWithUserAccessToken = /* @__PURE__ */ Symbol("with-user-access-token");
|
|
26397
|
+
var CUserAccessToken = /* @__PURE__ */ Symbol("user-access-token");
|
|
26398
|
+
var CAilySessionRecord = /* @__PURE__ */ Symbol("aily-session-record");
|
|
26395
26399
|
var string2Base64 = (content) => Buffer.from(content).toString("base64");
|
|
26396
26400
|
var DefaultCache = class {
|
|
26397
26401
|
constructor() {
|
|
@@ -26453,12 +26457,19 @@ var require_index = __commonJS({
|
|
|
26453
26457
|
return domain;
|
|
26454
26458
|
}
|
|
26455
26459
|
};
|
|
26456
|
-
var fillApiPath = (apiPath, pathSupplement = {}) =>
|
|
26457
|
-
|
|
26458
|
-
|
|
26459
|
-
|
|
26460
|
-
|
|
26461
|
-
|
|
26460
|
+
var fillApiPath = (apiPath, pathSupplement = {}) => (
|
|
26461
|
+
// Only treat `:name` as a path parameter when it starts a path segment
|
|
26462
|
+
// (string start or right after `/`). Colons inside the URL authority,
|
|
26463
|
+
// e.g. `http://localhost:3000` or `user:pw@host`, must be left untouched.
|
|
26464
|
+
// The separator is captured and re-emitted instead of using a lookbehind
|
|
26465
|
+
// because the compile target (es6) has no lookbehind support.
|
|
26466
|
+
apiPath.replace(/(^|\/):([^/]+)/g, (_, pathPrefix, pathKey) => {
|
|
26467
|
+
if (pathSupplement[pathKey] !== void 0) {
|
|
26468
|
+
return `${pathPrefix}${pathSupplement[pathKey]}`;
|
|
26469
|
+
}
|
|
26470
|
+
throw new Error(`request miss ${pathKey} path argument`);
|
|
26471
|
+
})
|
|
26472
|
+
);
|
|
26462
26473
|
var assert = (predication, callback) => __awaiter(void 0, void 0, void 0, function* () {
|
|
26463
26474
|
const isInvoke = typeof predication === "function" ? predication() : predication;
|
|
26464
26475
|
if (isInvoke) {
|
|
@@ -119921,6 +119932,8 @@ var require_index = __commonJS({
|
|
|
119921
119932
|
}
|
|
119922
119933
|
};
|
|
119923
119934
|
var CAppTicketHandle = "app_ticket";
|
|
119935
|
+
var duplicateHandleWarning = (key) => `${key} handle is already registered and has been replaced, call unregister('${key}') first to replace it explicitly`;
|
|
119936
|
+
var appTicketUnregisteredWarning = `the built-in ${CAppTicketHandle} handle is unregistered, pushed app tickets are no longer cached and every app_access_token request of an ISV app will miss the cache and trigger an app_ticket resend`;
|
|
119924
119937
|
var EventDispatcher = class {
|
|
119925
119938
|
constructor(params) {
|
|
119926
119939
|
this.verificationToken = "";
|
|
@@ -119954,16 +119967,46 @@ var require_index = __commonJS({
|
|
|
119954
119967
|
})
|
|
119955
119968
|
});
|
|
119956
119969
|
}
|
|
119970
|
+
/**
|
|
119971
|
+
* Register a handler for each of the given event keys.
|
|
119972
|
+
*
|
|
119973
|
+
* Registering a key that already has a handler replaces it. That is a
|
|
119974
|
+
* supported operation, but the replacement is easier to spot when it is
|
|
119975
|
+
* announced: call `unregister(key)` first and nothing is logged, otherwise
|
|
119976
|
+
* a warning flags what would otherwise be an unnoticed overwrite.
|
|
119977
|
+
*/
|
|
119957
119978
|
register(handles) {
|
|
119958
119979
|
Object.keys(handles).forEach((key) => {
|
|
119959
119980
|
if (this.handles.has(key) && key !== CAppTicketHandle) {
|
|
119960
|
-
this.logger.
|
|
119981
|
+
this.logger.warn(duplicateHandleWarning(key));
|
|
119961
119982
|
}
|
|
119962
119983
|
this.handles.set(key, handles[key]);
|
|
119963
119984
|
this.logger.debug(`register ${key} handle`);
|
|
119964
119985
|
});
|
|
119965
119986
|
return this;
|
|
119966
119987
|
}
|
|
119988
|
+
/**
|
|
119989
|
+
* Remove the handler registered for each of the given event keys, so that
|
|
119990
|
+
* the events are no longer dispatched. Keys without a handler are skipped.
|
|
119991
|
+
*
|
|
119992
|
+
* Removing the built-in `app_ticket` handle stops the SDK from caching
|
|
119993
|
+
* pushed app tickets, which makes every app_access_token request of an ISV
|
|
119994
|
+
* app miss the cache and trigger an app_ticket resend -- hence the warning.
|
|
119995
|
+
*/
|
|
119996
|
+
unregister(...keys) {
|
|
119997
|
+
keys.forEach((key) => {
|
|
119998
|
+
if (!this.handles.has(key)) {
|
|
119999
|
+
this.logger.debug(`no ${key} handle to unregister`);
|
|
120000
|
+
return;
|
|
120001
|
+
}
|
|
120002
|
+
this.handles.delete(key);
|
|
120003
|
+
this.logger.debug(`unregister ${key} handle`);
|
|
120004
|
+
if (key === CAppTicketHandle) {
|
|
120005
|
+
this.logger.warn(appTicketUnregisteredWarning);
|
|
120006
|
+
}
|
|
120007
|
+
});
|
|
120008
|
+
return this;
|
|
120009
|
+
}
|
|
119967
120010
|
invoke(data, params) {
|
|
119968
120011
|
var _a, _b;
|
|
119969
120012
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -120686,6 +120729,9 @@ var require_index = __commonJS({
|
|
|
120686
120729
|
}
|
|
120687
120730
|
mergeData(params) {
|
|
120688
120731
|
const { message_id, sum, seq, trace_id, data } = params;
|
|
120732
|
+
if (!Number.isInteger(sum) || sum <= 0 || !Number.isInteger(seq) || seq < 0 || seq >= sum) {
|
|
120733
|
+
throw new Error(`invalid event fragment metadata (sum: ${sum}, seq: ${seq})`);
|
|
120734
|
+
}
|
|
120689
120735
|
const cache = this.cache.get(message_id);
|
|
120690
120736
|
if (!cache) {
|
|
120691
120737
|
const buffer = new Array(sum).fill(void 0);
|
|
@@ -120697,6 +120743,9 @@ var require_index = __commonJS({
|
|
|
120697
120743
|
create_time: Date.now()
|
|
120698
120744
|
});
|
|
120699
120745
|
} else {
|
|
120746
|
+
if (sum !== cache.buffer.length) {
|
|
120747
|
+
throw new Error(`invalid event fragment metadata (sum: ${sum} differs from first fragment's ${cache.buffer.length}, seq: ${seq})`);
|
|
120748
|
+
}
|
|
120700
120749
|
cache.buffer[seq] = data;
|
|
120701
120750
|
}
|
|
120702
120751
|
const mergedCache = this.cache.get(message_id);
|
|
@@ -120787,12 +120836,17 @@ var require_index = __commonJS({
|
|
|
120787
120836
|
HttpStatusCode2[HttpStatusCode2["ok"] = 200] = "ok";
|
|
120788
120837
|
HttpStatusCode2[HttpStatusCode2["internal_server_error"] = 500] = "internal_server_error";
|
|
120789
120838
|
})(HttpStatusCode || (HttpStatusCode = {}));
|
|
120839
|
+
var describeError = (err) => {
|
|
120840
|
+
const message = err === null || err === void 0 ? void 0 : err.message;
|
|
120841
|
+
return message ? message : String(err);
|
|
120842
|
+
};
|
|
120790
120843
|
var WSClient = class {
|
|
120791
120844
|
constructor(params) {
|
|
120792
120845
|
var _a;
|
|
120793
120846
|
this.wsConfig = new WSConfig();
|
|
120794
120847
|
this.reconnectGeneration = 0;
|
|
120795
120848
|
this.isConnecting = false;
|
|
120849
|
+
this.closed = false;
|
|
120796
120850
|
this.reconnectInfo = {
|
|
120797
120851
|
lastConnectTime: 0,
|
|
120798
120852
|
nextConnectTime: 0
|
|
@@ -120861,6 +120915,53 @@ var require_index = __commonJS({
|
|
|
120861
120915
|
this.livenessTimer = void 0;
|
|
120862
120916
|
}
|
|
120863
120917
|
}
|
|
120918
|
+
/**
|
|
120919
|
+
* Detach a socket we are about to throw away: drop every listener, but
|
|
120920
|
+
* leave one 'error' sink behind.
|
|
120921
|
+
*
|
|
120922
|
+
* `ws` reports the abort of a non-OPEN socket asynchronously — both
|
|
120923
|
+
* `terminate()` and `close()` route through `abortHandshake()`, which
|
|
120924
|
+
* emits 'error' on a later tick — and a non-force `close()` on an OPEN
|
|
120925
|
+
* socket keeps the connection alive until the peer answers (up to `ws`'s
|
|
120926
|
+
* 30s closeTimeout), during which a TCP reset still surfaces as 'error'.
|
|
120927
|
+
* An EventEmitter with no 'error' listener throws instead of emitting, and
|
|
120928
|
+
* that throw lands outside every try/catch, killing the host process.
|
|
120929
|
+
* See https://github.com/larksuite/node-sdk/issues/197
|
|
120930
|
+
*
|
|
120931
|
+
* NOTE: not for the liveness watchdog — that one terminates *on purpose*
|
|
120932
|
+
* and needs its listeners intact so 'close' drives the reconnect.
|
|
120933
|
+
*/
|
|
120934
|
+
detachSocket(socket) {
|
|
120935
|
+
socket.removeAllListeners();
|
|
120936
|
+
socket.on("error", (err) => {
|
|
120937
|
+
this.logger.debug("[ws]", "ignored error from discarded socket", err === null || err === void 0 ? void 0 : err.message);
|
|
120938
|
+
});
|
|
120939
|
+
}
|
|
120940
|
+
/**
|
|
120941
|
+
* Throw away whatever the current attempt established — socket *and* the
|
|
120942
|
+
* timers its 'open' handler armed. A handshake that completes after
|
|
120943
|
+
* `close()` runs `pingLoop()`, and that timer is not unref'd: leaving it
|
|
120944
|
+
* behind keeps the event loop alive forever on a client the caller closed.
|
|
120945
|
+
*
|
|
120946
|
+
* Only safe when {@link closed} is set: otherwise a newer session may
|
|
120947
|
+
* already own `wsConfig`'s instance.
|
|
120948
|
+
*/
|
|
120949
|
+
discardConnection() {
|
|
120950
|
+
if (this.pingInterval) {
|
|
120951
|
+
clearTimeout(this.pingInterval);
|
|
120952
|
+
this.pingInterval = void 0;
|
|
120953
|
+
}
|
|
120954
|
+
this.clearLiveness();
|
|
120955
|
+
const socket = this.wsConfig.getWSInstance();
|
|
120956
|
+
if (!socket)
|
|
120957
|
+
return;
|
|
120958
|
+
this.detachSocket(socket);
|
|
120959
|
+
try {
|
|
120960
|
+
socket.terminate();
|
|
120961
|
+
} catch (_a) {
|
|
120962
|
+
}
|
|
120963
|
+
this.wsConfig.setWSInstance(null);
|
|
120964
|
+
}
|
|
120864
120965
|
/**
|
|
120865
120966
|
* Invoke a user-supplied callback safely: no-op if undefined, swallow any
|
|
120866
120967
|
* exception to avoid breaking the WS state machine.
|
|
@@ -120967,7 +121068,7 @@ var require_index = __commonJS({
|
|
|
120967
121068
|
if (this.handshakeTimeoutMs && this.handshakeTimeoutMs > 0) {
|
|
120968
121069
|
timer = setTimeout(() => {
|
|
120969
121070
|
this.logger.error("[ws]", `handshake timeout after ${this.handshakeTimeoutMs}ms`);
|
|
120970
|
-
|
|
121071
|
+
this.detachSocket(wsInstance);
|
|
120971
121072
|
try {
|
|
120972
121073
|
wsInstance.terminate();
|
|
120973
121074
|
} catch (_a) {
|
|
@@ -121023,6 +121124,13 @@ var require_index = __commonJS({
|
|
|
121023
121124
|
} finally {
|
|
121024
121125
|
this.isConnecting = false;
|
|
121025
121126
|
}
|
|
121127
|
+
if (this.closed) {
|
|
121128
|
+
this.discardConnection();
|
|
121129
|
+
return;
|
|
121130
|
+
}
|
|
121131
|
+
if (currentGeneration !== this.reconnectGeneration) {
|
|
121132
|
+
return;
|
|
121133
|
+
}
|
|
121026
121134
|
if (result.ok) {
|
|
121027
121135
|
this.hasEverConnected = true;
|
|
121028
121136
|
this.safeInvoke("onReady", this.onReady);
|
|
@@ -121064,6 +121172,10 @@ var require_index = __commonJS({
|
|
|
121064
121172
|
count++;
|
|
121065
121173
|
this.currentReconnectAttempts = count;
|
|
121066
121174
|
const result = yield tryConnect();
|
|
121175
|
+
if (this.closed) {
|
|
121176
|
+
this.discardConnection();
|
|
121177
|
+
return;
|
|
121178
|
+
}
|
|
121067
121179
|
if (currentGeneration !== this.reconnectGeneration) {
|
|
121068
121180
|
return;
|
|
121069
121181
|
}
|
|
@@ -121127,13 +121239,17 @@ var require_index = __commonJS({
|
|
|
121127
121239
|
const wsInstance = this.wsConfig.getWSInstance();
|
|
121128
121240
|
wsInstance === null || wsInstance === void 0 ? void 0 : wsInstance.on("message", (buffer) => __awaiter(this, void 0, void 0, function* () {
|
|
121129
121241
|
this.clearLiveness();
|
|
121130
|
-
|
|
121131
|
-
|
|
121132
|
-
|
|
121133
|
-
|
|
121134
|
-
|
|
121135
|
-
|
|
121136
|
-
|
|
121242
|
+
try {
|
|
121243
|
+
const data = decode(buffer);
|
|
121244
|
+
const { method } = data;
|
|
121245
|
+
if (method === FrameType.control) {
|
|
121246
|
+
yield this.handleControlData(data);
|
|
121247
|
+
}
|
|
121248
|
+
if (method === FrameType.data) {
|
|
121249
|
+
yield this.handleEventData(data);
|
|
121250
|
+
}
|
|
121251
|
+
} catch (err) {
|
|
121252
|
+
this.logger.error("[ws]", `failed to handle inbound frame: ${describeError(err)}`);
|
|
121137
121253
|
}
|
|
121138
121254
|
}));
|
|
121139
121255
|
wsInstance === null || wsInstance === void 0 ? void 0 : wsInstance.on("error", (e) => {
|
|
@@ -121155,8 +121271,15 @@ var require_index = __commonJS({
|
|
|
121155
121271
|
}
|
|
121156
121272
|
if (type === MessageType.pong && payload) {
|
|
121157
121273
|
this.logger.trace("[ws]", "receive pong");
|
|
121158
|
-
|
|
121159
|
-
|
|
121274
|
+
let pong;
|
|
121275
|
+
try {
|
|
121276
|
+
const dataString = new TextDecoder("utf-8").decode(payload);
|
|
121277
|
+
pong = JSON.parse(dataString);
|
|
121278
|
+
} catch (err) {
|
|
121279
|
+
this.logger.error("[ws]", `invalid pong payload: ${describeError(err)}`);
|
|
121280
|
+
return;
|
|
121281
|
+
}
|
|
121282
|
+
const { PingInterval, ReconnectCount, ReconnectInterval, ReconnectNonce } = pong;
|
|
121160
121283
|
this.wsConfig.updateWs({
|
|
121161
121284
|
pingInterval: PingInterval * 1e3,
|
|
121162
121285
|
reconnectCount: ReconnectCount,
|
|
@@ -121179,13 +121302,19 @@ var require_index = __commonJS({
|
|
|
121179
121302
|
if (type !== MessageType.event) {
|
|
121180
121303
|
return;
|
|
121181
121304
|
}
|
|
121182
|
-
|
|
121183
|
-
|
|
121184
|
-
|
|
121185
|
-
|
|
121186
|
-
|
|
121187
|
-
|
|
121188
|
-
|
|
121305
|
+
let mergedData;
|
|
121306
|
+
try {
|
|
121307
|
+
mergedData = this.dataCache.mergeData({
|
|
121308
|
+
message_id,
|
|
121309
|
+
sum: Number(sum),
|
|
121310
|
+
seq: Number(seq),
|
|
121311
|
+
trace_id,
|
|
121312
|
+
data: payload
|
|
121313
|
+
});
|
|
121314
|
+
} catch (err) {
|
|
121315
|
+
this.logger.error("[ws]", `failed to merge event fragments, message_id: ${message_id}; trace_id: ${trace_id}; error: ${describeError(err)}`);
|
|
121316
|
+
return;
|
|
121317
|
+
}
|
|
121189
121318
|
if (!mergedData) {
|
|
121190
121319
|
return;
|
|
121191
121320
|
}
|
|
@@ -121254,6 +121383,7 @@ var require_index = __commonJS({
|
|
|
121254
121383
|
*/
|
|
121255
121384
|
close(params = {}) {
|
|
121256
121385
|
const { force = false } = params;
|
|
121386
|
+
this.closed = true;
|
|
121257
121387
|
this.reconnectGeneration++;
|
|
121258
121388
|
if (this.pingInterval) {
|
|
121259
121389
|
clearTimeout(this.pingInterval);
|
|
@@ -121269,7 +121399,7 @@ var require_index = __commonJS({
|
|
|
121269
121399
|
this.currentReconnectAttempts = 0;
|
|
121270
121400
|
const wsInstance = this.wsConfig.getWSInstance();
|
|
121271
121401
|
if (wsInstance) {
|
|
121272
|
-
|
|
121402
|
+
this.detachSocket(wsInstance);
|
|
121273
121403
|
if (force) {
|
|
121274
121404
|
wsInstance.terminate();
|
|
121275
121405
|
} else {
|
|
@@ -121292,6 +121422,7 @@ var require_index = __commonJS({
|
|
|
121292
121422
|
return;
|
|
121293
121423
|
}
|
|
121294
121424
|
this.terminalError = false;
|
|
121425
|
+
this.closed = false;
|
|
121295
121426
|
this.currentReconnectAttempts = 0;
|
|
121296
121427
|
this.dataCache.clearAtInterval();
|
|
121297
121428
|
this.logger.info("[ws]", `receive events or callbacks through persistent connection only available in self-build & Feishu app, Configured in:
|
|
@@ -121711,6 +121842,7 @@ var require_index = __commonJS({
|
|
|
121711
121842
|
let domainSwitched = false;
|
|
121712
121843
|
let pollTimer = null;
|
|
121713
121844
|
let expireTimer = null;
|
|
121845
|
+
let settled = false;
|
|
121714
121846
|
const cleanup = () => {
|
|
121715
121847
|
var _a2;
|
|
121716
121848
|
if (pollTimer !== null) {
|
|
@@ -121723,25 +121855,51 @@ var require_index = __commonJS({
|
|
|
121723
121855
|
}
|
|
121724
121856
|
(_a2 = ctx.signal) === null || _a2 === void 0 ? void 0 : _a2.removeEventListener("abort", onAbort);
|
|
121725
121857
|
};
|
|
121726
|
-
const
|
|
121858
|
+
const succeed = (result) => {
|
|
121859
|
+
if (settled) {
|
|
121860
|
+
return;
|
|
121861
|
+
}
|
|
121862
|
+
settled = true;
|
|
121863
|
+
cleanup();
|
|
121864
|
+
resolve(result);
|
|
121865
|
+
};
|
|
121866
|
+
const fail = (err) => {
|
|
121867
|
+
if (settled) {
|
|
121868
|
+
return;
|
|
121869
|
+
}
|
|
121870
|
+
settled = true;
|
|
121727
121871
|
cleanup();
|
|
121728
|
-
reject(
|
|
121872
|
+
reject(err);
|
|
121873
|
+
};
|
|
121874
|
+
const scheduleNextPoll = () => {
|
|
121875
|
+
if (settled) {
|
|
121876
|
+
return;
|
|
121877
|
+
}
|
|
121878
|
+
pollTimer = setTimeout(poll, interval);
|
|
121879
|
+
};
|
|
121880
|
+
const onAbort = () => {
|
|
121881
|
+
fail(createError("abort", "Registration was aborted"));
|
|
121729
121882
|
};
|
|
121730
121883
|
if ((_a = ctx.signal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
121731
|
-
return
|
|
121884
|
+
return fail(createError("abort", "Registration was aborted"));
|
|
121732
121885
|
}
|
|
121733
121886
|
(_b = ctx.signal) === null || _b === void 0 ? void 0 : _b.addEventListener("abort", onAbort, { once: true });
|
|
121734
121887
|
expireTimer = setTimeout(() => {
|
|
121735
|
-
|
|
121736
|
-
reject(createError("expired_token", "Polling timed out"));
|
|
121888
|
+
fail(createError("expired_token", "Polling timed out"));
|
|
121737
121889
|
}, ctx.expireIn);
|
|
121738
121890
|
const poll = () => __awaiter(this, void 0, void 0, function* () {
|
|
121739
121891
|
var _c, _d, _e, _f, _g, _h;
|
|
121892
|
+
if (settled) {
|
|
121893
|
+
return;
|
|
121894
|
+
}
|
|
121740
121895
|
try {
|
|
121741
121896
|
const pollRes = yield requestRegistration(baseUrl, {
|
|
121742
121897
|
action: "poll",
|
|
121743
121898
|
device_code: ctx.deviceCode
|
|
121744
121899
|
});
|
|
121900
|
+
if (settled) {
|
|
121901
|
+
return;
|
|
121902
|
+
}
|
|
121745
121903
|
if (((_c = pollRes.user_info) === null || _c === void 0 ? void 0 : _c.tenant_brand) === "lark" && !domainSwitched) {
|
|
121746
121904
|
baseUrl = ctx.larkBaseUrl;
|
|
121747
121905
|
domainSwitched = true;
|
|
@@ -121750,8 +121908,7 @@ var require_index = __commonJS({
|
|
|
121750
121908
|
return;
|
|
121751
121909
|
}
|
|
121752
121910
|
if (pollRes.client_id && pollRes.client_secret) {
|
|
121753
|
-
|
|
121754
|
-
resolve({
|
|
121911
|
+
succeed({
|
|
121755
121912
|
client_id: pollRes.client_id,
|
|
121756
121913
|
client_secret: pollRes.client_secret,
|
|
121757
121914
|
user_info: pollRes.user_info
|
|
@@ -121768,21 +121925,18 @@ var require_index = __commonJS({
|
|
|
121768
121925
|
break;
|
|
121769
121926
|
case "access_denied":
|
|
121770
121927
|
case "expired_token":
|
|
121771
|
-
|
|
121772
|
-
reject(createError(pollRes.error, (_g = pollRes.error_description) !== null && _g !== void 0 ? _g : "Unknown error"));
|
|
121928
|
+
fail(createError(pollRes.error, (_g = pollRes.error_description) !== null && _g !== void 0 ? _g : "Unknown error"));
|
|
121773
121929
|
return;
|
|
121774
121930
|
default:
|
|
121775
121931
|
if (pollRes.error) {
|
|
121776
|
-
|
|
121777
|
-
reject(createError(pollRes.error, (_h = pollRes.error_description) !== null && _h !== void 0 ? _h : "Unknown error"));
|
|
121932
|
+
fail(createError(pollRes.error, (_h = pollRes.error_description) !== null && _h !== void 0 ? _h : "Unknown error"));
|
|
121778
121933
|
return;
|
|
121779
121934
|
}
|
|
121780
121935
|
break;
|
|
121781
121936
|
}
|
|
121782
|
-
|
|
121937
|
+
scheduleNextPoll();
|
|
121783
121938
|
} catch (e) {
|
|
121784
|
-
|
|
121785
|
-
reject(e);
|
|
121939
|
+
fail(e);
|
|
121786
121940
|
}
|
|
121787
121941
|
});
|
|
121788
121942
|
poll();
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wenbin_wb/dsh-bridge",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.14",
|
|
4
4
|
"description": "手机扫码即可在移动端/公网继续用 DeepSeek Harness,人不在电脑前也能接着干。一键局域网二维码、Cloudflare 公网隧道、自建隧道与微信 / QQ / 飞书 / Telegram Bot(多工作区/会话持久化/媒体/卡片审批/流式输出),无需自己搭公网服务器。",
|
|
5
|
-
"releaseNotes": "【v2.10.
|
|
5
|
+
"releaseNotes": "【v2.10.14】移动端设置页体验修复\n• 修复:手机设置页内容被裁掉、部分页签点不到(含第三方设置页),竖屏改为「分类列表 → 内容页」两级导航,字号与触控行恢复到可读可点,横屏分类不再被切\n• 修复:设置页「✕」回到标题行右上角,页面操作按钮统一收到底部动作栏\n• 修复:插件市场点「安装」没反应(确认框被设置弹窗盖住),横屏下确认框还会超出屏幕、按钮点不到;现均可正常显示与点击\n• 说明:纯前端样式与交互调整,刷新页面即生效(无需重启 dsh)",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|
|
8
8
|
"exports": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"ws": "^8.18.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@deepseek-ai/dsh-llm": "0.1.0-rc.
|
|
39
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.8",
|
|
40
40
|
"@eslint/js": "^10.0.1",
|
|
41
41
|
"@larksuiteoapi/node-sdk": "^1.73.0",
|
|
42
|
-
"esbuild": "^0.
|
|
42
|
+
"esbuild": "^0.28.2",
|
|
43
43
|
"eslint": "^10.9.1",
|
|
44
44
|
"globals": "^17.11.0",
|
|
45
45
|
"puppeteer-core": "^25.8.0"
|