@shellraining/dsh-plugin-updates 0.1.0 → 0.1.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/README.md +9 -6
- package/lib/client.js +132 -171
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dsh-plugin-updates
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
检查从 npm 安装的插件有没有新版本。插件页的「已安装插件」列表里可以逐个更新或全部更新,插件详情页里还能挑一个版本安装。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -11,22 +11,25 @@ dsh plugin --profile web add @shellraining/dsh-plugin-updates
|
|
|
11
11
|
## 使用
|
|
12
12
|
|
|
13
13
|
- **已安装插件列表**:有新版本时,「已安装插件」标题旁出现「全部更新(N)」,对应插件卡片的开关左边出现「更新到 x.y.z」。点卡片其他位置照常进入详情页。
|
|
14
|
-
- **更新标签**:打开侧栏的「插件」,切到「更新」,列出所有从 npm 安装的插件,以及当前版本、最新版本和检查状态。点插件名或「详情」会打开官方的插件详情页。
|
|
15
14
|
- **插件详情页**:有新版本时,标题旁显示「可更新」标签,右上角多一个「更新到 x.y.z」按钮。页面底部有版本列表,每个版本都能单独安装,不兼容当前 DSH 的版本不能点。
|
|
16
15
|
|
|
17
16
|
只检查依赖记录为 `包名@版本范围` 的插件。Git、本地目录、tarball 来源的插件和 DSH 官方插件都会跳过。
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
打开插件页或详情页时检查一次,结果缓存 10 分钟,过期后再打开会重新查询。查询直接从浏览器读 npm registry,用的是 profile 中 pnpm 配置的源,查不到时再试插件管理器配置的备选源(默认是 npmmirror)。需要认证的私有源无法检查。
|
|
20
19
|
|
|
21
20
|
## 更新是怎么做的
|
|
22
21
|
|
|
23
22
|
插件不改 profile 文件,所有改动都调用宿主插件管理器的接口:先卸载旧版本,再安装 `包名@版本`,用精确版本号保存,并保留原来的启用状态。版本兼容检查、构建脚本审批和锁文件回滚都由宿主处理。
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
操作前会重新读取安装状态,已经是目标版本时跳过;精确版本声明与实际安装版本不一致时,会停止更新,提示先修复安装。卸载失败后不会继续安装,也不会断言安装状态完全没变。
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
卸载后安装失败时,已安装列表下方会保留完整错误、日志路径和「恢复」按钮,按原来的版本重新安装;恢复失败后可以再次重试。只有确认卸载成功后才提供恢复,不会覆盖随后通过其他入口安装的版本。错误摘要优先显示错误行,不会把 pnpm 开头的成功检查信息当成失败原因。
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
发布不足 24 小时的版本会标为「新发布」,pnpm 开启 `minimumReleaseAge` 时,这类版本可能装不上。如果出现 `ERR_PNPM_RESOLUTION_POLICY_VIOLATIONS_UNHANDLED`,说明 pnpm 的策略处理发生内部错误,不代表供应链校验通过就能继续安装;插件会停止操作并保留日志,不会关闭安全策略。
|
|
29
|
+
|
|
30
|
+
本插件不能在页面里更新自己,因为卸载自己时界面也会一起卸载。有新版本时,它的详情页会给出对应的 `dsh plugin` 命令,退出 DSH 后在终端运行即可。
|
|
31
|
+
|
|
32
|
+
官方列表没有给卡片开放扩展点,列表上的按钮靠 `data-plugin-group="bundles"`、`data-plugin-package` 和开关的 `role="switch"` 这几个语义属性定位,见 `src/client/anchors.ts`。DSH 改了这部分结构时,列表上的按钮会消失,详情页不受影响。
|
|
30
33
|
|
|
31
34
|
## 开发
|
|
32
35
|
|
package/lib/client.js
CHANGED
|
@@ -1265,29 +1265,14 @@ module.exports = __toCommonJS(index_exports);
|
|
|
1265
1265
|
// src/client/locale.ts
|
|
1266
1266
|
var LOCALE_NS = "dshPluginUpdates";
|
|
1267
1267
|
var ZH = {
|
|
1268
|
-
"tab": "\u66F4\u65B0",
|
|
1269
|
-
"summary.loading": "\u6B63\u5728\u68C0\u67E5\u66F4\u65B0\u2026",
|
|
1270
|
-
"summary.some": "{count} \u4E2A\u63D2\u4EF6\u53EF\u66F4\u65B0",
|
|
1271
|
-
"summary.none": "\u6240\u6709 npm \u63D2\u4EF6\u90FD\u5DF2\u662F\u6700\u65B0\u7248\u672C",
|
|
1272
|
-
"summary.empty": "\u6CA1\u6709\u4ECE npm \u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
1273
|
-
"summary.skipped": "{count} \u4E2A\u63D2\u4EF6\u4E0D\u662F\u4ECE npm \u5B89\u88C5\u7684\uFF0C\u672A\u68C0\u67E5",
|
|
1274
|
-
"refresh": "\u68C0\u67E5\u66F4\u65B0",
|
|
1275
|
-
"updateAll": "\u5168\u90E8\u66F4\u65B0",
|
|
1276
1268
|
"updateAllCount": "\u5168\u90E8\u66F4\u65B0\uFF08{count}\uFF09",
|
|
1277
1269
|
"updateLabel": "\u628A {name} \u66F4\u65B0\u5230 {version}",
|
|
1278
1270
|
"updating": "\u66F4\u65B0\u4E2D\u2026",
|
|
1279
|
-
"update": "\u66F4\u65B0",
|
|
1280
1271
|
"updateTo": "\u66F4\u65B0\u5230 {version}",
|
|
1281
1272
|
"install": "\u5B89\u88C5",
|
|
1282
|
-
"details": "\u8BE6\u60C5",
|
|
1283
|
-
"loadFailed": "\u8BFB\u53D6\u63D2\u4EF6\u5217\u8868\u5931\u8D25\uFF1A{reason}",
|
|
1284
|
-
"retry": "\u91CD\u8BD5",
|
|
1285
1273
|
"status.update": "\u53EF\u66F4\u65B0 {version}",
|
|
1286
|
-
"
|
|
1287
|
-
"status.checking": "\u68C0\u67E5\u4E2D",
|
|
1288
|
-
"status.failed": "\u67E5\u8BE2\u5931\u8D25",
|
|
1274
|
+
"versions.loading": "\u6B63\u5728\u8BFB\u53D6\u7248\u672C\u2026",
|
|
1289
1275
|
"version.current": "\u5F53\u524D {version}",
|
|
1290
|
-
"version.arrow": "{from} \u2192 {to}",
|
|
1291
1276
|
"versions.title": "\u7248\u672C",
|
|
1292
1277
|
"versions.registry": "\u6765\u81EA {registry}",
|
|
1293
1278
|
"versions.showAll": "\u663E\u793A\u5168\u90E8 {count} \u4E2A\u7248\u672C",
|
|
@@ -1304,41 +1289,32 @@ var ZH = {
|
|
|
1304
1289
|
"self.body": "\u5728\u9875\u9762\u91CC\u5378\u8F7D\u81EA\u5DF1\u4F1A\u8BA9\u8FD9\u4E2A\u754C\u9762\u4E00\u8D77\u6D88\u5931\u3002\u8BF7\u5148\u5B8C\u5168\u9000\u51FA DSH\uFF0C\u5728\u7EC8\u7AEF\u8FD0\u884C\u4E0B\u9762\u7684\u547D\u4EE4\uFF0C\u518D\u91CD\u65B0\u6253\u5F00\uFF1A",
|
|
1305
1290
|
"self.copy": "\u590D\u5236\u547D\u4EE4",
|
|
1306
1291
|
"self.copied": "\u5DF2\u590D\u5236",
|
|
1292
|
+
"error.policy": "pnpm \u5904\u7406 minimumReleaseAge \u65F6\u53D1\u751F\u5185\u90E8\u9519\u8BEF\u3002\u8BF7\u5347\u7EA7\u5BBF\u4E3B\u9644\u5E26\u7684 pnpm\uFF0C\u6216\u7B49\u53D1\u5E03\u7B49\u5F85\u671F\u7ED3\u675F\u540E\u91CD\u8BD5\uFF1B\u5B8C\u6574\u9519\u8BEF\u89C1\u4E0B\u65B9\u65E5\u5FD7",
|
|
1293
|
+
"error.inconsistent": "\u5B89\u88C5\u58F0\u660E\u4E0E\u5B9E\u9645\u7248\u672C\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u5148\u7528\u5BBF\u4E3B\u63D2\u4EF6\u7BA1\u7406\u5668\u6216 CLI \u4FEE\u590D\u5B89\u88C5\uFF0C\u518D\u91CD\u8BD5\u66F4\u65B0",
|
|
1294
|
+
"error.stateChanged": "\u63D2\u4EF6\u5B89\u88C5\u72B6\u6001\u5DF2\u53D8\u5316\uFF0C\u8BF7\u5237\u65B0\u63D2\u4EF6\u5217\u8868\u540E\u91CD\u8BD5",
|
|
1295
|
+
"op.checking": "\u6B63\u5728\u6838\u5BF9 {name} \u7684\u5B89\u88C5\u72B6\u6001\u2026",
|
|
1296
|
+
"op.checkFailed": "\u65E0\u6CD5\u786E\u8BA4 {name} \u7684\u5B89\u88C5\u72B6\u6001\uFF0C\u5DF2\u505C\u6B62\u64CD\u4F5C\uFF1A{reason}",
|
|
1297
|
+
"op.current": "{name} \u5DF2\u662F {to}\uFF0C\u65E0\u9700\u91CD\u590D\u5B89\u88C5",
|
|
1307
1298
|
"op.removing": "\u6B63\u5728\u5378\u8F7D {name} {from}\u2026",
|
|
1308
1299
|
"op.installing": "\u6B63\u5728\u5B89\u88C5 {name} {to}\u2026",
|
|
1309
1300
|
"op.restoring": "\u6B63\u5728\u6062\u590D {name} {to}\u2026",
|
|
1310
1301
|
"op.done": "{name} \u5DF2\u5207\u6362\u5230 {to}",
|
|
1311
1302
|
"op.restart": "{name} \u5DF2\u5207\u6362\u5230 {to}\uFF0C\u91CD\u542F DSH \u540E\u751F\u6548",
|
|
1312
1303
|
"op.failed": "{name} \u5B89\u88C5 {to} \u5931\u8D25\uFF1A{reason}",
|
|
1313
|
-
"op.removeFailed": "{name} \u5378\u8F7D\
|
|
1304
|
+
"op.removeFailed": "{name} \u5378\u8F7D\u672A\u5B8C\u6210\uFF0C\u5DF2\u505C\u6B62\u540E\u7EED\u5B89\u88C5\uFF1A{reason}",
|
|
1314
1305
|
"op.restore": "\u6062\u590D {from}",
|
|
1315
1306
|
"op.dismiss": "\u5173\u95ED",
|
|
1316
1307
|
"op.log": "\u65E5\u5FD7\uFF1A{path}"
|
|
1317
1308
|
};
|
|
1318
1309
|
var EN = {
|
|
1319
|
-
"tab": "Updates",
|
|
1320
|
-
"summary.loading": "Checking for updates\u2026",
|
|
1321
|
-
"summary.some": "{count} plugin(s) can be updated",
|
|
1322
|
-
"summary.none": "All npm plugins are up to date",
|
|
1323
|
-
"summary.empty": "No plugins were installed from npm",
|
|
1324
|
-
"summary.skipped": "{count} plugin(s) not installed from npm were skipped",
|
|
1325
|
-
"refresh": "Check for updates",
|
|
1326
|
-
"updateAll": "Update all",
|
|
1327
1310
|
"updateAllCount": "Update all ({count})",
|
|
1328
1311
|
"updateLabel": "Update {name} to {version}",
|
|
1329
1312
|
"updating": "Updating\u2026",
|
|
1330
|
-
"update": "Update",
|
|
1331
1313
|
"updateTo": "Update to {version}",
|
|
1332
1314
|
"install": "Install",
|
|
1333
|
-
"details": "Details",
|
|
1334
|
-
"loadFailed": "Could not read the plugin list: {reason}",
|
|
1335
|
-
"retry": "Retry",
|
|
1336
1315
|
"status.update": "Update {version}",
|
|
1337
|
-
"
|
|
1338
|
-
"status.checking": "Checking",
|
|
1339
|
-
"status.failed": "Check failed",
|
|
1316
|
+
"versions.loading": "Reading versions\u2026",
|
|
1340
1317
|
"version.current": "Current {version}",
|
|
1341
|
-
"version.arrow": "{from} \u2192 {to}",
|
|
1342
1318
|
"versions.title": "Versions",
|
|
1343
1319
|
"versions.registry": "From {registry}",
|
|
1344
1320
|
"versions.showAll": "Show all {count} versions",
|
|
@@ -1355,13 +1331,19 @@ var EN = {
|
|
|
1355
1331
|
"self.body": "Uninstalling it from the page would unload this page too. Quit DSH completely, run this command in a terminal, then start DSH again:",
|
|
1356
1332
|
"self.copy": "Copy command",
|
|
1357
1333
|
"self.copied": "Copied",
|
|
1334
|
+
"error.policy": "pnpm hit an internal error while handling minimumReleaseAge. Upgrade the pnpm bundled with the host, or retry after the release-age waiting period; see the full error below",
|
|
1335
|
+
"error.inconsistent": "The declared and installed versions differ. Repair the installation with the host plugin manager or CLI before retrying",
|
|
1336
|
+
"error.stateChanged": "The installed state has changed. Refresh the plugin list and retry",
|
|
1337
|
+
"op.checking": "Checking the installed version of {name}\u2026",
|
|
1338
|
+
"op.checkFailed": "Could not confirm the installed state of {name}; stopped: {reason}",
|
|
1339
|
+
"op.current": "{name} is already at {to}; no reinstall needed",
|
|
1358
1340
|
"op.removing": "Uninstalling {name} {from}\u2026",
|
|
1359
1341
|
"op.installing": "Installing {name} {to}\u2026",
|
|
1360
1342
|
"op.restoring": "Restoring {name} {to}\u2026",
|
|
1361
1343
|
"op.done": "{name} is now at {to}",
|
|
1362
1344
|
"op.restart": "{name} is now at {to}; restart DSH to apply it",
|
|
1363
1345
|
"op.failed": "Could not install {name} {to}: {reason}",
|
|
1364
|
-
"op.removeFailed": "
|
|
1346
|
+
"op.removeFailed": "Uninstalling {name} did not finish; installation was not started: {reason}",
|
|
1365
1347
|
"op.restore": "Restore {from}",
|
|
1366
1348
|
"op.dismiss": "Dismiss",
|
|
1367
1349
|
"op.log": "Log: {path}"
|
|
@@ -1384,7 +1366,7 @@ function updateTarget(candidate, lookup) {
|
|
|
1384
1366
|
return best !== void 0 && (0, import_gt.default)(best.version, candidate.version) ? best.version : void 0;
|
|
1385
1367
|
}
|
|
1386
1368
|
function isBusy(operation) {
|
|
1387
|
-
return operation?.phase === "removing" || operation?.phase === "installing";
|
|
1369
|
+
return operation?.phase === "checking" || operation?.phase === "removing" || operation?.phase === "installing";
|
|
1388
1370
|
}
|
|
1389
1371
|
function record(value) {
|
|
1390
1372
|
return typeof value === "object" && value !== null ? value : {};
|
|
@@ -1392,6 +1374,14 @@ function record(value) {
|
|
|
1392
1374
|
function errorText(error) {
|
|
1393
1375
|
return error instanceof Error ? error.message : String(error);
|
|
1394
1376
|
}
|
|
1377
|
+
function failureReason(result) {
|
|
1378
|
+
if (!result.ok) return result.error.message;
|
|
1379
|
+
const { error, packageResult, application } = result.value;
|
|
1380
|
+
const diagnostic = error?.diagnostic?.trim();
|
|
1381
|
+
const lines = (diagnostic || packageResult?.output || "").split("\n").map((line) => line.trim()).filter(Boolean);
|
|
1382
|
+
const failure = lines.find((line) => /\bERR[_!\s]|\berror\b|\bfatal\b/i.test(line));
|
|
1383
|
+
return failure ?? error?.code ?? diagnostic ?? application;
|
|
1384
|
+
}
|
|
1395
1385
|
function npmInstalled(bundle) {
|
|
1396
1386
|
const prefix = `${bundle.name}@`;
|
|
1397
1387
|
return bundle.installed && !bundle.official && bundle.availability === "profile" && bundle.removable && bundle.readOnlyReason === void 0 && (0, import_valid.default)(bundle.version ?? "") !== null && bundle.source?.startsWith(prefix) === true && (0, import_valid2.default)(bundle.source.slice(prefix.length)) !== null;
|
|
@@ -1416,7 +1406,7 @@ var UpdatesStore = class {
|
|
|
1416
1406
|
this.ctx = ctx;
|
|
1417
1407
|
}
|
|
1418
1408
|
ctx;
|
|
1419
|
-
state = { status: "idle", candidates: [],
|
|
1409
|
+
state = { status: "idle", candidates: [], lookups: {} };
|
|
1420
1410
|
listeners = /* @__PURE__ */ new Set();
|
|
1421
1411
|
generation = 0;
|
|
1422
1412
|
disposed = false;
|
|
@@ -1441,25 +1431,28 @@ var UpdatesStore = class {
|
|
|
1441
1431
|
setLookup(name2, lookup) {
|
|
1442
1432
|
this.patch({ lookups: { ...this.state.lookups, [name2]: lookup } });
|
|
1443
1433
|
}
|
|
1444
|
-
/** A page opened: read the list the first time, and
|
|
1434
|
+
/** A page opened: read the list the first time, after a failure, and once a lookup is older than the cache. */
|
|
1445
1435
|
ensure = () => {
|
|
1446
1436
|
const now = Date.now();
|
|
1447
1437
|
const stale = Object.values(this.state.lookups).some((lookup) => lookup.status === "ready" && now - lookup.at > CACHE_MS);
|
|
1448
|
-
if (this.state.status === "idle" || this.state.status === "ready" && stale) void this.load(
|
|
1449
|
-
};
|
|
1450
|
-
/** Re-read the list and every lookup. */
|
|
1451
|
-
refresh = () => {
|
|
1452
|
-
void this.load(true);
|
|
1438
|
+
if (this.state.status === "idle" || this.state.status === "error" || this.state.status === "ready" && stale) void this.load();
|
|
1453
1439
|
};
|
|
1454
1440
|
/** Re-read the list after a Host change; lookups stay cached. */
|
|
1455
1441
|
bundlesChanged = () => {
|
|
1456
|
-
if (this.state.status !== "idle") void this.load(
|
|
1442
|
+
if (this.state.status !== "idle") void this.load();
|
|
1457
1443
|
};
|
|
1458
|
-
async load(
|
|
1444
|
+
async load() {
|
|
1445
|
+
try {
|
|
1446
|
+
await this.loadBundles();
|
|
1447
|
+
} catch {
|
|
1448
|
+
if (!this.disposed) this.patch({ status: "error" });
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
async loadBundles() {
|
|
1459
1452
|
const generation = ++this.generation;
|
|
1460
1453
|
this.patch({ status: this.state.status === "ready" ? "ready" : "loading" });
|
|
1461
1454
|
const pm = this.ctx.remote.pluginManager;
|
|
1462
|
-
if (
|
|
1455
|
+
if (this.registries === void 0) {
|
|
1463
1456
|
const [registries, exemptions] = await Promise.all([pm.registries(), pm.listVersionExemptions()]);
|
|
1464
1457
|
if (registries.ok) {
|
|
1465
1458
|
const first = registries.value.registry ?? registries.value.resolved ?? DEFAULT_REGISTRY;
|
|
@@ -1470,7 +1463,7 @@ var UpdatesStore = class {
|
|
|
1470
1463
|
const listed = await pm.listBundles();
|
|
1471
1464
|
if (generation !== this.generation) return;
|
|
1472
1465
|
if (!listed.ok) {
|
|
1473
|
-
this.patch({ status: "error"
|
|
1466
|
+
this.patch({ status: "error" });
|
|
1474
1467
|
return;
|
|
1475
1468
|
}
|
|
1476
1469
|
const resolve = (text) => text === void 0 ? void 0 : this.ctx.locale.resolveText(text);
|
|
@@ -1485,13 +1478,12 @@ var UpdatesStore = class {
|
|
|
1485
1478
|
...icon === void 0 ? {} : { icon }
|
|
1486
1479
|
};
|
|
1487
1480
|
}).sort((a, b) => a.title.localeCompare(b.title));
|
|
1488
|
-
|
|
1489
|
-
this.patch({ status: "ready", candidates, skipped: others.length - npm.length });
|
|
1481
|
+
this.patch({ status: "ready", candidates });
|
|
1490
1482
|
const now = Date.now();
|
|
1491
1483
|
for (const candidate of candidates) {
|
|
1492
1484
|
const lookup = this.state.lookups[candidate.name];
|
|
1493
1485
|
const stale = lookup === void 0 || lookup.status === "error" || lookup.status === "ready" && now - lookup.at > CACHE_MS;
|
|
1494
|
-
if (
|
|
1486
|
+
if (stale) void this.lookup(candidate.name);
|
|
1495
1487
|
}
|
|
1496
1488
|
}
|
|
1497
1489
|
async lookup(name2) {
|
|
@@ -1530,14 +1522,14 @@ var UpdatesStore = class {
|
|
|
1530
1522
|
/** Switch one plugin to `version`: uninstall it, then install that exact version with its enabled state. */
|
|
1531
1523
|
install = async (name2, version) => {
|
|
1532
1524
|
const candidate = this.state.candidates.find((item) => item.name === name2);
|
|
1533
|
-
if (candidate === void 0 || name2 === SELF || isBusy(this.state.operation)) return false;
|
|
1525
|
+
if (this.disposed || candidate === void 0 || name2 === SELF || isBusy(this.state.operation) || (0, import_valid.default)(version) === null) return false;
|
|
1534
1526
|
return this.run({ name: name2, from: candidate.version, to: version, enabled: candidate.enabled, restoring: false }, true);
|
|
1535
1527
|
};
|
|
1536
1528
|
/** Put back the version a failed switch removed; the plugin is no longer installed, so only install. */
|
|
1537
1529
|
restore = async () => {
|
|
1538
1530
|
const failed = this.state.operation;
|
|
1539
|
-
if (failed?.phase !== "failed" || failed.
|
|
1540
|
-
await this.run({ name: failed.name, from: failed.
|
|
1531
|
+
if (this.disposed || failed?.phase !== "failed" || !failed.recoverable) return;
|
|
1532
|
+
await this.run({ name: failed.name, from: failed.from, to: failed.from, enabled: failed.enabled, restoring: true }, false);
|
|
1541
1533
|
};
|
|
1542
1534
|
/** The outcome toast finished; the banner in the tab keeps the result. */
|
|
1543
1535
|
toastDone = () => {
|
|
@@ -1560,57 +1552,86 @@ var UpdatesStore = class {
|
|
|
1560
1552
|
};
|
|
1561
1553
|
async run(base, remove) {
|
|
1562
1554
|
const pm = this.ctx.remote.pluginManager;
|
|
1563
|
-
|
|
1555
|
+
let failurePhase = "check-failed";
|
|
1556
|
+
let recoverable = false;
|
|
1557
|
+
const fail = (result) => {
|
|
1564
1558
|
const value = result.ok ? result.value : void 0;
|
|
1565
|
-
const output = value?.packageResult?.output.trim();
|
|
1559
|
+
const output = value?.packageResult?.output.trim() || value?.error?.diagnostic;
|
|
1566
1560
|
const logPath = value?.packageResult?.logPath;
|
|
1567
|
-
|
|
1568
|
-
|
|
1561
|
+
this.patch({ operation: {
|
|
1562
|
+
...base,
|
|
1563
|
+
phase: failurePhase,
|
|
1564
|
+
recoverable,
|
|
1565
|
+
reason: failureReason(result),
|
|
1566
|
+
toast: Date.now(),
|
|
1567
|
+
...output ? { output } : {},
|
|
1568
|
+
...logPath ? { logPath } : {}
|
|
1569
|
+
} });
|
|
1569
1570
|
return false;
|
|
1570
1571
|
};
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
const
|
|
1574
|
-
|
|
1575
|
-
if (!
|
|
1576
|
-
|
|
1572
|
+
this.patch({ operation: { ...base, phase: "checking" } });
|
|
1573
|
+
try {
|
|
1574
|
+
const listed = await pm.listBundles();
|
|
1575
|
+
if (this.disposed) return false;
|
|
1576
|
+
if (!listed.ok) return fail(listed);
|
|
1577
|
+
const current = listed.value.find((bundle) => bundle.name === base.name && bundle.installed);
|
|
1578
|
+
if (current !== void 0 && (0, import_valid.default)(current.version ?? "") === (0, import_valid.default)(base.to)) {
|
|
1579
|
+
this.patch({ operation: { ...base, phase: "current", toast: Date.now() } });
|
|
1580
|
+
return true;
|
|
1577
1581
|
}
|
|
1582
|
+
if (remove) {
|
|
1583
|
+
if (current === void 0 || !npmInstalled(current)) {
|
|
1584
|
+
return fail({ ok: true, value: { application: "failed", error: { code: "plugin-state-changed" } } });
|
|
1585
|
+
}
|
|
1586
|
+
const declared = (0, import_valid.default)(current.source?.slice(`${base.name}@`.length) ?? "");
|
|
1587
|
+
if (declared !== null && declared !== (0, import_valid.default)(current.version ?? "")) {
|
|
1588
|
+
return fail({ ok: true, value: { application: "failed", error: { code: "installation-inconsistent" } } });
|
|
1589
|
+
}
|
|
1590
|
+
base = { ...base, from: current.version ?? base.from, enabled: current.enabled };
|
|
1591
|
+
failurePhase = "remove-failed";
|
|
1592
|
+
this.patch({ operation: { ...base, phase: "removing" } });
|
|
1593
|
+
const removed = await pm.removeBundle(base.name);
|
|
1594
|
+
const stopProfile = removed.ok && removed.value.error?.code === "stop-profile";
|
|
1595
|
+
if (!stopProfile && (!removed.ok || removed.value.application === "failed" || removed.value.application === "cancelled")) {
|
|
1596
|
+
return fail(removed);
|
|
1597
|
+
}
|
|
1598
|
+
recoverable = !stopProfile;
|
|
1599
|
+
} else {
|
|
1600
|
+
if (current !== void 0) {
|
|
1601
|
+
return fail({ ok: true, value: { application: "failed", error: { code: "plugin-state-changed" } } });
|
|
1602
|
+
}
|
|
1603
|
+
recoverable = true;
|
|
1604
|
+
}
|
|
1605
|
+
if (this.disposed) return false;
|
|
1606
|
+
failurePhase = "failed";
|
|
1607
|
+
this.patch({ operation: { ...base, phase: "installing" } });
|
|
1608
|
+
const installed = await pm.installBundle(`${base.name}@${base.to}`, {
|
|
1609
|
+
enabled: base.enabled,
|
|
1610
|
+
saveExact: true,
|
|
1611
|
+
requestId: `${SELF}:${Date.now()}`
|
|
1612
|
+
});
|
|
1613
|
+
if (!installed.ok || installed.value.application === "failed" || installed.value.application === "cancelled") {
|
|
1614
|
+
return fail(installed);
|
|
1615
|
+
}
|
|
1616
|
+
const to = installed.value.version ?? base.to;
|
|
1617
|
+
this.patch({ operation: { ...base, to, toast: Date.now(), phase: installed.value.application === "restart-required" ? "restart" : "done" } });
|
|
1618
|
+
return true;
|
|
1619
|
+
} catch (error) {
|
|
1620
|
+
return fail({ ok: false, error: { message: errorText(error) } });
|
|
1621
|
+
} finally {
|
|
1622
|
+
if (!this.disposed) await this.load();
|
|
1578
1623
|
}
|
|
1579
|
-
this.patch({ operation: { ...base, phase: "installing" } });
|
|
1580
|
-
const installed = await pm.installBundle(`${base.name}@${base.to}`, {
|
|
1581
|
-
enabled: base.enabled,
|
|
1582
|
-
saveExact: true,
|
|
1583
|
-
requestId: `${SELF}:${Date.now()}`
|
|
1584
|
-
});
|
|
1585
|
-
if (!installed.ok || installed.value.application === "failed" || installed.value.application === "cancelled") {
|
|
1586
|
-
return fail("failed", installed);
|
|
1587
|
-
}
|
|
1588
|
-
const to = installed.value.version ?? base.to;
|
|
1589
|
-
this.patch({ operation: { ...base, to, toast: Date.now(), phase: installed.value.application === "restart-required" ? "restart" : "done" } });
|
|
1590
|
-
return true;
|
|
1591
1624
|
}
|
|
1592
1625
|
};
|
|
1593
1626
|
|
|
1594
1627
|
// src/client/styles.ts
|
|
1595
1628
|
var STYLE_ID = "@shellraining/dsh-plugin-updates";
|
|
1596
1629
|
var CSS = `
|
|
1597
|
-
.dpu-
|
|
1630
|
+
.dpu-section { display: flex; flex-direction: column; gap: 12px; min-width: 0; color: var(--dsw-alias-label-primary); }
|
|
1598
1631
|
.dpu-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; min-height: 28px; }
|
|
1599
1632
|
.dpu-summary { flex: 1; min-width: 0; color: var(--dsw-alias-label-secondary); font-size: 13px; line-height: 20px; }
|
|
1600
1633
|
.dpu-caption { color: var(--dsw-alias-label-caption); font-size: 12px; line-height: 18px; }
|
|
1601
1634
|
.dpu-title { margin: 0; font-size: 14px; font-weight: 500; line-height: 20px; }
|
|
1602
|
-
.dpu-list { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
|
|
1603
|
-
.dpu-card { display: flex; align-items: center; gap: 14px; min-width: 0; margin: 0 -8px; padding: 8px; border-radius: var(--dsw-radius-xl); }
|
|
1604
|
-
.dpu-card:hover { background: var(--dsw-alias-interactive-bg-hover); }
|
|
1605
|
-
.dpu-icon { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; overflow: hidden; border: .5px solid var(--dsw-alias-border-l3); border-radius: var(--dsw-radius-lg); color: var(--dsw-alias-label-secondary); }
|
|
1606
|
-
.dpu-icon img { width: 100%; height: 100%; object-fit: cover; }
|
|
1607
|
-
.dpu-main { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
1608
|
-
.dpu-name-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; min-width: 0; }
|
|
1609
|
-
.dpu-name { min-width: 0; padding: 0; overflow: hidden; border: 0; background: none; color: inherit; font: inherit; font-size: 14px; font-weight: 500; line-height: 20px; text-align: left; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
|
|
1610
|
-
.dpu-name:hover { text-decoration: underline; }
|
|
1611
|
-
.dpu-name:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: 2px; }
|
|
1612
|
-
.dpu-meta { color: var(--dsw-alias-label-tertiary); font-size: 13px; line-height: 18px; font-variant-numeric: tabular-nums; }
|
|
1613
|
-
.dpu-end { flex: none; display: inline-flex; align-items: center; gap: 8px; }
|
|
1614
1635
|
.dpu-mono { font-family: var(--ds-font-family-code); font-variant-numeric: tabular-nums; }
|
|
1615
1636
|
.dpu-rows { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; border-top: .5px solid var(--dsw-alias-border-l2); }
|
|
1616
1637
|
.dpu-row { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 2px 0; border-bottom: .5px solid var(--dsw-alias-border-l2); }
|
|
@@ -1665,10 +1686,11 @@ function scan(document2) {
|
|
|
1665
1686
|
const end = card.querySelector('[role="switch"]')?.parentElement;
|
|
1666
1687
|
if (name2 && end) cards.set(name2, mountIn(end, "card", true));
|
|
1667
1688
|
}
|
|
1668
|
-
|
|
1689
|
+
const status = mountIn(group, "status", false);
|
|
1690
|
+
return { ...head === void 0 ? {} : { head }, status, cards };
|
|
1669
1691
|
}
|
|
1670
1692
|
function same(a, b) {
|
|
1671
|
-
if (a.head !== b.head || a.cards.size !== b.cards.size) return false;
|
|
1693
|
+
if (a.head !== b.head || a.status !== b.status || a.cards.size !== b.cards.size) return false;
|
|
1672
1694
|
for (const [name2, node] of a.cards) if (b.cards.get(name2) !== node) return false;
|
|
1673
1695
|
return true;
|
|
1674
1696
|
}
|
|
@@ -1707,16 +1729,6 @@ function selfCommand(version) {
|
|
|
1707
1729
|
function dateText(stamp) {
|
|
1708
1730
|
return stamp === void 0 ? "" : new Date(stamp).toLocaleDateString();
|
|
1709
1731
|
}
|
|
1710
|
-
function Artwork({ src }) {
|
|
1711
|
-
const [broken, setBroken] = (0, import_react.useState)(false);
|
|
1712
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-icon", "aria-hidden": "true", children: src === void 0 || broken ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.PluginArtworkDefault, { size: 28 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src, alt: "", onError: () => setBroken(true) }) });
|
|
1713
|
-
}
|
|
1714
|
-
function StatusTag({ t, candidate, lookup }) {
|
|
1715
|
-
if (lookup === void 0 || lookup.status === "loading") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "quiet", children: t("status.checking") });
|
|
1716
|
-
if (lookup.status === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "warning", children: t("status.failed") });
|
|
1717
|
-
const target = updateTarget(candidate, lookup);
|
|
1718
|
-
return target === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "quiet", children: t("status.latest") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "info", children: t("status.update", { version: target }) });
|
|
1719
|
-
}
|
|
1720
1732
|
function SelfNotice({ t, version }) {
|
|
1721
1733
|
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
1722
1734
|
const command = selfCommand(version);
|
|
@@ -1732,8 +1744,16 @@ function SelfNotice({ t, version }) {
|
|
|
1732
1744
|
] });
|
|
1733
1745
|
}
|
|
1734
1746
|
function operationText(t, operation) {
|
|
1735
|
-
const
|
|
1747
|
+
const raw = operation.reason ?? "";
|
|
1748
|
+
const reason = raw.includes("ERR_PNPM_RESOLUTION_POLICY_VIOLATIONS_UNHANDLED") ? t("error.policy") : raw === "installation-inconsistent" ? t("error.inconsistent") : raw === "plugin-state-changed" ? t("error.stateChanged") : raw;
|
|
1749
|
+
const params = { name: operation.name, from: operation.from, to: operation.to, reason };
|
|
1736
1750
|
switch (operation.phase) {
|
|
1751
|
+
case "checking":
|
|
1752
|
+
return t("op.checking", params);
|
|
1753
|
+
case "check-failed":
|
|
1754
|
+
return t("op.checkFailed", params);
|
|
1755
|
+
case "current":
|
|
1756
|
+
return t("op.current", params);
|
|
1737
1757
|
case "removing":
|
|
1738
1758
|
return t("op.removing", params);
|
|
1739
1759
|
case "installing":
|
|
@@ -1751,8 +1771,8 @@ function operationText(t, operation) {
|
|
|
1751
1771
|
function OperationToast({ t, useUpdates, actions }) {
|
|
1752
1772
|
const operation = useUpdates((state) => state.operation);
|
|
1753
1773
|
if (operation?.toast === void 0) return null;
|
|
1754
|
-
const failed = operation.phase === "failed" || operation.phase === "remove-failed";
|
|
1755
|
-
const restorable = operation.phase === "failed" &&
|
|
1774
|
+
const failed = operation.phase === "failed" || operation.phase === "remove-failed" || operation.phase === "check-failed";
|
|
1775
|
+
const restorable = operation.phase === "failed" && operation.recoverable;
|
|
1756
1776
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1757
1777
|
import_dsh_client_ui_primitives.Toast,
|
|
1758
1778
|
{
|
|
@@ -1770,12 +1790,12 @@ function OperationToast({ t, useUpdates, actions }) {
|
|
|
1770
1790
|
function OperationBanner({ t, operation, actions }) {
|
|
1771
1791
|
const params = { from: operation.from };
|
|
1772
1792
|
const busy = isBusy(operation);
|
|
1773
|
-
const failed = operation.phase === "failed" || operation.phase === "remove-failed";
|
|
1793
|
+
const failed = operation.phase === "failed" || operation.phase === "remove-failed" || operation.phase === "check-failed";
|
|
1774
1794
|
const text = operationText(t, operation);
|
|
1775
1795
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dpu-banner", role: failed ? "alert" : "status", ...failed ? { "data-tone": "error" } : {}, children: [
|
|
1776
1796
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dpu-banner-row", children: [
|
|
1777
1797
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: text }),
|
|
1778
|
-
operation.phase === "failed" &&
|
|
1798
|
+
operation.phase === "failed" && operation.recoverable ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", onClick: () => {
|
|
1779
1799
|
void actions.restore();
|
|
1780
1800
|
}, children: t("op.restore", params) }) : null,
|
|
1781
1801
|
busy ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "ghost", onClick: actions.dismiss, children: t("op.dismiss") })
|
|
@@ -1784,63 +1804,6 @@ function OperationBanner({ t, operation, actions }) {
|
|
|
1784
1804
|
failed && operation.logPath !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-caption", children: t("op.log", { path: operation.logPath }) }) : null
|
|
1785
1805
|
] });
|
|
1786
1806
|
}
|
|
1787
|
-
function UpdatesTab({ t, useUpdates, actions, openPackage }) {
|
|
1788
|
-
const state = useUpdates((snapshot) => snapshot);
|
|
1789
|
-
(0, import_react.useEffect)(() => {
|
|
1790
|
-
actions.ensure();
|
|
1791
|
-
}, [actions]);
|
|
1792
|
-
const busy = isBusy(state.operation);
|
|
1793
|
-
const lookups = Object.values(state.lookups);
|
|
1794
|
-
const checking = state.status === "loading" || lookups.some((lookup) => lookup.status === "loading");
|
|
1795
|
-
const outdated = state.candidates.filter((item) => updateTarget(item, state.lookups[item.name]) !== void 0);
|
|
1796
|
-
const pending = outdated.filter((item) => item.name !== SELF);
|
|
1797
|
-
const self = outdated.find((item) => item.name === SELF);
|
|
1798
|
-
const selfTarget = self === void 0 ? void 0 : updateTarget(self, state.lookups[SELF]);
|
|
1799
|
-
let summary;
|
|
1800
|
-
if (state.status === "idle" || state.status === "loading" && state.candidates.length === 0) summary = t("summary.loading");
|
|
1801
|
-
else if (state.candidates.length === 0) summary = t("summary.empty");
|
|
1802
|
-
else if (outdated.length > 0) summary = t("summary.some", { count: outdated.length });
|
|
1803
|
-
else summary = checking ? t("summary.loading") : t("summary.none");
|
|
1804
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "dpu-tab", "aria-busy": checking, children: [
|
|
1805
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dpu-head", children: [
|
|
1806
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-summary", role: "status", children: summary }),
|
|
1807
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives2.IconRefreshOutlineRegular, { size: 13 }), disabled: checking || busy, onClick: actions.refresh, children: t("refresh") }),
|
|
1808
|
-
pending.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "primary", disabled: busy, onClick: () => {
|
|
1809
|
-
void actions.updateAll();
|
|
1810
|
-
}, children: t("updateAll") }) : null
|
|
1811
|
-
] }),
|
|
1812
|
-
state.operation === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OperationBanner, { t, operation: state.operation, actions }),
|
|
1813
|
-
state.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dpu-banner", "data-tone": "error", role: "alert", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dpu-banner-row", children: [
|
|
1814
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("loadFailed", { reason: state.error ?? "" }) }),
|
|
1815
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", onClick: actions.refresh, children: t("retry") })
|
|
1816
|
-
] }) }) : null,
|
|
1817
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "dpu-list", children: state.candidates.map((candidate) => {
|
|
1818
|
-
const lookup = state.lookups[candidate.name];
|
|
1819
|
-
const target = updateTarget(candidate, lookup);
|
|
1820
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "dpu-card", "data-plugin-updates-package": candidate.name, children: [
|
|
1821
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Artwork, { src: candidate.icon }),
|
|
1822
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dpu-main", children: [
|
|
1823
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dpu-name-row", children: [
|
|
1824
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "dpu-name", title: candidate.name, onClick: () => openPackage(candidate.name), children: candidate.title }),
|
|
1825
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusTag, { t, candidate, lookup })
|
|
1826
|
-
] }),
|
|
1827
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dpu-meta", children: [
|
|
1828
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-mono", children: target === void 0 ? candidate.version : t("version.arrow", { from: candidate.version, to: target }) }),
|
|
1829
|
-
lookup?.status === "error" ? ` \xB7 ${lookup.reason}` : ""
|
|
1830
|
-
] })
|
|
1831
|
-
] }),
|
|
1832
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dpu-end", children: [
|
|
1833
|
-
target !== void 0 && candidate.name !== SELF ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives2.IconDownloadOutlineRegular, { size: 13 }), disabled: busy, onClick: () => {
|
|
1834
|
-
void actions.install(candidate.name, target);
|
|
1835
|
-
}, children: t("update") }) : null,
|
|
1836
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "ghost", onClick: () => openPackage(candidate.name), children: t("details") })
|
|
1837
|
-
] })
|
|
1838
|
-
] }, candidate.name);
|
|
1839
|
-
}) }),
|
|
1840
|
-
state.skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-caption", children: t("summary.skipped", { count: state.skipped }) }) : null,
|
|
1841
|
-
selfTarget === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelfNotice, { t, version: selfTarget })
|
|
1842
|
-
] });
|
|
1843
|
-
}
|
|
1844
1807
|
function useSubject({ subject, useUpdates, actions }) {
|
|
1845
1808
|
const name2 = subject.kind === "bundle" ? subject.pkg.name : void 0;
|
|
1846
1809
|
const candidate = useUpdates((state) => state.candidates.find((item) => item.name === name2));
|
|
@@ -1888,7 +1851,7 @@ function DetailSection(props) {
|
|
|
1888
1851
|
const self = candidate.name === SELF;
|
|
1889
1852
|
const target = updateTarget(candidate, lookup);
|
|
1890
1853
|
let body;
|
|
1891
|
-
if (lookup === void 0 || lookup.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-caption", children: t("
|
|
1854
|
+
if (lookup === void 0 || lookup.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-caption", children: t("versions.loading") });
|
|
1892
1855
|
else if (lookup.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-error", children: t("versions.failed", { reason: lookup.reason }) });
|
|
1893
1856
|
else if (lookup.versions.length === 0) body = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dpu-caption", children: t("versions.empty") });
|
|
1894
1857
|
else {
|
|
@@ -1940,6 +1903,13 @@ function ListControls({ t, useUpdates, actions }) {
|
|
|
1940
1903
|
if (target !== void 0 && candidate.name !== SELF) targets.set(candidate.name, target);
|
|
1941
1904
|
}
|
|
1942
1905
|
const portals = [];
|
|
1906
|
+
if (anchors.status !== void 0 && operation !== void 0) {
|
|
1907
|
+
portals.push((0, import_react_dom.createPortal)(
|
|
1908
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(OperationBanner, { t, operation, actions }),
|
|
1909
|
+
anchors.status,
|
|
1910
|
+
"operation"
|
|
1911
|
+
));
|
|
1912
|
+
}
|
|
1943
1913
|
if (anchors.head !== void 0 && targets.size > 0) {
|
|
1944
1914
|
portals.push((0, import_react_dom.createPortal)(
|
|
1945
1915
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives2.IconDownloadOutlineRegular, { size: 13 }), disabled: busy, onClick: () => {
|
|
@@ -1983,7 +1953,6 @@ function apply(ctx) {
|
|
|
1983
1953
|
hooks: { updates: store },
|
|
1984
1954
|
actions: {
|
|
1985
1955
|
ensure: store.ensure,
|
|
1986
|
-
refresh: store.refresh,
|
|
1987
1956
|
install: store.install,
|
|
1988
1957
|
updateAll: store.updateAll,
|
|
1989
1958
|
restore: store.restore,
|
|
@@ -1991,14 +1960,6 @@ function apply(ctx) {
|
|
|
1991
1960
|
toastDone: store.toastDone
|
|
1992
1961
|
}
|
|
1993
1962
|
};
|
|
1994
|
-
ctx.slots.inject("plugins.tab", () => ctx.slots.register({
|
|
1995
|
-
name: "plugins.tab",
|
|
1996
|
-
id: "updates",
|
|
1997
|
-
order: 10,
|
|
1998
|
-
label: () => t("tab"),
|
|
1999
|
-
locale: LOCALE_NS,
|
|
2000
|
-
inject: () => face
|
|
2001
|
-
}, UpdatesTab));
|
|
2002
1963
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
2003
1964
|
name: "shell.overlay",
|
|
2004
1965
|
id: "plugin-updates.toast",
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shellraining/dsh-plugin-updates",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "在插件页检查 npm 来源插件的新版本,一键更新或安装指定版本",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./lib/index.js",
|
|
@@ -14,10 +14,6 @@
|
|
|
14
14
|
"lib",
|
|
15
15
|
"cordis.patch.yml"
|
|
16
16
|
],
|
|
17
|
-
"scripts": {
|
|
18
|
-
"typecheck": "tsc -p tsconfig.json",
|
|
19
|
-
"build": "pnpm run typecheck && node build.mjs"
|
|
20
|
-
},
|
|
21
17
|
"engines": {
|
|
22
18
|
"node": ">=20"
|
|
23
19
|
},
|
|
@@ -59,5 +55,9 @@
|
|
|
59
55
|
],
|
|
60
56
|
"publishConfig": {
|
|
61
57
|
"access": "public"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
61
|
+
"build": "pnpm run typecheck && node build.mjs"
|
|
62
62
|
}
|
|
63
|
-
}
|
|
63
|
+
}
|