@noob-stupid/dsh-plugin-console 0.5.44 → 0.5.45
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.
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// L2 · routes —— 框架(/framework-check · /check-update · /framework-upgrade · /framework-rollback · /framework-upgrade-status · /framework-relaunch · /compat-gate · /restart)
|
|
2
2
|
// 分层 Step 8b:从 lib/index.js 的 handle() 原样搬出(只搬移未改逻辑;缩进保持原样)
|
|
3
3
|
|
|
4
|
-
import { readFileSync, writeFileSync, existsSync, statSync, mkdirSync } from 'node:fs'
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, statSync, mkdirSync, rmSync } from 'node:fs'
|
|
5
5
|
import { writeFile } from 'node:fs/promises'
|
|
6
6
|
import { execFile } from 'node:child_process'
|
|
7
|
-
import { dirname, join, resolve } from 'node:path'
|
|
7
|
+
import { dirname, join, resolve, basename } from 'node:path'
|
|
8
8
|
import { tmpdir } from 'node:os'
|
|
9
9
|
import { createRequire } from 'node:module'
|
|
10
10
|
import { readCompatGate, writeCompatGate } from '../domain/compat.js'
|
|
@@ -460,14 +460,56 @@ async function routeRestart(req, res, rc) {
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
/** 清掉「最近一次升级/回滚记录」(2026-09-25 用户要求):记录常驻是设计,但用户要能一键关掉。
|
|
463
|
-
* 只删状态文件与心跳(不动日志,日志仍可在 ~/.dsh/plugin-console 里查)。
|
|
463
|
+
* 只删状态文件与心跳(不动日志,日志仍可在 ~/.dsh/plugin-console 里查)。
|
|
464
|
+
* 2026-10-11 改错:删除失败**如实上报**(500 + 每个文件的原因 + removed/failed 明细),
|
|
465
|
+
* 不再像旧实现那样吞掉异常还回 ok:true —— 静默失败一律不许(见函数内注释与
|
|
466
|
+
* tests/test-framework-status-clear.mjs 的正控/负控)。 */
|
|
467
|
+
/** 删文件失败时给用户看的一句话原因(code + 系统原文,便于判因)。 */
|
|
468
|
+
function explainRemoveError(error) {
|
|
469
|
+
const code = typeof error?.code === 'string' && error.code !== '' ? error.code : 'UNKNOWN'
|
|
470
|
+
const text = (error instanceof Error ? error.message : String(error ?? '')).split('\n')[0].trim()
|
|
471
|
+
return text === '' ? code : `${code}: ${text}`
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/** 删除时文件已不在 = 目标达成(不计失败);其余错误一律算失败。 */
|
|
475
|
+
function removeTargetGone(error) {
|
|
476
|
+
return error?.code === 'ENOENT'
|
|
477
|
+
}
|
|
478
|
+
|
|
464
479
|
async function routeFrameworkStatusClear(req, res, rc) {
|
|
465
480
|
const dir = join(dshHome(), 'plugin-console')
|
|
466
481
|
const state = join(dir, 'fw-upgrade-state.txt')
|
|
482
|
+
const io = rc.deps?.fs ?? { existsSync, rmSync } // 注入缝:负控要能造出真实的删除失败
|
|
467
483
|
const removed = []
|
|
484
|
+
const failed = []
|
|
468
485
|
for (const f of [state, `${state}.hb`]) {
|
|
469
|
-
|
|
486
|
+
let present = false
|
|
487
|
+
try { present = io.existsSync(f) === true } catch (error) { failed.push({ file: basename(f), reason: explainRemoveError(error) }); continue }
|
|
488
|
+
if (!present) continue
|
|
489
|
+
try {
|
|
490
|
+
io.rmSync(f, { force: true })
|
|
491
|
+
removed.push(basename(f))
|
|
492
|
+
} catch (error) {
|
|
493
|
+
// 2026-10-11 改错:这里原来是 `catch {}` + 无条件 ok:true —— 静默失败。
|
|
494
|
+
// 先前的真实现状更糟:rmSync/basename 没 import ⇒ 每轮都抛 ReferenceError、被空 catch 吞掉,
|
|
495
|
+
// 路由照样回 200 {"ok":true,"removed":[]},标记文件一个都没删(用户以为清掉了)。
|
|
496
|
+
// 判据(用户红线):宁可红,也不报假的绿 —— 删除失败必须如实上报原因。
|
|
497
|
+
if (removeTargetGone(error)) { removed.push(basename(f)); continue }
|
|
498
|
+
failed.push({ file: basename(f), reason: explainRemoveError(error) })
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
if (failed.length > 0) {
|
|
502
|
+
// 如实上报:500 + 每个文件的原因 + 与成功路径同形的 removed/status 字段(客户端不必猜)。
|
|
503
|
+
sendJson(res, 500, {
|
|
504
|
+
ok: false,
|
|
505
|
+
error: `清除升级记录失败:${failed.map((x) => `${x.file}(${x.reason})`).join('、')}`,
|
|
506
|
+
removed,
|
|
507
|
+
failed,
|
|
508
|
+
status: 'clear-failed',
|
|
509
|
+
message: null,
|
|
510
|
+
})
|
|
511
|
+
return
|
|
470
512
|
}
|
|
471
|
-
sendJson(res, 200, { ok: true, removed, status: 'idle', message: null })
|
|
513
|
+
sendJson(res, 200, { ok: true, removed, failed, status: 'idle', message: null })
|
|
472
514
|
}
|
|
473
515
|
export { refuseWhenShellHosted, refuseWhenPlatformUnsupported, routeFrameworkStatusClear, routeFrameworkUpgradeStatusGet, routeFrameworkRelaunch, routeFrameworkCheck, routeCompatGate, routeCheckUpdate, routeFrameworkRollback, routeRestart }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noob-stupid/dsh-plugin-console",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.45",
|
|
4
4
|
"description": "DSH 框架升级安全与插件升级门控:一键升级、失败自动回滚、升级后回滚上版、旧插件不适配自动禁用;内置多源插件市场为发现层,插件源全部可自定义,可指向公司内网私有源 / 私有索引 / 本地 Git 仓库,纯内网离线可用 | Framework upgrade safety & plugin version gating for DSH, with a customizable multi-source plugin market: point every source at internal mirrors or a local file:// repo for intranet-only, offline installs.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|