@wanghaopeng1148/deskpet 2.0.6 → 2.0.7

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.
Files changed (2) hide show
  1. package/bin/deskpet.mjs +32 -8
  2. package/package.json +1 -1
package/bin/deskpet.mjs CHANGED
@@ -52,13 +52,24 @@ function newestMtime(dir) {
52
52
  *
53
53
  * 为什么需要:bin 优先跑编译产物,若改了 `server/` 却没重新编译,
54
54
  * 就会**静默跑旧代码**(开机自启走的正是这条路径,最不容易发现)。
55
- * 发布包里 npm 会把所有文件时间统一,两者相等 → 视为产物可用,不受影响。
55
+ *
56
+ * ⚠️ 必须留容差,不能用严格比较。踩过的坑:从 npm 安装时包内所有文件是
57
+ * **同一瞬间解包的**,实测彼此只差几百毫秒、且先后顺序随机 ——
58
+ * `dist/node/server/main.js` 是 22.106,`server/http/ws-hub.ts` 是 22.327,
59
+ * 于是严格 `>` 判定「源码更新」,选了 .ts,在 node_modules 下直接崩
60
+ * (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING)。而且哪次中招纯看解包顺序,
61
+ * 同一版本可能这次好下次坏 —— 极难排查。
62
+ *
63
+ * 真实的手改代码与上次编译之间至少相隔数秒,所以留 3 秒容差:
64
+ * 安装形态下的毫秒级乱序被忽略,真实改动照样能识别。
56
65
  */
66
+ const STALE_TOLERANCE_MS = 3000
67
+
57
68
  function sourceIsNewer() {
58
69
  try {
59
70
  const compiledTime = statSync(compiledEntry).mtimeMs
60
71
  for (const dir of ['server', 'shared']) {
61
- if (newestMtime(join(pkgRoot, dir)) > compiledTime) return true
72
+ if (newestMtime(join(pkgRoot, dir)) > compiledTime + STALE_TOLERANCE_MS) return true
62
73
  }
63
74
  } catch {
64
75
  /* 读不到就按「不更新」处理,退回产物 */
@@ -66,15 +77,26 @@ function sourceIsNewer() {
66
77
  return false
67
78
  }
68
79
 
80
+ /** 路径是否位于 node_modules 之下 */
81
+ function underNodeModules(p) {
82
+ return /[\\/]node_modules[\\/]/i.test(p)
83
+ }
84
+
69
85
  /** 返回 { entry, args }:编译产物无需额外参数 */
70
86
  function resolveServerEntry() {
71
87
  const hasCompiled = existsSync(compiledEntry)
72
88
  const hasSource = existsSync(sourceEntry)
89
+ /**
90
+ * 硬约束:node_modules 下的 .ts **根本跑不起来**(Node 禁止对 node_modules
91
+ * 内的文件做类型擦除)。所以无论新旧判断给出了什么结论,这类入口一律不能用 ——
92
+ * 这是比「新旧」更高优先级的规则,也是上面那个坑的兜底。
93
+ */
94
+ const sourceUsable = hasSource && !underNodeModules(sourceEntry)
73
95
 
74
- if (hasCompiled && !(hasSource && sourceIsNewer())) {
96
+ if (hasCompiled && !(sourceUsable && sourceIsNewer())) {
75
97
  return { entry: compiledEntry, args: [], compiled: true, stale: false }
76
98
  }
77
- if (hasSource) {
99
+ if (sourceUsable) {
78
100
  return {
79
101
  entry: sourceEntry,
80
102
  args: ['--experimental-strip-types'],
@@ -83,10 +105,12 @@ function resolveServerEntry() {
83
105
  stale: hasCompiled
84
106
  }
85
107
  }
86
- console.error('[deskpet] 找不到后端入口。')
87
- console.error(` 已尝试:${compiledEntry}`)
88
- console.error(` ${sourceEntry}`)
89
- console.error(' 源码方式请先执行:npm install && npm run build')
108
+ // 走到这里只有一种情况:没有编译产物,而 .ts 又位于 node_modules 下不能运行
109
+ console.error('[deskpet] 无法启动:包里没有后端编译产物 dist/node,')
110
+ console.error(' 而 server/main.ts 位于 node_modules 下,不能直接运行')
111
+ console.error(' (Node 禁止对 node_modules 内的文件做类型擦除)')
112
+ console.error(` 期望的产物:${compiledEntry}`)
113
+ console.error(' 处理:重装该包(建议先清缓存),或从源码目录执行 npm start')
90
114
  process.exit(1)
91
115
  }
92
116
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wanghaopeng1148/deskpet",
3
3
  "productName": "DeskPet",
4
- "version": "2.0.6",
4
+ "version": "2.0.7",
5
5
  "description": "DeskPet 2.0 — 本机任务自动化服务 + Web 管理台 (Node + Express + Vue 3 + TypeScript)",
6
6
  "type": "module",
7
7
  "author": "whp",