sandboxedjs 0.1.22 → 0.1.24

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/dist/index.d.cts CHANGED
@@ -1,4 +1,120 @@
1
- import { MemoryVolume, Nodepod } from '@scelar/nodepod';
1
+ import EventEmitter from 'events';
2
+ import streamModule from 'stream-browserify';
3
+
4
+ /** The handle a pod's process manager returns. */
5
+ interface ChildHandle {
6
+ pid: number;
7
+ state: "starting" | "running" | "exited";
8
+ exitCode: number | undefined;
9
+ on(event: "stdout" | "stderr" | "exit", listener: (...args: any[]) => void): unknown;
10
+ exec(): void;
11
+ sendStdin(data: string): void;
12
+ kill(signal?: string): void;
13
+ }
14
+ interface ChildSpawnConfig {
15
+ command: string;
16
+ args?: string[];
17
+ cwd?: string;
18
+ env?: Record<string, string>;
19
+ parentPid?: number;
20
+ }
21
+ type SpawnChild = (config: ChildSpawnConfig) => ChildHandle;
22
+ declare function createChildProcessModule(spawnChild: SpawnChild, defaultCwd: () => string): Record<string, unknown>;
23
+
24
+ /**
25
+ * Clean-room contracts between SandboxedJS and its JavaScript runtime.
26
+ *
27
+ * These deliberately describe only behavior SandboxedJS consumes. Runtime
28
+ * implementations may use Web Workers in browsers or worker_threads on Node.
29
+ */
30
+
31
+ interface VolumeStats {
32
+ totalBytes: number;
33
+ fileCount: number;
34
+ /** New runtime spelling. */
35
+ directoryCount?: number;
36
+ /** Compatibility spelling used by existing volume implementations. */
37
+ dirCount?: number;
38
+ }
39
+ interface VolumeStat {
40
+ mode: number;
41
+ size: number;
42
+ uid: number;
43
+ gid: number;
44
+ ino: number;
45
+ nlink: number;
46
+ atimeMs: number;
47
+ mtimeMs: number;
48
+ ctimeMs: number;
49
+ birthtimeMs: number;
50
+ isFile(): boolean;
51
+ isDirectory(): boolean;
52
+ isSymbolicLink(): boolean;
53
+ }
54
+ interface RuntimeVolume {
55
+ readFileSync(path: string): Uint8Array;
56
+ writeFileSync(path: string, data: string | Uint8Array): void;
57
+ appendFileSync(path: string, data: string | Uint8Array): void;
58
+ readdirSync(path: string): string[];
59
+ lstatSync(path: string): VolumeStat;
60
+ readlinkSync(path: string): string;
61
+ mkdirSync(path: string, options?: {
62
+ mode?: number;
63
+ }): void;
64
+ rmdirSync(path: string): void;
65
+ unlinkSync(path: string): void;
66
+ renameSync(from: string, to: string): void;
67
+ symlinkSync(target: string, path: string): void;
68
+ linkSync(existing: string, path: string): void;
69
+ truncateSync(path: string, length?: number): void;
70
+ chmodSync(path: string, mode: number): void;
71
+ lchmodSync(path: string, mode: number): void;
72
+ chownSync(path: string, uid: number, gid: number): void;
73
+ lchownSync(path: string, uid: number, gid: number): void;
74
+ utimesSync(path: string, atime: Date, mtime: Date): void;
75
+ getStats(): VolumeStats;
76
+ }
77
+ interface RuntimeProcessResult {
78
+ exitCode: number;
79
+ stdout: string;
80
+ stderr: string;
81
+ }
82
+ interface RuntimeProcess {
83
+ readonly completion: Promise<RuntimeProcessResult>;
84
+ on(event: "output" | "error" | "exit", listener: (...args: any[]) => void): this;
85
+ write(data: string): void;
86
+ kill(signal?: string): void;
87
+ }
88
+ interface RuntimeHttpResponse {
89
+ statusCode?: number;
90
+ statusMessage?: string;
91
+ headers?: Record<string, string>;
92
+ body?: string | Uint8Array | ArrayBuffer;
93
+ }
94
+ interface RuntimePackageInstaller {
95
+ install(name: string, version?: string, options?: Record<string, unknown>): Promise<unknown>;
96
+ installFromManifest(path: string, options?: Record<string, unknown>): Promise<unknown>;
97
+ /** Create a view that installs into another project root. */
98
+ forCwd?(cwd: string): RuntimePackageInstaller;
99
+ }
100
+ /** The process-manager protocol a container's kernel bridge substitutes for. */
101
+ interface RuntimeProcessManager {
102
+ spawn(config: ChildSpawnConfig): ChildHandle;
103
+ }
104
+ interface RuntimePod {
105
+ readonly volume: RuntimeVolume;
106
+ readonly packages: RuntimePackageInstaller;
107
+ readonly instanceId: string;
108
+ readonly processManager: RuntimeProcessManager;
109
+ readonly proxy: {
110
+ activePorts(instanceId?: string): number[];
111
+ };
112
+ spawn(command: string, args?: string[], options?: Record<string, unknown>): Promise<RuntimeProcess>;
113
+ request(port: number, init?: Record<string, unknown>): Promise<RuntimeHttpResponse>;
114
+ snapshot(options?: Record<string, unknown>): unknown;
115
+ restore(snapshot: unknown, options?: Record<string, unknown>): Promise<void>;
116
+ teardown(): void;
117
+ }
2
118
 
