Files
codex/prs/bolinfest/study/PR-2237-study.md
2025-09-02 15:17:45 -07:00

3.3 KiB
Raw Blame History

DOs

  • Keep Prettier Coverage For JS: ensure codex-cli JavaScript stays formatted in CI.
// package.json
{
  "scripts": {
    "format": "prettier --check *.json *.md .github/workflows/*.yml **/*.js",
    "format:fix": "prettier --write *.json *.md .github/workflows/*.yml **/*.js"
  },
  "devDependencies": {
    "prettier": "^3.5.3"
  }
}
  • Use A Safe Dynamic Import Helper: return null on failure; dont throw here.
async function tryImport(moduleName) {
  try {
    return await import(moduleName);
  } catch {
    return null;
  }
}
  • Name Functions For What They Return: resolveRgDir() returns a directory, not a file path. Also, avoid double catches—check for null.
import path from "node:path";

async function resolveRgDir() {
  const mod = await tryImport("@vscode/ripgrep");
  if (!mod?.rgPath) return null;
  return path.dirname(mod.rgPath);
}
  • Prepend To PATH With Correct Separator: prefer process.env.PATH only; make new dirs take precedence.
function getUpdatedPath(newDirs) {
  const sep = process.platform === "win32" ? ";" : ":";
  const existing = process.env.PATH || "";
  return [...newDirs, ...existing.split(sep).filter(Boolean)].join(sep);
}
  • Degrade Gracefully If ripgrep Missing: only add the rg dir when available; still run the CLI.
const extraDirs = [];
const rgDir = await resolveRgDir();
if (rgDir) extraDirs.push(rgDir);
const updatedPath = getUpdatedPath(extraDirs);
  • Pass Updated PATH Only To The Child: dont mutate global env; include CODEX_MANAGED_BY_NPM.
const child = spawn(binaryPath, process.argv.slice(2), {
  stdio: "inherit",
  env: { ...process.env, PATH: updatedPath, CODEX_MANAGED_BY_NPM: "1" }
});
  • Validate Against Node 20: if module type is ambiguous, avoid toplevel await; wrap in an async entry point.
(async function main() {
  const { spawn } = await import("node:child_process");
  // ...rest of startup logic...
})().catch((err) => {
  console.error("codex failed:", err);
  process.exit(1);
});

DONTs

  • Dont Treat Env Vars As CaseSensitive On Windows: skip process.env.Path.
// ❌ Dont
const existingPath = process.env.PATH || process.env.Path || "";
  • Dont Throw When ripgrep Isnt Installed: it may be missing due to --ignore-scripts or network issues.
// ❌ Dont
if (!mod?.rgPath) {
  throw new Error("ripgrep not found");
}
  • Dont DoubleCatch And Hide Logic Errors: rely on tryImport() and test for null.
// ❌ Dont
async function resolveRgDir() {
  try {
    const { rgPath } = await import("@vscode/ripgrep");
    return path.dirname(rgPath);
  } catch (err) {
    console.error("unable to import ripgrep", err);
    return null;
  }
}
  • Dont Append New Dirs To The End Of PATH: rg should win precedence.
// ❌ Dont
const updatedPath = `${process.env.PATH}${sep}${newDirs.join(sep)}`;
  • Dont Spam Errors For Optional Deps: missing ripgrep isnt fatal; keep logs minimal.
// ❌ Dont
console.error("rg missing; aborting startup");
// ✅ Prefer silent skip or a lownoise debug log
  • Dont Rely On TopLevel Await In CJS: it may break under the Node 20 minimum if the file isnt ESM.
// ❌ Dont (in CommonJS)
const { spawn } = await import("node:child_process");