dsh-mobile-plugin 0.1.59 → 0.1.61
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/lib/index.js +35 -30
- package/lib/panel/index.html +1 -1
- package/lib/routes/control-plane.js +112 -15
- package/lib/shell/updater.js +68 -8
- package/lib/update-install.cjs +311 -0
- package/lib/update-registry.cjs +142 -0
- package/package.json +4 -2
package/lib/index.js
CHANGED
|
@@ -15,11 +15,16 @@
|
|
|
15
15
|
* 这一层同时是**故障边界**:代装载失败时外壳回滚到上一代并把错误暴露出去,而不是让整个
|
|
16
16
|
* 插件从宿主里消失(那会让手机连不上,且日志里只剩一行 pending)。
|
|
17
17
|
*
|
|
18
|
-
* ## 更新从哪儿来(2026-10
|
|
18
|
+
* ## 更新从哪儿来(2026-10 改,2026-10-11 再分一刀)
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* **查与装都归实现自己**:查直接问 npm 注册表、装在 profile 里跑它自己的包管理器
|
|
21
|
+
* (`lib/update-registry.cjs` / `lib/update-install.cjs`),市场不再是这条路上的任何一环。
|
|
22
|
+
* 装完会把 `<profile>/node_modules/dsh-mobile-plugin` 指向一个新的 store 目录,外壳照着新
|
|
23
|
+
* realpath 重新 import 一代即可,**不需要重启 DSH**。自动更新(默认关)按 `AUTO_INTERVAL_MS`
|
|
24
|
+
* 轮询,见 `shell/updater.js`。
|
|
25
|
+
*
|
|
26
|
+
* 这里那个 `updateState` 对象记的是「最近一次查/装的结果」。名字里别再叫 market:里面那份
|
|
27
|
+
* 市场信息(`marketResult`)只是外壳从市场那条老路继承下来的兜底,装的时候用不到它。
|
|
23
28
|
*/
|
|
24
29
|
|
|
25
30
|
import path from 'node:path'
|
|
@@ -32,7 +37,7 @@ export const name = 'dsh-mobile-plugin'
|
|
|
32
37
|
export const inject = ['webServer', 'sessions']
|
|
33
38
|
|
|
34
39
|
/**
|
|
35
|
-
*
|
|
40
|
+
* 装载当前代,并把「查 / 装 / 换代码」这套动作暴露成服务。
|
|
36
41
|
*
|
|
37
42
|
* 对照 `lib/impl.js` 的 `apply`:那边签名也是 `(ctx)`,只是它注册的是真正的移动 API;
|
|
38
43
|
* 这里注册的是「装载它」。两者的 effect 各自归属自己那层 fiber —— 外壳被卸载时,代的
|
|
@@ -42,7 +47,7 @@ export function apply(ctx) {
|
|
|
42
47
|
const runtime = createRuntime()
|
|
43
48
|
// 跑着的外壳的指纹。它必须在**启动时**算:之后盘上那份可能已经被市场换掉了。
|
|
44
49
|
const runningShellHash = updater.shellFingerprint(path.dirname(path.dirname(fileURLToPath(import.meta.url))))
|
|
45
|
-
const
|
|
50
|
+
const updateState = {
|
|
46
51
|
checking: false,
|
|
47
52
|
lastCheckedAt: null,
|
|
48
53
|
lastError: null,
|
|
@@ -58,25 +63,25 @@ export function apply(ctx) {
|
|
|
58
63
|
|
|
59
64
|
/** 查一次有没有新版。只记结果,装不装由开关或人来决定。 */
|
|
60
65
|
async function check({ force = false } = {}) {
|
|
61
|
-
if (
|
|
62
|
-
|
|
66
|
+
if (updateState.checking) return updateState.result
|
|
67
|
+
updateState.checking = true
|
|
63
68
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
updateState.result = await updater.checkUpdate(base())
|
|
70
|
+
updateState.lastError = null
|
|
66
71
|
} catch (error) {
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
updateState.result = null
|
|
73
|
+
updateState.lastError = String(error?.message || error)
|
|
69
74
|
} finally {
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
updateState.checking = false
|
|
76
|
+
updateState.lastCheckedAt = new Date().toISOString()
|
|
72
77
|
}
|
|
73
|
-
return
|
|
78
|
+
return updateState.result
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
/**
|
|
77
|
-
*
|
|
82
|
+
* 装新版(实现自己装,见 `shell/updater.js`),装完**就地换代**。
|
|
78
83
|
*
|
|
79
|
-
*
|
|
84
|
+
* 手动与自动走的是同一条路:手动只是「现在就做一次」。装的那一步报的 `restartRequired` 一律
|
|
80
85
|
* 不照做 —— 外壳自己换代码,这正是这个文件存在的全部理由。
|
|
81
86
|
*/
|
|
82
87
|
async function applyUpdate({ force = false } = {}) {
|
|
@@ -90,9 +95,9 @@ export function apply(ctx) {
|
|
|
90
95
|
} else if (outcome.state && outcome.state !== 'succeeded') {
|
|
91
96
|
log('warn', 'dsh-mobile-plugin: 更新没有成功(%s)%s', outcome.state, outcome.failure?.message || '')
|
|
92
97
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (outcome.installed)
|
|
98
|
+
updateState.lastApply = { ...outcome, swapped }
|
|
99
|
+
updateState.appliedAt = new Date().toISOString()
|
|
100
|
+
if (outcome.installed) updateState.lastError = null
|
|
96
101
|
return { ...outcome, swapped, status }
|
|
97
102
|
}
|
|
98
103
|
|
|
@@ -128,11 +133,11 @@ export function apply(ctx) {
|
|
|
128
133
|
autoUpdate: updater.autoUpdateEnabled(),
|
|
129
134
|
autoIntervalMs: updater.AUTO_INTERVAL_MS,
|
|
130
135
|
marketBase: base(),
|
|
131
|
-
marketLastCheckedAt:
|
|
132
|
-
marketLastError:
|
|
133
|
-
marketResult:
|
|
134
|
-
lastApply:
|
|
135
|
-
appliedAt:
|
|
136
|
+
marketLastCheckedAt: updateState.lastCheckedAt,
|
|
137
|
+
marketLastError: updateState.lastError,
|
|
138
|
+
marketResult: updateState.result,
|
|
139
|
+
lastApply: updateState.lastApply,
|
|
140
|
+
appliedAt: updateState.appliedAt,
|
|
136
141
|
}),
|
|
137
142
|
check,
|
|
138
143
|
apply: applyUpdate,
|
|
@@ -148,12 +153,12 @@ export function apply(ctx) {
|
|
|
148
153
|
.start(ctx)
|
|
149
154
|
.then(() => {
|
|
150
155
|
log('info', 'dsh-mobile-plugin: 已装载 %s(来源 %s)', runtime.status().version, runtime.status().source)
|
|
151
|
-
//
|
|
156
|
+
// 自动更新:默认关。开了才轮询;每次都是「查一次 → 有新版就自己装 → 就地换代」。
|
|
152
157
|
const timer = setInterval(() => {
|
|
153
158
|
if (!updater.autoUpdateEnabled()) return
|
|
154
159
|
applyUpdate().catch(error => {
|
|
155
|
-
|
|
156
|
-
log('warn', 'dsh-mobile-plugin: 自动更新失败:%s',
|
|
160
|
+
updateState.lastError = String(error?.message || error)
|
|
161
|
+
log('warn', 'dsh-mobile-plugin: 自动更新失败:%s', updateState.lastError)
|
|
157
162
|
})
|
|
158
163
|
}, updater.AUTO_INTERVAL_MS)
|
|
159
164
|
if (typeof timer.unref === 'function') timer.unref()
|
|
@@ -162,8 +167,8 @@ export function apply(ctx) {
|
|
|
162
167
|
if (updater.autoUpdateEnabled()) {
|
|
163
168
|
const kick = setTimeout(() => {
|
|
164
169
|
applyUpdate().catch(error => {
|
|
165
|
-
|
|
166
|
-
log('warn', 'dsh-mobile-plugin: 启动时的自动更新失败:%s',
|
|
170
|
+
updateState.lastError = String(error?.message || error)
|
|
171
|
+
log('warn', 'dsh-mobile-plugin: 启动时的自动更新失败:%s', updateState.lastError)
|
|
167
172
|
})
|
|
168
173
|
}, 10000)
|
|
169
174
|
if (typeof kick.unref === 'function') kick.unref()
|