rules_js
rules_js copied to clipboard
[FR]: Relative runfiles resolution
What is the current behavior?
Every Bazel program eventually needs to look up data in runfiles. Currently this done in JavaScript by either:
- Accessing the
${RUNFILES}environment variable like${RUNFILES}/wksp/path/to/file.txt. - Using
@bazel/runfiles. I think this technically works with@aspect_rules_js, though I've had trouble with it in the past.
Describe the feature
It would be very cool to have an API which works with relative paths like other JavaScript features such as import. This can be achieved with import.meta like so:
// wksp/path/to/script.mjs
import { promises as fs } from 'fs';
import { runfile } from '...';
// Returns `/.../wksp/path/to/file.txt`.
const filePath = runfile('./file.txt', import.meta);
const contents = await fs.readFile(filePath, 'utf8');
console.log(contents);
I'm not sure if @aspect_rules_js exposes any other JavaScript APIs, but I think this would be a useful and elegant one. It does require import.meta which necessitates either native ESM execution or a bundler which supports it. Exposing the absolute path to the runfile probably isn't ideal, since it leaks some information from outside the sandbox. Another approach would be to return a file path relative to the CWD, that way it could still be passed directly into APIs like fs.readFile and work as expected.
The actual implementation probably isn't too involved. I did my own version of this pattern with a Preact element <InlinedSvg src="./image.svg" importMeta={import.meta} />. We could probably copy most of that implementation.
I can't think of any other JS APIs for @aspect_rules_js and I know from experience that pairing a Bazel ruleset with an NPM package can be quite challenging, so I can understand if this is out of scope. I just think it's a cool and elegant idea which is worth considering adopting directly into the ruleset.