Linter · Rules
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
Reported:
import { readFileSync } from "node:fs";
const config = JSON.parse(readFileSync("config.json", "utf8"));
import path from "node:path";
const schema = Bun.file(`schemas/${name}.json`);
const output = path.resolve("dist", "index.js");
Not reported:
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(). |
const user = loadFixture("fixtures/user.json");
const team = helpers.loadFixture("fixtures/team.json");
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");