Skip to content

Commit 3b59d52

Browse files
authored
feat(js): expose mounts option, mountReal, and unmount on wrapper (#1133)
## Summary - Adds `mounts` option to `BashOptions` for constructor-time real FS mounts with per-mount `readOnly` support - Exposes `mountReal()` and `unmount()` methods on both `Bash` and `BashTool` wrapper classes - Achieves full parity with the Python bindings' mount API ## Test plan - [x] New test: `mountReal and unmount` — mounts /tmp, verifies access, unmounts - [x] JS crate compiles cleanly - [x] No Rust code changes — wrapper only Closes #1128
1 parent 5a3c055 commit 3b59d52

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

crates/bashkit-js/__test__/runtime-compat/vfs.test.mjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,17 @@ describe("VFS API", () => {
121121
const entries = fs.readDir("/tmp");
122122
assert.ok(entries.some((e) => e.name === "fsapi.txt"));
123123
});
124+
125+
it("mountReal and unmount", () => {
126+
const bash = new Bash();
127+
// Mount /tmp as a real filesystem at /host-tmp
128+
bash.mountReal("/tmp", "/host-tmp", true);
129+
// The mount should be accessible
130+
const r = bash.executeSync("ls /host-tmp 2>/dev/null; echo status=$?");
131+
assert.ok(r.stdout.includes("status=0"));
132+
// Unmount
133+
bash.unmount("/host-tmp");
134+
const r2 = bash.executeSync("ls /host-tmp 2>/dev/null; echo status=$?");
135+
assert.ok(r2.stdout.includes("status="));
136+
});
124137
});

crates/bashkit-js/wrapper.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,19 @@ export interface BashOptions {
6363
* ```
6464
*/
6565
files?: Record<string, FileValue>;
66+
/**
67+
* Real filesystem mounts. Each mount maps a host directory into the VFS.
68+
*
69+
* @example
70+
* ```typescript
71+
* const bash = new Bash({
72+
* mounts: [
73+
* { path: "/docs", root: "/real/path/to/docs", readOnly: true },
74+
* ],
75+
* });
76+
* ```
77+
*/
78+
mounts?: Array<{ path: string; root: string; readOnly?: boolean }>;
6679
/**
6780
* Enable embedded Python execution (`python`/`python3` builtins).
6881
*
@@ -136,6 +149,11 @@ function toNativeOptions(
136149
maxLoopIterations: options?.maxLoopIterations,
137150
maxMemory: options?.maxMemory,
138151
files: resolvedFiles,
152+
mounts: options?.mounts?.map((m) => ({
153+
hostPath: m.root,
154+
vfsPath: m.path,
155+
readOnly: m.readOnly,
156+
})),
139157
python: options?.python,
140158
externalFunctions: options?.externalFunctions,
141159
};
@@ -403,6 +421,16 @@ export class Bash {
403421
return this.native.fs();
404422
}
405423

424+
/** Mount a host directory into the VFS. readOnly defaults to true. */
425+
mountReal(hostPath: string, vfsPath: string, readOnly?: boolean): void {
426+
this.native.mountReal(hostPath, vfsPath, readOnly);
427+
}
428+
429+
/** Unmount a previously mounted filesystem. */
430+
unmount(vfsPath: string): void {
431+
this.native.unmount(vfsPath);
432+
}
433+
406434
/**
407435
* List entry names in a directory. Returns empty array if directory does not exist.
408436
*/
@@ -625,6 +653,16 @@ export class BashTool {
625653
return this.native.fs();
626654
}
627655

656+
/** Mount a host directory into the VFS. readOnly defaults to true. */
657+
mountReal(hostPath: string, vfsPath: string, readOnly?: boolean): void {
658+
this.native.mountReal(hostPath, vfsPath, readOnly);
659+
}
660+
661+
/** Unmount a previously mounted filesystem. */
662+
unmount(vfsPath: string): void {
663+
this.native.unmount(vfsPath);
664+
}
665+
628666
/**
629667
* List entry names in a directory. Returns empty array if directory does not exist.
630668
*/

0 commit comments

Comments
 (0)