@seanhogg/builderforce-webcontainers-core 2026.10.1 → 2026.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/dist/build.d.ts +42 -0
  2. package/dist/build.d.ts.map +1 -0
  3. package/dist/build.js +65 -0
  4. package/dist/build.js.map +1 -0
  5. package/dist/buildHost.d.ts +31 -0
  6. package/dist/buildHost.d.ts.map +1 -0
  7. package/dist/buildHost.js +125 -0
  8. package/dist/buildHost.js.map +1 -0
  9. package/dist/buildHtml.d.ts +28 -0
  10. package/dist/buildHtml.d.ts.map +1 -0
  11. package/dist/buildHtml.js +74 -0
  12. package/dist/buildHtml.js.map +1 -0
  13. package/dist/bundler.d.ts +129 -0
  14. package/dist/bundler.d.ts.map +1 -0
  15. package/dist/bundler.js +79 -0
  16. package/dist/bundler.js.map +1 -0
  17. package/dist/check/acquire.d.ts +46 -0
  18. package/dist/check/acquire.d.ts.map +1 -0
  19. package/dist/check/acquire.js +179 -0
  20. package/dist/check/acquire.js.map +1 -0
  21. package/dist/check/compilerHost.d.ts +22 -0
  22. package/dist/check/compilerHost.d.ts.map +1 -0
  23. package/dist/check/compilerHost.js +128 -0
  24. package/dist/check/compilerHost.js.map +1 -0
  25. package/dist/check/diagnostics.d.ts +23 -0
  26. package/dist/check/diagnostics.d.ts.map +1 -0
  27. package/dist/check/diagnostics.js +28 -0
  28. package/dist/check/diagnostics.js.map +1 -0
  29. package/dist/check/index.d.ts +19 -0
  30. package/dist/check/index.d.ts.map +1 -0
  31. package/dist/check/index.js +13 -0
  32. package/dist/check/index.js.map +1 -0
  33. package/dist/check/projects.d.ts +26 -0
  34. package/dist/check/projects.d.ts.map +1 -0
  35. package/dist/check/projects.js +124 -0
  36. package/dist/check/projects.js.map +1 -0
  37. package/dist/check/shims.d.ts +29 -0
  38. package/dist/check/shims.d.ts.map +1 -0
  39. package/dist/check/shims.js +76 -0
  40. package/dist/check/shims.js.map +1 -0
  41. package/dist/check/typeStore.d.ts +57 -0
  42. package/dist/check/typeStore.d.ts.map +1 -0
  43. package/dist/check/typeStore.js +89 -0
  44. package/dist/check/typeStore.js.map +1 -0
  45. package/dist/check/typecheck.d.ts +29 -0
  46. package/dist/check/typecheck.d.ts.map +1 -0
  47. package/dist/check/typecheck.js +91 -0
  48. package/dist/check/typecheck.js.map +1 -0
  49. package/dist/compileComponent.d.ts +8 -0
  50. package/dist/compileComponent.d.ts.map +1 -0
  51. package/dist/compileComponent.js +22 -0
  52. package/dist/compileComponent.js.map +1 -0
  53. package/dist/compileScript.d.ts +19 -4
  54. package/dist/compileScript.d.ts.map +1 -1
  55. package/dist/compileScript.js +37 -12
  56. package/dist/compileScript.js.map +1 -1
  57. package/dist/components.d.ts +41 -0
  58. package/dist/components.d.ts.map +1 -0
  59. package/dist/components.js +14 -0
  60. package/dist/components.js.map +1 -0
  61. package/dist/detectProject.d.ts +3 -0
  62. package/dist/detectProject.d.ts.map +1 -1
  63. package/dist/detectProject.js +16 -6
  64. package/dist/detectProject.js.map +1 -1
  65. package/dist/devServer.d.ts +5 -2
  66. package/dist/devServer.d.ts.map +1 -1
  67. package/dist/devServer.js +16 -8
  68. package/dist/devServer.js.map +1 -1
  69. package/dist/hash.d.ts +2 -0
  70. package/dist/hash.d.ts.map +1 -0
  71. package/dist/hash.js +22 -0
  72. package/dist/hash.js.map +1 -0
  73. package/dist/html.d.ts +8 -0
  74. package/dist/html.d.ts.map +1 -1
  75. package/dist/html.js +17 -1
  76. package/dist/html.js.map +1 -1
  77. package/dist/index.d.ts +25 -7
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +15 -4
  80. package/dist/index.js.map +1 -1
  81. package/dist/installer/bins.d.ts +24 -0
  82. package/dist/installer/bins.d.ts.map +1 -0
  83. package/dist/installer/bins.js +56 -0
  84. package/dist/installer/bins.js.map +1 -0
  85. package/dist/installer/index.d.ts +14 -0
  86. package/dist/installer/index.d.ts.map +1 -0
  87. package/dist/installer/index.js +9 -0
  88. package/dist/installer/index.js.map +1 -0
  89. package/dist/installer/install.d.ts +46 -0
  90. package/dist/installer/install.d.ts.map +1 -0
  91. package/dist/installer/install.js +245 -0
  92. package/dist/installer/install.js.map +1 -0
  93. package/dist/installer/lockfile.d.ts +49 -0
  94. package/dist/installer/lockfile.d.ts.map +1 -0
  95. package/dist/installer/lockfile.js +110 -0
  96. package/dist/installer/lockfile.js.map +1 -0
  97. package/dist/installer/registry.d.ts +84 -0
  98. package/dist/installer/registry.d.ts.map +1 -0
  99. package/dist/installer/registry.js +130 -0
  100. package/dist/installer/registry.js.map +1 -0
  101. package/dist/installer/semver.d.ts +38 -0
  102. package/dist/installer/semver.d.ts.map +1 -0
  103. package/dist/installer/semver.js +187 -0
  104. package/dist/installer/semver.js.map +1 -0
  105. package/dist/installer/spec.d.ts +30 -0
  106. package/dist/installer/spec.d.ts.map +1 -0
  107. package/dist/installer/spec.js +30 -0
  108. package/dist/installer/spec.js.map +1 -0
  109. package/dist/installer/tar.d.ts +17 -0
  110. package/dist/installer/tar.d.ts.map +1 -0
  111. package/dist/installer/tar.js +150 -0
  112. package/dist/installer/tar.js.map +1 -0
  113. package/dist/installer/tree.d.ts +48 -0
  114. package/dist/installer/tree.d.ts.map +1 -0
  115. package/dist/installer/tree.js +179 -0
  116. package/dist/installer/tree.js.map +1 -0
  117. package/dist/node/assert.d.ts +15 -0
  118. package/dist/node/assert.d.ts.map +1 -0
  119. package/dist/node/assert.js +137 -0
  120. package/dist/node/assert.js.map +1 -0
  121. package/dist/node/buffer.d.ts +84 -0
  122. package/dist/node/buffer.d.ts.map +1 -0
  123. package/dist/node/buffer.js +304 -0
  124. package/dist/node/buffer.js.map +1 -0
  125. package/dist/node/builtins.d.ts +25 -0
  126. package/dist/node/builtins.d.ts.map +1 -0
  127. package/dist/node/builtins.js +101 -0
  128. package/dist/node/builtins.js.map +1 -0
  129. package/dist/node/callable.d.ts +13 -0
  130. package/dist/node/callable.d.ts.map +1 -0
  131. package/dist/node/callable.js +26 -0
  132. package/dist/node/callable.js.map +1 -0
  133. package/dist/node/childProcess.d.ts +13 -0
  134. package/dist/node/childProcess.d.ts.map +1 -0
  135. package/dist/node/childProcess.js +143 -0
  136. package/dist/node/childProcess.js.map +1 -0
  137. package/dist/node/crypto.d.ts +3 -0
  138. package/dist/node/crypto.d.ts.map +1 -0
  139. package/dist/node/crypto.js +180 -0
  140. package/dist/node/crypto.js.map +1 -0
  141. package/dist/node/esm.d.ts +9 -0
  142. package/dist/node/esm.d.ts.map +1 -0
  143. package/dist/node/esm.js +202 -0
  144. package/dist/node/esm.js.map +1 -0
  145. package/dist/node/events.d.ts +40 -0
  146. package/dist/node/events.d.ts.map +1 -0
  147. package/dist/node/events.js +160 -0
  148. package/dist/node/events.js.map +1 -0
  149. package/dist/node/fs/index.d.ts +7 -0
  150. package/dist/node/fs/index.d.ts.map +1 -0
  151. package/dist/node/fs/index.js +270 -0
  152. package/dist/node/fs/index.js.map +1 -0
  153. package/dist/node/fs/stats.d.ts +93 -0
  154. package/dist/node/fs/stats.d.ts.map +1 -0
  155. package/dist/node/fs/stats.js +104 -0
  156. package/dist/node/fs/stats.js.map +1 -0
  157. package/dist/node/fs/sync.d.ts +98 -0
  158. package/dist/node/fs/sync.d.ts.map +1 -0
  159. package/dist/node/fs/sync.js +348 -0
  160. package/dist/node/fs/sync.js.map +1 -0
  161. package/dist/node/hashes.d.ts +15 -0
  162. package/dist/node/hashes.d.ts.map +1 -0
  163. package/dist/node/hashes.js +195 -0
  164. package/dist/node/hashes.js.map +1 -0
  165. package/dist/node/http/client.d.ts +35 -0
  166. package/dist/node/http/client.d.ts.map +1 -0
  167. package/dist/node/http/client.js +161 -0
  168. package/dist/node/http/client.js.map +1 -0
  169. package/dist/node/http/index.d.ts +5 -0
  170. package/dist/node/http/index.d.ts.map +1 -0
  171. package/dist/node/http/index.js +125 -0
  172. package/dist/node/http/index.js.map +1 -0
  173. package/dist/node/http/server.d.ts +135 -0
  174. package/dist/node/http/server.d.ts.map +1 -0
  175. package/dist/node/http/server.js +308 -0
  176. package/dist/node/http/server.js.map +1 -0
  177. package/dist/node/http/status.d.ts +3 -0
  178. package/dist/node/http/status.d.ts.map +1 -0
  179. package/dist/node/http/status.js +13 -0
  180. package/dist/node/http/status.js.map +1 -0
  181. package/dist/node/inspect.d.ts +22 -0
  182. package/dist/node/inspect.d.ts.map +1 -0
  183. package/dist/node/inspect.js +172 -0
  184. package/dist/node/inspect.js.map +1 -0
  185. package/dist/node/loader.d.ts +91 -0
  186. package/dist/node/loader.d.ts.map +1 -0
  187. package/dist/node/loader.js +265 -0
  188. package/dist/node/loader.js.map +1 -0
  189. package/dist/node/loop.d.ts +71 -0
  190. package/dist/node/loop.d.ts.map +1 -0
  191. package/dist/node/loop.js +189 -0
  192. package/dist/node/loop.js.map +1 -0
  193. package/dist/node/misc.d.ts +10 -0
  194. package/dist/node/misc.d.ts.map +1 -0
  195. package/dist/node/misc.js +256 -0
  196. package/dist/node/misc.js.map +1 -0
  197. package/dist/node/path.d.ts +14 -0
  198. package/dist/node/path.d.ts.map +1 -0
  199. package/dist/node/path.js +128 -0
  200. package/dist/node/path.js.map +1 -0
  201. package/dist/node/process.d.ts +31 -0
  202. package/dist/node/process.d.ts.map +1 -0
  203. package/dist/node/process.js +309 -0
  204. package/dist/node/process.js.map +1 -0
  205. package/dist/node/program.d.ts +19 -0
  206. package/dist/node/program.d.ts.map +1 -0
  207. package/dist/node/program.js +165 -0
  208. package/dist/node/program.js.map +1 -0
  209. package/dist/node/readline.d.ts +2 -0
  210. package/dist/node/readline.d.ts.map +1 -0
  211. package/dist/node/readline.js +155 -0
  212. package/dist/node/readline.js.map +1 -0
  213. package/dist/node/resolve.d.ts +45 -0
  214. package/dist/node/resolve.d.ts.map +1 -0
  215. package/dist/node/resolve.js +206 -0
  216. package/dist/node/resolve.js.map +1 -0
  217. package/dist/node/runtime.d.ts +40 -0
  218. package/dist/node/runtime.d.ts.map +1 -0
  219. package/dist/node/runtime.js +149 -0
  220. package/dist/node/runtime.js.map +1 -0
  221. package/dist/node/stream/index.d.ts +52 -0
  222. package/dist/node/stream/index.d.ts.map +1 -0
  223. package/dist/node/stream/index.js +184 -0
  224. package/dist/node/stream/index.js.map +1 -0
  225. package/dist/node/stream/readable.d.ts +83 -0
  226. package/dist/node/stream/readable.d.ts.map +1 -0
  227. package/dist/node/stream/readable.js +325 -0
  228. package/dist/node/stream/readable.js.map +1 -0
  229. package/dist/node/stream/writable.d.ts +80 -0
  230. package/dist/node/stream/writable.d.ts.map +1 -0
  231. package/dist/node/stream/writable.js +224 -0
  232. package/dist/node/stream/writable.js.map +1 -0
  233. package/dist/node/urlqs.d.ts +22 -0
  234. package/dist/node/urlqs.d.ts.map +1 -0
  235. package/dist/node/urlqs.js +165 -0
  236. package/dist/node/urlqs.js.map +1 -0
  237. package/dist/node/util.d.ts +37 -0
  238. package/dist/node/util.d.ts.map +1 -0
  239. package/dist/node/util.js +160 -0
  240. package/dist/node/util.js.map +1 -0
  241. package/dist/node/zlib.d.ts +2 -0
  242. package/dist/node/zlib.d.ts.map +1 -0
  243. package/dist/node/zlib.js +133 -0
  244. package/dist/node/zlib.js.map +1 -0
  245. package/dist/packageCdn.d.ts +12 -0
  246. package/dist/packageCdn.d.ts.map +1 -1
  247. package/dist/packageCdn.js +3 -1
  248. package/dist/packageCdn.js.map +1 -1
  249. package/dist/projectConfig.d.ts +6 -2
  250. package/dist/projectConfig.d.ts.map +1 -1
  251. package/dist/projectConfig.js +32 -8
  252. package/dist/projectConfig.js.map +1 -1
  253. package/dist/shell/builtins.d.ts +23 -0
  254. package/dist/shell/builtins.d.ts.map +1 -0
  255. package/dist/shell/builtins.js +131 -0
  256. package/dist/shell/builtins.js.map +1 -0
  257. package/dist/shell/context.d.ts +41 -0
  258. package/dist/shell/context.d.ts.map +1 -0
  259. package/dist/shell/context.js +65 -0
  260. package/dist/shell/context.js.map +1 -0
  261. package/dist/shell/devHandoff.d.ts +18 -0
  262. package/dist/shell/devHandoff.d.ts.map +1 -0
  263. package/dist/shell/devHandoff.js +36 -0
  264. package/dist/shell/devHandoff.js.map +1 -0
  265. package/dist/shell/exec.d.ts +67 -0
  266. package/dist/shell/exec.d.ts.map +1 -0
  267. package/dist/shell/exec.js +247 -0
  268. package/dist/shell/exec.js.map +1 -0
  269. package/dist/shell/expand.d.ts +28 -0
  270. package/dist/shell/expand.d.ts.map +1 -0
  271. package/dist/shell/expand.js +149 -0
  272. package/dist/shell/expand.js.map +1 -0
  273. package/dist/shell/fileCommands.d.ts +10 -0
  274. package/dist/shell/fileCommands.d.ts.map +1 -0
  275. package/dist/shell/fileCommands.js +208 -0
  276. package/dist/shell/fileCommands.js.map +1 -0
  277. package/dist/shell/lineEditor.d.ts +43 -0
  278. package/dist/shell/lineEditor.d.ts.map +1 -0
  279. package/dist/shell/lineEditor.js +234 -0
  280. package/dist/shell/lineEditor.js.map +1 -0
  281. package/dist/shell/npm.d.ts +6 -0
  282. package/dist/shell/npm.d.ts.map +1 -0
  283. package/dist/shell/npm.js +234 -0
  284. package/dist/shell/npm.js.map +1 -0
  285. package/dist/shell/parse.d.ts +73 -0
  286. package/dist/shell/parse.d.ts.map +1 -0
  287. package/dist/shell/parse.js +300 -0
  288. package/dist/shell/parse.js.map +1 -0
  289. package/dist/shell/program.d.ts +12 -0
  290. package/dist/shell/program.d.ts.map +1 -0
  291. package/dist/shell/program.js +219 -0
  292. package/dist/shell/program.js.map +1 -0
  293. package/dist/shell/textCommands.d.ts +15 -0
  294. package/dist/shell/textCommands.d.ts.map +1 -0
  295. package/dist/shell/textCommands.js +185 -0
  296. package/dist/shell/textCommands.js.map +1 -0
  297. package/dist/styleModules.d.ts +6 -0
  298. package/dist/styleModules.d.ts.map +1 -1
  299. package/dist/styleModules.js +14 -4
  300. package/dist/styleModules.js.map +1 -1
  301. package/dist/svelteCompiler.d.ts +28 -0
  302. package/dist/svelteCompiler.d.ts.map +1 -0
  303. package/dist/svelteCompiler.js +13 -0
  304. package/dist/svelteCompiler.js.map +1 -0
  305. package/dist/system/commands.d.ts +26 -0
  306. package/dist/system/commands.d.ts.map +1 -0
  307. package/dist/system/commands.js +53 -0
  308. package/dist/system/commands.js.map +1 -0
  309. package/dist/system/index.d.ts +23 -0
  310. package/dist/system/index.d.ts.map +1 -0
  311. package/dist/system/index.js +16 -0
  312. package/dist/system/index.js.map +1 -0
  313. package/dist/system/kernel.d.ts +54 -0
  314. package/dist/system/kernel.d.ts.map +1 -0
  315. package/dist/system/kernel.js +81 -0
  316. package/dist/system/kernel.js.map +1 -0
  317. package/dist/system/ports.d.ts +32 -0
  318. package/dist/system/ports.d.ts.map +1 -0
  319. package/dist/system/ports.js +57 -0
  320. package/dist/system/ports.js.map +1 -0
  321. package/dist/system/process.d.ts +32 -0
  322. package/dist/system/process.d.ts.map +1 -0
  323. package/dist/system/process.js +130 -0
  324. package/dist/system/process.js.map +1 -0
  325. package/dist/system/programs.d.ts +10 -0
  326. package/dist/system/programs.d.ts.map +1 -0
  327. package/dist/system/programs.js +22 -0
  328. package/dist/system/programs.js.map +1 -0
  329. package/dist/system/terminal.d.ts +45 -0
  330. package/dist/system/terminal.d.ts.map +1 -0
  331. package/dist/system/terminal.js +127 -0
  332. package/dist/system/terminal.js.map +1 -0
  333. package/dist/system/types.d.ts +100 -0
  334. package/dist/system/types.d.ts.map +1 -0
  335. package/dist/system/types.js +2 -0
  336. package/dist/system/types.js.map +1 -0
  337. package/dist/vfs.d.ts +28 -4
  338. package/dist/vfs.d.ts.map +1 -1
  339. package/dist/vfs.js +95 -32
  340. package/dist/vfs.js.map +1 -1
  341. package/dist/vueCompiler.d.ts +75 -0
  342. package/dist/vueCompiler.d.ts.map +1 -0
  343. package/dist/vueCompiler.js +67 -0
  344. package/dist/vueCompiler.js.map +1 -0
  345. package/package.json +18 -2
  346. package/src/build.ts +105 -0
  347. package/src/buildHost.ts +154 -0
  348. package/src/buildHtml.ts +101 -0
  349. package/src/bundler.ts +190 -0
  350. package/src/check/acquire.ts +212 -0
  351. package/src/check/compilerHost.ts +138 -0
  352. package/src/check/diagnostics.ts +48 -0
  353. package/src/check/index.ts +28 -0
  354. package/src/check/projects.ts +149 -0
  355. package/src/check/shims.ts +88 -0
  356. package/src/check/typeStore.ts +103 -0
  357. package/src/check/typecheck.ts +134 -0
  358. package/src/compileComponent.ts +21 -0
  359. package/src/compileScript.ts +42 -13
  360. package/src/components.ts +59 -0
  361. package/src/detectProject.ts +18 -6
  362. package/src/devServer.ts +19 -10
  363. package/src/hash.ts +22 -0
  364. package/src/html.ts +19 -1
  365. package/src/index.ts +36 -7
  366. package/src/installer/bins.ts +64 -0
  367. package/src/installer/index.ts +13 -0
  368. package/src/installer/install.ts +275 -0
  369. package/src/installer/lockfile.ts +146 -0
  370. package/src/installer/registry.ts +175 -0
  371. package/src/installer/semver.ts +190 -0
  372. package/src/installer/spec.ts +53 -0
  373. package/src/installer/tar.ts +155 -0
  374. package/src/installer/tree.ts +236 -0
  375. package/src/node/assert.ts +127 -0
  376. package/src/node/buffer.ts +304 -0
  377. package/src/node/builtins.ts +123 -0
  378. package/src/node/callable.ts +25 -0
  379. package/src/node/childProcess.ts +164 -0
  380. package/src/node/crypto.ts +187 -0
  381. package/src/node/esm.ts +196 -0
  382. package/src/node/events.ts +176 -0
  383. package/src/node/fs/index.ts +277 -0
  384. package/src/node/fs/stats.ts +110 -0
  385. package/src/node/fs/sync.ts +335 -0
  386. package/src/node/hashes.ts +171 -0
  387. package/src/node/http/client.ts +173 -0
  388. package/src/node/http/index.ts +122 -0
  389. package/src/node/http/server.ts +308 -0
  390. package/src/node/http/status.ts +13 -0
  391. package/src/node/inspect.ts +166 -0
  392. package/src/node/loader.ts +293 -0
  393. package/src/node/loop.ts +193 -0
  394. package/src/node/misc.ts +250 -0
  395. package/src/node/path.ts +135 -0
  396. package/src/node/process.ts +324 -0
  397. package/src/node/program.ts +170 -0
  398. package/src/node/readline.ts +157 -0
  399. package/src/node/resolve.ts +216 -0
  400. package/src/node/runtime.ts +184 -0
  401. package/src/node/stream/index.ts +196 -0
  402. package/src/node/stream/readable.ts +345 -0
  403. package/src/node/stream/writable.ts +244 -0
  404. package/src/node/urlqs.ts +162 -0
  405. package/src/node/util.ts +145 -0
  406. package/src/node/zlib.ts +145 -0
  407. package/src/packageCdn.ts +11 -1
  408. package/src/projectConfig.ts +34 -7
  409. package/src/shell/builtins.ts +141 -0
  410. package/src/shell/context.ts +89 -0
  411. package/src/shell/devHandoff.ts +49 -0
  412. package/src/shell/exec.ts +268 -0
  413. package/src/shell/expand.ts +145 -0
  414. package/src/shell/fileCommands.ts +206 -0
  415. package/src/shell/lineEditor.ts +233 -0
  416. package/src/shell/npm.ts +229 -0
  417. package/src/shell/parse.ts +295 -0
  418. package/src/shell/program.ts +223 -0
  419. package/src/shell/textCommands.ts +177 -0
  420. package/src/styleModules.ts +15 -4
  421. package/src/svelteCompiler.ts +31 -0
  422. package/src/system/commands.ts +72 -0
  423. package/src/system/index.ts +22 -0
  424. package/src/system/kernel.ts +106 -0
  425. package/src/system/ports.ts +73 -0
  426. package/src/system/process.ts +158 -0
  427. package/src/system/programs.ts +31 -0
  428. package/src/system/terminal.ts +135 -0
  429. package/src/system/types.ts +103 -0
  430. package/src/vfs.ts +92 -28
  431. package/src/vueCompiler.ts +121 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * The contract between programs (node, the shell, npm, coreutils) and whatever
