toiljs 0.0.3 → 0.0.5

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 (360) hide show
  1. package/.idea/prettier.xml +1 -0
  2. package/as-pect.config.js +1 -1
  3. package/build/backend/.tsbuildinfo +1 -1
  4. package/build/backend/index.js +1 -2
  5. package/build/cli/.tsbuildinfo +1 -1
  6. package/build/cli/configure.d.ts +15 -0
  7. package/build/cli/configure.js +201 -0
  8. package/build/cli/create.d.ts +4 -0
  9. package/build/cli/create.js +169 -56
  10. package/build/cli/features.d.ts +23 -0
  11. package/build/cli/features.js +85 -0
  12. package/build/cli/index.js +42 -2
  13. package/build/cli/proc.d.ts +1 -0
  14. package/build/cli/proc.js +11 -0
  15. package/build/cli/ui.js +1 -2
  16. package/build/cli/validate.d.ts +4 -0
  17. package/build/cli/validate.js +19 -0
  18. package/build/client/.tsbuildinfo +1 -1
  19. package/build/client/Link.d.ts +8 -0
  20. package/build/client/Link.js +44 -0
  21. package/build/client/NavLink.d.ts +14 -0
  22. package/build/client/NavLink.js +37 -0
  23. package/build/client/Router.d.ts +7 -0
  24. package/build/client/Router.js +55 -0
  25. package/build/client/error-boundary.d.ts +16 -0
  26. package/build/client/error-boundary.js +19 -0
  27. package/build/client/head.d.ts +26 -0
  28. package/build/client/head.js +87 -0
  29. package/build/client/hooks.d.ts +17 -0
  30. package/build/client/hooks.js +48 -0
  31. package/build/client/index.d.ts +14 -2
  32. package/build/client/index.js +8 -1
  33. package/build/client/lazy.d.ts +16 -0
  34. package/build/client/lazy.js +53 -0
  35. package/build/client/match.js +7 -0
  36. package/build/client/mount.d.ts +2 -0
  37. package/build/client/mount.js +13 -0
  38. package/build/client/navigation.d.ts +13 -0
  39. package/build/client/navigation.js +97 -0
  40. package/build/client/params-context.d.ts +2 -0
  41. package/build/client/params-context.js +2 -0
  42. package/build/client/prefetch.d.ts +11 -0
  43. package/build/client/prefetch.js +100 -0
  44. package/build/client/scroll.d.ts +8 -0
  45. package/build/client/scroll.js +36 -0
  46. package/build/client/types.d.ts +27 -0
  47. package/build/client/types.js +1 -0
  48. package/build/compiler/.tsbuildinfo +1 -1
  49. package/build/compiler/config.d.ts +2 -0
  50. package/build/compiler/config.js +4 -1
  51. package/build/compiler/docs.d.ts +10 -0
  52. package/build/compiler/docs.js +59 -0
  53. package/build/compiler/generate.d.ts +1 -0
  54. package/build/compiler/generate.js +139 -21
  55. package/build/compiler/index.d.ts +5 -2
  56. package/build/compiler/index.js +5 -3
  57. package/build/compiler/plugin.js +2 -1
  58. package/build/compiler/routes.js +5 -1
  59. package/build/compiler/vite.d.ts +1 -1
  60. package/build/compiler/vite.js +17 -1
  61. package/build/io/.tsbuildinfo +1 -1
  62. package/build/io/BinaryWriter.js +2 -2
  63. package/eslint.config.js +1 -1
  64. package/examples/basic/.toil/docs/cli.md +3 -0
  65. package/examples/basic/.toil/docs/client.md +3 -0
  66. package/examples/basic/.toil/docs/index.md +3 -0
  67. package/examples/basic/.toil/docs/routing.md +3 -0
  68. package/examples/basic/.toil/docs/server.md +3 -0
  69. package/examples/basic/.toil/docs/styling.md +3 -0
  70. package/examples/basic/.toil/entry.tsx +3 -8
  71. package/examples/basic/.toil/globals.ts +6 -0
  72. package/examples/basic/.toil/index.html +16 -12
  73. package/examples/basic/.toil/public/images/.gitkeep +1 -0
  74. package/examples/basic/.toil/public/images/logo.svg +37 -0
  75. package/examples/basic/.toil/public/robots.txt +2 -0
  76. package/examples/basic/.toil/routes.ts +9 -7
  77. package/examples/basic/build/client/assets/404-Bq0jNTUo.js +1 -0
  78. package/examples/basic/build/client/assets/_...slug_-CXKf6qnB.js +1 -0
  79. package/examples/basic/build/client/assets/_id_-BadAyQnb.js +1 -0
  80. package/examples/basic/build/client/assets/about-BOhoEcEO.js +1 -0
  81. package/examples/basic/build/client/assets/get-started-BIXpcjkT.js +9 -0
  82. package/examples/basic/build/client/assets/index-BmqcTaBB.js +1 -0
  83. package/examples/basic/build/client/assets/io-DEVjjaJj.js +1 -0
  84. package/examples/basic/build/client/assets/layout-DJegirdz.js +1 -0
  85. package/examples/basic/build/client/assets/react-DEQrz1q7.js +9 -0
  86. package/examples/basic/build/client/assets/rolldown-runtime-KL5VtC6j.js +1 -0
  87. package/examples/basic/build/client/assets/routes-BYWn6TxK.js +1 -0
  88. package/examples/basic/build/client/css/style.css +2 -0
  89. package/examples/basic/build/client/images/.gitkeep +1 -0
  90. package/examples/basic/build/client/images/logo.svg +37 -0
  91. package/examples/basic/build/client/index.html +17 -0
  92. package/examples/basic/build/client/robots.txt +2 -0
  93. package/examples/basic/client/404.tsx +2 -5
  94. package/examples/basic/client/components/.gitkeep +1 -0
  95. package/examples/basic/client/components/Footer.tsx +8 -0
  96. package/examples/basic/client/layout.tsx +39 -26
  97. package/examples/basic/client/public/images/.gitkeep +1 -0
  98. package/examples/basic/client/public/images/logo.svg +37 -0
  99. package/examples/basic/client/public/index.html +15 -0
  100. package/examples/basic/client/public/robots.txt +2 -0
  101. package/examples/basic/client/routes/about.tsx +1 -3
  102. package/examples/basic/client/routes/blog/[id].tsx +2 -4
  103. package/examples/basic/client/routes/docs/[...slug].tsx +3 -6
  104. package/examples/basic/client/routes/get-started.tsx +84 -0
  105. package/examples/basic/client/routes/index.tsx +74 -7
  106. package/examples/basic/client/routes/io.tsx +3 -7
  107. package/examples/basic/client/styles/main.css +461 -0
  108. package/examples/basic/client/toil.tsx +7 -0
  109. package/examples/basic/node_modules/.bin/toilinit +16 -0
  110. package/examples/basic/node_modules/.bin/toilinit.cmd +17 -0
  111. package/examples/basic/node_modules/.bin/toilinit.ps1 +28 -0
  112. package/examples/basic/node_modules/.bin/toilscript +16 -0
  113. package/examples/basic/node_modules/.bin/toilscript.cmd +17 -0
  114. package/examples/basic/node_modules/.bin/toilscript.ps1 +28 -0
  115. package/examples/basic/node_modules/.bin/wasm-as +16 -0
  116. package/examples/basic/node_modules/.bin/wasm-as.cmd +17 -0
  117. package/examples/basic/node_modules/.bin/wasm-as.ps1 +28 -0
  118. package/examples/basic/node_modules/.bin/wasm-ctor-eval +16 -0
  119. package/examples/basic/node_modules/.bin/wasm-ctor-eval.cmd +17 -0
  120. package/examples/basic/node_modules/.bin/wasm-ctor-eval.ps1 +28 -0
  121. package/examples/basic/node_modules/.bin/wasm-dis +16 -0
  122. package/examples/basic/node_modules/.bin/wasm-dis.cmd +17 -0
  123. package/examples/basic/node_modules/.bin/wasm-dis.ps1 +28 -0
  124. package/examples/basic/node_modules/.bin/wasm-merge +16 -0
  125. package/examples/basic/node_modules/.bin/wasm-merge.cmd +17 -0
  126. package/examples/basic/node_modules/.bin/wasm-merge.ps1 +28 -0
  127. package/examples/basic/node_modules/.bin/wasm-metadce +16 -0
  128. package/examples/basic/node_modules/.bin/wasm-metadce.cmd +17 -0
  129. package/examples/basic/node_modules/.bin/wasm-metadce.ps1 +28 -0
  130. package/examples/basic/node_modules/.bin/wasm-opt +16 -0
  131. package/examples/basic/node_modules/.bin/wasm-opt.cmd +17 -0
  132. package/examples/basic/node_modules/.bin/wasm-opt.ps1 +28 -0
  133. package/examples/basic/node_modules/.bin/wasm-reduce +16 -0
  134. package/examples/basic/node_modules/.bin/wasm-reduce.cmd +17 -0
  135. package/examples/basic/node_modules/.bin/wasm-reduce.ps1 +28 -0
  136. package/examples/basic/node_modules/.bin/wasm-shell +16 -0
  137. package/examples/basic/node_modules/.bin/wasm-shell.cmd +17 -0
  138. package/examples/basic/node_modules/.bin/wasm-shell.ps1 +28 -0
  139. package/examples/basic/node_modules/.bin/wasm2js +16 -0
  140. package/examples/basic/node_modules/.bin/wasm2js.cmd +17 -0
  141. package/examples/basic/node_modules/.bin/wasm2js.ps1 +28 -0
  142. package/examples/basic/node_modules/.package-lock.json +49 -1
  143. package/examples/basic/node_modules/.vite/deps/_metadata.json +9 -9
  144. package/examples/basic/node_modules/binaryen/LICENSE +201 -0
  145. package/examples/basic/node_modules/binaryen/README.md +1362 -0
  146. package/examples/basic/node_modules/binaryen/bin/package.json +3 -0
  147. package/examples/basic/node_modules/binaryen/bin/wasm-as +0 -0
  148. package/examples/basic/node_modules/binaryen/bin/wasm-ctor-eval +0 -0
  149. package/examples/basic/node_modules/binaryen/bin/wasm-dis +0 -0
  150. package/examples/basic/node_modules/binaryen/bin/wasm-merge +0 -0
  151. package/examples/basic/node_modules/binaryen/bin/wasm-metadce +0 -0
  152. package/examples/basic/node_modules/binaryen/bin/wasm-opt +0 -0
  153. package/examples/basic/node_modules/binaryen/bin/wasm-reduce +0 -0
  154. package/examples/basic/node_modules/binaryen/bin/wasm-shell +0 -0
  155. package/examples/basic/node_modules/binaryen/bin/wasm2js +0 -0
  156. package/examples/basic/node_modules/binaryen/index.d.ts +2371 -0
  157. package/examples/basic/node_modules/binaryen/index.js +30552 -0
  158. package/examples/basic/node_modules/binaryen/package.json +50 -0
  159. package/examples/basic/node_modules/long/LICENSE +202 -0
  160. package/examples/basic/node_modules/long/README.md +286 -0
  161. package/examples/basic/node_modules/long/index.d.ts +2 -0
  162. package/examples/basic/node_modules/long/index.js +1581 -0
  163. package/examples/basic/node_modules/long/package.json +58 -0
  164. package/examples/basic/node_modules/long/types.d.ts +474 -0
  165. package/examples/basic/node_modules/long/umd/index.d.ts +3 -0
  166. package/examples/basic/node_modules/long/umd/index.js +1622 -0
  167. package/examples/basic/node_modules/long/umd/package.json +3 -0
  168. package/examples/basic/node_modules/long/umd/types.d.ts +474 -0
  169. package/examples/basic/node_modules/toilscript/LICENSE +201 -0
  170. package/examples/basic/node_modules/toilscript/NOTICE +94 -0
  171. package/examples/basic/node_modules/toilscript/README.md +66 -0
  172. package/examples/basic/node_modules/toilscript/bin/toilinit.js +468 -0
  173. package/examples/basic/node_modules/toilscript/bin/toilscript.js +35 -0
  174. package/examples/basic/node_modules/toilscript/dist/cli.d.ts +4 -0
  175. package/examples/basic/node_modules/toilscript/dist/cli.generated.d.ts +10027 -0
  176. package/examples/basic/node_modules/toilscript/dist/cli.js +24474 -0
  177. package/examples/basic/node_modules/toilscript/dist/cli.js.map +7 -0
  178. package/examples/basic/node_modules/toilscript/dist/importmap.json +9 -0
  179. package/examples/basic/node_modules/toilscript/dist/toilscript.d.ts +4 -0
  180. package/examples/basic/node_modules/toilscript/dist/toilscript.generated.d.ts +11242 -0
  181. package/examples/basic/node_modules/toilscript/dist/toilscript.js +337 -0
  182. package/examples/basic/node_modules/toilscript/dist/toilscript.js.map +7 -0
  183. package/examples/basic/node_modules/toilscript/dist/transform.cjs +1 -0
  184. package/examples/basic/node_modules/toilscript/dist/transform.d.ts +1 -0
  185. package/examples/basic/node_modules/toilscript/dist/transform.js +1 -0
  186. package/examples/basic/node_modules/toilscript/dist/web.js +22 -0
  187. package/examples/basic/node_modules/toilscript/lib/binaryen.d.ts +2 -0
  188. package/examples/basic/node_modules/toilscript/lib/binaryen.js +2 -0
  189. package/examples/basic/node_modules/toilscript/package.json +115 -0
  190. package/examples/basic/node_modules/toilscript/std/README.md +6 -0
  191. package/examples/basic/node_modules/toilscript/std/assembly/array.ts +550 -0
  192. package/examples/basic/node_modules/toilscript/std/assembly/arraybuffer.ts +77 -0
  193. package/examples/basic/node_modules/toilscript/std/assembly/atomics.ts +127 -0
  194. package/examples/basic/node_modules/toilscript/std/assembly/bindings/asyncify.ts +16 -0
  195. package/examples/basic/node_modules/toilscript/std/assembly/bindings/dom.ts +291 -0
  196. package/examples/basic/node_modules/toilscript/std/assembly/bindings/node.ts +6 -0
  197. package/examples/basic/node_modules/toilscript/std/assembly/bitflags.ts +53 -0
  198. package/examples/basic/node_modules/toilscript/std/assembly/builtins.ts +2650 -0
  199. package/examples/basic/node_modules/toilscript/std/assembly/byteslice.ts +177 -0
  200. package/examples/basic/node_modules/toilscript/std/assembly/compat.ts +2 -0
  201. package/examples/basic/node_modules/toilscript/std/assembly/console.ts +42 -0
  202. package/examples/basic/node_modules/toilscript/std/assembly/crypto.ts +9 -0
  203. package/examples/basic/node_modules/toilscript/std/assembly/dataview.ts +181 -0
  204. package/examples/basic/node_modules/toilscript/std/assembly/date.ts +375 -0
  205. package/examples/basic/node_modules/toilscript/std/assembly/diagnostics.ts +11 -0
  206. package/examples/basic/node_modules/toilscript/std/assembly/encoding.ts +151 -0
  207. package/examples/basic/node_modules/toilscript/std/assembly/endian.ts +45 -0
  208. package/examples/basic/node_modules/toilscript/std/assembly/error.ts +44 -0
  209. package/examples/basic/node_modules/toilscript/std/assembly/fixedarray.ts +173 -0
  210. package/examples/basic/node_modules/toilscript/std/assembly/fixedmap.ts +326 -0
  211. package/examples/basic/node_modules/toilscript/std/assembly/fixedset.ts +275 -0
  212. package/examples/basic/node_modules/toilscript/std/assembly/function.ts +42 -0
  213. package/examples/basic/node_modules/toilscript/std/assembly/index.d.ts +2892 -0
  214. package/examples/basic/node_modules/toilscript/std/assembly/iterator.ts +35 -0
  215. package/examples/basic/node_modules/toilscript/std/assembly/map.ts +269 -0
  216. package/examples/basic/node_modules/toilscript/std/assembly/math.ts +3289 -0
  217. package/examples/basic/node_modules/toilscript/std/assembly/memory.ts +123 -0
  218. package/examples/basic/node_modules/toilscript/std/assembly/number.ts +388 -0
  219. package/examples/basic/node_modules/toilscript/std/assembly/object.ts +36 -0
  220. package/examples/basic/node_modules/toilscript/std/assembly/performance.ts +9 -0
  221. package/examples/basic/node_modules/toilscript/std/assembly/pointer.ts +80 -0
  222. package/examples/basic/node_modules/toilscript/std/assembly/polyfills.ts +27 -0
  223. package/examples/basic/node_modules/toilscript/std/assembly/process.ts +50 -0
  224. package/examples/basic/node_modules/toilscript/std/assembly/reference.ts +48 -0
  225. package/examples/basic/node_modules/toilscript/std/assembly/regexp.ts +12 -0
  226. package/examples/basic/node_modules/toilscript/std/assembly/rt/README.md +83 -0
  227. package/examples/basic/node_modules/toilscript/std/assembly/rt/common.ts +81 -0
  228. package/examples/basic/node_modules/toilscript/std/assembly/rt/index-incremental.ts +2 -0
  229. package/examples/basic/node_modules/toilscript/std/assembly/rt/index-memory.ts +1 -0
  230. package/examples/basic/node_modules/toilscript/std/assembly/rt/index-minimal.ts +2 -0
  231. package/examples/basic/node_modules/toilscript/std/assembly/rt/index-stub.ts +1 -0
  232. package/examples/basic/node_modules/toilscript/std/assembly/rt/index.d.ts +37 -0
  233. package/examples/basic/node_modules/toilscript/std/assembly/rt/itcms.ts +419 -0
  234. package/examples/basic/node_modules/toilscript/std/assembly/rt/memory-runtime.ts +94 -0
  235. package/examples/basic/node_modules/toilscript/std/assembly/rt/rtrace.ts +15 -0
  236. package/examples/basic/node_modules/toilscript/std/assembly/rt/stub.ts +133 -0
  237. package/examples/basic/node_modules/toilscript/std/assembly/rt/tcms.ts +254 -0
  238. package/examples/basic/node_modules/toilscript/std/assembly/rt/tlsf.ts +592 -0
  239. package/examples/basic/node_modules/toilscript/std/assembly/rt.ts +90 -0
  240. package/examples/basic/node_modules/toilscript/std/assembly/set.ts +225 -0
  241. package/examples/basic/node_modules/toilscript/std/assembly/shared/feature.ts +68 -0
  242. package/examples/basic/node_modules/toilscript/std/assembly/shared/runtime.ts +13 -0
  243. package/examples/basic/node_modules/toilscript/std/assembly/shared/target.ts +11 -0
  244. package/examples/basic/node_modules/toilscript/std/assembly/shared/tsconfig.json +11 -0
  245. package/examples/basic/node_modules/toilscript/std/assembly/shared/typeinfo.ts +72 -0
  246. package/examples/basic/node_modules/toilscript/std/assembly/staticarray.ts +423 -0
  247. package/examples/basic/node_modules/toilscript/std/assembly/string.ts +850 -0
  248. package/examples/basic/node_modules/toilscript/std/assembly/symbol.ts +114 -0
  249. package/examples/basic/node_modules/toilscript/std/assembly/table.ts +16 -0
  250. package/examples/basic/node_modules/toilscript/std/assembly/toilscript.ts +16 -0
  251. package/examples/basic/node_modules/toilscript/std/assembly/tsconfig.json +6 -0
  252. package/examples/basic/node_modules/toilscript/std/assembly/typedarray.ts +1954 -0
  253. package/examples/basic/node_modules/toilscript/std/assembly/uri.ts +17 -0
  254. package/examples/basic/node_modules/toilscript/std/assembly/util/bytes.ts +107 -0
  255. package/examples/basic/node_modules/toilscript/std/assembly/util/casemap.ts +497 -0
  256. package/examples/basic/node_modules/toilscript/std/assembly/util/error.ts +58 -0
  257. package/examples/basic/node_modules/toilscript/std/assembly/util/hash.ts +117 -0
  258. package/examples/basic/node_modules/toilscript/std/assembly/util/math.ts +1922 -0
  259. package/examples/basic/node_modules/toilscript/std/assembly/util/memory.ts +290 -0
  260. package/examples/basic/node_modules/toilscript/std/assembly/util/number.ts +873 -0
  261. package/examples/basic/node_modules/toilscript/std/assembly/util/sort.ts +313 -0
  262. package/examples/basic/node_modules/toilscript/std/assembly/util/string.ts +1202 -0
  263. package/examples/basic/node_modules/toilscript/std/assembly/util/uri.ts +275 -0
  264. package/examples/basic/node_modules/toilscript/std/assembly/vector.ts +4 -0
  265. package/examples/basic/node_modules/toilscript/std/assembly.json +16 -0
  266. package/examples/basic/node_modules/toilscript/std/portable/index.d.ts +461 -0
  267. package/examples/basic/node_modules/toilscript/std/portable/index.js +416 -0
  268. package/examples/basic/node_modules/toilscript/std/portable.json +11 -0
  269. package/examples/basic/node_modules/toilscript/std/types/assembly/index.d.ts +1 -0
  270. package/examples/basic/node_modules/toilscript/std/types/assembly/package.json +3 -0
  271. package/examples/basic/node_modules/toilscript/std/types/portable/index.d.ts +1 -0
  272. package/examples/basic/node_modules/toilscript/std/types/portable/package.json +3 -0
  273. package/examples/basic/node_modules/toilscript/tsconfig-base.json +13 -0
  274. package/examples/basic/node_modules/toilscript/util/README.md +23 -0
  275. package/examples/basic/node_modules/toilscript/util/browser/fs.js +1 -0
  276. package/examples/basic/node_modules/toilscript/util/browser/module.js +5 -0
  277. package/examples/basic/node_modules/toilscript/util/browser/path.js +520 -0
  278. package/examples/basic/node_modules/toilscript/util/browser/process.js +59 -0
  279. package/examples/basic/node_modules/toilscript/util/browser/url.js +23 -0
  280. package/examples/basic/node_modules/toilscript/util/cpu.d.ts +9 -0
  281. package/examples/basic/node_modules/toilscript/util/cpu.js +42 -0
  282. package/examples/basic/node_modules/toilscript/util/find.d.ts +6 -0
  283. package/examples/basic/node_modules/toilscript/util/find.js +20 -0
  284. package/examples/basic/node_modules/toilscript/util/node.d.ts +21 -0
  285. package/examples/basic/node_modules/toilscript/util/node.js +34 -0
  286. package/examples/basic/node_modules/toilscript/util/options.d.ts +70 -0
  287. package/examples/basic/node_modules/toilscript/util/options.js +262 -0
  288. package/examples/basic/node_modules/toilscript/util/terminal.d.ts +52 -0
  289. package/examples/basic/node_modules/toilscript/util/terminal.js +35 -0
  290. package/examples/basic/node_modules/toilscript/util/text.d.ts +26 -0
  291. package/examples/basic/node_modules/toilscript/util/text.js +114 -0
  292. package/examples/basic/node_modules/toilscript/util/tsconfig.json +9 -0
  293. package/examples/basic/node_modules/toilscript/util/web.d.ts +11 -0
  294. package/examples/basic/node_modules/toilscript/util/web.js +33 -0
  295. package/examples/basic/package-lock.json +50 -1
  296. package/examples/basic/package.json +5 -2
  297. package/examples/basic/server/index.ts +3 -0
  298. package/examples/basic/server/main.ts +6 -0
  299. package/examples/basic/server/tsconfig.json +7 -0
  300. package/examples/basic/toil-env.d.ts +20 -1
  301. package/examples/basic/toil.config.ts +2 -5
  302. package/examples/basic/toilconfig.json +30 -0
  303. package/package.json +1 -1
  304. package/presets/eslint.js +2 -7
  305. package/presets/no-uint8array-tostring.js +4 -5
  306. package/presets/prettier.json +8 -1
  307. package/src/backend/index.ts +11 -18
  308. package/src/cli/configure.ts +272 -0
  309. package/src/cli/create.ts +228 -67
  310. package/src/cli/features.ts +128 -0
  311. package/src/cli/index.ts +44 -3
  312. package/src/cli/proc.ts +20 -0
  313. package/src/cli/ui.ts +4 -6
  314. package/src/cli/validate.ts +31 -0
  315. package/src/client/Link.tsx +99 -0
  316. package/src/client/NavLink.tsx +86 -0
  317. package/src/client/Router.tsx +95 -0
  318. package/src/client/error-boundary.tsx +43 -0
  319. package/src/client/head.ts +140 -0
  320. package/src/client/hooks.ts +115 -0
  321. package/src/client/index.ts +35 -5
  322. package/src/client/lazy.ts +93 -0
  323. package/src/client/match.ts +11 -3
  324. package/src/client/mount.tsx +28 -0
  325. package/src/client/navigation.ts +142 -0
  326. package/src/client/params-context.ts +10 -0
  327. package/src/client/prefetch.ts +130 -0
  328. package/src/client/scroll.ts +53 -0
  329. package/src/client/types.ts +36 -0
  330. package/src/compiler/config.ts +15 -8
  331. package/src/compiler/docs.ts +87 -0
  332. package/src/compiler/generate.ts +180 -33
  333. package/src/compiler/index.ts +7 -4
  334. package/src/compiler/plugin.ts +3 -1
  335. package/src/compiler/routes.ts +13 -7
  336. package/src/compiler/vite.ts +28 -5
  337. package/src/io/BinaryReader.ts +1 -5
  338. package/src/io/BinaryWriter.ts +3 -3
  339. package/src/server/index.ts +3 -4
  340. package/src/server/tsconfig.json +4 -0
  341. package/test/configure.test.ts +90 -0
  342. package/test/features.test.ts +111 -0
  343. package/test/head.test.ts +35 -0
  344. package/test/io.test.ts +8 -0
  345. package/test/navlink.test.ts +28 -0
  346. package/test/routes.test.ts +15 -0
  347. package/test/validate.test.ts +42 -0
  348. package/vitest.config.ts +1 -1
  349. package/examples/basic/dist/assets/404-D1bS2aH_.js +0 -1
  350. package/examples/basic/dist/assets/_...slug_-wR3shlWn.js +0 -1
  351. package/examples/basic/dist/assets/_id_-EWYvHfi2.js +0 -1
  352. package/examples/basic/dist/assets/about-Ddvj1tjF.js +0 -1
  353. package/examples/basic/dist/assets/index-CdG0me90.js +0 -1
  354. package/examples/basic/dist/assets/io-CODNJU57.js +0 -1
  355. package/examples/basic/dist/assets/layout-C15ZTPYI.js +0 -1
  356. package/examples/basic/dist/assets/react-JbAfoxYe.js +0 -9
  357. package/examples/basic/dist/assets/rolldown-runtime-1VNLd2iN.js +0 -1
  358. package/examples/basic/dist/assets/routes-GoydenoY.js +0 -1
  359. package/examples/basic/dist/index.html +0 -12
  360. package/src/client/runtime.tsx +0 -190
