fix(bun-spawn-shim): eliminate globalThis.Bun top-level destructures for Electron/Node compat
Root cause: bun build --target bun inlines top-level
var { spawn } = globalThis.Bun;
for every file that contains 'import { spawn } from "bun"'. On Node/Electron
where globalThis.Bun is undefined, this crashes with
Cannot destructure property 'spawn' of 'globalThis.Bun' as it is undefined.
26 source files had this import; the bundled output had 25 top-level destructures.
Fix:
- Add src/shared/bun-spawn-shim.ts: a thin wrapper that
- delegates to Bun.spawn/spawnSync when globalThis.Bun is present (real Bun)
- falls back to static ESM imports of node:child_process otherwise
- uses static 'import { spawn } from "node:child_process"' so Bun bundler
does NOT emit any globalThis.Bun destructures for this module
- Replace all 26 'from "bun"' spawn/spawnSync imports with relative paths to shim
- Replace 4 direct Bun.spawn() call sites with shim's spawn()
- Remove src/electron-compat.ts and script/prepend-electron-shim.ts (no longer needed)
- Update src/electron-compat.test.ts to assert 0 top-level globalThis.Bun destructures
Verification: grep -c '} = globalThis.Bun;' dist/index.js → 0 (was 25)
All 5921 tests pass (1 pre-existing timeout failure unrelated to this change).
Fixes #3797
This commit is contained in:
+1
-2
@@ -22,8 +22,7 @@
|
||||
"./schema.json": "./dist/oh-my-opencode.schema.json"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi --external zod && bun run build:prepend-shim && tsc --emitDeclarationOnly && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi && bun run build:schema",
|
||||
"build:prepend-shim": "bun run script/prepend-electron-shim.ts",
|
||||
"build": "bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi --external zod && tsc --emitDeclarationOnly && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi && bun run build:schema",
|
||||
"build:all": "bun run build && bun run build:binaries",
|
||||
"build:binaries": "bun run script/build-binaries.ts",
|
||||
"build:schema": "bun run script/build-schema.ts",
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/usr/bin/env bun
|
||||
/**
|
||||
* Prepend the Electron/Node compat shim to dist/index.js.
|
||||
*
|
||||
* When bundled with --target bun, Bun inlines top-level
|
||||
* var { spawn } = globalThis.Bun;
|
||||
* statements from its own internal modules. These crash on Node/Electron
|
||||
* because globalThis.Bun is undefined there.
|
||||
*
|
||||
* Since Bun's bundler does not guarantee that a side-effect import at the
|
||||
* top of src/index.ts will appear before all other module top-level code,
|
||||
* we post-process the bundle and manually prepend the shim.
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
|
||||
const DIST_PATH = join(import.meta.dir, "..", "dist", "index.js")
|
||||
|
||||
const SHIM = `// [omo] Electron/Node compat shim — prepended by script/prepend-electron-shim.ts
|
||||
// Populates globalThis.Bun before any top-level destructure fires.
|
||||
if (!globalThis.Bun) {
|
||||
const _cp = await import("node:child_process");
|
||||
const _Readable = (await import("node:stream")).Readable;
|
||||
function _mkproc(p) {
|
||||
let c = null;
|
||||
const exited = new Promise(r => {
|
||||
p.on("exit", code => { c = code ?? 1; r(c); });
|
||||
p.on("error", () => { if (c === null) { c = 1; r(1); } });
|
||||
});
|
||||
return { get exitCode() { return c; }, exited,
|
||||
stdout: p.stdout ? _Readable.toWeb(p.stdout) : undefined,
|
||||
stderr: p.stderr ? _Readable.toWeb(p.stderr) : undefined,
|
||||
stdin: p.stdin, kill(s) { try { p.kill(s); } catch {} }, pid: p.pid };
|
||||
}
|
||||
function _spawn(cmdOrOpts, opts) {
|
||||
const isObj = !Array.isArray(cmdOrOpts);
|
||||
const cmd = isObj ? cmdOrOpts.cmd : cmdOrOpts;
|
||||
const o = isObj ? cmdOrOpts : (opts || {});
|
||||
const [bin, ...args] = cmd;
|
||||
return _mkproc(_cp.spawn(bin, args, { cwd: o.cwd, env: o.env,
|
||||
stdio: [o.stdin||"pipe", o.stdout||"pipe", o.stderr||"pipe"] }));
|
||||
}
|
||||
function _spawnSync(cmdOrOpts) {
|
||||
const isObj = !Array.isArray(cmdOrOpts);
|
||||
const cmd = isObj ? cmdOrOpts.cmd : cmdOrOpts;
|
||||
const o = isObj ? cmdOrOpts : {};
|
||||
const [bin, ...args] = cmd;
|
||||
const r = _cp.spawnSync(bin, args, { cwd: o.cwd, env: o.env, stdio: ["pipe","pipe","pipe"] });
|
||||
return { exitCode: r.status ?? 1, stdout: r.stdout, stderr: r.stderr };
|
||||
}
|
||||
globalThis.Bun = { spawn: _spawn, spawnSync: _spawnSync, env: process.env, version: "0.0.0-node-shim" };
|
||||
}
|
||||
`
|
||||
|
||||
const original = readFileSync(DIST_PATH, "utf-8")
|
||||
|
||||
// Avoid double-prepend
|
||||
if (original.includes("[omo] Electron/Node compat shim")) {
|
||||
console.log("Shim already present in dist/index.js, skipping.")
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
writeFileSync(DIST_PATH, SHIM + original, "utf-8")
|
||||
console.log(`✓ Prepended Electron/Node compat shim to dist/index.js`)
|
||||
+15
-19
@@ -1,27 +1,23 @@
|
||||
import { describe, test, expect } from "bun:test"
|
||||
|
||||
describe("electron-compat shim", () => {
|
||||
test("#given shim module #when inspected #then it exports no values (side-effect only)", async () => {
|
||||
// The shim is a side-effect module — no named exports
|
||||
const mod = await import("./electron-compat")
|
||||
expect(Object.keys(mod)).toHaveLength(0)
|
||||
describe("electron-compat: dist/index.js globalThis.Bun safety", () => {
|
||||
test("#given dist/index.js #then no top-level globalThis.Bun destructures exist", async () => {
|
||||
// This guards the fix for https://github.com/code-yeongyu/oh-my-openagent/issues/3797.
|
||||
// Previously 'bun build --target bun' emitted 25 top-level
|
||||
// var { spawn } = globalThis.Bun;
|
||||
// statements that crashed on Node/Electron where globalThis.Bun is undefined.
|
||||
// The fix replaces all 'from "bun"' spawn imports with a node:child_process
|
||||
// shim so the bundler no longer emits these destructures.
|
||||
const dist = await Bun.file("dist/index.js").text()
|
||||
const destructures = (dist.match(/\} = globalThis\.Bun;/g) ?? []).length
|
||||
expect(destructures).toBe(0)
|
||||
})
|
||||
|
||||
test("#given Bun runtime #when shim is loaded #then globalThis.Bun remains the real Bun", () => {
|
||||
// In Bun (our test environment), globalThis.Bun is already defined.
|
||||
// The shim must not overwrite it.
|
||||
test("#given Bun runtime #when shim module is loaded #then globalThis.Bun remains real Bun", () => {
|
||||
// On real Bun runtime, globalThis.Bun must not be overwritten by any shim
|
||||
expect(globalThis.Bun).toBeDefined()
|
||||
// Real Bun version looks like "1.x.x", not our shim string
|
||||
expect(typeof globalThis.Bun.spawn).toBe("function")
|
||||
// The shim version string is only set when globalThis.Bun was absent
|
||||
expect(globalThis.Bun.version).not.toBe("0.0.0-node-shim")
|
||||
})
|
||||
|
||||
test("#given dist/index.js #when inspected #then compat shim appears before first globalThis.Bun destructure", async () => {
|
||||
// This test guards that build/prepend-electron-shim ran.
|
||||
// If the shim is missing, the plugin crashes on Electron at line 2876.
|
||||
const dist = await Bun.file("dist/index.js").text()
|
||||
const shimPos = dist.indexOf("[omo] Electron/Node compat shim")
|
||||
const firstDestructure = dist.indexOf("} = globalThis.Bun;")
|
||||
expect(shimPos).toBeGreaterThanOrEqual(0) // shim present
|
||||
expect(shimPos).toBeLessThan(firstDestructure) // shim before destructures
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* Electron/Node runtime compatibility shim.
|
||||
*
|
||||
* OpenCode Desktop runs the plugin in an Electron renderer/main process
|
||||
* whose ESM loader is Node — not Bun. When bundled with `--target bun`,
|
||||
* every chunk that calls `Bun.spawn` / `Bun.spawnSync` emits a top-level
|
||||
* `var { spawn } = globalThis.Bun` destructure. On Node/Electron,
|
||||
* `globalThis.Bun` is `undefined`, so module evaluation crashes before any
|
||||
* plugin hook is ever reached.
|
||||
*
|
||||
* We patch globalThis.Bun at module-evaluation time so the destructures
|
||||
* resolve to real functions backed by node:child_process.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const _cp = require("node:child_process") as typeof import("node:child_process")
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const _stream = require("node:stream") as typeof import("node:stream")
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type AnyRecord = Record<string, any>
|
||||
|
||||
function _makeProc(proc: ReturnType<typeof _cp.spawn>) {
|
||||
let _exitCode: number | null = null
|
||||
const exited = new Promise<number>((resolve) => {
|
||||
proc.on("exit", (code) => { _exitCode = code ?? 1; resolve(_exitCode) })
|
||||
proc.on("error", () => { if (_exitCode === null) { _exitCode = 1; resolve(1) } })
|
||||
})
|
||||
return {
|
||||
get exitCode() { return _exitCode },
|
||||
exited,
|
||||
stdout: proc.stdout ? (_stream.Readable.toWeb(proc.stdout) as ReadableStream<Uint8Array>) : undefined,
|
||||
stderr: proc.stderr ? (_stream.Readable.toWeb(proc.stderr) as ReadableStream<Uint8Array>) : undefined,
|
||||
stdin: proc.stdin,
|
||||
kill(sig?: NodeJS.Signals) { try { proc.kill(sig) } catch {} },
|
||||
pid: proc.pid,
|
||||
}
|
||||
}
|
||||
|
||||
function _spawnShim(cmdOrOpts: string[] | AnyRecord, optsArg?: AnyRecord) {
|
||||
const isObj = !Array.isArray(cmdOrOpts)
|
||||
const cmd: string[] = isObj ? (cmdOrOpts as AnyRecord)["cmd"] as string[] : (cmdOrOpts as string[])
|
||||
const o: AnyRecord = isObj ? (cmdOrOpts as AnyRecord) : (optsArg ?? {})
|
||||
const [bin, ...args] = cmd
|
||||
const proc = _cp.spawn(bin, args, {
|
||||
cwd: o["cwd"] as string | undefined,
|
||||
env: o["env"] as NodeJS.ProcessEnv | undefined,
|
||||
stdio: [(o["stdin"] ?? "pipe") as "pipe", (o["stdout"] ?? "pipe") as "pipe", (o["stderr"] ?? "pipe") as "pipe"],
|
||||
})
|
||||
return _makeProc(proc)
|
||||
}
|
||||
|
||||
function _spawnSyncShim(cmdOrOpts: string[] | AnyRecord) {
|
||||
const isObj = !Array.isArray(cmdOrOpts)
|
||||
const cmd: string[] = isObj ? (cmdOrOpts as AnyRecord)["cmd"] as string[] : (cmdOrOpts as string[])
|
||||
const o: AnyRecord = isObj ? (cmdOrOpts as AnyRecord) : {}
|
||||
const [bin, ...args] = cmd
|
||||
const r = _cp.spawnSync(bin, args, {
|
||||
cwd: o["cwd"] as string | undefined,
|
||||
env: o["env"] as NodeJS.ProcessEnv | undefined,
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
})
|
||||
return { exitCode: r.status ?? 1, stdout: r.stdout, stderr: r.stderr }
|
||||
}
|
||||
|
||||
if (!globalThis.Bun) {
|
||||
// @ts-expect-error – intentional globalThis shim for Electron/Node compat
|
||||
globalThis.Bun = {
|
||||
spawn: _spawnShim as unknown as typeof globalThis.Bun.spawn,
|
||||
spawnSync: _spawnSyncShim as unknown as typeof globalThis.Bun.spawnSync,
|
||||
env: process.env,
|
||||
version: "0.0.0-node-shim",
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,10 @@ import fs from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
|
||||
import type { TeamModeConfig } from "./manager"
|
||||
import { spawn as bunSpawn } from "../../../shared/bun-spawn-shim"
|
||||
|
||||
async function runGit(args: string[]): Promise<{ code: number; stderr: string }> {
|
||||
const process = Bun.spawn({ cmd: ["git", ...args], stdout: "pipe", stderr: "pipe" })
|
||||
const process = bunSpawn({ cmd: ["git", ...args], stdout: "pipe", stderr: "pipe" })
|
||||
const [exitCode, stderrText] = await Promise.all([process.exited, new Response(process.stderr).text()])
|
||||
return { code: exitCode, stderr: stderrText }
|
||||
}
|
||||
@@ -12,7 +13,7 @@ async function runGit(args: string[]): Promise<{ code: number; stderr: string }>
|
||||
export async function removeWorktree(worktreePath: string): Promise<void> {
|
||||
await fs.rm(worktreePath, { recursive: true, force: true })
|
||||
|
||||
const rootLookup = await Bun.spawn({
|
||||
const rootLookup = bunSpawn({
|
||||
cmd: ["git", "-C", worktreePath, "rev-parse", "--show-superproject-working-tree"],
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from "node:path"
|
||||
import { spawn as bunSpawn } from "../../../shared/bun-spawn-shim"
|
||||
|
||||
export type TeamModeConfig = {
|
||||
worktreeBaseDir?: string
|
||||
@@ -16,7 +17,7 @@ function countParentSegments(spec: string): number {
|
||||
}
|
||||
|
||||
async function runGit(args: string[], cwd?: string): Promise<{ code: number; stderr: string }> {
|
||||
const process = Bun.spawn({ cmd: ["git", ...args], cwd, stdout: "pipe", stderr: "pipe" })
|
||||
const process = bunSpawn({ cmd: ["git", ...args], cwd, stdout: "pipe", stderr: "pipe" })
|
||||
const [exitCode, stderrBytes] = await Promise.all([process.exited, new Response(process.stderr).text()])
|
||||
return { code: exitCode, stderr: stderrBytes }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../shared/bun-spawn-shim"
|
||||
import type { WindowState, TmuxPaneInfo } from "./types"
|
||||
import { parsePaneStateOutput } from "./pane-state-parser"
|
||||
import { getTmuxPath } from "../../tools/interactive-bash/tmux-path-resolver"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../shared/bun-spawn-shim"
|
||||
import { createRequire } from "module"
|
||||
import { dirname, join } from "path"
|
||||
import { existsSync } from "fs"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "./electron-compat"
|
||||
import { initConfigContext } from "./cli/config-manager/config-context"
|
||||
import type { Hooks, Plugin, PluginModule } from "@opencode-ai/plugin"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../shared/bun-spawn-shim"
|
||||
import { validateGatewayUrl } from "./gateway-url-validation"
|
||||
import type { OpenClawGateway, WakeResult } from "./types"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { readFileSync } from "fs"
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../shared/bun-spawn-shim"
|
||||
|
||||
export const REPLY_LISTENER_DAEMON_IDENTITY_MARKER = "--openclaw-reply-listener-daemon"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../shared/bun-spawn-shim"
|
||||
import {
|
||||
createReplyListenerDaemonEnv,
|
||||
REPLY_LISTENER_DAEMON_IDENTITY_MARKER,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../shared/bun-spawn-shim"
|
||||
|
||||
export function getCurrentTmuxSession(): string | null {
|
||||
const env = process.env.TMUX
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { chmodSync, existsSync, mkdirSync, unlinkSync } from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import { spawn } from "bun";
|
||||
import { spawn } from "./bun-spawn-shim";
|
||||
import { validateArchiveEntries, type ArchiveEntry } from "./archive-entry-validator";
|
||||
import { extractZip } from "./zip-extractor";
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Node/Electron-compatible spawn shim.
|
||||
*
|
||||
* Replaces direct `import { spawn } from "bun"` throughout the codebase so
|
||||
* that `bun build --target bun` no longer emits top-level
|
||||
* var { spawn } = globalThis.Bun;
|
||||
* destructures that crash on Node/Electron (where globalThis.Bun is undefined).
|
||||
*
|
||||
* On real Bun runtime: delegates straight to Bun.spawn / Bun.spawnSync.
|
||||
* On Node/Electron: backed by node:child_process (via static ESM imports
|
||||
* which are safe in both runtimes).
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process"
|
||||
import { Readable } from "node:stream"
|
||||
|
||||
const IS_BUN = typeof globalThis.Bun !== "undefined"
|
||||
|
||||
function _resolveCmd(cmdOrOpts: any, optsArg?: any): { cmd: string[]; opts: any } {
|
||||
const isObj = !Array.isArray(cmdOrOpts)
|
||||
return {
|
||||
cmd: isObj ? (cmdOrOpts as any).cmd : (cmdOrOpts as string[]),
|
||||
opts: isObj ? cmdOrOpts : (optsArg ?? {}),
|
||||
}
|
||||
}
|
||||
|
||||
function _wrapNodeProc(proc: ReturnType<typeof nodeSpawn>): any {
|
||||
let code: number | null = null
|
||||
const exited = new Promise<number>((resolve) => {
|
||||
proc.on("exit", (c) => { code = c ?? 1; resolve(code) })
|
||||
proc.on("error", () => { if (code === null) { code = 1; resolve(1) } })
|
||||
})
|
||||
return {
|
||||
get exitCode() { return code },
|
||||
exited,
|
||||
stdout: proc.stdout ? Readable.toWeb(proc.stdout) as ReadableStream<Uint8Array> : undefined,
|
||||
stderr: proc.stderr ? Readable.toWeb(proc.stderr) as ReadableStream<Uint8Array> : undefined,
|
||||
stdin: proc.stdin,
|
||||
kill(s?: NodeJS.Signals) { try { proc.kill(s) } catch {} },
|
||||
pid: proc.pid,
|
||||
}
|
||||
}
|
||||
|
||||
export function spawn(cmdOrOpts: any, opts?: any): any {
|
||||
if (IS_BUN) return (globalThis.Bun as any).spawn(cmdOrOpts, opts)
|
||||
const { cmd, opts: o } = _resolveCmd(cmdOrOpts, opts)
|
||||
const [bin, ...args] = cmd
|
||||
const proc = nodeSpawn(bin, args, {
|
||||
cwd: o.cwd as string | undefined,
|
||||
env: o.env as NodeJS.ProcessEnv | undefined,
|
||||
stdio: [(o.stdin ?? "pipe") as any, (o.stdout ?? "pipe") as any, (o.stderr ?? "pipe") as any],
|
||||
})
|
||||
return _wrapNodeProc(proc)
|
||||
}
|
||||
|
||||
export function spawnSync(cmdOrOpts: any, _opts?: any): any {
|
||||
if (IS_BUN) return (globalThis.Bun as any).spawnSync(cmdOrOpts)
|
||||
const { cmd, opts: o } = _resolveCmd(cmdOrOpts)
|
||||
const [bin, ...args] = cmd
|
||||
const r = nodeSpawnSync(bin, args, {
|
||||
cwd: o.cwd as string | undefined,
|
||||
env: o.env as NodeJS.ProcessEnv | undefined,
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
})
|
||||
return { exitCode: r.status ?? 1, stdout: r.stdout, stderr: r.stderr, success: (r.status ?? 1) === 0, pid: -1 }
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn as bunSpawn } from "bun"
|
||||
import { spawn as bunSpawn } from "./bun-spawn-shim"
|
||||
import { spawn as nodeSpawn, type ChildProcess } from "node:child_process"
|
||||
import { Readable } from "node:stream"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../bun-spawn-shim"
|
||||
import type { TmuxLayout } from "../../../config/schema"
|
||||
import { getTmuxPath } from "../../../tools/interactive-bash/tmux-path-resolver"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../bun-spawn-shim"
|
||||
import { getTmuxPath } from "../../../tools/interactive-bash/tmux-path-resolver"
|
||||
|
||||
export interface PaneDimensions {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../bun-spawn-shim"
|
||||
import type { TmuxConfig } from "../../../config/schema"
|
||||
import { getTmuxPath } from "../../../tools/interactive-bash/tmux-path-resolver"
|
||||
import type { SpawnPaneResult } from "../types"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../bun-spawn-shim"
|
||||
import type { TmuxConfig } from "../../../config/schema"
|
||||
import { getTmuxPath } from "../../../tools/interactive-bash/tmux-path-resolver"
|
||||
import type { SpawnPaneResult } from "../types"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../bun-spawn-shim"
|
||||
import type { TmuxConfig } from "../../../config/schema"
|
||||
import { getTmuxPath } from "../../../tools/interactive-bash/tmux-path-resolver"
|
||||
import type { SpawnPaneResult } from "../types"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { spawn } from "bun"
|
||||
export { spawn } from "../../bun-spawn-shim"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../bun-spawn-shim"
|
||||
import type { TmuxConfig } from "../../../config/schema"
|
||||
import { getTmuxPath } from "../../../tools/interactive-bash/tmux-path-resolver"
|
||||
import type { SpawnPaneResult } from "../types"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../bun-spawn-shim"
|
||||
|
||||
import type { ArchiveEntry } from "../archive-entry-validator"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn, spawnSync } from "bun"
|
||||
import { spawn, spawnSync } from "../bun-spawn-shim"
|
||||
|
||||
import type { ArchiveEntry } from "../archive-entry-validator"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../bun-spawn-shim"
|
||||
|
||||
export async function readZipSymlinkTarget(
|
||||
archivePath: string,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../bun-spawn-shim"
|
||||
|
||||
import type { ArchiveEntry } from "../archive-entry-validator"
|
||||
import { log } from "../logger"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn, spawnSync } from "bun"
|
||||
import { spawn, spawnSync } from "../bun-spawn-shim"
|
||||
|
||||
import type { ArchiveEntry } from "../archive-entry-validator"
|
||||
import { readZipSymlinkTarget } from "./read-zip-symlink-target"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn, spawnSync } from "bun"
|
||||
import { spawn, spawnSync } from "./bun-spawn-shim"
|
||||
import { release } from "os"
|
||||
|
||||
import { validateArchiveEntries } from "./archive-entry-validator"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../shared/bun-spawn-shim"
|
||||
import { existsSync } from "fs"
|
||||
import {
|
||||
getSgCliPath,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { resolve } from "node:path"
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../shared/bun-spawn-shim"
|
||||
import {
|
||||
resolveGrepCli,
|
||||
type GrepBackend,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../shared/bun-spawn-shim"
|
||||
import {
|
||||
resolveGrepCli,
|
||||
type ResolvedCli,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import path from "path"
|
||||
import { log } from "../../shared"
|
||||
import { spawn as bunSpawn } from "../../shared/bun-spawn-shim"
|
||||
|
||||
interface FormatterConfig {
|
||||
disabled?: boolean
|
||||
@@ -106,7 +107,7 @@ export async function runFormattersForFile(
|
||||
const cmd = buildFormatterCommand(formatter.command, filePath)
|
||||
try {
|
||||
log("[formatter-trigger] Running formatter", { command: cmd, file: filePath })
|
||||
const proc = Bun.spawn(cmd, {
|
||||
const proc = bunSpawn(cmd, {
|
||||
cwd: directory,
|
||||
env: { ...process.env, ...formatter.environment },
|
||||
stdout: "ignore",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "bun"
|
||||
import { spawn } from "../../shared/bun-spawn-shim"
|
||||
|
||||
let tmuxPath: string | null = null
|
||||
let initPromise: Promise<string | null> | null = null
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn as bunSpawn } from "bun"
|
||||
import { spawn as bunSpawn } from "../../shared/bun-spawn-shim"
|
||||
import { spawn as nodeSpawn, type ChildProcess } from "node:child_process"
|
||||
import { existsSync, statSync } from "fs"
|
||||
import { log } from "../../shared/logger"
|
||||
|
||||
Reference in New Issue
Block a user