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 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
- | 冻结 | 连续失败 3 次 | 重试(解除冻结)/ 移除 |
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` | client 端组件 | 是(宿主提供) |
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 './fence.js'
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(() => webServer.register({
45
- kind: 'prefix',
46
- path: '/guardian/api',
47
- handler: (request, response) => handleApiRequest(ctx, shared, webRuntime, request, response),
48
- }), 'dsh-my-guardian: /guardian/api routes')
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(`[dsh-my-guardian] api registration failed: ${error instanceof Error ? error.message : String(error)}`)
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, { ok: false, error: { message: error instanceof Error ? error.message : String(error) } })
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, { ok: false, error: { message: `"${id}" already in the staged file` } })
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) ? 'running' : record.frozen ? 'frozen' : record.attempts > 0 ? 'failed' : 'pending',
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) ? 'running' : record.frozen ? 'frozen' : record.attempts > 0 ? 'failed' : 'pending',
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 { safeMode: shared.state.safeMode, staged: stagedList, promoted: promotedList, events: shared.state.events.slice(-10) }
197
+ return {
198
+ safeMode: shared.state.safeMode,
199
+ staged: stagedList,
200
+ promoted: promotedList,
201
+ events: shared.state.events.slice(-10),
202
+ }
190
203
  }