@@ -15,11 +15,12 @@
15
15
  "@types/react-dom": "^19.2.3",
16
16
  "eslint": "^10.2.0",
17
17
  "prettier": "^3.8.1",
18
+ "toilscript": "^0.1.2",
18
19
  "typescript": "^6.0.3"
19
20
  }
20
21
  },
21
22
  "../..": {
22
- "version": "0.0.1",
23
+ "version": "0.0.4",
23
24
  "license": "Apache-2.0",
24
25
  "dependencies": {
25
26
  "@btc-vision/as-bignum": "^1.0.0",
@@ -340,6 +341,24 @@
340
341
  "node": "18 || 20 || >=22"
341
342
  }
342
343
  },
344
+ "node_modules/binaryen": {
345
+ "version": "129.0.0-nightly.20260428",
346
+ "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-129.0.0-nightly.20260428.tgz",
347
+ "integrity": "sha512-RpjRVPZw8NOhkGzx3tTaKYdv4C+zO1VVI0VB9GSCNLM81flHOAZUwRJTLDM3Hqco3OmwB8hTLpkkpMSJjUfHXw==",
348
+ "dev": true,
349
+ "license": "Apache-2.0",
350
+ "bin": {
351
+ "wasm-as": "bin/wasm-as",
352
+ "wasm-ctor-eval": "bin/wasm-ctor-eval",
353
+ "wasm-dis": "bin/wasm-dis",
354
+ "wasm-merge": "bin/wasm-merge",
355
+ "wasm-metadce": "bin/wasm-metadce",
356
+ "wasm-opt": "bin/wasm-opt",
357
+ "wasm-reduce": "bin/wasm-reduce",
358
+ "wasm-shell": "bin/wasm-shell",
359
+ "wasm2js": "bin/wasm2js"
360
+ }
361
+ },
343
362
  "node_modules/brace-expansion": {
344
363
  "version": "5.0.6",
345
364
  "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
@@ -761,6 +780,13 @@
761
780
  "url": "https://github.com/sponsors/sindresorhus"
762
781
  }
