@yunzai-ng/core 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/LICENSE +661 -0
- package/README.md +51 -0
- package/dist/adapter/accounts.d.ts +174 -0
- package/dist/adapter/accounts.d.ts.map +1 -0
- package/dist/adapter/accounts.js +653 -0
- package/dist/adapter/accounts.js.map +1 -0
- package/dist/adapter/bots.d.ts +142 -0
- package/dist/adapter/bots.d.ts.map +1 -0
- package/dist/adapter/bots.js +454 -0
- package/dist/adapter/bots.js.map +1 -0
- package/dist/adapter/host.d.ts +114 -0
- package/dist/adapter/host.d.ts.map +1 -0
- package/dist/adapter/host.js +90 -0
- package/dist/adapter/host.js.map +1 -0
- package/dist/adapter/login.d.ts +174 -0
- package/dist/adapter/login.d.ts.map +1 -0
- package/dist/adapter/login.js +345 -0
- package/dist/adapter/login.js.map +1 -0
- package/dist/adapter/registry.d.ts +102 -0
- package/dist/adapter/registry.d.ts.map +1 -0
- package/dist/adapter/registry.js +150 -0
- package/dist/adapter/registry.js.map +1 -0
- package/dist/config/core-config.d.ts +151 -0
- package/dist/config/core-config.d.ts.map +1 -0
- package/dist/config/core-config.js +338 -0
- package/dist/config/core-config.js.map +1 -0
- package/dist/config/schema.d.ts +449 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +871 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/store.d.ts +184 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +428 -0
- package/dist/config/store.js.map +1 -0
- package/dist/config/yaml.d.ts +23 -0
- package/dist/config/yaml.d.ts.map +1 -0
- package/dist/config/yaml.js +108 -0
- package/dist/config/yaml.js.map +1 -0
- package/dist/http/client.d.ts +82 -0
- package/dist/http/client.d.ts.map +1 -0
- package/dist/http/client.js +658 -0
- package/dist/http/client.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/app.d.ts +244 -0
- package/dist/kernel/app.d.ts.map +1 -0
- package/dist/kernel/app.js +654 -0
- package/dist/kernel/app.js.map +1 -0
- package/dist/kernel/kv-sink.d.ts +34 -0
- package/dist/kernel/kv-sink.d.ts.map +1 -0
- package/dist/kernel/kv-sink.js +25 -0
- package/dist/kernel/kv-sink.js.map +1 -0
- package/dist/kernel/policy.d.ts +77 -0
- package/dist/kernel/policy.d.ts.map +1 -0
- package/dist/kernel/policy.js +99 -0
- package/dist/kernel/policy.js.map +1 -0
- package/dist/kernel/runtime.d.ts +117 -0
- package/dist/kernel/runtime.d.ts.map +1 -0
- package/dist/kernel/runtime.js +197 -0
- package/dist/kernel/runtime.js.map +1 -0
- package/dist/kernel/sql-sink.d.ts +36 -0
- package/dist/kernel/sql-sink.d.ts.map +1 -0
- package/dist/kernel/sql-sink.js +114 -0
- package/dist/kernel/sql-sink.js.map +1 -0
- package/dist/logger/format.d.ts +67 -0
- package/dist/logger/format.d.ts.map +1 -0
- package/dist/logger/format.js +218 -0
- package/dist/logger/format.js.map +1 -0
- package/dist/logger/index.d.ts +97 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +363 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/rotate.d.ts +47 -0
- package/dist/logger/rotate.d.ts.map +1 -0
- package/dist/logger/rotate.js +242 -0
- package/dist/logger/rotate.js.map +1 -0
- package/dist/message/segment.d.ts +255 -0
- package/dist/message/segment.d.ts.map +1 -0
- package/dist/message/segment.js +510 -0
- package/dist/message/segment.js.map +1 -0
- package/dist/message/split.d.ts +34 -0
- package/dist/message/split.d.ts.map +1 -0
- package/dist/message/split.js +79 -0
- package/dist/message/split.js.map +1 -0
- package/dist/message/target.d.ts +29 -0
- package/dist/message/target.d.ts.map +1 -0
- package/dist/message/target.js +34 -0
- package/dist/message/target.js.map +1 -0
- package/dist/pipeline/cooldown.d.ts +84 -0
- package/dist/pipeline/cooldown.d.ts.map +1 -0
- package/dist/pipeline/cooldown.js +94 -0
- package/dist/pipeline/cooldown.js.map +1 -0
- package/dist/pipeline/dispatch.d.ts +98 -0
- package/dist/pipeline/dispatch.d.ts.map +1 -0
- package/dist/pipeline/dispatch.js +323 -0
- package/dist/pipeline/dispatch.js.map +1 -0
- package/dist/pipeline/event.d.ts +130 -0
- package/dist/pipeline/event.d.ts.map +1 -0
- package/dist/pipeline/event.js +538 -0
- package/dist/pipeline/event.js.map +1 -0
- package/dist/pipeline/middleware.d.ts +63 -0
- package/dist/pipeline/middleware.d.ts.map +1 -0
- package/dist/pipeline/middleware.js +174 -0
- package/dist/pipeline/middleware.js.map +1 -0
- package/dist/pipeline/prompt.d.ts +80 -0
- package/dist/pipeline/prompt.d.ts.map +1 -0
- package/dist/pipeline/prompt.js +155 -0
- package/dist/pipeline/prompt.js.map +1 -0
- package/dist/pipeline/router.d.ts +98 -0
- package/dist/pipeline/router.d.ts.map +1 -0
- package/dist/pipeline/router.js +489 -0
- package/dist/pipeline/router.js.map +1 -0
- package/dist/platform/detect.d.ts +24 -0
- package/dist/platform/detect.d.ts.map +1 -0
- package/dist/platform/detect.js +178 -0
- package/dist/platform/detect.js.map +1 -0
- package/dist/platform/paths.d.ts +38 -0
- package/dist/platform/paths.d.ts.map +1 -0
- package/dist/platform/paths.js +129 -0
- package/dist/platform/paths.js.map +1 -0
- package/dist/platform/system.d.ts +71 -0
- package/dist/platform/system.d.ts.map +1 -0
- package/dist/platform/system.js +242 -0
- package/dist/platform/system.js.map +1 -0
- package/dist/plugin/context.d.ts +92 -0
- package/dist/plugin/context.d.ts.map +1 -0
- package/dist/plugin/context.js +573 -0
- package/dist/plugin/context.js.map +1 -0
- package/dist/plugin/define.d.ts +92 -0
- package/dist/plugin/define.d.ts.map +1 -0
- package/dist/plugin/define.js +82 -0
- package/dist/plugin/define.js.map +1 -0
- package/dist/plugin/discover.d.ts +106 -0
- package/dist/plugin/discover.d.ts.map +1 -0
- package/dist/plugin/discover.js +254 -0
- package/dist/plugin/discover.js.map +1 -0
- package/dist/plugin/events.d.ts +109 -0
- package/dist/plugin/events.d.ts.map +1 -0
- package/dist/plugin/events.js +209 -0
- package/dist/plugin/events.js.map +1 -0
- package/dist/plugin/hooks.d.ts +266 -0
- package/dist/plugin/hooks.d.ts.map +1 -0
- package/dist/plugin/hooks.js +84 -0
- package/dist/plugin/hooks.js.map +1 -0
- package/dist/plugin/host.d.ts +160 -0
- package/dist/plugin/host.d.ts.map +1 -0
- package/dist/plugin/host.js +546 -0
- package/dist/plugin/host.js.map +1 -0
- package/dist/plugin/market.d.ts +264 -0
- package/dist/plugin/market.d.ts.map +1 -0
- package/dist/plugin/market.js +700 -0
- package/dist/plugin/market.js.map +1 -0
- package/dist/plugin/services.d.ts +116 -0
- package/dist/plugin/services.d.ts.map +1 -0
- package/dist/plugin/services.js +213 -0
- package/dist/plugin/services.js.map +1 -0
- package/dist/plugin/tar.d.ts +65 -0
- package/dist/plugin/tar.d.ts.map +1 -0
- package/dist/plugin/tar.js +277 -0
- package/dist/plugin/tar.js.map +1 -0
- package/dist/render/registry.d.ts +127 -0
- package/dist/render/registry.d.ts.map +1 -0
- package/dist/render/registry.js +306 -0
- package/dist/render/registry.js.map +1 -0
- package/dist/scheduler/index.d.ts +67 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +279 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/server/api.d.ts +179 -0
- package/dist/server/api.d.ts.map +1 -0
- package/dist/server/api.js +602 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/auth.d.ts +83 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +178 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/browse.d.ts +60 -0
- package/dist/server/browse.d.ts.map +1 -0
- package/dist/server/browse.js +187 -0
- package/dist/server/browse.js.map +1 -0
- package/dist/server/files.d.ts +27 -0
- package/dist/server/files.d.ts.map +1 -0
- package/dist/server/files.js +76 -0
- package/dist/server/files.js.map +1 -0
- package/dist/server/index.d.ts +189 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1123 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/table.d.ts +105 -0
- package/dist/server/table.d.ts.map +1 -0
- package/dist/server/table.js +289 -0
- package/dist/server/table.js.map +1 -0
- package/dist/store/index.d.ts +50 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +120 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/json.d.ts +73 -0
- package/dist/store/json.d.ts.map +1 -0
- package/dist/store/json.js +174 -0
- package/dist/store/json.js.map +1 -0
- package/dist/store/kv.d.ts +126 -0
- package/dist/store/kv.d.ts.map +1 -0
- package/dist/store/kv.js +232 -0
- package/dist/store/kv.js.map +1 -0
- package/dist/store/level.d.ts +103 -0
- package/dist/store/level.d.ts.map +1 -0
- package/dist/store/level.js +119 -0
- package/dist/store/level.js.map +1 -0
- package/dist/store/memory.d.ts +61 -0
- package/dist/store/memory.d.ts.map +1 -0
- package/dist/store/memory.js +94 -0
- package/dist/store/memory.js.map +1 -0
- package/dist/store/sql.d.ts +142 -0
- package/dist/store/sql.d.ts.map +1 -0
- package/dist/store/sql.js +246 -0
- package/dist/store/sql.js.map +1 -0
- package/dist/testing/fake.d.ts +109 -0
- package/dist/testing/fake.d.ts.map +1 -0
- package/dist/testing/fake.js +196 -0
- package/dist/testing/fake.js.map +1 -0
- package/dist/testing/index.d.ts +16 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +16 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock-adapter.d.ts +205 -0
- package/dist/testing/mock-adapter.d.ts.map +1 -0
- package/dist/testing/mock-adapter.js +309 -0
- package/dist/testing/mock-adapter.js.map +1 -0
- package/dist/util/deep.d.ts +108 -0
- package/dist/util/deep.d.ts.map +1 -0
- package/dist/util/deep.js +275 -0
- package/dist/util/deep.js.map +1 -0
- package/dist/util/defer.d.ts +107 -0
- package/dist/util/defer.d.ts.map +1 -0
- package/dist/util/defer.js +163 -0
- package/dist/util/defer.js.map +1 -0
- package/dist/util/dispose.d.ts +88 -0
- package/dist/util/dispose.d.ts.map +1 -0
- package/dist/util/dispose.js +143 -0
- package/dist/util/dispose.js.map +1 -0
- package/dist/util/duration.d.ts +28 -0
- package/dist/util/duration.d.ts.map +1 -0
- package/dist/util/duration.js +77 -0
- package/dist/util/duration.js.map +1 -0
- package/dist/util/fs.d.ts +110 -0
- package/dist/util/fs.d.ts.map +1 -0
- package/dist/util/fs.js +269 -0
- package/dist/util/fs.js.map +1 -0
- package/dist/util/id.d.ts +49 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +87 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/lru.d.ts +74 -0
- package/dist/util/lru.d.ts.map +1 -0
- package/dist/util/lru.js +156 -0
- package/dist/util/lru.js.map +1 -0
- package/dist/util/queue.d.ts +64 -0
- package/dist/util/queue.d.ts.map +1 -0
- package/dist/util/queue.js +147 -0
- package/dist/util/queue.js.map +1 -0
- package/dist/util/text.d.ts +86 -0
- package/dist/util/text.d.ts.map +1 -0
- package/dist/util/text.js +182 -0
- package/dist/util/text.js.map +1 -0
- package/package.json +44 -0
- package/src/adapter/accounts.ts +758 -0
- package/src/adapter/bots.ts +582 -0
- package/src/adapter/host.ts +224 -0
- package/src/adapter/login.ts +481 -0
- package/src/adapter/registry.ts +202 -0
- package/src/config/core-config.test.ts +60 -0
- package/src/config/core-config.ts +401 -0
- package/src/config/schema.test.ts +179 -0
- package/src/config/schema.ts +1036 -0
- package/src/config/store.test.ts +245 -0
- package/src/config/store.ts +506 -0
- package/src/config/yaml.ts +119 -0
- package/src/http/client.test.ts +568 -0
- package/src/http/client.ts +777 -0
- package/src/index.ts +106 -0
- package/src/kernel/app.test.ts +267 -0
- package/src/kernel/app.ts +843 -0
- package/src/kernel/kv-sink.ts +58 -0
- package/src/kernel/policy.ts +120 -0
- package/src/kernel/runtime.test.ts +542 -0
- package/src/kernel/runtime.ts +307 -0
- package/src/kernel/sql-sink.ts +154 -0
- package/src/logger/format.ts +259 -0
- package/src/logger/index.ts +427 -0
- package/src/logger/rotate.ts +265 -0
- package/src/message/segment.test.ts +335 -0
- package/src/message/segment.ts +569 -0
- package/src/message/split.ts +97 -0
- package/src/message/target.ts +48 -0
- package/src/pipeline/cooldown.ts +136 -0
- package/src/pipeline/dispatch.ts +419 -0
- package/src/pipeline/event.ts +735 -0
- package/src/pipeline/middleware.test.ts +426 -0
- package/src/pipeline/middleware.ts +199 -0
- package/src/pipeline/prompt.ts +212 -0
- package/src/pipeline/router.test.ts +432 -0
- package/src/pipeline/router.ts +575 -0
- package/src/platform/detect.ts +178 -0
- package/src/platform/paths.ts +147 -0
- package/src/platform/system.test.ts +102 -0
- package/src/platform/system.ts +289 -0
- package/src/plugin/context.test.ts +459 -0
- package/src/plugin/context.ts +757 -0
- package/src/plugin/define.test.ts +120 -0
- package/src/plugin/define.ts +142 -0
- package/src/plugin/discover.test.ts +253 -0
- package/src/plugin/discover.ts +353 -0
- package/src/plugin/events.test.ts +162 -0
- package/src/plugin/events.ts +266 -0
- package/src/plugin/hooks.ts +373 -0
- package/src/plugin/host.test.ts +696 -0
- package/src/plugin/host.ts +738 -0
- package/src/plugin/market.test.ts +781 -0
- package/src/plugin/market.ts +870 -0
- package/src/plugin/services.test.ts +135 -0
- package/src/plugin/services.ts +261 -0
- package/src/plugin/tar.test.ts +158 -0
- package/src/plugin/tar.ts +309 -0
- package/src/render/registry.test.ts +127 -0
- package/src/render/registry.ts +439 -0
- package/src/scheduler/index.ts +357 -0
- package/src/server/api.test.ts +802 -0
- package/src/server/api.ts +869 -0
- package/src/server/auth.ts +201 -0
- package/src/server/browse.test.ts +193 -0
- package/src/server/browse.ts +240 -0
- package/src/server/files.ts +97 -0
- package/src/server/index.test.ts +566 -0
- package/src/server/index.ts +1386 -0
- package/src/server/table.ts +351 -0
- package/src/store/index.ts +156 -0
- package/src/store/json.ts +198 -0
- package/src/store/kv.test.ts +307 -0
- package/src/store/kv.ts +256 -0
- package/src/store/level.ts +167 -0
- package/src/store/memory.ts +109 -0
- package/src/store/sql.test.ts +204 -0
- package/src/store/sql.ts +324 -0
- package/src/testing/fake.ts +297 -0
- package/src/testing/index.ts +15 -0
- package/src/testing/mock-adapter.ts +588 -0
- package/src/util/deep.ts +272 -0
- package/src/util/defer.ts +211 -0
- package/src/util/dispose.ts +169 -0
- package/src/util/duration.ts +82 -0
- package/src/util/fs.ts +279 -0
- package/src/util/id.ts +94 -0
- package/src/util/lru.ts +185 -0
- package/src/util/queue.ts +167 -0
- package/src/util/text.ts +189 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块职责:对象深操作(合并、克隆、按路径读写、差异路径计算)
|
|
3
|
+
* 依赖方向:无
|
|
4
|
+
* 生命周期:纯函数
|
|
5
|
+
* 注意事项:配置系统的地基。`diffPaths` 算出实际变化的叶子路径,故配置变更只通知
|
|
6
|
+
* 关心那些路径的订阅者,而不是让每个读配置的地方全量重算。
|
|
7
|
+
*
|
|
8
|
+
* **数组是整体替换,不逐元素合并。** 配置里的数组(主人列表、黑名单)语义上是
|
|
9
|
+
* "一个值",逐元素合并会让使用者无法删除默认项。
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 判断是否为普通对象(排除数组、null、Date、Buffer、类实例等)
|
|
13
|
+
* @param value 待判定值
|
|
14
|
+
* @returns 是否为普通对象
|
|
15
|
+
*/
|
|
16
|
+
export function isPlainObject(value) {
|
|
17
|
+
if (value === null || typeof value !== "object")
|
|
18
|
+
return false;
|
|
19
|
+
if (Array.isArray(value))
|
|
20
|
+
return false;
|
|
21
|
+
const proto = Object.getPrototypeOf(value);
|
|
22
|
+
return proto === Object.prototype || proto === null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 深克隆
|
|
26
|
+
*
|
|
27
|
+
* 优先用 `structuredClone`(Node 17+ 内置,能处理 Map/Set/Date/循环引用),
|
|
28
|
+
* 遇到函数等不可克隆值时退回浅拷贝语义。
|
|
29
|
+
* @param value 源值
|
|
30
|
+
* @returns 克隆结果
|
|
31
|
+
*/
|
|
32
|
+
export function deepClone(value) {
|
|
33
|
+
try {
|
|
34
|
+
return structuredClone(value);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return cloneFallback(value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* structuredClone 失败时的回退克隆(跳过不可克隆值)
|
|
42
|
+
* @param value 源值
|
|
43
|
+
* @returns 克隆结果
|
|
44
|
+
*/
|
|
45
|
+
function cloneFallback(value) {
|
|
46
|
+
if (Array.isArray(value))
|
|
47
|
+
return value.map(item => cloneFallback(item));
|
|
48
|
+
if (isPlainObject(value)) {
|
|
49
|
+
const out = {};
|
|
50
|
+
for (const [k, v] of Object.entries(value))
|
|
51
|
+
out[k] = cloneFallback(v);
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 深合并:把 `source` 覆盖到 `target` 的副本上
|
|
58
|
+
*
|
|
59
|
+
* - 普通对象递归合并
|
|
60
|
+
* - 数组、`Date` 等整体替换
|
|
61
|
+
* - `source` 中值为 `undefined` 的键被忽略(不会把 target 的值抹成 undefined)
|
|
62
|
+
* @param target 基准值(不被修改)
|
|
63
|
+
* @param source 覆盖值
|
|
64
|
+
* @returns 合并后的新对象
|
|
65
|
+
*/
|
|
66
|
+
export function deepMerge(target, source) {
|
|
67
|
+
if (!source)
|
|
68
|
+
return deepClone(target);
|
|
69
|
+
const out = deepClone(target);
|
|
70
|
+
for (const [key, value] of Object.entries(source)) {
|
|
71
|
+
if (value === undefined)
|
|
72
|
+
continue;
|
|
73
|
+
// 拒绝原型链污染:合并的数据可能来自 WebUI 提交的 JSON
|
|
74
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype")
|
|
75
|
+
continue;
|
|
76
|
+
const existing = out[key];
|
|
77
|
+
if (isPlainObject(value) && isPlainObject(existing)) {
|
|
78
|
+
out[key] = deepMerge(existing, value);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
out[key] = deepClone(value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 深比较
|
|
88
|
+
* @param a 左值
|
|
89
|
+
* @param b 右值
|
|
90
|
+
* @returns 是否深度相等
|
|
91
|
+
*/
|
|
92
|
+
export function deepEqual(a, b) {
|
|
93
|
+
if (a === b)
|
|
94
|
+
return true;
|
|
95
|
+
if (typeof a !== typeof b)
|
|
96
|
+
return false;
|
|
97
|
+
if (a === null || b === null)
|
|
98
|
+
return false;
|
|
99
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
100
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
|
|
101
|
+
return false;
|
|
102
|
+
return a.every((item, i) => deepEqual(item, b[i]));
|
|
103
|
+
}
|
|
104
|
+
if (a instanceof Date || b instanceof Date) {
|
|
105
|
+
return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();
|
|
106
|
+
}
|
|
107
|
+
if (typeof a === "object" && typeof b === "object") {
|
|
108
|
+
const ao = a;
|
|
109
|
+
const bo = b;
|
|
110
|
+
const aKeys = Object.keys(ao);
|
|
111
|
+
const bKeys = Object.keys(bo);
|
|
112
|
+
if (aKeys.length !== bKeys.length)
|
|
113
|
+
return false;
|
|
114
|
+
return aKeys.every(k => Object.prototype.hasOwnProperty.call(bo, k) && deepEqual(ao[k], bo[k]));
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 把点分路径切成键数组
|
|
120
|
+
*
|
|
121
|
+
* 支持 `a.b[0].c` 与 `a.b.0.c` 两种写法。
|
|
122
|
+
* @param path 路径字符串
|
|
123
|
+
* @returns 键数组
|
|
124
|
+
*/
|
|
125
|
+
export function splitPath(path) {
|
|
126
|
+
if (path === "")
|
|
127
|
+
return [];
|
|
128
|
+
return path
|
|
129
|
+
.replace(/\[(\d+)\]/g, ".$1")
|
|
130
|
+
.split(".")
|
|
131
|
+
.filter(seg => seg !== "");
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 按路径取值
|
|
135
|
+
* @param obj 源对象
|
|
136
|
+
* @param path 点分路径;空串返回 obj 本身
|
|
137
|
+
* @returns 值;路径不存在时 undefined
|
|
138
|
+
*/
|
|
139
|
+
export function getPath(obj, path) {
|
|
140
|
+
const keys = splitPath(path);
|
|
141
|
+
let cur = obj;
|
|
142
|
+
for (const key of keys) {
|
|
143
|
+
if (cur === null || cur === undefined)
|
|
144
|
+
return undefined;
|
|
145
|
+
if (typeof cur !== "object")
|
|
146
|
+
return undefined;
|
|
147
|
+
cur = cur[key];
|
|
148
|
+
}
|
|
149
|
+
return cur;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 按路径写值(原地修改)
|
|
153
|
+
*
|
|
154
|
+
* 中间层不存在时自动创建:下一级键是纯数字则建数组,否则建对象。
|
|
155
|
+
* @param obj 目标对象
|
|
156
|
+
* @param path 点分路径
|
|
157
|
+
* @param value 值
|
|
158
|
+
* @throws 当路径为空或中间层是不可写入的标量时
|
|
159
|
+
*/
|
|
160
|
+
export function setPath(obj, path, value) {
|
|
161
|
+
const keys = splitPath(path);
|
|
162
|
+
if (keys.length === 0)
|
|
163
|
+
throw new Error("setPath: 路径不能为空");
|
|
164
|
+
let cur = obj;
|
|
165
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
166
|
+
const key = keys[i];
|
|
167
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
168
|
+
throw new Error(`setPath: 非法路径片段 ${key}`);
|
|
169
|
+
}
|
|
170
|
+
const next = cur[key];
|
|
171
|
+
if (isPlainObject(next) || Array.isArray(next)) {
|
|
172
|
+
cur = next;
|
|
173
|
+
}
|
|
174
|
+
else if (next === undefined || next === null) {
|
|
175
|
+
const created = /^\d+$/.test(keys[i + 1]) ? [] : {};
|
|
176
|
+
cur[key] = created;
|
|
177
|
+
cur = created;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
throw new Error(`setPath: ${keys.slice(0, i + 1).join(".")} 已是标量,无法继续写入`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const last = keys[keys.length - 1];
|
|
184
|
+
if (last === "__proto__" || last === "constructor" || last === "prototype") {
|
|
185
|
+
throw new Error(`setPath: 非法路径片段 ${last}`);
|
|
186
|
+
}
|
|
187
|
+
;
|
|
188
|
+
cur[last] = value;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* 按路径删除(原地修改)
|
|
192
|
+
* @param obj 目标对象
|
|
193
|
+
* @param path 点分路径
|
|
194
|
+
* @returns 是否确实删掉了什么
|
|
195
|
+
*/
|
|
196
|
+
export function deletePath(obj, path) {
|
|
197
|
+
const keys = splitPath(path);
|
|
198
|
+
if (keys.length === 0)
|
|
199
|
+
return false;
|
|
200
|
+
const parentPath = keys.slice(0, -1).join(".");
|
|
201
|
+
const parent = parentPath === "" ? obj : getPath(obj, parentPath);
|
|
202
|
+
if (parent === null || typeof parent !== "object")
|
|
203
|
+
return false;
|
|
204
|
+
const last = keys[keys.length - 1];
|
|
205
|
+
if (Array.isArray(parent)) {
|
|
206
|
+
const index = Number(last);
|
|
207
|
+
if (!Number.isInteger(index) || index < 0 || index >= parent.length)
|
|
208
|
+
return false;
|
|
209
|
+
parent.splice(index, 1);
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
if (!Object.prototype.hasOwnProperty.call(parent, last))
|
|
213
|
+
return false;
|
|
214
|
+
delete parent[last];
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* 计算两个对象间发生变化的**叶子路径**
|
|
219
|
+
*
|
|
220
|
+
* 这是细粒度配置失效的核心:改了 `bot.masterQQ` 就只通知订阅
|
|
221
|
+
* `bot.masterQQ`(或其祖先 `bot`)的人,不打扰订阅 `render.*` 的人。
|
|
222
|
+
*
|
|
223
|
+
* 数组视为叶子(整体变化),不下钻元素。
|
|
224
|
+
* @param before 旧值
|
|
225
|
+
* @param after 新值
|
|
226
|
+
* @param prefix 内部递归用的路径前缀
|
|
227
|
+
* @returns 变化路径列表,已去重
|
|
228
|
+
*/
|
|
229
|
+
export function diffPaths(before, after, prefix = "") {
|
|
230
|
+
if (deepEqual(before, after))
|
|
231
|
+
return [];
|
|
232
|
+
// 任一侧不是普通对象 → 当前节点整体变化
|
|
233
|
+
if (!isPlainObject(before) || !isPlainObject(after)) {
|
|
234
|
+
return prefix === "" ? [""] : [prefix];
|
|
235
|
+
}
|
|
236
|
+
const out = [];
|
|
237
|
+
const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
238
|
+
for (const key of keys) {
|
|
239
|
+
const path = prefix === "" ? key : `${prefix}.${key}`;
|
|
240
|
+
out.push(...diffPaths(before[key], after[key], path));
|
|
241
|
+
}
|
|
242
|
+
return out;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* 判断某条变化路径是否影响到订阅路径
|
|
246
|
+
*
|
|
247
|
+
* 双向前缀匹配:改 `bot` 影响订阅 `bot.masterQQ` 的人(父变子受影响),
|
|
248
|
+
* 改 `bot.masterQQ` 也影响订阅 `bot` 的人(子变父受影响)。
|
|
249
|
+
* @param changed 发生变化的路径
|
|
250
|
+
* @param watched 订阅的路径;空串表示订阅全部
|
|
251
|
+
* @returns 是否受影响
|
|
252
|
+
*/
|
|
253
|
+
export function pathAffects(changed, watched) {
|
|
254
|
+
if (watched === "" || changed === "")
|
|
255
|
+
return true;
|
|
256
|
+
if (changed === watched)
|
|
257
|
+
return true;
|
|
258
|
+
return changed.startsWith(`${watched}.`) || watched.startsWith(`${changed}.`);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* 摘出对象里的指定路径,组成新对象
|
|
262
|
+
* @param obj 源对象
|
|
263
|
+
* @param paths 路径列表
|
|
264
|
+
* @returns 只含这些路径的新对象
|
|
265
|
+
*/
|
|
266
|
+
export function pickPaths(obj, paths) {
|
|
267
|
+
const out = {};
|
|
268
|
+
for (const path of paths) {
|
|
269
|
+
const value = getPath(obj, path);
|
|
270
|
+
if (value !== undefined)
|
|
271
|
+
setPath(out, path, deepClone(value));
|
|
272
|
+
}
|
|
273
|
+
return out;
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=deep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep.js","sourceRoot":"","sources":["../../src/util/deep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块职责:Promise 原语(外部可控 Promise、超时、休眠、重试)
|
|
3
|
+
* 依赖方向:仅依赖类型包
|
|
4
|
+
* 生命周期:纯函数 / 短生命周期对象
|
|
5
|
+
* 注意事项:所有会挂起的等待均必须可被取消,否则热重载时插件已卸载、
|
|
6
|
+
* 而 Promise 仍持有定时器,即构成内存泄漏。因此 `Deferred` 暴露
|
|
7
|
+
* `reject`,`withTimeout` 必定清除 timer,`sleep` 支持 signal。
|
|
8
|
+
*/
|
|
9
|
+
/** 超时错误:与普通业务错误相区分,便于上层决定"重试"或"放弃" */
|
|
10
|
+
export declare class TimeoutError extends Error {
|
|
11
|
+
/** 错误名,便于 `err.name === "TimeoutError"` 判定 */
|
|
12
|
+
readonly name = "TimeoutError";
|
|
13
|
+
/**
|
|
14
|
+
* @param message 错误信息
|
|
15
|
+
*/
|
|
16
|
+
constructor(message?: string);
|
|
17
|
+
}
|
|
18
|
+
/** 中止错误:signal 触发时抛出 */
|
|
19
|
+
export declare class AbortError extends Error {
|
|
20
|
+
/** 错误名 */
|
|
21
|
+
readonly name = "AbortError";
|
|
22
|
+
/**
|
|
23
|
+
* @param message 错误信息
|
|
24
|
+
*/
|
|
25
|
+
constructor(message?: string);
|
|
26
|
+
}
|
|
27
|
+
/** 外部可控的 Promise */
|
|
28
|
+
export interface Deferred<T> {
|
|
29
|
+
/** Promise 本体 */
|
|
30
|
+
readonly promise: Promise<T>;
|
|
31
|
+
/**
|
|
32
|
+
* 兑现
|
|
33
|
+
* @param value 结果值
|
|
34
|
+
*/
|
|
35
|
+
resolve(value: T | PromiseLike<T>): void;
|
|
36
|
+
/**
|
|
37
|
+
* 拒绝
|
|
38
|
+
* @param reason 原因
|
|
39
|
+
*/
|
|
40
|
+
reject(reason?: unknown): void;
|
|
41
|
+
/** 是否已结束(兑现或拒绝) */
|
|
42
|
+
readonly settled: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 创建外部可控的 Promise
|
|
46
|
+
*
|
|
47
|
+
* 用于把"回调/事件"风格的等待(如适配器 echo 应答、`e.prompt`)转成 await。
|
|
48
|
+
* 重复调用 resolve/reject 会被忽略,不会抛错。
|
|
49
|
+
* @returns Deferred 句柄
|
|
50
|
+
*/
|
|
51
|
+
export declare function defer<T>(): Deferred<T>;
|
|
52
|
+
/**
|
|
53
|
+
* 休眠
|
|
54
|
+
* @param ms 毫秒
|
|
55
|
+
* @param signal 可选中止信号;触发时以 AbortError 拒绝
|
|
56
|
+
* @returns 到期后兑现
|
|
57
|
+
*/
|
|
58
|
+
export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* 给 Promise 套超时
|
|
61
|
+
*
|
|
62
|
+
* 注意:超时只是让调用方不再等待,**并不能真正取消**底层操作。需要真取消
|
|
63
|
+
* 的场景(HTTP 请求)请把 signal 传给底层。
|
|
64
|
+
* @param promise 被包装的 Promise
|
|
65
|
+
* @param ms 超时毫秒;<=0 表示不限时
|
|
66
|
+
* @param message 超时错误信息
|
|
67
|
+
* @returns 原结果,或以 TimeoutError 拒绝
|
|
68
|
+
*/
|
|
69
|
+
export declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
|
|
70
|
+
/** 重试选项 */
|
|
71
|
+
export interface RetryOptions {
|
|
72
|
+
/** 最大尝试次数(含首次),缺省 3 */
|
|
73
|
+
attempts?: number;
|
|
74
|
+
/** 首次退避毫秒,缺省 500 */
|
|
75
|
+
baseDelay?: number;
|
|
76
|
+
/** 退避上限毫秒,缺省 30000 */
|
|
77
|
+
maxDelay?: number;
|
|
78
|
+
/** 退避倍率,缺省 2 */
|
|
79
|
+
factor?: number;
|
|
80
|
+
/** 抖动比例 0~1,缺省 0.2;用于避免多账号重连时步调一致而对服务端造成过载 */
|
|
81
|
+
jitter?: number;
|
|
82
|
+
/** 中止信号 */
|
|
83
|
+
signal?: AbortSignal;
|
|
84
|
+
/**
|
|
85
|
+
* 每次失败后的回调
|
|
86
|
+
* @param err 本次错误
|
|
87
|
+
* @param attempt 已尝试次数(从 1 开始)
|
|
88
|
+
* @param delay 即将等待的毫秒
|
|
89
|
+
*/
|
|
90
|
+
onRetry?: (err: unknown, attempt: number, delay: number) => void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 计算指数退避(带抖动)的等待时长
|
|
94
|
+
* @param attempt 已尝试次数(从 1 开始)
|
|
95
|
+
* @param opts 退避参数
|
|
96
|
+
* @returns 毫秒
|
|
97
|
+
*/
|
|
98
|
+
export declare function backoffDelay(attempt: number, opts?: RetryOptions): number;
|
|
99
|
+
/**
|
|
100
|
+
* 带指数退避的重试
|
|
101
|
+
* @param task 任务;参数为已尝试次数(从 1 开始)
|
|
102
|
+
* @param opts 重试选项
|
|
103
|
+
* @returns 任务结果
|
|
104
|
+
* @throws 最后一次的错误
|
|
105
|
+
*/
|
|
106
|
+
export declare function retry<T>(task: (attempt: number) => Promise<T>, opts?: RetryOptions): Promise<T>;
|
|
107
|
+
//# sourceMappingURL=defer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defer.d.ts","sourceRoot":"","sources":["../../src/util/defer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,sCAAsC;AACtC,qBAAa,YAAa,SAAQ,KAAK;IACrC,8CAA8C;IAC9C,SAAkB,IAAI,kBAAiB;IAEvC;;OAEG;gBACS,OAAO,SAAS;CAG7B;AAED,wBAAwB;AACxB,qBAAa,UAAW,SAAQ,KAAK;IACnC,UAAU;IACV,SAAkB,IAAI,gBAAe;IAErC;;OAEG;gBACS,OAAO,SAAW;CAG/B;AAED,oBAAoB;AACpB,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,iBAAiB;IACjB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5B;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IACxC;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC9B,mBAAmB;IACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CA0BtC;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBrE;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAgB5F;AAED,WAAW;AACX,MAAM,WAAW,YAAY;IAC3B,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gBAAgB;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW;IACX,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACjE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,MAAM,CAU7E;AAED;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,CAiBzG"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块职责:Promise 原语(外部可控 Promise、超时、休眠、重试)
|
|
3
|
+
* 依赖方向:仅依赖类型包
|
|
4
|
+
* 生命周期:纯函数 / 短生命周期对象
|
|
5
|
+
* 注意事项:所有会挂起的等待均必须可被取消,否则热重载时插件已卸载、
|
|
6
|
+
* 而 Promise 仍持有定时器,即构成内存泄漏。因此 `Deferred` 暴露
|
|
7
|
+
* `reject`,`withTimeout` 必定清除 timer,`sleep` 支持 signal。
|
|
8
|
+
*/
|
|
9
|
+
/** 超时错误:与普通业务错误相区分,便于上层决定"重试"或"放弃" */
|
|
10
|
+
export class TimeoutError extends Error {
|
|
11
|
+
/** 错误名,便于 `err.name === "TimeoutError"` 判定 */
|
|
12
|
+
name = "TimeoutError";
|
|
13
|
+
/**
|
|
14
|
+
* @param message 错误信息
|
|
15
|
+
*/
|
|
16
|
+
constructor(message = "操作超时") {
|
|
17
|
+
super(message);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** 中止错误:signal 触发时抛出 */
|
|
21
|
+
export class AbortError extends Error {
|
|
22
|
+
/** 错误名 */
|
|
23
|
+
name = "AbortError";
|
|
24
|
+
/**
|
|
25
|
+
* @param message 错误信息
|
|
26
|
+
*/
|
|
27
|
+
constructor(message = "操作已被取消") {
|
|
28
|
+
super(message);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 创建外部可控的 Promise
|
|
33
|
+
*
|
|
34
|
+
* 用于把"回调/事件"风格的等待(如适配器 echo 应答、`e.prompt`)转成 await。
|
|
35
|
+
* 重复调用 resolve/reject 会被忽略,不会抛错。
|
|
36
|
+
* @returns Deferred 句柄
|
|
37
|
+
*/
|
|
38
|
+
export function defer() {
|
|
39
|
+
let resolveFn;
|
|
40
|
+
let rejectFn;
|
|
41
|
+
let settled = false;
|
|
42
|
+
const promise = new Promise((res, rej) => {
|
|
43
|
+
resolveFn = res;
|
|
44
|
+
rejectFn = rej;
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
promise,
|
|
48
|
+
resolve(value) {
|
|
49
|
+
if (settled)
|
|
50
|
+
return;
|
|
51
|
+
settled = true;
|
|
52
|
+
resolveFn(value);
|
|
53
|
+
},
|
|
54
|
+
reject(reason) {
|
|
55
|
+
if (settled)
|
|
56
|
+
return;
|
|
57
|
+
settled = true;
|
|
58
|
+
rejectFn(reason);
|
|
59
|
+
},
|
|
60
|
+
get settled() {
|
|
61
|
+
return settled;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 休眠
|
|
67
|
+
* @param ms 毫秒
|
|
68
|
+
* @param signal 可选中止信号;触发时以 AbortError 拒绝
|
|
69
|
+
* @returns 到期后兑现
|
|
70
|
+
*/
|
|
71
|
+
export function sleep(ms, signal) {
|
|
72
|
+
if (ms <= 0)
|
|
73
|
+
return Promise.resolve();
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
if (signal?.aborted) {
|
|
76
|
+
reject(new AbortError());
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const timer = setTimeout(() => {
|
|
80
|
+
signal?.removeEventListener("abort", onAbort);
|
|
81
|
+
resolve();
|
|
82
|
+
}, ms);
|
|
83
|
+
// Node 下 unref 让"只剩一个 sleep"时进程仍能退出
|
|
84
|
+
if (typeof timer.unref === "function")
|
|
85
|
+
timer.unref();
|
|
86
|
+
/** 中止回调 */
|
|
87
|
+
function onAbort() {
|
|
88
|
+
clearTimeout(timer);
|
|
89
|
+
reject(new AbortError());
|
|
90
|
+
}
|
|
91
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 给 Promise 套超时
|
|
96
|
+
*
|
|
97
|
+
* 注意:超时只是让调用方不再等待,**并不能真正取消**底层操作。需要真取消
|
|
98
|
+
* 的场景(HTTP 请求)请把 signal 传给底层。
|
|
99
|
+
* @param promise 被包装的 Promise
|
|
100
|
+
* @param ms 超时毫秒;<=0 表示不限时
|
|
101
|
+
* @param message 超时错误信息
|
|
102
|
+
* @returns 原结果,或以 TimeoutError 拒绝
|
|
103
|
+
*/
|
|
104
|
+
export function withTimeout(promise, ms, message) {
|
|
105
|
+
if (ms <= 0)
|
|
106
|
+
return promise;
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
const timer = setTimeout(() => reject(new TimeoutError(message)), ms);
|
|
109
|
+
if (typeof timer.unref === "function")
|
|
110
|
+
timer.unref();
|
|
111
|
+
promise.then(value => {
|
|
112
|
+
clearTimeout(timer);
|
|
113
|
+
resolve(value);
|
|
114
|
+
}, reason => {
|
|
115
|
+
clearTimeout(timer);
|
|
116
|
+
reject(reason);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 计算指数退避(带抖动)的等待时长
|
|
122
|
+
* @param attempt 已尝试次数(从 1 开始)
|
|
123
|
+
* @param opts 退避参数
|
|
124
|
+
* @returns 毫秒
|
|
125
|
+
*/
|
|
126
|
+
export function backoffDelay(attempt, opts = {}) {
|
|
127
|
+
const base = opts.baseDelay ?? 500;
|
|
128
|
+
const factor = opts.factor ?? 2;
|
|
129
|
+
const max = opts.maxDelay ?? 30_000;
|
|
130
|
+
const jitter = opts.jitter ?? 0.2;
|
|
131
|
+
const raw = Math.min(max, base * factor ** Math.max(0, attempt - 1));
|
|
132
|
+
// 抖动只往下浮动,保证不会超过 maxDelay
|
|
133
|
+
const delta = raw * jitter * Math.random();
|
|
134
|
+
return Math.round(raw - delta);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 带指数退避的重试
|
|
138
|
+
* @param task 任务;参数为已尝试次数(从 1 开始)
|
|
139
|
+
* @param opts 重试选项
|
|
140
|
+
* @returns 任务结果
|
|
141
|
+
* @throws 最后一次的错误
|
|
142
|
+
*/
|
|
143
|
+
export async function retry(task, opts = {}) {
|
|
144
|
+
const attempts = Math.max(1, opts.attempts ?? 3);
|
|
145
|
+
let lastError;
|
|
146
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
147
|
+
if (opts.signal?.aborted)
|
|
148
|
+
throw new AbortError();
|
|
149
|
+
try {
|
|
150
|
+
return await task(attempt);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
lastError = err;
|
|
154
|
+
if (attempt >= attempts)
|
|
155
|
+
break;
|
|
156
|
+
const delay = backoffDelay(attempt, opts);
|
|
157
|
+
opts.onRetry?.(err, attempt, delay);
|
|
158
|
+
await sleep(delay, opts.signal);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
throw lastError;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=defer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defer.js","sourceRoot":"","sources":["../../src/util/defer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,sCAAsC;AACtC,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,8CAA8C;IAC5B,IAAI,GAAG,cAAc,CAAA;IAEvC;;OAEG;IACH,YAAY,OAAO,GAAG,MAAM;QAC1B,KAAK,CAAC,OAAO,CAAC,CAAA;IAChB,CAAC;CACF;AAED,wBAAwB;AACxB,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,UAAU;IACQ,IAAI,GAAG,YAAY,CAAA;IAErC;;OAEG;IACH,YAAY,OAAO,GAAG,QAAQ;QAC5B,KAAK,CAAC,OAAO,CAAC,CAAA;IAChB,CAAC;CACF;AAoBD;;;;;;GAMG;AACH,MAAM,UAAU,KAAK;IACnB,IAAI,SAA+C,CAAA;IACnD,IAAI,QAAqC,CAAA;IACzC,IAAI,OAAO,GAAG,KAAK,CAAA;IAEnB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC1C,SAAS,GAAG,GAAG,CAAA;QACf,QAAQ,GAAG,GAAG,CAAA;IAChB,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,OAAO;QACP,OAAO,CAAC,KAAK;YACX,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,SAAS,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC;QACD,MAAM,CAAC,MAAM;YACX,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,QAAQ,CAAC,MAAM,CAAC,CAAA;QAClB,CAAC;QACD,IAAI,OAAO;YACT,OAAO,OAAO,CAAA;QAChB,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU,EAAE,MAAoB;IACpD,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IACrC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC,CAAA;YACxB,OAAM;QACR,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAC7C,OAAO,EAAE,CAAA;QACX,CAAC,EAAE,EAAE,CAAC,CAAA;QACN,oCAAoC;QACpC,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU;YAAE,KAAK,CAAC,KAAK,EAAE,CAAA;QAEpD,WAAW;QACX,SAAS,OAAO;YACd,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC,CAAA;QAC1B,CAAC;QACD,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAI,OAAmB,EAAE,EAAU,EAAE,OAAgB;IAC9E,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,OAAO,CAAA;IAC3B,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QACrE,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU;YAAE,KAAK,CAAC,KAAK,EAAE,CAAA;QACpD,OAAO,CAAC,IAAI,CACV,KAAK,CAAC,EAAE;YACN,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,OAAO,CAAC,KAAK,CAAC,CAAA;QAChB,CAAC,EACD,MAAM,CAAC,EAAE;YACP,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,MAAM,CAAC,MAAM,CAAC,CAAA;QAChB,CAAC,CACF,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAyBD;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,OAAqB,EAAE;IACnE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,CAAA;IAClC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAA;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAA;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAA;IAEjC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;IACpE,0BAA0B;IAC1B,MAAM,KAAK,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;IAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,CAAA;AAChC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAI,IAAqC,EAAE,OAAqB,EAAE;IAC3F,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAA;IAChD,IAAI,SAAkB,CAAA;IAEtB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC;QACrD,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,UAAU,EAAE,CAAA;QAChD,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,CAAA;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAG,CAAA;YACf,IAAI,OAAO,IAAI,QAAQ;gBAAE,MAAK;YAC9B,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACzC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;YACnC,MAAM,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAA;AACjB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块职责:资源回收登记簿
|
|
3
|
+
* 依赖方向:依赖类型包的 Disposer
|
|
4
|
+
* 生命周期:与其宿主(插件实例 / 账号连接 / 应用)同寿
|
|
5
|
+
* 注意事项:**内核提供给插件的每一个注册型 API 都返回 Disposer**,并自动登记到该插件的
|
|
6
|
+
* registry。插件卸载时逆序全量回收,故插件作者不需要(也无从忘记)手工清理 ——
|
|
7
|
+
* 否则改十次代码就有十份定时器在跑同一件事。
|
|
8
|
+
*
|
|
9
|
+
* 逆序回收是有意的:后注册的往往依赖先注册的(如先 provide 服务再
|
|
10
|
+
* 注册用到它的命令),倒着拆才不会拆到一半引用空对象。
|
|
11
|
+
*/
|
|
12
|
+
import type { Disposer } from "@yunzai-ng/types";
|
|
13
|
+
/** 回收过程中收集到的错误 */
|
|
14
|
+
export interface DisposeFailure {
|
|
15
|
+
/** 登记时的标签 */
|
|
16
|
+
label: string;
|
|
17
|
+
/** 抛出的错误 */
|
|
18
|
+
error: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 资源回收登记簿
|
|
22
|
+
*
|
|
23
|
+
* 线程模型:同进程单线程,无需加锁;但 `dispose()` 可能重入
|
|
24
|
+
* (插件在 disposer 里又触发卸载),故有 `#disposed` 幂等保护。
|
|
25
|
+
*/
|
|
26
|
+
export declare class DisposalRegistry {
|
|
27
|
+
#private;
|
|
28
|
+
/**
|
|
29
|
+
* @param owner 归属标识(插件名等),出错时用于定位
|
|
30
|
+
*/
|
|
31
|
+
constructor(owner: string);
|
|
32
|
+
/** 是否已回收 */
|
|
33
|
+
get disposed(): boolean;
|
|
34
|
+
/** 尚未回收的登记项数量 */
|
|
35
|
+
get size(): number;
|
|
36
|
+
/**
|
|
37
|
+
* 登记一个回收器
|
|
38
|
+
*
|
|
39
|
+
* 若 registry 已回收,传入的 disposer 会**立即执行** —— 这防止"卸载竞态":
|
|
40
|
+
* 异步初始化的插件在卸载后才完成注册,资源没人回收。
|
|
41
|
+
* @param dispose 回收函数
|
|
42
|
+
* @param label 标签,用于报错定位
|
|
43
|
+
* @returns 取消登记并执行回收的函数;重复调用无副作用
|
|
44
|
+
*/
|
|
45
|
+
add(dispose: Disposer, label?: string): Disposer;
|
|
46
|
+
/**
|
|
47
|
+
* 登记一个 `Map`/`Set` 条目的清理
|
|
48
|
+
* @param collection 容器
|
|
49
|
+
* @param key 键
|
|
50
|
+
* @param label 标签
|
|
51
|
+
* @returns 回收函数
|
|
52
|
+
*/
|
|
53
|
+
addEntry<K>(collection: {
|
|
54
|
+
delete(key: K): unknown;
|
|
55
|
+
}, key: K, label?: string): Disposer;
|
|
56
|
+
/**
|
|
57
|
+
* 登记一个定时器
|
|
58
|
+
*
|
|
59
|
+
* 顺带 `unref`,让"只剩定时器"时进程能正常退出。
|
|
60
|
+
* @param timer 定时器句柄
|
|
61
|
+
* @param label 标签
|
|
62
|
+
* @returns 回收函数
|
|
63
|
+
*/
|
|
64
|
+
addTimer(timer: NodeJS.Timeout, label?: string): Disposer;
|
|
65
|
+
/**
|
|
66
|
+
* 创建从属子登记簿
|
|
67
|
+
*
|
|
68
|
+
* 父簿回收时自动带走子簿。用于"插件里的账号连接"这类嵌套生命周期。
|
|
69
|
+
* @param owner 子簿归属标识
|
|
70
|
+
* @returns 子登记簿
|
|
71
|
+
*/
|
|
72
|
+
child(owner: string): DisposalRegistry;
|
|
73
|
+
/**
|
|
74
|
+
* 逆序回收全部登记项
|
|
75
|
+
*
|
|
76
|
+
* 单个 disposer 抛错**不会**中断后续回收 —— 一个插件写错清理逻辑不应该
|
|
77
|
+
* 导致其余资源全部泄漏。所有错误汇总返回,由调用方(插件宿主)记日志。
|
|
78
|
+
* @returns 回收过程中发生的错误列表;无错时为空数组
|
|
79
|
+
*/
|
|
80
|
+
dispose(): DisposeFailure[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 把多个 Disposer 合成一个
|
|
84
|
+
* @param disposers 回收函数列表(可含 undefined,便于条件注册)
|
|
85
|
+
* @returns 合成后的回收函数;逆序执行,单个抛错不影响其余
|
|
86
|
+
*/
|
|
87
|
+
export declare function combineDisposers(...disposers: (Disposer | undefined)[]): Disposer;
|
|
88
|
+
//# sourceMappingURL=dispose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispose.d.ts","sourceRoot":"","sources":["../../src/util/dispose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEhD,kBAAkB;AAClB,MAAM,WAAW,cAAc;IAC7B,aAAa;IACb,KAAK,EAAE,MAAM,CAAA;IACb,YAAY;IACZ,KAAK,EAAE,OAAO,CAAA;CACf;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;;IAQ3B;;OAEG;gBACS,KAAK,EAAE,MAAM;IAIzB,YAAY;IACZ,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,iBAAiB;IACjB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;;;OAQG;IACH,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,SAAc,GAAG,QAAQ;IAmBrD;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,EAAE,UAAU,EAAE;QAAE,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAA;KAAE,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,SAAU,GAAG,QAAQ;IAIvF;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,SAAU,GAAG,QAAQ;IAK1D;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB;IAMtC;;;;;;OAMG;IACH,OAAO,IAAI,cAAc,EAAE;CA2B5B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,SAAS,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC,EAAE,GAAG,QAAQ,CAUjF"}
|