node-karin 1.12.2 → 1.13.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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # 更新日志
2
2
 
3
+ ## [1.13.0](https://github.com/KarinJS/Karin/compare/core-v1.12.2...core-v1.13.0) (2025-11-22)
4
+
5
+
6
+ ### ✨ Features
7
+
8
+ * 使用@karinjs/log4js 增强开发体验 ([#577](https://github.com/KarinJS/Karin/issues/577)) ([4e4f998](https://github.com/KarinJS/Karin/commit/4e4f9980cb70e7267a41d63630e9841c74bab161))
9
+
10
+
11
+ ### 🐛 Bug Fixes
12
+
13
+ * Prevent loading plugins with incompatible engine versions and add ignoreEngines option ([#571](https://github.com/KarinJS/Karin/issues/571)) ([33e3279](https://github.com/KarinJS/Karin/commit/33e3279a30908a4aad10cc9d1cba5cd16d17c382))
14
+ * 增强ffmpeg鲁棒性 ([#574](https://github.com/KarinJS/Karin/issues/574)) ([972c901](https://github.com/KarinJS/Karin/commit/972c9013b13fac197a2e1eb19a7341a3a48b380c))
15
+
3
16
  ## [1.12.2](https://github.com/KarinJS/Karin/compare/core-v1.12.1...core-v1.12.2) (2025-10-20)
4
17
 
5
18
 
package/dist/index.d.ts CHANGED
@@ -6964,6 +6964,12 @@ interface PkgData {
6964
6964
  version: string;
6965
6965
  /** 插件入口 */
6966
6966
  main: string;
6967
+ /** 官方的 engines 字段 */
6968
+ engines?: {
6969
+ karin?: string;
6970
+ ['node-karin']?: string;
6971
+ [key: string]: any;
6972
+ };
6967
6973
  karin?: {
6968
6974
  /** ts入口 */
6969
6975
  main?: string;
@@ -6981,17 +6987,18 @@ interface PkgData {
6981
6987
  files?: string[];
6982
6988
  /** 环境变量配置 */
6983
6989
  env?: PkgEnv[];
6984
- /** 引擎兼容性 官方的翻译。。。奇奇怪怪的 */
6985
- engines?: {
6986
- /**
6987
- * @description karin版本
6988
- * @example ^0.0.1
6989
- * @example >=0.0.1
6990
- * @example 0.0.1
6991
- * @example 0.0.x
6992
- */
6993
- karin?: string;
6994
- };
6990
+ /**
6991
+ * 引擎兼容性 官方的翻译。。。奇奇怪怪的
6992
+ * @description 插件的引擎兼容性配置,用于指定插件在哪些karin版本下运行。
6993
+ * @description karin版本
6994
+ * @example ^0.0.1
6995
+ * @example >=0.0.1
6996
+ * @example 0.0.1
6997
+ * @example 0.0.x
6998
+ */
6999
+ engines?: string;
7000
+ /** 忽略引擎版本检查,强制加载插件(仅适用于karin.engines,不影响package.engines) */
7001
+ ignoreEngines?: boolean;
6995
7002
  };
6996
7003
  [key: string]: any;
6997
7004
  }
@@ -9032,7 +9039,7 @@ declare const formatTime$1: (time: number, time2?: number) => string;
9032
9039
  * 传入一个函数 判断是否是类
9033
9040
  * @param fnc 函数
9034
9041
  */
9035
- declare const isClass: (fnc: Function) => boolean;
9042
+ declare const isClass: (fnc: unknown) => fnc is Function;
9036
9043
 
9037
9044
  /**
9038
9045
  * @description 拆解错误对象 用于`JSON`序列化
package/dist/index.mjs CHANGED
@@ -11247,13 +11247,24 @@ var init_ffmpeg = __esm({
11247
11247
  setTimeout(async () => {
11248
11248
  const env3 = await exec("ffmpeg -version", { booleanResult: true });
11249
11249
  if (!env3) {
11250
- const cfg = await Promise.resolve().then(() => (init_config(), config_exports));
11251
- const ffmpeg2 = cfg.ffmpegPath();
11252
- const ffprobe2 = cfg.ffprobePath();
11253
- const ffplay2 = cfg.ffplayPath();
11254
- ffmpegPath2 = ffmpeg2 ? `"${ffmpeg2}"` : ffmpegPath2;
11255
- ffprobePath2 = ffprobe2 ? `"${ffprobe2}"` : ffprobePath2;
11256
- ffplayPath2 = ffplay2 ? `"${ffplay2}"` : ffplayPath2;
11250
+ try {
11251
+ const name = "@karinjs/plugin-ffmpeg";
11252
+ const plugin = await import(name);
11253
+ const ffmpeg2 = plugin.default.ffmpegPath;
11254
+ const ffprobe2 = plugin.default.ffprobePath;
11255
+ const ffplay2 = plugin.default.ffplayPath;
11256
+ ffmpegPath2 = ffmpeg2 ? `"${ffmpeg2}"` : ffmpegPath2;
11257
+ ffprobePath2 = ffprobe2 ? `"${ffprobe2}"` : ffprobePath2;
11258
+ ffplayPath2 = ffplay2 ? `"${ffplay2}"` : ffplayPath2;
11259
+ } catch {
11260
+ const cfg = await Promise.resolve().then(() => (init_config(), config_exports));
11261
+ const ffmpeg2 = cfg.ffmpegPath();
11262
+ const ffprobe2 = cfg.ffprobePath();
11263
+ const ffplay2 = cfg.ffplayPath();
11264
+ ffmpegPath2 = ffmpeg2 ? `"${ffmpeg2}"` : ffmpegPath2;
11265
+ ffprobePath2 = ffprobe2 ? `"${ffprobe2}"` : ffprobePath2;
11266
+ ffplayPath2 = ffplay2 ? `"${ffplay2}"` : ffplayPath2;
11267
+ }
11257
11268
  }
11258
11269
  }, 1e3);
11259
11270
  ffmpeg = async (cmd, options) => {
@@ -12713,6 +12724,101 @@ var init_system2 = __esm({
12713
12724
  init_range();
12714
12725
  }
12715
12726
  });
12727
+
12728
+ // src/plugin/system/versionCheck.ts
12729
+ var cmpVer, normalizeCore, nextPatchIfGreater, calcLowerBoundSingle, calcLowerBoundBySatisfies, createPluginMismatchReporter;
12730
+ var init_versionCheck = __esm({
12731
+ "src/plugin/system/versionCheck.ts"() {
12732
+ init_system2();
12733
+ cmpVer = (a, b) => {
12734
+ const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
12735
+ const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
12736
+ if (pa[0] !== pb[0]) return pa[0] - pb[0];
12737
+ if (pa[1] !== pb[1]) return pa[1] - pb[1];
12738
+ return pa[2] - pb[2];
12739
+ };
12740
+ normalizeCore = (v) => {
12741
+ const core = v.replace(/[xX*]/g, "0");
12742
+ const m = core.match(/\d+\.\d+\.\d+/);
12743
+ return m ? m[0] : null;
12744
+ };
12745
+ nextPatchIfGreater = (op, core) => {
12746
+ if (op !== ">") return core;
12747
+ const [maj, min, pat] = core.split(".").map((n) => parseInt(n, 10) || 0);
12748
+ return `${maj}.${min}.${pat + 1}`;
12749
+ };
12750
+ calcLowerBoundSingle = (range3) => {
12751
+ const tokens = range3.split(/\s+/).map((t) => t.trim()).filter((t) => t && t !== "&&");
12752
+ const candidates = [];
12753
+ for (const tk of tokens) {
12754
+ const m = tk.match(/^(\^|>=|>|~)?(.+)$/);
12755
+ const op = m?.[1] || "";
12756
+ const ver = (m?.[2] || tk).trim();
12757
+ const core = normalizeCore(ver);
12758
+ if (!core) continue;
12759
+ const candidate = op === ">" ? nextPatchIfGreater(op, core) : core;
12760
+ candidates.push(candidate);
12761
+ }
12762
+ let lower = null;
12763
+ for (const v of candidates) {
12764
+ if (!satisfies(range3, v)) continue;
12765
+ if (!lower || cmpVer(v, lower) < 0) {
12766
+ lower = v;
12767
+ }
12768
+ }
12769
+ return lower;
12770
+ };
12771
+ calcLowerBoundBySatisfies = (range3) => {
12772
+ const parts = range3.split("||").map((s) => s.trim()).filter(Boolean);
12773
+ if (parts.length <= 1) return calcLowerBoundSingle(range3);
12774
+ let best = null;
12775
+ for (const part of parts) {
12776
+ const lb = calcLowerBoundSingle(part);
12777
+ if (lb && (!best || cmpVer(lb, best) < 0)) {
12778
+ best = lb;
12779
+ }
12780
+ }
12781
+ return best;
12782
+ };
12783
+ createPluginMismatchReporter = () => {
12784
+ const items = [];
12785
+ let maxRequired = null;
12786
+ const add = (name, engines) => {
12787
+ items.push({ name, engines });
12788
+ const lower = calcLowerBoundBySatisfies(engines);
12789
+ if (lower) {
12790
+ if (!maxRequired || cmpVer(lower, maxRequired) > 0) {
12791
+ maxRequired = lower;
12792
+ }
12793
+ }
12794
+ };
12795
+ const flush = async (shouldPrint = true, currentVersion) => {
12796
+ if (!items.length || !shouldPrint) return;
12797
+ const lines = [];
12798
+ lines.push(logger.yellow("\u26A0 \u4EE5\u4E0B\u63D2\u4EF6\u7248\u672C\u4E0D\u5339\u914D\u5F53\u524D Karin \u7248\u672C:"));
12799
+ lines.push("");
12800
+ for (const it of items) {
12801
+ lines.push(logger.yellow(` ${logger.blue(it.name)}: ${it.engines}`));
12802
+ }
12803
+ lines.push("");
12804
+ lines.push(logger.yellow("dependencies:"));
12805
+ if (maxRequired) {
12806
+ if (currentVersion && cmpVer(currentVersion, maxRequired) < 0) {
12807
+ lines.push(` ${logger.green("node-karin:")} ${logger.gray(currentVersion)} -> ${logger.cyan(maxRequired)}`);
12808
+ lines.push("");
12809
+ lines.push(logger.white(`\u4E3A\u8FBE\u5230\u6B64\u90E8\u5206\u63D2\u4EF6\u7684\u6700\u4F4E\u8FD0\u884C\u8981\u6C42\uFF0C\u5EFA\u8BAE\u6267\u884C\uFF1A${logger.yellow(`pnpm up node-karin@${maxRequired}`)}`));
12810
+ } else if (!currentVersion) {
12811
+ lines.push(` ${logger.green("node-karin:")} ${logger.cyan(maxRequired)}`);
12812
+ lines.push("");
12813
+ lines.push(logger.white(`\u4E3A\u8FBE\u5230\u6B64\u90E8\u5206\u63D2\u4EF6\u7684\u6700\u4F4E\u8FD0\u884C\u8981\u6C42\uFF0C\u5EFA\u8BAE\u6267\u884C\uFF1A${logger.yellow(`pnpm up node-karin@${maxRequired}`)}`));
12814
+ }
12815
+ }
12816
+ console.log(lines.join("\n"));
12817
+ };
12818
+ return { add, flush };
12819
+ };
12820
+ }
12821
+ });
12716
12822
  var isInit, cache5, resetCache, initCache, setCachedList, setCachedInfo, getCachedData, createPkg, getAppInfo, getGitInfo, getNpmInfo, getPluginsInfo, collectAppPlugins, collectGitPlugins, NPM_EXCLUDE_LIST, collectNpmPlugins, collectAllPlugins, getPlugins;
12717
12823
  var init_list = __esm({
12718
12824
  "src/plugin/system/list.ts"() {
@@ -12723,6 +12829,7 @@ var init_list = __esm({
12723
12829
  init_path();
12724
12830
  init_env3();
12725
12831
  init_require();
12832
+ init_versionCheck();
12726
12833
  isInit = true;
12727
12834
  cache5 = {
12728
12835
  list: void 0,
@@ -12886,21 +12993,33 @@ var init_list = __esm({
12886
12993
  );
12887
12994
  };
12888
12995
  collectGitPlugins = async (files, list2) => {
12996
+ const reporter = createPluginMismatchReporter();
12889
12997
  await Promise.all(
12890
12998
  files.map(async (v) => {
12891
12999
  if (!v.isDirectory()) return;
12892
13000
  if (!v.name.startsWith("karin-plugin-")) return;
12893
13001
  if (!fs5.existsSync(path4.join(karinPathPlugins, v.name, "package.json"))) return;
12894
13002
  const pkg2 = await requireFile(path4.join(karinPathPlugins, v.name, "package.json"));
12895
- const engines = pkg2?.karin?.engines?.karin || pkg2?.engines?.karin;
12896
- if (engines && !satisfies(engines, process.env.KARIN_VERSION)) {
12897
- const msg = `[getPlugins][git] ${v.name} \u8981\u6C42 node-karin \u7248\u672C\u4E3A ${engines}\uFF0C\u5F53\u524D\u4E0D\u7B26\u5408\u8981\u6C42\uFF0C\u8DF3\u8FC7\u52A0\u8F7D\u63D2\u4EF6`;
12898
- isInit && setTimeout(() => logger.error(msg), 1e3);
12899
- return;
13003
+ const ignore = pkg2?.karin?.ignoreEngines === true;
13004
+ const preferred = typeof pkg2?.karin?.engines === "string" ? pkg2.karin.engines.trim() : "";
13005
+ let fallback = "";
13006
+ if (!preferred) {
13007
+ if (typeof pkg2?.engines?.karin === "string") fallback = pkg2.engines.karin.trim();
13008
+ else if (typeof pkg2?.engines?.["node-karin"] === "string") fallback = pkg2.engines["node-karin"].trim();
13009
+ }
13010
+ const range3 = preferred || fallback;
13011
+ if (range3 && !satisfies(range3, process.env.KARIN_VERSION)) {
13012
+ if (ignore) {
13013
+ list2.push(`git:${v.name}`);
13014
+ } else {
13015
+ reporter.add(v.name, range3);
13016
+ }
13017
+ } else {
13018
+ list2.push(`git:${v.name}`);
12900
13019
  }
12901
- list2.push(`git:${v.name}`);
12902
13020
  })
12903
13021
  );
13022
+ await reporter.flush(isInit, process.env.KARIN_VERSION);
12904
13023
  const root = await requireFile("./package.json");
12905
13024
  if (root.name && root.karin) list2.push(`root:${root.name}`);
12906
13025
  };
@@ -12931,28 +13050,37 @@ var init_list = __esm({
12931
13050
  ];
12932
13051
  collectNpmPlugins = async (list2) => {
12933
13052
  logger.debug("[collectNpmPlugins] \u5F00\u59CB\u6536\u96C6NPM\u63D2\u4EF6");
12934
- const pkg2 = await requireFile("./package.json", { force: true });
13053
+ const rootPkg = await requireFile("./package.json", { force: true });
13054
+ const reporter = createPluginMismatchReporter();
12935
13055
  const dependencies = [
12936
- ...Object.keys(pkg2.dependencies || {}),
12937
- ...Object.keys(pkg2.devDependencies || {})
13056
+ ...Object.keys(rootPkg.dependencies || {}),
13057
+ ...Object.keys(rootPkg.devDependencies || {})
12938
13058
  ].filter((name) => !NPM_EXCLUDE_LIST.includes(name) && !name.startsWith("@types"));
12939
13059
  await Promise.allSettled(
12940
13060
  dependencies.map(async (name) => {
12941
13061
  const file2 = path4.join(process.cwd(), "node_modules", name, "package.json");
12942
- const pkg3 = await requireFile(file2);
12943
- if (!pkg3.karin) return;
12944
- const engines = pkg3.karin?.engines?.karin || pkg3.engines?.karin;
12945
- if (engines) {
12946
- if (!satisfies(engines, process.env.KARIN_VERSION)) {
12947
- isInit && logger.error(
12948
- `[getPlugins][npm] ${name} \u8981\u6C42 node-karin \u7248\u672C\u4E3A ${engines}\uFF0C\u5F53\u524D\u4E0D\u7B26\u5408\u8981\u6C42\uFF0C\u8DF3\u8FC7\u52A0\u8F7D\u63D2\u4EF6`
12949
- );
12950
- return;
13062
+ const depPkg = await requireFile(file2);
13063
+ if (!depPkg.karin) return;
13064
+ const ignore = depPkg?.karin?.ignoreEngines === true;
13065
+ const preferred = typeof depPkg?.karin?.engines === "string" ? depPkg.karin.engines.trim() : "";
13066
+ let fallback = "";
13067
+ if (!preferred) {
13068
+ if (typeof depPkg?.engines?.karin === "string") fallback = depPkg.engines.karin.trim();
13069
+ else if (typeof depPkg?.engines?.["node-karin"] === "string") fallback = depPkg.engines["node-karin"].trim();
13070
+ }
13071
+ const range3 = preferred || fallback;
13072
+ if (range3 && !satisfies(range3, process.env.KARIN_VERSION)) {
13073
+ if (ignore) {
13074
+ list2.push(`npm:${name}`);
13075
+ } else {
13076
+ reporter.add(name, range3);
12951
13077
  }
13078
+ } else {
13079
+ list2.push(`npm:${name}`);
12952
13080
  }
12953
- list2.push(`npm:${name}`);
12954
13081
  })
12955
13082
  );
13083
+ await reporter.flush(isInit, process.env.KARIN_VERSION);
12956
13084
  };
12957
13085
  collectAllPlugins = async (files, list2) => {
12958
13086
  await Promise.all([
@@ -22350,6 +22478,10 @@ var init_logger = __esm({
22350
22478
  return logger3.info(logger3.violet(`[Bot:${id}]`), ...args);
22351
22479
  }
22352
22480
  };
22481
+ logger3.setContextLayouts("pattern", {
22482
+ type: "pattern",
22483
+ pattern: "[%d{hh:mm:ss.SSS}][%4.4p] %m"
22484
+ });
22353
22485
  return logger3;
22354
22486
  };
22355
22487
  createLogger = () => {
@@ -22725,23 +22857,49 @@ var init_load = __esm({
22725
22857
  init_cache();
22726
22858
  init_utils();
22727
22859
  init_tools2();
22860
+ init_system2();
22728
22861
  init_class();
22729
22862
  init_file();
22730
22863
  init_import();
22731
22864
  init_internal();
22732
22865
  init_list();
22866
+ init_versionCheck();
22733
22867
  seq = 0;
22734
22868
  pkgLoads = async (pkg2, allPromises) => {
22869
+ const reporter = createPluginMismatchReporter();
22870
+ let isCompatible = true;
22871
+ let shouldLoad = true;
22872
+ if (pkg2.type !== "app") {
22873
+ const ignoreEngines = pkg2.pkgData?.karin?.ignoreEngines === true;
22874
+ const preferred = typeof pkg2.pkgData?.karin?.engines === "string" ? String(pkg2.pkgData.karin.engines).trim() : "";
22875
+ let fallback = "";
22876
+ if (!preferred) {
22877
+ if (typeof pkg2.pkgData?.engines?.karin === "string") fallback = String(pkg2.pkgData.engines.karin).trim();
22878
+ else if (typeof pkg2.pkgData?.engines?.["node-karin"] === "string") fallback = String(pkg2.pkgData.engines["node-karin"]).trim();
22879
+ }
22880
+ const range3 = preferred || fallback;
22881
+ isCompatible = !range3 || satisfies(range3, process.env.KARIN_VERSION);
22882
+ if (range3 && !isCompatible) {
22883
+ if (!ignoreEngines) {
22884
+ reporter.add(pkg2.name, range3);
22885
+ await reporter.flush(true, process.env.KARIN_VERSION);
22886
+ shouldLoad = false;
22887
+ }
22888
+ }
22889
+ }
22890
+ if (!shouldLoad) {
22891
+ return;
22892
+ }
22735
22893
  pkg2.id = ++seq;
22736
22894
  cache3.index[pkg2.id] = pkg2;
22737
22895
  const files = [];
22738
22896
  if (pkg2.type === "app") {
22739
22897
  files.push("config", "data", "resources");
22740
- } else if (Array.isArray(pkg2.pkgData.karin?.files)) {
22898
+ } else if (pkg2.pkgData.karin?.files && Array.isArray(pkg2.pkgData.karin?.files)) {
22741
22899
  files.push(...pkg2.pkgData.karin.files);
22742
22900
  }
22743
22901
  await createPluginDir(pkg2.name, files);
22744
- if (pkg2.type !== "app") {
22902
+ if (pkg2.type !== "app" && shouldLoad) {
22745
22903
  const main2 = pkg2.type === "npm" || !isTs() ? await loadMainFile(pkg2, pkg2.pkgData?.main) : await loadMainFile(pkg2, pkg2.pkgData?.karin?.main);
22746
22904
  if (main2 && main2.KARIN_PLUGIN_INIT) {
22747
22905
  try {
@@ -22752,7 +22910,7 @@ var init_load = __esm({
22752
22910
  }
22753
22911
  }
22754
22912
  }
22755
- pkg2.apps.forEach((app5) => {
22913
+ shouldLoad && pkg2.apps.forEach((app5) => {
22756
22914
  const promise = async () => {
22757
22915
  const result = await pkgLoadModule(pkg2.name, app5);
22758
22916
  pkgCache(result, pkg2, app5);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-karin",
3
- "version": "1.12.2",
3
+ "version": "1.13.0",
4
4
  "description": "Lightweight, efficient, concise, and stable robot framework.",
5
5
  "keywords": [
6
6
  "node",
@@ -166,7 +166,7 @@
166
166
  "chokidar": "4.0.3",
167
167
  "express": "npm:@karinjs/express@1.0.3",
168
168
  "lodash": "npm:@karinjs/lodash@1.1.1",
169
- "log4js": "^6.9.1",
169
+ "log4js": "npm:@karinjs/log4js@1.5.4",
170
170
  "moment": "npm:@karinjs/moment@1.1.5",
171
171
  "node-schedule": "npm:@karinjs/node-schedule@1.0.0",
172
172
  "redis": "npm:@karinjs/redis@1.1.3",