mioku 0.9.9 → 1.0.1

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.
@@ -1,19 +1,23 @@
1
- import { spawn, spawnSync } from "node:child_process";
2
1
  import * as fs$1 from "node:fs";
3
- import * as os from "node:os";
4
2
  import * as path$1 from "node:path";
3
+ import * as os$1 from "node:os";
4
+ import { spawn, spawnSync } from "node:child_process";
5
5
 
6
- //#region src/core/exec.ts
6
+ //#region package.json
7
+ var version = "1.0.1";
8
+
9
+ //#endregion
10
+ //#region src/internal/exec.ts
7
11
  const isWindows = process.platform === "win32";
8
12
  const resolveCache = new Map();
9
13
  function windowsExtensions() {
10
14
  const raw = process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD";
11
- return raw.split(";").map((ext) => ext.trim()).filter(Boolean);
15
+ return raw.split(");").map((ext) => ext.trim()).filter(Boolean);
12
16
  }
13
17
  function searchDirs() {
14
18
  const raw = process.env.PATH || process.env.Path || "";
15
19
  const dirs = raw.split(path$1.delimiter).map((d) => d.trim()).filter(Boolean);
16
- const home = os.homedir();
20
+ const home = os$1.homedir();
17
21
  const extra = isWindows ? [
18
22
  path$1.join(home, ".bun", "bin"),
19
23
  path$1.join(process.env.APPDATA || "", "npm"),
@@ -33,6 +37,7 @@ function isExecutableFile(candidate) {
33
37
  return false;
34
38
  }
35
39
  }
40
+ /** 在 PATH 及常见安装目录中解析命令的完整路径,结果带缓存 */
36
41
  function resolveCommand(command) {
37
42
  if (resolveCache.has(command)) return resolveCache.get(command) ?? null;
38
43
  let resolved = null;
@@ -74,6 +79,7 @@ function quoteForCmd(arg) {
74
79
  const escaped = arg.replace(/(\\*)"/g, "$1$1\\\"").replace(/(\\+)$/, "$1$1");
75
80
  return `"${escaped}"`;
76
81
  }
82
+ /** 生成跨平台的 spawn 参数,Windows 下 .cmd/.bat 会改经 cmd.exe 执行 */
77
83
  function buildSpawnPlan(command, args) {
78
84
  const resolved = resolveCommand(command);
79
85
  if (!resolved) return {
@@ -97,6 +103,7 @@ function buildSpawnPlan(command, args) {
97
103
  windowsVerbatimArguments: true
98
104
  };
99
105
  }
106
+ /** 执行命令并收集 stdout/stderr 与退出码,失败不抛异常 */
100
107
  function runCommand(command, args, options = {}) {
101
108
  const plan = buildSpawnPlan(command, args);
102
109
  return new Promise((resolve) => {
@@ -134,6 +141,7 @@ function runCommand(command, args, options = {}) {
134
141
  });
135
142
  });
136
143
  }
144
+ /** 同步执行命令并继承当前终端的输入输出,非零退出码时抛错 */
137
145
  function runCommandInherit(command, args, options = {}) {
138
146
  const plan = buildSpawnPlan(command, args);
139
147
  const result = spawnSync(plan.file, plan.args, {
@@ -144,10 +152,11 @@ function runCommandInherit(command, args, options = {}) {
144
152
  if (result.error) throw result.error;
145
153
  if (result.status !== 0) throw new Error(`${command} 退出码 ${result.status}`);
146
154
  }
155
+ /** 判断命令是否可用 */
147
156
  function commandExists(command) {
148
157
  return resolveCommand(command) !== null;
149
158
  }
150
159
 
151
160
  //#endregion
152
- export { buildSpawnPlan, clearCommandCache, commandExists, resolveCommand, runCommand, runCommandInherit };
153
- //# sourceMappingURL=exec-BzODBZwA.js.map
161
+ export { buildSpawnPlan, clearCommandCache, commandExists, resolveCommand, runCommand, runCommandInherit, version };
162
+ //# sourceMappingURL=exec-DGQCm_XV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec-DGQCm_XV.js","names":["path","candidate: string","command: string","resolved: string | null","resolved: string","arg: string","args: string[]","options: { cwd?: string; env?: NodeJS.ProcessEnv }","options: { cwd?: string }"],"sources":["../package.json","../src/internal/exec.ts"],"sourcesContent":["{\n \"name\": \"mioku\",\n \"type\": \"module\",\n \"version\": \"1.0.1\",\n \"packageManager\": \"bun@1.2.0\",\n \"description\": \"Mioku - A plugin-based QQ bot framework\",\n \"keywords\": [\n \"onebot\",\n \"framework\",\n \"bot\",\n \"mioku\"\n ],\n \"bin\": {\n \"mioku\": \"./dist/cli/index.js\"\n },\n \"engines\": {\n \"node\": \">= 22.18.0\"\n },\n \"homepage\": \"https://github.com/mioku-lab/mioku#readme\",\n \"files\": [\n \"dist\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/mioku-lab/mioku/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/mioku-lab/mioku.git\",\n \"directory\": \"packages/mioku\"\n },\n \"scripts\": {\n \"dev\": \"tsdown -w\",\n \"build\": \"tsdown\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"exports\": {\n \".\": {\n \"require\": \"./dist/index.cjs\",\n \"import\": \"./dist/index.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"author\": \"Jerryplusy <jerryplusy@outlook.com>\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"napcat-sdk\": \"^0.16.0\",\n \"consola\": \"^3.4.2\",\n \"dayjs\": \"^1.11.19\",\n \"dedent\": \"^1.7.1\",\n \"filesize\": \"^11.0.13\",\n \"inquirer\": \"^10.0.0\",\n \"jiti\": \"^2.6.1\",\n \"lowdb\": \"^7.0.1\",\n \"mri\": \"^1.2.0\",\n \"node-cron\": \"^4.2.1\",\n \"pretty-ms\": \"^9.3.0\",\n \"string2argv\": \"^1.0.2\",\n \"lodash\": \"^4.17.21\"\n },\n \"devDependencies\": {\n \"@types/lodash\": \"^4.17.0\",\n \"@types/node\": \"^22.0.0\",\n \"tsdown\": \"^0.11.0\",\n \"typescript\": \"^5.8.0\"\n }\n}\n","import { spawn, spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\n\nconst isWindows = process.platform === \"win32\";\n\nconst resolveCache = new Map<string, string | null>();\n\nfunction windowsExtensions(): string[] {\n const raw = process.env.PATHEXT || \".COM;.EXE;.BAT;.CMD\";\n return raw\n .split(\");\")\n .map((ext) => ext.trim())\n .filter(Boolean);\n}\n\n// PATH is a snapshot taken at process start, so a package manager installed\n// mid-run won't be on it. These are the standard install prefixes for bun and\n// for npm's global bin, which is where `npm i -g bun` actually lands.\nfunction searchDirs(): string[] {\n const raw = process.env.PATH || process.env.Path || \"\";\n const dirs = raw.split(path.delimiter).map((d) => d.trim()).filter(Boolean);\n const home = os.homedir();\n\n const extra = isWindows\n ? [\n path.join(home, \".bun\", \"bin\"),\n path.join(process.env.APPDATA || \"\", \"npm\"),\n path.join(process.env.ProgramFiles || \"\", \"nodejs\"),\n ]\n : [\n path.join(home, \".bun\", \"bin\"),\n \"/usr/local/bin\",\n \"/opt/homebrew/bin\",\n path.join(home, \".npm-global\", \"bin\"),\n ];\n\n return [...dirs, ...extra.filter((dir) => dir && !dir.endsWith(path.sep))];\n}\n\nfunction isExecutableFile(candidate: string): boolean {\n try {\n return fs.statSync(candidate).isFile();\n } catch {\n return false;\n }\n}\n\n/** 在 PATH 及常见安装目录中解析命令的完整路径,结果带缓存 */\nexport function resolveCommand(command: string): string | null {\n if (resolveCache.has(command)) return resolveCache.get(command) ?? null;\n\n let resolved: string | null = null;\n\n if (command.includes(\"/\") || command.includes(path.sep)) {\n resolved = isExecutableFile(command) ? path.resolve(command) : null;\n } else {\n const exts = isWindows ? windowsExtensions() : [\"\"];\n const hasKnownExt =\n isWindows && exts.some((ext) => command.toLowerCase().endsWith(ext.toLowerCase()));\n\n outer: for (const dir of searchDirs()) {\n if (hasKnownExt) {\n const direct = path.join(dir, command);\n if (isExecutableFile(direct)) {\n resolved = direct;\n break;\n }\n continue;\n }\n for (const ext of exts) {\n const candidate = path.join(dir, command + ext);\n if (isExecutableFile(candidate)) {\n resolved = candidate;\n break outer;\n }\n }\n }\n }\n\n resolveCache.set(command, resolved);\n return resolved;\n}\n\nexport function clearCommandCache(): void {\n resolveCache.clear();\n}\n\nfunction needsCmdShell(resolved: string): boolean {\n if (!isWindows) return false;\n const ext = path.extname(resolved).toLowerCase();\n return ext === \".cmd\" || ext === \".bat\";\n}\n\n// cmd.exe argument quoting: escape embedded quotes and any run of backslashes\n// that precedes a quote, then wrap the whole thing so metacharacters inside\n// (&, |, <, >, ^) are inert.\nfunction quoteForCmd(arg: string): string {\n if (arg === \"\") return '\"\"';\n const escaped = arg\n .replace(/(\\\\*)\"/g, '$1$1\\\\\"')\n .replace(/(\\\\+)$/, \"$1$1\");\n return `\"${escaped}\"`;\n}\n\nexport interface SpawnPlan {\n file: string;\n args: string[];\n windowsVerbatimArguments?: boolean;\n}\n\n// Windows can't CreateProcess a .cmd/.bat shim directly (npm installs bun as\n// bun.cmd), so those get routed through cmd.exe with hand-quoted arguments\n// rather than shell: true, which would leave the args unquoted.\n/** 生成跨平台的 spawn 参数,Windows 下 .cmd/.bat 会改经 cmd.exe 执行 */\nexport function buildSpawnPlan(command: string, args: string[]): SpawnPlan {\n const resolved = resolveCommand(command);\n\n if (!resolved) {\n return { file: command, args };\n }\n\n if (!needsCmdShell(resolved)) {\n return { file: resolved, args };\n }\n\n const comspec = process.env.ComSpec || process.env.COMSPEC || \"cmd.exe\";\n const line = [resolved, ...args].map(quoteForCmd).join(\" \");\n return {\n file: comspec,\n args: [\"/d\", \"/s\", \"/c\", `\"${line}\"`],\n windowsVerbatimArguments: true,\n };\n}\n\nexport interface RunCommandResult {\n stdout: string;\n stderr: string;\n code: number;\n}\n\n/** 执行命令并收集 stdout/stderr 与退出码,失败不抛异常 */\nexport function runCommand(\n command: string,\n args: string[],\n options: { cwd?: string; env?: NodeJS.ProcessEnv } = {},\n): Promise<RunCommandResult> {\n const plan = buildSpawnPlan(command, args);\n\n return new Promise((resolve) => {\n const child = spawn(plan.file, plan.args, {\n cwd: options.cwd,\n env: options.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsVerbatimArguments: plan.windowsVerbatimArguments,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (chunk) => {\n stdout += String(chunk);\n });\n child.stderr?.on(\"data\", (chunk) => {\n stderr += String(chunk);\n });\n\n child.on(\"close\", (code) => {\n resolve({ stdout, stderr, code: code ?? 1 });\n });\n child.on(\"error\", (error) => {\n resolve({\n stdout,\n stderr: `${stderr}\\n${error.message}`.trim(),\n code: 1,\n });\n });\n });\n}\n\n/** 同步执行命令并继承当前终端的输入输出,非零退出码时抛错 */\nexport function runCommandInherit(\n command: string,\n args: string[],\n options: { cwd?: string } = {},\n): void {\n const plan = buildSpawnPlan(command, args);\n const result = spawnSync(plan.file, plan.args, {\n cwd: options.cwd,\n stdio: \"inherit\",\n windowsVerbatimArguments: plan.windowsVerbatimArguments,\n });\n\n if (result.error) throw result.error;\n if (result.status !== 0) {\n throw new Error(`${command} 退出码 ${result.status}`);\n }\n}\n\n/** 判断命令是否可用 */\nexport function commandExists(command: string): boolean {\n return resolveCommand(command) !== null;\n}\n"],"mappings":"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"}