dsh-my-guardian 0.3.1 → 0.3.2
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 +10 -0
- package/README.md +12 -15
- package/lib/api.js +41 -28
- package/lib/client.js +893 -221
- package/lib/client.src.js +1 -0
- package/lib/events.js +5 -1
- package/lib/index.js +22 -15
- package/lib/mount.js +14 -2
- package/lib/parts/apply.part.js +24 -20
- package/lib/parts/row.part.js +160 -37
- package/lib/parts/styles.part.js +138 -27
- package/lib/parts/util.part.js +117 -53
- package/lib/parts/view.part.js +176 -78
- package/lib/state.js +3 -3
- package/package.json +3 -2
- package/lib/fence.js +0 -57
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.2] - 2026-08-28
|
|
9
|
+
|
|
10
|
+
### 变更
|
|
11
|
+
|
|
12
|
+
- feat(ui): dsh-my-guardian 插件治理面板翻新——开关/图标/日志层级(issue #54)
|
|
13
|
+
- refactor(shared): 抽取 dsh-shared 共享工具包,10 个插件迁移消除重复实现(issue #45)
|
|
14
|
+
- chore(deps): 升级 react 19 兼容性——13 个插件 peer 声明 ^18.2.0 || ^19.2.0(issue #49)
|
|
15
|
+
- style(format): 全仓 prettier 格式化(issue #44)
|
|
16
|
+
- fix(ci): 并行化后的两个失败——Syntax check 对无 lib 的插件(dsh-plugin-dev-mode)用 if 结构;guardian waitFor 超时 3s→10s(并行环境更稳)
|
|
17
|
+
|
|
8
18
|
## [0.3.1] - 2026-08-27
|
|
9
19
|
|
|
10
20
|
### 变更
|
package/README.md
CHANGED
|
@@ -31,7 +31,6 @@ cordis.staged.json(候选区)
|
|
|
31
31
|
|
|
32
32
|
> 💡 **npm 安装(普通用户推荐)**:`dsh plugin --profile web add dsh-my-guardian`——无需克隆本仓库;以下 link 方式供本仓库开发者使用。
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
### 方式一:dsh plugin(推荐)
|
|
36
35
|
|
|
37
36
|
```sh
|
|
@@ -64,9 +63,7 @@ dsh plugin --profile web add link:<仓库路径>/plugins/dsh-my-guardian
|
|
|
64
63
|
新建 `~/.dsh/profiles/web/cordis.staged.json`(与 `cordis.patch.yml` 同目录):
|
|
65
64
|
|
|
66
65
|
```json
|
|
67
|
-
[
|
|
68
|
-
{ "id": "my-plugin", "name": "dsh-my-plugin", "config": { "option": 1 } }
|
|
69
|
-
]
|
|
66
|
+
[{ "id": "my-plugin", "name": "dsh-my-plugin", "config": { "option": 1 } }]
|
|
70
67
|
```
|
|
71
68
|
|
|
72
69
|
- `id`:唯一标识(不能与现有插件行 id 冲突)
|
|
@@ -79,12 +76,12 @@ dsh plugin --profile web add link:<仓库路径>/plugins/dsh-my-guardian
|
|
|
79
76
|
|
|
80
77
|
侧边栏 → "插件守护"页签:
|
|
81
78
|
|
|
82
|
-
| 状态
|
|
83
|
-
|
|
84
|
-
| 运行中
|
|
85
|
-
| 待加载
|
|
86
|
-
| 失败 ×N | 挂载失败 N 次
|
|
87
|
-
| 冻结
|
|
79
|
+
| 状态 | 含义 | 操作 |
|
|
80
|
+
| ------- | ---------------------- | ---------------------- |
|
|
81
|
+
| 运行中 | 已挂载 | 移除 |
|
|
82
|
+
| 待加载 | 尚未处理(安全模式等) | — |
|
|
83
|
+
| 失败 ×N | 挂载失败 N 次 | 重试 / 移除 |
|
|
84
|
+
| 冻结 | 连续失败 3 次 | 重试(解除冻结)/ 移除 |
|
|
88
85
|
|
|
89
86
|
### 效果截图(真实 DSH 实例验证)
|
|
90
87
|
|
|
@@ -110,12 +107,12 @@ dsh plugin --profile web add link:<仓库路径>/plugins/dsh-my-guardian
|
|
|
110
107
|
|
|
111
108
|
## 依赖
|
|
112
109
|
|
|
113
|
-
| 依赖
|
|
114
|
-
|
|
115
|
-
| `cordis`
|
|
110
|
+
| 依赖 | 用途 | 可选 |
|
|
111
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------- | -------------- |
|
|
112
|
+
| `cordis` | 插件运行时 | 是(宿主提供) |
|
|
116
113
|
| `dsh-better-sidebar` | 侧边栏「插件守护」诊断面板(**可选增强,不参与依赖声明**:未安装时自动跳过面板注册,API / 候选区治理不受影响) | 否(可选增强) |
|
|
117
|
-
| `react`
|
|
118
|
-
| `dsh-my-notify`
|
|
114
|
+
| `react` | client 端组件 | 是(宿主提供) |
|
|
115
|
+
| `dsh-my-notify` | 失败 / 冻结事件浏览器通知 | 是 |
|
|
119
116
|
|
|
120
117
|
## 相关文档
|
|
121
118
|
|
package/lib/api.js
CHANGED
|
@@ -4,23 +4,7 @@
|
|
|
4
4
|
* appears), trust fence, method dispatch and the panel snapshot.
|
|
5
5
|
*/
|
|
6
6
|
import { readStagedFile, writeStagedFile } from './state.js'
|
|
7
|
-
import { isTrustedApiRequest } from '
|
|
8
|
-
|
|
9
|
-
function writeJson(response, status, value) {
|
|
10
|
-
const payload = JSON.stringify(value)
|
|
11
|
-
response.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-cache' })
|
|
12
|
-
response.end(payload)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async function readJsonBody(request) {
|
|
16
|
-
let body = ''
|
|
17
|
-
for await (const chunk of request) {
|
|
18
|
-
body += chunk
|
|
19
|
-
if (body.length > 1_000_000) throw new Error('request body too large')
|
|
20
|
-
}
|
|
21
|
-
if (body === '') return {}
|
|
22
|
-
return JSON.parse(body)
|
|
23
|
-
}
|
|
7
|
+
import { isTrustedApiRequest, readJsonBody, writeJson } from 'dsh-shared'
|
|
24
8
|
|
|
25
9
|
/** Bind the API entry points to one guardian instance's shared state. */
|
|
26
10
|
export function createApi(ctx, shared) {
|
|
@@ -41,15 +25,21 @@ function ensureApi(ctx, shared) {
|
|
|
41
25
|
const webRuntime = ctx.get('webRuntime')
|
|
42
26
|
shared.apiRegistered = true
|
|
43
27
|
try {
|
|
44
|
-
ctx.effect(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
28
|
+
ctx.effect(
|
|
29
|
+
() =>
|
|
30
|
+
webServer.register({
|
|
31
|
+
kind: 'prefix',
|
|
32
|
+
path: '/guardian/api',
|
|
33
|
+
handler: (request, response) => handleApiRequest(ctx, shared, webRuntime, request, response),
|
|
34
|
+
}),
|
|
35
|
+
'dsh-my-guardian: /guardian/api routes',
|
|
36
|
+
)
|
|
49
37
|
} catch (error) {
|
|
50
38
|
// registration failed: allow a later poll tick to retry
|
|
51
39
|
shared.apiRegistered = false
|
|
52
|
-
ctx.logger?.warn(
|
|
40
|
+
ctx.logger?.warn(
|
|
41
|
+
`[dsh-my-guardian] api registration failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
42
|
+
)
|
|
53
43
|
}
|
|
54
44
|
}
|
|
55
45
|
|
|
@@ -64,7 +54,10 @@ async function handleApiRequest(ctx, shared, webRuntime, request, response) {
|
|
|
64
54
|
try {
|
|
65
55
|
await dispatchApiMethod(ctx, shared, method, request, response)
|
|
66
56
|
} catch (error) {
|
|
67
|
-
writeJson(response, 400, {
|
|
57
|
+
writeJson(response, 400, {
|
|
58
|
+
ok: false,
|
|
59
|
+
error: { message: error instanceof Error ? error.message : String(error) },
|
|
60
|
+
})
|
|
68
61
|
}
|
|
69
62
|
}
|
|
70
63
|
|
|
@@ -112,7 +105,10 @@ async function handleStagedPost(ctx, shared, request, response) {
|
|
|
112
105
|
}
|
|
113
106
|
const entries = await readStagedFile(shared.stagedFile)
|
|
114
107
|
if (entries.some((item) => item?.id === id)) {
|
|
115
|
-
writeJson(response, 409, {
|
|
108
|
+
writeJson(response, 409, {
|
|
109
|
+
ok: false,
|
|
110
|
+
error: { message: `"${id}" already in the staged file` },
|
|
111
|
+
})
|
|
116
112
|
return
|
|
117
113
|
}
|
|
118
114
|
entries.push({ id, name, ...(payload.config !== undefined ? { config: payload.config } : {}) })
|
|
@@ -170,7 +166,13 @@ function snapshot(shared) {
|
|
|
170
166
|
frozen: record.frozen,
|
|
171
167
|
lastError: record.lastError,
|
|
172
168
|
lastFailedAt: record.lastFailedAt,
|
|
173
|
-
status: shared.mounted.has(id)
|
|
169
|
+
status: shared.mounted.has(id)
|
|
170
|
+
? 'running'
|
|
171
|
+
: record.frozen
|
|
172
|
+
? 'frozen'
|
|
173
|
+
: record.attempts > 0
|
|
174
|
+
? 'failed'
|
|
175
|
+
: 'pending',
|
|
174
176
|
})
|
|
175
177
|
}
|
|
176
178
|
const promotedList = []
|
|
@@ -183,8 +185,19 @@ function snapshot(shared) {
|
|
|
183
185
|
lastError: record.lastError,
|
|
184
186
|
lastFailedAt: record.lastFailedAt,
|
|
185
187
|
promotedAt: record.promotedAt,
|
|
186
|
-
status: shared.mounted.has(id)
|
|
188
|
+
status: shared.mounted.has(id)
|
|
189
|
+
? 'running'
|
|
190
|
+
: record.frozen
|
|
191
|
+
? 'frozen'
|
|
192
|
+
: record.attempts > 0
|
|
193
|
+
? 'failed'
|
|
194
|
+
: 'pending',
|
|
187
195
|
})
|
|
188
196
|
}
|
|
189
|
-
return {
|
|
197
|
+
return {
|
|
198
|
+
safeMode: shared.state.safeMode,
|
|
199
|
+
staged: stagedList,
|
|
200
|
+
promoted: promotedList,
|
|
201
|
+
events: shared.state.events.slice(-10),
|
|
202
|
+
}
|
|
190
203
|
}
|