@hyzyn/dsh-safe 0.13.0 → 0.13.1
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/repair.js +52 -0
- package/package.json +1 -1
package/lib/repair.js
CHANGED
|
@@ -164,6 +164,36 @@ export async function cmdRepair(args, { spawn = spawnSync, log = err, write = ou
|
|
|
164
164
|
const e = restored[0]
|
|
165
165
|
write(`[dsh-safe] ${t('restored')} ${e.name ?? e.id} (id: ${e.id})`)
|
|
166
166
|
}
|
|
167
|
+
|
|
168
|
+
// 防复发:修复的插件若同时被多个 bundle 挂载(如聚合包已内置同一插件),
|
|
169
|
+
// 恢复后下次启动会 duplicate——自动去重(交互选择保留来源,-y 保留先声明者)
|
|
170
|
+
const knownAfter = collectKnownRows(profile)
|
|
171
|
+
const sources = bundleMountSources(knownAfter, opts.id)
|
|
172
|
+
if (sources.length >= 2) {
|
|
173
|
+
const manifest = readJsonIfExists(profileManifestPath(profile))
|
|
174
|
+
const declared = manifest?.dsh?.profile?.bundles
|
|
175
|
+
const ordered = Array.isArray(declared)
|
|
176
|
+
? [...sources].sort(
|
|
177
|
+
(a, b) =>
|
|
178
|
+
(declared.indexOf(a) < 0 ? 999 : declared.indexOf(a)) - (declared.indexOf(b) < 0 ? 999 : declared.indexOf(b)),
|
|
179
|
+
)
|
|
180
|
+
: sources
|
|
181
|
+
let keep = ordered[0]
|
|
182
|
+
if (!opts.yes) {
|
|
183
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr })
|
|
184
|
+
log(t('repairDedupePick', { id: opts.id }))
|
|
185
|
+
ordered.forEach((b, i) => log(`${i + 1}. ${b}${i === 0 ? t('repairDedupeDefault') : ''}`))
|
|
186
|
+
const answer = await rl.question(t('repairDedupeChoose'))
|
|
187
|
+
rl.close()
|
|
188
|
+
const pick = Math.min(Math.max(parseInt(answer, 10) || 1, 1), ordered.length)
|
|
189
|
+
keep = ordered[pick - 1]
|
|
190
|
+
}
|
|
191
|
+
const removed = ordered.filter((b) => b !== keep)
|
|
192
|
+
if (removeFromManifestBundles(profile, removed)) {
|
|
193
|
+
log(t('repairDedupeDone', { removed: removed.join(', '), keep }))
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
167
197
|
log(t('repairDone'))
|
|
168
198
|
return 0
|
|
169
199
|
}
|
|
@@ -193,6 +223,28 @@ const readJsonIfExists = (path) => {
|
|
|
193
223
|
}
|
|
194
224
|
}
|
|
195
225
|
|
|
226
|
+
/** 该 id 的 bundle 挂载来源(profile/home 层是 override,不算挂载来源)。 */
|
|
227
|
+
function bundleMountSources(known, id) {
|
|
228
|
+
return [
|
|
229
|
+
...new Set(
|
|
230
|
+
known.rows.filter((r) => r.id === id && r.source !== 'profile' && r.source !== 'home').map((r) => r.source),
|
|
231
|
+
),
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** 从 profile 清单的 bundles 数组移除指定来源;没有变化返回 false。 */
|
|
236
|
+
function removeFromManifestBundles(profile, removeNames) {
|
|
237
|
+
const manifestPath = profileManifestPath(profile)
|
|
238
|
+
const manifest = readJsonIfExists(manifestPath)
|
|
239
|
+
const current = manifest?.dsh?.profile?.bundles
|
|
240
|
+
if (!Array.isArray(current)) return false
|
|
241
|
+
const next = current.filter((b) => !removeNames.includes(b))
|
|
242
|
+
if (next.length === current.length) return false
|
|
243
|
+
manifest.dsh.profile.bundles = next
|
|
244
|
+
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`)
|
|
245
|
+
return true
|
|
246
|
+
}
|
|
247
|
+
|
|
196
248
|
/**
|
|
197
249
|
* duplicate 类的自动去重:同一 id 被多个 bundle 挂载时,从 profile 清单的
|
|
198
250
|
* bundles 数组移除一个来源(保留的来源继续提供插件),并摘除无效的禁用行。
|