bvisor 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,23 @@ Node.js bindings for bVisor. Linux only.
6
6
 
7
7
  Requires: Zig 0.16+, Docker
8
8
 
9
+ From the repo root (next to build.zig), run:
10
+
11
+ ```bash
12
+ zig build test-node
13
+ ```
14
+
15
+ For a targeted test, from this directory, run:
9
16
  ```bash
10
- npm run dev # builds native binaries (zig build), then runs test.ts in a linux container
17
+ # Install the latest published bvisor and run test.ts in a linux container
18
+ npm run test:published
11
19
  ```
12
20
 
21
+ ## Publishing
22
+
23
+ Bump versions across all packages, then publish:
24
+
25
+ ```bash
26
+ bun run version:patch
27
+ bun run publish:all
28
+ ```
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { Sandbox } from "./src/sandbox";
package/package.json CHANGED
@@ -1,25 +1,38 @@
1
1
  {
2
2
  "name": "bvisor",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
+ "exports": {
7
+ ".": {
8
+ "bun": "./index.ts",
9
+ "default": "./dist/index.js"
10
+ }
11
+ },
6
12
  "files": [
7
- "dist/"
13
+ "dist/",
14
+ "index.ts",
15
+ "src/"
8
16
  ],
9
17
  "scripts": {
10
18
  "build": "tsc",
19
+ "prebuild": "cd ../../.. && zig build",
11
20
  "prepublishOnly": "npm run build",
12
- "predev": "cd ../../.. && zig build",
13
- "dev": "docker run --rm -v .:/app -w /app oven/bun:alpine sh -c 'bun install && bun test.ts'"
21
+ "test:published": "docker run --rm -v ./test.ts:/test.ts:ro oven/bun:alpine sh -c 'cd /tmp && echo {} > package.json && bun add bvisor && cp /test.ts . && bun test.ts'",
22
+ "version:patch": "npm version patch --workspaces --no-git-tag-version --force && npm version patch --no-git-tag-version --force",
23
+ "publish:all": "npm run prebuild && cd platforms/linux-arm64-musl && bun publish --access public && cd ../linux-arm64-gnu && bun publish --access public && cd ../linux-x64-musl && bun publish --access public && cd ../linux-x64-gnu && bun publish --access public && cd ../.. && bun publish --access public"
14
24
  },
25
+ "workspaces": [
26
+ "platforms/*"
27
+ ],
15
28
  "dependencies": {
16
29
  "detect-libc": "^2.0.3"
17
30
  },
18
31
  "optionalDependencies": {
19
- "@bvisor/linux-arm64-musl": "0.0.1",
20
- "@bvisor/linux-arm64-gnu": "0.0.1",
21
- "@bvisor/linux-x64-musl": "0.0.1",
22
- "@bvisor/linux-x64-gnu": "0.0.1"
32
+ "@bvisor/linux-arm64-musl": "0.0.2",
33
+ "@bvisor/linux-arm64-gnu": "0.0.2",
34
+ "@bvisor/linux-x64-musl": "0.0.2",
35
+ "@bvisor/linux-x64-gnu": "0.0.2"
23
36
  },
24
37
  "devDependencies": {
25
38
  "@types/node": "^25.2.0",
package/src/napi.ts ADDED
@@ -0,0 +1,5 @@
1
+ // Phantom-typed opaque handle to a native object.
2
+ // N-API "externals" are opaque pointers that JS holds but can't inspect.
3
+ // The phantom T prevents accidentally swapping e.g. External<"Sandbox"> and External<"Stream">.
4
+ declare const __external: unique symbol;
5
+ export type External<T> = unknown & { [__external]: T };
package/src/native.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { arch, platform } from "os";
2
+ import { familySync, MUSL } from "detect-libc";
3
+ import { External } from "./napi";
4
+
5
+ if (platform() !== "linux") {
6
+ throw new Error("bVisor only supports Linux");
7
+ }
8
+
9
+ /** FFI contract: typed interface for the native Zig module loaded via require(). */
10
+ export interface NativeModule {
11
+ createSandbox(): External<"Sandbox">;
12
+ sandboxRunCmd(
13
+ sandbox: External<"Sandbox">,
14
+ command: string
15
+ ): {
16
+ stdout: External<"Stream">;
17
+ stderr: External<"Stream">;
18
+ };
19
+ streamNext(stream: External<"Stream">): Uint8Array | null;
20
+ }
21
+
22
+ const libc = familySync() === MUSL ? "musl" : "gnu";
23
+ export const native: NativeModule = require(`@bvisor/linux-${arch()}-${libc}`);
package/src/sandbox.ts ADDED
@@ -0,0 +1,60 @@
1
+ import { External } from "./napi";
2
+ import { native } from "./native";
3
+
4
+ class Stream {
5
+ private ptr: External<"Stream">;
6
+
7
+ constructor(ptr: External<"Stream">) {
8
+ this.ptr = ptr;
9
+ }
10
+
11
+ toReadableStream(): ReadableStream<Uint8Array> {
12
+ const self = this;
13
+ return new ReadableStream({
14
+ async pull(controller) {
15
+ // TODO: make streamNext return a promise
16
+ const chunk = native.streamNext(self.ptr);
17
+ if (chunk) {
18
+ controller.enqueue(chunk);
19
+ } else {
20
+ controller.close();
21
+ }
22
+ },
23
+ });
24
+ }
25
+ }
26
+
27
+ export class Sandbox {
28
+ private ptr: External<"Sandbox">;
29
+
30
+ constructor() {
31
+ this.ptr = native.createSandbox();
32
+ }
33
+
34
+ runCmd(command: string) {
35
+ const result = native.sandboxRunCmd(this.ptr, command);
36
+ return createOutput(
37
+ new Stream(result.stdout).toReadableStream(),
38
+ new Stream(result.stderr).toReadableStream()
39
+ );
40
+ }
41
+ }
42
+
43
+ export interface Output {
44
+ stdoutStream: ReadableStream<Uint8Array>;
45
+ stderrStream: ReadableStream<Uint8Array>;
46
+ stdout: () => Promise<string>;
47
+ stderr: () => Promise<string>;
48
+ }
49
+
50
+ function createOutput(
51
+ stdoutStream: ReadableStream<Uint8Array>,
52
+ stderrStream: ReadableStream<Uint8Array>
53
+ ): Output {
54
+ return {
55
+ stdoutStream,
56
+ stderrStream,
57
+ stdout: () => new Response(stdoutStream).text(),
58
+ stderr: () => new Response(stderrStream).text(),
59
+ };
60
+ }