@secure-exec/core 0.1.1-rc.3 → 0.2.0-rc.2

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.
Files changed (102) hide show
  1. package/dist/esm-compiler.d.ts +5 -1
  2. package/dist/esm-compiler.js +5 -1
  3. package/dist/fs-helpers.d.ts +1 -1
  4. package/dist/generated/isolate-runtime.d.ts +15 -15
  5. package/dist/generated/isolate-runtime.js +15 -15
  6. package/dist/index.d.ts +24 -5
  7. package/dist/index.js +23 -3
  8. package/dist/isolate-runtime/apply-custom-global-policy.js +3 -3
  9. package/dist/isolate-runtime/apply-timing-mitigation-freeze.js +2 -2
  10. package/dist/isolate-runtime/apply-timing-mitigation-off.js +2 -2
  11. package/dist/isolate-runtime/bridge-attach.js +2 -2
  12. package/dist/isolate-runtime/bridge-initial-globals.js +145 -6
  13. package/dist/isolate-runtime/eval-script-result.js +1 -1
  14. package/dist/isolate-runtime/global-exposure-helpers.js +2 -2
  15. package/dist/isolate-runtime/init-commonjs-module-globals.js +2 -2
  16. package/dist/isolate-runtime/override-process-cwd.js +1 -1
  17. package/dist/isolate-runtime/override-process-env.js +1 -1
  18. package/dist/isolate-runtime/require-setup.js +2868 -494
  19. package/dist/isolate-runtime/set-commonjs-file-globals.js +2 -2
  20. package/dist/isolate-runtime/set-stdin-data.js +1 -1
  21. package/dist/isolate-runtime/setup-dynamic-import.js +78 -19
  22. package/dist/isolate-runtime/setup-fs-facade.js +62 -23
  23. package/dist/kernel/command-registry.d.ts +44 -0
  24. package/dist/kernel/command-registry.js +114 -0
  25. package/dist/kernel/device-layer.d.ts +12 -0
  26. package/dist/kernel/device-layer.js +262 -0
  27. package/dist/kernel/dns-cache.d.ts +29 -0
  28. package/dist/kernel/dns-cache.js +52 -0
  29. package/dist/kernel/fd-table.d.ts +84 -0
  30. package/dist/kernel/fd-table.js +278 -0
  31. package/dist/kernel/file-lock.d.ts +34 -0
  32. package/dist/kernel/file-lock.js +122 -0
  33. package/dist/kernel/host-adapter.d.ts +50 -0
  34. package/dist/kernel/host-adapter.js +8 -0
  35. package/dist/kernel/index.d.ts +36 -0
  36. package/dist/kernel/index.js +34 -0
  37. package/dist/kernel/inode-table.d.ts +43 -0
  38. package/dist/kernel/inode-table.js +85 -0
  39. package/dist/kernel/kernel.d.ts +9 -0
  40. package/dist/kernel/kernel.js +1393 -0
  41. package/dist/kernel/permissions.d.ts +27 -0
  42. package/dist/kernel/permissions.js +118 -0
  43. package/dist/kernel/pipe-manager.d.ts +64 -0
  44. package/dist/kernel/pipe-manager.js +267 -0
  45. package/dist/kernel/proc-layer.d.ts +11 -0
  46. package/dist/kernel/proc-layer.js +501 -0
  47. package/dist/kernel/process-table.d.ts +124 -0
  48. package/dist/kernel/process-table.js +631 -0
  49. package/dist/kernel/pty.d.ts +108 -0
  50. package/dist/kernel/pty.js +541 -0
  51. package/dist/kernel/socket-table.d.ts +312 -0
  52. package/dist/kernel/socket-table.js +1188 -0
  53. package/dist/kernel/timer-table.d.ts +54 -0
  54. package/dist/kernel/timer-table.js +108 -0
  55. package/dist/kernel/types.d.ts +500 -0
  56. package/dist/kernel/types.js +89 -0
  57. package/dist/kernel/user.d.ts +29 -0
  58. package/dist/kernel/user.js +35 -0
  59. package/dist/kernel/vfs.d.ts +54 -0
  60. package/dist/kernel/vfs.js +8 -0
  61. package/dist/kernel/wait.d.ts +45 -0
  62. package/dist/kernel/wait.js +112 -0
  63. package/dist/kernel/wstatus.d.ts +21 -0
  64. package/dist/kernel/wstatus.js +33 -0
  65. package/dist/module-resolver.d.ts +4 -0
  66. package/dist/module-resolver.js +4 -0
  67. package/dist/package-bundler.d.ts +6 -1
  68. package/dist/runtime-driver.d.ts +3 -1
  69. package/dist/shared/bridge-contract.d.ts +349 -22
  70. package/dist/shared/bridge-contract.js +62 -5
  71. package/dist/shared/console-formatter.js +8 -4
  72. package/dist/shared/global-exposure.js +364 -19
  73. package/dist/shared/in-memory-fs.d.ts +33 -11
  74. package/dist/shared/in-memory-fs.js +439 -130
  75. package/dist/shared/permissions.d.ts +4 -6
  76. package/dist/shared/permissions.js +19 -39
  77. package/dist/types.d.ts +8 -159
  78. package/dist/types.js +5 -0
  79. package/package.json +12 -22
  80. package/dist/bridge/active-handles.d.ts +0 -22
  81. package/dist/bridge/active-handles.js +0 -55
  82. package/dist/bridge/child-process.d.ts +0 -99
  83. package/dist/bridge/child-process.js +0 -670
  84. package/dist/bridge/fs.d.ts +0 -281
  85. package/dist/bridge/fs.js +0 -2235
  86. package/dist/bridge/index.d.ts +0 -10
  87. package/dist/bridge/index.js +0 -41
  88. package/dist/bridge/module.d.ts +0 -75
  89. package/dist/bridge/module.js +0 -308
  90. package/dist/bridge/network.d.ts +0 -350
  91. package/dist/bridge/network.js +0 -2050
  92. package/dist/bridge/os.d.ts +0 -13
  93. package/dist/bridge/os.js +0 -256
  94. package/dist/bridge/polyfills.d.ts +0 -2
  95. package/dist/bridge/polyfills.js +0 -11
  96. package/dist/bridge/process.d.ts +0 -89
  97. package/dist/bridge/process.js +0 -1015
  98. package/dist/bridge.js +0 -12496
  99. package/dist/python-runtime.d.ts +0 -16
  100. package/dist/python-runtime.js +0 -45
  101. package/dist/runtime.d.ts +0 -31
  102. package/dist/runtime.js +0 -69
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  (() => {
3
- // isolate-runtime/src/common/global-exposure.ts
3
+ // ../core/isolate-runtime/src/common/global-exposure.ts
4
4
  function defineRuntimeGlobalBinding(name, value, mutable) {
5
5
  Object.defineProperty(globalThis, name, {
6
6
  value,
@@ -21,7 +21,7 @@
21
21
  return createRuntimeGlobalExposer(true);
22
22
  }
23
23
 
24
- // isolate-runtime/src/inject/set-commonjs-file-globals.ts
24
+ // ../core/isolate-runtime/src/inject/set-commonjs-file-globals.ts
25
25
  var __runtimeExposeMutableGlobal = getRuntimeExposeMutableGlobal();
26
26
  var __commonJsFileConfig = globalThis.__runtimeCommonJsFileConfig ?? {};
27
27
  var __filePath = typeof __commonJsFileConfig.filePath === "string" ? __commonJsFileConfig.filePath : "/<entry>.js";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  (() => {
3
- // isolate-runtime/src/inject/set-stdin-data.ts
3
+ // ../core/isolate-runtime/src/inject/set-stdin-data.ts
4
4
  if (typeof globalThis._stdinData !== "undefined") {
5
5
  globalThis._stdinData = globalThis.__runtimeStdinData;
6
6
  globalThis._stdinPosition = 0;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  (() => {
3
- // isolate-runtime/src/common/global-access.ts
3
+ // ../core/isolate-runtime/src/common/global-access.ts
4
4
  function isObjectLike(value) {
5
5
  return value !== null && (typeof value === "object" || typeof value === "function");
6
6
  }
7
7
 
8
- // isolate-runtime/src/common/global-exposure.ts
8
+ // ../core/isolate-runtime/src/common/global-exposure.ts
9
9
  function defineRuntimeGlobalBinding(name, value, mutable) {
10
10
  Object.defineProperty(globalThis, name, {
11
11
  value,
@@ -26,30 +26,58 @@
26
26
  return createRuntimeGlobalExposer(false);
27
27
  }
28
28
 
29
- // isolate-runtime/src/inject/setup-dynamic-import.ts
29
+ // ../core/isolate-runtime/src/inject/setup-dynamic-import.ts
30
30
  var __runtimeExposeCustomGlobal = getRuntimeExposeCustomGlobal();
31
31
  var __dynamicImportConfig = globalThis.__runtimeDynamicImportConfig ?? {};
32
32
  var __fallbackReferrer = typeof __dynamicImportConfig.referrerPath === "string" && __dynamicImportConfig.referrerPath.length > 0 ? __dynamicImportConfig.referrerPath : "/";
33
- var __dynamicImportHandler = async function(specifier, fromPath) {
33
+ var __dynamicImportCache = /* @__PURE__ */ new Map();
34
+ var __pathToFileURL = typeof globalThis.require === "function" ? globalThis.require("node:url").pathToFileURL ?? null : null;
35
+ var __resolveDynamicImportPath = function(request, referrer) {
36
+ if (!request.startsWith("./") && !request.startsWith("../") && !request.startsWith("/")) {
37
+ return request;
38
+ }
39
+ const baseDir = referrer.endsWith("/") ? referrer : referrer.slice(0, referrer.lastIndexOf("/")) || "/";
40
+ const segments = baseDir.split("/").filter(Boolean);
41
+ for (const part of request.split("/")) {
42
+ if (part === "." || part.length === 0) continue;
43
+ if (part === "..") {
44
+ segments.pop();
45
+ continue;
46
+ }
47
+ segments.push(part);
48
+ }
49
+ return `/${segments.join("/")}`;
50
+ };
51
+ var __dynamicImportHandler = function(specifier, fromPath) {
34
52
  const request = String(specifier);
35
53
  const referrer = typeof fromPath === "string" && fromPath.length > 0 ? fromPath : __fallbackReferrer;
36
- const allowRequireFallback = request.endsWith(".cjs") || request.endsWith(".json");
37
- const namespace = await globalThis._dynamicImport.apply(
38
- void 0,
39
- [request, referrer],
40
- { result: { promise: true } }
41
- );
42
- if (namespace !== null) {
43
- return namespace;
54
+ let resolved = null;
55
+ if (typeof globalThis._resolveModuleSync !== "undefined") {
56
+ resolved = globalThis._resolveModuleSync.applySync(
57
+ void 0,
58
+ [request, referrer, "import"]
59
+ );
44
60
  }
45
- if (!allowRequireFallback) {
46
- throw new Error("Cannot find module '" + request + "'");
61
+ const resolvedPath = typeof resolved === "string" && resolved.length > 0 ? resolved : __resolveDynamicImportPath(request, referrer);
62
+ const cacheKey = typeof resolved === "string" && resolved.length > 0 ? resolved : `${referrer}\0${request}`;
63
+ const cached = __dynamicImportCache.get(cacheKey);
64
+ if (cached) return Promise.resolve(cached);
65
+ if (typeof globalThis._requireFrom !== "function") {
66
+ throw new Error("Cannot load module: " + resolvedPath);
47
67
  }
48
- const runtimeRequire = globalThis.require;
49
- if (typeof runtimeRequire !== "function") {
50
- throw new Error("Cannot find module '" + request + "'");
68
+ let mod;
69
+ try {
70
+ mod = globalThis._requireFrom(resolved ?? request, referrer);
71
+ } catch (error) {
72
+ const message = error instanceof Error ? error.message : String(error);
73
+ if (error && typeof error === "object" && "code" in error && error.code === "MODULE_NOT_FOUND") {
74
+ throw new Error("Cannot load module: " + resolvedPath);
75
+ }
76
+ if (message.startsWith("Cannot find module ")) {
77
+ throw new Error("Cannot load module: " + resolvedPath);
78
+ }
79
+ throw error;
51
80
  }
52
- const mod = runtimeRequire(request);
53
81
  const namespaceFallback = { default: mod };
54
82
  if (isObjectLike(mod)) {
55
83
  for (const key of Object.keys(mod)) {
@@ -58,7 +86,38 @@
58
86
  }
59
87
  }
60
88
  }
61
- return namespaceFallback;
89
+ __dynamicImportCache.set(cacheKey, namespaceFallback);
90
+ return Promise.resolve(namespaceFallback);
91
+ };
92
+ var __importMetaResolveHandler = function(specifier, fromPath) {
93
+ const request = String(specifier);
94
+ const referrer = typeof fromPath === "string" && fromPath.length > 0 ? fromPath : __fallbackReferrer;
95
+ let resolved = null;
96
+ if (typeof globalThis._resolveModuleSync !== "undefined") {
97
+ resolved = globalThis._resolveModuleSync.applySync(
98
+ void 0,
99
+ [request, referrer, "import"]
100
+ );
101
+ }
102
+ if (resolved === null || resolved === void 0) {
103
+ resolved = globalThis._resolveModule.applySyncPromise(
104
+ void 0,
105
+ [request, referrer, "import"]
106
+ );
107
+ }
108
+ if (resolved === null) {
109
+ const err = new Error("Cannot find module '" + request + "'");
110
+ err.code = "MODULE_NOT_FOUND";
111
+ throw err;
112
+ }
113
+ if (resolved.startsWith("node:")) {
114
+ return resolved;
115
+ }
116
+ if (__pathToFileURL && resolved.startsWith("/")) {
117
+ return __pathToFileURL(resolved).href;
118
+ }
119
+ return resolved;
62
120
  };
63
121
  __runtimeExposeCustomGlobal("__dynamicImport", __dynamicImportHandler);
122
+ __runtimeExposeCustomGlobal("__importMetaResolve", __importMetaResolveHandler);
64
123
  })();
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  (() => {
3
- // isolate-runtime/src/common/global-exposure.ts
3
+ // ../core/isolate-runtime/src/common/global-exposure.ts
4
4
  function defineRuntimeGlobalBinding(name, value, mutable) {
5
5
  Object.defineProperty(globalThis, name, {
6
6
  value,
@@ -21,28 +21,67 @@
21
21
  return createRuntimeGlobalExposer(false);
22
22
  }
23
23
 
24
- // isolate-runtime/src/inject/setup-fs-facade.ts
24
+ // ../core/isolate-runtime/src/inject/setup-fs-facade.ts
25
25
  var __runtimeExposeCustomGlobal = getRuntimeExposeCustomGlobal();
26
- var __fsFacade = {
27
- readFile: globalThis._fsReadFile,
28
- writeFile: globalThis._fsWriteFile,
29
- readFileBinary: globalThis._fsReadFileBinary,
30
- writeFileBinary: globalThis._fsWriteFileBinary,
31
- readDir: globalThis._fsReadDir,
32
- mkdir: globalThis._fsMkdir,
33
- rmdir: globalThis._fsRmdir,
34
- exists: globalThis._fsExists,
35
- stat: globalThis._fsStat,
36
- unlink: globalThis._fsUnlink,
37
- rename: globalThis._fsRename,
38
- chmod: globalThis._fsChmod,
39
- chown: globalThis._fsChown,
40
- link: globalThis._fsLink,
41
- symlink: globalThis._fsSymlink,
42
- readlink: globalThis._fsReadlink,
43
- lstat: globalThis._fsLstat,
44
- truncate: globalThis._fsTruncate,
45
- utimes: globalThis._fsUtimes
46
- };
26
+ var __fsFacade = {};
27
+ Object.defineProperties(__fsFacade, {
28
+ readFile: { get() {
29
+ return globalThis._fsReadFile;
30
+ }, enumerable: true },
31
+ writeFile: { get() {
32
+ return globalThis._fsWriteFile;
33
+ }, enumerable: true },
34
+ readFileBinary: { get() {
35
+ return globalThis._fsReadFileBinary;
36
+ }, enumerable: true },
37
+ writeFileBinary: { get() {
38
+ return globalThis._fsWriteFileBinary;
39
+ }, enumerable: true },
40
+ readDir: { get() {
41
+ return globalThis._fsReadDir;
42
+ }, enumerable: true },
43
+ mkdir: { get() {
44
+ return globalThis._fsMkdir;
45
+ }, enumerable: true },
46
+ rmdir: { get() {
47
+ return globalThis._fsRmdir;
48
+ }, enumerable: true },
49
+ exists: { get() {
50
+ return globalThis._fsExists;
51
+ }, enumerable: true },
52
+ stat: { get() {
53
+ return globalThis._fsStat;
54
+ }, enumerable: true },
55
+ unlink: { get() {
56
+ return globalThis._fsUnlink;
57
+ }, enumerable: true },
58
+ rename: { get() {
59
+ return globalThis._fsRename;
60
+ }, enumerable: true },
61
+ chmod: { get() {
62
+ return globalThis._fsChmod;
63
+ }, enumerable: true },
64
+ chown: { get() {
65
+ return globalThis._fsChown;
66
+ }, enumerable: true },
67
+ link: { get() {
68
+ return globalThis._fsLink;
69
+ }, enumerable: true },
70
+ symlink: { get() {
71
+ return globalThis._fsSymlink;
72
+ }, enumerable: true },
73
+ readlink: { get() {
74
+ return globalThis._fsReadlink;
75
+ }, enumerable: true },
76
+ lstat: { get() {
77
+ return globalThis._fsLstat;
78
+ }, enumerable: true },
79
+ truncate: { get() {
80
+ return globalThis._fsTruncate;
81
+ }, enumerable: true },
82
+ utimes: { get() {
83
+ return globalThis._fsUtimes;
84
+ }, enumerable: true }
85
+ });
47
86
  __runtimeExposeCustomGlobal("_fs", __fsFacade);
48
87
  })();
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Command registry.
3
+ *
4
+ * Maps command names to runtime drivers. When a process calls
5
+ * spawn("grep", ...), the registry resolves "grep" to the WasmVM driver.
6
+ * Also populates /bin in the VFS so shell PATH lookup succeeds.
7
+ */
8
+ import type { RuntimeDriver } from "./types.js";
9
+ import type { VirtualFileSystem } from "./vfs.js";
10
+ export declare class CommandRegistry {
11
+ /** command name → RuntimeDriver */
12
+ private commands;
13
+ /** Warning log for command overrides. */
14
+ private warnings;
15
+ /**
16
+ * Register all commands from a driver.
17
+ * Last-mounted driver wins on conflicts (allows override with warning).
18
+ */
19
+ register(driver: RuntimeDriver): void;
20
+ /** Get recorded warnings (for testing). */
21
+ getWarnings(): readonly string[];
22
+ /**
23
+ * Register a single command to a driver.
24
+ * Used for on-demand dynamic registration (e.g. after tryResolve).
25
+ */
26
+ registerCommand(command: string, driver: RuntimeDriver): void;
27
+ /**
28
+ * Resolve a command name to a driver. Returns null if unknown.
29
+ * Supports path-based lookup: '/bin/ls' resolves to the driver for 'ls'.
30
+ */
31
+ resolve(command: string): RuntimeDriver | null;
32
+ /** List all registered commands. Returns command → driver name. */
33
+ list(): Map<string, string>;
34
+ /**
35
+ * Create a single /bin stub entry for a command.
36
+ * Used for on-demand registration after tryResolve discovers a new command.
37
+ */
38
+ populateBinEntry(vfs: VirtualFileSystem, command: string): Promise<void>;
39
+ /**
40
+ * Populate /bin in the VFS with stub entries for all registered commands.
41
+ * This enables brush-shell's PATH lookup to find commands.
42
+ */
43
+ populateBin(vfs: VirtualFileSystem): Promise<void>;
44
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Command registry.
3
+ *
4
+ * Maps command names to runtime drivers. When a process calls
5
+ * spawn("grep", ...), the registry resolves "grep" to the WasmVM driver.
6
+ * Also populates /bin in the VFS so shell PATH lookup succeeds.
7
+ */
8
+ export class CommandRegistry {
9
+ /** command name → RuntimeDriver */
10
+ commands = new Map();
11
+ /** Warning log for command overrides. */
12
+ warnings = [];
13
+ /**
14
+ * Register all commands from a driver.
15
+ * Last-mounted driver wins on conflicts (allows override with warning).
16
+ */
17
+ register(driver) {
18
+ for (const cmd of driver.commands) {
19
+ const existing = this.commands.get(cmd);
20
+ if (existing) {
21
+ const msg = `command "${cmd}" overridden: ${existing.name} → ${driver.name}`;
22
+ this.warnings.push(msg);
23
+ console.warn(`[CommandRegistry] ${msg}`);
24
+ }
25
+ this.commands.set(cmd, driver);
26
+ }
27
+ }
28
+ /** Get recorded warnings (for testing). */
29
+ getWarnings() {
30
+ return this.warnings;
31
+ }
32
+ /**
33
+ * Register a single command to a driver.
34
+ * Used for on-demand dynamic registration (e.g. after tryResolve).
35
+ */
36
+ registerCommand(command, driver) {
37
+ const existing = this.commands.get(command);
38
+ if (existing) {
39
+ const msg = `command "${command}" overridden: ${existing.name} → ${driver.name}`;
40
+ this.warnings.push(msg);
41
+ console.warn(`[CommandRegistry] ${msg}`);
42
+ }
43
+ this.commands.set(command, driver);
44
+ }
45
+ /**
46
+ * Resolve a command name to a driver. Returns null if unknown.
47
+ * Supports path-based lookup: '/bin/ls' resolves to the driver for 'ls'.
48
+ */
49
+ resolve(command) {
50
+ // Direct name lookup
51
+ const direct = this.commands.get(command);
52
+ if (direct)
53
+ return direct;
54
+ // Path-based: extract basename and retry
55
+ if (command.includes("/")) {
56
+ const basename = command.split("/").pop();
57
+ if (basename)
58
+ return this.commands.get(basename) ?? null;
59
+ }
60
+ return null;
61
+ }
62
+ /** List all registered commands. Returns command → driver name. */
63
+ list() {
64
+ const result = new Map();
65
+ for (const [cmd, driver] of this.commands) {
66
+ result.set(cmd, driver.name);
67
+ }
68
+ return result;
69
+ }
70
+ /**
71
+ * Create a single /bin stub entry for a command.
72
+ * Used for on-demand registration after tryResolve discovers a new command.
73
+ */
74
+ async populateBinEntry(vfs, command) {
75
+ if (!(await vfs.exists("/bin"))) {
76
+ await vfs.mkdir("/bin", { recursive: true });
77
+ }
78
+ const path = `/bin/${command}`;
79
+ if (!(await vfs.exists(path))) {
80
+ const stub = new TextEncoder().encode("#!/bin/sh\n# kernel command stub\n");
81
+ await vfs.writeFile(path, stub);
82
+ try {
83
+ await vfs.chmod(path, 0o755);
84
+ }
85
+ catch {
86
+ // chmod may not be supported by all VFS backends
87
+ }
88
+ }
89
+ }
90
+ /**
91
+ * Populate /bin in the VFS with stub entries for all registered commands.
92
+ * This enables brush-shell's PATH lookup to find commands.
93
+ */
94
+ async populateBin(vfs) {
95
+ // Ensure /bin exists
96
+ if (!(await vfs.exists("/bin"))) {
97
+ await vfs.mkdir("/bin", { recursive: true });
98
+ }
99
+ // Create a stub file for each command
100
+ const stub = new TextEncoder().encode("#!/bin/sh\n# kernel command stub\n");
101
+ for (const cmd of this.commands.keys()) {
102
+ const path = `/bin/${cmd}`;
103
+ if (!(await vfs.exists(path))) {
104
+ await vfs.writeFile(path, stub);
105
+ try {
106
+ await vfs.chmod(path, 0o755);
107
+ }
108
+ catch {
109
+ // chmod may not be supported by all VFS backends
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Device layer.
3
+ *
4
+ * Intercepts device node paths (/dev/*) before they reach the VFS backend.
5
+ * Wraps a VirtualFileSystem and handles device-specific read/write semantics.
6
+ */
7
+ import type { VirtualFileSystem } from "./vfs.js";
8
+ /**
9
+ * Wrap a VFS with device node interception.
10
+ * Device paths are handled directly; all other paths pass through.
11
+ */
12
+ export declare function createDeviceLayer(vfs: VirtualFileSystem): VirtualFileSystem;