3
119
  type FileKind = "file" | "directory" | "symlink" | "chardev" | "blockdev" | "fifo" | "socket";
4
120
  /** Render as `drwxr-xr-x`, honouring setuid/setgid/sticky. */
@@ -138,11 +254,11 @@ interface ResolveOptions {
138
254
  followFinal?: boolean;
139
255
  }
140
256
  declare class Vfs {
141
- readonly volume: MemoryVolume;
257
+ readonly volume: RuntimeVolume;
142
258
  private readonly providers;
143
259
  private nextVirtualIno;
144
260
  private readonly virtualInos;
145
- constructor(volume: MemoryVolume);
261
+ constructor(volume: RuntimeVolume);
146
262
  addProvider(provider: VirtualProvider): void;
147
263
  removeProvider(root: string): void;
148
264
  /** The mount points currently served synthetically. */
@@ -665,7 +781,7 @@ declare class NetworkStack {
665
781
  private readonly ifaces;
666
782
  private readonly listeners;
667
783
  readonly options: Required<Pick<NetworkOptions, "allowOutbound">> & NetworkOptions;
668
- constructor(pod: Nodepod, vfs: Vfs, options?: NetworkOptions);
784
+ constructor(pod: RuntimePod, vfs: Vfs, options?: NetworkOptions);
669
785
  interfaces(): NetInterface[];
670
786
  interface(name: string): NetInterface | undefined;
671
787
  setInterfaceUp(name: string, up: boolean): boolean;
@@ -705,7 +821,7 @@ declare class NetworkStack {
705
821
  */
706
822
 
707
823
  interface KernelOptions {
708
- pod: Nodepod;
824
+ pod: RuntimePod;
709
825
  hostname?: string;
710
826
  /** Login user for interactive sessions. Defaults to `root`. */
711
827
  user?: string;
@@ -760,7 +876,7 @@ declare class Kernel {
760
876
  readonly procs: ProcessTable;
761
877
  readonly commands: CommandRegistry;
762
878
  readonly users: UserDatabase;
763
- readonly pod: Nodepod;
879
+ readonly pod: RuntimePod;
764
880
  readonly bootTime: number;
765
881
  readonly memoryBytes: number;
766
882
  readonly cpus: number;
@@ -1489,33 +1605,21 @@ interface ContainerOptions {
1489
1605
  /** Invoked when an in-container HTTP server starts listening. */
1490
1606
  onServerReady?: (port: number, url: string) => void;
1491
1607
  /**
1492
- * Supply the Nodepod instance instead of letting the container boot one.
1608
+ * Run on a JavaScript runtime you booted yourself.
1493
1609
  *
1494
- * The default path imports `@scelar/nodepod/headless`, which installs a
1495
- * `worker_threads` host and is the right choice on Node. In a browser you
1496
- * boot Nodepod's browser build yourself (it needs a service worker) and hand
1497
- * the instance over:
1610
+ * The container boots a {@link LocalRuntimePod} when this is omitted, which
1611
+ * is what almost every caller wants. Pass one to share a single runtime
1612
+ * across containers, to seed it differently, or to substitute an
1613
+ * implementation of your own — anything satisfying {@link RuntimePod} works.
1498
1614
  *
1499
1615
  * ```ts
1500
- * import { Nodepod } from "@scelar/nodepod";
1501
- * const pod = await Nodepod.boot({ ... });
1502
- * const box = await createContainer({ pod });
1616
+ * const pod = await LocalRuntimePod.boot({ workdir: "/app" });
1617
+ * const box = await createContainer({ pod, cwd: "/app" });
1503
1618
  * ```
1504
1619
  */
1505
- pod?: Nodepod;
1620
+ pod?: RuntimePod;
1506
1621
  /** Python runtime settings; a browser host uses this to locate the wasm. */
1507
1622
  python?: PythonOptions;
1508
- /**
1509
- * Forwarded to Nodepod when this package boots it in a browser. `swUrl`
1510
- * points at the service worker if you serve it somewhere other than
1511
- * `/__sw__.js`; `serviceWorker: false` skips registration entirely, which
1512
- * also disables preview iframes.
1513
- */
1514
- browser?: {
1515
- swUrl?: string;
1516
- serviceWorker?: boolean;
1517
- watermark?: boolean;
1518
- };
1519
1623
  }
1520
1624
  interface ExecOptions {
1521
1625
  cwd?: string;
@@ -1561,7 +1665,7 @@ interface HttpResponse {
1561
1665
  }
1562
1666
  declare class Container {
1563
1667
  readonly kernel: Kernel;
1564
- readonly pod: Nodepod;
1668
+ readonly pod: RuntimePod;
1565
1669
  readonly fs: ContainerFs;
1566
1670
  readonly net: NetworkStack;
1567
1671
  private readonly defaults;
@@ -1739,13 +1843,13 @@ declare function exitCodeForSignal(sig: string): number;
1739
1843
  /**
1740
1844
  * The identity the container reports for itself.
1741
1845
  *
1742
- * The release string deliberately matches what Nodepod's `os.release()` returns
1743
- * inside a spawned Node process, so `uname -r` and
1744
- * `node -p "os.release()"` agree.
1846
+ * The runtime's `os.release()` is built from these same constants, so `uname -r`
1847
+ * and `node -p "os.release()"` agree inside the container — a program that
1848
+ * checks the platform gets one answer whichever way it asks.
1745
1849
  */
1746
1850
  declare const KERNEL_NAME = "Linux";
1747
1851
  declare const KERNEL_RELEASE = "5.10.0";
1748
- declare const OS_RELEASE = "PRETTY_NAME=\"SandboxedJS 1.0 (nodepod)\"\nNAME=\"SandboxedJS\"\nVERSION_ID=\"1.0\"\nVERSION=\"1.0 (nodepod)\"\nVERSION_CODENAME=nodepod\nID=sandboxedjs\nID_LIKE=debian\nHOME_URL=\"https://github.com/R1ck404/Nodepod\"\nSUPPORT_URL=\"https://www.npmjs.com/package/sandboxedjs\"\n";
1852
+ declare const OS_RELEASE = "PRETTY_NAME=\"SandboxedJS 1.0 (sandbox)\"\nNAME=\"SandboxedJS\"\nVERSION_ID=\"1.0\"\nVERSION=\"1.0 (sandbox)\"\nVERSION_CODENAME=sandbox\nID=sandboxedjs\nID_LIKE=debian\nHOME_URL=\"https://www.npmjs.com/package/sandboxedjs\"\nSUPPORT_URL=\"https://www.npmjs.com/package/sandboxedjs\"\n";
1749
1853
  interface UnameInfo {
1750
1854
  sysname: string;
1751
1855
  nodename: string;
@@ -2016,12 +2120,486 @@ declare function buildRootfs(vfs: Vfs, opts?: RootfsOptions): void;
2016
2120
  declare const NODE_VERSION = "v22.12.0";
2017
2121
 
2018
2122
  /**
2019
- * Package managers: `npm`/`npx`/`yarn`/`pnpm` on top of Nodepod's installer,
2020
- * and an `apt`-shaped front end for the things a container image would ship.
2123
+ * Package managers: `npm`/`npx`/`yarn`/`pnpm` on top of the runtime's package
2124
+ * installer, and an `apt`-shaped front end for the things a container image
2125
+ * would ship.
2021
2126
  */
2022
2127
 
2023
2128
  declare const NPM_VERSION = "10.9.0";
2024
2129
 
2130
+ type NodeKind = "file" | "directory" | "symlink";
2131
+ interface MemoryVolumeSnapshotEntry {
2132
+ path: string;
2133
+ ino: number;
2134
+ kind: NodeKind;
2135
+ mode: number;
2136
+ uid: number;
2137
+ gid: number;
2138
+ nlink: number;
2139
+ data: number[];
2140
+ target: string;
2141
+ atimeMs: number;
2142
+ mtimeMs: number;
2143
+ ctimeMs: number;
2144
+ birthtimeMs: number;
2145
+ }
2146
+ /** Browser-safe, synchronous in-memory filesystem used by the new runtime. */
2147
+ declare class MemoryVolume implements RuntimeVolume {
2148
+ private readonly entries;
2149
+ private nextIno;
2150
+ constructor();
2151
+ readFileSync(path: string): Uint8Array;
2152
+ writeFileSync(path: string, data: string | Uint8Array): void;
2153
+ appendFileSync(path: string, data: string | Uint8Array): void;
2154
+ readdirSync(path: string): string[];
2155
+ lstatSync(path: string): VolumeStat;
2156
+ readlinkSync(path: string): string;
2157
+ mkdirSync(path: string, options?: {
2158
+ mode?: number;
2159
+ }): void;
2160
+ rmdirSync(path: string): void;
2161
+ unlinkSync(path: string): void;
2162
+ renameSync(from: string, to: string): void;
2163
+ symlinkSync(target: string, path: string): void;
2164
+ linkSync(existing: string, path: string): void;
2165
+ truncateSync(path: string, length?: number): void;
2166
+ chmodSync(path: string, mode: number): void;
2167
+ lchmodSync(path: string, mode: number): void;
2168
+ chownSync(path: string, uid: number, gid: number): void;
2169
+ lchownSync(path: string, uid: number, gid: number): void;
2170
+ utimesSync(path: string, atime: Date, mtime: Date): void;
2171
+ getStats(): VolumeStats;
2172
+ snapshot(): MemoryVolumeSnapshotEntry[];
2173
+ restore(snapshot: MemoryVolumeSnapshotEntry[]): void;
2174
+ /** Serializable representation used by RuntimePod snapshots. */
2175
+ export(): Array<{
2176
+ path: string;
2177
+ kind: NodeKind;
2178
+ mode: number;
2179
+ uid: number;
2180
+ gid: number;
2181
+ data?: number[];
2182
+ target?: string;
2183
+ }>;
2184
+ private setMode;
2185
+ private setOwner;
2186
+ private key;
2187
+ private required;
2188
+ private requireParent;
2189
+ private inode;
2190
+ private touchChanged;
2191
+ }
2192
+
2193
+ /**
2194
+ * How a specifier was requested. Node resolves the same package differently
2195
+ * for the two, and a dual package depends on that: `is-promise` exports a
2196
+ * callable function under "require" and a namespace under "import", so
2197
+ * `require("is-promise")` served the ESM build is not merely suboptimal, it is
2198
+ * a `TypeError` at the first call site.
2199
+ */
2200
+ type RequestKind = "import" | "require";
2201
+ interface CommonJsModule {
2202
+ id: string;
2203
+ filename: string;
2204
+ exports: any;
2205
+ loaded: boolean;
2206
+ parent: CommonJsModule | null;
2207
+ children: CommonJsModule[];
2208
+ /**
2209
+ * Set for an ES module whose body contains a top-level `await`: the promise
2210
+ * for its completion. A synchronous `require` of such a module cannot
2211
+ * succeed, and this is what lets the engine say so precisely.
2212
+ */
2213
+ pending?: Promise<void>;
2214
+ }
2215
+ interface CommonJsEngineOptions {
2216
+ volume: RuntimeVolume;
2217
+ cwd?: string;
2218
+ builtins?: Record<string, unknown>;
2219
+ globals?: Record<string, unknown>;
2220
+ /**
2221
+ * Package-name substitutions, applied to bare specifiers before resolution.
2222
+ *
2223
+ * Several cornerstone build tools ship a compiled addon on the platforms
2224
+ * they support and a WebAssembly build for everywhere else — `rollup` and
2225
+ * `@rollup/wasm-node`, `esbuild` and `esbuild-wasm`. This runtime is always
2226
+ * the "everywhere else" case, but the packages select their binding by
2227
+ * reading `process.platform`, which reports a platform whose addon exists
2228
+ * and cannot be loaded. Redirecting the name is how the WebAssembly build
2229
+ * gets chosen instead.
2230
+ *
2231
+ * A substitution that is not installed falls back to the original name, so
2232
+ * an alias is a preference rather than a requirement.
2233
+ */
2234
+ aliases?: Record<string, string>;
2235
+ /**
2236
+ * Modules supplied by the runtime instead of resolved from the filesystem.
2237
+ *
2238
+ * The case this exists for is a toolchain component that cannot execute
2239
+ * inside the sandbox at all. `esbuild` is the example: every build of it
2240
+ * either dlopens a compiled addon or drives a Go/WebAssembly process through
2241
+ * facilities the runtime does not have, so the copy installed in
2242
+ * `node_modules` is unusable no matter which one is chosen. Handing over a
2243
+ * working implementation is what lets the tools built on it run.
2244
+ *
2245
+ * These take precedence over an installed package of the same name but not
2246
+ * over a Node built-in, so an override can never shadow `fs`.
2247
+ */
2248
+ overrides?: Record<string, unknown>;
2249
+ }
2250
+ /**
2251
+ * CommonJS loader for a runtime worker. The worker is the security boundary;
2252
+ * this class intentionally has no dependency on Node's module implementation.
2253
+ */
2254
+ declare class CommonJsEngine {
2255
+ readonly volume: RuntimeVolume;
2256
+ readonly cache: Map<string, CommonJsModule>;
2257
+ readonly builtins: Record<string, unknown>;
2258
+ readonly globals: Record<string, unknown>;
2259
+ readonly aliases: Record<string, string>;
2260
+ readonly overrides: Record<string, unknown>;
2261
+ cwd: string;
2262
+ main: CommonJsModule | null;
2263
+ /** `package.json` per directory; resolution reads them constantly. */
2264
+ private readonly manifests;
2265
+ constructor(volume: RuntimeVolume, options?: Omit<CommonJsEngineOptions, "volume">);
2266
+ /**
2267
+ * Evaluate an entry point.
2268
+ *
2269
+ * Returns the module's exports, or a promise for them when the entry is an
2270
+ * ES module with a top-level `await` — the caller has to await that before
2271
+ * treating the program as finished.
2272
+ */
2273
+ run(entry: string): unknown | Promise<unknown>;
2274
+ require(specifier: string, importer?: string): unknown;
2275
+ resolve(specifier: string, importer: string, kind?: RequestKind): string;
2276
+ private load;
2277
+ private evaluate;
2278
+ /** The `require` a module sees, complete with `resolve`, `cache` and `main`. */
2279
+ private makeRequire;
2280
+ /**
2281
+ * Load `specifier` and present it as an ES module namespace.
2282
+ *
2283
+ * A static `import` is synchronous here, exactly as the CommonJS `require`
2284
+ * it compiles down to. That is the one place this engine knowingly differs
2285
+ * from Node's real ESM semantics, and it is the trade that lets both module
2286
+ * systems share a single cache and resolver.
2287
+ */
2288
+ private importNamespace;
2289
+ /** `import(...)`: the same load, but able to await a top-level `await`. */
2290
+ private dynamicImport;
2291
+ /** `import.meta` for a module. */
2292
+ private importMeta;
2293
+ /**
2294
+ * The substituted specifier for `specifier`, or null when none applies.
2295
+ *
2296
+ * An alias names a package, so a subpath rides along: aliasing `rollup` also
2297
+ * redirects `rollup/dist/native.js` into the substitute.
2298
+ */
2299
+ private aliasFor;
2300
+ /**
2301
+ * Resolve a bare specifier (`pkg`, `@scope/pkg`, `pkg/sub`) by walking
2302
+ * `node_modules` up from the importer, exactly as Node does.
2303
+ */
2304
+ private resolvePackage;
2305
+ /**
2306
+ * Resolve `subpath` ("" for the package root) inside an installed package.
2307
+ *
2308
+ * An `exports` map, when present, is authoritative: Node refuses paths it
2309
+ * does not name, and packages rely on that to keep their internals private.
2310
+ * Only a package without one falls back to `main`/`module` and to treating
2311
+ * the subpath as a plain file path.
2312
+ */
2313
+ private resolveInPackage;
2314
+ /**
2315
+ * Resolve a `#private` specifier through the importing package's `imports`
2316
+ * map, which is scoped to the nearest enclosing package rather than to
2317
+ * `node_modules`.
2318
+ */
2319
+ private resolveImports;
2320
+ /** Resolve a path to a file, trying Node's extension and index fallbacks. */
2321
+ private resolvePath;
2322
+ private resolveIndex;
2323
+ /** The nearest ancestor directory holding a `package.json`. */
2324
+ private packageRoot;
2325
+ private readManifest;
2326
+ private builtin;
2327
+ private exists;
2328
+ private isFile;
2329
+ private isDirectory;
2330
+ private readText;
2331
+ private moduleNotFound;
2332
+ }
2333
+
2334
+ interface VirtualRequestInit {
2335
+ method?: string;
2336
+ path?: string;
2337
+ headers?: Record<string, string>;
2338
+ body?: string | Uint8Array | ArrayBuffer | null;
2339
+ }
2340
+ declare class VirtualIncomingMessage extends streamModule.Readable {
2341
+ readonly method: string;
2342
+ readonly url: string;
2343
+ readonly headers: Record<string, string>;
2344
+ readonly rawHeaders: string[];
2345
+ readonly httpVersion = "1.1";
2346
+ readonly httpVersionMajor = 1;
2347
+ readonly httpVersionMinor = 1;
2348
+ readonly complete = true;
2349
+ readonly socket: Record<string, unknown>;
2350
+ readonly connection: Record<string, unknown>;
2351
+ constructor(init: VirtualRequestInit);
2352
+ _read(): void;
2353
+ setTimeout(_milliseconds: number, callback?: () => void): this;
2354
+ }
2355
+ declare class VirtualServerResponse extends streamModule.Writable {
2356
+ statusCode: number;
2357
+ statusMessage: string;
2358
+ headersSent: boolean;
2359
+ sendDate: boolean;
2360
+ readonly req: VirtualIncomingMessage;
2361
+ readonly socket: Record<string, unknown>;
2362
+ readonly connection: Record<string, unknown>;
2363
+ private readonly headers;
2364
+ private readonly chunks;
2365
+ private resolve;
2366
+ readonly completed: Promise<RuntimeHttpResponse>;
2367
+ constructor(request: VirtualIncomingMessage);
2368
+ _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
2369
+ _final(callback: (error?: Error | null) => void): void;
2370
+ setHeader(name: string, value: string | number | readonly string[]): this;
2371
+ appendHeader(name: string, value: string | readonly string[]): this;
2372
+ getHeader(name: string): string | string[] | undefined;
2373
+ getHeaders(): Record<string, string | string[]>;
2374
+ getHeaderNames(): string[];
2375
+ hasHeader(name: string): boolean;
2376
+ removeHeader(name: string): void;
2377
+ writeHead(statusCode: number, statusMessage?: string | Record<string, unknown>, headers?: Record<string, unknown>): this;
2378
+ flushHeaders(): void;
2379
+ writeContinue(): void;
2380
+ writeProcessing(): void;
2381
+ addTrailers(_headers: Record<string, string>): void;
2382
+ setTimeout(_milliseconds: number, callback?: () => void): this;
2383
+ }
2384
+ declare class VirtualHttpServer extends EventEmitter {
2385
+ private readonly router;
2386
+ readonly owner: string;
2387
+ listening: boolean;
2388
+ private portValue;
2389
+ constructor(router: VirtualHttpRouter, owner: string, listener?: (req: VirtualIncomingMessage, res: VirtualServerResponse) => void);
2390
+ listen(...args: any[]): this;
2391
+ close(callback?: (error?: Error) => void): this;
2392
+ address(): {
2393
+ address: string;
2394
+ family: string;
2395
+ port: number;
2396
+ } | null;
2397
+ ref(): this;
2398
+ unref(): this;
2399
+ setTimeout(_milliseconds: number, callback?: () => void): this;
2400
+ }
2401
+ declare class VirtualHttpRouter {
2402
+ private readonly servers;
2403
+ /** Notified when a server begins listening, for `onServerReady`. */
2404
+ onListen: ((port: number) => void) | undefined;
2405
+ register(port: number, server: VirtualHttpServer, owner: string): void;
2406
+ unregister(port: number, server: VirtualHttpServer): void;
2407
+ activePorts(owner?: string): number[];
2408
+ closeOwner(owner: string): void;
2409
+ closeAll(): void;
2410
+ request(port: number, init?: VirtualRequestInit): Promise<RuntimeHttpResponse>;
2411
+ }
2412
+
2413
+ interface CoreModulesOptions {
2414
+ volume: RuntimeVolume;
2415
+ cwd?: string;
2416
+ env?: Record<string, string>;
2417
+ argv?: string[];
2418
+ stdout?: (chunk: string) => void;
2419
+ stderr?: (chunk: string) => void;
2420
+ onExit?: (code: number) => void;
2421
+ http?: {
2422
+ router: VirtualHttpRouter;
2423
+ owner: string;
2424
+ };
2425
+ /** Backs `child_process`; without it the module reports as unavailable. */
2426
+ spawnChild?: SpawnChild;
2427
+ /** File holding the process's standard input, exposed as descriptor 0. */
2428
+ stdinPath?: string;
2429
+ }
2430
+ /** Build the core-module table injected into each isolated JS worker. */
2431
+ declare function createCoreModules(options: CoreModulesOptions): {
2432
+ builtins: Record<string, unknown>;
2433
+ globals: Record<string, unknown>;
2434
+ process: Record<string, any>;
2435
+ /**
2436
+ * How many timers this process still has outstanding.
2437
+ *
2438
+ * Node keeps a process alive while its event loop has work, and exits when
2439
+ * it does not. Tracking the timers a program schedules is what lets this
2440
+ * runtime make the same decision — without it a server that binds its port
2441
+ * one turn after its entry module settles looks indistinguishable from a
2442
+ * script that has simply finished.
2443
+ */
2444
+ pendingHandles(): number;
2445
+ };
2446
+
2447
+ interface EsmTransformResult {
2448
+ /** The rewritten source. */
2449
+ code: string;
2450
+ /**
2451
+ * True when the file is an ES module, and so must be evaluated in a wrapper
2452
+ * that does not inject `require`, `module`, `__filename` or `__dirname`.
2453
+ *
2454
+ * False for a CommonJS file that was rewritten only because it contains a
2455
+ * dynamic `import(...)`, which is legal there and still has to be routed
2456
+ * through the engine rather than to the host realm.
2457
+ */
2458
+ esm: boolean;
2459
+ /** True when the module body contains a top-level `await`. */
2460
+ topLevelAwait: boolean;
2461
+ }
2462
+ declare function looksLikeEsm(source: string): boolean;
2463
+ /**
2464
+ * Rewrite `source` from ESM to the engine's CommonJS wrapper shape, or return
2465
+ * `null` when it is not an ES module and should be evaluated as-is.
2466
+ *
2467
+ * `null` is also returned when the source does not parse as a module: that is
2468
+ * not this function's error to raise. Letting it through means the engine
2469
+ * evaluates the original text and the runtime reports the real syntax error at
2470
+ * the real position.
2471
+ */
2472
+ declare function transformEsm(source: string, filename?: string): EsmTransformResult | null;
2473
+
2474
+ interface LocalRuntimeOptions {
2475
+ workdir?: string;
2476
+ env?: Record<string, string>;
2477
+ files?: Record<string, string | Uint8Array>;
2478
+ registry?: string;
2479
+ fetch?: typeof globalThis.fetch;
2480
+ /** Invoked when a program inside the runtime starts listening on a port. */
2481
+ onServerReady?: (port: number, url: string) => void;
2482
+ /** Extra package substitutions, merged over {@link WASM_ALIASES}. */
2483
+ aliases?: Record<string, string>;
2484
+ /** Modules supplied by the host rather than resolved from the volume. */
2485
+ modules?: Record<string, unknown>;
2486
+ /**
2487
+ * Supply `esbuild` from the host when it can be loaded. On by default: no
2488
+ * build of esbuild runs inside the sandbox, so without this every toolchain
2489
+ * that depends on it — Vite included — starts and then fails on the first
2490
+ * transform.
2491
+ */
2492
+ hostEsbuild?: boolean;
2493
+ }
2494
+ /**
2495
+ * Default substitutions for packages that would otherwise load a compiled
2496
+ * addon.
2497
+ *
2498
+ * Each of these ships a WebAssembly build under a second package name for
2499
+ * exactly this situation — a host with no prebuilt binary for its platform.
2500
+ * The substitute is only used when it is actually installed, so a project that
2501
+ * has neither is unaffected and one that has both gets the runnable one.
2502
+ */
2503
+ declare const WASM_ALIASES: Record<string, string>;
2504
+ /**
2505
+ * First complete clean-room RuntimePod composition. Execution currently uses
2506
+ * the caller's JS realm; BrowserRuntimePod will place the same engine in a
2507
+ * dedicated Worker before this becomes the default untrusted-code path.
2508
+ */
2509
+ declare class LocalRuntimePod implements RuntimePod {
2510
+ readonly volume: MemoryVolume;
2511
+ readonly packages: RuntimePackageInstaller;
2512
+ readonly instanceId: string;
2513
+ private readonly router;
2514
+ readonly proxy: {
2515
+ activePorts: (_instanceId?: string) => number[];
2516
+ };
2517
+ /**
2518
+ * Mutable on purpose: a container replaces `spawn` so that children resolve
2519
+ * against the kernel's PATH. Left alone, it runs `node` and reports anything
2520
+ * else as not found, which is the correct answer for a bare pod.
2521
+ */
2522
+ readonly processManager: {
2523
+ spawn(config: ChildSpawnConfig): ChildHandle;
2524
+ };
2525
+ private disposed;
2526
+ private readonly workdir;
2527
+ private readonly env;
2528
+ private readonly aliases;
2529
+ private readonly modules;
2530
+ private constructor();
2531
+ static boot(options?: LocalRuntimeOptions): Promise<LocalRuntimePod>;
2532
+ spawn(command: string, args?: string[], options?: Record<string, unknown>): Promise<RuntimeProcess>;
2533
+ /**
2534
+ * Wait until the process has either started serving or genuinely run out of
2535
+ * work.
2536
+ *
2537
+ * Two different kinds of pending work have to be waited on. Callbacks queued
2538
+ * as microtasks or `nextTick` — which is most of what streams and promise
2539
+ * chains are built from — need only for the current turn to end, so a few
2540
+ * turns of the macrotask queue are yielded first. Without that, a script
2541
+ * whose last act is `process.stdin.on("data", …)` exits before its own
2542
+ * handler runs and produces no output at all. Timers are the part that can
2543
+ * outlive any number of turns, so those are then polled until none remain.
2544
+ *
2545
+ * A plain script that has genuinely finished falls straight through both,
2546
+ * costing a handful of empty turns.
2547
+ */
2548
+ private settle;
2549
+ request(_port: number, _init?: Record<string, unknown>): Promise<RuntimeHttpResponse>;
2550
+ snapshot(): MemoryVolumeSnapshotEntry[];
2551
+ restore(snapshot: unknown): Promise<void>;
2552
+ teardown(): void;
2553
+ private seed;
2554
+ private assertActive;
2555
+ }
2556
+
2557
+ interface RegistryManifest {
2558
+ name: string;
2559
+ version: string;
2560
+ dist: {
2561
+ tarball: string;
2562
+ integrity?: string;
2563
+ shasum?: string;
2564
+ };
2565
+ dependencies?: Record<string, string>;
2566
+ optionalDependencies?: Record<string, string>;
2567
+ bin?: string | Record<string, string>;
2568
+ }
2569
+ interface CleanInstallerOptions {
2570
+ cwd?: string;
2571
+ registry?: string;
2572
+ fetch?: typeof globalThis.fetch;
2573
+ }
2574
+ interface InstallOptions extends Record<string, unknown> {
2575
+ onProgress?: (message: string) => void;
2576
+ persist?: boolean;
2577
+ persistDev?: boolean;
2578
+ withDevDeps?: boolean;
2579
+ }
2580
+ /** npm-registry installer independent of npm CLI and Node host APIs. */
2581
+ declare class CleanPackageInstaller implements RuntimePackageInstaller {
2582
+ readonly volume: RuntimeVolume;
2583
+ readonly options: CleanInstallerOptions;
2584
+ private readonly registry;
2585
+ private readonly fetcher;
2586
+ private readonly metadata;
2587
+ private readonly tarballs;
2588
+ constructor(volume: RuntimeVolume, options?: CleanInstallerOptions);
2589
+ forCwd(cwd: string): CleanPackageInstaller;
2590
+ install(name: string, version?: string, options?: InstallOptions): Promise<RegistryManifest>;
2591
+ installFromManifest(path: string, options?: InstallOptions): Promise<void>;
2592
+ private installAt;
2593
+ private getMetadata;
2594
+ private getTarball;
2595
+ private createBinLinks;
2596
+ private persist;
2597
+ private removeIfPresent;
2598
+ private readJson;
2599
+ private tryReadJson;
2600
+ }
2601
+ declare function extractNpmTarball(volume: RuntimeVolume, compressed: Uint8Array, destination: string): void;
2602
+
2025
2603
  /**
2026
2604
  * sandboxedjs — a Linux-like container that runs entirely inside Node.js.
2027
2605
  *
@@ -2040,4 +2618,4 @@ declare const NPM_VERSION = "10.9.0";
2040
2618
  * ```
2041
2619
  */
2042
2620
 
2043
- export { ArithError, BufferSink, type CPythonOptions, CallbackSink, type Command, CommandRegistry, Container, ContainerFs, type ContainerOptions, type ContextInit, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, type VirtualNode, type VirtualProvider, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createContainer, createContext, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, resetPidCounter, shellQuote, strerror, unameInfo };
2621
+ export { ArithError, BufferSink, type CPythonOptions, CallbackSink, type ChildHandle, type ChildSpawnConfig, type CleanInstallerOptions, CleanPackageInstaller, type Command, CommandRegistry, CommonJsEngine, type CommonJsEngineOptions, type CommonJsModule, Container, ContainerFs, type ContainerOptions, type ContextInit, type CoreModulesOptions, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type EsmTransformResult, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type InstallOptions, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type LocalRuntimeOptions, LocalRuntimePod, MemoryVolume, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, type RuntimePackageInstaller, type RuntimePod, type RuntimeProcess, type RuntimeProcessManager, type RuntimeProcessResult, type RuntimeVolume, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnChild, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, VirtualHttpRouter, VirtualHttpServer, VirtualIncomingMessage, type VirtualNode, type VirtualProvider, VirtualServerResponse, WASM_ALIASES, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createChildProcessModule, createContainer, createContext, createCoreModules, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, extractNpmTarball, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, looksLikeEsm, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, resetPidCounter, shellQuote, strerror, transformEsm, unameInfo };