@wanghaopeng1148/deskpet 2.0.2 → 2.0.3

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.
@@ -220,12 +220,16 @@ async function main() {
220
220
  startHeartbeat();
221
221
  scheduler.start({ recover: instanceLock.acquired });
222
222
  // 开机自启:启动时应用 + 跟随设置变化
223
+ // removeWhenOff: false —— 启动时的同步只「确保开启时文件存在」,不删除。
224
+ // 否则一个用默认配置(autoStart=false)起来的实例(例如临时跑一次 npx,
225
+ // 或换了 DESKPET_HOME)会把主实例写在同一个启动文件夹里的自启文件删掉。
223
226
  let lastAutoStart = config.get().system.autoStart;
224
- void setAutoStart(lastAutoStart);
227
+ void setAutoStart(lastAutoStart, { removeWhenOff: false });
225
228
  config.on('changed', () => {
226
229
  const next = config.get().system.autoStart;
227
230
  if (next !== lastAutoStart) {
228
231
  lastAutoStart = next;
232
+ // 用户在设置页显式切换 → 关闭时应当真的移除文件
229
233
  void setAutoStart(next);
230
234
  }
231
235
  });
@@ -22,12 +22,19 @@
22
22
  */
23
23
  import { existsSync, mkdirSync, unlinkSync, writeFileSync } from 'node:fs';
24
24
  import { homedir } from 'node:os';
25
- import { dirname, join, resolve } from 'node:path';
26
- import { fileURLToPath } from 'node:url';
25
+ import { dirname, join } from 'node:path';
26
+ import { getPackageRoot } from "./paths.js";
27
27
  const APP_ID = 'DeskPet';
28
- /** 应用根目录(源码运行为项目根,npm 包运行为包根) */
28
+ /**
29
+ * 应用根目录。
30
+ *
31
+ * 用 getPackageRoot() 向上查找 package.json,而不是写死 `../..`:
32
+ * 源码运行时本模块在 `server/utils/`,编译产物在 `dist/node/server/utils/`,
33
+ * 距包根的层数不同 —— 写死层级会让**从 npm 安装版开启自启**生成一个指向
34
+ * 不存在路径的启动脚本(开机静默失败)。
35
+ */
29
36
  function appRoot() {
30
- return resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
37
+ return getPackageRoot();
31
38
  }
32
39
  /** 开机要执行的 node 可执行文件与入口脚本 */
33
40
  function launch() {
@@ -106,9 +113,9 @@ function linuxDesktopContent() {
106
113
  ''
107
114
  ].join('\n');
108
115
  }
109
- // ── 对外接口 ────────────────────────────────────────────────
110
116
  /** 开启 / 关闭开机自启,返回是否成功(失败原因会打印到日志) */
111
- export async function setAutoStart(on) {
117
+ export async function setAutoStart(on, opts = {}) {
118
+ const removeWhenOff = opts.removeWhenOff ?? true;
112
119
  try {
113
120
  if (process.platform === 'win32') {
114
121
  const dir = winStartupDir();
@@ -129,7 +136,7 @@ export async function setAutoStart(on) {
129
136
  writeFileSync(file, winCmdContent(), 'utf-8');
130
137
  console.log(`[autostart] 开机自启已开启: ${file}`);
131
138
  }
132
- else if (existsSync(file)) {
139
+ else if (removeWhenOff && existsSync(file)) {
133
140
  unlinkSync(file);
134
141
  console.log('[autostart] 开机自启已关闭');
135
142
  }
@@ -142,7 +149,7 @@ export async function setAutoStart(on) {
142
149
  writeFileSync(file, macPlistContent(), 'utf-8');
143
150
  console.log(`[autostart] 开机自启已开启: ${file}`);
144
151
  }
145
- else if (existsSync(file)) {
152
+ else if (removeWhenOff && existsSync(file)) {
146
153
  unlinkSync(file);
147
154
  console.log('[autostart] 开机自启已关闭');
148
155
  }
@@ -155,7 +162,7 @@ export async function setAutoStart(on) {
155
162
  writeFileSync(file, linuxDesktopContent(), 'utf-8');
156
163
  console.log(`[autostart] 开机自启已开启: ${file}`);
157
164
  }
158
- else if (existsSync(file)) {
165
+ else if (removeWhenOff && existsSync(file)) {
159
166
  unlinkSync(file);
160
167
  console.log('[autostart] 开机自启已关闭');
161
168
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wanghaopeng1148/deskpet",
3
3
  "productName": "DeskPet",
4
- "version": "2.0.2",
4
+ "version": "2.0.3",
5
5
  "description": "DeskPet 2.0 — 本机任务自动化服务 + Web 管理台 (Node + Express + Vue 3 + TypeScript)",
6
6
  "type": "module",
7
7
  "author": "whp",
package/server/main.ts CHANGED
@@ -239,12 +239,16 @@ async function main(): Promise<void> {
239
239
  scheduler.start({ recover: instanceLock.acquired })
240
240
 
241
241
  // 开机自启:启动时应用 + 跟随设置变化
242
+ // removeWhenOff: false —— 启动时的同步只「确保开启时文件存在」,不删除。
243
+ // 否则一个用默认配置(autoStart=false)起来的实例(例如临时跑一次 npx,
244
+ // 或换了 DESKPET_HOME)会把主实例写在同一个启动文件夹里的自启文件删掉。
242
245
  let lastAutoStart = config.get().system.autoStart
243
- void setAutoStart(lastAutoStart)
246
+ void setAutoStart(lastAutoStart, { removeWhenOff: false })
244
247
  config.on('changed', () => {
245
248
  const next = config.get().system.autoStart
246
249
  if (next !== lastAutoStart) {
247
250
  lastAutoStart = next
251
+ // 用户在设置页显式切换 → 关闭时应当真的移除文件
248
252
  void setAutoStart(next)
249
253
  }
250
254
  })
@@ -22,14 +22,21 @@
22
22
  */
23
23
  import { existsSync, mkdirSync, unlinkSync, writeFileSync } from 'node:fs'
24
24
  import { homedir } from 'node:os'
25
- import { dirname, join, resolve } from 'node:path'
26
- import { fileURLToPath } from 'node:url'
25
+ import { dirname, join } from 'node:path'
26
+ import { getPackageRoot } from './paths.ts'
27
27
 
28
28
  const APP_ID = 'DeskPet'
29
29
 
30
- /** 应用根目录(源码运行为项目根,npm 包运行为包根) */
30
+ /**
31
+ * 应用根目录。
32
+ *
33
+ * 用 getPackageRoot() 向上查找 package.json,而不是写死 `../..`:
34
+ * 源码运行时本模块在 `server/utils/`,编译产物在 `dist/node/server/utils/`,
35
+ * 距包根的层数不同 —— 写死层级会让**从 npm 安装版开启自启**生成一个指向
36
+ * 不存在路径的启动脚本(开机静默失败)。
37
+ */
31
38
  function appRoot(): string {
32
- return resolve(dirname(fileURLToPath(import.meta.url)), '..', '..')
39
+ return getPackageRoot()
33
40
  }
34
41
 
35
42
  /** 开机要执行的 node 可执行文件与入口脚本 */
@@ -123,8 +130,22 @@ function linuxDesktopContent(): string {
123
130
 
124
131
  // ── 对外接口 ────────────────────────────────────────────────
125
132
 
133
+ export interface AutoStartOptions {
134
+ /**
135
+ * 配置为「关闭」时是否删除自启文件(默认 true)。
136
+ *
137
+ * 启动时的同步必须传 false:多个实例可能共用同一个启动文件夹,
138
+ * 一个以默认配置(autoStart=false)起来的实例不该把别人的自启文件删掉。
139
+ * 这个坑很隐蔽 —— 临时跑一次 `npx deskpet`(数据目录是全新的默认配置)
140
+ * 就会把主实例的开机自启悄悄弄没,之后每次开机都得手动启动。
141
+ * 关闭自启只应由「设置页里显式关掉开关」这个动作来执行。
142
+ */
143
+ removeWhenOff?: boolean
144
+ }
145
+
126
146
  /** 开启 / 关闭开机自启,返回是否成功(失败原因会打印到日志) */
127
- export async function setAutoStart(on: boolean): Promise<boolean> {
147
+ export async function setAutoStart(on: boolean, opts: AutoStartOptions = {}): Promise<boolean> {
148
+ const removeWhenOff = opts.removeWhenOff ?? true
128
149
  try {
129
150
  if (process.platform === 'win32') {
130
151
  const dir = winStartupDir()
@@ -145,7 +166,7 @@ export async function setAutoStart(on: boolean): Promise<boolean> {
145
166
  if (on) {
146
167
  writeFileSync(file, winCmdContent(), 'utf-8')
147
168
  console.log(`[autostart] 开机自启已开启: ${file}`)
148
- } else if (existsSync(file)) {
169
+ } else if (removeWhenOff && existsSync(file)) {
149
170
  unlinkSync(file)
150
171
  console.log('[autostart] 开机自启已关闭')
151
172
  }
@@ -158,7 +179,7 @@ export async function setAutoStart(on: boolean): Promise<boolean> {
158
179
  mkdirSync(dirname(file), { recursive: true })
159
180
  writeFileSync(file, macPlistContent(), 'utf-8')
160
181
  console.log(`[autostart] 开机自启已开启: ${file}`)
161
- } else if (existsSync(file)) {
182
+ } else if (removeWhenOff && existsSync(file)) {
162
183
  unlinkSync(file)
163
184
  console.log('[autostart] 开机自启已关闭')
164
185
  }
@@ -171,7 +192,7 @@ export async function setAutoStart(on: boolean): Promise<boolean> {
171
192
  mkdirSync(dirname(file), { recursive: true })
172
193
  writeFileSync(file, linuxDesktopContent(), 'utf-8')
173
194
  console.log(`[autostart] 开机自启已开启: ${file}`)
174
- } else if (existsSync(file)) {
195
+ } else if (removeWhenOff && existsSync(file)) {
175
196
  unlinkSync(file)
176
197
  console.log('[autostart] 开机自启已关闭')
177
198
  }