almostnode 0.1.0

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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +731 -0
  3. package/dist/__sw__.js +394 -0
  4. package/dist/ai-chatbot-demo-entry.d.ts +6 -0
  5. package/dist/ai-chatbot-demo-entry.d.ts.map +1 -0
  6. package/dist/ai-chatbot-demo.d.ts +42 -0
  7. package/dist/ai-chatbot-demo.d.ts.map +1 -0
  8. package/dist/assets/runtime-worker-D9x_Ddwz.js +60543 -0
  9. package/dist/assets/runtime-worker-D9x_Ddwz.js.map +1 -0
  10. package/dist/convex-app-demo-entry.d.ts +6 -0
  11. package/dist/convex-app-demo-entry.d.ts.map +1 -0
  12. package/dist/convex-app-demo.d.ts +68 -0
  13. package/dist/convex-app-demo.d.ts.map +1 -0
  14. package/dist/cors-proxy.d.ts +46 -0
  15. package/dist/cors-proxy.d.ts.map +1 -0
  16. package/dist/create-runtime.d.ts +42 -0
  17. package/dist/create-runtime.d.ts.map +1 -0
  18. package/dist/demo.d.ts +6 -0
  19. package/dist/demo.d.ts.map +1 -0
  20. package/dist/dev-server.d.ts +97 -0
  21. package/dist/dev-server.d.ts.map +1 -0
  22. package/dist/frameworks/next-dev-server.d.ts +202 -0
  23. package/dist/frameworks/next-dev-server.d.ts.map +1 -0
  24. package/dist/frameworks/vite-dev-server.d.ts +85 -0
  25. package/dist/frameworks/vite-dev-server.d.ts.map +1 -0
  26. package/dist/index.cjs +14965 -0
  27. package/dist/index.cjs.map +1 -0
  28. package/dist/index.d.ts +71 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.mjs +14867 -0
  31. package/dist/index.mjs.map +1 -0
  32. package/dist/next-demo.d.ts +49 -0
  33. package/dist/next-demo.d.ts.map +1 -0
  34. package/dist/npm/index.d.ts +71 -0
  35. package/dist/npm/index.d.ts.map +1 -0
  36. package/dist/npm/registry.d.ts +66 -0
  37. package/dist/npm/registry.d.ts.map +1 -0
  38. package/dist/npm/resolver.d.ts +52 -0
  39. package/dist/npm/resolver.d.ts.map +1 -0
  40. package/dist/npm/tarball.d.ts +29 -0
  41. package/dist/npm/tarball.d.ts.map +1 -0
  42. package/dist/runtime-interface.d.ts +90 -0
  43. package/dist/runtime-interface.d.ts.map +1 -0
  44. package/dist/runtime.d.ts +103 -0
  45. package/dist/runtime.d.ts.map +1 -0
  46. package/dist/sandbox-helpers.d.ts +43 -0
  47. package/dist/sandbox-helpers.d.ts.map +1 -0
  48. package/dist/sandbox-runtime.d.ts +65 -0
  49. package/dist/sandbox-runtime.d.ts.map +1 -0
  50. package/dist/server-bridge.d.ts +89 -0
  51. package/dist/server-bridge.d.ts.map +1 -0
  52. package/dist/shims/assert.d.ts +51 -0
  53. package/dist/shims/assert.d.ts.map +1 -0
  54. package/dist/shims/async_hooks.d.ts +37 -0
  55. package/dist/shims/async_hooks.d.ts.map +1 -0
  56. package/dist/shims/buffer.d.ts +20 -0
  57. package/dist/shims/buffer.d.ts.map +1 -0
  58. package/dist/shims/child_process-browser.d.ts +92 -0
  59. package/dist/shims/child_process-browser.d.ts.map +1 -0
  60. package/dist/shims/child_process.d.ts +93 -0
  61. package/dist/shims/child_process.d.ts.map +1 -0
  62. package/dist/shims/chokidar.d.ts +55 -0
  63. package/dist/shims/chokidar.d.ts.map +1 -0
  64. package/dist/shims/cluster.d.ts +52 -0
  65. package/dist/shims/cluster.d.ts.map +1 -0
  66. package/dist/shims/crypto.d.ts +122 -0
  67. package/dist/shims/crypto.d.ts.map +1 -0
  68. package/dist/shims/dgram.d.ts +34 -0
  69. package/dist/shims/dgram.d.ts.map +1 -0
  70. package/dist/shims/diagnostics_channel.d.ts +80 -0
  71. package/dist/shims/diagnostics_channel.d.ts.map +1 -0
  72. package/dist/shims/dns.d.ts +87 -0
  73. package/dist/shims/dns.d.ts.map +1 -0
  74. package/dist/shims/domain.d.ts +25 -0
  75. package/dist/shims/domain.d.ts.map +1 -0
  76. package/dist/shims/esbuild.d.ts +105 -0
  77. package/dist/shims/esbuild.d.ts.map +1 -0
  78. package/dist/shims/events.d.ts +37 -0
  79. package/dist/shims/events.d.ts.map +1 -0
  80. package/dist/shims/fs.d.ts +115 -0
  81. package/dist/shims/fs.d.ts.map +1 -0
  82. package/dist/shims/fsevents.d.ts +67 -0
  83. package/dist/shims/fsevents.d.ts.map +1 -0
  84. package/dist/shims/http.d.ts +217 -0
  85. package/dist/shims/http.d.ts.map +1 -0
  86. package/dist/shims/http2.d.ts +81 -0
  87. package/dist/shims/http2.d.ts.map +1 -0
  88. package/dist/shims/https.d.ts +36 -0
  89. package/dist/shims/https.d.ts.map +1 -0
  90. package/dist/shims/inspector.d.ts +25 -0
  91. package/dist/shims/inspector.d.ts.map +1 -0
  92. package/dist/shims/module.d.ts +22 -0
  93. package/dist/shims/module.d.ts.map +1 -0
  94. package/dist/shims/net.d.ts +100 -0
  95. package/dist/shims/net.d.ts.map +1 -0
  96. package/dist/shims/os.d.ts +159 -0
  97. package/dist/shims/os.d.ts.map +1 -0
  98. package/dist/shims/path.d.ts +72 -0
  99. package/dist/shims/path.d.ts.map +1 -0
  100. package/dist/shims/perf_hooks.d.ts +50 -0
  101. package/dist/shims/perf_hooks.d.ts.map +1 -0
  102. package/dist/shims/process.d.ts +93 -0
  103. package/dist/shims/process.d.ts.map +1 -0
  104. package/dist/shims/querystring.d.ts +23 -0
  105. package/dist/shims/querystring.d.ts.map +1 -0
  106. package/dist/shims/readdirp.d.ts +52 -0
  107. package/dist/shims/readdirp.d.ts.map +1 -0
  108. package/dist/shims/readline.d.ts +62 -0
  109. package/dist/shims/readline.d.ts.map +1 -0
  110. package/dist/shims/rollup.d.ts +34 -0
  111. package/dist/shims/rollup.d.ts.map +1 -0
  112. package/dist/shims/sentry.d.ts +163 -0
  113. package/dist/shims/sentry.d.ts.map +1 -0
  114. package/dist/shims/stream.d.ts +181 -0
  115. package/dist/shims/stream.d.ts.map +1 -0
  116. package/dist/shims/tls.d.ts +53 -0
  117. package/dist/shims/tls.d.ts.map +1 -0
  118. package/dist/shims/tty.d.ts +30 -0
  119. package/dist/shims/tty.d.ts.map +1 -0
  120. package/dist/shims/url.d.ts +64 -0
  121. package/dist/shims/url.d.ts.map +1 -0
  122. package/dist/shims/util.d.ts +106 -0
  123. package/dist/shims/util.d.ts.map +1 -0
  124. package/dist/shims/v8.d.ts +73 -0
  125. package/dist/shims/v8.d.ts.map +1 -0
  126. package/dist/shims/vfs-adapter.d.ts +126 -0
  127. package/dist/shims/vfs-adapter.d.ts.map +1 -0
  128. package/dist/shims/vm.d.ts +45 -0
  129. package/dist/shims/vm.d.ts.map +1 -0
  130. package/dist/shims/worker_threads.d.ts +66 -0
  131. package/dist/shims/worker_threads.d.ts.map +1 -0
  132. package/dist/shims/ws.d.ts +66 -0
  133. package/dist/shims/ws.d.ts.map +1 -0
  134. package/dist/shims/zlib.d.ts +161 -0
  135. package/dist/shims/zlib.d.ts.map +1 -0
  136. package/dist/transform.d.ts +24 -0
  137. package/dist/transform.d.ts.map +1 -0
  138. package/dist/virtual-fs.d.ts +226 -0
  139. package/dist/virtual-fs.d.ts.map +1 -0
  140. package/dist/vite-demo.d.ts +35 -0
  141. package/dist/vite-demo.d.ts.map +1 -0
  142. package/dist/vite-sw.js +132 -0
  143. package/dist/worker/runtime-worker.d.ts +8 -0
  144. package/dist/worker/runtime-worker.d.ts.map +1 -0
  145. package/dist/worker-runtime.d.ts +50 -0
  146. package/dist/worker-runtime.d.ts.map +1 -0
  147. package/package.json +85 -0
  148. package/src/ai-chatbot-demo-entry.ts +244 -0
  149. package/src/ai-chatbot-demo.ts +509 -0
  150. package/src/convex-app-demo-entry.ts +1107 -0
  151. package/src/convex-app-demo.ts +1316 -0
  152. package/src/cors-proxy.ts +81 -0
  153. package/src/create-runtime.ts +147 -0
  154. package/src/demo.ts +304 -0
  155. package/src/dev-server.ts +274 -0
  156. package/src/frameworks/next-dev-server.ts +2224 -0
  157. package/src/frameworks/vite-dev-server.ts +702 -0
  158. package/src/index.ts +101 -0
  159. package/src/next-demo.ts +1784 -0
  160. package/src/npm/index.ts +347 -0
  161. package/src/npm/registry.ts +152 -0
  162. package/src/npm/resolver.ts +385 -0
  163. package/src/npm/tarball.ts +209 -0
  164. package/src/runtime-interface.ts +103 -0
  165. package/src/runtime.ts +1046 -0
  166. package/src/sandbox-helpers.ts +173 -0
  167. package/src/sandbox-runtime.ts +252 -0
  168. package/src/server-bridge.ts +426 -0
  169. package/src/shims/assert.ts +664 -0
  170. package/src/shims/async_hooks.ts +86 -0
  171. package/src/shims/buffer.ts +75 -0
  172. package/src/shims/child_process-browser.ts +217 -0
  173. package/src/shims/child_process.ts +463 -0
  174. package/src/shims/chokidar.ts +313 -0
  175. package/src/shims/cluster.ts +67 -0
  176. package/src/shims/crypto.ts +830 -0
  177. package/src/shims/dgram.ts +47 -0
  178. package/src/shims/diagnostics_channel.ts +196 -0
  179. package/src/shims/dns.ts +172 -0
  180. package/src/shims/domain.ts +58 -0
  181. package/src/shims/esbuild.ts +805 -0
  182. package/src/shims/events.ts +195 -0
  183. package/src/shims/fs.ts +803 -0
  184. package/src/shims/fsevents.ts +63 -0
  185. package/src/shims/http.ts +904 -0
  186. package/src/shims/http2.ts +96 -0
  187. package/src/shims/https.ts +86 -0
  188. package/src/shims/inspector.ts +30 -0
  189. package/src/shims/module.ts +82 -0
  190. package/src/shims/net.ts +359 -0
  191. package/src/shims/os.ts +195 -0
  192. package/src/shims/path.ts +199 -0
  193. package/src/shims/perf_hooks.ts +92 -0
  194. package/src/shims/process.ts +346 -0
  195. package/src/shims/querystring.ts +97 -0
  196. package/src/shims/readdirp.ts +228 -0
  197. package/src/shims/readline.ts +110 -0
  198. package/src/shims/rollup.ts +80 -0
  199. package/src/shims/sentry.ts +133 -0
  200. package/src/shims/stream.ts +1126 -0
  201. package/src/shims/tls.ts +95 -0
  202. package/src/shims/tty.ts +64 -0
  203. package/src/shims/url.ts +171 -0
  204. package/src/shims/util.ts +312 -0
  205. package/src/shims/v8.ts +113 -0
  206. package/src/shims/vfs-adapter.ts +402 -0
  207. package/src/shims/vm.ts +83 -0
  208. package/src/shims/worker_threads.ts +111 -0
  209. package/src/shims/ws.ts +382 -0
  210. package/src/shims/zlib.ts +289 -0
  211. package/src/transform.ts +313 -0
  212. package/src/types/external.d.ts +67 -0
  213. package/src/virtual-fs.ts +903 -0
  214. package/src/vite-demo.ts +577 -0
  215. package/src/worker/runtime-worker.ts +128 -0
  216. package/src/worker-runtime.ts +145 -0
