bun/no-cwd-dependent-path
Disallow relative paths that depend on the directory the process was started in
readFileSync("config.json") doesn't look next to the file that calls it. It looks in the directory the process was started in. The code works when you run it from the project root and fails with ENOENT when it runs from anywhere else. Start from import.meta.dirname to name a file next to your source.
The rule checks a string or a template literal that starts with a relative path, in these places:
- The
node:fsandnode:fs/promisesfunctions, exceptglobandglobSync. ForcopyFile,cp,link, andrename, both paths are checked. Forsymlink, only the second one is, because the target is relative to the link. path.resolve(), if every argument is a literal like that.Bun.file()andBun.write().
Configure#
Off by default. To turn it on:
[lint.rules]
"bun/no-cwd-dependent-path" = "error" # or "warn"Every option, set to its default:
[lint.rules]
"bun/no-cwd-dependent-path" = ["error", {
functions = [], # list of strings
}]Examples#
import { readFileSync } from "node:fs";
const config = JSON.parse(readFileSync("config.json"config.json is relative to the working directory of the process. Resolve it from import.meta.dirname., "utf8"));import path from "node:path";
const schema = Bun.file(`schemas/${name}.json`schemas/${name}.json is relative to the working directory of the process. Resolve it from import.meta.dirname.);
const output = path.resolve("dist"dist is relative to the working directory of the process. Resolve it from import.meta.dirname., "index.js");import { readFileSync } from "node:fs";
import path from "node:path";
const config = JSON.parse(readFileSync(path.join(import.meta.dirname, "config.json"), "utf8"));
const schema = Bun.file(new URL(`./schemas/${name}.json`, import.meta.url));
const output = path.resolve(import.meta.dirname, "dist", "index.js");Absolute paths and paths that come from a variable are fine:
import { readFileSync } from "node:fs";
readFileSync("/etc/hosts", "utf8");
readFileSync(process.argv[2], "utf8");
readFileSync(`${root}/config.json`, "utf8");Options#
| Option | Default | What it does |
|---|---|---|
functions | [] | Names of more functions that take a path as their first argument. A name matches both loadFixture() and helpers.loadFixture(). |
{ "functions": ["loadFixture"] }2 problemsconst user = loadFixture("fixtures/user.json"fixtures/user.json is relative to the working directory of the process. Resolve it from import.meta.dirname.);
const team = helpers.loadFixture("fixtures/team.json"fixtures/team.json is relative to the working directory of the process. Resolve it from import.meta.dirname.);When not to use it#
A command-line tool often means the working directory, like when it reads the package.json of the project it was started in. Say so with process.cwd(), or turn the rule off for those files:
import { readFileSync } from "node:fs";
import path from "node:path";
const manifest = readFileSync(path.resolve(process.cwd(), "package.json"), "utf8");