Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
import type { VmSandboxHandle } from "@suaveplan/api-sandbox-vm";
import {
SAND_VM_BRIDGE_CODES,
SandboxVmBridgeError,
} from "../error-codes/error-codes.js";
/**
* Idempotent lifecycle forwarder around a `VmSandboxHandle`. Wraps
* `start` so a second call is a silent no-op (the underlying sandbox
* has already evaluated its module) and wraps `dispose` so a second
* call is also a no-op (the sandbox's own `isDisposed()` would short-
* circuit, but having the guard at the bridge layer means the host
* never sees a stray throw if a future sandbox impl tightens its
* behaviour).
*
* Underlying-handle failures are re-wrapped as
* `SAND_VM_BRIDGE.LIFECYCLE_FAILED` with the original error preserved
* as `cause`.
*/
export interface SandboxLifecycleForwarder {
readonly start: () => Promise<void>;
readonly dispose: () => void;
readonly hasStarted: () => boolean;
readonly isDisposed: () => boolean;
}
/**
* Build the idempotent lifecycle forwarder around a `VmSandboxHandle`.
*/
export function createSandboxLifecycleForwarder(
sandbox: VmSandboxHandle
): SandboxLifecycleForwarder {
let started = false;
let disposed = false;
return Object.freeze({
async start(): Promise<void> {
if (started) return;
if (disposed) {
throw new SandboxVmBridgeError(
SAND_VM_BRIDGE_CODES.LIFECYCLE_FAILED,
"cannot start a disposed sandbox bridge"
);
}
try {
await sandbox.start();
} catch (err) {
throw new SandboxVmBridgeError(
SAND_VM_BRIDGE_CODES.LIFECYCLE_FAILED,
"sandbox start failed",
{ cause: err }
);
}
started = true;
},
dispose(): void {
if (disposed) return;
disposed = true;
try {
sandbox.dispose();
} catch (err) {
throw new SandboxVmBridgeError(
SAND_VM_BRIDGE_CODES.LIFECYCLE_FAILED,
"sandbox dispose failed",
{ cause: err }
);
}
},
hasStarted(): boolean {
return started;
},
isDisposed(): boolean {
return disposed;
},
});
}