dsh-plugin-update 0.5.7 → 0.6.0
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/CHANGELOG.md +17 -4
- package/README.md +29 -10
- package/dist/bilingual.d.ts +23 -13
- package/dist/bilingual.js +324 -10
- package/dist/changelog.d.ts +19 -13
- package/dist/changelog.js +60 -22
- package/dist/diag.d.ts +3 -0
- package/dist/diag.js +32 -20
- package/dist/entry-batch.d.ts +22 -5
- package/dist/entry-batch.js +86 -19
- package/dist/entry.d.ts +37 -9
- package/dist/entry.js +105 -51
- package/dist/host-batch.js +104 -13
- package/dist/http.d.ts +2 -2
- package/dist/http.js +1 -1
- package/dist/lang.js +150 -0
- package/dist/panel-batch.d.ts +50 -9
- package/dist/panel-batch.js +484 -150
- package/dist/panel.d.ts +37 -22
- package/dist/panel.js +504 -362
- package/dist/store.d.ts +42 -0
- package/dist/store.js +139 -0
- package/package.json +1 -1
package/dist/changelog.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// AUTO-GENERATED by node build.mjs — DO NOT EDIT. Source: src/changelog.ts
|
|
2
2
|
import { compareReleaseVersions, validReleaseVersion } from "./service.js";
|
|
3
|
+
import { copyText } from "./bilingual.js";
|
|
4
|
+
import { normalizeLangTag } from "./lang.js";
|
|
3
5
|
const CHANGELOG_FILENAME = "CHANGELOG.md";
|
|
4
6
|
const CHANGELOG_NEUTRAL_HINT = "\u4F5C\u8005\u672A\u63D0\u4F9B\u66F4\u65B0\u8BF4\u660E";
|
|
5
7
|
const CHANGELOG_NEUTRAL_LINE = "\u4F5C\u8005\u672A\u63D0\u4F9B\u66F4\u65B0\u8BF4\u660E\uFF0C\u5B89\u88C5\u4E0D\u53D7\u5F71\u54CD\u3002";
|
|
@@ -109,6 +111,18 @@ function isFenceToggle(line) {
|
|
|
109
111
|
}
|
|
110
112
|
}
|
|
111
113
|
const BREAKING_BADGE_TEXT = "\u4E0D\u517C\u5BB9";
|
|
114
|
+
function changelogCategoryLabel(cat, lang) {
|
|
115
|
+
const l = normalizeLangTag(lang ?? "zh");
|
|
116
|
+
const zh = CHANGELOG_CATEGORY_ZH[cat];
|
|
117
|
+
if (l === "en") return cat;
|
|
118
|
+
return zh + "\uFF08" + cat + "\uFF09";
|
|
119
|
+
}
|
|
120
|
+
function changelogFoldedLabel(cat, count, lang) {
|
|
121
|
+
const l = normalizeLangTag(lang ?? "zh");
|
|
122
|
+
const n = String(Math.floor(count));
|
|
123
|
+
if (l === "en") return cat + " (" + n + ")";
|
|
124
|
+
return CHANGELOG_CATEGORY_ZH[cat] + "\uFF08" + cat + "\uFF09\uFF08" + n + "\uFF09";
|
|
125
|
+
}
|
|
112
126
|
function stripBreakingDecorations(s) {
|
|
113
127
|
try {
|
|
114
128
|
let t = String(s !== null && s !== void 0 ? s : "").trim();
|
|
@@ -331,26 +345,31 @@ function countsOf(entry) {
|
|
|
331
345
|
return { Added: 0, Fixed: 0, Changed: 0, Deprecated: 0, Removed: 0, Security: 0 };
|
|
332
346
|
}
|
|
333
347
|
}
|
|
334
|
-
function truncatedNoteHTML(total, shown) {
|
|
348
|
+
function truncatedNoteHTML(total, shown, lang) {
|
|
335
349
|
try {
|
|
350
|
+
const l = normalizeLangTag(lang ?? "zh");
|
|
336
351
|
const m = Math.floor(total);
|
|
337
352
|
const n = Math.floor(shown);
|
|
338
|
-
|
|
353
|
+
const text = copyText("changelog.truncated.count", l, { m: String(m), n: String(n) });
|
|
354
|
+
return '<div class="dsh-upd-changelog-count">' + escapeChangelogHtml(text) + "</div>";
|
|
339
355
|
} catch {
|
|
340
356
|
return "";
|
|
341
357
|
}
|
|
342
358
|
}
|
|
343
|
-
function yankedBannerHTML(version) {
|
|
359
|
+
function yankedBannerHTML(version, lang) {
|
|
344
360
|
try {
|
|
361
|
+
const l = normalizeLangTag(lang ?? "zh");
|
|
345
362
|
const v = typeof version === "string" ? version.trim() : "";
|
|
346
363
|
if (!v) return "";
|
|
347
|
-
|
|
364
|
+
const text = copyText("changelog.yanked.banner", l, { version: v });
|
|
365
|
+
return '<div class="dsh-upd-changelog-yanked" role="alert">' + escapeChangelogHtml(text) + "</div>";
|
|
348
366
|
} catch {
|
|
349
367
|
return "";
|
|
350
368
|
}
|
|
351
369
|
}
|
|
352
|
-
function renderChangelogItem(item) {
|
|
370
|
+
function renderChangelogItem(item, lang) {
|
|
353
371
|
try {
|
|
372
|
+
const l = normalizeLangTag(lang ?? "zh");
|
|
354
373
|
const s = String(item !== null && item !== void 0 ? item : "");
|
|
355
374
|
if (!s) return "";
|
|
356
375
|
const split = splitBreakingPrefix(s);
|
|
@@ -358,22 +377,25 @@ function renderChangelogItem(item) {
|
|
|
358
377
|
const head = escapeChangelogHtml(split.head);
|
|
359
378
|
const prefix = escapeChangelogHtml(split.prefix);
|
|
360
379
|
const rest = escapeChangelogHtml(split.rest);
|
|
361
|
-
const
|
|
380
|
+
const badgeText = copyText("changelog.breaking.badge", l);
|
|
381
|
+
const badgeAria = copyText("changelog.breaking.aria", l);
|
|
382
|
+
const badge = '<span class="dsh-upd-breaking-badge" role="img" aria-label="' + escapeChangelogHtml(badgeAria) + '">' + escapeChangelogHtml(badgeText) + "</span> ";
|
|
362
383
|
return "<li>" + head + badge + "<strong>" + prefix + "</strong>" + rest + "</li>";
|
|
363
384
|
} catch {
|
|
364
385
|
return "";
|
|
365
386
|
}
|
|
366
387
|
}
|
|
367
|
-
function renderChangelogSection(entry) {
|
|
388
|
+
function renderChangelogSection(entry, lang) {
|
|
368
389
|
try {
|
|
369
390
|
if (!entry || typeof entry !== "object") return "";
|
|
370
391
|
const version = String(entry.version !== void 0 && entry.version !== null ? String(entry.version) : "").trim();
|
|
371
392
|
if (!version || isUnreleasedVersion(version)) return "";
|
|
372
393
|
if (!hasVisibleSections(entry)) return "";
|
|
394
|
+
const l = normalizeLangTag(lang ?? "zh");
|
|
373
395
|
const dateRaw = entry.date;
|
|
374
396
|
const date = typeof dateRaw === "string" ? dateRaw : "";
|
|
375
397
|
const yankedFlag = entry.yanked === true;
|
|
376
|
-
const yankedSuffix = yankedFlag ? "
|
|
398
|
+
const yankedSuffix = yankedFlag ? copyText("changelog.yanked.suffix", l) : "";
|
|
377
399
|
const title = (date ? version + " \xB7 " + date : version) + yankedSuffix;
|
|
378
400
|
const counts = countsOf(entry);
|
|
379
401
|
const parts = [];
|
|
@@ -382,42 +404,44 @@ function renderChangelogSection(entry) {
|
|
|
382
404
|
for (const cat of CHANGELOG_MUST_SHOW) {
|
|
383
405
|
const items = Array.isArray(entry.sections ? entry.sections[cat] : null) ? entry.sections[cat] : [];
|
|
384
406
|
if (!items || items.length === 0) continue;
|
|
385
|
-
const label = cat
|
|
407
|
+
const label = changelogCategoryLabel(cat, l);
|
|
386
408
|
parts.push('<div class="dsh-upd-changelog-cat" data-cat="' + cat + '">');
|
|
387
409
|
parts.push('<div class="dsh-upd-changelog-catname">' + escapeChangelogHtml(label) + "</div>");
|
|
388
410
|
const total = counts[cat];
|
|
389
411
|
const shown = items.length;
|
|
390
412
|
if (total > shown) {
|
|
391
|
-
parts.push(truncatedNoteHTML(total, shown));
|
|
413
|
+
parts.push(truncatedNoteHTML(total, shown, l));
|
|
392
414
|
}
|
|
393
415
|
parts.push("<ul>");
|
|
394
416
|
for (const item of items) {
|
|
395
417
|
if (!item) continue;
|
|
396
|
-
const li = renderChangelogItem(item);
|
|
418
|
+
const li = renderChangelogItem(item, l);
|
|
397
419
|
if (li) parts.push(li);
|
|
398
420
|
}
|
|
399
421
|
parts.push("</ul>");
|
|
400
422
|
if (cat === "Security" && total > shown) {
|
|
401
423
|
const restCount = total - shown;
|
|
402
|
-
|
|
424
|
+
const sumText = copyText("changelog.security.summary", l, { n: String(restCount) });
|
|
425
|
+
const noteText = copyText("changelog.security.note", l);
|
|
426
|
+
parts.push('<details class="dsh-upd-changelog-security-more"><summary>' + escapeChangelogHtml(sumText) + '</summary><div class="dsh-upd-changelog-more-note">' + escapeChangelogHtml(noteText) + "</div></details>");
|
|
403
427
|
}
|
|
404
428
|
parts.push("</div>");
|
|
405
429
|
}
|
|
406
430
|
for (const cat of CHANGELOG_FOLDED) {
|
|
407
431
|
const items = Array.isArray(entry.sections ? entry.sections[cat] : null) ? entry.sections[cat] : [];
|
|
408
432
|
if (!items || items.length === 0) continue;
|
|
409
|
-
const label = cat
|
|
433
|
+
const label = changelogFoldedLabel(cat, items.length, l);
|
|
410
434
|
parts.push('<details class="dsh-upd-changelog-fold" data-cat="' + cat + '">');
|
|
411
435
|
parts.push("<summary>" + escapeChangelogHtml(label) + "</summary>");
|
|
412
436
|
const total = counts[cat];
|
|
413
437
|
const shown = items.length;
|
|
414
438
|
if (total > shown) {
|
|
415
|
-
parts.push(truncatedNoteHTML(total, shown));
|
|
439
|
+
parts.push(truncatedNoteHTML(total, shown, l));
|
|
416
440
|
}
|
|
417
441
|
parts.push("<ul>");
|
|
418
442
|
for (const item of items) {
|
|
419
443
|
if (!item) continue;
|
|
420
|
-
const li = renderChangelogItem(item);
|
|
444
|
+
const li = renderChangelogItem(item, l);
|
|
421
445
|
if (li) parts.push(li);
|
|
422
446
|
}
|
|
423
447
|
parts.push("</ul></details>");
|
|
@@ -428,12 +452,19 @@ function renderChangelogSection(entry) {
|
|
|
428
452
|
return "";
|
|
429
453
|
}
|
|
430
454
|
}
|
|
431
|
-
function renderChangelogNeutral() {
|
|
432
|
-
|
|
455
|
+
function renderChangelogNeutral(lang) {
|
|
456
|
+
try {
|
|
457
|
+
const l = normalizeLangTag(lang ?? "zh");
|
|
458
|
+
const text = copyText("changelog.neutral.line", l);
|
|
459
|
+
return `<div class="dsh-upd-changelog-neutral">${escapeChangelogHtml(text)}</div>`;
|
|
460
|
+
} catch {
|
|
461
|
+
return "";
|
|
462
|
+
}
|
|
433
463
|
}
|
|
434
464
|
function renderChangelogHTML(entries, opts) {
|
|
435
465
|
try {
|
|
436
|
-
|
|
466
|
+
const l = normalizeLangTag(opts?.lang ?? "zh");
|
|
467
|
+
if (!Array.isArray(entries) || entries.length === 0) return renderChangelogNeutral(l);
|
|
437
468
|
const from = opts && typeof opts.from === "string" ? opts.from : null;
|
|
438
469
|
const to = opts && typeof opts.to === "string" ? opts.to : null;
|
|
439
470
|
let ranged;
|
|
@@ -449,14 +480,19 @@ function renderChangelogHTML(entries, opts) {
|
|
|
449
480
|
}
|
|
450
481
|
});
|
|
451
482
|
}
|
|
452
|
-
if (ranged.length === 0) return renderChangelogNeutral();
|
|
453
|
-
const blocks = ranged.map((e) => renderChangelogSection(e)).filter((s) => !!s);
|
|
454
|
-
if (blocks.length === 0) return renderChangelogNeutral();
|
|
483
|
+
if (ranged.length === 0) return renderChangelogNeutral(l);
|
|
484
|
+
const blocks = ranged.map((e) => renderChangelogSection(e, l)).filter((s) => !!s);
|
|
485
|
+
if (blocks.length === 0) return renderChangelogNeutral(l);
|
|
455
486
|
return `<div class="dsh-upd-changelog">
|
|
456
487
|
${blocks.join("\n")}
|
|
457
488
|
</div>`;
|
|
458
489
|
} catch {
|
|
459
|
-
|
|
490
|
+
try {
|
|
491
|
+
const ll = normalizeLangTag(opts?.lang ?? "zh");
|
|
492
|
+
return renderChangelogNeutral(ll);
|
|
493
|
+
} catch {
|
|
494
|
+
return "";
|
|
495
|
+
}
|
|
460
496
|
}
|
|
461
497
|
}
|
|
462
498
|
const CHANGELOG_VALIDATE_HINTS = {
|
|
@@ -639,6 +675,8 @@ export {
|
|
|
639
675
|
RE_VERSION_HEADING,
|
|
640
676
|
RE_VERSION_NUM,
|
|
641
677
|
RE_YANKED,
|
|
678
|
+
changelogCategoryLabel,
|
|
679
|
+
changelogFoldedLabel,
|
|
642
680
|
changelogForUpdate,
|
|
643
681
|
countsOf,
|
|
644
682
|
hasVisibleSections,
|
package/dist/diag.d.ts
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
* 构造全程 best-effort:任何一步异常即回 undefined(调用方按无 diag 的旧形状返回,
|
|
32
32
|
* 新面板×旧载荷仍为正常缺省,不抛)。
|
|
33
33
|
*/
|
|
34
|
+
import { type AppLang } from './lang.js';
|
|
34
35
|
/** diag 对象版本:只管大门,新增可选键不 bump,面板永不分支于版本。 */
|
|
35
36
|
export declare const DIAG_VERSION = 1;
|
|
36
37
|
/** 阶段枚举(冻结 6 值,与真实接缝对齐)。 */
|
|
@@ -67,6 +68,8 @@ export interface DiagInput {
|
|
|
67
68
|
environmentKind?: unknown;
|
|
68
69
|
/** 本次电话耗时毫秒(只收有限非负数)。 */
|
|
69
70
|
latencyMs?: unknown;
|
|
71
|
+
/** 人话兜底渲染语言(#66 单语:缺省 zh 零回归;电话侧无 DOM 信号时仍落 zh,面板侧 free-text 英文混入属正常见 #57 v2 非目标)。 */
|
|
72
|
+
lang?: AppLang | string | null;
|
|
70
73
|
}
|
|
71
74
|
export interface DiagObject {
|
|
72
75
|
v: number;
|
package/dist/diag.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// AUTO-GENERATED by node build.mjs — DO NOT EDIT. Source: src/diag.ts
|
|
2
2
|
import { DIAG_INLINE_BUDGET_BYTES, diagByteLength, enforceDiagBudget, resolveRegistryHost, sanitizeDetail } from "./redaction.js";
|
|
3
3
|
import { validReleaseVersion, validRequestId } from "./service.js";
|
|
4
|
+
import { copyText } from "./bilingual.js";
|
|
5
|
+
import { normalizeLangTag } from "./lang.js";
|
|
4
6
|
const DIAG_VERSION = 1;
|
|
5
7
|
const DIAG_STAGES = [
|
|
6
8
|
"read-installed",
|
|
@@ -116,7 +118,7 @@ function pickEnvironmentKind(raw) {
|
|
|
116
118
|
function pickId(raw) {
|
|
117
119
|
return typeof raw === "string" && validRequestId(raw) ? raw.trim() : null;
|
|
118
120
|
}
|
|
119
|
-
function pickDetail(errorCode, error, httpStatus, phoneKind) {
|
|
121
|
+
function pickDetail(errorCode, error, httpStatus, phoneKind, lang) {
|
|
120
122
|
try {
|
|
121
123
|
const rawDetail = error?.detail;
|
|
122
124
|
if (typeof rawDetail === "string" && rawDetail.trim()) {
|
|
@@ -132,24 +134,34 @@ function pickDetail(errorCode, error, httpStatus, phoneKind) {
|
|
|
132
134
|
}
|
|
133
135
|
const code = String(errorCode || "");
|
|
134
136
|
const phone = String(phoneKind || "");
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
else if (code === "check-failed" &&
|
|
140
|
-
else if (code === "check-failed"
|
|
141
|
-
else if (code === "
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
else if (code === "
|
|
145
|
-
else if (code === "
|
|
146
|
-
else if (code === "
|
|
147
|
-
else if (code === "
|
|
148
|
-
else if (code === "
|
|
149
|
-
else if (code === "
|
|
150
|
-
else if (code === "
|
|
151
|
-
else if (code === "
|
|
152
|
-
else if (code === "
|
|
137
|
+
const l = normalizeLangTag(lang ?? "zh");
|
|
138
|
+
let key = "diag.fallback.generic";
|
|
139
|
+
let values;
|
|
140
|
+
if (code === "check-failed" && phone === "update-status") key = "diag.fallback.read-installed";
|
|
141
|
+
else if ((code === "check-failed" || code === "internal") && phone === "update-install") key = "diag.fallback.revalidate-fetch";
|
|
142
|
+
else if (code === "check-failed" && httpStatus === 429) key = "diag.fallback.rate-limited";
|
|
143
|
+
else if (code === "check-failed" && typeof httpStatus === "number") {
|
|
144
|
+
key = "diag.fallback.http-status";
|
|
145
|
+
values = { status: String(httpStatus) };
|
|
146
|
+
} else if (code === "check-failed" || code === "internal") key = "panel.failure.check-failed.title";
|
|
147
|
+
else if (code === "invalid-release") key = "diag.fallback.invalid-release";
|
|
148
|
+
else if (code === "check-expired") key = "panel.failure.check-expired.title";
|
|
149
|
+
else if (code === "update-busy") key = "panel.failure.update-busy.title";
|
|
150
|
+
else if (code === "install-failed") key = "diag.fallback.install-failed";
|
|
151
|
+
else if (code === "unknown-profile") key = "diag.fallback.unknown-profile";
|
|
152
|
+
else if (code === "source-install") key = "diag.fallback.source-install";
|
|
153
|
+
else if (code === "invalid-installation") key = "diag.fallback.invalid-installation";
|
|
154
|
+
else if (code === "installation-changed") key = "diag.fallback.installation-changed";
|
|
155
|
+
else if (code === "pending-restart") key = "diag.fallback.pending-restart";
|
|
156
|
+
else if (code === "incompatible-node") key = "diag.fallback.incompatible-node";
|
|
157
|
+
else if (code === "registry-conflict") key = "diag.fallback.registry-conflict";
|
|
158
|
+
else if (code === "recovery-required") key = "diag.fallback.recovery-required";
|
|
159
|
+
let fallback;
|
|
160
|
+
try {
|
|
161
|
+
fallback = copyText(key, l, values);
|
|
162
|
+
} catch {
|
|
163
|
+
fallback = copyText("diag.fallback.generic", "zh");
|
|
164
|
+
}
|
|
153
165
|
const clean = sanitizeDetail(fallback);
|
|
154
166
|
return clean ? clean : null;
|
|
155
167
|
} catch {
|
|
@@ -176,7 +188,7 @@ function buildDiag(input) {
|
|
|
176
188
|
const httpStatus = pickHttpStatus(stage, input?.error);
|
|
177
189
|
const exitCode = pickExitCode(stage, input?.error);
|
|
178
190
|
const latencyMs = pickLatencyMs(input?.latencyMs);
|
|
179
|
-
const detail = pickDetail(errorCode, input?.error, httpStatus, phoneKind);
|
|
191
|
+
const detail = pickDetail(errorCode, input?.error, httpStatus, phoneKind, input?.lang ?? "zh");
|
|
180
192
|
const targetPackageName = pickPackageName(input?.targetPackageName);
|
|
181
193
|
const runningVersion = pickVersion(input?.runningVersion);
|
|
182
194
|
const latestVersion = pickVersion(input?.latestVersion);
|
package/dist/entry-batch.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type BilingualKey } from './bilingual.js';
|
|
2
|
+
import { type AppLang, type LocaleOption } from './lang.js';
|
|
1
3
|
import { type BatchRowView } from './panel-batch.js';
|
|
2
4
|
import { type UpdatePanelTheme } from './panel.js';
|
|
3
5
|
/** 批量入口件的形态(与单入口同一套取值)。 */
|
|
@@ -38,14 +40,20 @@ export interface UpdateBatchEntryOptions {
|
|
|
38
40
|
/** 调宿主电话:(phoneName, args) => Promise<reply>。 */
|
|
39
41
|
call: (name: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
40
42
|
variant?: BatchEntryVariant;
|
|
41
|
-
/** 主题:与单入口/面板同一套(default/archive
|
|
43
|
+
/** 主题:与单入口/面板同一套(default/archive)。 */
|
|
42
44
|
theme?: UpdatePanelTheme;
|
|
43
45
|
/** 缺省 'mount':进页面静默查一次(只调 .batchStatus,只读)。'never' 则只在用户点击时查。 */
|
|
44
46
|
autoCheck?: BatchEntryAutoCheck;
|
|
47
|
+
/** 打开面板自动查(#59 D3,透传给批量面板):缺省 true;面板按用户偏好 > 本选项 > 缺省,并与入口预查共用知识时间戳去重(一击只查一次)。 */
|
|
48
|
+
checkOnOpen?: boolean;
|
|
49
|
+
/** 自动继续未终态轮次(#59 Q3,透传给批量面板):缺省 true,与显式按钮并存。 */
|
|
50
|
+
autoResume?: boolean;
|
|
45
51
|
/** 缺省 'always':查完总是开批量面板(见本类型说明)。 */
|
|
46
52
|
openOn?: BatchEntryOpenOn;
|
|
47
53
|
/** 覆盖默认按钮文案(不传就用聚合文案)。 */
|
|
48
54
|
label?: string;
|
|
55
|
+
/** 语言覆盖(#60 v2):'zh' | 'en' | { getActive(): string; subscribe?(cb): () => void },不传即跟随全局信号。 */
|
|
56
|
+
locale?: LocaleOption;
|
|
49
57
|
/** 可选:键 -> 中文名覆盖(透传给批量面板)。 */
|
|
50
58
|
titles?: Record<string, string>;
|
|
51
59
|
/** 轮询间隔(毫秒,透传给批量面板;缺省 1500,下限 250)。 */
|
|
@@ -79,12 +87,21 @@ export interface UpdateBatchEntryController {
|
|
|
79
87
|
/**
|
|
80
88
|
* 聚合读数:计数唯一出处 batchLedgerCounts(与面板总账同一份,忙失败占位翻回可更新)。
|
|
81
89
|
* hasUpdate = 忙/失败/待重启/可更新任一非零(openOn has-update 按它开面板;全 settled/待查/跳过即 idle)。
|
|
90
|
+
* v2 单语:label 与 HTML 出口同语言(lang 显式入参,缺省跟随全局;zh 口径逐字兼容旧中文)。
|
|
82
91
|
*/
|
|
83
|
-
export declare function batchEntrySummary(state: UpdateBatchEntryState | null | undefined): BatchEntrySummary;
|
|
84
|
-
/** 状态档(唯一出处:batchEntrySummary
|
|
92
|
+
export declare function batchEntrySummary(state: UpdateBatchEntryState | null | undefined, lang?: AppLang | string | null): BatchEntrySummary;
|
|
93
|
+
/** 状态档(唯一出处:batchEntrySummary,不各写一份;lang 仅影响 label,不影响档位)。 */
|
|
85
94
|
export declare function batchEntryStateKind(state: UpdateBatchEntryState | null | undefined): BatchEntryStateKind;
|
|
86
|
-
/**
|
|
87
|
-
export declare function batchEntryLabelFor(state: UpdateBatchEntryState | null | undefined): string;
|
|
95
|
+
/** 批量入口件文案第二出口(唯一出处;与 HTML 出口同语言,v2 起按 lang 取字典)。 */
|
|
96
|
+
export declare function batchEntryLabelFor(state: UpdateBatchEntryState | null | undefined, lang?: AppLang | string | null): string;
|
|
97
|
+
/** 批量 key(与 entryStateKind 同输入,分支只认稳定码与计数,不读文案)。 */
|
|
98
|
+
export declare function batchEntryBilingualKeyFor(state: UpdateBatchEntryState | null | undefined): BilingualKey;
|
|
99
|
+
/** 批量插值({count} 运行时值永不翻译,冻结词元两语言逐字相同)。 */
|
|
100
|
+
export declare function batchEntryBilingualValuesFor(state: UpdateBatchEntryState | null | undefined): Record<string, string>;
|
|
101
|
+
/** 批量单语块 HTML(按钮正文唯一来源;lang 显式入参,缺省跟随全局)。 */
|
|
102
|
+
export declare function batchEntryBilingualHTMLFor(state: UpdateBatchEntryState | null | undefined, lang?: AppLang | string | null): string;
|
|
103
|
+
/** 批量单语纯文本(title/aria 用;与 HTML 出口同语言)。 */
|
|
104
|
+
export declare function batchEntryBilingualTextFor(state: UpdateBatchEntryState | null | undefined, lang?: AppLang | string | null): string;
|
|
88
105
|
export declare function mountUpdateBatchEntry(container: {
|
|
89
106
|
innerHTML: string;
|
|
90
107
|
addEventListener?: (type: string, listener: (ev: unknown) => void) => void;
|
package/dist/entry-batch.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// AUTO-GENERATED by node build.mjs — DO NOT EDIT. Source: src/entry-batch.ts
|
|
2
2
|
import { MIN_PANEL_POLL_MS } from "./config.js";
|
|
3
3
|
import { UPDATE_ENTRY_CSS } from "./entry.js";
|
|
4
|
+
import { BILINGUAL_CSS, copyHTML, copyText } from "./bilingual.js";
|
|
5
|
+
import { normalizeLangTag, resolveLang, subscribeLang } from "./lang.js";
|
|
4
6
|
import {
|
|
5
7
|
batchLedgerCounts,
|
|
6
8
|
batchLedgerText,
|
|
@@ -11,8 +13,6 @@ import {
|
|
|
11
13
|
failureCodeOf,
|
|
12
14
|
normalizePanelTheme
|
|
13
15
|
} from "./panel.js";
|
|
14
|
-
const LABEL_IDLE = "\u68C0\u67E5\u66F4\u65B0";
|
|
15
|
-
const LABEL_BUSY = "\u6B63\u5728\u5B89\u88C5\u2026";
|
|
16
16
|
function isObject(value) {
|
|
17
17
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
18
18
|
}
|
|
@@ -23,7 +23,7 @@ function asRows(value) {
|
|
|
23
23
|
function escapeHtml(value) {
|
|
24
24
|
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
25
25
|
}
|
|
26
|
-
function batchEntrySummary(state) {
|
|
26
|
+
function batchEntrySummary(state, lang) {
|
|
27
27
|
const rows = state?.rows ?? null;
|
|
28
28
|
const counts = batchLedgerCounts(Array.isArray(rows) ? rows : []);
|
|
29
29
|
const total = Array.isArray(rows) ? rows.length : 0;
|
|
@@ -47,22 +47,23 @@ function batchEntrySummary(state) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
const hasUpdate = counts.installing > 0 || counts.failed > 0 || counts.restart > 0 || counts.updatable > 0;
|
|
50
|
+
const l = lang !== void 0 && lang !== null ? normalizeLangTag(lang) : resolveLang();
|
|
50
51
|
let label;
|
|
51
52
|
switch (kind) {
|
|
52
53
|
case "busy":
|
|
53
|
-
label =
|
|
54
|
+
label = copyText("batch-entry.label.busy", l);
|
|
54
55
|
break;
|
|
55
56
|
case "failed":
|
|
56
|
-
label = counts.failed > 0 ?
|
|
57
|
+
label = counts.failed > 0 ? copyText("batch-entry.label.failed", l, { count: String(counts.failed) }) : copyText("entry.label.failed", l);
|
|
57
58
|
break;
|
|
58
59
|
case "restart":
|
|
59
|
-
label =
|
|
60
|
+
label = copyText("batch-entry.label.restart", l, { count: String(counts.restart) });
|
|
60
61
|
break;
|
|
61
62
|
case "update":
|
|
62
|
-
label = counts.updatable
|
|
63
|
+
label = copyText("batch-entry.label.update", l, { count: String(counts.updatable) });
|
|
63
64
|
break;
|
|
64
65
|
default:
|
|
65
|
-
label =
|
|
66
|
+
label = copyText("batch-entry.label.idle", l);
|
|
66
67
|
break;
|
|
67
68
|
}
|
|
68
69
|
return {
|
|
@@ -82,8 +83,44 @@ function batchEntrySummary(state) {
|
|
|
82
83
|
function batchEntryStateKind(state) {
|
|
83
84
|
return batchEntrySummary(state).kind;
|
|
84
85
|
}
|
|
85
|
-
function batchEntryLabelFor(state) {
|
|
86
|
-
return batchEntrySummary(state).label;
|
|
86
|
+
function batchEntryLabelFor(state, lang) {
|
|
87
|
+
return batchEntrySummary(state, lang).label;
|
|
88
|
+
}
|
|
89
|
+
function batchEntryBilingualKeyFor(state) {
|
|
90
|
+
const s = batchEntrySummary(state);
|
|
91
|
+
switch (s.kind) {
|
|
92
|
+
case "busy":
|
|
93
|
+
return "batch-entry.label.busy";
|
|
94
|
+
case "failed":
|
|
95
|
+
return s.failed > 0 ? "batch-entry.label.failed" : "entry.label.failed";
|
|
96
|
+
case "restart":
|
|
97
|
+
return "batch-entry.label.restart";
|
|
98
|
+
case "update":
|
|
99
|
+
return "batch-entry.label.update";
|
|
100
|
+
default:
|
|
101
|
+
return "batch-entry.label.idle";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function batchEntryBilingualValuesFor(state) {
|
|
105
|
+
const s = batchEntrySummary(state);
|
|
106
|
+
switch (s.kind) {
|
|
107
|
+
case "update":
|
|
108
|
+
return { count: String(s.updatable) };
|
|
109
|
+
case "restart":
|
|
110
|
+
return { count: String(s.restart) };
|
|
111
|
+
case "failed":
|
|
112
|
+
return s.failed > 0 ? { count: String(s.failed) } : {};
|
|
113
|
+
default:
|
|
114
|
+
return {};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function batchEntryBilingualHTMLFor(state, lang) {
|
|
118
|
+
const l = lang !== void 0 && lang !== null ? normalizeLangTag(lang) : resolveLang();
|
|
119
|
+
return copyHTML(batchEntryBilingualKeyFor(state), l, batchEntryBilingualValuesFor(state));
|
|
120
|
+
}
|
|
121
|
+
function batchEntryBilingualTextFor(state, lang) {
|
|
122
|
+
const l = lang !== void 0 && lang !== null ? normalizeLangTag(lang) : resolveLang();
|
|
123
|
+
return copyText(batchEntryBilingualKeyFor(state), l, batchEntryBilingualValuesFor(state));
|
|
87
124
|
}
|
|
88
125
|
function mountUpdateBatchEntry(container, options) {
|
|
89
126
|
if (!container || typeof container.innerHTML !== "string") {
|
|
@@ -108,8 +145,8 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
108
145
|
if (openOn !== "has-update" && openOn !== "always" && openOn !== "manual" && openOn !== "direct") {
|
|
109
146
|
throw new Error("[dsh-plugin-update] \u70B9\u51FB\u53BB\u5411\u975E\u6CD5\uFF1A\u53EA\u6536 has-update / always / manual / direct\uFF08\u6536\u5230 " + JSON.stringify(options.openOn) + "\uFF09");
|
|
110
147
|
}
|
|
111
|
-
if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive"
|
|
112
|
-
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\
|
|
148
|
+
if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive") {
|
|
149
|
+
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 " + JSON.stringify(options.theme) + "\uFF09");
|
|
113
150
|
}
|
|
114
151
|
let theme = normalizePanelTheme(options.theme ?? "default");
|
|
115
152
|
const pollMs = options.pollMs;
|
|
@@ -117,6 +154,20 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
117
154
|
throw new Error("[dsh-plugin-update] \u9762\u677F\u8F6E\u8BE2\u95F4\u9694\u975E\u6CD5\uFF1A\u4E0D\u5F97\u5C0F\u4E8E 250 \u6BEB\u79D2\uFF08\u6536\u5230 " + JSON.stringify(options.pollMs) + "\uFF09");
|
|
118
155
|
}
|
|
119
156
|
const labelOverride = typeof options.label === "string" && options.label ? options.label : null;
|
|
157
|
+
const localeOpt = options.locale ?? void 0;
|
|
158
|
+
if (localeOpt !== void 0 && localeOpt !== null) {
|
|
159
|
+
const isStr = typeof localeOpt === "string";
|
|
160
|
+
const isObj = typeof localeOpt === "object" && typeof localeOpt.getActive === "function";
|
|
161
|
+
if (!isStr && !isObj) {
|
|
162
|
+
throw new Error("[dsh-plugin-update] invalid locale: expected zh / en / BCP47 or { getActive(), subscribe? }");
|
|
163
|
+
}
|
|
164
|
+
if (isStr && !localeOpt.trim()) {
|
|
165
|
+
throw new Error("[dsh-plugin-update] invalid locale: empty string");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function currentLang() {
|
|
169
|
+
return resolveLang(localeOpt);
|
|
170
|
+
}
|
|
120
171
|
const titles = options.titles && typeof options.titles === "object" ? options.titles : {};
|
|
121
172
|
const onActivate = typeof options.onActivate === "function" ? options.onActivate : null;
|
|
122
173
|
const call = options.call;
|
|
@@ -154,7 +205,7 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
154
205
|
return { rows, error };
|
|
155
206
|
}
|
|
156
207
|
function summaryOf() {
|
|
157
|
-
return batchEntrySummary(stateOf());
|
|
208
|
+
return batchEntrySummary(stateOf(), currentLang());
|
|
158
209
|
}
|
|
159
210
|
function currentLabel() {
|
|
160
211
|
return labelOverride ?? summaryOf().label;
|
|
@@ -163,13 +214,15 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
163
214
|
return {};
|
|
164
215
|
}
|
|
165
216
|
function entryHTML() {
|
|
166
|
-
const
|
|
167
|
-
const
|
|
217
|
+
const lang = currentLang();
|
|
218
|
+
const summary = batchEntrySummary(stateOf(), lang);
|
|
219
|
+
const labelHTML = labelOverride ? escapeHtml(labelOverride) : activating ? copyHTML("batch-entry.action.checking", lang) : copyHTML(batchEntryBilingualKeyFor(stateOf()), lang, batchEntryBilingualValuesFor(stateOf()));
|
|
220
|
+
const labelText = labelOverride ?? (activating ? copyText("batch-entry.action.checking", lang) : copyText(batchEntryBilingualKeyFor(stateOf()), lang, batchEntryBilingualValuesFor(stateOf())));
|
|
168
221
|
const busyAttr = activating ? ' disabled aria-busy="true"' : "";
|
|
169
222
|
const themeAttr = theme === "archive" ? ' data-theme="archive"' : "";
|
|
170
|
-
const control = variant === "badge" ? '<button type="button" class="dsh-upd-entry-dot" ' + ENTRY_ATTR + '="activate" title="' + escapeHtml(
|
|
223
|
+
const control = variant === "badge" ? '<button type="button" class="dsh-upd-entry-dot" ' + ENTRY_ATTR + '="activate" title="' + escapeHtml(labelText) + '" aria-label="' + escapeHtml(labelText) + '"' + busyAttr + "></button>" : '<button type="button" class="dsh-upd-entry-btn" ' + ENTRY_ATTR + '="activate"' + busyAttr + ">" + labelHTML + "</button>";
|
|
171
224
|
const noteHTML = note ? '<span class="dsh-upd-entry-note" data-dsh-upd-note="1">' + escapeHtml(note) + "</span>" : "";
|
|
172
|
-
return "<style>" + UPDATE_ENTRY_CSS + '</style>\n<span class="dsh-upd-entry" data-variant="' + variant + '" data-state="' + summary.kind + '"' + themeAttr + ">" + control + noteHTML + "</span>";
|
|
225
|
+
return "<style>" + UPDATE_ENTRY_CSS + "\n" + BILINGUAL_CSS + '</style>\n<span class="dsh-upd-entry" data-variant="' + variant + '" data-state="' + summary.kind + '"' + themeAttr + ">" + control + noteHTML + "</span>";
|
|
173
226
|
}
|
|
174
227
|
function render() {
|
|
175
228
|
if (!mounted) return;
|
|
@@ -219,6 +272,9 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
219
272
|
onRestartRequested: options.onRestartRequested,
|
|
220
273
|
copyText: options.copyText,
|
|
221
274
|
autoChangelog: options.autoChangelog,
|
|
275
|
+
locale: localeOpt,
|
|
276
|
+
checkOnOpen: options.checkOnOpen,
|
|
277
|
+
autoResume: options.autoResume,
|
|
222
278
|
// 面板点「关闭」即走入口件的完整关闭(收 dialog + 还原按钮 + 重查一次),不再是面板自己停轮询。
|
|
223
279
|
onCloseRequested: () => close(),
|
|
224
280
|
call: panelCall
|
|
@@ -283,8 +339,8 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
283
339
|
render();
|
|
284
340
|
}
|
|
285
341
|
function setTheme(next) {
|
|
286
|
-
if (next !== "default" && next !== "archive"
|
|
287
|
-
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\
|
|
342
|
+
if (next !== "default" && next !== "archive") {
|
|
343
|
+
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 " + JSON.stringify(next) + "\uFF09");
|
|
288
344
|
}
|
|
289
345
|
theme = normalizePanelTheme(next);
|
|
290
346
|
if (panel) void panel.setTheme(theme);
|
|
@@ -314,6 +370,10 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
314
370
|
function unmount() {
|
|
315
371
|
if (!mounted) return;
|
|
316
372
|
mounted = false;
|
|
373
|
+
try {
|
|
374
|
+
unsubLang();
|
|
375
|
+
} catch {
|
|
376
|
+
}
|
|
317
377
|
const opened = panel;
|
|
318
378
|
panel = null;
|
|
319
379
|
panelMode = null;
|
|
@@ -332,6 +392,9 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
332
392
|
} catch {
|
|
333
393
|
}
|
|
334
394
|
}
|
|
395
|
+
const unsubLang = subscribeLang(() => {
|
|
396
|
+
render();
|
|
397
|
+
}, localeOpt);
|
|
335
398
|
try {
|
|
336
399
|
;
|
|
337
400
|
container.addEventListener?.("click", onClick);
|
|
@@ -348,6 +411,10 @@ function mountUpdateBatchEntry(container, options) {
|
|
|
348
411
|
return { refresh, open, close, label: currentLabel, summary: summaryOf, setTheme, unmount };
|
|
349
412
|
}
|
|
350
413
|
export {
|
|
414
|
+
batchEntryBilingualHTMLFor,
|
|
415
|
+
batchEntryBilingualKeyFor,
|
|
416
|
+
batchEntryBilingualTextFor,
|
|
417
|
+
batchEntryBilingualValuesFor,
|
|
351
418
|
batchEntryLabelFor,
|
|
352
419
|
batchEntryStateKind,
|
|
353
420
|
batchEntrySummary,
|