napcat-plugin-debug-cli 1.2.7 → 1.2.8

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 (3) hide show
  1. package/cli.mjs +49 -21
  2. package/package.json +1 -1
  3. package/vite.mjs +65 -23
package/cli.mjs CHANGED
@@ -5242,6 +5242,15 @@ function createWatcher(watchPath, onPluginChange) {
5242
5242
  }
5243
5243
  };
5244
5244
  }
5245
+ function copyDirRecursive(src, dest) {
5246
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
5247
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
5248
+ const srcPath = path.join(src, entry.name);
5249
+ const destPath = path.join(dest, entry.name);
5250
+ if (entry.isDirectory()) copyDirRecursive(srcPath, destPath);
5251
+ else fs.copyFileSync(srcPath, destPath);
5252
+ }
5253
+ }
5245
5254
  function collectFiles(dir, prefix = "") {
5246
5255
  const files = [];
5247
5256
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
@@ -5267,7 +5276,7 @@ function countFiles(dir) {
5267
5276
  }
5268
5277
  return count;
5269
5278
  }
5270
- async function deployPlugin(projectDir, remotePluginPath, rpc) {
5279
+ async function deployPlugin(projectDir, remotePluginPath, rpc, supportsRemoteTransfer) {
5271
5280
  const distDir = path.resolve(projectDir, "dist");
5272
5281
  if (!fs.existsSync(distDir)) {
5273
5282
  logErr(`dist/ 目录不存在: ${distDir}`);
@@ -5293,30 +5302,42 @@ async function deployPlugin(projectDir, remotePluginPath, rpc) {
5293
5302
  }
5294
5303
  logInfo(`部署 ${co(pluginName, C.bold, C.cyan)} → 远程插件目录`);
5295
5304
  try {
5296
- await rpc.call("removeDir", pluginName);
5297
- const files = collectFiles(distDir, pluginName);
5298
- await rpc.call("writeFiles", files);
5299
- logOk(`文件传输完成 (${countFiles(distDir)} 个文件)`);
5305
+ if (supportsRemoteTransfer) {
5306
+ await rpc.call("removeDir", pluginName);
5307
+ const files = collectFiles(distDir, pluginName);
5308
+ await rpc.call("writeFiles", files);
5309
+ } else {
5310
+ const destPath = path.join(remotePluginPath, pluginName);
5311
+ if (fs.existsSync(destPath)) {
5312
+ fs.rmSync(destPath, { recursive: true, force: true });
5313
+ }
5314
+ copyDirRecursive(distDir, destPath);
5315
+ }
5316
+ logOk(`文件部署完成 (${countFiles(distDir)} 个文件)`);
5300
5317
  } catch (e) {
5301
5318
  logErr(`部署失败: ${e.message}`);
5302
5319
  return false;
5303
5320
  }
5304
5321
  try {
5305
- await rpc.call("reloadPlugin", pluginName);
5306
- logOk(`${co(pluginName, C.green, C.bold)} 重载成功`);
5307
- } catch {
5308
- try {
5309
- logInfo("插件未注册,尝试从目录加载...");
5310
- await rpc.call("loadDirectoryPlugin", pluginName);
5322
+ const ok = await rpc.call("reloadPlugin", pluginName);
5323
+ if (ok) {
5324
+ logOk(`${co(pluginName, C.green, C.bold)} 重载成功`);
5325
+ } else {
5326
+ logInfo("插件未注册或重载失败,尝试从目录加载...");
5311
5327
  try {
5312
- await rpc.call("setPluginStatus", pluginName, true);
5313
- await rpc.call("loadPluginById", pluginName);
5314
- } catch {
5328
+ await rpc.call("loadDirectoryPlugin", pluginName);
5329
+ try {
5330
+ await rpc.call("setPluginStatus", pluginName, true);
5331
+ await rpc.call("loadPluginById", pluginName);
5332
+ } catch {
5333
+ }
5334
+ logOk(`${co(pluginName, C.green, C.bold)} 首次加载成功`);
5335
+ } catch (e2) {
5336
+ logWarn(`自动加载失败: ${e2.message},请手动 load ${pluginName}`);
5315
5337
  }
5316
- logOk(`${co(pluginName, C.green, C.bold)} 首次加载成功`);
5317
- } catch (e2) {
5318
- logWarn(`自动加载失败: ${e2.message},请手动 load ${pluginName}`);
5319
5338
  }
5339
+ } catch (e) {
5340
+ logErr(`重载失败: ${e.message}`);
5320
5341
  }
5321
5342
  return true;
5322
5343
  }
@@ -5335,6 +5356,7 @@ async function main() {
5335
5356
  let rpc = null;
5336
5357
  let watcher = null;
5337
5358
  let remotePluginPath = null;
5359
+ let supportsRemoteTransfer = false;
5338
5360
  const dirToId = /* @__PURE__ */ new Map();
5339
5361
  async function refreshMap() {
5340
5362
  if (!rpc) return;
@@ -5372,8 +5394,14 @@ async function main() {
5372
5394
  } catch (e) {
5373
5395
  logWarn(`获取信息失败: ${e.message}`);
5374
5396
  }
5397
+ try {
5398
+ await rpc.call("removeDir", "__probe_nonexistent__");
5399
+ supportsRemoteTransfer = true;
5400
+ } catch {
5401
+ supportsRemoteTransfer = false;
5402
+ }
5375
5403
  if (opts.deploy && remotePluginPath && rpc) {
5376
- const ok = await deployPlugin(path.resolve(opts.deploy), remotePluginPath, rpc);
5404
+ const ok = await deployPlugin(path.resolve(opts.deploy), remotePluginPath, rpc, supportsRemoteTransfer);
5377
5405
  ws.close(1e3);
5378
5406
  process.exit(ok ? 0 : 1);
5379
5407
  }
@@ -5384,7 +5412,7 @@ async function main() {
5384
5412
  watcher = createWatcher(remotePluginPath, onFileChange);
5385
5413
  watcher.start();
5386
5414
  }
5387
- startRepl(rpc, watcher, remotePluginPath, onFileChange);
5415
+ startRepl(rpc, watcher, remotePluginPath, onFileChange, supportsRemoteTransfer);
5388
5416
  }
5389
5417
  if (msg.method === "event" && opts.verbose) {
5390
5418
  logInfo(`事件: ${JSON.stringify(msg.params).substring(0, 100)}`);
@@ -5405,7 +5433,7 @@ async function main() {
5405
5433
  process.exit(0);
5406
5434
  });
5407
5435
  }
5408
- function startRepl(rpc, watcher, remotePath, onFileChange) {
5436
+ function startRepl(rpc, watcher, remotePath, onFileChange, supportsRemoteTransfer) {
5409
5437
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: co("debug> ", C.cyan) });
5410
5438
  rl.prompt();
5411
5439
  rl.on("line", async (line) => {
@@ -5490,7 +5518,7 @@ function startRepl(rpc, watcher, remotePath, onFileChange) {
5490
5518
  break;
5491
5519
  }
5492
5520
  const dir = args[0] || ".";
5493
- await deployPlugin(path.resolve(dir), remotePath, rpc);
5521
+ await deployPlugin(path.resolve(dir), remotePath, rpc, supportsRemoteTransfer);
5494
5522
  break;
5495
5523
  }
5496
5524
  case "watch": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "napcat-plugin-debug-cli",
3
- "version": "1.2.7",
3
+ "version": "1.2.8",
4
4
  "type": "module",
5
5
  "description": "NapCat 插件调试 CLI — 连接调试服务实现热重载",
6
6
  "author": "NapNeko",
package/vite.mjs CHANGED
@@ -65,6 +65,15 @@ class SimpleRpcClient {
65
65
  }
66
66
  }
67
67
  }
68
+ function copyDirRecursive(src, dest) {
69
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
70
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
71
+ const srcPath = path.join(src, entry.name);
72
+ const destPath = path.join(dest, entry.name);
73
+ if (entry.isDirectory()) copyDirRecursive(srcPath, destPath);
74
+ else fs.copyFileSync(srcPath, destPath);
75
+ }
76
+ }
68
77
  function countFiles(dir) {
69
78
  let count = 0;
70
79
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
@@ -101,6 +110,7 @@ function napcatHmrPlugin(options = {}) {
101
110
  const webuiConfigs = webui ? Array.isArray(webui) ? webui : [webui] : [];
102
111
  let rpc = null;
103
112
  let remotePluginPath = null;
113
+ let supportsRemoteTransfer = false;
104
114
  let connecting = false;
105
115
  let config;
106
116
  let isFirstBuild = true;
@@ -142,6 +152,12 @@ function napcatHmrPlugin(options = {}) {
142
152
  log(`远程插件目录: ${co(info.pluginPath, C.dim)}`);
143
153
  } catch {
144
154
  }
155
+ try {
156
+ await rpc.call("removeDir", "__probe_nonexistent__");
157
+ supportsRemoteTransfer = true;
158
+ } catch {
159
+ supportsRemoteTransfer = false;
160
+ }
145
161
  connecting = false;
146
162
  resolve(true);
147
163
  }
@@ -156,6 +172,7 @@ function napcatHmrPlugin(options = {}) {
156
172
  ws.on("close", () => {
157
173
  rpc = null;
158
174
  remotePluginPath = null;
175
+ supportsRemoteTransfer = false;
159
176
  connecting = false;
160
177
  });
161
178
  });
@@ -186,18 +203,31 @@ function napcatHmrPlugin(options = {}) {
186
203
  logErr("解析 dist/package.json 失败");
187
204
  return;
188
205
  }
189
- try {
190
- await rpc.call("removeDir", pluginName);
191
- } catch (e) {
192
- logErr(`清理远程目录失败: ${e.message}`);
193
- return;
194
- }
195
- try {
196
- const files = collectFiles(distDir, pluginName);
197
- await rpc.call("writeFiles", files);
198
- } catch (e) {
199
- logErr(`传输文件失败: ${e.message}`);
200
- return;
206
+ if (supportsRemoteTransfer) {
207
+ try {
208
+ await rpc.call("removeDir", pluginName);
209
+ } catch (e) {
210
+ logErr(`清理远程目录失败: ${e.message}`);
211
+ return;
212
+ }
213
+ try {
214
+ const files = collectFiles(distDir, pluginName);
215
+ await rpc.call("writeFiles", files);
216
+ } catch (e) {
217
+ logErr(`传输文件失败: ${e.message}`);
218
+ return;
219
+ }
220
+ } else {
221
+ const destDir = path.join(remotePluginPath, pluginName);
222
+ try {
223
+ if (fs.existsSync(destDir)) {
224
+ fs.rmSync(destDir, { recursive: true, force: true });
225
+ }
226
+ copyDirRecursive(distDir, destDir);
227
+ } catch (e) {
228
+ logErr(`复制文件失败: ${e.message}`);
229
+ return;
230
+ }
201
231
  }
202
232
  const projectRoot = config.root || process.cwd();
203
233
  for (const wc of webuiConfigs) {
@@ -225,20 +255,23 @@ function napcatHmrPlugin(options = {}) {
225
255
  continue;
226
256
  }
227
257
  try {
228
- const webuiFiles = collectFiles(webuiDistDir, `${pluginName}/${webuiTargetDir}`);
229
- await rpc.call("writeFiles", webuiFiles);
258
+ if (supportsRemoteTransfer) {
259
+ const webuiFiles = collectFiles(webuiDistDir, `${pluginName}/${webuiTargetDir}`);
260
+ await rpc.call("writeFiles", webuiFiles);
261
+ } else {
262
+ const destDir = path.join(remotePluginPath, pluginName);
263
+ const webuiDestDir = path.join(destDir, webuiTargetDir);
264
+ copyDirRecursive(webuiDistDir, webuiDestDir);
265
+ }
230
266
  logOk(`WebUI (${webuiTargetDir}) 已部署 (${countFiles(webuiDistDir)} 个文件)`);
231
267
  } catch (e) {
232
268
  logErr(`WebUI (${webuiTargetDir}) 部署失败: ${e.message}`);
233
269
  }
234
270
  }
235
- try {
236
- const reloaded = await rpc.call("reloadPlugin", pluginName);
237
- if (reloaded === false) {
238
- throw new Error("not registered");
239
- }
271
+ const reloaded = await rpc.call("reloadPlugin", pluginName);
272
+ if (reloaded) {
240
273
  logHmr(`${co(pluginName, C.green, C.bold)} 已重载 (${countFiles(distDir)} 个文件)`);
241
- } catch {
274
+ } else {
242
275
  try {
243
276
  await rpc.call("loadDirectoryPlugin", pluginName);
244
277
  try {
@@ -298,9 +331,18 @@ function napcatHmrPlugin(options = {}) {
298
331
  continue;
299
332
  }
300
333
  try {
301
- await rpc.call("removeDir", `${pluginName}/${webuiTargetDir}`);
302
- const webuiFiles = collectFiles(webuiDistDir, `${pluginName}/${webuiTargetDir}`);
303
- await rpc.call("writeFiles", webuiFiles);
334
+ if (supportsRemoteTransfer) {
335
+ await rpc.call("removeDir", `${pluginName}/${webuiTargetDir}`);
336
+ const webuiFiles = collectFiles(webuiDistDir, `${pluginName}/${webuiTargetDir}`);
337
+ await rpc.call("writeFiles", webuiFiles);
338
+ } else {
339
+ const destDir = path.join(remotePluginPath, pluginName);
340
+ const webuiDestDir = path.join(destDir, webuiTargetDir);
341
+ if (fs.existsSync(webuiDestDir)) {
342
+ fs.rmSync(webuiDestDir, { recursive: true, force: true });
343
+ }
344
+ copyDirRecursive(webuiDistDir, webuiDestDir);
345
+ }
304
346
  logOk(`WebUI (${webuiTargetDir}) 已部署 (${countFiles(webuiDistDir)} 个文件)`);
305
347
  hasChanges = true;
306
348
  } catch (e) {