package/src/runtime.ts ADDED
@@ -0,0 +1,1046 @@
1
+ /**
2
+ * Runtime - Execute user code with shimmed Node.js globals
3
+ *
4
+ * ESM to CJS transformation is now handled during npm install by transform.ts
5
+ * using esbuild-wasm. This runtime just executes the pre-transformed CJS code.
6
+ */
7
+
8
+ import { VirtualFS } from './virtual-fs';
9
+ import type { IRuntime, IExecuteResult, IRuntimeOptions } from './runtime-interface';
10
+ import { createFsShim, FsShim } from './shims/fs';
11
+ import * as pathShim from './shims/path';
12
+ import { createProcess, Process } from './shims/process';
13
+ import * as httpShim from './shims/http';
14
+ import * as httpsShim from './shims/https';
15
+ import * as netShim from './shims/net';
16
+ import eventsShim from './shims/events';
17
+ import streamShim from './shims/stream';
18
+ import * as urlShim from './shims/url';
19
+ import * as querystringShim from './shims/querystring';
20
+ import * as utilShim from './shims/util';
21
+ import * as ttyShim from './shims/tty';
22
+ import * as osShim from './shims/os';
23
+ import * as cryptoShim from './shims/crypto';
24
+ import * as zlibShim from './shims/zlib';
25
+ import * as dnsShim from './shims/dns';
26
+ import bufferShim from './shims/buffer';
27
+ import * as childProcessShim from './shims/child_process';
28
+ import { initChildProcess } from './shims/child_process';
29
+ import { getServerBridge } from './server-bridge';
30
+ import * as chokidarShim from './shims/chokidar';
31
+ import * as wsShim from './shims/ws';
32
+ import * as fseventsShim from './shims/fsevents';
33
+ import * as readdirpShim from './shims/readdirp';
34
+ import * as moduleShim from './shims/module';
35
+ import * as perfHooksShim from './shims/perf_hooks';
36
+ import * as workerThreadsShim from './shims/worker_threads';
37
+ import * as esbuildShim from './shims/esbuild';
38
+ import * as rollupShim from './shims/rollup';
39
+ import * as v8Shim from './shims/v8';
40
+ import * as readlineShim from './shims/readline';
41
+ import * as tlsShim from './shims/tls';
42
+ import * as http2Shim from './shims/http2';
43
+ import * as clusterShim from './shims/cluster';
44
+ import * as dgramShim from './shims/dgram';
45
+ import * as vmShim from './shims/vm';
46
+ import * as inspectorShim from './shims/inspector';
47
+ import * as asyncHooksShim from './shims/async_hooks';
48
+ import * as domainShim from './shims/domain';
49
+ import * as diagnosticsChannelShim from './shims/diagnostics_channel';
50
+ import * as sentryShim from './shims/sentry';
51
+ import assertShim from './shims/assert';
52
+ import { resolve as resolveExports } from 'resolve.exports';
53
+
54
+ /**
55
+ * Transform dynamic imports in code: import('x') -> __dynamicImport('x')
56
+ * This allows dynamic imports to work in our eval-based runtime
57
+ */
58
+ function transformDynamicImports(code: string): string {
59
+ // Use a regex that matches import( but not things like:
60
+ // - "import(" in strings
61
+ // - // import( in comments
62
+ // This is a simple approach that works for most bundled code
63
+ // For a more robust solution, we'd need a proper parser
64
+
65
+ // Match: import( with optional whitespace, not preceded by word char or $
66
+ // This handles: import('x'), import ("x"), await import('x'), etc.
67
+ return code.replace(/(?<![.$\w])import\s*\(/g, '__dynamicImport(');
68
+ }
69
+
70
+ /**
71
+ * Simple synchronous ESM to CJS transform
72
+ * Handles basic import/export syntax without needing esbuild
73
+ */
74
+ function transformEsmToCjs(code: string, filename: string): string {
75
+ // Check if code has ESM syntax
76
+ const hasImport = /\bimport\s+[\w{*'"]/m.test(code);
77
+ const hasExport = /\bexport\s+(?:default|const|let|var|function|class|{|\*)/m.test(code);
78
+ const hasImportMeta = /\bimport\.meta\b/.test(code);
79
+
80
+ if (!hasImport && !hasExport && !hasImportMeta) {
81
+ return code; // Already CJS or no module syntax
82
+ }
83
+
84
+ let transformed = code;
85
+
86
+ // Transform import.meta.url to a file:// URL
87
+ transformed = transformed.replace(/\bimport\.meta\.url\b/g, `"file://${filename}"`);
88
+ transformed = transformed.replace(/\bimport\.meta\.dirname\b/g, `"${pathShim.dirname(filename)}"`);
89
+ transformed = transformed.replace(/\bimport\.meta\.filename\b/g, `"${filename}"`);
90
+ transformed = transformed.replace(/\bimport\.meta\b/g, `({ url: "file://${filename}", dirname: "${pathShim.dirname(filename)}", filename: "${filename}" })`);
91
+
92
+ // Transform named imports: import { a, b } from 'x' -> const { a, b } = require('x')
93
+ transformed = transformed.replace(
94
+ /\bimport\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g,
95
+ (_, imports, module) => {
96
+ const cleanImports = imports.replace(/\s+as\s+/g, ': ');
97
+ return `const {${cleanImports}} = require("${module}");`;
98
+ }
99
+ );
100
+
101
+ // Transform default imports: import x from 'y' -> const x = require('y').default || require('y')
102
+ transformed = transformed.replace(
103
+ /\bimport\s+(\w+)\s+from\s+['"]([^'"]+)['"]\s*;?/g,
104
+ (_, name, module) => {
105
+ return `const ${name} = (function() { const m = require("${module}"); return m && m.__esModule ? m.default : m; })();`;
106
+ }
107
+ );
108
+
109
+ // Transform namespace imports: import * as x from 'y' -> const x = require('y')
110
+ transformed = transformed.replace(
111
+ /\bimport\s+\*\s+as\s+(\w+)\s+from\s+['"]([^'"]+)['"]\s*;?/g,
112
+ 'const $1 = require("$2");'
113
+ );
114
+
115
+ // Transform side-effect imports: import 'x' -> require('x')
116
+ transformed = transformed.replace(
117
+ /\bimport\s+['"]([^'"]+)['"]\s*;?/g,
118
+ 'require("$1");'
119
+ );
120
+
121
+ // Transform export default: export default x -> module.exports.default = x; module.exports = x
122
+ transformed = transformed.replace(
123
+ /\bexport\s+default\s+/g,
124
+ 'module.exports = module.exports.default = '
125
+ );
126
+
127
+ // Transform named exports: export { a, b } -> module.exports.a = a; module.exports.b = b
128
+ transformed = transformed.replace(
129
+ /\bexport\s+\{([^}]+)\}\s*;?/g,
130
+ (_, exports) => {
131
+ const items = exports.split(',').map((item: string) => {
132
+ const [local, exported] = item.trim().split(/\s+as\s+/);
133
+ const exportName = exported || local;
134
+ return `module.exports.${exportName.trim()} = ${local.trim()};`;
135
+ });
136
+ return items.join('\n');
137
+ }
138
+ );
139
+
140
+ // Transform export const/let/var: export const x = 1 -> const x = 1; module.exports.x = x
141
+ transformed = transformed.replace(
142
+ /\bexport\s+(const|let|var)\s+(\w+)\s*=/g,
143
+ '$1 $2 = module.exports.$2 ='
144
+ );
145
+
146
+ // Transform export function: export function x() {} -> function x() {} module.exports.x = x
147
+ transformed = transformed.replace(
148
+ /\bexport\s+function\s+(\w+)/g,
149
+ 'function $1'
150
+ );
151
+
152
+ // Transform export class: export class X {} -> class X {} module.exports.X = X
153
+ transformed = transformed.replace(
154
+ /\bexport\s+class\s+(\w+)/g,
155
+ 'class $1'
156
+ );
157
+
158
+ // Mark as ES module for interop
159
+ if (hasExport) {
160
+ transformed = 'Object.defineProperty(exports, "__esModule", { value: true });\n' + transformed;
161
+ }
162
+
163
+ return transformed;
164
+ }
165
+
166
+ /**
167
+ * Create a dynamic import function for a module context
168
+ * Returns a function that wraps require() in a Promise
169
+ */
170
+ function createDynamicImport(moduleRequire: RequireFunction): (specifier: string) => Promise<unknown> {
171
+ return async (specifier: string): Promise<unknown> => {
172
+ try {
173
+ const mod = moduleRequire(specifier);
174
+
175
+ // If the module has a default export or is already ESM-like, return as-is
176
+ if (mod && typeof mod === 'object' && ('default' in (mod as object) || '__esModule' in (mod as object))) {
177
+ return mod;
178
+ }
179
+
180
+ // For CommonJS modules, wrap in an object with default export
181
+ // This matches how dynamic import() handles CJS modules
182
+ return {
183
+ default: mod,
184
+ ...(mod && typeof mod === 'object' ? mod as object : {}),
185
+ };
186
+ } catch (error) {
187
+ // Re-throw as a rejected promise (which is what dynamic import does)
188
+ throw error;
189
+ }
190
+ };
191
+ }
192
+
193
+ export interface Module {
194
+ id: string;
195
+ filename: string;
196
+ exports: unknown;
197
+ loaded: boolean;
198
+ children: Module[];
199
+ paths: string[];
200
+ }
201
+
202
+ export interface RuntimeOptions {
203
+ cwd?: string;
204
+ env?: Record<string, string>;
205
+ onConsole?: (method: string, args: unknown[]) => void;
206
+ }
207
+
208
+ export interface RequireFunction {
209
+ (id: string): unknown;
210
+ resolve: (id: string) => string;
211
+ cache: Record<string, Module>;
212
+ }
213
+
214
+ /**
215
+ * Create a basic string_decoder module
216
+ */
217
+ function createStringDecoderModule() {
218
+ class StringDecoder {
219
+ encoding: string;
220
+ constructor(encoding?: string) {
221
+ this.encoding = encoding || 'utf8';
222
+ }
223
+ write(buffer: Uint8Array): string {
224
+ return new TextDecoder(this.encoding).decode(buffer);
225
+ }
226
+ end(buffer?: Uint8Array): string {
227
+ if (buffer) return this.write(buffer);
228
+ return '';
229
+ }
230
+ }
231
+ return { StringDecoder };
232
+ }
233
+
234
+ /**
235
+ * Create a basic timers module
236
+ */
237
+ function createTimersModule() {
238
+ return {
239
+ setTimeout: globalThis.setTimeout.bind(globalThis),
240
+ setInterval: globalThis.setInterval.bind(globalThis),
241
+ setImmediate: (fn: () => void) => setTimeout(fn, 0),
242
+ clearTimeout: globalThis.clearTimeout.bind(globalThis),
243
+ clearInterval: globalThis.clearInterval.bind(globalThis),
244
+ clearImmediate: globalThis.clearTimeout.bind(globalThis),
245
+ };
246
+ }
247
+
248
+ /**
249
+ * Minimal prettier shim - just returns input unchanged
250
+ * This is needed because prettier uses createRequire which conflicts with our runtime
251
+ */
252
+ const prettierShim = {
253
+ format: (source: string, _options?: unknown) => Promise.resolve(source),
254
+ formatWithCursor: (source: string, _options?: unknown) => Promise.resolve({ formatted: source, cursorOffset: 0 }),
255
+ check: (_source: string, _options?: unknown) => Promise.resolve(true),
256
+ resolveConfig: () => Promise.resolve(null),
257
+ resolveConfigFile: () => Promise.resolve(null),
258
+ clearConfigCache: () => {},
259
+ getFileInfo: () => Promise.resolve({ ignored: false, inferredParser: null }),
260
+ getSupportInfo: () => Promise.resolve({ languages: [], options: [] }),
261
+ version: '3.0.0',
262
+ doc: {
263
+ builders: {},
264
+ printer: {},
265
+ utils: {},
266
+ },
267
+ };
268
+
269
+ /**
270
+ * Create a mutable copy of a module for packages that need to patch it
271
+ * (e.g., Sentry needs to patch http.request/http.get)
272
+ */
273
+ function makeMutable(mod: Record<string, unknown>): Record<string, unknown> {
274
+ const mutable: Record<string, unknown> = {};
275
+ for (const key of Object.keys(mod)) {
276
+ mutable[key] = mod[key];
277
+ }
278
+ return mutable;
279
+ }
280
+
281
+ /**
282
+ * Built-in modules registry
283
+ */
284
+ const builtinModules: Record<string, unknown> = {
285
+ path: pathShim,
286
+ // Make http/https mutable so packages like Sentry can patch them
287
+ http: makeMutable(httpShim as unknown as Record<string, unknown>),
288
+ https: makeMutable(httpsShim as unknown as Record<string, unknown>),
289
+ net: netShim,
290
+ events: eventsShim,
291
+ stream: streamShim,
292
+ buffer: bufferShim,
293
+ url: urlShim,
294
+ querystring: querystringShim,
295
+ util: utilShim,
296
+ tty: ttyShim,
297
+ os: osShim,
298
+ crypto: cryptoShim,
299
+ zlib: zlibShim,
300
+ dns: dnsShim,
301
+ child_process: childProcessShim,
302
+ assert: assertShim,
303
+ string_decoder: createStringDecoderModule(),
304
+ timers: createTimersModule(),
305
+ _http_common: {},
306
+ _http_incoming: {},
307
+ _http_outgoing: {},
308
+ // New shims for Vite support
309
+ chokidar: chokidarShim,
310
+ ws: wsShim,
311
+ fsevents: fseventsShim,
312
+ readdirp: readdirpShim,
313
+ module: moduleShim,
314
+ perf_hooks: perfHooksShim,
315
+ worker_threads: workerThreadsShim,
316
+ esbuild: esbuildShim,
317
+ rollup: rollupShim,
318
+ v8: v8Shim,
319
+ readline: readlineShim,
320
+ tls: tlsShim,
321
+ http2: http2Shim,
322
+ cluster: clusterShim,
323
+ dgram: dgramShim,
324
+ vm: vmShim,
325
+ inspector: inspectorShim,
326
+ 'inspector/promises': inspectorShim,
327
+ async_hooks: asyncHooksShim,
328
+ domain: domainShim,
329
+ diagnostics_channel: diagnosticsChannelShim,
330
+ // prettier uses createRequire which doesn't work in our runtime, so we shim it
331
+ prettier: prettierShim,
332
+ // Some packages explicitly require 'console'
333
+ console: console,
334
+ // util/types is accessed as a subpath
335
+ 'util/types': utilShim.types,
336
+ // Sentry SDK (no-op since error tracking isn't useful in browser runtime)
337
+ '@sentry/node': sentryShim,
338
+ '@sentry/core': sentryShim,
339
+ };
340
+
341
+ /**
342
+ * Create a require function for a specific module context
343
+ */
344
+ function createRequire(
345
+ vfs: VirtualFS,
346
+ fsShim: FsShim,
347
+ process: Process,
348
+ currentDir: string,
349
+ moduleCache: Record<string, Module>,
350
+ options: RuntimeOptions
351
+ ): RequireFunction {
352
+ const resolveModule = (id: string, fromDir: string): string => {
353
+ // Handle node: protocol prefix (Node.js 16+)
354
+ if (id.startsWith('node:')) {
355
+ id = id.slice(5);
356
+ }
357
+
358
+ // Built-in modules
359
+ if (builtinModules[id] || id === 'fs' || id === 'process' || id === 'url' || id === 'querystring' || id === 'util') {
360
+ return id;
361
+ }
362
+
363
+ // Relative paths
364
+ if (id.startsWith('./') || id.startsWith('../') || id.startsWith('/')) {
365
+ const resolved = id.startsWith('/')
366
+ ? id
367
+ : pathShim.resolve(fromDir, id);
368
+
369
+ // Try exact path
370
+ if (vfs.existsSync(resolved)) {
371
+ const stats = vfs.statSync(resolved);
372
+ if (stats.isFile()) {
373
+ return resolved;
374
+ }
375
+ // Directory - look for index.js
376
+ const indexPath = pathShim.join(resolved, 'index.js');
377
+ if (vfs.existsSync(indexPath)) {
378
+ return indexPath;
379
+ }
380
+ }
381
+
382
+ // Try with extensions
383
+ const extensions = ['.js', '.json'];
384
+ for (const ext of extensions) {
385
+ const withExt = resolved + ext;
386
+ if (vfs.existsSync(withExt)) {
387
+ return withExt;
388
+ }
389
+ }
390
+
391
+ throw new Error(`Cannot find module '${id}' from '${fromDir}'`);
392
+ }
393
+
394
+ // Helper to try resolving a path with extensions
395
+ const tryResolveFile = (basePath: string): string | null => {
396
+ // Try exact path first
397
+ if (vfs.existsSync(basePath)) {
398
+ const stats = vfs.statSync(basePath);
399
+ if (stats.isFile()) {
400
+ return basePath;
401
+ }
402
+ // Directory - look for index.js
403
+ const indexPath = pathShim.join(basePath, 'index.js');
404
+ if (vfs.existsSync(indexPath)) {
405
+ return indexPath;
406
+ }
407
+ }
408
+
409
+ // Try with extensions
410
+ const extensions = ['.js', '.json', '.node'];
411
+ for (const ext of extensions) {
412
+ const withExt = basePath + ext;
413
+ if (vfs.existsSync(withExt)) {
414
+ return withExt;
415
+ }
416
+ }
417
+
418
+ return null;
419
+ };
420
+
421
+ // Helper to resolve from a node_modules directory
422
+ const tryResolveFromNodeModules = (nodeModulesDir: string, moduleId: string): string | null => {
423
+ const fullPath = pathShim.join(nodeModulesDir, moduleId);
424
+
425
+ // Check if path exists (as file or directory)
426
+ const resolved = tryResolveFile(fullPath);
427
+ if (resolved) return resolved;
428
+
429
+ // Check if this is a package (has package.json)
430
+ // For sub-paths like "pkg/sub", we need to find the package root first
431
+ const parts = moduleId.split('/');
432
+ const pkgName = parts[0].startsWith('@') && parts.length > 1
433
+ ? `${parts[0]}/${parts[1]}` // Scoped package
434
+ : parts[0];
435
+
436
+ const pkgRoot = pathShim.join(nodeModulesDir, pkgName);
437
+ const pkgPath = pathShim.join(pkgRoot, 'package.json');
438
+
439
+ if (vfs.existsSync(pkgPath)) {
440
+ const pkgContent = vfs.readFileSync(pkgPath, 'utf8');
441
+ const pkg = JSON.parse(pkgContent);
442
+
443
+ // Use resolve.exports to handle the exports field
444
+ if (pkg.exports) {
445
+ try {
446
+ // resolveExports expects the full module specifier (e.g., 'convex/server')
447
+ // and returns the resolved path(s) relative to package root
448
+ const resolved = resolveExports(pkg, moduleId, { require: true });
449
+ if (resolved && resolved.length > 0) {
450
+ const exportPath = resolved[0];
451
+ const fullExportPath = pathShim.join(pkgRoot, exportPath);
452
+ const resolvedFile = tryResolveFile(fullExportPath);
453
+ if (resolvedFile) return resolvedFile;
454
+ }
455
+ } catch {
456
+ // resolveExports throws if no match found, fall through to main
457
+ }
458
+ }
459
+
460
+ // If this is the package root (no sub-path), use main entry
461
+ if (pkgName === moduleId) {
462
+ const main = pkg.main || 'index.js';
463
+ const mainPath = pathShim.join(pkgRoot, main);
464
+ const resolvedMain = tryResolveFile(mainPath);
465
+ if (resolvedMain) return resolvedMain;
466
+ }
467
+ }
468
+
469
+ return null;
470
+ };
471
+
472
+ // Node modules resolution
473
+ let searchDir = fromDir;
474
+ while (searchDir !== '/') {
475
+ const nodeModulesDir = pathShim.join(searchDir, 'node_modules');
476
+ const resolved = tryResolveFromNodeModules(nodeModulesDir, id);
477
+ if (resolved) return resolved;
478
+
479
+ searchDir = pathShim.dirname(searchDir);
480
+ }
481
+
482
+ // Try root node_modules as last resort
483
+ const rootResolved = tryResolveFromNodeModules('/node_modules', id);
484
+ if (rootResolved) return rootResolved;
485
+
486
+ throw new Error(`Cannot find module '${id}'`);
487
+ };
488
+
489
+ const loadModule = (resolvedPath: string): Module => {
490
+ // Return cached module
491
+ if (moduleCache[resolvedPath]) {
492
+ return moduleCache[resolvedPath];
493
+ }
494
+
495
+ // Create module object
496
+ const module: Module = {
497
+ id: resolvedPath,
498
+ filename: resolvedPath,
499
+ exports: {},
500
+ loaded: false,
501
+ children: [],
502
+ paths: [],
503
+ };
504
+
505
+ // Cache before loading to handle circular dependencies
506
+ moduleCache[resolvedPath] = module;
507
+
508
+ // Handle JSON files
509
+ if (resolvedPath.endsWith('.json')) {
510
+ const content = vfs.readFileSync(resolvedPath, 'utf8');
511
+ module.exports = JSON.parse(content);
512
+ module.loaded = true;
513
+ return module;
514
+ }
515
+
516
+ // Read and execute JS file
517
+ let code = vfs.readFileSync(resolvedPath, 'utf8');
518
+ const dirname = pathShim.dirname(resolvedPath);
519
+
520
+ // Transform ESM to CJS if needed (for .mjs files or ESM that wasn't pre-transformed)
521
+ // This handles files that weren't transformed during npm install
522
+ // BUT skip .cjs files and already-bundled CJS code
523
+ const isCjsFile = resolvedPath.endsWith('.cjs');
524
+ const isAlreadyBundledCjs = code.startsWith('"use strict";\nvar __') ||
525
+ code.startsWith("'use strict';\nvar __");
526
+
527
+ const hasEsmImport = /\bimport\s+[\w{*'"]/m.test(code);
528
+ const hasEsmExport = /\bexport\s+(?:default|const|let|var|function|class|{|\*)/m.test(code);
529
+
530
+ if (!isCjsFile && !isAlreadyBundledCjs) {
531
+ if (resolvedPath.endsWith('.mjs') || resolvedPath.includes('/esm/') || hasEsmImport || hasEsmExport) {
532
+ code = transformEsmToCjs(code, resolvedPath);
533
+ }
534
+ }
535
+
536
+ // Transform dynamic imports: import('x') -> __dynamicImport('x')
537
+ // This allows dynamic imports to work in our eval-based runtime
538
+ code = transformDynamicImports(code);
539
+
540
+ // Create require for this module
541
+ const moduleRequire = createRequire(
542
+ vfs,
543
+ fsShim,
544
+ process,
545
+ dirname,
546
+ moduleCache,
547
+ options
548
+ );
549
+ moduleRequire.cache = moduleCache;
550
+
551
+ // Create console wrapper
552
+ const consoleWrapper = createConsoleWrapper(options.onConsole);
553
+
554
+ // Execute module code
555
+ // We use an outer/inner function pattern to avoid conflicts:
556
+ // - Outer function receives parameters and sets up vars
557
+ // - Inner function runs the code, allowing let/const to shadow without "already declared" errors
558
+ // - import.meta is provided for ESM code that uses it
559
+ try {
560
+ const importMetaUrl = 'file://' + resolvedPath;
561
+ const wrappedCode = `(function($exports, $require, $module, $filename, $dirname, $process, $console, $importMeta, $dynamicImport) {
562
+ var exports = $exports;
563
+ var require = $require;
564
+ var module = $module;
565
+ var __filename = $filename;
566
+ var __dirname = $dirname;
567
+ var process = $process;
568
+ var console = $console;
569
+ var import_meta = $importMeta;
570
+ var __dynamicImport = $dynamicImport;
571
+ // Set up global.process and globalThis.process for code that accesses them directly
572
+ var global = globalThis;
573
+ globalThis.process = $process;
574
+ global.process = $process;
575
+ return (function() {
576
+ ${code}
577
+ }).call(this);
578
+ })`;
579
+
580
+ let fn;
581
+ try {
582
+ fn = eval(wrappedCode);
583
+ } catch (evalError) {
584
+ console.error('[runtime] Eval failed for:', resolvedPath);
585
+ console.error('[runtime] First 500 chars of code:', code.substring(0, 500));
586
+ throw evalError;
587
+ }
588
+ // Create dynamic import function for this module context
589
+ const dynamicImport = createDynamicImport(moduleRequire);
590
+
591
+ fn(
592
+ module.exports,
593
+ moduleRequire,
594
+ module,
595
+ resolvedPath,
596
+ dirname,
597
+ process,
598
+ consoleWrapper,
599
+ { url: importMetaUrl, dirname, filename: resolvedPath },
600
+ dynamicImport
601
+ );
602
+
603
+ module.loaded = true;
604
+ } catch (error) {
605
+ // Remove from cache on error
606
+ delete moduleCache[resolvedPath];
607
+ throw error;
608
+ }
609
+
610
+ return module;
611
+ };
612
+
613
+ const require: RequireFunction = (id: string): unknown => {
614
+ // Handle node: protocol prefix (Node.js 16+)
615
+ if (id.startsWith('node:')) {
616
+ id = id.slice(5);
617
+ }
618
+
619
+ // Built-in modules
620
+ if (id === 'fs') {
621
+ return fsShim;
622
+ }
623
+ if (id === 'fs/promises') {
624
+ return fsShim.promises;
625
+ }
626
+ if (id === 'process') {
627
+ return process;
628
+ }
629
+ // Special handling for 'module' - provide a working createRequire
630
+ if (id === 'module') {
631
+ return {
632
+ ...moduleShim,
633
+ createRequire: (filenameOrUrl: string) => {
634
+ // Convert file:// URL to path
635
+ let fromPath = filenameOrUrl;
636
+ if (filenameOrUrl.startsWith('file://')) {
637
+ fromPath = filenameOrUrl.slice(7); // Remove 'file://'
638
+ // Handle Windows-style file:///C:/ URLs (though unlikely in our env)
639
+ if (fromPath.startsWith('/') && fromPath[2] === ':') {
640
+ fromPath = fromPath.slice(1);
641
+ }
642
+ }
643
+ // Get directory from the path
644
+ const fromDir = pathShim.dirname(fromPath);
645
+ // Return a require function that resolves from this directory
646
+ const newRequire = createRequire(
647
+ vfs,
648
+ fsShim,
649
+ process,
650
+ fromDir,
651
+ moduleCache,
652
+ options
653
+ );
654
+ newRequire.cache = moduleCache;
655
+ return newRequire;
656
+ },
657
+ };
658
+ }
659
+ if (builtinModules[id]) {
660
+ return builtinModules[id];
661
+ }
662
+
663
+ // Intercept rollup and esbuild - always use our shims
664
+ // These packages have native binaries that don't work in browser
665
+ if (id === 'rollup' || id.startsWith('rollup/') || id.startsWith('@rollup/')) {
666
+ console.log('[runtime] Intercepted rollup:', id);
667
+ return builtinModules['rollup'];
668
+ }
669
+ if (id === 'esbuild' || id.startsWith('esbuild/') || id.startsWith('@esbuild/')) {
670
+ console.log('[runtime] Intercepted esbuild:', id);
671
+ return builtinModules['esbuild'];
672
+ }
673
+ // Intercept prettier - uses createRequire which doesn't work in our runtime
674
+ if (id === 'prettier' || id.startsWith('prettier/')) {
675
+ return builtinModules['prettier'];
676
+ }
677
+ // Intercept Sentry - SDK tries to monkey-patch http which doesn't work
678
+ if (id.startsWith('@sentry/')) {
679
+ return builtinModules['@sentry/node'];
680
+ }
681
+
682
+ const resolved = resolveModule(id, currentDir);
683
+
684
+ // If resolved to a built-in name (shouldn't happen but safety check)
685
+ if (builtinModules[resolved]) {
686
+ return builtinModules[resolved];
687
+ }
688
+
689
+ // Also check if resolved path is to rollup, esbuild, or prettier in node_modules
690
+ if (resolved.includes('/node_modules/rollup/') ||
691
+ resolved.includes('/node_modules/@rollup/')) {
692
+ return builtinModules['rollup'];
693
+ }
694
+ if (resolved.includes('/node_modules/esbuild/') ||
695
+ resolved.includes('/node_modules/@esbuild/')) {
696
+ return builtinModules['esbuild'];
697
+ }
698
+ if (resolved.includes('/node_modules/prettier/')) {
699
+ return builtinModules['prettier'];
700
+ }
701
+ if (resolved.includes('/node_modules/@sentry/')) {
702
+ return builtinModules['@sentry/node'];
703
+ }
704
+
705
+ return loadModule(resolved).exports;
706
+ };
707
+
708
+ require.resolve = (id: string): string => {
709
+ if (id === 'fs' || id === 'process' || builtinModules[id]) {
710
+ return id;
711
+ }
712
+ return resolveModule(id, currentDir);
713
+ };
714
+
715
+ require.cache = moduleCache;
716
+
717
+ return require;
718
+ }
719
+
720
+ /**
721
+ * Create a console wrapper that can capture output
722
+ */
723
+ function createConsoleWrapper(
724
+ onConsole?: (method: string, args: unknown[]) => void
725
+ ): Console {
726
+ const wrapper = {
727
+ log: (...args: unknown[]) => {
728
+ console.log(...args);
729
+ onConsole?.('log', args);
730
+ },
731
+ error: (...args: unknown[]) => {
732
+ console.error(...args);
733
+ onConsole?.('error', args);
734
+ },
735
+ warn: (...args: unknown[]) => {
736
+ console.warn(...args);
737
+ onConsole?.('warn', args);
738
+ },
739
+ info: (...args: unknown[]) => {
740
+ console.info(...args);
741
+ onConsole?.('info', args);
742
+ },
743
+ debug: (...args: unknown[]) => {
744
+ console.debug(...args);
745
+ onConsole?.('debug', args);
746
+ },
747
+ trace: (...args: unknown[]) => {
748
+ console.trace(...args);
749
+ onConsole?.('trace', args);
750
+ },
751
+ dir: (obj: unknown) => {
752
+ console.dir(obj);
753
+ onConsole?.('dir', [obj]);
754
+ },
755
+ time: console.time.bind(console),
756
+ timeEnd: console.timeEnd.bind(console),
757
+ timeLog: console.timeLog.bind(console),
758
+ assert: console.assert.bind(console),
759
+ clear: console.clear.bind(console),
760
+ count: console.count.bind(console),
761
+ countReset: console.countReset.bind(console),
762
+ group: console.group.bind(console),
763
+ groupCollapsed: console.groupCollapsed.bind(console),
764
+ groupEnd: console.groupEnd.bind(console),
765
+ table: console.table.bind(console),
766
+ };
767
+
768
+ return wrapper as unknown as Console;
769
+ }
770
+
771
+ /**
772
+ * Runtime class for executing code in virtual environment
773
+ * Note: This class has sync methods for backward compatibility.
774
+ * Use createRuntime() factory for IRuntime interface compliance.
775
+ */
776
+ export class Runtime {
777
+ private vfs: VirtualFS;
778
+ private fsShim: FsShim;
779
+ private process: Process;
780
+ private moduleCache: Record<string, Module> = {};
781
+ private options: RuntimeOptions;
782
+
783
+ constructor(vfs: VirtualFS, options: RuntimeOptions = {}) {
784
+ this.vfs = vfs;
785
+ // Create process first so we can get cwd for fs shim
786
+ this.process = createProcess({
787
+ cwd: options.cwd || '/',
788
+ env: options.env,
789
+ });
790
+ // Create fs shim with cwd getter for relative path resolution
791
+ this.fsShim = createFsShim(vfs, () => this.process.cwd());
792
+ this.options = options;
793
+
794
+ // Initialize child_process with VFS for bash command support
795
+ initChildProcess(vfs);
796
+
797
+ // Initialize file watcher shims with VFS
798
+ chokidarShim.setVFS(vfs);
799
+ readdirpShim.setVFS(vfs);
800
+
801
+ // Initialize esbuild shim with VFS for file access
802
+ esbuildShim.setVFS(vfs);
803
+
804
+ // Polyfill TextDecoder to handle base64/base64url/hex gracefully
805
+ // (Some CLI tools incorrectly try to use TextDecoder for these)
806
+ this.setupTextDecoderPolyfill();
807
+ }
808
+
809
+ /**
810
+ * Set up a polyfilled TextDecoder that handles binary encodings
811
+ */
812
+ private setupTextDecoderPolyfill(): void {
813
+ const OriginalTextDecoder = globalThis.TextDecoder;
814
+
815
+ class PolyfillTextDecoder {
816
+ private encoding: string;
817
+ private decoder: TextDecoder | null = null;
818
+
819
+ constructor(encoding: string = 'utf-8', options?: TextDecoderOptions) {
820
+ this.encoding = encoding.toLowerCase();
821
+
822
+ // For valid text encodings, use the real TextDecoder
823
+ const validTextEncodings = [
824
+ 'utf-8', 'utf8', 'utf-16le', 'utf-16be', 'utf-16',
825
+ 'ascii', 'iso-8859-1', 'latin1', 'windows-1252'
826
+ ];
827
+
828
+ if (validTextEncodings.includes(this.encoding)) {
829
+ try {
830
+ this.decoder = new OriginalTextDecoder(encoding, options);
831
+ } catch {
832
+ // Fall back to utf-8
833
+ this.decoder = new OriginalTextDecoder('utf-8', options);
834
+ }
835
+ }
836
+ // For binary encodings (base64, base64url, hex), decoder stays null
837
+ }
838
+
839
+ decode(input?: BufferSource, options?: TextDecodeOptions): string {
840
+ if (this.decoder) {
841
+ return this.decoder.decode(input, options);
842
+ }
843
+
844
+ // Handle binary encodings manually
845
+ if (!input) return '';
846
+
847
+ const bytes = input instanceof ArrayBuffer
848
+ ? new Uint8Array(input)
849
+ : new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
850
+
851
+ if (this.encoding === 'base64') {
852
+ let binary = '';
853
+ for (let i = 0; i < bytes.length; i++) {
854
+ binary += String.fromCharCode(bytes[i]);
855
+ }
856
+ return btoa(binary);
857
+ }
858
+
859
+ if (this.encoding === 'base64url') {
860
+ let binary = '';
861
+ for (let i = 0; i < bytes.length; i++) {
862
+ binary += String.fromCharCode(bytes[i]);
863
+ }
864
+ return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
865
+ }
866
+
867
+ if (this.encoding === 'hex') {
868
+ let hex = '';
869
+ for (let i = 0; i < bytes.length; i++) {
870
+ hex += bytes[i].toString(16).padStart(2, '0');
871
+ }
872
+ return hex;
873
+ }
874
+
875
+ // Fallback: decode as utf-8
876
+ return new OriginalTextDecoder('utf-8').decode(input, options);
877
+ }
878
+
879
+ get fatal(): boolean {
880
+ return this.decoder?.fatal ?? false;
881
+ }
882
+
883
+ get ignoreBOM(): boolean {
884
+ return this.decoder?.ignoreBOM ?? false;
885
+ }
886
+ }
887
+
888
+ globalThis.TextDecoder = PolyfillTextDecoder as unknown as typeof TextDecoder;
889
+ }
890
+
891
+ /**
892
+ * Execute code as a module (synchronous - backward compatible)
893
+ */
894
+ execute(
895
+ code: string,
896
+ filename: string = '/index.js'
897
+ ): { exports: unknown; module: Module } {
898
+ const dirname = pathShim.dirname(filename);
899
+
900
+ // Write code to virtual file system
901
+ this.vfs.writeFileSync(filename, code);
902
+
903
+ // Create require function
904
+ const require = createRequire(
905
+ this.vfs,
906
+ this.fsShim,
907
+ this.process,
908
+ dirname,
909
+ this.moduleCache,
910
+ this.options
911
+ );
912
+
913
+ // Create module object
914
+ const module: Module = {
915
+ id: filename,
916
+ filename,
917
+ exports: {},
918
+ loaded: false,
919
+ children: [],
920
+ paths: [],
921
+ };
922
+
923
+ // Cache the module
924
+ this.moduleCache[filename] = module;
925
+
926
+ // Create console wrapper
927
+ const consoleWrapper = createConsoleWrapper(this.options.onConsole);
928
+
929
+ // Execute code
930
+ // Use the same wrapper pattern as loadModule for consistency
931
+ try {
932
+ const importMetaUrl = 'file://' + filename;
933
+ const wrappedCode = `(function($exports, $require, $module, $filename, $dirname, $process, $console, $importMeta) {
934
+ var exports = $exports;
935
+ var require = $require;
936
+ var module = $module;
937
+ var __filename = $filename;
938
+ var __dirname = $dirname;
939
+ var process = $process;
940
+ var console = $console;
941
+ var import_meta = $importMeta;
942
+ // Set up global.process and globalThis.process for code that accesses them directly
943
+ var global = globalThis;
944
+ globalThis.process = $process;
945
+ global.process = $process;
946
+
947
+ return (function() {
948
+ ${code}
949
+ }).call(this);
950
+ })`;
951
+
952
+ const fn = eval(wrappedCode);
953
+ fn(
954
+ module.exports,
955
+ require,
956
+ module,
957
+ filename,
958
+ dirname,
959
+ this.process,
960
+ consoleWrapper,
961
+ { url: importMetaUrl, dirname, filename }
962
+ );
963
+
964
+ module.loaded = true;
965
+ } catch (error) {
966
+ delete this.moduleCache[filename];
967
+ throw error;
968
+ }
969
+
970
+ return { exports: module.exports, module };
971
+ }
972
+
973
+ /**
974
+ * Execute code as a module (async version for IRuntime interface)
975
+ * Alias: executeSync() is the same as execute() for backward compatibility
976
+ */
977
+ executeSync = this.execute;
978
+
979
+ /**
980
+ * Execute code as a module (async - for IRuntime interface)
981
+ */
982
+ async executeAsync(
983
+ code: string,
984
+ filename: string = '/index.js'
985
+ ): Promise<IExecuteResult> {
986
+ return Promise.resolve(this.execute(code, filename));
987
+ }
988
+
989
+ /**
990
+ * Run a file from the virtual file system (synchronous - backward compatible)
991
+ */
992
+ runFile(filename: string): { exports: unknown; module: Module } {
993
+ const code = this.vfs.readFileSync(filename, 'utf8');
994
+ return this.execute(code, filename);
995
+ }
996
+
997
+ /**
998
+ * Alias for runFile (backward compatibility)
999
+ */
1000
+ runFileSync = this.runFile;
1001
+
1002
+ /**
1003
+ * Run a file from the virtual file system (async - for IRuntime interface)
1004
+ */
1005
+ async runFileAsync(filename: string): Promise<IExecuteResult> {
1006
+ return Promise.resolve(this.runFile(filename));
1007
+ }
1008
+
1009
+ /**
1010
+ * Clear the module cache
1011
+ */
1012
+ clearCache(): void {
1013
+ this.moduleCache = {};
1014
+ }
1015
+
1016
+ /**
1017
+ * Get the virtual file system
1018
+ */
1019
+ getVFS(): VirtualFS {
1020
+ return this.vfs;
1021
+ }
1022
+
1023
+ /**
1024
+ * Get the process object
1025
+ */
1026
+ getProcess(): Process {
1027
+ return this.process;
1028
+ }
1029
+ }
1030
+
1031
+ /**
1032
+ * Create and execute code in a new runtime (synchronous - backward compatible)
1033
+ */
1034
+ export function execute(
1035
+ code: string,
1036
+ vfs: VirtualFS,
1037
+ options?: RuntimeOptions
1038
+ ): { exports: unknown; module: Module } {
1039
+ const runtime = new Runtime(vfs, options);
1040
+ return runtime.execute(code);
1041
+ }
1042
+
1043
+ // Re-export types
1044
+ export type { IRuntime, IExecuteResult, IRuntimeOptions } from './runtime-interface';
1045
+
1046
+ export default Runtime;