koishi-plugin-kkk 3.3.1 → 3.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # 更新日志
2
2
 
3
+ ## 3.3.2
4
+
5
+ > 修 3.3.1 的一个**致命笔误**:播放器模块里一行 import 多写了一层 `..`,导致插件在**加载时**就失败(`Cannot find module '../../compat/runtime'`),整个插件都起不来。构建链路只做转译不解析路径,所以当时没拦住 —— 现在补了一个「每个编译产物都 require 得动」的自测(scripts/smoke-require.cjs)。
6
+
3
7
  ## 3.3.1
4
8
 
5
9
  > 3.3.0-beta.1 ~ beta.3 是给先行测试的人用的预览版,内容全部并进这一版;从 3.2.2 直接升上来就行。
@@ -64,7 +64,8 @@ const node_fs_1 = __importDefault(require("node:fs"));
64
64
  const node_http_1 = __importDefault(require("node:http"));
65
65
  const node_path_1 = __importDefault(require("node:path"));
66
66
  const node_karin_1 = require("../compat/node-karin.js");
67
- const runtime_1 = require("../../compat/runtime");
67
+ // 注意只有一层 .. :src/player/server.ts → src/compat/runtime(写两层会变成根目录下的 compat,直接 MODULE_NOT_FOUND)
68
+ const runtime_1 = require("../compat/runtime");
68
69
  const page_1 = require("./page");
69
70
  const store_1 = require("./store");
70
71
  /** 路由前缀 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-kkk",
3
- "version": "3.3.1",
3
+ "version": "3.3.2",
4
4
  "description": "抖音 / B站 / 快手 / 小红书 视频解析与动态推送,带 QQ 交互面板与弹幕烧录(karin-plugin-kkk 的 Koishi 移植版)",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -0,0 +1,91 @@
1
+ /**
2
+ * 「每个编译产物都 require 得动」冒烟测试。
3
+ *
4
+ * 起因(线上真实故障):给 player/server.ts 加了一行
5
+ * `import { tryGetRuntime } from '../../compat/runtime'` —— 多写了一层 `..`,
6
+ * 编译出来变成 `require("../../compat/runtime")`(指向插件根目录下的 compat,不存在)。
7
+ * TypeScript 那条链路只做转译、不解析路径,构建时毫无提示;**插件在用户机器上直接加载失败**:
8
+ *
9
+ * [W] config failed to load kkk
10
+ * Error: Cannot find module '../../compat/runtime'
11
+ *
12
+ * 这个测试就是把 lib 下每个 .js 都 require 一遍 —— 路径写错、模块顶层就抛异常,全都跑不掉。
13
+ *
14
+ * 用法:node scripts/smoke-require.cjs
15
+ */
16
+ const fs = require('node:fs')
17
+ const path = require('node:path')
18
+ const { createRequire } = require('node:module')
19
+
20
+ const pluginRoot = path.resolve(__dirname, '..')
21
+ const libRoot = path.join(pluginRoot, 'lib')
22
+
23
+ /** 绑定最小运行时:很多模块在顶层就读配置/日志 */
24
+ const runtime = require(path.join(libRoot, 'compat', 'runtime.js'))
25
+ const noop = () => {}
26
+ runtime.bindRuntime({
27
+ ctx: {
28
+ get: () => undefined,
29
+ logger: () => ({ info: noop, warn: noop, error: noop, debug: noop, mark: noop }),
30
+ bots: [],
31
+ registry: new Map(),
32
+ on: noop,
33
+ middleware: noop
34
+ },
35
+ config: { app: {} },
36
+ dataRoot: path.join(pluginRoot, 'data-smoke-require'),
37
+ pluginRoot,
38
+ master: () => []
39
+ })
40
+
41
+ const walk = (dir) => {
42
+ const out = []
43
+ for (const item of fs.readdirSync(dir, { withFileTypes: true })) {
44
+ const full = path.join(dir, item.name)
45
+ if (item.isDirectory()) out.push(...walk(full))
46
+ else if (item.name.endsWith('.js')) out.push(full)
47
+ }
48
+ return out
49
+ }
50
+
51
+ const req = createRequire(path.join(libRoot, 'index.js'))
52
+ const files = walk(libRoot)
53
+ const failures = []
54
+ let ok = 0
55
+ let esm = 0
56
+ /** 缺第三方依赖(宿主没装)的模块:单独列出,不算失败 */
57
+ const optional = []
58
+ for (const file of files) {
59
+ try {
60
+ req(file)
61
+ ok++
62
+ } catch (error) {
63
+ const message = String(error?.message ?? error)
64
+ /** 模板类模块是 ESM(用 import 加载的),require 报这个是**预期**的,不算失败 */
65
+ const isEsm = error?.code === 'ERR_REQUIRE_ESM' || error?.code === 'ERR_REQUIRE_ASYNC_MODULE'
66
+ || /Cannot use import statement outside a module|require\(\) of ES Module/.test(message)
67
+ if (isEsm) { esm++; continue }
68
+ /**
69
+ * 缺**第三方包**(cors / node:sqlite 之类)不算这次要抓的问题:有些模块是动态 import 的可选路径,
70
+ * 依赖装没装取决于宿主环境。**相对路径**找不到才是真问题(就是这次线上的那种),照旧算失败。
71
+ */
72
+ const missing = /Cannot find module '([^']+)'/.exec(message)
73
+ if (missing && !missing[1].startsWith('.')) {
74
+ optional.push(path.relative(libRoot, file) + ' → 缺依赖 ' + missing[1])
75
+ continue
76
+ }
77
+ failures.push({ file: path.relative(libRoot, file), message })
78
+ }
79
+ }
80
+
81
+ console.log('检查了 ' + files.length + ' 个编译产物:require 成功 ' + ok + ' 个,ESM(预期跳过)' + esm + ' 个,缺第三方依赖(预期跳过)' + optional.length + ' 个')
82
+ for (const item of optional) console.log(' · ' + item)
83
+ if (failures.length === 0) {
84
+ console.log('\n=== 通过:每个模块都加载得动(没有写错的 import 路径 / 顶层异常) ===')
85
+ // 用 process.exit:require 这些模块时可能有别的东西把 exitCode 置成了非 0
86
+ process.exit(0)
87
+ } else {
88
+ for (const item of failures) console.log(' ❌ ' + item.file + ' → ' + item.message.split('\n')[0])
89
+ console.log('\n=== 失败:' + failures.length + ' 个模块加载不了 ===')
90
+ process.exit(1)
91
+ }
@@ -23,7 +23,8 @@ import path from 'node:path'
23
23
 
24
24
  import { logger } from 'node-karin'
25
25
 
26
- import { tryGetRuntime } from '../../compat/runtime'
26
+ // 注意只有一层 .. :src/player/server.ts → src/compat/runtime(写两层会变成根目录下的 compat,直接 MODULE_NOT_FOUND)
27
+ import { tryGetRuntime } from '../compat/runtime'
27
28
 
28
29
  import { renderExpiredPage, renderPlayerPage } from './page'
29
30
  import {