81 lines
2.9 KiB
TypeScript
81 lines
2.9 KiB
TypeScript
import type {
|
||
RuntimeContext,
|
||
ProcHandle,
|
||
CompatibleBodyInit,
|
||
SpawnOptions,
|
||
} from "../types";
|
||
import { resolve } from "pathe"; // Unjs 标准:跨平台路径处理
|
||
import { isCI } from "std-env";
|
||
|
||
export const createBunRuntime = (): RuntimeContext => ({
|
||
fs: {
|
||
exists: (path) => Bun.file(path).exists(),
|
||
// 返回标准 Response,极大简化了后续的文件解析逻辑
|
||
read: async (path) => new Response(Bun.file(path)),
|
||
write: async (path, data: CompatibleBodyInit) => {
|
||
await Bun.write(path, data as any);
|
||
},
|
||
openWritable: (path) => {
|
||
const file = Bun.file(path);
|
||
// 利用 Bun.file().writer() 转换为符合 Web 标准的 WritableStream
|
||
return new WritableStream({
|
||
async write(chunk) {
|
||
const writer = file.writer();
|
||
writer.write(chunk);
|
||
writer.flush();
|
||
},
|
||
});
|
||
},
|
||
mkdir: async (path, options) => {
|
||
const fs = await import("node:fs/promises");
|
||
await fs.mkdir(path, options);
|
||
},
|
||
remove: async (path) => {
|
||
const fs = await import("node:fs/promises");
|
||
await fs.rm(path, { recursive: true, force: true });
|
||
},
|
||
symlink: async (target, path) => {
|
||
const fs = await import("node:fs/promises");
|
||
await fs.symlink(target, path);
|
||
},
|
||
readdir: async (path) => {
|
||
const fs = await import("node:fs/promises");
|
||
return await fs.readdir(path);
|
||
},
|
||
stat: async (path) => {
|
||
const { stat } = await import("node:fs/promises");
|
||
const s = await stat(path);
|
||
return {
|
||
size: s.size,
|
||
mtime: s.mtime,
|
||
isDirectory: s.isDirectory(),
|
||
};
|
||
},
|
||
},
|
||
proc: {
|
||
spawn: (args: string[], options: SpawnOptions = {}): ProcHandle => {
|
||
// 核心改进:自动处理交互逻辑
|
||
// 如果是在 CI 环境,强制使用 pipe 避免挂起;否则根据用户需求或自动选择
|
||
const mode = options.stdio || (isCI ? "pipe" : "inherit");
|
||
|
||
const process = Bun.spawn(args, {
|
||
cwd: options.cwd,
|
||
env: options.env,
|
||
stdout: mode,
|
||
stderr: mode,
|
||
stdin: mode,
|
||
});
|
||
|
||
return {
|
||
pid: process.pid,
|
||
exited: process.exited,
|
||
kill: (sig) => process.kill(sig as any),
|
||
// 仅在非继承模式下暴露流,避免类型与行为冲突
|
||
stdout: mode === "pipe" ? (process.stdout as any) : undefined,
|
||
stderr: mode === "pipe" ? (process.stderr as any) : undefined,
|
||
stdin: mode === "pipe" ? (process.stdin as any) : undefined,
|
||
};
|
||
},
|
||
},
|
||
});
|