763
782
  },
783
+ "node_modules/long": {
784
+ "version": "5.3.2",
785
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
786
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
787
+ "dev": true,
788
+ "license": "Apache-2.0"
789
+ },
764
790
  "node_modules/minimatch": {
765
791
  "version": "10.2.5",
766
792
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
@@ -951,6 +977,29 @@
951
977
  "resolved": "../..",
952
978
  "link": true
953
979
  },
980
+ "node_modules/toilscript": {
981
+ "version": "0.1.2",
982
+ "resolved": "https://registry.npmjs.org/toilscript/-/toilscript-0.1.2.tgz",
983
+ "integrity": "sha512-FqSUBb8IO2ryEeZfY+/WK7LB+B5RBdl+QY7bg5proYWENMvyvUEm5zLjNmpsMksTEqOPMF0GsJZzRn9Eh8fPpQ==",
984
+ "dev": true,
985
+ "license": "Apache-2.0",
986
+ "dependencies": {
987
+ "binaryen": "129.0.0-nightly.20260428",
988
+ "long": "^5.2.4"
989
+ },
990
+ "bin": {
991
+ "toilinit": "bin/toilinit.js",
992
+ "toilscript": "bin/toilscript.js"
993
+ },
994
+ "engines": {
995
+ "node": ">=20",
996
+ "npm": ">=10"
997
+ },
998
+ "funding": {
999
+ "type": "opencollective",
1000
+ "url": "https://opencollective.com/assemblyscript"
1001
+ }
1002
+ },
954
1003
  "node_modules/type-check": {
955
1004
  "version": "0.4.0",
956
1005
  "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -4,10 +4,12 @@
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "toiljs dev",
7
- "build": "toiljs build",
7
+ "build": "toiljs build && toilscript --target release",
8
+ "build:client": "toiljs build",
9
+ "build:server": "toilscript --target release",
8
10
  "lint": "eslint client",
9
11
  "typecheck": "tsc --noEmit",
10
- "format": "prettier --write \"client/**/*.{ts,tsx}\""
12
+ "format": "prettier --write \"client/**/*.{ts,tsx,css}\" \"client/public/**/*.html\""
11
13
  },
