unplugin-devpilot 0.0.2 → 0.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.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # unplugin-devpilot
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
+ [![Unit Test][unit-test-src]][unit-test-href]
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm i -D unplugin-devpilot
11
+ ```
12
+
13
+ <details>
14
+ <summary>Vite</summary><br>
15
+
16
+ ```ts
17
+ // vite.config.ts
18
+ import Devpilot from 'unplugin-devpilot/vite';
19
+
20
+ export default defineConfig({
21
+ plugins: [Devpilot()],
22
+ });
23
+ ```
24
+
25
+ <br></details>
26
+
27
+ <details>
28
+ <summary>Webpack</summary><br>
29
+
30
+ ```js
31
+ // webpack.config.js
32
+ import Devpilot from 'unplugin-devpilot/webpack';
33
+
34
+ export default {
35
+ /* ... */
36
+ plugins: [Devpilot()],
37
+ };
38
+ ```
39
+
40
+ <br></details>
41
+
42
+ <details>
43
+ <summary>Rspack</summary><br>
44
+
45
+ ```ts
46
+ // rspack.config.js
47
+ import Devpilot from 'unplugin-devpilot/rspack';
48
+
49
+ export default {
50
+ /* ... */
51
+ plugins: [Devpilot()],
52
+ };
53
+ ```
54
+
55
+ <br></details>
56
+
57
+ ## Client Import
58
+
59
+ Add this import to your project entry point to enable the devpilot client:
60
+
61
+ ```ts
62
+ // main.ts or main.js (entry point)
63
+ import 'virtual:devpilot-client';
64
+ ```
65
+
66
+ This import activates the WebSocket connection to the development server and initializes all registered plugins on the client side.
67
+
68
+ ## Configuration
69
+
70
+ You can customize the plugin behavior by passing options:
71
+
72
+ ```ts
73
+ // vite.config.ts
74
+ import Devpilot from 'unplugin-devpilot/vite';
75
+
76
+ export default defineConfig({
77
+ plugins: [
78
+ Devpilot({
79
+ wsPort: 3100, // Optional: Specify WebSocket port (will be randomly allocated if not specified)
80
+ mcpPort: 3101, // Optional: Specify MCP server port (will use random port if specified port is occupied)
81
+ plugins: [], // Optional: Array of DevpilotPlugin instances
82
+ }),
83
+ ],
84
+ });
85
+ ```
86
+
87
+ ### Port Allocation Strategy
88
+
89
+ - **wsPort**: When provided, the specified port is used if available; otherwise, a random available port is allocated. When not provided, a random available port is automatically allocated
90
+ - **mcpPort**: When not provided, defaults to 3101. If the port is already in use, an error will be thrown
91
+
92
+ This ensures your MCP server runs on a predictable port. If the default port is occupied, you'll need to specify a different port or free up the occupied port.
93
+
94
+ ## License
95
+
96
+ [MIT](./LICENSE) License © 2025-PRESENT [Huali](https://github.com/zcf0508)
97
+
98
+ <!-- Badges -->
99
+
100
+ [npm-version-src]: https://img.shields.io/npm/v/unplugin-devpilot.svg
101
+ [npm-version-href]: https://npmjs.com/package/unplugin-devpilot
102
+ [npm-downloads-src]: https://img.shields.io/npm/dm/unplugin-devpilot
103
+ [npm-downloads-href]: https://www.npmcharts.com/compare/unplugin-devpilot?interval=30
104
+ [unit-test-src]: https://github.com/zcf0508/unplugin-devpilot/actions/workflows/unit-test.yml/badge.svg
105
+ [unit-test-href]: https://github.com/zcf0508/unplugin-devpilot/actions/workflows/unit-test.yml
package/dist/farm.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot } from "./src-D62s1VAN.mjs";
1
+ import { n as unpluginDevpilot } from "./src-Bm2tOOQC.mjs";
2
2
 
3
3
  //#region src/farm.ts
4
4
  /**
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot, r as clientManager, t as src_default } from "./src-D62s1VAN.mjs";
1
+ import { n as unpluginDevpilot, r as clientManager, t as src_default } from "./src-Bm2tOOQC.mjs";
2
2
  import { n as defineMcpToolRegister, t as resolveClientModule } from "./plugin-BPkoZQbf.mjs";
3
3
 
4
4
  export { clientManager, src_default as default, defineMcpToolRegister, resolveClientModule, unpluginDevpilot };
package/dist/rspack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot } from "./src-D62s1VAN.mjs";
1
+ import { n as unpluginDevpilot } from "./src-Bm2tOOQC.mjs";
2
2
 
3
3
  //#region src/rspack.ts
4
4
  /**
@@ -5,6 +5,10 @@ import { createServer } from "node:http";
5
5
  import { Http2ServerRequest } from "http2";
6
6
  import { Readable } from "stream";
7
7
  import crypto$1 from "crypto";
8
+ import { createServer as createServer$1 } from "node:net";
9
+ import { networkInterfaces } from "node:os";
10
+ import { join } from "node:path";
11
+ import { exec } from "node:child_process";
8
12
 
9
13
  //#region rolldown:runtime
10
14
  var __create = Object.create;
@@ -19793,7 +19797,7 @@ var StreamableHTTPServerTransport = class {
19793
19797
 
19794
19798
  //#endregion
19795
19799
  //#region package.json
19796
- var version = "0.0.2";
19800
+ var version = "0.0.3";
19797
19801
 
19798
19802
  //#endregion
19799
19803
  //#region ../../node_modules/.pnpm/es-toolkit@1.44.0/node_modules/es-toolkit/dist/compat/util/uniqueId.mjs
@@ -20196,16 +20200,184 @@ function stopMcpServer() {
20196
20200
  }
20197
20201
  }
20198
20202
 
20203
+ //#endregion
20204
+ //#region ../../node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs
20205
+ const unsafePorts = /* @__PURE__ */ new Set([
20206
+ 1,
20207
+ 7,
20208
+ 9,
20209
+ 11,
20210
+ 13,
20211
+ 15,
20212
+ 17,
20213
+ 19,
20214
+ 20,
20215
+ 21,
20216
+ 22,
20217
+ 23,
20218
+ 25,
20219
+ 37,
20220
+ 42,
20221
+ 43,
20222
+ 53,
20223
+ 69,
20224
+ 77,
20225
+ 79,
20226
+ 87,
20227
+ 95,
20228
+ 101,
20229
+ 102,
20230
+ 103,
20231
+ 104,
20232
+ 109,
20233
+ 110,
20234
+ 111,
20235
+ 113,
20236
+ 115,
20237
+ 117,
20238
+ 119,
20239
+ 123,
20240
+ 135,
20241
+ 137,
20242
+ 139,
20243
+ 143,
20244
+ 161,
20245
+ 179,
20246
+ 389,
20247
+ 427,
20248
+ 465,
20249
+ 512,
20250
+ 513,
20251
+ 514,
20252
+ 515,
20253
+ 526,
20254
+ 530,
20255
+ 531,
20256
+ 532,
20257
+ 540,
20258
+ 548,
20259
+ 554,
20260
+ 556,
20261
+ 563,
20262
+ 587,
20263
+ 601,
20264
+ 636,
20265
+ 989,
20266
+ 990,
20267
+ 993,
20268
+ 995,
20269
+ 1719,
20270
+ 1720,
20271
+ 1723,
20272
+ 2049,
20273
+ 3659,
20274
+ 4045,
20275
+ 5060,
20276
+ 5061,
20277
+ 6e3,
20278
+ 6566,
20279
+ 6665,
20280
+ 6666,
20281
+ 6667,
20282
+ 6668,
20283
+ 6669,
20284
+ 6697,
20285
+ 10080
20286
+ ]);
20287
+ function isUnsafePort(port) {
20288
+ return unsafePorts.has(port);
20289
+ }
20290
+ function isSafePort(port) {
20291
+ return !isUnsafePort(port);
20292
+ }
20293
+ var GetPortError = class extends Error {
20294
+ constructor(message, opts) {
20295
+ super(message, opts);
20296
+ this.message = message;
20297
+ }
20298
+ name = "GetPortError";
20299
+ };
20300
+ function _log(verbose, message) {
20301
+ if (verbose) console.log(`[get-port] ${message}`);
20302
+ }
20303
+ function _tryPort(port, host) {
20304
+ return new Promise((resolve) => {
20305
+ const server = createServer$1();
20306
+ server.unref();
20307
+ server.on("error", () => {
20308
+ resolve(false);
20309
+ });
20310
+ server.listen({
20311
+ port,
20312
+ host
20313
+ }, () => {
20314
+ const { port: port2 } = server.address();
20315
+ server.close(() => {
20316
+ resolve(isSafePort(port2) && port2);
20317
+ });
20318
+ });
20319
+ });
20320
+ }
20321
+ function _getLocalHosts(additional) {
20322
+ const hosts = new Set(additional);
20323
+ for (const _interface of Object.values(networkInterfaces())) for (const config of _interface || []) if (config.address && !config.internal && !config.address.startsWith("fe80::") && !config.address.startsWith("169.254")) hosts.add(config.address);
20324
+ return [...hosts];
20325
+ }
20326
+ function _fmtOnHost(hostname) {
20327
+ return hostname ? `on host ${JSON.stringify(hostname)}` : "on any host";
20328
+ }
20329
+ async function getRandomPort(host) {
20330
+ const port = await checkPort(0, host);
20331
+ if (port === false) throw new GetPortError(`Unable to find a random port ${_fmtOnHost(host)}`);
20332
+ return port;
20333
+ }
20334
+ async function checkPort(port, host = process.env.HOST, verbose) {
20335
+ if (!host) host = _getLocalHosts([void 0, "0.0.0.0"]);
20336
+ if (!Array.isArray(host)) return _tryPort(port, host);
20337
+ for (const _host of host) {
20338
+ const _port = await _tryPort(port, _host);
20339
+ if (_port === false) {
20340
+ if (port < 1024 && verbose) _log(verbose, `Unable to listen to the privileged port ${port} ${_fmtOnHost(_host)}`);
20341
+ return false;
20342
+ }
20343
+ if (port === 0 && _port !== 0) port = _port;
20344
+ }
20345
+ return port;
20346
+ }
20347
+
20199
20348
  //#endregion
20200
20349
  //#region src/core/options.ts
20201
- function resolveOptions(options) {
20350
+ async function resolveOptions(options) {
20351
+ let wsPort;
20352
+ if (options.wsPort !== void 0) if (await checkPort(options.wsPort) === false) wsPort = options.wsPort;
20353
+ else wsPort = await getRandomPort();
20354
+ else wsPort = await getRandomPort();
20355
+ const preferredMcpPort = options.mcpPort || 3101;
20356
+ if (await checkPort(preferredMcpPort) === false) throw new Error(`MCP port ${preferredMcpPort} is already in use. Please specify a different port or free up the port.`);
20202
20357
  return {
20203
- wsPort: options.wsPort || 3100,
20204
- mcpPort: options.mcpPort || 3101,
20358
+ wsPort,
20359
+ mcpPort: preferredMcpPort,
20205
20360
  plugins: options.plugins || []
20206
20361
  };
20207
20362
  }
20208
20363
 
20364
+ //#endregion
20365
+ //#region src/core/utils.ts
20366
+ /**
20367
+ * npx free-port :port
20368
+ */
20369
+ async function killPort(port) {
20370
+ return new Promise((resolve, reject) => {
20371
+ exec(`npx -y @maxbo/free-port ${port} -s`, (err, stdout, _stderr) => {
20372
+ if (err) reject(err);
20373
+ else {
20374
+ console.log(stdout);
20375
+ resolve();
20376
+ }
20377
+ });
20378
+ });
20379
+ }
20380
+
20209
20381
  //#endregion
20210
20382
  //#region ../../node_modules/.pnpm/birpc@4.0.0/node_modules/birpc/dist/index.mjs
20211
20383
  const TYPE_REQUEST = "q";
@@ -24025,22 +24197,29 @@ ${handlerCollection}
24025
24197
  `;
