-
Notifications
You must be signed in to change notification settings - Fork 8
feat(js): expose real filesystem mounts with per-mount readOnly support #1128
Description
Summary
The Python bindings expose mount_real_readonly_at, mount_real_readwrite_at, and dynamic mount/unmount methods. The JS bindings have none of these — the only way to populate the VFS is via the files option in BashOptions.
Note: readOnly is accepted in BashOptions since 0.1.14 but is not enforced — all writes (redirections, rm, mkdir) still succeed.
Use case
We're building an SSH server (supabase.sh) that mounts a real docs directory as read-only into the VFS. Users connect via SSH and run grep/find/cat against the docs.
With the Python bindings:
bash = Bash()
bash.mount_real_readonly_at("/supabase/docs", docs_dir)With the JS bindings, we have to walk the directory ourselves and pass lazy loaders, plus install bash function overrides to block writes:
function walkDir(root: string, vRoot: string): Record<string, () => string> {
// ... recursively walk with readdirSync, map to () => readFileSync(...)
}
const bash = new Bash({ files: { ...walkDir(docsDir, "/supabase/docs") } })
// Then override rm, mv, cp, mkdir, etc. as EROFS functions
// But redirections (>, >>) and `command rm` still bypass thisRequested API
Parity with Python bindings:
// Constructor-time mounts
const bash = new Bash({
mounts: [
{ path: "/supabase/docs", root: "/real/path/to/docs", readOnly: true },
],
})
// Or method-based (like Python)
bash.mountRealReadonlyAt("/supabase/docs", docsDir)
bash.unmount("/supabase/docs")Why this matters
Without native VFS-level read-only enforcement, bash function overrides are the only option. These are bypassable via command rm and don't cover redirections (echo x > /file). The Python bindings solve this at the Rust VFS level — JS should too.
The Rust crate already has OverlayFs with readOnly support, and v0.1.13 added mount/unmount (#784). The Python bindings expose this.