3
+ * hosts them. Programs only ever see these ports, so the same program code runs
4
+ * in-process under the core `Kernel` (Node tests) and one-per-Web-Worker in the
5
+ * browser runtime, where `spawn` and `listen` are relayed to the page.
6
+ */
7
+ import type { VirtualFileSystem } from '../vfs.js';
8
+ import type { PackageCache } from '../installer/registry.js';
9
+
10
+ export interface TerminalPort {
11
+ cols: number;
12
+ rows: number;
13
+ onResize(listener: (cols: number, rows: number) => void): () => void;
14
+ /** Raw mode: the program handles keystrokes itself (no line editing, no echo). */
15
+ setRawMode(raw: boolean): void;
16
+ }
17
+
18
+ export interface ProgramIO {
19
+ stdout(chunk: string | Uint8Array): void;
20
+ stderr(chunk: string | Uint8Array): void;
21
+ /** Stdin chunks as they arrive; `null` is end-of-file. Buffered until the first subscriber. */
22
+ onStdin(listener: (chunk: string | null) => void): () => void;
23
+ /** Present when attached to a terminal (xterm.js). */
24
+ terminal?: TerminalPort;
25
+ }
26
+
27
+ export interface SpawnOptions {
28
+ cwd?: string;
29
+ env?: Record<string, string>;
30
+ /** Attach to a terminal of this size (`isTTY`, line discipline, `\r\n` output). */
31
+ terminal?: { cols: number; rows: number };
32
+ }
33
+
34
+ /** A child as its parent sees it (separate stdout/stderr, unlike the public API). */
35
+ export interface ChildHandle {
36
+ readonly pid: number;
37
+ onStdout(listener: (chunk: string) => void): () => void;
38
+ onStderr(listener: (chunk: string) => void): () => void;
39
+ write(data: string): void;
40
+ closeStdin(): void;
41
+ kill(signal?: string): void;
42
+ resize?(cols: number, rows: number): void;
43
+ readonly exit: Promise<number>;
44
+ }
45
+
46
+ export interface HttpRequestData {
47
+ method: string;
48
+ /** Path and query, as the server sees it (`/api?x=1`). */
49
+ url: string;
50
+ headers: Record<string, string>;
51
+ body: Uint8Array | null;
52
+ }
53
+
54
+ export interface HttpResponseData {
55
+ status: number;
56
+ statusText?: string;
57
+ headers: Record<string, string | string[]>;
58
+ body: Uint8Array;
59
+ }
60
+
61
+ export type HttpHandler = (request: HttpRequestData) => Promise<HttpResponseData>;
62
+
63
+ export interface System {
64
+ fs: VirtualFileSystem;
65
+ /** Outbound network (registry, `http.request`, `fetch`). */
66
+ fetch(input: string, init?: RequestInit): Promise<Response>;
67
+ spawn(command: string, args: string[], options?: SpawnOptions): ChildHandle;
68
+ /** Register a virtual server; throws `EADDRINUSE`. Port 0 picks a free one. Returns the port and an unlisten. */
69
+ listen(port: number, handler: HttpHandler): { port: number; close(): void };
70
+ /** Send a request to a virtual server in this runtime (`http.get('http://localhost:3000')`); undefined when nothing listens. */
71
+ loopback(port: number, request: HttpRequestData): Promise<HttpResponseData | undefined>;
72
+ /** Where a browser reaches a server on `port` (the preview URL), if known. */
73
+ serverUrl(port: number): string | undefined;
74
+ /** Tell the host a server is ready (`server-ready`); used by the dev-server handoff. */
75
+ announceServer(port: number, url: string): void;
76
+ /** The in-browser dev server's preview URL, for `vite`/`react-scripts start` handoff. */
77
+ previewUrl?: string;
78
+ /**
79
+ * This program has the JS realm to itself (one process per Web Worker): node
80
+ * may install `process`, `Buffer`, timers on `globalThis`, and the host routes
81
+ * the realm's uncaught errors to it through `trapUncaught`.
82
+ */
83
+ ownsRealm?: boolean;
84
+ /** Register for the realm's uncaught errors and unhandled rejections. */
85
+ trapUncaught?(handler: (error: unknown) => void): () => void;
86
+ /** npm registry and cache for `npm install`. */
87
+ registry?: string;
88
+ packageCache?: PackageCache;
89
+ }
90
+
91
+ export interface ProgramContext {
92
+ /** Arguments after the program name. */
93
+ args: string[];
94
+ cwd: string;
95
+ env: Record<string, string>;
96
+ io: ProgramIO;
97
+ system: System;
98
+ /** Aborted by kill(): in-process programs stop at their next await. */
99
+ signal: AbortSignal;
100
+ }
101
+
102
+ /** A program resolves with its exit code. */
103
+ export type Program = (ctx: ProgramContext) => Promise<number>;
package/src/vfs.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { normalizePath, join } from './paths.js';
1
+ import { normalizePath, join, dirname } from './paths.js';
2
2
 