24026
24198
  }
24027
24199
  const unpluginDevpilot = createUnplugin((rawOptions = {}) => {
24028
- const options = resolveOptions(rawOptions);
24200
+ let options = null;
24029
24201
  let serversStarted = false;
24030
24202
  const name = "unplugin-devpilot";
24203
+ async function ensureOptionsResolved() {
24204
+ if (!options) options = await resolveOptions(rawOptions);
24205
+ return options;
24206
+ }
24031
24207
  async function startServers() {
24032
24208
  if (serversStarted) return;
24033
24209
  serversStarted = true;
24034
- registerPluginServerMethods(options.plugins);
24035
- registerPluginMcpRegisterMethods(options.plugins);
24036
- startWebSocketServer(options.wsPort);
24037
- await startMcpServer(options.mcpPort);
24210
+ const resolvedOptions = await ensureOptionsResolved();
24211
+ registerPluginServerMethods(resolvedOptions.plugins);
24212
+ registerPluginMcpRegisterMethods(resolvedOptions.plugins);
24213
+ startWebSocketServer(resolvedOptions.wsPort);
24214
+ await startMcpServer(resolvedOptions.mcpPort);
24038
24215
  }
24039
- function stopServers() {
24216
+ async function stopServers() {
24040
24217
  if (!serversStarted) return;
24218
+ const resolvedOptions = await ensureOptionsResolved();
24041
24219
  serversStarted = false;
24042
24220
  stopWebSocketServer();
24043
24221
  stopMcpServer();
24222
+ await killPort(resolvedOptions.mcpPort);
24044
24223
  }
24045
24224
  return {
24046
24225
  name,
@@ -24051,18 +24230,18 @@ const unpluginDevpilot = createUnplugin((rawOptions = {}) => {
24051
24230
  loadInclude(id) {
24052
24231
  return id === RESOLVED_VIRTUAL_MODULE_ID;
24053
24232
  },
24054
- load(id) {
24055
- if (id === RESOLVED_VIRTUAL_MODULE_ID) return generateVirtualClientModule(options, process$1.env.NODE_ENV !== "production");
24233
+ async load(id) {
24234
+ if (id === RESOLVED_VIRTUAL_MODULE_ID) return generateVirtualClientModule(await ensureOptionsResolved(), process$1.env.NODE_ENV !== "production");
24056
24235
  },
24057
24236
  buildStart() {
24058
24237
  if (process$1.env.NODE_ENV === "production") return;
24059
- startServers();
24238
+ return startServers();
24060
24239
  },
24061
24240
  buildEnd() {
24062
24241
  stopServers();
24063
24242
  },
24064
24243
  vite: { configureServer() {
24065
- startServers();
24244
+ return startServers();
24066
24245
  } },
24067
24246
  webpack(compiler) {
24068
24247
  compiler.hooks.watchRun.tapPromise(name, async () => {
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot } from "./src-D62s1VAN.mjs";
1
+ import { n as unpluginDevpilot } from "./src-Bm2tOOQC.mjs";
2
2
 
3
3
  //#region src/vite.ts
4
4
  /**
package/dist/webpack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot } from "./src-D62s1VAN.mjs";
1
+ import { n as unpluginDevpilot } from "./src-Bm2tOOQC.mjs";
2
2
 
3
3
  //#region src/webpack.ts
4
4
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "unplugin-devpilot",
3
3
  "type": "module",
4
- "version": "0.0.2",
4
+ "version": "0.0.3",
5
5
  "description": "Description.",
6
6
  "author": "zcf0508 <zcf0508@live.com>",
7
7
  "license": "MIT",
@@ -60,6 +60,7 @@
60
60
  "@types/ws": "^8.18.1",
61
61
  "birpc": "^4.0.0",
62
62
  "es-toolkit": "^1.44.0",
63
+ "get-port-please": "^3.2.0",
63
64
  "hookable": "^6.0.1",
64
65
  "mitt": "^3.0.1",
65
66
  "ws": "^8.19.0",