@seanhogg/builderforce-webcontainers-core 2026.10.2 → 2026.10.4

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 (426) 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 +12 -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/index.d.ts +24 -6
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +14 -3
  76. package/dist/index.js.map +1 -1
  77. package/dist/installer/bins.d.ts +24 -0
  78. package/dist/installer/bins.d.ts.map +1 -0
  79. package/dist/installer/bins.js +56 -0
  80. package/dist/installer/bins.js.map +1 -0
  81. package/dist/installer/index.d.ts +14 -0
  82. package/dist/installer/index.d.ts.map +1 -0
  83. package/dist/installer/index.js +9 -0
  84. package/dist/installer/index.js.map +1 -0
  85. package/dist/installer/install.d.ts +46 -0
  86. package/dist/installer/install.d.ts.map +1 -0
  87. package/dist/installer/install.js +245 -0
  88. package/dist/installer/install.js.map +1 -0
  89. package/dist/installer/lockfile.d.ts +49 -0
  90. package/dist/installer/lockfile.d.ts.map +1 -0
  91. package/dist/installer/lockfile.js +110 -0
  92. package/dist/installer/lockfile.js.map +1 -0
  93. package/dist/installer/registry.d.ts +84 -0
  94. package/dist/installer/registry.d.ts.map +1 -0
  95. package/dist/installer/registry.js +130 -0
  96. package/dist/installer/registry.js.map +1 -0
  97. package/dist/installer/semver.d.ts +38 -0
  98. package/dist/installer/semver.d.ts.map +1 -0
  99. package/dist/installer/semver.js +187 -0
  100. package/dist/installer/semver.js.map +1 -0
  101. package/dist/installer/spec.d.ts +30 -0
  102. package/dist/installer/spec.d.ts.map +1 -0
  103. package/dist/installer/spec.js +30 -0
  104. package/dist/installer/spec.js.map +1 -0
  105. package/dist/installer/tar.d.ts +17 -0
  106. package/dist/installer/tar.d.ts.map +1 -0
  107. package/dist/installer/tar.js +150 -0
  108. package/dist/installer/tar.js.map +1 -0
  109. package/dist/installer/tree.d.ts +48 -0
  110. package/dist/installer/tree.d.ts.map +1 -0
  111. package/dist/installer/tree.js +179 -0
  112. package/dist/installer/tree.js.map +1 -0
  113. package/dist/node/assert.d.ts +15 -0
  114. package/dist/node/assert.d.ts.map +1 -0
  115. package/dist/node/assert.js +137 -0
  116. package/dist/node/assert.js.map +1 -0
  117. package/dist/node/buffer.d.ts +84 -0
  118. package/dist/node/buffer.d.ts.map +1 -0
  119. package/dist/node/buffer.js +304 -0
  120. package/dist/node/buffer.js.map +1 -0
  121. package/dist/node/builtins.d.ts +25 -0
  122. package/dist/node/builtins.d.ts.map +1 -0
  123. package/dist/node/builtins.js +101 -0
  124. package/dist/node/builtins.js.map +1 -0
  125. package/dist/node/callable.d.ts +13 -0
  126. package/dist/node/callable.d.ts.map +1 -0
  127. package/dist/node/callable.js +26 -0
  128. package/dist/node/callable.js.map +1 -0
  129. package/dist/node/childProcess.d.ts +13 -0
  130. package/dist/node/childProcess.d.ts.map +1 -0
  131. package/dist/node/childProcess.js +143 -0
  132. package/dist/node/childProcess.js.map +1 -0
  133. package/dist/node/crypto.d.ts +3 -0
  134. package/dist/node/crypto.d.ts.map +1 -0
  135. package/dist/node/crypto.js +180 -0
  136. package/dist/node/crypto.js.map +1 -0
  137. package/dist/node/esm.d.ts +9 -0
  138. package/dist/node/esm.d.ts.map +1 -0
  139. package/dist/node/esm.js +202 -0
  140. package/dist/node/esm.js.map +1 -0
  141. package/dist/node/events.d.ts +40 -0
  142. package/dist/node/events.d.ts.map +1 -0
  143. package/dist/node/events.js +160 -0
  144. package/dist/node/events.js.map +1 -0
  145. package/dist/node/fs/index.d.ts +7 -0
  146. package/dist/node/fs/index.d.ts.map +1 -0
  147. package/dist/node/fs/index.js +270 -0
  148. package/dist/node/fs/index.js.map +1 -0
  149. package/dist/node/fs/stats.d.ts +93 -0
  150. package/dist/node/fs/stats.d.ts.map +1 -0
  151. package/dist/node/fs/stats.js +104 -0
  152. package/dist/node/fs/stats.js.map +1 -0
  153. package/dist/node/fs/sync.d.ts +98 -0
  154. package/dist/node/fs/sync.d.ts.map +1 -0
  155. package/dist/node/fs/sync.js +348 -0
  156. package/dist/node/fs/sync.js.map +1 -0
  157. package/dist/node/hashes.d.ts +15 -0
  158. package/dist/node/hashes.d.ts.map +1 -0
  159. package/dist/node/hashes.js +195 -0
  160. package/dist/node/hashes.js.map +1 -0
  161. package/dist/node/http/client.d.ts +35 -0
  162. package/dist/node/http/client.d.ts.map +1 -0
  163. package/dist/node/http/client.js +161 -0
  164. package/dist/node/http/client.js.map +1 -0
  165. package/dist/node/http/index.d.ts +5 -0
  166. package/dist/node/http/index.d.ts.map +1 -0
  167. package/dist/node/http/index.js +125 -0
  168. package/dist/node/http/index.js.map +1 -0
  169. package/dist/node/http/server.d.ts +135 -0
  170. package/dist/node/http/server.d.ts.map +1 -0
  171. package/dist/node/http/server.js +308 -0
  172. package/dist/node/http/server.js.map +1 -0
  173. package/dist/node/http/status.d.ts +3 -0
  174. package/dist/node/http/status.d.ts.map +1 -0
  175. package/dist/node/http/status.js +13 -0
  176. package/dist/node/http/status.js.map +1 -0
  177. package/dist/node/inspect.d.ts +22 -0
  178. package/dist/node/inspect.d.ts.map +1 -0
  179. package/dist/node/inspect.js +172 -0
  180. package/dist/node/inspect.js.map +1 -0
  181. package/dist/node/loader.d.ts +91 -0
  182. package/dist/node/loader.d.ts.map +1 -0
  183. package/dist/node/loader.js +265 -0
  184. package/dist/node/loader.js.map +1 -0
  185. package/dist/node/loop.d.ts +71 -0
  186. package/dist/node/loop.d.ts.map +1 -0
  187. package/dist/node/loop.js +189 -0
  188. package/dist/node/loop.js.map +1 -0
  189. package/dist/node/misc.d.ts +10 -0
  190. package/dist/node/misc.d.ts.map +1 -0
  191. package/dist/node/misc.js +256 -0
  192. package/dist/node/misc.js.map +1 -0
  193. package/dist/node/path.d.ts +14 -0
  194. package/dist/node/path.d.ts.map +1 -0
  195. package/dist/node/path.js +128 -0
  196. package/dist/node/path.js.map +1 -0
  197. package/dist/node/process.d.ts +31 -0
  198. package/dist/node/process.d.ts.map +1 -0
  199. package/dist/node/process.js +309 -0
  200. package/dist/node/process.js.map +1 -0
  201. package/dist/node/program.d.ts +19 -0
  202. package/dist/node/program.d.ts.map +1 -0
  203. package/dist/node/program.js +165 -0
  204. package/dist/node/program.js.map +1 -0
  205. package/dist/node/readline.d.ts +2 -0
  206. package/dist/node/readline.d.ts.map +1 -0
  207. package/dist/node/readline.js +155 -0
  208. package/dist/node/readline.js.map +1 -0
  209. package/dist/node/resolve.d.ts +45 -0
  210. package/dist/node/resolve.d.ts.map +1 -0
  211. package/dist/node/resolve.js +206 -0
  212. package/dist/node/resolve.js.map +1 -0
  213. package/dist/node/runtime.d.ts +40 -0
  214. package/dist/node/runtime.d.ts.map +1 -0
  215. package/dist/node/runtime.js +149 -0
  216. package/dist/node/runtime.js.map +1 -0
  217. package/dist/node/stream/index.d.ts +52 -0
  218. package/dist/node/stream/index.d.ts.map +1 -0
  219. package/dist/node/stream/index.js +184 -0
  220. package/dist/node/stream/index.js.map +1 -0
  221. package/dist/node/stream/readable.d.ts +83 -0
  222. package/dist/node/stream/readable.d.ts.map +1 -0
  223. package/dist/node/stream/readable.js +325 -0
  224. package/dist/node/stream/readable.js.map +1 -0
  225. package/dist/node/stream/writable.d.ts +80 -0
  226. package/dist/node/stream/writable.d.ts.map +1 -0
  227. package/dist/node/stream/writable.js +224 -0
  228. package/dist/node/stream/writable.js.map +1 -0
  229. package/dist/node/urlqs.d.ts +22 -0
  230. package/dist/node/urlqs.d.ts.map +1 -0
  231. package/dist/node/urlqs.js +165 -0
  232. package/dist/node/urlqs.js.map +1 -0
  233. package/dist/node/util.d.ts +37 -0
  234. package/dist/node/util.d.ts.map +1 -0
  235. package/dist/node/util.js +160 -0
  236. package/dist/node/util.js.map +1 -0
  237. package/dist/node/zlib.d.ts +2 -0
  238. package/dist/node/zlib.d.ts.map +1 -0
  239. package/dist/node/zlib.js +133 -0
  240. package/dist/node/zlib.js.map +1 -0
  241. package/dist/packageCdn.d.ts +40 -0
  242. package/dist/packageCdn.d.ts.map +1 -1
  243. package/dist/packageCdn.js +54 -7
  244. package/dist/packageCdn.js.map +1 -1
  245. package/dist/projectConfig.d.ts +6 -2
  246. package/dist/projectConfig.d.ts.map +1 -1
  247. package/dist/projectConfig.js +32 -8
  248. package/dist/projectConfig.js.map +1 -1
  249. package/dist/shell/builtins.d.ts +23 -0
  250. package/dist/shell/builtins.d.ts.map +1 -0
  251. package/dist/shell/builtins.js +131 -0
  252. package/dist/shell/builtins.js.map +1 -0
  253. package/dist/shell/context.d.ts +41 -0
  254. package/dist/shell/context.d.ts.map +1 -0
  255. package/dist/shell/context.js +65 -0
  256. package/dist/shell/context.js.map +1 -0
  257. package/dist/shell/devHandoff.d.ts +18 -0
  258. package/dist/shell/devHandoff.d.ts.map +1 -0
  259. package/dist/shell/devHandoff.js +36 -0
  260. package/dist/shell/devHandoff.js.map +1 -0
  261. package/dist/shell/exec.d.ts +67 -0
  262. package/dist/shell/exec.d.ts.map +1 -0
  263. package/dist/shell/exec.js +247 -0
  264. package/dist/shell/exec.js.map +1 -0
  265. package/dist/shell/expand.d.ts +28 -0
  266. package/dist/shell/expand.d.ts.map +1 -0
  267. package/dist/shell/expand.js +149 -0
  268. package/dist/shell/expand.js.map +1 -0
  269. package/dist/shell/fileCommands.d.ts +10 -0
  270. package/dist/shell/fileCommands.d.ts.map +1 -0
  271. package/dist/shell/fileCommands.js +208 -0
  272. package/dist/shell/fileCommands.js.map +1 -0
  273. package/dist/shell/lineEditor.d.ts +43 -0
  274. package/dist/shell/lineEditor.d.ts.map +1 -0
  275. package/dist/shell/lineEditor.js +234 -0
  276. package/dist/shell/lineEditor.js.map +1 -0
  277. package/dist/shell/npm.d.ts +6 -0
  278. package/dist/shell/npm.d.ts.map +1 -0
  279. package/dist/shell/npm.js +234 -0
  280. package/dist/shell/npm.js.map +1 -0
  281. package/dist/shell/parse.d.ts +73 -0
  282. package/dist/shell/parse.d.ts.map +1 -0
  283. package/dist/shell/parse.js +300 -0
  284. package/dist/shell/parse.js.map +1 -0
  285. package/dist/shell/program.d.ts +12 -0
  286. package/dist/shell/program.d.ts.map +1 -0
  287. package/dist/shell/program.js +219 -0
  288. package/dist/shell/program.js.map +1 -0
  289. package/dist/shell/textCommands.d.ts +15 -0
  290. package/dist/shell/textCommands.d.ts.map +1 -0
  291. package/dist/shell/textCommands.js +185 -0
  292. package/dist/shell/textCommands.js.map +1 -0
  293. package/dist/styleModules.d.ts +6 -0
  294. package/dist/styleModules.d.ts.map +1 -1
  295. package/dist/styleModules.js +14 -4
  296. package/dist/styleModules.js.map +1 -1
  297. package/dist/svelteCompiler.d.ts +28 -0
  298. package/dist/svelteCompiler.d.ts.map +1 -0
  299. package/dist/svelteCompiler.js +13 -0
  300. package/dist/svelteCompiler.js.map +1 -0
  301. package/dist/system/commands.d.ts +26 -0
  302. package/dist/system/commands.d.ts.map +1 -0
  303. package/dist/system/commands.js +53 -0
  304. package/dist/system/commands.js.map +1 -0
  305. package/dist/system/index.d.ts +23 -0
  306. package/dist/system/index.d.ts.map +1 -0
  307. package/dist/system/index.js +16 -0
  308. package/dist/system/index.js.map +1 -0
  309. package/dist/system/kernel.d.ts +54 -0
  310. package/dist/system/kernel.d.ts.map +1 -0
  311. package/dist/system/kernel.js +81 -0
  312. package/dist/system/kernel.js.map +1 -0
  313. package/dist/system/ports.d.ts +32 -0
  314. package/dist/system/ports.d.ts.map +1 -0
  315. package/dist/system/ports.js +57 -0
  316. package/dist/system/ports.js.map +1 -0
  317. package/dist/system/process.d.ts +32 -0
  318. package/dist/system/process.d.ts.map +1 -0
  319. package/dist/system/process.js +130 -0
  320. package/dist/system/process.js.map +1 -0
  321. package/dist/system/programs.d.ts +10 -0
  322. package/dist/system/programs.d.ts.map +1 -0
  323. package/dist/system/programs.js +22 -0
  324. package/dist/system/programs.js.map +1 -0
  325. package/dist/system/terminal.d.ts +45 -0
  326. package/dist/system/terminal.d.ts.map +1 -0
  327. package/dist/system/terminal.js +127 -0
  328. package/dist/system/terminal.js.map +1 -0
  329. package/dist/system/types.d.ts +100 -0
  330. package/dist/system/types.d.ts.map +1 -0
  331. package/dist/system/types.js +2 -0
  332. package/dist/system/types.js.map +1 -0
  333. package/dist/vfs.d.ts +28 -4
  334. package/dist/vfs.d.ts.map +1 -1
  335. package/dist/vfs.js +95 -32
  336. package/dist/vfs.js.map +1 -1
  337. package/dist/vueCompiler.d.ts +75 -0
  338. package/dist/vueCompiler.d.ts.map +1 -0
  339. package/dist/vueCompiler.js +67 -0
  340. package/dist/vueCompiler.js.map +1 -0
  341. package/package.json +18 -2
  342. package/src/build.ts +105 -0
  343. package/src/buildHost.ts +154 -0
  344. package/src/buildHtml.ts +101 -0
  345. package/src/bundler.ts +190 -0
  346. package/src/check/acquire.ts +212 -0
  347. package/src/check/compilerHost.ts +138 -0
  348. package/src/check/diagnostics.ts +48 -0
  349. package/src/check/index.ts +28 -0
  350. package/src/check/projects.ts +149 -0
  351. package/src/check/shims.ts +88 -0
  352. package/src/check/typeStore.ts +103 -0
  353. package/src/check/typecheck.ts +134 -0
  354. package/src/compileComponent.ts +21 -0
  355. package/src/compileScript.ts +42 -13
  356. package/src/components.ts +59 -0
  357. package/src/detectProject.ts +18 -6
  358. package/src/devServer.ts +16 -11
  359. package/src/hash.ts +22 -0
  360. package/src/index.ts +35 -6
  361. package/src/installer/bins.ts +64 -0
  362. package/src/installer/index.ts +13 -0
  363. package/src/installer/install.ts +275 -0
  364. package/src/installer/lockfile.ts +146 -0
  365. package/src/installer/registry.ts +175 -0
  366. package/src/installer/semver.ts +190 -0
  367. package/src/installer/spec.ts +53 -0
  368. package/src/installer/tar.ts +155 -0
  369. package/src/installer/tree.ts +236 -0
  370. package/src/node/assert.ts +127 -0
  371. package/src/node/buffer.ts +304 -0
  372. package/src/node/builtins.ts +123 -0
  373. package/src/node/callable.ts +25 -0
  374. package/src/node/childProcess.ts +164 -0
  375. package/src/node/crypto.ts +187 -0
  376. package/src/node/esm.ts +196 -0
  377. package/src/node/events.ts +176 -0
  378. package/src/node/fs/index.ts +277 -0
  379. package/src/node/fs/stats.ts +110 -0
  380. package/src/node/fs/sync.ts +335 -0
  381. package/src/node/hashes.ts +171 -0
  382. package/src/node/http/client.ts +173 -0
  383. package/src/node/http/index.ts +122 -0
  384. package/src/node/http/server.ts +308 -0
  385. package/src/node/http/status.ts +13 -0
  386. package/src/node/inspect.ts +166 -0
  387. package/src/node/loader.ts +293 -0
  388. package/src/node/loop.ts +193 -0
  389. package/src/node/misc.ts +250 -0
  390. package/src/node/path.ts +135 -0
  391. package/src/node/process.ts +324 -0
  392. package/src/node/program.ts +170 -0
  393. package/src/node/readline.ts +157 -0
  394. package/src/node/resolve.ts +216 -0
  395. package/src/node/runtime.ts +184 -0
  396. package/src/node/stream/index.ts +196 -0
  397. package/src/node/stream/readable.ts +345 -0
  398. package/src/node/stream/writable.ts +244 -0
  399. package/src/node/urlqs.ts +162 -0
  400. package/src/node/util.ts +145 -0
  401. package/src/node/zlib.ts +145 -0
  402. package/src/packageCdn.ts +91 -7
  403. package/src/projectConfig.ts +34 -7
  404. package/src/shell/builtins.ts +141 -0
  405. package/src/shell/context.ts +89 -0
  406. package/src/shell/devHandoff.ts +49 -0
  407. package/src/shell/exec.ts +268 -0
  408. package/src/shell/expand.ts +145 -0
  409. package/src/shell/fileCommands.ts +206 -0
  410. package/src/shell/lineEditor.ts +233 -0
  411. package/src/shell/npm.ts +229 -0
  412. package/src/shell/parse.ts +295 -0
  413. package/src/shell/program.ts +223 -0
  414. package/src/shell/textCommands.ts +177 -0
  415. package/src/styleModules.ts +15 -4
  416. package/src/svelteCompiler.ts +31 -0
  417. package/src/system/commands.ts +72 -0
  418. package/src/system/index.ts +22 -0
  419. package/src/system/kernel.ts +106 -0
  420. package/src/system/ports.ts +73 -0
  421. package/src/system/process.ts +158 -0
  422. package/src/system/programs.ts +31 -0
  423. package/src/system/terminal.ts +135 -0
  424. package/src/system/types.ts +103 -0
  425. package/src/vfs.ts +92 -28
  426. package/src/vueCompiler.ts +121 -0
