mioku 1.2.0 → 1.2.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/dist/cli/index.cjs +51 -42
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +51 -42
- package/dist/cli/index.js.map +1 -1
- package/dist/{exec-C18L88s9.cjs → exec-B2fmdRh2.cjs} +80 -2
- package/dist/exec-B2fmdRh2.cjs.map +1 -0
- package/dist/{exec-JBR-IZk0.js → exec-CBlGXt5y.js} +69 -3
- package/dist/exec-CBlGXt5y.js.map +1 -0
- package/dist/index.cjs +108 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +108 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/exec-C18L88s9.cjs.map +0 -1
- package/dist/exec-JBR-IZk0.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildSpawnPlan, commandExists, resolveCommand, runCommand, runCommandInherit, version } from "./exec-
|
|
1
|
+
import { buildSpawnPlan, commandExists, compareVersions, pickHighestVersion, resolveCommand, runCommand, runCommandInherit, version } from "./exec-CBlGXt5y.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import * as fs$5 from "node:fs";
|
|
4
4
|
import * as fs$4 from "node:fs";
|
|
@@ -3770,28 +3770,36 @@ function getInstalledVersion(pkgName) {
|
|
|
3770
3770
|
const pkg = readPackageJson$1(path$6.join(projectRoot(), "node_modules", pkgName));
|
|
3771
3771
|
return String(pkg?.version || "0.0.0");
|
|
3772
3772
|
}
|
|
3773
|
-
|
|
3774
|
-
|
|
3773
|
+
/** 项目 package.json 声明的 mioku 依赖,不含被 hoist 上来的传递依赖 */
|
|
3774
|
+
function listDeclaredPackages() {
|
|
3775
|
+
const pkg = readPackageJson$1(projectRoot());
|
|
3776
|
+
if (!pkg) return [];
|
|
3777
|
+
const deps = {
|
|
3778
|
+
...pkg.dependencies ?? {},
|
|
3779
|
+
...pkg.devDependencies ?? {},
|
|
3780
|
+
...pkg.optionalDependencies ?? {}
|
|
3781
|
+
};
|
|
3775
3782
|
const result = [];
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
for (const entry of entries) {
|
|
3779
|
-
const type = detectType(entry.name);
|
|
3783
|
+
for (const name of Object.keys(deps)) {
|
|
3784
|
+
const type = detectType(name);
|
|
3780
3785
|
if (!type) continue;
|
|
3781
|
-
const fullPath = path$6.join(
|
|
3782
|
-
const
|
|
3783
|
-
if (!
|
|
3784
|
-
const pkg = readPackageJson$1(fullPath);
|
|
3786
|
+
const fullPath = path$6.join(projectRoot(), "node_modules", name);
|
|
3787
|
+
const installed = readPackageJson$1(fullPath);
|
|
3788
|
+
if (!installed) continue;
|
|
3785
3789
|
result.push({
|
|
3786
|
-
name
|
|
3790
|
+
name,
|
|
3787
3791
|
type,
|
|
3788
|
-
shortName: shortNameOf(
|
|
3789
|
-
version: String(
|
|
3792
|
+
shortName: shortNameOf(name),
|
|
3793
|
+
version: String(installed.version || "0.0.0"),
|
|
3790
3794
|
path: fullPath
|
|
3791
3795
|
});
|
|
3792
3796
|
}
|
|
3793
3797
|
return result.sort((a, b) => a.name.localeCompare(b.name));
|
|
3794
3798
|
}
|
|
3799
|
+
/** .update all 的作用范围:声明的插件与服务,不含框架与传递依赖 */
|
|
3800
|
+
function listManagedPackages() {
|
|
3801
|
+
return listDeclaredPackages().filter((pkg) => pkg.type !== "framework");
|
|
3802
|
+
}
|
|
3795
3803
|
async function fetchJson(url) {
|
|
3796
3804
|
const res = await fetch(url, { headers: {
|
|
3797
3805
|
Accept: "application/json",
|
|
@@ -3803,8 +3811,13 @@ async function fetchJson(url) {
|
|
|
3803
3811
|
async function fetchNpmMeta(pkgName) {
|
|
3804
3812
|
try {
|
|
3805
3813
|
const data = await fetchJson(`${NPM_REGISTRY}/${encodeURIComponent(pkgName)}`);
|
|
3806
|
-
const
|
|
3807
|
-
const
|
|
3814
|
+
const versions = Object.keys(data?.versions ?? {});
|
|
3815
|
+
const distTag = String(data?.["dist-tags"]?.latest || "").trim();
|
|
3816
|
+
const staleTag = distTag !== "" && !versions.includes(distTag);
|
|
3817
|
+
const latest = staleTag ? pickHighestVersion(versions) ?? distTag : distTag || (pickHighestVersion(versions) ?? "");
|
|
3818
|
+
if (!latest) return null;
|
|
3819
|
+
if (staleTag) rootLogger.debug(`[core] ${pkgName} 的 latest 标签 ${distTag} 不存在,改用 ${latest}`);
|
|
3820
|
+
const version$2 = data?.versions?.[latest] || {};
|
|
3808
3821
|
const repository = version$2?.repository || data?.repository;
|
|
3809
3822
|
let repoUrl = "";
|
|
3810
3823
|
if (typeof repository === "string") repoUrl = repository;
|
|
@@ -3812,6 +3825,8 @@ async function fetchNpmMeta(pkgName) {
|
|
|
3812
3825
|
repoUrl = repoUrl.replace(/^git\+/, "").replace(/\.git$/, "");
|
|
3813
3826
|
return {
|
|
3814
3827
|
latest,
|
|
3828
|
+
distTag,
|
|
3829
|
+
staleTag,
|
|
3815
3830
|
description: String(version$2?.description || data?.description || "").trim(),
|
|
3816
3831
|
keywords: Array.isArray(version$2?.keywords) ? version$2.keywords : [],
|
|
3817
3832
|
homepage: String(version$2?.homepage || data?.homepage || "").trim(),
|
|
@@ -3824,7 +3839,7 @@ async function fetchNpmMeta(pkgName) {
|
|
|
3824
3839
|
}
|
|
3825
3840
|
}
|
|
3826
3841
|
async function checkUpdates() {
|
|
3827
|
-
const installed =
|
|
3842
|
+
const installed = listDeclaredPackages();
|
|
3828
3843
|
const metas = await Promise.all(installed.map(async (pkg) => {
|
|
3829
3844
|
const meta = await fetchNpmMeta(pkg.name);
|
|
3830
3845
|
return {
|
|
@@ -3835,7 +3850,7 @@ async function checkUpdates() {
|
|
|
3835
3850
|
const updates = [];
|
|
3836
3851
|
for (const { pkg, meta } of metas) {
|
|
3837
3852
|
if (!meta || !meta.latest) continue;
|
|
3838
|
-
if (meta.latest
|
|
3853
|
+
if (compareVersions(meta.latest, pkg.version) <= 0) continue;
|
|
3839
3854
|
updates.push({
|
|
3840
3855
|
name: pkg.name,
|
|
3841
3856
|
type: pkg.type,
|
|
@@ -3846,53 +3861,72 @@ async function checkUpdates() {
|
|
|
3846
3861
|
}
|
|
3847
3862
|
return updates;
|
|
3848
3863
|
}
|
|
3864
|
+
/** 取 bun 输出里最有用的一行:优先 error: 行,去掉颜色与前缀,超长截断 */
|
|
3865
|
+
function errorSummary(text$1) {
|
|
3866
|
+
const lines = String(text$1 ?? "").replace(/\u001b\[[0-9;]*m/g, "").split("\n").map((line$1) => line$1.trim()).filter(Boolean);
|
|
3867
|
+
const line = (lines.find((item) => /^error:/i.test(item)) ?? lines[0] ?? "更新失败").replace(/^error:\s*/i, "");
|
|
3868
|
+
return line.length > 160 ? `${line.slice(0, 157)}...` : line;
|
|
3869
|
+
}
|
|
3849
3870
|
function snapshotVersions(names) {
|
|
3850
3871
|
const map = new Map();
|
|
3851
3872
|
for (const name of names) map.set(name, getInstalledVersion(name));
|
|
3852
3873
|
return map;
|
|
3853
3874
|
}
|
|
3875
|
+
function outcomeOf(name, before, ok = true, error) {
|
|
3876
|
+
const prev = before.get(name) ?? "0.0.0";
|
|
3877
|
+
const after = getInstalledVersion(name);
|
|
3878
|
+
return {
|
|
3879
|
+
name,
|
|
3880
|
+
ok,
|
|
3881
|
+
before: prev,
|
|
3882
|
+
after,
|
|
3883
|
+
changed: prev !== after,
|
|
3884
|
+
error
|
|
3885
|
+
};
|
|
3886
|
+
}
|
|
3887
|
+
/** latest 标签不可解析时,改用 npm 上真实存在的最高版本 */
|
|
3888
|
+
async function updateWithPinnedVersion(name) {
|
|
3889
|
+
const meta = await fetchNpmMeta(name);
|
|
3890
|
+
const target = meta?.latest ?? "";
|
|
3891
|
+
if (!target) return false;
|
|
3892
|
+
if (compareVersions(target, getInstalledVersion(name)) <= 0) return true;
|
|
3893
|
+
rootLogger.info(`[core] ${name} 的 latest 标签不可用,改用 ${target} 更新`);
|
|
3894
|
+
const result = await runBun(["update", `${name}@${target}`]);
|
|
3895
|
+
return result.code === 0;
|
|
3896
|
+
}
|
|
3897
|
+
async function updateOne(name, before) {
|
|
3898
|
+
const single = await runBun([
|
|
3899
|
+
"update",
|
|
3900
|
+
name,
|
|
3901
|
+
"--latest"
|
|
3902
|
+
]);
|
|
3903
|
+
if (single.code === 0) return outcomeOf(name, before);
|
|
3904
|
+
if (await updateWithPinnedVersion(name)) return outcomeOf(name, before);
|
|
3905
|
+
return outcomeOf(name, before, false, errorSummary(single.stderr || single.stdout));
|
|
3906
|
+
}
|
|
3854
3907
|
async function updatePackages(names) {
|
|
3855
3908
|
if (names.length === 0) return {
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
stderr: ""
|
|
3909
|
+
outcomes: [],
|
|
3910
|
+
failures: []
|
|
3859
3911
|
};
|
|
3860
|
-
|
|
3912
|
+
const before = snapshotVersions(names);
|
|
3913
|
+
const batch = await runBun([
|
|
3861
3914
|
"update",
|
|
3862
3915
|
...names,
|
|
3863
3916
|
"--latest"
|
|
3864
3917
|
]);
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
if (managed.length === 0) return {
|
|
3869
|
-
result: {
|
|
3870
|
-
code: 0,
|
|
3871
|
-
stdout: "",
|
|
3872
|
-
stderr: ""
|
|
3873
|
-
},
|
|
3874
|
-
names: []
|
|
3918
|
+
if (batch.code === 0) return {
|
|
3919
|
+
outcomes: names.map((name) => outcomeOf(name, before)),
|
|
3920
|
+
failures: []
|
|
3875
3921
|
};
|
|
3922
|
+
rootLogger.warn(`[core] 批量更新失败,改为逐个更新: ${errorSummary(batch.stderr || batch.stdout)}`);
|
|
3923
|
+
const outcomes = [];
|
|
3924
|
+
for (const name of names) outcomes.push(await updateOne(name, before));
|
|
3876
3925
|
return {
|
|
3877
|
-
|
|
3878
|
-
|
|
3926
|
+
outcomes,
|
|
3927
|
+
failures: outcomes.filter((outcome) => !outcome.ok)
|
|
3879
3928
|
};
|
|
3880
3929
|
}
|
|
3881
|
-
function diffVersions(names, before) {
|
|
3882
|
-
return names.map((name) => {
|
|
3883
|
-
const after = getInstalledVersion(name);
|
|
3884
|
-
const prev = before.get(name) || "0.0.0";
|
|
3885
|
-
return {
|
|
3886
|
-
name,
|
|
3887
|
-
before: prev,
|
|
3888
|
-
after,
|
|
3889
|
-
changed: prev !== after
|
|
3890
|
-
};
|
|
3891
|
-
});
|
|
3892
|
-
}
|
|
3893
|
-
function snapshotAll(names) {
|
|
3894
|
-
return snapshotVersions(names);
|
|
3895
|
-
}
|
|
3896
3930
|
function appendToMiokuPlugins(pkgName) {
|
|
3897
3931
|
if (!pkgName.startsWith(PLUGIN_PREFIX)) return false;
|
|
3898
3932
|
const shortName = pkgName.slice(PLUGIN_PREFIX.length);
|
|
@@ -4257,24 +4291,27 @@ async function performUpdateAndReport(ctx, event, names) {
|
|
|
4257
4291
|
await replyText(event, "没有需要更新的项。");
|
|
4258
4292
|
return;
|
|
4259
4293
|
}
|
|
4260
|
-
const before = snapshotAll(names);
|
|
4261
4294
|
await replyText(event, `正在更新 ${names.length} 个包,请稍候...`);
|
|
4262
|
-
const
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4295
|
+
const report = await updatePackages(names);
|
|
4296
|
+
const changed = report.outcomes.filter((item) => item.changed);
|
|
4297
|
+
const failures = report.failures;
|
|
4298
|
+
ctx.logger.info(`[core] 更新结束:升级 ${changed.length} 个,失败 ${failures.length} 个`);
|
|
4299
|
+
if (failures.length > 0) ctx.logger.error(`[core] 更新失败: ${failures.map((item) => `${item.name}(${item.error})`).join("; ")}`);
|
|
4300
|
+
if (changed.length === 0 && failures.length === 0) {
|
|
4301
|
+
await replyText(event, "更新完成,所有包均已是最新版本");
|
|
4266
4302
|
return;
|
|
4267
4303
|
}
|
|
4268
|
-
const
|
|
4269
|
-
|
|
4270
|
-
|
|
4304
|
+
const parts = [];
|
|
4305
|
+
if (changed.length > 0) {
|
|
4306
|
+
parts.push(`更新完成,共 ${changed.length} 个包已升级:`, ...changed.map((item) => `• ${item.name}: ${item.before} → ${item.after}`));
|
|
4307
|
+
const unchanged = report.outcomes.length - changed.length - failures.length;
|
|
4308
|
+
if (unchanged > 0) parts.push("", `另有 ${unchanged} 个包已是最新`);
|
|
4309
|
+
}
|
|
4310
|
+
if (failures.length > 0) parts.push("", `以下 ${failures.length} 个包未能更新:`, ...failures.map((item) => `• ${item.name}: ${item.error}`), "", "通常是 npm 上的版本信息尚未同步,可稍后重试");
|
|
4271
4311
|
if (changed.length === 0) {
|
|
4272
|
-
await replyText(event, "
|
|
4312
|
+
await replyText(event, parts.join("\n"));
|
|
4273
4313
|
return;
|
|
4274
4314
|
}
|
|
4275
|
-
const lines = changed.map((d) => `• ${d.name}: ${d.before} → ${d.after}`);
|
|
4276
|
-
const parts = [`更新完成,共 ${changed.length} 个包已升级:`, ...lines];
|
|
4277
|
-
if (unchanged.length > 0) parts.push("", `另有 ${unchanged.length} 个包已是最新`);
|
|
4278
4315
|
parts.push("", "即将重启...");
|
|
4279
4316
|
await replyText(event, parts.join("\n"));
|
|
4280
4317
|
const selfId = String(event?.self_id ?? "");
|
|
@@ -4303,12 +4340,12 @@ function registerUpdateCommands(ctx) {
|
|
|
4303
4340
|
const bot = event.bot;
|
|
4304
4341
|
if (!bot) return;
|
|
4305
4342
|
if (arg === "all") {
|
|
4306
|
-
const managed =
|
|
4307
|
-
if (managed.
|
|
4343
|
+
const managed = listManagedPackages();
|
|
4344
|
+
if (managed.length === 0) {
|
|
4308
4345
|
await replyText(event, "未找到可更新的 mioku 包");
|
|
4309
4346
|
return;
|
|
4310
4347
|
}
|
|
4311
|
-
await performUpdateAndReport(ctx, event, managed.
|
|
4348
|
+
await performUpdateAndReport(ctx, event, managed.map((item) => item.name));
|
|
4312
4349
|
return;
|
|
4313
4350
|
}
|
|
4314
4351
|
if (arg === "mioku" || arg === "self") {
|
|
@@ -4713,18 +4750,20 @@ function startAutoUpdateScheduler(enabled, time, frequency) {
|
|
|
4713
4750
|
running = true;
|
|
4714
4751
|
try {
|
|
4715
4752
|
rootLogger.info("[core] 自动更新开始...");
|
|
4716
|
-
const allInstalled =
|
|
4753
|
+
const allInstalled = listDeclaredPackages();
|
|
4717
4754
|
const names = allInstalled.map((pkg) => pkg.name);
|
|
4718
4755
|
if (names.length === 0) {
|
|
4719
4756
|
rootLogger.info("[core] 未找到需要更新的包");
|
|
4720
4757
|
return;
|
|
4721
4758
|
}
|
|
4722
|
-
const
|
|
4723
|
-
|
|
4724
|
-
|
|
4759
|
+
const report = await updatePackages(names);
|
|
4760
|
+
const changed = report.outcomes.filter((item) => item.changed);
|
|
4761
|
+
if (report.failures.length > 0) rootLogger.error(`[core] 自动更新失败: ${report.failures.map((item) => `${item.name}(${item.error})`).join("; ")}`);
|
|
4762
|
+
if (changed.length === 0) {
|
|
4763
|
+
rootLogger.info("[core] 自动更新结束,没有包需要升级");
|
|
4725
4764
|
return;
|
|
4726
4765
|
}
|
|
4727
|
-
rootLogger.info(
|
|
4766
|
+
rootLogger.info(`[core] 自动更新成功,升级 ${changed.length} 个包,准备重启...`);
|
|
4728
4767
|
const marker = {
|
|
4729
4768
|
initiatedAt: Date.now(),
|
|
4730
4769
|
selfId: "",
|