3
3
  export type FileContent = string | Uint8Array;
4
4
 
@@ -11,7 +11,8 @@ export interface FileSystemTree {
11
11
  export type FlatFiles = Record<string, FileContent>;
12
12
 
13
13
  export interface FsChange {
14
- type: 'write' | 'remove';
14
+ /** `mkdir` is an explicitly created (possibly empty) directory. */
15
+ type: 'write' | 'remove' | 'mkdir';
15
16
  path: string;
16
17
  /** For a write: the file did not exist before. A new file can change how imports resolve. */
17
18
  created?: boolean;
@@ -20,9 +21,14 @@ export interface FsChange {
20
21
  const decoder = new TextDecoder();
21
22
 
22
23
  /**
23
- * An in-memory file system. Files only — a directory exists while it contains a
24
- * file, which keeps the store a single map and makes "is this a directory?" a
25
- * prefix check rather than a second structure to keep consistent.
24
+ * An in-memory file system. Files are the store; a directory exists while it
25
+ * contains something, or because it was created explicitly with `mkdir` (shells
26
+ * and Node programs create empty directories, a preview never needs to).
27
+ *
28
+ * A directory index (dir → child names) is maintained alongside the files, so
29
+ * `isDirectory`/`readdir` stay O(1)/O(children) even with a populated
30
+ * `node_modules` of tens of thousands of files — module resolution probes those
31
+ * constantly.
26
32
  *
27
33
  * Every write bumps a per-file version, so a transform cache can key on
28
34
  * (path, version) instead of hashing contents.
@@ -30,14 +36,22 @@ const decoder = new TextDecoder();
30
36
  export class VirtualFileSystem {
31
37
  private readonly files = new Map<string, FileContent>();
32
38
  private readonly versions = new Map<string, number>();
39
+ private readonly mtimes = new Map<string, number>();
40
+ /** dir → names of its direct children (files and directories). */
41
+ private readonly children = new Map<string, Set<string>>([['/', new Set()]]);
42
+ /** Directories created with `mkdir`: they outlive their last file. */
43
+ private readonly explicit = new Set<string>();
33
44
  private readonly listeners = new Set<(change: FsChange) => void>();
34
45
  private clock = 0;
35
46
 
36
47
  writeFile(path: string, contents: FileContent): void {
37
48
  const key = normalizePath(path);
49
+ if (key === '/' || this.children.has(key)) throw new Error(`EISDIR: illegal operation on a directory, open '${key}'`);
38
50
  const created = !this.files.has(key);
51
+ if (created) this.link(key);
39
52
  this.files.set(key, contents);
40
53
  this.versions.set(key, ++this.clock);
54
+ this.mtimes.set(key, Date.now());
41
55
  this.emit({ type: 'write', path: key, created });
42
56
  }
43
57
 
@@ -56,29 +70,28 @@ export class VirtualFileSystem {
56
70
  }
57
71
 
58
72
  isDirectory(path: string): boolean {
59
- const key = normalizePath(path);
60
- if (key === '/') return true;
61
- const prefix = key + '/';
62
- for (const file of this.files.keys()) if (file.startsWith(prefix)) return true;
63
- return false;
73
+ return this.children.has(normalizePath(path));
64
74
  }
65
75
 
66
76
  exists(path: string): boolean {
67
77
  return this.isFile(path) || this.isDirectory(path);
68
78
  }
69
79
 
80
+ /** Create a directory (and its parents). A no-op when it already exists. */
81
+ mkdir(path: string): void {
82
+ const key = normalizePath(path);
83
+ if (this.files.has(key)) throw new Error(`EEXIST: file already exists, mkdir '${key}'`);
84
+ if (key === '/') return;
85
+ const existed = this.children.has(key);
86
+ this.explicit.add(key);
87
+ if (existed) return;
88
+ this.ensureDir(key);
89
+ this.emit({ type: 'mkdir', path: key });
90
+ }
91
+
70
92
  /** Direct children of a directory (files and sub-directories), sorted. */
71
93
  readdir(path: string): string[] {
72
- const key = normalizePath(path);
73
- const prefix = key === '/' ? '/' : key + '/';
74
- const names = new Set<string>();
75
- for (const file of this.files.keys()) {
76
- if (!file.startsWith(prefix)) continue;
77
- const rest = file.slice(prefix.length);
78
- const name = rest.split('/')[0];
79
- if (name) names.add(name);
80
- }
81
- return [...names].sort();
94
+ return [...(this.children.get(normalizePath(path)) ?? [])].sort();
82
95
  }
83
96
 
84
97
  /** Every file path, sorted. */
@@ -86,17 +99,24 @@ export class VirtualFileSystem {
86
99
  return [...this.files.keys()].sort();
87
100
  }
88
101
 
102
+ /** Directories created explicitly with `mkdir` — what `list()` cannot reproduce. */
103
+ explicitDirectories(): string[] {
104
+ return [...this.explicit].sort();
105
+ }
106
+
89
107
  /** Remove a file, or a directory and everything under it. */
90
108
  rm(path: string): void {
91
109
  const key = normalizePath(path);
92
- const prefix = key === '/' ? '/' : key + '/';
93
- for (const file of [...this.files.keys()]) {
94
- if (file === key || file.startsWith(prefix)) {
95
- this.files.delete(file);
96
- this.versions.delete(file);
97
- this.emit({ type: 'remove', path: file });
98
- }
110
+ if (this.files.has(key)) {
111
+ this.removeFile(key);
112
+ return;
99
113
  }
114
+ if (!this.children.has(key)) return;
115
+ for (const name of [...(this.children.get(key) ?? [])]) this.rm(key === '/' ? '/' + name : `${key}/${name}`);
116
+ if (key === '/') return;
117
+ const wasExplicit = this.explicit.delete(key);
118
+ if (this.children.has(key)) this.unlinkDir(key);
119
+ if (wasExplicit) this.emit({ type: 'remove', path: key });
100
120
  }
101
121
 
102
122
  /** The file's version (bumped on every write), or undefined when absent. */
@@ -104,6 +124,11 @@ export class VirtualFileSystem {
104
124
  return this.versions.get(normalizePath(path));
105
125
  }
106
126
 
127
+ /** When the file was last written (epoch ms), or undefined when absent. */
128
+ mtime(path: string): number | undefined {
129
+ return this.mtimes.get(normalizePath(path));
130
+ }
131
+
107
132
  /**
108
133
  * Write many files at once. Takes either the nested WebContainer tree or a flat
109
134
  * path→contents map — or a mix, since each entry is judged on its own.
@@ -113,7 +138,10 @@ export class VirtualFileSystem {
113
138
  const path = join(at, name);
114
139
  if (typeof entry === 'string' || entry instanceof Uint8Array) this.writeFile(path, entry);
115
140
  else if ('file' in entry) this.writeFile(path, entry.file.contents);
116
- else this.mount(entry.directory, path);
141
+ else {
142
+ this.mkdir(path);
143
+ this.mount(entry.directory, path);
144
+ }
117
145
  }
118
146
  }
119
147
 
@@ -129,6 +157,42 @@ export class VirtualFileSystem {
129
157
  return () => this.listeners.delete(listener);
130
158
  }
131
159
 
160
+ private removeFile(key: string): void {
161
+ this.files.delete(key);
162
+ this.versions.delete(key);
163
+ this.mtimes.delete(key);
164
+ this.unlink(key);
165
+ this.emit({ type: 'remove', path: key });
166
+ }
167
+
168
+ /** Register `key` under its parent, creating implicit ancestors as needed. */
169
+ private link(key: string): void {
170
+ const parent = dirname(key);
171
+ this.ensureDir(parent);
172
+ this.children.get(parent)!.add(key.slice(key.lastIndexOf('/') + 1));
173
+ }
174
+
175
+ private ensureDir(dir: string): void {
176
+ if (this.children.has(dir)) return;
177
+ if (this.files.has(dir)) throw new Error(`ENOTDIR: not a directory, '${dir}'`);
178
+ this.children.set(dir, new Set());
179
+ this.link(dir);
180
+ }
181
+
182
+ /** Detach `key` from its parent, pruning implicit ancestors left empty. */
183
+ private unlink(key: string): void {
184
+ const parent = dirname(key);
185
+ const siblings = this.children.get(parent);
186
+ if (!siblings) return;
187
+ siblings.delete(key.slice(key.lastIndexOf('/') + 1));
188
+ if (siblings.size === 0 && parent !== '/' && !this.explicit.has(parent)) this.unlinkDir(parent);
189
+ }
190
+
191
+ private unlinkDir(dir: string): void {
192
+ this.children.delete(dir);
193
+ this.unlink(dir);
194
+ }
195
+
132
196
  private emit(change: FsChange): void {
133
197
  for (const listener of this.listeners) listener(change);
134
198
  }
@@ -0,0 +1,121 @@
1
+ import type { ComponentCompiler } from './components.js';
2
+ import type { Loader } from './transformer.js';
3
+ import { contentHash } from './hash.js';
4
+
5
+ /**
6
+ * Vue single-file components through `@vue/compiler-sfc` — the same steps
7
+ * `@vitejs/plugin-vue` takes, minus HMR: script (with `<script setup>` and its
8
+ * template inlined), a separate render function for options-API components, and
9
+ * each `<style>` compiled with the component's scope id.
10
+ */
11
+
12
+ interface VueBlock {
13
+ content: string;
14
+ lang?: string;
15
+ }
16
+
17
+ interface VueStyleBlock extends VueBlock {
18
+ scoped?: boolean;
19
+ }
20
+
21
+ export interface VueDescriptor {
22
+ script: VueBlock | null;
23
+ scriptSetup: VueBlock | null;
24
+ template: VueBlock | null;
25
+ styles: VueStyleBlock[];
26
+ }
27
+
28
+ type Problem = string | { message: string };
29
+ /**
30
+ * The script's binding analysis, passed from compileScript to compileTemplate
31
+ * untouched. Opaque here (`any`) so the real compiler's precise type fits.
32
+ */
33
+ type BindingMetadata = any;
34
+
35
+ /** The subset of `@vue/compiler-sfc` used (its browser build has the same API). */
36
+ export interface VueCompilerSfcLike {
37
+ parse(source: string, options: { filename: string; sourceMap: boolean }): { descriptor: VueDescriptor; errors: Problem[] };
38
+ compileScript(
39
+ descriptor: VueDescriptor,
40
+ options: { id: string; inlineTemplate: boolean; genDefaultAs: string; isProd: boolean; sourceMap: boolean },
41
+ ): { content: string; bindings?: BindingMetadata };
42
+ compileTemplate(options: {
43
+ source: string;
44
+ filename: string;
45
+ id: string;
46
+ scoped: boolean;
47
+ isProd: boolean;
48
+ compilerOptions: { bindingMetadata?: BindingMetadata; isTS?: boolean };
49
+ }): { code: string; errors: Problem[] };
50
+ compileStyle(options: { source: string; filename: string; id: string; scoped: boolean; isProd: boolean }): {
51
+ code: string;
52
+ errors: Problem[];
53
+ };
54
+ }
55
+
56
+ const SCRIPT_LOADERS: Record<string, Loader> = { js: 'js', jsx: 'jsx', ts: 'ts', tsx: 'tsx' };
57
+
58
+ function fail(path: string, problems: Problem[]): never {
59
+ const first = problems[0];
60
+ throw new Error(`${path}: ${typeof first === 'string' ? first : first?.message ?? 'Vue compile error'}`);
61
+ }
62
+
63
+ export function createVueCompiler(sfc: VueCompilerSfcLike): ComponentCompiler {
64
+ return {
65
+ compile(source, { path, dev }) {
66
+ const { descriptor, errors } = sfc.parse(source, { filename: path, sourceMap: false });
67
+ if (errors.length) fail(path, errors);
68
+
69
+ for (const style of descriptor.styles) {
70
+ if (style.lang && style.lang !== 'css') {
71
+ throw new Error(`${path}: <style lang="${style.lang}"> needs a CSS preprocessor this runtime does not have yet.`);
72
+ }
73
+ }
74
+
75
+ // Stable per file, so the scope attribute does not change between reloads.
76
+ const id = contentHash(path);
77
+ const scoped = descriptor.styles.some((style) => style.scoped);
78
+ const lang = descriptor.scriptSetup?.lang ?? descriptor.script?.lang ?? 'js';
79
+ const loader = SCRIPT_LOADERS[lang];
80
+ if (!loader) throw new Error(`${path}: <script lang="${lang}"> is not supported.`);
81
+
82
+ const parts: string[] = [];
83
+ let bindings: BindingMetadata;
84
+ if (descriptor.script || descriptor.scriptSetup) {
85
+ const script = sfc.compileScript(descriptor, { id, inlineTemplate: true, genDefaultAs: '_sfc_main', isProd: !dev, sourceMap: false });
86
+ parts.push(script.content);
87
+ bindings = script.bindings;
88
+ } else {
89
+ parts.push('const _sfc_main = {};');
90
+ }
91
+
92
+ // `<script setup>` inlines its template; anything else needs a render function.
93
+ if (descriptor.template && !descriptor.scriptSetup) {
94
+ const template = sfc.compileTemplate({
95
+ source: descriptor.template.content,
96
+ filename: path,
97
+ id,
98
+ scoped,
99
+ isProd: !dev,
100
+ compilerOptions: { bindingMetadata: bindings, isTS: loader === 'ts' || loader === 'tsx' },
101
+ });
102
+ if (template.errors.length) fail(path, template.errors);
103
+ parts.push(template.code.replace(/\bexport (function|const) render\b/, '$1 _sfc_render'));
104
+ parts.push('_sfc_main.render = _sfc_render;');
105
+ }
106
+ if (scoped) parts.push(`_sfc_main.__scopeId = ${JSON.stringify(`data-v-${id}`)};`);
107
+ if (dev) parts.push(`_sfc_main.__file = ${JSON.stringify(path)};`);
108
+ parts.push('export default _sfc_main;');
109
+
110
+ const css = descriptor.styles
111
+ .map((style) => {
112
+ const out = sfc.compileStyle({ source: style.content, filename: path, id: `data-v-${id}`, scoped: !!style.scoped, isProd: !dev });
113
+ if (out.errors.length) fail(path, out.errors);
114
+ return out.code;
115
+ })
116
+ .join('\n');
117
+
118
+ return { code: parts.join('\n'), loader, css };
119
+ },
120
+ };
121
+ }