Spaces:
Runtime error
Runtime error
| /** | |
| * Best-effort build of the TPROXY IP_TRANSPARENT native addon so the production | |
| * build can copy `build/Release/transparent.node` into the standalone bundle | |
| * (assembleStandalone's NATIVE_ASSET_ENTRIES). Called from build-next-isolated.mjs | |
| * before the standalone is assembled. | |
| * | |
| * IP_TRANSPARENT is Linux-only, so this is a no-op everywhere else. A missing C | |
| * toolchain is NOT fatal — the TPROXY capture mode degrades gracefully when the | |
| * addon is absent (transparentSocket.ts returns "unavailable"). Every effectful | |
| * seam (platform/run/exists) is injectable so the decision logic is unit-testable. | |
| * | |
| * Hard Rule #13: the command + args are a fixed allowlist (no interpolation of | |
| * external/runtime values); `cwd` is derived from `projectRoot`, never user input. | |
| */ | |
| import { execFileSync } from "node:child_process"; | |
| import { existsSync } from "node:fs"; | |
| import path from "node:path"; | |
| /** | |
| * @param {string} projectRoot | |
| * @param {{ platform?: string, run?: (cmd:string, args:string[], cwd:string) => void, | |
| * exists?: (p:string) => boolean }} [opts] | |
| * @returns {{ built: boolean, reason?: string }} | |
| */ | |
| export function buildTproxyNative(projectRoot, opts = {}) { | |
| const platform = opts.platform ?? process.platform; | |
| const run = opts.run ?? defaultRun; | |
| const exists = opts.exists ?? existsSync; | |
| if (platform !== "linux") { | |
| return { built: false, reason: "non-linux host (IP_TRANSPARENT is Linux-only)" }; | |
| } | |
| const nativeDir = path.join(projectRoot, "src", "mitm", "tproxy", "native"); | |
| if (!exists(path.join(nativeDir, "binding.gyp"))) { | |
| return { built: false, reason: "native sources absent (binding.gyp not found)" }; | |
| } | |
| const out = path.join(nativeDir, "build", "Release", "transparent.node"); | |
| try { | |
| run("npx", ["--yes", "node-gyp", "rebuild"], nativeDir); | |
| } catch (err) { | |
| return { built: false, reason: `toolchain/build failed: ${err?.message ?? String(err)}` }; | |
| } | |
| if (!exists(out)) { | |
| return { built: false, reason: "node-gyp produced no transparent.node" }; | |
| } | |
| return { built: true }; | |
| } | |
| /** @type {(cmd: string, args: string[], cwd: string) => void} */ | |
| function defaultRun(cmd, args, cwd) { | |
| execFileSync(cmd, args, { cwd, stdio: "inherit" }); | |
| } | |