12
14
  "dependencies": {
13
15
  "react": "^19.2.6",
@@ -19,6 +21,7 @@
19
21
  "@types/react-dom": "^19.2.3",
20
22
  "eslint": "^10.2.0",
21
23
  "prettier": "^3.8.1",
24
+ "toilscript": "^0.1.2",
22
25
  "typescript": "^6.0.3"
23
26
  }
24
27
  }
@@ -0,0 +1,3 @@
1
+ export function add(a: i32, b: i32): i32 {
2
+ return a + b;
3
+ }
@@ -0,0 +1,6 @@
1
+ import { add } from './index';
2
+
3
+ @main
4
+ function run(): i32 {
5
+ return add(40, 2);
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "toilscript/std/assembly.json",
3
+ "compilerOptions": {
4
+ "plugins": [{ "name": "toilscript/std/ts-plugin.cjs" }]
5
+ },
6
+ "include": ["./**/*.ts"]
7
+ }
@@ -1,2 +1,21 @@
1
1
  // AUTO-GENERATED by toil — do not edit.
2
- /// <reference types="toiljs/globals" />
2
+ declare const Toil: typeof import('toiljs/client');
3
+ declare const BinaryWriter: typeof import('toiljs/io').BinaryWriter;
4
+ declare const BinaryReader: typeof import('toiljs/io').BinaryReader;
5
+ declare const FastMap: typeof import('toiljs/io').FastMap;
6
+ declare const FastSet: typeof import('toiljs/io').FastSet;
7
+
8
+ declare module '*.css' {}
9
+ declare module '*.scss' {}
10
+ declare module '*.sass' {}
11
+ declare module '*.less' {}
12
+ declare module '*.styl' {}
13
+ declare module '*.stylus' {}
14
+ declare module '*.pcss' {}
15
+ declare module '*.sss' {}
16
+
17
+ declare module 'toiljs/routes' {
18
+ export const routes: import('toiljs/client').RouteDef[];
19
+ export const layout: import('toiljs/client').LayoutLoader;
20
+ export const notFound: import('toiljs/client').NotFoundLoader;
21
+ }
@@ -1,7 +1,4 @@
1
1
  import { defineConfig } from 'toiljs/compiler';
