@huaqiu/dsh-tool-plugin-update 0.6.12 → 0.6.16

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.
@@ -132,9 +132,42 @@ export function normalizePluginUpdateItem<T extends PluginUpdateItem>(item: T):
132
132
 
133
133
  /** States that carry an install action (the badge/actionable definition). */
134
134
  function isActionableState(item: PluginUpdateItem): boolean {
135
+ // A muted item carries no action even if an older hq-edge left its state at
136
+ // `update` (it also flags the item, and the whole set, when it can).
137
+ if (item.ignored === true) return false
135
138
  return item.state === 'update' || item.state === 'install'
136
139
  }
137
140
 
141
+ /**
142
+ * How many PLUGIN updates a report makes actionable — the ONE definition the
143
+ * footer bar, the panel's sections and `actionableCount` share, so they can
144
+ * never disagree about how much plugin work is left.
145
+ *
146
+ * Deliberately narrow (spec §6.3/§7.1):
147
+ * - compatible `update` + `install` items only;
148
+ * - nothing once the user has muted the offer (`ignoredSet`), and nothing
149
+ * for an individually-ignored item;
150
+ * - plugin items only. The HQ Edge runtime update is a separate deliverable
151
+ * with its own card, so it is not a plugin item here — the sidebar badge
152
+ * adds it on top, once, in `badge.ts`. Never fold it into this number:
153
+ * that is what made the footer claim "准备安装 N 项兼容插件" one too many.
154
+ *
155
+ * Note what is absent: no durable-job input. The job history is permanent
156
+ * (`listRecent(20)`), so any rule that counts a settled job latches on forever.
157
+ */
158
+ export function actionableUpdateCount(report: PluginUpdateReport | null | undefined): number {
159
+ if (report === null || report === undefined) return 0
160
+ // The whole offered set is muted. An older hq-edge sets this flag but leaves
161
+ // the item states at `update`, so it must be checked before counting.
162
+ if (report.ignoredSet === true) return 0
163
+ if (!Array.isArray(report.items)) return 0
164
+ let count = 0
165
+ for (const item of report.items) {
166
+ if (isActionableState(item)) count += 1
167
+ }
168
+ return count
169
+ }
170
+
138
171
  /**
139
172
  * Apply {@link normalizePluginUpdateItem} to a whole report and recompute
140
173
  * `actionableCount` from the corrected states, so the server's count can
@@ -143,9 +176,9 @@ function isActionableState(item: PluginUpdateItem): boolean {
143
176
  export function normalizePluginUpdateReport<T extends PluginUpdateReport>(report: T): T {
144
177
  if (!Array.isArray(report.items)) return report
145
178
  const items = report.items.map(normalizePluginUpdateItem)
179
+ const next = { ...report, items }
146
180
  return {
147
- ...report,
148
- items,
149
- actionableCount: items.filter(isActionableState).length,
181
+ ...next,
182
+ actionableCount: actionableUpdateCount(next),
150
183
  }
151
184
  }
package/src/routes.ts CHANGED
@@ -16,6 +16,12 @@
16
16
  * POST /plugin-update/install → POST /api/v1/plugin-updates/install {setVersion}
17
17
  * POST /plugin-update/ignore → POST /api/v1/plugin-updates/ignore {setVersion}
18
18
  * POST /plugin-update/unignore → POST /api/v1/plugin-updates/unignore {setVersion}
19
+ * POST /plugin-update/plugin-ignore
20
+ * → POST /api/v1/plugin-updates/plugin-ignore
21
+ * {setVersion, name}
22
+ * POST /plugin-update/plugin-unignore
23
+ * → POST /api/v1/plugin-updates/plugin-unignore
24
+ * {setVersion, name}
19
25
  * GET /plugin-update/runtime → GET /api/v1/runtime-update
20
26
  * POST /plugin-update/runtime-request
21
27
  * → POST /api/v1/runtime-update/request {targetVersion}
@@ -184,6 +190,21 @@ function routeFor(
184
190
  if (sub === '/unignore') {
185
191
  return method === 'POST' ? { method: 'POST', path: '/api/v1/plugin-updates/unignore' } : null
186
192
  }
193
+ // Per-package ignore (the card-level 忽略 / 恢复提醒). hq-edge names these
194
+ // `plugin-ignore` / `plugin-unignore`; the browser half has always called
195
+ // those paths, and while this table did not carry them the forwarder
196
+ // answered 404 — which the caller swallowed, so clicking 忽略 on a card did
197
+ // nothing at all and the count never moved.
198
+ if (sub === '/plugin-ignore') {
199
+ return method === 'POST'
200
+ ? { method: 'POST', path: '/api/v1/plugin-updates/plugin-ignore' }
201
+ : null
202
+ }
203
+ if (sub === '/plugin-unignore') {
204
+ return method === 'POST'
205
+ ? { method: 'POST', path: '/api/v1/plugin-updates/plugin-unignore' }
206
+ : null
207
+ }
187
208
  return null
188
209
  }
189
210
 
@@ -196,6 +217,8 @@ const STATIC_SUB_PATHS = new Set([
196
217
  '/install',
197
218
  '/ignore',
198
219
  '/unignore',
220
+ '/plugin-ignore',
221
+ '/plugin-unignore',
199
222
  '/runtime',
200
223
  '/runtime-request',
201
224
  '/runtime-source',