@@ -0,0 +1,162 @@
1
+ /**
2
+ * `url` (WHATWG URL plus the legacy `parse`/`format`/`resolve`) and
3
+ * `querystring`. Legacy `url.parse` is still everywhere in Express-era code
4
+ * (`parseurl`, `send`), so it returns Node's full shape.
5
+ */
6
+
7
+ export function createQuerystringModule(): Record<string, unknown> {
8
+ const escape = (s: string) => encodeURIComponent(s);
9
+ const unescape = (s: string) => {
10
+ try {
11
+ return decodeURIComponent(s);
12
+ } catch {
13
+ return s;
14
+ }
15
+ };
16
+ const stringifyPrimitive = (v: unknown) => (typeof v === 'string' ? v : typeof v === 'number' && Number.isFinite(v) ? String(v) : typeof v === 'boolean' || typeof v === 'bigint' ? String(v) : '');
17
+ const parse = (str: string, sep = '&', eq = '=', options?: { maxKeys?: number; decodeURIComponent?: (s: string) => string }) => {
18
+ const out: Record<string, string | string[]> = Object.create(null);
19
+ if (typeof str !== 'string' || !str) return out;
20
+ const decode = options?.decodeURIComponent ?? unescape;
21
+ const parts = str.split(sep);
22
+ const max = options?.maxKeys ?? 1000;
23
+ for (const part of max > 0 ? parts.slice(0, max) : parts) {
24
+ if (!part) continue;
25
+ const idx = part.indexOf(eq);
26
+ const key = decode((idx >= 0 ? part.slice(0, idx) : part).replace(/\+/g, ' '));
27
+ const value = idx >= 0 ? decode(part.slice(idx + eq.length).replace(/\+/g, ' ')) : '';
28
+ const existing = out[key];
29
+ if (existing === undefined) out[key] = value;
30
+ else if (Array.isArray(existing)) existing.push(value);
31
+ else out[key] = [existing, value];
32
+ }
33
+ return out;
34
+ };
35
+ const stringify = (obj: Record<string, unknown>, sep = '&', eq = '=', options?: { encodeURIComponent?: (s: string) => string }) => {
36
+ const encode = options?.encodeURIComponent ?? escape;
37
+ if (!obj || typeof obj !== 'object') return '';
38
+ return Object.keys(obj)
39
+ .map((k) => {
40
+ const v = obj[k];
41
+ const ks = encode(stringifyPrimitive(k)) + eq;
42
+ return Array.isArray(v) ? v.map((x) => ks + encode(stringifyPrimitive(x))).join(sep) : ks + encode(stringifyPrimitive(v));
43
+ })
44
+ .filter(Boolean)
45
+ .join(sep);
46
+ };
47
+ return { parse, decode: parse, stringify, encode: stringify, escape, unescape };
48
+ }
49
+
50
+ export interface LegacyUrl {
51
+ protocol: string | null;
52
+ slashes: boolean | null;
53
+ auth: string | null;
54
+ host: string | null;
55
+ port: string | null;
56
+ hostname: string | null;
57
+ hash: string | null;
58
+ search: string | null;
59
+ query: string | Record<string, unknown> | null;
60
+ pathname: string | null;
61
+ path: string | null;
62
+ href: string;
63
+ }
64
+
65
+ export function createUrlModule(qs: Record<string, any>): Record<string, unknown> {
66
+ function parse(input: string, parseQueryString = false, slashesDenoteHost = false): LegacyUrl {
67
+ let rest = input.trim();
68
+ const out: LegacyUrl = { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: null, query: null, pathname: null, path: null, href: '' };
69
+ const hashAt = rest.indexOf('#');
70
+ if (hashAt >= 0) {
71
+ out.hash = rest.slice(hashAt);
72
+ rest = rest.slice(0, hashAt);
73
+ }
74
+ const queryAt = rest.indexOf('?');
75
+ if (queryAt >= 0) {
76
+ out.search = rest.slice(queryAt);
77
+ out.query = rest.slice(queryAt + 1);
78
+ rest = rest.slice(0, queryAt);
79
+ } else if (parseQueryString) {
80
+ out.search = '';
81
+ out.query = {};
82
+ }
83
+ const proto = /^([a-z][a-z0-9.+-]*:)/i.exec(rest);
84
+ if (proto) {
85
+ out.protocol = proto[1]!.toLowerCase();
86
+ rest = rest.slice(proto[1]!.length);
87
+ }
88
+ if ((proto || slashesDenoteHost) && rest.startsWith('//')) {
89
+ out.slashes = true;
90
+ rest = rest.slice(2);
91
+ const end = rest.search(/[/]/);
92
+ let authority = end >= 0 ? rest.slice(0, end) : rest;
93
+ rest = end >= 0 ? rest.slice(end) : '';
94
+ const at = authority.lastIndexOf('@');
95
+ if (at >= 0) {
96
+ out.auth = decodeURIComponent(authority.slice(0, at));
97
+ authority = authority.slice(at + 1);
98
+ }
99
+ out.host = authority.toLowerCase();
100
+ const portMatch = /:(\d*)$/.exec(out.host);
101
+ if (portMatch) {
102
+ out.port = portMatch[1] || null;
103
+ out.hostname = out.host.slice(0, -portMatch[0].length);
104
+ } else out.hostname = out.host;
105
+ if (out.hostname.startsWith('[') && out.hostname.endsWith(']')) out.hostname = out.hostname.slice(1, -1);
106
+ if (!rest && out.protocol && /^(https?|ftp|wss?|file):$/.test(out.protocol)) rest = '/';
107
+ }
108
+ out.pathname = rest || (out.slashes ? '/' : null);
109
+ if (parseQueryString && typeof out.query === 'string') out.query = qs.parse(out.query);
110
+ out.path = (out.pathname ?? '') + (out.search ?? '') || null;
111
+ out.href = format(out);
112
+ return out;
113
+ }
114
+
115
+ function format(obj: Partial<LegacyUrl> | URL | string): string {
116
+ if (typeof obj === 'string') return format(parse(obj));
117
+ if (obj instanceof URL) return obj.href;
118
+ const protocol = obj.protocol ? (obj.protocol.endsWith(':') ? obj.protocol : obj.protocol + ':') : '';
119
+ let host = '';
120
+ if (obj.host) host = (obj.auth ? encodeURIComponent(obj.auth).replace(/%3A/i, ':') + '@' : '') + obj.host;
121
+ else if (obj.hostname) host = (obj.auth ? obj.auth + '@' : '') + (obj.hostname.includes(':') ? `[${obj.hostname}]` : obj.hostname) + (obj.port ? ':' + obj.port : '');
122
+ let search = obj.search ?? '';
123
+ if (!search && obj.query && typeof obj.query === 'object') {
124
+ const s = qs.stringify(obj.query);
125
+ if (s) search = '?' + s;
126
+ } else if (search && !search.startsWith('?')) search = '?' + search;
127
+ const slashes = obj.slashes || (host && /^(https?|ftp|wss?|file):$/.test(protocol)) ? '//' : '';
128
+ let pathname = obj.pathname ?? '';
129
+ if (host && pathname && !pathname.startsWith('/')) pathname = '/' + pathname;
130
+ const hash = obj.hash ? (obj.hash.startsWith('#') ? obj.hash : '#' + obj.hash) : '';
131
+ return `${protocol}${slashes}${host}${pathname}${search}${hash}`;
132
+ }
133
+
134
+ function resolve(from: string, to: string): string {
135
+ const base = new URL(from, 'resolve://');
136
+ const resolved = new URL(to, base);
137
+ if (resolved.protocol === 'resolve:') {
138
+ const { pathname, search, hash } = resolved;
139
+ return pathname + search + hash;
140
+ }
141
+ return resolved.href;
142
+ }
143
+
144
+ return {
145
+ URL,
146
+ URLSearchParams,
147
+ parse,
148
+ format,
149
+ resolve,
150
+ resolveObject: (from: string, to: string) => parse(resolve(from, to)),
151
+ fileURLToPath: (url: string | URL) => {
152
+ const u = typeof url === 'string' ? new URL(url) : url;
153
+ if (u.protocol !== 'file:') throw Object.assign(new TypeError('The URL must be of scheme file'), { code: 'ERR_INVALID_URL_SCHEME' });
154
+ return decodeURIComponent(u.pathname);
155
+ },
156
+ pathToFileURL: (path: string) => new URL('file://' + encodeURI(path).replace(/[?#]/g, encodeURIComponent)),
157
+ domainToASCII: (d: string) => d,
158
+ domainToUnicode: (d: string) => d,
159
+ urlToHttpOptions: (u: URL) => ({ protocol: u.protocol, hostname: u.hostname, hash: u.hash, search: u.search, pathname: u.pathname, path: u.pathname + u.search, href: u.href, port: u.port ? Number(u.port) : undefined }),
160
+ Url: function Url() {},
161
+ };
162
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Node's `util` module: formatting and inspection (inspect.ts), the classic
3
+ * helpers (`inherits`, `promisify`, `deprecate`, `callbackify`), `types` and
4
+ * `isDeepStrictEqual`.
5
+ */
6
+ import { format, inspect } from './inspect.js';
7
+
8
+ export const promisifyCustom = Symbol.for('nodejs.util.promisify.custom');
9
+
10
+ export function promisify(fn: (...args: any[]) => unknown): (...args: any[]) => Promise<any> {
11
+ if (typeof fn !== 'function') throw new TypeError('The "original" argument must be of type function');
12
+ const custom = (fn as any)[promisifyCustom];
13
+ if (typeof custom === 'function') return custom;
14
+ function promisified(this: unknown, ...args: unknown[]) {
15
+ return new Promise((resolve, reject) => {
16
+ fn.call(this, ...args, (error: unknown, ...values: unknown[]) => {
17
+ if (error) reject(error);
18
+ else resolve(values.length > 1 ? values : values[0]);
19
+ });
20
+ });
21
+ }
22
+ Object.setPrototypeOf(promisified, Object.getPrototypeOf(fn));
23
+ return Object.defineProperties(promisified, Object.getOwnPropertyDescriptors(fn));
24
+ }
25
+ promisify.custom = promisifyCustom;
26
+
27
+ export function inherits(ctor: { prototype: object; super_?: unknown }, superCtor: { prototype: object }): void {
28
+ if (!superCtor?.prototype) throw new TypeError('The "superCtor.prototype" property must be of type object');
29
+ ctor.super_ = superCtor;
30
+ Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
31
+ }
32
+
33
+ export function isDeepStrictEqual(a: unknown, b: unknown, seen = new Map<object, object>()): boolean {
34
+ if (Object.is(a, b)) return true;
35
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;
36
+ if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) return false;
37
+ if (seen.get(a) === b) return true;
38
+ seen.set(a, b);
39
+ if (a instanceof Date) return a.getTime() === (b as Date).getTime();
40
+ if (a instanceof RegExp) return String(a) === String(b);
41
+ if (a instanceof Map) {
42
+ const m = b as Map<unknown, unknown>;
43
+ if (a.size !== m.size) return false;
44
+ for (const [k, v] of a) if (!m.has(k) || !isDeepStrictEqual(v, m.get(k), seen)) return false;
45
+ return true;
46
+ }
47
+ if (a instanceof Set) {
48
+ const s = b as Set<unknown>;
49
+ if (a.size !== s.size) return false;
50
+ for (const v of a) if (!s.has(v) && ![...s].some((w) => isDeepStrictEqual(v, w, seen))) return false;
51
+ return true;
52
+ }
53
+ if (ArrayBuffer.isView(a)) {
54
+ const x = a as unknown as ArrayLike<number>;
55
+ const y = b as unknown as ArrayLike<number>;
56
+ if (x.length !== y.length) return false;
57
+ for (let i = 0; i < x.length; i++) if (!Object.is(x[i], y[i])) return false;
58
+ return true;
59
+ }
60
+ const ka = Object.keys(a);
61
+ const kb = Object.keys(b);
62
+ if (ka.length !== kb.length) return false;
63
+ return ka.every((k) => Object.prototype.hasOwnProperty.call(b, k) && isDeepStrictEqual((a as any)[k], (b as any)[k], seen));
64
+ }
65
+
66
+ const tag = (v: unknown) => Object.prototype.toString.call(v).slice(8, -1);
67
+
68
+ export const types = {
69
+ isPromise: (v: unknown) => v instanceof Promise,
70
+ isDate: (v: unknown) => v instanceof Date,
71
+ isRegExp: (v: unknown) => v instanceof RegExp,
72
+ isMap: (v: unknown) => v instanceof Map,
73
+ isSet: (v: unknown) => v instanceof Set,
74
+ isWeakMap: (v: unknown) => v instanceof WeakMap,
75
+ isWeakSet: (v: unknown) => v instanceof WeakSet,
76
+ isNativeError: (v: unknown) => v instanceof Error,
77
+ isTypedArray: (v: unknown) => ArrayBuffer.isView(v) && !(v instanceof DataView),
78
+ isUint8Array: (v: unknown) => v instanceof Uint8Array,
79
+ isArrayBuffer: (v: unknown) => v instanceof ArrayBuffer,
80
+ isAnyArrayBuffer: (v: unknown) => v instanceof ArrayBuffer || tag(v) === 'SharedArrayBuffer',
81
+ isArrayBufferView: (v: unknown) => ArrayBuffer.isView(v),
82
+ isDataView: (v: unknown) => v instanceof DataView,
83
+ isAsyncFunction: (v: unknown) => tag(v) === 'AsyncFunction' || tag(v) === 'AsyncGeneratorFunction',
84
+ isGeneratorFunction: (v: unknown) => tag(v) === 'GeneratorFunction' || tag(v) === 'AsyncGeneratorFunction',
85
+ isGeneratorObject: (v: unknown) => tag(v) === 'Generator',
86
+ isBoxedPrimitive: (v: unknown) => v instanceof Number || v instanceof String || v instanceof Boolean,
87
+ isProxy: () => false,
88
+ isExternal: () => false,
89
+ isModuleNamespaceObject: (v: unknown) => tag(v) === 'Module',
90
+ };
91
+
92
+ export function createUtilModule(env: () => Record<string, string | undefined>, warn: (message: string) => void): Record<string, unknown> {
93
+ const warned = new Set<string>();
94
+ return {
95
+ format,
96
+ formatWithOptions: (_options: unknown, ...args: unknown[]) => format(...args),
97
+ inspect,
98
+ inherits,
99
+ promisify,
100
+ callbackify(fn: (...args: any[]) => Promise<unknown>) {
101
+ return function (this: unknown, ...args: any[]) {
102
+ const callback = args.pop() as (error: unknown, value?: unknown) => void;
103
+ fn.apply(this, args).then((value) => callback(null, value), (error) => callback(error ?? new Error('Promise was rejected with a falsy value')));
104
+ };
105
+ },
106
+ deprecate<T extends (...args: any[]) => unknown>(fn: T, message: string, code?: string): T {
107
+ return function (this: unknown, ...args: unknown[]) {
108
+ const key = code ?? message;
109
+ if (!warned.has(key)) {
110
+ warned.add(key);
111
+ warn(`(node) [${code ?? 'DEP'}] DeprecationWarning: ${message}`);
112
+ }
113
+ return fn.apply(this, args);
114
+ } as T;
115
+ },
116
+ debuglog(section: string) {
117
+ const enabled = new RegExp(`\\b${section}\\b`, 'i').test(env().NODE_DEBUG ?? '');
118
+ const log = (...args: unknown[]) => enabled && warn(`${section.toUpperCase()}: ${format(...args)}`);
119
+ log.enabled = enabled;
120
+ return log;
121
+ },
122
+ isDeepStrictEqual: (a: unknown, b: unknown) => isDeepStrictEqual(a, b),
123
+ types,
124
+ TextEncoder,
125
+ TextDecoder,
126
+ stripVTControlCharacters: (s: string) => s.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, ''),
127
+ styleText: (_style: unknown, text: string) => text,
128
+ toUSVString: (s: string) => s.replace(/[\uD800-\uDFFF]/g, '�'),
129
+ isArray: Array.isArray,
130
+ isBoolean: (v: unknown) => typeof v === 'boolean',
131
+ isNull: (v: unknown) => v === null,
132
+ isNullOrUndefined: (v: unknown) => v == null,
133
+ isNumber: (v: unknown) => typeof v === 'number',
134
+ isString: (v: unknown) => typeof v === 'string',
135
+ isSymbol: (v: unknown) => typeof v === 'symbol',
136
+ isUndefined: (v: unknown) => v === undefined,
137
+ isRegExp: types.isRegExp,
138
+ isObject: (v: unknown) => v !== null && typeof v === 'object',
139
+ isDate: types.isDate,
140
+ isError: types.isNativeError,
141
+ isFunction: (v: unknown) => typeof v === 'function',
142
+ isPrimitive: (v: unknown) => v === null || (typeof v !== 'object' && typeof v !== 'function'),
143
+ isBuffer: (v: unknown) => (v as { constructor?: { name?: string } })?.constructor?.name === 'Buffer',
144
+ };
145
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * `zlib` over fflate: gzip/deflate/raw deflate in sync, callback, promise-less
3
+ * and streaming forms (compression middleware pipes through `createGzip`).
4
+ * Brotli is not available and says so.
5
+ */
6
+ import * as fflate from 'fflate';
7
+ import { Buffer } from './buffer.js';
8
+ import { Transform } from './stream/index.js';
9
+
10
+ type Input = string | ArrayBufferView | ArrayBuffer;
11
+ type Options = { level?: number };
12
+
13
+ const bytes = (input: Input): Uint8Array =>
14
+ typeof input === 'string' ? Buffer.from(input) : input instanceof ArrayBuffer ? new Uint8Array(input) : new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
15
+
16
+ const level = (options?: Options) => (options?.level === undefined || options.level < 0 ? 6 : Math.min(9, options.level)) as fflate.DeflateOptions['level'];
17
+
18
+ const SYNC: Record<string, (data: Uint8Array, options?: Options) => Uint8Array> = {
19
+ gzip: (d, o) => fflate.gzipSync(d, { level: level(o) }),
20
+ gunzip: (d) => fflate.gunzipSync(d),
21
+ deflate: (d, o) => fflate.zlibSync(d, { level: level(o) }),
22
+ inflate: (d) => fflate.unzlibSync(d),
23
+ deflateRaw: (d, o) => fflate.deflateSync(d, { level: level(o) }),
24
+ inflateRaw: (d) => fflate.inflateSync(d),
25
+ unzip: (d) => fflate.decompressSync(d),
26
+ };
27
+
28
+ type StreamCtor = new (cb?: fflate.FlateStreamHandler) => { push(chunk: Uint8Array, final?: boolean): void; ondata: fflate.FlateStreamHandler };
29
+ const STREAMS: Record<string, (options?: Options) => InstanceType<StreamCtor>> = {
30
+ Gzip: (o) => new fflate.Gzip({ level: level(o) }),
31
+ Gunzip: () => new fflate.Gunzip(),
32
+ Deflate: (o) => new fflate.Zlib({ level: level(o) }),
33
+ Inflate: () => new fflate.Unzlib(),
34
+ DeflateRaw: (o) => new fflate.Deflate({ level: level(o) }),
35
+ InflateRaw: () => new fflate.Inflate(),
36
+ Unzip: () => new fflate.Decompress() as unknown as InstanceType<StreamCtor>,
37
+ };
38
+
39
+ function zlibError(error: unknown): Error {
40
+ const message = error instanceof Error ? error.message : String(error);
41
+ return Object.assign(new Error(message || 'invalid compressed data'), { code: 'Z_DATA_ERROR', errno: -3 });
42
+ }
43
+
44
+ class ZlibStream extends Transform {
45
+ private readonly engine: InstanceType<StreamCtor>;
46
+ bytesWritten = 0;
47
+
48
+ constructor(kind: string, options?: Options) {
49
+ super();
50
+ this.engine = STREAMS[kind]!(options);
51
+ this.engine.ondata = (data: Uint8Array) => {
52
+ if (data.length) this.push(Buffer.from(data));
53
+ };
54
+ }
55
+
56
+ override _transform(chunk: Uint8Array, _encoding: string, callback: (error?: Error | null) => void): void {
57
+ try {
58
+ this.bytesWritten += chunk.length;
59
+ this.engine.push(chunk, false);
60
+ callback();
61
+ } catch (error) {
62
+ callback(zlibError(error));
63
+ }
64
+ }
65
+
66
+ override _flush(callback: (error?: Error | null) => void): void {
67
+ try {
68
+ this.engine.push(new Uint8Array(0), true);
69
+ callback();
70
+ } catch (error) {
71
+ callback(zlibError(error));
72
+ }
73
+ }
74
+
75
+ flush(_kind?: unknown, callback?: () => void): void {
76
+ callback?.();
77
+ }
78
+
79
+ params(_level: number, _strategy: number, callback?: () => void): void {
80
+ callback?.();
81
+ }
82
+
83
+ close(callback?: () => void): void {
84
+ this.destroy();
85
+ callback?.();
86
+ }
87
+ }
88
+
89
+ const noBrotli = () => {
90
+ throw Object.assign(new Error('Brotli is not available in the browser runtime'), { code: 'ERR_FEATURE_UNAVAILABLE_ON_PLATFORM' });
91
+ };
92
+
93
+ export function createZlibModule(): Record<string, unknown> {
94
+ const mod: Record<string, unknown> = {
95
+ constants: {
96
+ Z_NO_FLUSH: 0, Z_PARTIAL_FLUSH: 1, Z_SYNC_FLUSH: 2, Z_FULL_FLUSH: 3, Z_FINISH: 4, Z_BLOCK: 5,
97
+ Z_OK: 0, Z_STREAM_END: 1, Z_NEED_DICT: 2, Z_ERRNO: -1, Z_STREAM_ERROR: -2, Z_DATA_ERROR: -3, Z_BUF_ERROR: -5,
98
+ Z_NO_COMPRESSION: 0, Z_BEST_SPEED: 1, Z_BEST_COMPRESSION: 9, Z_DEFAULT_COMPRESSION: -1,
99
+ Z_FILTERED: 1, Z_HUFFMAN_ONLY: 2, Z_RLE: 3, Z_FIXED: 4, Z_DEFAULT_STRATEGY: 0,
100
+ BROTLI_OPERATION_PROCESS: 0, BROTLI_OPERATION_FLUSH: 1, BROTLI_OPERATION_FINISH: 2, BROTLI_PARAM_QUALITY: 1,
101
+ },
102
+ brotliCompressSync: noBrotli,
103
+ brotliDecompressSync: noBrotli,
104
+ brotliCompress: noBrotli,
105
+ brotliDecompress: noBrotli,
106
+ createBrotliCompress: noBrotli,
107
+ createBrotliDecompress: noBrotli,
108
+ crc32: (data: Input, value = 0) => {
109
+ let crc = ~value >>> 0;
110
+ for (const byte of bytes(data)) {
111
+ crc ^= byte;
112
+ for (let k = 0; k < 8; k++) crc = crc & 1 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1;
113
+ }
114
+ return ~crc >>> 0;
115
+ },
116
+ };
117
+ for (const [name, fn] of Object.entries(SYNC)) {
118
+ mod[`${name}Sync`] = (input: Input, options?: Options) => {
119
+ try {
120
+ return Buffer.from(fn(bytes(input), options));
121
+ } catch (error) {
122
+ throw zlibError(error);
123
+ }
124
+ };
125
+ mod[name] = (input: Input, options: Options | ((e: Error | null, r?: Buffer) => void), callback?: (e: Error | null, r?: Buffer) => void) => {
126
+ const cb = (typeof options === 'function' ? options : callback)!;
127
+ queueMicrotask(() => {
128
+ try {
129
+ cb(null, Buffer.from(fn(bytes(input), typeof options === 'object' ? options : undefined)));
130
+ } catch (error) {
131
+ cb(zlibError(error));
132
+ }
133
+ });
134
+ };
135
+ }
136
+ for (const kind of Object.keys(STREAMS)) {
137
+ mod[`create${kind}`] = (options?: Options) => new ZlibStream(kind, options);
138
+ mod[kind] = class extends ZlibStream {
139
+ constructor(options?: Options) {
140
+ super(kind, options);
141
+ }
142
+ };
143
+ }
144
+ return mod;
145
+ }
package/src/packageCdn.ts CHANGED
@@ -8,6 +8,28 @@ export interface PackageCdn {
8
8
  urlFor(name: string, subpath: string): string;
9
9
  }
10
10
 
11
+ /**
12
+ * Makes the CDN for one project, from its dependency ranges. `dev` is true for the
13
+ * dev server and false for a production build, so a factory can pick development
14
+ * or production package builds (React's readable errors vs its small bundle).
15
+ * It may be async: the esm.sh one loads package metadata first.
16
+ */
17
+ export type PackageCdnFactory = (
18
+ dependencies: Record<string, string>,
19
+ options: { dev: boolean },
20
+ ) => PackageCdn | Promise<PackageCdn>;
21
+
22
+ /** The package.json fields that say which other packages a package imports. */
23
+ export interface PackageDependencyFields {
24
+ dependencies?: Record<string, string>;
25
+ peerDependencies?: Record<string, string>;
26
+ optionalDependencies?: Record<string, string>;
27
+ }
28
+
29
+ /** esm.sh, pinned to the project's ranges, with each declared package's manifest loaded. */
30
+ export const esmShCdnFactory: PackageCdnFactory = async (dependencies, { dev }) =>
31
+ createEsmShCdn({ dependencies, dev, manifests: await loadPackageManifests(dependencies) });
32
+
11
33
  export interface EsmShOptions {
12
34
  /** Defaults to https://esm.sh. Any esm.sh-compatible server works. */
13
35
  origin?: string;
@@ -15,34 +37,96 @@ export interface EsmShOptions {
15
37
  dependencies?: Record<string, string>;
16
38
  /** Serve development builds (readable React errors). Default true. */
17
39
  dev?: boolean;
40
+ /**
41
+ * Each declared package's own dependency fields, by name. They decide which pins
42
+ * go on that package's URL (see `urlFor`). A declared package missing here falls
43
+ * back to carrying every other pin.
44
+ */
45
+ manifests?: Record<string, PackageDependencyFields>;
18
46
  }
19
47
 
20
48
  /** A range the CDN can't fetch (`workspace:*`, `file:../x`, `link:`, git URLs). */
21
- function isRegistryRange(range: string): boolean {
49
+ export function isRegistryRange(range: string): boolean {
22
50
  return !/^(workspace|file|link|portal|git\+|git:|github:|https?:)/.test(range) && !range.includes('/');
23
51
  }
24
52
 
53
+ function importsPackage(manifest: PackageDependencyFields, name: string): boolean {
54
+ return [manifest.dependencies, manifest.peerDependencies, manifest.optionalDependencies].some((field) => !!field && name in field);
55
+ }
56
+
25
57
  export function createEsmShCdn(options: EsmShOptions = {}): PackageCdn {
26
58
  const origin = (options.origin ?? 'https://esm.sh').replace(/\/+$/, '');
27
59
  const dependencies = options.dependencies ?? {};
60
+ const manifests = options.manifests ?? {};
28
61
  const dev = options.dev ?? true;
29
62
 
30
- // Pin every declared dependency into each package's own graph, so `react-dom`
31
- // and the app share ONE `react` — two copies is the classic "invalid hook call".
32
63
  const pinned = Object.entries(dependencies)
33
64
  .filter(([, range]) => isRegistryRange(range))
34
- .map(([name, range]) => `${name}@${range}`)
35
- .sort();
65
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
36
66
 
37
67
  return {
38
68
  urlFor(name, subpath) {
39
69
  const range = dependencies[name];
40
- const versioned = range && isRegistryRange(range) ? `${name}@${range}` : name;
70
+ const declared = !!range && isRegistryRange(range);
71
+ const versioned = declared ? `${name}@${range}` : name;
72
+ // ONE React means the app must import the very module esm.sh links a package's
73
+ // own imports to. When esm.sh builds `react-dom?deps=react@x`, its `import
74
+ // 'react'` becomes `react@x` pinned with only the deps REACT itself imports
75
+ // (none), i.e. the plain build. Pinning every other declared package onto
76
+ // `react` too made the app load a second `?deps=react-dom,…` copy, and its
77
+ // first `useState` read a null dispatcher. So a declared package carries only
78
+ // the pins it imports. An undeclared one (nothing links to it by name) and one
79
+ // whose manifest could not load carry every pin, which is what dedupes the
80
+ // packages THEY import.
81
+ const manifest = declared ? manifests[name] : undefined;
82
+ const deps = pinned
83
+ .filter(([other]) => other !== name && (!manifest || importsPackage(manifest, other)))
84
+ .map(([other, otherRange]) => `${other}@${otherRange}`);
41
85
  const params: string[] = [];
42
- const deps = pinned.filter((entry) => !entry.startsWith(name + '@'));
43
86
  if (deps.length) params.push('deps=' + deps.map(encodeURIComponent).join(','));
44
87
  if (dev) params.push('dev');
45
88
  return `${origin}/${versioned}${subpath}${params.length ? '?' + params.join('&') : ''}`;
46
89
  },
47
90
  };
48
91
  }
92
+
93
+ export interface ManifestLoadOptions {
94
+ /** Defaults to https://esm.sh, which serves `<name>@<range>/package.json`. */
95
+ origin?: string;
96
+ fetch?: (url: string) => Promise<{ ok: boolean; json(): Promise<unknown> }>;
97
+ }
98
+
99
+ const manifestCache = new Map<string, Promise<PackageDependencyFields | undefined>>();
100
+
101
+ /**
102
+ * The dependency fields of every declared registry package, fetched in parallel and
103
+ * kept for the session (a range resolves the same way for its lifetime). A package
104
+ * whose manifest cannot be fetched is simply absent, and `createEsmShCdn` falls
105
+ * back to pinning everything onto it.
106
+ */
107
+ export async function loadPackageManifests(
108
+ dependencies: Record<string, string>,
109
+ options: ManifestLoadOptions = {},
110
+ ): Promise<Record<string, PackageDependencyFields>> {
111
+ const origin = (options.origin ?? 'https://esm.sh').replace(/\/+$/, '');
112
+ const fetcher = options.fetch ?? (typeof fetch === 'function' ? (url: string) => fetch(url) : undefined);
113
+ if (!fetcher) return {};
114
+ const entries = await Promise.all(
115
+ Object.entries(dependencies)
116
+ .filter(([, range]) => isRegistryRange(range))
117
+ .map(async ([name, range]) => {
118
+ const url = `${origin}/${name}@${range}/package.json`;
119
+ let pending = manifestCache.get(url);
120
+ if (!pending) {
121
+ pending = fetcher(url)
122
+ .then(async (res) => (res.ok ? ((await res.json()) as PackageDependencyFields) : undefined))
123
+ .catch(() => undefined);
124
+ manifestCache.set(url, pending);
125
+ }
126
+ return [name, await pending] as const;
127
+ }),
128
+ );
129
+ const loaded: Record<string, PackageDependencyFields> = {};
130
+ for (const [name, manifest] of entries) if (manifest) loaded[name] = manifest;
131
+ return loaded;
132
+ }
@@ -17,8 +17,18 @@ export const CONFIG_FILES = [
17
17
  '/.env.local',
18
18
  '/.env.development',
19
19
  '/.env.development.local',
20
+ '/.env.production',
21
+ '/.env.production.local',
20
22
  ] as const;
21
23
 
24
+ /** Which `.env.<mode>` files apply: the dev server reads development, a build production. */
25
+ export type BuildMode = 'development' | 'production';
26
+
27
+ /** Vite's load order — later files win. */
28
+ export function envFiles(mode: BuildMode): string[] {
29
+ return ['/.env', '/.env.local', `/.env.${mode}`, `/.env.${mode}.local`];
30
+ }
31
+
22
32
  export interface PathAlias {
23
33
  /** The specifier prefix, without the trailing `*` (`@/`). Exact when `wildcard` is false. */
24
34
  prefix: string;
@@ -83,9 +93,25 @@ function readDependencies(fs: VirtualFileSystem): Record<string, string> {
83
93
  return out;
84
94
  }
85
95
 
96
+ /**
97
+ * The root tsconfig's compiler options. Current Vite templates (React, Vue,
98
+ * Svelte) keep a root `tsconfig.json` with only `references`, and the app's real
99
+ * options — `paths` included — in `tsconfig.app.json`; options missing from the
100
+ * root are taken from the referenced configs, in order.
101
+ */
86
102
  function readCompilerOptions(fs: VirtualFileSystem): Record<string, unknown> {
87
103
  const tsconfig = readJson(fs, '/tsconfig.json') ?? readJson(fs, '/jsconfig.json') ?? {};
88
- return asRecord(tsconfig.compilerOptions);
104
+ const options = { ...asRecord(tsconfig.compilerOptions) };
105
+ const references = Array.isArray(tsconfig.references) ? tsconfig.references : [];
106
+ for (const reference of references) {
107
+ const target = asRecord(reference).path;
108
+ if (typeof target !== 'string') continue;
109
+ const file = target.endsWith('.json') ? join('/', target) : join('/', target, 'tsconfig.json');
110
+ for (const [key, value] of Object.entries(asRecord(readJson(fs, file)?.compilerOptions))) {
111
+ if (!(key in options)) options[key] = value;
112
+ }
113
+ }
114
+ return options;
89
115
  }
90
116
 
91
117
  function readAliases(options: Record<string, unknown>): PathAlias[] {
@@ -131,27 +157,28 @@ export function parseDotenv(text: string): Record<string, string> {
131
157
  return out;
132
158
  }
133
159
 
134
- function readEnv(fs: VirtualFileSystem): Record<string, string> {
160
+ function readEnv(fs: VirtualFileSystem, mode: BuildMode): Record<string, string> {
135
161
  const env: Record<string, string> = {};
136
- for (const file of CONFIG_FILES) {
137
- if (!file.startsWith('/.env')) continue;
162
+ for (const file of envFiles(mode)) {
138
163
  const text = fs.readText(file);
139
164
  if (text !== undefined) Object.assign(env, parseDotenv(text));
140
165
  }
141
166
  return env;
142
167
  }
143
168
 
144
- export function readProjectConfig(fs: VirtualFileSystem): ProjectConfig {
169
+ export function readProjectConfig(fs: VirtualFileSystem, mode: BuildMode = 'development'): ProjectConfig {
145
170
  const options = readCompilerOptions(fs);
146
171
  return {
147
172
  dependencies: readDependencies(fs),
148
173
  aliases: readAliases(options),
149
174
  jsx: readJsx(options),
150
- env: readEnv(fs),
175
+ env: readEnv(fs, mode),
151
176
  };
152
177
  }
153
178
 
154
179
  /** True when a change to `path` invalidates the derived {@link ProjectConfig}. */
155
180
  export function isConfigFile(path: string): boolean {
156
- return (CONFIG_FILES as readonly string[]).includes(normalizePath(path));
181
+ const normalized = normalizePath(path);
182
+ // Any root tsconfig: the root one may reference `tsconfig.app.json` and friends.
183
+ return (CONFIG_FILES as readonly string[]).includes(normalized) || /^\/tsconfig[^/]*\.json$/.test(normalized);
157
184
  }