mioku 1.1.1 → 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/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_exec = require('./exec-CoLrq043.cjs');
1
+ const require_exec = require('./exec-B2fmdRh2.cjs');
2
2
  const node_fs = require_exec.__toESM(require("node:fs"));
3
3
  const node_path = require_exec.__toESM(require("node:path"));
4
4
  const node_url = require_exec.__toESM(require("node:url"));
@@ -3755,28 +3755,36 @@ function getInstalledVersion(pkgName) {
3755
3755
  const pkg = readPackageJson$1(node_path.join(projectRoot(), "node_modules", pkgName));
3756
3756
  return String(pkg?.version || "0.0.0");
3757
3757
  }
3758
- function listInstalledPackages() {
3759
- const modulesPath = node_path.join(projectRoot(), "node_modules");
3758
+ /** 项目 package.json 声明的 mioku 依赖,不含被 hoist 上来的传递依赖 */
3759
+ function listDeclaredPackages() {
3760
+ const pkg = readPackageJson$1(projectRoot());
3761
+ if (!pkg) return [];
3762
+ const deps = {
3763
+ ...pkg.dependencies ?? {},
3764
+ ...pkg.devDependencies ?? {},
3765
+ ...pkg.optionalDependencies ?? {}
3766
+ };
3760
3767
  const result = [];
3761
- if (!node_fs.existsSync(modulesPath)) return result;
3762
- const entries = node_fs.readdirSync(modulesPath, { withFileTypes: true });
3763
- for (const entry of entries) {
3764
- const type = detectType(entry.name);
3768
+ for (const name of Object.keys(deps)) {
3769
+ const type = detectType(name);
3765
3770
  if (!type) continue;
3766
- const fullPath = node_path.join(modulesPath, entry.name);
3767
- const stat = node_fs.lstatSync(fullPath);
3768
- if (!stat.isDirectory() && !stat.isSymbolicLink()) continue;
3769
- const pkg = readPackageJson$1(fullPath);
3771
+ const fullPath = node_path.join(projectRoot(), "node_modules", name);
3772
+ const installed = readPackageJson$1(fullPath);
3773
+ if (!installed) continue;
3770
3774
  result.push({
3771
- name: entry.name,
3775
+ name,
3772
3776
  type,
3773
- shortName: shortNameOf(entry.name),
3774
- version: String(pkg?.version || "0.0.0"),
3777
+ shortName: shortNameOf(name),
3778
+ version: String(installed.version || "0.0.0"),
3775
3779
  path: fullPath
3776
3780
  });
3777
3781
  }
3778
3782
  return result.sort((a, b) => a.name.localeCompare(b.name));
3779
3783
  }
3784
+ /** .update all 的作用范围:声明的插件与服务,不含框架与传递依赖 */
3785
+ function listManagedPackages() {
3786
+ return listDeclaredPackages().filter((pkg) => pkg.type !== "framework");
3787
+ }
3780
3788
  async function fetchJson(url) {
3781
3789
  const res = await fetch(url, { headers: {
3782
3790
  Accept: "application/json",
@@ -3788,8 +3796,13 @@ async function fetchJson(url) {
3788
3796
  async function fetchNpmMeta(pkgName) {
3789
3797
  try {
3790
3798
  const data = await fetchJson(`${NPM_REGISTRY}/${encodeURIComponent(pkgName)}`);
3791
- const latest = String(data?.["dist-tags"]?.latest || "").trim();
3792
- const version$2 = latest ? data?.versions?.[latest] || {} : {};
3799
+ const versions = Object.keys(data?.versions ?? {});
3800
+ const distTag = String(data?.["dist-tags"]?.latest || "").trim();
3801
+ const staleTag = distTag !== "" && !versions.includes(distTag);
3802
+ const latest = staleTag ? require_exec.pickHighestVersion(versions) ?? distTag : distTag || (require_exec.pickHighestVersion(versions) ?? "");
3803
+ if (!latest) return null;
3804
+ if (staleTag) rootLogger.debug(`[core] ${pkgName} 的 latest 标签 ${distTag} 不存在,改用 ${latest}`);
3805
+ const version$2 = data?.versions?.[latest] || {};
3793
3806
  const repository = version$2?.repository || data?.repository;
3794
3807
  let repoUrl = "";
3795
3808
  if (typeof repository === "string") repoUrl = repository;
@@ -3797,6 +3810,8 @@ async function fetchNpmMeta(pkgName) {
3797
3810
  repoUrl = repoUrl.replace(/^git\+/, "").replace(/\.git$/, "");
3798
3811
  return {
3799
3812
  latest,
3813
+ distTag,
3814
+ staleTag,
3800
3815
  description: String(version$2?.description || data?.description || "").trim(),
3801
3816
  keywords: Array.isArray(version$2?.keywords) ? version$2.keywords : [],
3802
3817
  homepage: String(version$2?.homepage || data?.homepage || "").trim(),
@@ -3809,7 +3824,7 @@ async function fetchNpmMeta(pkgName) {
3809
3824
  }
3810
3825
  }
3811
3826
  async function checkUpdates() {
3812
- const installed = listInstalledPackages();
3827
+ const installed = listDeclaredPackages();
3813
3828
  const metas = await Promise.all(installed.map(async (pkg) => {
3814
3829
  const meta = await fetchNpmMeta(pkg.name);
3815
3830
  return {
@@ -3820,7 +3835,7 @@ async function checkUpdates() {
3820
3835
  const updates = [];
3821
3836
  for (const { pkg, meta } of metas) {
3822
3837
  if (!meta || !meta.latest) continue;
3823
- if (meta.latest === pkg.version) continue;
3838
+ if (require_exec.compareVersions(meta.latest, pkg.version) <= 0) continue;
3824
3839
  updates.push({
3825
3840
  name: pkg.name,
3826
3841
  type: pkg.type,
@@ -3831,53 +3846,72 @@ async function checkUpdates() {
3831
3846
  }
3832
3847
  return updates;
3833
3848
  }
3849
+ /** 取 bun 输出里最有用的一行:优先 error: 行,去掉颜色与前缀,超长截断 */
3850
+ function errorSummary(text$1) {
3851
+ const lines = String(text$1 ?? "").replace(/\u001b\[[0-9;]*m/g, "").split("\n").map((line$1) => line$1.trim()).filter(Boolean);
3852
+ const line = (lines.find((item) => /^error:/i.test(item)) ?? lines[0] ?? "更新失败").replace(/^error:\s*/i, "");
3853
+ return line.length > 160 ? `${line.slice(0, 157)}...` : line;
3854
+ }
3834
3855
  function snapshotVersions(names) {
3835
3856
  const map = new Map();
3836
3857
  for (const name of names) map.set(name, getInstalledVersion(name));
3837
3858
  return map;
3838
3859
  }
3860
+ function outcomeOf(name, before, ok = true, error) {
3861
+ const prev = before.get(name) ?? "0.0.0";
3862
+ const after = getInstalledVersion(name);
3863
+ return {
3864
+ name,
3865
+ ok,
3866
+ before: prev,
3867
+ after,
3868
+ changed: prev !== after,
3869
+ error
3870
+ };
3871
+ }
3872
+ /** latest 标签不可解析时,改用 npm 上真实存在的最高版本 */
3873
+ async function updateWithPinnedVersion(name) {
3874
+ const meta = await fetchNpmMeta(name);
3875
+ const target = meta?.latest ?? "";
3876
+ if (!target) return false;
3877
+ if (require_exec.compareVersions(target, getInstalledVersion(name)) <= 0) return true;
3878
+ rootLogger.info(`[core] ${name} 的 latest 标签不可用,改用 ${target} 更新`);
3879
+ const result = await runBun(["update", `${name}@${target}`]);
3880
+ return result.code === 0;
3881
+ }
3882
+ async function updateOne(name, before) {
3883
+ const single = await runBun([
3884
+ "update",
3885
+ name,
3886
+ "--latest"
3887
+ ]);
3888
+ if (single.code === 0) return outcomeOf(name, before);
3889
+ if (await updateWithPinnedVersion(name)) return outcomeOf(name, before);
3890
+ return outcomeOf(name, before, false, errorSummary(single.stderr || single.stdout));
3891
+ }
3839
3892
  async function updatePackages(names) {
3840
3893
  if (names.length === 0) return {
3841
- code: 0,
3842
- stdout: "",
3843
- stderr: ""
3894
+ outcomes: [],
3895
+ failures: []
3844
3896
  };
3845
- return runBun([
3897
+ const before = snapshotVersions(names);
3898
+ const batch = await runBun([
3846
3899
  "update",
3847
3900
  ...names,
3848
3901
  "--latest"
3849
3902
  ]);
3850
- }
3851
- async function updateAllManaged() {
3852
- const managed = listInstalledPackages().filter((pkg) => pkg.type !== "framework").map((pkg) => pkg.name);
3853
- if (managed.length === 0) return {
3854
- result: {
3855
- code: 0,
3856
- stdout: "",
3857
- stderr: ""
3858
- },
3859
- names: []
3903
+ if (batch.code === 0) return {
3904
+ outcomes: names.map((name) => outcomeOf(name, before)),
3905
+ failures: []
3860
3906
  };
3907
+ rootLogger.warn(`[core] 批量更新失败,改为逐个更新: ${errorSummary(batch.stderr || batch.stdout)}`);
3908
+ const outcomes = [];
3909
+ for (const name of names) outcomes.push(await updateOne(name, before));
3861
3910
  return {
3862
- result: await updatePackages(managed),
3863
- names: managed
3911
+ outcomes,
3912
+ failures: outcomes.filter((outcome) => !outcome.ok)
3864
3913
  };
3865
3914
  }
3866
- function diffVersions(names, before) {
3867
- return names.map((name) => {
3868
- const after = getInstalledVersion(name);
3869
- const prev = before.get(name) || "0.0.0";
3870
- return {
3871
- name,
3872
- before: prev,
3873
- after,
3874
- changed: prev !== after
3875
- };
3876
- });
3877
- }
3878
- function snapshotAll(names) {
3879
- return snapshotVersions(names);
3880
- }
3881
3915
  function appendToMiokuPlugins(pkgName) {
3882
3916
  if (!pkgName.startsWith(PLUGIN_PREFIX)) return false;
3883
3917
  const shortName = pkgName.slice(PLUGIN_PREFIX.length);
@@ -3998,8 +4032,10 @@ function buildMarketItem(pkgName, meta, official) {
3998
4032
  }
3999
4033
  async function getMarketItems(type) {
4000
4034
  const registry = await fetchOfficialRegistry();
4001
- const officialEntries = type === "plugin" ? registry.plugins || {} : registry.services || {};
4035
+ const registryKey = type === "plugin" ? "plugins" : "services";
4036
+ const officialEntries = registry[registryKey] || {};
4002
4037
  const officialNpmNames = new Set(Object.values(officialEntries).map((entry) => String(entry?.npm || "")).filter(Boolean));
4038
+ const hiddenShorts = new Set(registry.hidden?.[registryKey] ?? []);
4003
4039
  const searchObjects = await searchNpmPackages().catch(() => []);
4004
4040
  const prefix = type === "plugin" ? PLUGIN_PREFIX : SERVICE_PREFIX;
4005
4041
  const candidateNames = new Set();
@@ -4008,6 +4044,7 @@ async function getMarketItems(type) {
4008
4044
  if (name.startsWith(prefix)) candidateNames.add(name);
4009
4045
  }
4010
4046
  for (const name of officialNpmNames) if (name.startsWith(prefix)) candidateNames.add(name);
4047
+ for (const name of Array.from(candidateNames)) if (hiddenShorts.has(name.slice(prefix.length))) candidateNames.delete(name);
4011
4048
  const metas = await Promise.all(Array.from(candidateNames).map(async (pkgName) => {
4012
4049
  const meta = await fetchNpmMeta(pkgName);
4013
4050
  return {
@@ -4239,24 +4276,27 @@ async function performUpdateAndReport(ctx, event, names) {
4239
4276
  await replyText(event, "没有需要更新的项。");
4240
4277
  return;
4241
4278
  }
4242
- const before = snapshotAll(names);
4243
4279
  await replyText(event, `正在更新 ${names.length} 个包,请稍候...`);
4244
- const result = await updatePackages(names);
4245
- if (result.code !== 0) {
4246
- ctx.logger.error(`[core] 更新失败: ${result.stderr || result.stdout}`);
4247
- await replyText(event, `更新失败:${result.stderr || result.stdout}`);
4280
+ const report = await updatePackages(names);
4281
+ const changed = report.outcomes.filter((item) => item.changed);
4282
+ const failures = report.failures;
4283
+ ctx.logger.info(`[core] 更新结束:升级 ${changed.length} 个,失败 ${failures.length} 个`);
4284
+ if (failures.length > 0) ctx.logger.error(`[core] 更新失败: ${failures.map((item) => `${item.name}(${item.error})`).join("; ")}`);
4285
+ if (changed.length === 0 && failures.length === 0) {
4286
+ await replyText(event, "更新完成,所有包均已是最新版本");
4248
4287
  return;
4249
4288
  }
4250
- const diffs = diffVersions(names, before);
4251
- const changed = diffs.filter((d) => d.changed);
4252
- const unchanged = diffs.filter((d) => !d.changed);
4289
+ const parts = [];
4290
+ if (changed.length > 0) {
4291
+ parts.push(`更新完成,共 ${changed.length} 个包已升级:`, ...changed.map((item) => `• ${item.name}: ${item.before} → ${item.after}`));
4292
+ const unchanged = report.outcomes.length - changed.length - failures.length;
4293
+ if (unchanged > 0) parts.push("", `另有 ${unchanged} 个包已是最新`);
4294
+ }
4295
+ if (failures.length > 0) parts.push("", `以下 ${failures.length} 个包未能更新:`, ...failures.map((item) => `• ${item.name}: ${item.error}`), "", "通常是 npm 上的版本信息尚未同步,可稍后重试");
4253
4296
  if (changed.length === 0) {
4254
- await replyText(event, "更新完成,所有包均已是最新版本");
4297
+ await replyText(event, parts.join("\n"));
4255
4298
  return;
4256
4299
  }
4257
- const lines = changed.map((d) => `• ${d.name}: ${d.before} → ${d.after}`);
4258
- const parts = [`更新完成,共 ${changed.length} 个包已升级:`, ...lines];
4259
- if (unchanged.length > 0) parts.push("", `另有 ${unchanged.length} 个包已是最新`);
4260
4300
  parts.push("", "即将重启...");
4261
4301
  await replyText(event, parts.join("\n"));
4262
4302
  const selfId = String(event?.self_id ?? "");
@@ -4285,12 +4325,12 @@ function registerUpdateCommands(ctx) {
4285
4325
  const bot = event.bot;
4286
4326
  if (!bot) return;
4287
4327
  if (arg === "all") {
4288
- const managed = await updateAllManaged();
4289
- if (managed.names.length === 0) {
4328
+ const managed = listManagedPackages();
4329
+ if (managed.length === 0) {
4290
4330
  await replyText(event, "未找到可更新的 mioku 包");
4291
4331
  return;
4292
4332
  }
4293
- await performUpdateAndReport(ctx, event, managed.names);
4333
+ await performUpdateAndReport(ctx, event, managed.map((item) => item.name));
4294
4334
  return;
4295
4335
  }
4296
4336
  if (arg === "mioku" || arg === "self") {
@@ -4695,18 +4735,20 @@ function startAutoUpdateScheduler(enabled, time, frequency) {
4695
4735
  running = true;
4696
4736
  try {
4697
4737
  rootLogger.info("[core] 自动更新开始...");
4698
- const allInstalled = listInstalledPackages();
4738
+ const allInstalled = listDeclaredPackages();
4699
4739
  const names = allInstalled.map((pkg) => pkg.name);
4700
4740
  if (names.length === 0) {
4701
4741
  rootLogger.info("[core] 未找到需要更新的包");
4702
4742
  return;
4703
4743
  }
4704
- const result = await updatePackages(names);
4705
- if (result.code !== 0) {
4706
- rootLogger.error(`[core] 自动更新失败: ${result.stderr || result.stdout}`);
4744
+ const report = await updatePackages(names);
4745
+ const changed = report.outcomes.filter((item) => item.changed);
4746
+ if (report.failures.length > 0) rootLogger.error(`[core] 自动更新失败: ${report.failures.map((item) => `${item.name}(${item.error})`).join("; ")}`);
4747
+ if (changed.length === 0) {
4748
+ rootLogger.info("[core] 自动更新结束,没有包需要升级");
4707
4749
  return;
4708
4750
  }
4709
- rootLogger.info("[core] 自动更新成功,准备重启...");
4751
+ rootLogger.info(`[core] 自动更新成功,升级 ${changed.length} 个包,准备重启...`);
4710
4752
  const marker = {
4711
4753
  initiatedAt: Date.now(),
4712
4754
  selfId: "",