2
2
 
3
- export default defineConfig({
4
- client: {
5
- outDir: 'dist'
6
- }
7
- });
3
+ // Client and server options go here. Output defaults to build/client and build/server.
4
+ export default defineConfig({});
@@ -0,0 +1,30 @@
1
+ {
2
+ "entries": ["server/main.ts"],
3
+ "targets": {
4
+ "release": {
5
+ "outFile": "build/server/release.wasm",
6
+ "textFile": "build/server/release.wat"
7
+ }
8
+ },
9
+ "options": {
10
+ "sourceMap": false,
11
+ "optimizeLevel": 3,
12
+ "shrinkLevel": 1,
13
+ "converge": true,
14
+ "noAssert": false,
15
+ "enable": [
16
+ "sign-extension",
17
+ "mutable-globals",
18
+ "nontrapping-f2i",
19
+ "bulk-memory",
20
+ "simd",
21
+ "reference-types",
22
+ "multi-value"
23
+ ],
24
+ "runtime": "stub",
25
+ "memoryBase": 0,
26
+ "initialMemory": 1,
27
+ "debug": false,
28
+ "trapMode": "allow"
29
+ }
30
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "toiljs",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.5",
5
5
  "author": "Dacely",
6
6
  "description": "todo",
7
7
  "engines": {
package/presets/eslint.js CHANGED
@@ -1,7 +1,4 @@
1
- // toiljs shared ESLint flat config opinionated, strict, React-aware.
2
- // Use it from your project's eslint.config.js:
3
- // import toiljs from 'toiljs/eslint';
4
- // export default toiljs;
1
+ /** toiljs shared ESLint flat config: `import toiljs from 'toiljs/eslint'; export default toiljs;` */
5
2
  import eslintReact from '@eslint-react/eslint-plugin';
6
3
  import eslint from '@eslint/js';
7
4
  import reactHooks from 'eslint-plugin-react-hooks';
@@ -11,8 +8,7 @@ import tseslint from 'typescript-eslint';
11
8
  import noUint8ArrayToString from './no-uint8array-tostring.js';
12
9
 
13
10
  export default tseslint.config(
14
- // Build output, the toil working dir, and generated ambient types are not hand-written source.
15
- { ignores: ['dist', 'build', '.toil', 'node_modules', 'toil-env.d.ts'] },
11
+ { ignores: ['dist', 'build', '.toil', 'node_modules', 'toil-env.d.ts', 'server/**'] },
16
12
  {
17
13
  extends: [
18
14
  eslint.configs.recommended,
@@ -22,7 +18,6 @@ export default tseslint.config(
22
18
  files: ['**/*.{ts,tsx}'],
23
19
  languageOptions: {
24
20
  ecmaVersion: 2023,
25
- // No tsconfigRootDir: projectService discovers the consumer's tsconfig from cwd.
26
21
  parserOptions: {
27
22
  projectService: true,
28
23
  },
@@ -1,6 +1,7 @@
1
- // ESLint rule: disallow `.toString()` on Uint8Array (and branded byte types), which returns
2
- // comma-separated decimals instead of hex. Ported to plain JS from the typed source so the
3
- // shareable preset can load it at runtime without a TypeScript loader.
1
+ /**
2
+ * ESLint rule: disallow `.toString()` on Uint8Array (and branded byte types), which returns
3
+ * comma-separated decimals instead of hex.
4
+ */
4
5
  import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';
5
6
  import { SyntaxKind } from 'typescript';
6
7
 
@@ -108,8 +109,6 @@ function hasCustomToString(type, checker) {
108
109
  }
109
110
  }
110
111
 
111
- // Fallback: also check the apparent type, which can differ for branded
112
- // types or type aliases that wrap a class.
113
112
  const apparentType = checker.getApparentType(type);
114
113
  if (apparentType !== type) {
115
114
  const apparentToString = apparentType.getProperty('toString');
@@ -7,5 +7,12 @@
7
7
  "trailingComma": "none",
8
8
  "bracketSpacing": true,
9
9
  "bracketSameLine": true,
10
- "arrowParens": "always"
10
+ "arrowParens": "always",
11
+ "htmlWhitespaceSensitivity": "css",
12
+ "overrides": [
13
+ {
14
+ "files": "*.html",
15
+ "options": { "parser": "html" }
16
+ }
17
+ ]
11
18
  }
@@ -4,7 +4,7 @@
4
4
  * a WebSocket channel for realtime / live updates.
5
5
  *
6
6
  * This is the Node "server" that hosts the app on a local machine; it is distinct from the
7
- * AssemblyScript WASM target in `src/server`.
7
+ * toilscript WASM target in `src/server`.
8
8
  */
9
9
  import fs from 'node:fs';
10
10
  import path from 'node:path';
@@ -17,14 +17,14 @@ import {
17
17
  type Websocket,
18
18
  } from '@btc-vision/hyper-express';
19
19
 
20
- const DEFAULT_MAX_BODY_LENGTH = 1024 * 1024 * 8; // 8 MB
21
- const MAX_BODY_BUFFER = 1024 * 32; // 32 KB
22
- const HTTP_IDLE_TIMEOUT = 60; // seconds
23
- const HTTP_RESPONSE_TIMEOUT = 120; // seconds
20
+ const DEFAULT_MAX_BODY_LENGTH = 1024 * 1024 * 8;
21
+ const MAX_BODY_BUFFER = 1024 * 32;
22
+ const HTTP_IDLE_TIMEOUT = 60;
23
+ const HTTP_RESPONSE_TIMEOUT = 120;
24
24
 
25
- const WS_MAX_PAYLOAD_LENGTH = 1024 * 1024; // 1 MB
26
- const WS_IDLE_TIMEOUT = 120; // seconds
27
- const WS_MAX_BACKPRESSURE = 1024 * 1024 * 2; // 2 MB
25
+ const WS_MAX_PAYLOAD_LENGTH = 1024 * 1024;
26
+ const WS_IDLE_TIMEOUT = 120;
27
+ const WS_MAX_BACKPRESSURE = 1024 * 1024 * 2;
28
28
 
29
29
  const CORS_METHODS = 'GET, POST, OPTIONS, PUT, PATCH, DELETE';
30
30
  const CORS_HEADERS = 'X-Requested-With, content-type';
@@ -62,8 +62,8 @@ export interface RunningBackend {
62
62
  function resolveStaticFile(root: string, requestPath: string): string | null {
63
63
  const decoded = decodeURIComponent(requestPath);
64
64
  const resolved = path.join(root, decoded);
65
- if (resolved !== root && !resolved.startsWith(root + path.sep)) return null; // traversal
66
- if (decoded === '/' || decoded === '') return null; // defer to SPA fallback
65
+ if (resolved !== root && !resolved.startsWith(root + path.sep)) return null;
66
+ if (decoded === '/' || decoded === '') return null;
67
67
  if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) return resolved;
68
68
  return null;
69
69
  }
@@ -90,7 +90,6 @@ export async function startBackend(options: BackendOptions): Promise<RunningBack
90
90
 
91
91
  const clients = new Set<Websocket>();
92
92
 
93
- // Never let an unhandled error leak a stack trace; write a safe response if the socket is live.
94
93
  app.set_error_handler((_request: Request, response: Response, _error: Error) => {
95
94
  if (response.completed) return;
96
95
  response.atomic(() => {
@@ -98,7 +97,6 @@ export async function startBackend(options: BackendOptions): Promise<RunningBack
98
97
  });
99
98
  });
100
99
 
101
- // CORS + hide the underlying server header.
102
100
  if (cors) {
103
101
  app.use((request: Request, response: Response, next: MiddlewareNext) => {
104
102
  if (request.method !== 'OPTIONS') {
@@ -118,7 +116,6 @@ export async function startBackend(options: BackendOptions): Promise<RunningBack
118
116
  });
119
117
  }
120
118
 
121
- // Realtime WebSocket channel: each client joins, messages are broadcast to all peers.
122
119
  app.ws(
123
120
  wsPath,
124
121
  {
@@ -133,17 +130,13 @@ export async function startBackend(options: BackendOptions): Promise<RunningBack
133
130
  ws.on('message', (message: string) => {
134
131
  for (const client of clients) client.send(message);
135
132
  });
136
- // Backpressure on this socket has drained — broadcast channel has nothing to flush.
137
- ws.on('drain', () => {
138
- /* no-op */
139
- });
133
+ ws.on('drain', () => {});
140
134
  ws.on('close', () => {
141
135
  clients.delete(ws);
142
136
  });
143
137
  },
144
138
  );
145
139
 
146
- // Static client with SPA fallback — anything that isn't a real file serves index.html.
147
140
  app.get('/*', (request: Request, response: Response) => {
148
141
  if (response.completed) return;
149
142
  const file = resolveStaticFile(root, request.path);
@@ -0,0 +1,272 @@
1
+ /**
2
+ * `toiljs configure` — toggle a project's client styling features (CSS preprocessor + Tailwind) on
3
+ * an existing app. Detects the current setup, prompts for the desired one, then rewrites the
4
+ * stylesheet(s) + the `client/toil.tsx` imports, edits `package.json`, and syncs node_modules with
5
+ * the project's package manager (so removed features are fully cleaned, not just disabled).
6
+ */
7
+ import fs from 'node:fs/promises';
8
+ import path from 'node:path';
9
+
10
+ import { intro, outro, select, confirm, isCancel, cancel, spinner, note } from '@clack/prompts';
11
+ import { loadConfig } from 'toiljs/compiler';
12
+ import pc from 'picocolors';
13
+
14
+ import {
15
+ PKG_VERSION,
16
+ PREPROCESSORS,
17
+ TAILWIND_CSS,
18
+ TAILWIND_ENTRY,
19
+ detectPreprocessor,
20
+ detectTailwind,
21
+ packageDiff,
22
+ preprocessorForExt,
23
+ setStyleImports,
24
+ styleEntry,
25
+ type Preprocessor,
26
+ type StyleFeatures,
27
+ } from './features.js';
28
+ import { run } from './proc.js';
29
+ import { accent, dim } from './ui.js';
30
+
31
+ export interface ConfigureOptions {
32
+ readonly root?: string;
33
+ readonly cwd: string;
34
+ /** When set, the corresponding prompt is skipped (non-interactive). */
35
+ readonly preprocessor?: Preprocessor;
36
+ readonly tailwind?: boolean;
37
+ /** Run the package manager to sync deps. Default `true`; `false` edits files only. */
38
+ readonly install?: boolean;
39
+ }
40
+
41
+ /** Resolves the client source dir, falling back to `<root>/client` if the config can't be loaded. */
42
+ async function resolveClientDir(root: string): Promise<string> {
43
+ try {
44
+ const cfg = await loadConfig({ root });
45
+ return cfg.clientAbsDir;
46
+ } catch {
47
+ return path.join(root, 'client');
48
+ }
49
+ }
50
+
51
+ const PREPROCESSOR_LABEL: Record<Preprocessor, string> = {
52
+ css: 'Plain CSS',
53
+ sass: 'Sass (SCSS)',
54
+ less: 'Less',
55
+ stylus: 'Stylus',
56
+ };
57
+
58
+ interface PackageJson {
59
+ dependencies?: Record<string, string>;
60
+ devDependencies?: Record<string, string>;
61
+ }
62
+
63
+ function bail<T>(value: T | symbol): asserts value is T {
64
+ if (isCancel(value)) {
65
+ cancel('Configuration cancelled.');
66
+ process.exit(0);
67
+ }
68
+ }
69
+
70
+ /** Finds the existing main stylesheet's preprocessor by extension, or null if none is present. */
71
+ async function detectStylesheet(clientDir: string): Promise<Preprocessor | null> {
72
+ for (const p of PREPROCESSORS) {
73
+ try {
74
+ await fs.access(path.join(clientDir, styleEntry(p)));
75
+ return p;
76
+ } catch {}
77
+ }
78
+ try {
79
+ await fs.access(path.join(clientDir, 'styles/main.sass'));
80
+ return preprocessorForExt('sass');
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
85
+
86
+ /** Returns the path of the existing `styles/main.*` stylesheet, or null. */
87
+ async function findMainStylesheet(clientDir: string): Promise<string | null> {
88
+ for (const ext of ['css', 'scss', 'sass', 'less', 'styl']) {
89
+ const p = path.join(clientDir, 'styles', `main.${ext}`);
90
+ try {
91
+ await fs.access(p);
92
+ return p;
93
+ } catch {}
94
+ }
95
+ return null;
96
+ }
97
+
98
+ /** Picks the project's package manager from its lockfile (defaults to npm). */
99
+ async function detectPackageManager(root: string): Promise<string> {
100
+ const lock: [string, string][] = [
101
+ ['pnpm-lock.yaml', 'pnpm'],
102
+ ['yarn.lock', 'yarn'],
103
+ ['bun.lockb', 'bun'],
104
+ ];
105
+ for (const [file, pm] of lock) {
106
+ try {
107
+ await fs.access(path.join(root, file));
108
+ return pm;
109
+ } catch {}
110
+ }
111
+ return 'npm';
112
+ }
113
+
114
+ /** Applies the stylesheet renames, Tailwind entry, and entry imports for the new feature set. */
115
+ async function applyStyleFiles(
116
+ clientDir: string,
117
+ from: StyleFeatures,
118
+ to: StyleFeatures,
119
+ ): Promise<void> {
120
+ if (from.preprocessor !== to.preprocessor) {
121
+ const newPath = path.join(clientDir, styleEntry(to.preprocessor));
122
+ await fs.mkdir(path.dirname(newPath), { recursive: true });
123
+ // Rename whatever main stylesheet actually exists (preserving its content), not an assumed
124
+ // name — so we never blow away the user's styles when the on-disk extension differs.
125
+ const existing = await findMainStylesheet(clientDir);
126
+ if (existing && path.resolve(existing) !== path.resolve(newPath)) {
127
+ await fs.rename(existing, newPath);
128
+ } else if (!existing) {
129
+ await fs.writeFile(newPath, '', 'utf8');
130
+ }
131
+ }
132
+
133
+ const tailwindPath = path.join(clientDir, TAILWIND_ENTRY);
134
+ if (to.tailwind && !from.tailwind) {
135
+ await fs.mkdir(path.dirname(tailwindPath), { recursive: true });
136
+ await fs.writeFile(tailwindPath, TAILWIND_CSS, 'utf8');
137
+ } else if (!to.tailwind && from.tailwind) {
138
+ await fs.rm(tailwindPath, { force: true });
139
+ }
140
+
141
+ for (const entry of ['toil.tsx', 'toil.jsx']) {
142
+ const entryPath = path.join(clientDir, entry);
143
+ try {
144
+ const source = await fs.readFile(entryPath, 'utf8');
145
+ await fs.writeFile(entryPath, setStyleImports(source, to), 'utf8');
146
+ return;
147
+ } catch {}
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Applies a styling change to a project on disk (no prompts): rewrites stylesheets + the app
153
+ * entry's imports and edits `package.json`. Exposed for testing and reuse; the package manager is
154
+ * run separately by {@link runConfigure}.
155
+ */
156
+ export async function applyConfigure(
157
+ clientDir: string,
158
+ pkgPath: string,
159
+ pkg: PackageJson,
160
+ from: StyleFeatures,
161
+ to: StyleFeatures,
162
+ ): Promise<void> {
163
+ await applyStyleFiles(clientDir, from, to);
164
+ await applyPackages(pkgPath, pkg, from, to);
165
+ }
166
+
167
+ /** Adds/removes the managed styling packages in `package.json` (sorted devDependencies). */
168
+ async function applyPackages(
169
+ pkgPath: string,
170
+ pkg: PackageJson,
171
+ from: StyleFeatures,
172
+ to: StyleFeatures,
173
+ ): Promise<void> {
174
+ const { add, remove } = packageDiff(from, to);
175
+ const dev: Record<string, string> = { ...pkg.devDependencies };
176
+ const deps: Record<string, string> = { ...pkg.dependencies };
177
+ for (const name of add) dev[name] = PKG_VERSION[name] ?? 'latest';
178
+ for (const name of remove) {
179
+ delete dev[name];
180
+ delete deps[name];
181
+ }
182
+ const sortedDev = Object.fromEntries(Object.entries(dev).sort(([a], [b]) => a.localeCompare(b)));
183
+ const next: PackageJson = { ...pkg, devDependencies: sortedDev };
184
+ // Always reflect the pruned dependencies (or drop the key entirely if now empty), so a removed
185
+ // package can't survive via the original `...pkg` spread.
186
+ if (Object.keys(deps).length) next.dependencies = deps;
187
+ else delete next.dependencies;
188
+ await fs.writeFile(pkgPath, JSON.stringify(next, null, 4) + '\n', 'utf8');
189
+ }
190
+
191
+ /** Human-readable summary of what changed. */
192
+ function describe(from: StyleFeatures, to: StyleFeatures): string {
193
+ const lines: string[] = [];
194
+ if (from.preprocessor !== to.preprocessor) {
195
+ lines.push(`preprocessor: ${PREPROCESSOR_LABEL[from.preprocessor]} → ${PREPROCESSOR_LABEL[to.preprocessor]}`);
196
+ }
197
+ if (from.tailwind !== to.tailwind) {
198
+ lines.push(`Tailwind: ${from.tailwind ? 'on' : 'off'} → ${to.tailwind ? 'on' : 'off'}`);
199
+ }
200
+ const { add, remove } = packageDiff(from, to);
201
+ if (add.length) lines.push(`+ ${add.join(', ')}`);
202
+ if (remove.length) lines.push(`- ${remove.join(', ')}`);
203
+ return lines.map((l) => dim(' ') + l).join('\n');
204
+ }
205
+
206
+ /** Runs the interactive configure flow. */
207
+ export async function runConfigure(opts: ConfigureOptions): Promise<void> {
208
+ intro(accent(' toiljs configure '));
209
+ const root = path.resolve(opts.root ?? opts.cwd);
210
+
211
+ const pkgPath = path.join(root, 'package.json');
212
+ let pkg: PackageJson;
213
+ try {
214
+ pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8')) as PackageJson;
215
+ } catch {
216
+ cancel(`No package.json in ${pc.cyan(root)} — run this inside a toiljs project.`);
217
+ process.exit(1);
218
+ }
219
+
220
+ const clientAbsDir = await resolveClientDir(root);
221
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
222
+ const current: StyleFeatures = {
223
+ preprocessor: (await detectStylesheet(clientAbsDir)) ?? detectPreprocessor(deps),
224
+ tailwind: detectTailwind(deps),
225
+ };
226
+
227
+ const nonInteractive = opts.preprocessor !== undefined || opts.tailwind !== undefined;
228
+ let target: StyleFeatures;
229
+ if (nonInteractive) {
230
+ target = {
231
+ preprocessor: opts.preprocessor ?? current.preprocessor,
232
+ tailwind: opts.tailwind ?? current.tailwind,
233
+ };
234
+ } else {
235
+ const ppChoice = await select<Preprocessor>({
236
+ message: 'CSS preprocessor',
237
+ options: PREPROCESSORS.map((value) => ({ value, label: PREPROCESSOR_LABEL[value] })),
238
+ initialValue: current.preprocessor,
239
+ });
240
+ bail(ppChoice);
241
+ const twChoice = await confirm({ message: 'Use Tailwind CSS?', initialValue: current.tailwind });
242
+ bail(twChoice);
243
+ target = { preprocessor: ppChoice, tailwind: twChoice };
244
+ }
245
+
246
+ if (target.preprocessor === current.preprocessor && target.tailwind === current.tailwind) {
247
+ outro('No changes — your styling setup is already up to date.');
248
+ return;
249
+ }
250
+
251
+ const s = spinner();
252
+ s.start('Updating project files');
253
+ await applyConfigure(clientAbsDir, pkgPath, pkg, current, target);
254
+ s.stop('Updated stylesheets, entry imports, and package.json');
255
+
256
+ const pm = await detectPackageManager(root);
257
+ if (opts.install === false) {
258
+ note(`${pc.cyan(`${pm} install`)} to sync the dependency changes.`, 'Next step');
259
+ } else {
260
+ const i = spinner();
261
+ i.start(`Syncing dependencies with ${pm}`);
262
+ try {
263
+ await run(pm, ['install'], root);
264
+ i.stop('Dependencies synced');
265
+ } catch {
266
+ i.stop(pc.yellow(`Could not run \`${pm} install\` — run it yourself to finish`));
267
+ }
268
+ }
269
+
270
+ note(describe(current, target), 'Styling updated');
271
+ outro(`Reconfigured — restart \`${accent('toiljs dev')}\` to pick up the changes.`);
272
+ }