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
@@ -1,22 +1,33 @@
1
- import { spawn } from 'node:child_process';
2
1
  import fs from 'node:fs/promises';
3
2
  import path from 'node:path';
4
- import { intro, outro, text, select, confirm, isCancel, cancel, spinner, note } from '@clack/prompts';
3
+ import { intro, outro, text, select, multiselect, confirm, isCancel, cancel, spinner, note, } from '@clack/prompts';
4
+ import { AI_HELPERS, AI_HELPER_IDS, aiHelperFiles, TOIL_DOCS, TOIL_ENV_DTS } from 'toiljs/compiler';
5
5
  import pc from 'picocolors';
6
+ import { PKG_VERSION, PREPROCESSORS, requiredPackages, styleEntry, styleImportLines, TAILWIND_CSS, TAILWIND_ENTRY, } from './features.js';
7
+ import { run } from './proc.js';
6
8
  import { accent, dim, version } from './ui.js';
9
+ import { isPackageManager, isValidName, resolveProjectDir } from './validate.js';
10
+ const PREPROCESSOR_LABEL = {
11
+ css: 'Plain CSS',
12
+ sass: 'Sass (SCSS)',
13
+ less: 'Less',
14
+ stylus: 'Stylus',
15
+ };
16
+ const DEFAULT_STYLE_CONTENT = ':root {\n color-scheme: dark;\n}\n\n' +
17
+ 'body {\n margin: 0;\n background: #080d11;\n color: #f5f6fa;\n' +
18
+ ' font-family: system-ui, -apple-system, sans-serif;\n line-height: 1.6;\n}\n\n' +
19
+ 'a {\n color: #2563ff;\n text-decoration: none;\n}\n\n' +
20
+ 'a:hover {\n color: #22e3ab;\n}\n\n' +
21
+ 'code {\n background: #11161f;\n color: #22e3ab;\n padding: 0.1rem 0.4rem;\n' +
22
+ ' border-radius: 4px;\n font-size: 0.9em;\n}\n\n' +
23
+ 'h1 {\n background: linear-gradient(90deg, #2563ff, #7c3aed, #22e3ab);\n' +
24
+ ' -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n}\n';
7
25
  function bail(value) {
8
26
  if (isCancel(value)) {
9
27
  cancel('Scaffolding cancelled.');
10
28
  process.exit(0);
11
29
  }
12
30
  }
13
- function isValidName(name) {
14
- if (!name.trim())
15
- return 'Please enter a project name.';
16
- if (!/^[a-z0-9._@/-]+$/i.test(name))
17
- return 'Use letters, numbers, dashes, dots or slashes.';
18
- return true;
19
- }
20
31
  async function isEmptyDir(dir) {
21
32
  try {
22
33
  const entries = await fs.readdir(dir);
@@ -26,58 +37,128 @@ async function isEmptyDir(dir) {
26
37
  return true;
27
38
  }
28
39
  }
29
- function scaffold(name, template) {
40
+ function scaffold(name, template, features, aiTools) {
30
41
  const toilVersion = version();
42
+ const devDependencies = {
43
+ '@types/react': '^19.2.15',
44
+ '@types/react-dom': '^19.2.3',
45
+ eslint: '^10.2.0',
46
+ prettier: '^3.8.1',
47
+ toilscript: '^0.1.2',
48
+ typescript: '^6.0.3',
49
+ };
50
+ for (const dep of requiredPackages(features).sort()) {
51
+ devDependencies[dep] = PKG_VERSION[dep] ?? 'latest';
52
+ }
31
53
  const pkg = {
32
54
  name: path.basename(name),
33
55
  private: true,
34
56
  type: 'module',
35
57
  scripts: {
36
58
  dev: 'toiljs dev',
37
- build: 'toiljs build',
59
+ build: 'toiljs build && toilscript --target release',
60
+ 'build:client': 'toiljs build',
61
+ 'build:server': 'toilscript --target release',
38
62
  lint: 'eslint client',
39
63
  typecheck: 'tsc --noEmit',
40
- format: 'prettier --write "client/**/*.{ts,tsx}"',
64
+ format: 'prettier --write "client/**/*.{ts,tsx,css,scss,less}" "client/public/**/*.html"',
41
65
  },
42
66
  dependencies: {
43
67
  toiljs: `^${toilVersion}`,
44
68
  react: '^19.2.6',
45
69
  'react-dom': '^19.2.6',
46
70
  },
47
- devDependencies: {
48
- '@types/react': '^19.2.15',
49
- '@types/react-dom': '^19.2.3',
50
- eslint: '^10.2.0',
51
- prettier: '^3.8.1',
52
- typescript: '^6.0.3',
53
- },
71
+ devDependencies,
54
72
  };
55
73
  const files = {
56
74
  'package.json': JSON.stringify(pkg, null, 4) + '\n',
57
75
  'toil.config.ts': "import { defineConfig } from 'toiljs/compiler';\n\n" +
58
- 'export default defineConfig({\n client: {\n outDir: \'dist\',\n },\n});\n',
76
+ 'export default defineConfig({});\n',
59
77
  'tsconfig.json': '{\n "extends": "toiljs/tsconfig",\n "include": ["client", "toil-env.d.ts"]\n}\n',
60
78
  'eslint.config.js': "import toiljs from 'toiljs/eslint';\n\nexport default toiljs;\n",
61
79
  '.prettierrc': '"toiljs/prettier"\n',
62
- '.gitignore': 'node_modules\ndist\n.toil\ntoil-env.d.ts\n',
80
+ '.gitignore': 'node_modules\nbuild\n.toil\ntoil-env.d.ts\n',
81
+ 'client/public/index.html': '<!doctype html>\n<html lang="en">\n <head>\n' +
82
+ ' <meta charset="utf-8" />\n' +
83
+ ' <meta name="viewport" content="width=device-width, initial-scale=1" />\n' +
84
+ ' <meta name="theme-color" content="#080D11" />\n' +
85
+ ' <meta name="description" content="" />\n' +
86
+ ' <link rel="icon" type="image/svg+xml" href="/favicon.svg" />\n' +
87
+ ' <link rel="manifest" href="/manifest.webmanifest" />\n' +
88
+ ` <title>${path.basename(name)}</title>\n` +
89
+ ' </head>\n <body>\n <div id="root"></div>\n </body>\n</html>\n',
90
+ 'client/public/favicon.svg': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">\n' +
91
+ ' <defs>\n' +
92
+ ' <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">\n' +
93
+ ' <stop offset="0" stop-color="#2563FF" />\n' +
94
+ ' <stop offset="0.5" stop-color="#7C3AED" />\n' +
95
+ ' <stop offset="1" stop-color="#22E3AB" />\n' +
96
+ ' </linearGradient>\n' +
97
+ ' </defs>\n' +
98
+ ' <rect width="32" height="32" rx="7" fill="#080D11" />\n' +
99
+ ' <path d="M9 10h14v3.2h-5.4V24h-3.2V13.2H9z" fill="url(#g)" />\n' +
100
+ '</svg>\n',
101
+ 'client/public/robots.txt': 'User-agent: *\nAllow: /\n',
102
+ 'client/public/manifest.webmanifest': JSON.stringify({
103
+ name: path.basename(name),
104
+ short_name: path.basename(name),
105
+ start_url: '/',
106
+ display: 'standalone',
107
+ background_color: '#080D11',
108
+ theme_color: '#080D11',
109
+ icons: [{ src: '/favicon.svg', type: 'image/svg+xml', sizes: 'any' }],
110
+ }, null, 4) + '\n',
111
+ 'client/public/images/.gitkeep': '# Place images and other static assets here; served at /images/*.\n',
112
+ 'client/toil.tsx': "import { routes, layout, notFound } from 'toiljs/routes';\n\n" +
113
+ styleImportLines(features).join('\n') +
114
+ '\n\n' +
115
+ 'Toil.mount(routes, layout, notFound);\n',
116
+ [`client/${styleEntry(features.preprocessor)}`]: DEFAULT_STYLE_CONTENT,
117
+ 'client/components/.gitkeep': '# Place shared React components here.\n',
118
+ 'toil-env.d.ts': TOIL_ENV_DTS,
119
+ 'toilconfig.json': JSON.stringify({
120
+ entries: ['server/main.ts'],
121
+ targets: {
122
+ release: {
123
+ outFile: 'build/server/release.wasm',
124
+ textFile: 'build/server/release.wat',
125
+ },
126
+ },
127
+ options: {
128
+ sourceMap: false,
129
+ optimizeLevel: 3,
130
+ shrinkLevel: 1,
131
+ converge: true,
132
+ noAssert: false,
133
+ enable: [
134
+ 'sign-extension',
135
+ 'mutable-globals',
136
+ 'nontrapping-f2i',
137
+ 'bulk-memory',
138
+ 'simd',
139
+ 'reference-types',
140
+ 'multi-value',
141
+ ],
142
+ runtime: 'stub',
143
+ memoryBase: 0,
144
+ initialMemory: 1,
145
+ debug: false,
146
+ trapMode: 'allow',
147
+ },
148
+ }, null, 4) + '\n',
149
+ 'server/tsconfig.json': JSON.stringify({
150
+ extends: 'toilscript/std/assembly.json',
151
+ include: ['./**/*.ts'],
152
+ }, null, 4) + '\n',
153
+ 'server/index.ts': 'export function add(a: i32, b: i32): i32 {\n return a + b;\n}\n',
154
+ 'server/main.ts': "import { add } from './index';\n\n" +
155
+ '@main\nfunction run(): i32 {\n return add(40, 2);\n}\n',
63
156
  'README.md': ['# ' + path.basename(name), '', 'A [toiljs](https://toil.org) app.', '', '## Develop', '', ' npm install', ' npm run dev', '', '## Build', '', ' npm run build', ''].join('\n'),
64
157
  'client/layout.tsx': `import { type ReactNode } from 'react';
65
158
 
66
- import { Link } from 'toiljs/client';
67
-
68
- const styles = \`
69
- :root { color-scheme: dark; }
70
- body { margin: 0; background: #080D11; color: #F5F6FA; font-family: system-ui, -apple-system, sans-serif; line-height: 1.6; }
71
- a { color: #2563FF; text-decoration: none; }
72
- a:hover { color: #22E3AB; }
73
- code { background: #11161f; color: #22E3AB; padding: 0.1rem 0.4rem; border-radius: 4px; font-size: 0.9em; }
74
- h1 { background: linear-gradient(90deg, #2563FF, #7C3AED, #22E3AB); -webkit-background-clip: text; background-clip: text; color: transparent; }
75
- \`;
76
-
77
159
  export default function Layout({ children }: { children?: ReactNode }) {
78
160
  return (
79
161
  <div style={{ maxWidth: 680, margin: '0 auto', padding: '3rem 1.5rem' }}>
80
- <style>{styles}</style>
81
162
  <header
82
163
  style={{
83
164
  display: 'flex',
@@ -89,7 +170,7 @@ export default function Layout({ children }: { children?: ReactNode }) {
89
170
  }}>
90
171
  <strong style={{ color: '#2563FF', fontSize: '1.1rem' }}>${path.basename(name)}</strong>
91
172
  <nav style={{ display: 'flex', gap: '1rem' }}>
92
- <Link href="/">home</Link>${template === 'app' ? '\n <Link href="/about">about</Link>' : ''}
173
+ <Toil.Link href="/">home</Toil.Link>${template === 'app' ? '\n <Toil.Link href="/about">about</Toil.Link>' : ''}
93
174
  </nav>
94
175
  </header>
95
176
  {children}
@@ -97,30 +178,34 @@ export default function Layout({ children }: { children?: ReactNode }) {
97
178
  );
98
179
  }
99
180
  `,
100
- 'client/routes/index.tsx': "import { Link } from 'toiljs/client';\n\n" +
101
- 'export default function Home() {\n' +
181
+ 'client/routes/index.tsx': 'export default function Home() {\n' +
102
182
  ' return (\n <main>\n' +
103
183
  ' <h1>Welcome to toiljs</h1>\n' +
104
184
  ' <p>File-based routing, bundled by Vite, zero config.</p>\n' +
105
185
  (template === 'app'
106
- ? ' <p>\n <Link href="/about">About</Link> · <Link href="/blog/42">Blog post 42</Link>\n </p>\n'
186
+ ? ' <p>\n <Toil.Link href="/about">About</Toil.Link> · <Toil.Link href="/blog/42">Blog post 42</Toil.Link>\n </p>\n'
107
187
  : '') +
108
188
  ' </main>\n );\n}\n',
109
189
  };
110
190
  if (template === 'app') {
111
191
  files['client/routes/about.tsx'] =
112
- "import { Link } from 'toiljs/client';\n\n" +
113
- 'export default function About() {\n' +
192
+ 'export default function About() {\n' +
114
193
  ' return (\n <main>\n <h1>About</h1>\n' +
115
194
  ' <p>\n This page is served by <code>client/routes/about.tsx</code>.\n </p>\n' +
116
- ' <Link href="/">Back home</Link>\n </main>\n );\n}\n';
195
+ ' <Toil.Link href="/">Back home</Toil.Link>\n </main>\n );\n}\n';
117
196
  files['client/routes/blog/[id].tsx'] =
118
- "import { Link, useParams } from 'toiljs/client';\n\n" +
119
- 'export default function BlogPost() {\n' +
120
- ' const { id } = useParams();\n' +
197
+ 'export default function BlogPost() {\n' +
198
+ ' const { id } = Toil.useParams();\n' +
121
199
  ' return (\n <main>\n <h1>Blog post {id}</h1>\n' +
122
200
  ' <p>\n Dynamic route from <code>client/routes/blog/[id].tsx</code>.\n </p>\n' +
123
- ' <Link href="/">Back home</Link>\n </main>\n );\n}\n';
201
+ ' <Toil.Link href="/">Back home</Toil.Link>\n </main>\n );\n}\n';
202
+ }
203
+ if (features.tailwind) {
204
+ files[`client/${TAILWIND_ENTRY}`] = TAILWIND_CSS;
205
+ }
206
+ Object.assign(files, aiHelperFiles(aiTools));
207
+ for (const [name, content] of Object.entries(TOIL_DOCS)) {
208
+ files[`.toil/docs/${name}`] = content;
124
209
  }
125
210
  return files;
126
211
  }
@@ -131,16 +216,6 @@ async function writeFiles(dir, files) {
131
216
  await fs.writeFile(full, contents, 'utf8');
132
217
  }
133
218
  }
134
- function run(cmd, args, cwd) {
135
- return new Promise((resolve, reject) => {
136
- const onWindows = process.platform === 'win32';
137
- const child = onWindows
138
- ? spawn([cmd, ...args].join(' '), { cwd, stdio: 'ignore', shell: true })
139
- : spawn(cmd, args, { cwd, stdio: 'ignore' });
140
- child.on('error', reject);
141
- child.on('close', (code) => code === 0 ? resolve() : reject(new Error(`${cmd} exited with code ${String(code)}`)));
142
- });
143
- }
144
219
  export async function runCreate(opts) {
145
220
  intro(accent(' toiljs create '));
146
221
  let name = opts.name;
@@ -167,7 +242,11 @@ export async function runCreate(opts) {
167
242
  cancel(valid);
168
243
  process.exit(1);
169
244
  }
170
- const targetDir = path.resolve(opts.cwd, name);
245
+ const targetDir = resolveProjectDir(opts.cwd, name);
246
+ if (targetDir === null) {
247
+ cancel('Project name must stay inside the current directory (no "..", no absolute paths).');
248
+ process.exit(1);
249
+ }
171
250
  const rel = path.relative(opts.cwd, targetDir) || '.';
172
251
  if (!(await isEmptyDir(targetDir))) {
173
252
  if (opts.yes) {
@@ -194,9 +273,43 @@ export async function runCreate(opts) {
194
273
  bail(choice);
195
274
  template = choice === 'minimal' ? 'minimal' : 'app';
196
275
  }
276
+ let preprocessor = opts.preprocessor ?? 'css';
277
+ let tailwind = opts.tailwind ?? false;
278
+ if (!opts.yes) {
279
+ if (opts.preprocessor === undefined) {
280
+ const choice = await select({
281
+ message: 'Styling',
282
+ options: PREPROCESSORS.map((value) => ({ value, label: PREPROCESSOR_LABEL[value] })),
283
+ initialValue: 'css',
284
+ });
285
+ bail(choice);
286
+ preprocessor = choice;
287
+ }
288
+ if (opts.tailwind === undefined) {
289
+ const tw = await confirm({ message: 'Add Tailwind CSS?', initialValue: false });
290
+ bail(tw);
291
+ tailwind = tw;
292
+ }
293
+ }
294
+ const features = { preprocessor, tailwind };
295
+ let aiTools = opts.ai === false ? [] : [...AI_HELPER_IDS];
296
+ if (opts.ai === undefined && !opts.yes) {
297
+ const picked = await multiselect({
298
+ message: 'AI assistant files (read by Claude, Cursor, Codex, Copilot)',
299
+ options: AI_HELPERS.map((h) => ({ value: h.id, label: h.label })),
300
+ initialValues: [...AI_HELPER_IDS],
301
+ required: false,
302
+ });
303
+ bail(picked);
304
+ aiTools = picked;
305
+ }
197
306
  let initGit = opts.git ?? false;
198
307
  let install = opts.install ?? false;
199
308
  const pm = opts.pm ?? 'npm';
309
+ if (!isPackageManager(pm)) {
310
+ cancel(`Unsupported package manager: ${pm} (use npm, pnpm, yarn, or bun).`);
311
+ process.exit(1);
312
+ }
200
313
  if (!opts.yes) {
201
314
  if (opts.git === undefined) {
202
315
  const g = await confirm({ message: 'Initialize a git repository?', initialValue: true });
@@ -211,7 +324,7 @@ export async function runCreate(opts) {
211
324
  }
212
325
  const s = spinner();
213
326
  s.start('Scaffolding project');
214
- await writeFiles(targetDir, scaffold(name, template));
327
+ await writeFiles(targetDir, scaffold(name, template, features, aiTools));
215
328
  s.stop(`Scaffolded ${pc.cyan(rel)}`);
216
329
  if (initGit) {
217
330
  const g = spinner();
@@ -0,0 +1,23 @@
1
+ export type Preprocessor = 'css' | 'sass' | 'less' | 'stylus';
2
+ export interface StyleFeatures {
3
+ readonly preprocessor: Preprocessor;
4
+ readonly tailwind: boolean;
5
+ }
6
+ export declare const PREPROCESSORS: readonly Preprocessor[];
7
+ export declare const STYLE_EXT: Record<Preprocessor, string>;
8
+ export declare const PREPROCESSOR_PKG: Record<Preprocessor, string | null>;
9
+ export declare const TAILWIND_PKGS: readonly string[];
10
+ export declare const PKG_VERSION: Record<string, string>;
11
+ export declare const TAILWIND_ENTRY = "styles/tailwind.css";
12
+ export declare const TAILWIND_CSS = "@import 'tailwindcss';\n";
13
+ export declare function styleEntry(p: Preprocessor): string;
14
+ export declare function preprocessorForExt(ext: string): Preprocessor | null;
15
+ export declare function requiredPackages(f: StyleFeatures): string[];
16
+ export declare function packageDiff(from: StyleFeatures, to: StyleFeatures): {
17
+ add: string[];
18
+ remove: string[];
19
+ };
20
+ export declare function styleImportLines(f: StyleFeatures): string[];
21
+ export declare function setStyleImports(source: string, f: StyleFeatures): string;
22
+ export declare function detectPreprocessor(deps: Record<string, string>): Preprocessor;
23
+ export declare function detectTailwind(deps: Record<string, string>): boolean;
@@ -0,0 +1,85 @@
1
+ export const PREPROCESSORS = ['css', 'sass', 'less', 'stylus'];
2
+ export const STYLE_EXT = {
3
+ css: 'css',
4
+ sass: 'scss',
5
+ less: 'less',
6
+ stylus: 'styl',
7
+ };
8
+ export const PREPROCESSOR_PKG = {
9
+ css: null,
10
+ sass: 'sass',
11
+ less: 'less',
12
+ stylus: 'stylus',
13
+ };
14
+ export const TAILWIND_PKGS = ['tailwindcss', '@tailwindcss/vite'];
15
+ export const PKG_VERSION = {
16
+ sass: '^1.83.0',
17
+ less: '^4.2.1',
18
+ stylus: '^0.64.0',
19
+ tailwindcss: '^4.0.0',
20
+ '@tailwindcss/vite': '^4.0.0',
21
+ };
22
+ export const TAILWIND_ENTRY = 'styles/tailwind.css';
23
+ export const TAILWIND_CSS = `@import 'tailwindcss';\n`;
24
+ export function styleEntry(p) {
25
+ return `styles/main.${STYLE_EXT[p]}`;
26
+ }
27
+ export function preprocessorForExt(ext) {
28
+ const e = ext.replace(/^\./, '');
29
+ if (e === 'sass')
30
+ return 'sass';
31
+ return PREPROCESSORS.find((p) => STYLE_EXT[p] === e) ?? null;
32
+ }
33
+ export function requiredPackages(f) {
34
+ const pkgs = [];
35
+ const pp = PREPROCESSOR_PKG[f.preprocessor];
36
+ if (pp)
37
+ pkgs.push(pp);
38
+ if (f.tailwind)
39
+ pkgs.push(...TAILWIND_PKGS);
40
+ return pkgs;
41
+ }
42
+ export function packageDiff(from, to) {
43
+ const want = new Set(requiredPackages(to));
44
+ const had = new Set(requiredPackages(from));
45
+ return {
46
+ add: [...want].filter((p) => !had.has(p)),
47
+ remove: [...had].filter((p) => !want.has(p)),
48
+ };
49
+ }
50
+ export function styleImportLines(f) {
51
+ const lines = [];
52
+ if (f.tailwind)
53
+ lines.push(`import './${TAILWIND_ENTRY}';`);
54
+ lines.push(`import './${styleEntry(f.preprocessor)}';`);
55
+ return lines;
56
+ }
57
+ export function setStyleImports(source, f) {
58
+ const stripped = source.replace(/^[ \t]*import\s+['"]\.\/styles\/[^'"]+['"];?[ \t]*\r?\n/gm, '');
59
+ const block = styleImportLines(f).join('\n') + '\n';
60
+ const lines = stripped.split('\n');
61
+ const routesIdx = lines.findIndex((l) => /from\s+['"]toiljs\/routes['"]/.test(l));
62
+ let insertAt;
63
+ if (routesIdx !== -1) {
64
+ insertAt = routesIdx + 1;
65
+ }
66
+ else {
67
+ const lastImport = lines.reduce((acc, l, i) => (/^\s*import\s/.test(l) ? i : acc), -1);
68
+ insertAt = lastImport + 1;
69
+ }
70
+ const head = lines.slice(0, insertAt).join('\n');
71
+ const tail = lines.slice(insertAt).join('\n');
72
+ return `${head}\n\n${block}\n${tail}`.replace(/\n{3,}/g, '\n\n');
73
+ }
74
+ export function detectPreprocessor(deps) {
75
+ if ('sass' in deps)
76
+ return 'sass';
77
+ if ('less' in deps)
78
+ return 'less';
79
+ if ('stylus' in deps)
80
+ return 'stylus';
81
+ return 'css';
82
+ }
83
+ export function detectTailwind(deps) {
84
+ return '@tailwindcss/vite' in deps || 'tailwindcss' in deps;
85
+ }
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { build, dev, start } from 'toiljs/compiler';
3
+ import { runConfigure } from './configure.js';
3
4
  import { runCreate } from './create.js';
5
+ import { PREPROCESSORS } from './features.js';
4
6
  import { accent, banner, bold, danger, dim, success, version } from './ui.js';
5
7
  function parseArgs(argv) {
6
8
  const flags = {};
@@ -10,9 +12,12 @@ function parseArgs(argv) {
10
12
  case '--root':
11
13
  flags.root = argv[++i];
12
14
  break;
13
- case '--port':
14
- flags.port = Number(argv[++i]);
15
+ case '--port': {
16
+ const port = Number(argv[++i]);
17
+ if (!Number.isNaN(port))
18
+ flags.port = port;
15
19
  break;
20
+ }
16
21
  case '--template':
17
22
  case '-t': {
18
23
  const t = argv[++i];
@@ -23,6 +28,24 @@ function parseArgs(argv) {
23
28
  case '--pm':
24
29
  flags.pm = argv[++i];
25
30
  break;
31
+ case '--style': {
32
+ const s = argv[++i];
33
+ if (PREPROCESSORS.includes(s))
34
+ flags.preprocessor = s;
35
+ break;
36
+ }
37
+ case '--tailwind':
38
+ flags.tailwind = true;
39
+ break;
40
+ case '--no-tailwind':
41
+ flags.tailwind = false;
42
+ break;
43
+ case '--ai':
44
+ flags.ai = true;
45
+ break;
46
+ case '--no-ai':
47
+ flags.ai = false;
48
+ break;
26
49
  case '--install':
27
50
  flags.install = true;
28
51
  break;
@@ -53,6 +76,7 @@ function printHelp() {
53
76
  '',
54
77
  bold('Commands'),
55
78
  cmd('create [name]', 'scaffold a new toiljs app'),
79
+ cmd('configure', 'toggle styling features (Sass/Less/Stylus, Tailwind)'),
56
80
  cmd('dev', 'start the dev server with HMR'),
57
81
  cmd('build', 'build the optimized production bundle'),
58
82
  cmd('start', 'self-host the built app (hyper-express / uWS)'),
@@ -61,6 +85,9 @@ function printHelp() {
61
85
  cmd('--root <dir>', 'project root (default: current directory)'),
62
86
  cmd('--port <n>', 'dev server port'),
63
87
  cmd('-t, --template', 'create: app | minimal'),
88
+ cmd('--style <name>', 'create/configure: css | sass | less | stylus'),
89
+ cmd('--tailwind', 'create/configure: enable Tailwind (--no-tailwind to remove)'),
90
+ cmd('--no-ai', 'create: skip AI assistant files (CLAUDE.md, etc.)'),
64
91
  cmd('-y, --yes', 'create: accept defaults (non-interactive)'),
65
92
  cmd('--no-install', "create: don't install dependencies"),
66
93
  cmd('-v, --version', 'print the toiljs version'),
@@ -80,6 +107,9 @@ async function main() {
80
107
  await runCreate({
81
108
  name: flags.name,
82
109
  template: flags.template,
110
+ preprocessor: flags.preprocessor,
111
+ tailwind: flags.tailwind,
112
+ ai: flags.ai,
83
113
  install: flags.install,
84
114
  git: flags.git,
85
115
  pm: flags.pm,
@@ -87,6 +117,16 @@ async function main() {
87
117
  cwd: process.cwd(),
88
118
  });
89
119
  break;
120
+ case 'configure':
121
+ banner();
122
+ await runConfigure({
123
+ root: flags.root,
124
+ preprocessor: flags.preprocessor,
125
+ tailwind: flags.tailwind,
126
+ install: flags.install,
127
+ cwd: process.cwd(),
128
+ });
129
+ break;
90
130
  case 'dev':
91
131
  banner();
92
132
  process.stdout.write(dim(' starting dev server…') + '\n\n');
@@ -0,0 +1 @@
1
+ export declare function run(cmd: string, args: string[], cwd: string): Promise<void>;
@@ -0,0 +1,11 @@
1
+ import { spawn } from 'node:child_process';
2
+ export function run(cmd, args, cwd) {
3
+ return new Promise((resolve, reject) => {
4
+ const onWindows = process.platform === 'win32';
5
+ const child = onWindows
6
+ ? spawn([cmd, ...args].join(' '), { cwd, stdio: 'ignore', shell: true })
7
+ : spawn(cmd, args, { cwd, stdio: 'ignore' });
8
+ child.on('error', reject);
9
+ child.on('close', (code) => code === 0 ? resolve() : reject(new Error(`${cmd} exited with code ${String(code)}`)));
10
+ });
11
+ }
package/build/cli/ui.js CHANGED
@@ -63,8 +63,7 @@ export function version() {
63
63
  if (match && match[1])
64
64
  return match[1];
65
65
  }
66
- catch {
67
- }
66
+ catch { }
68
67
  return '0.0.0';
69
68
  }
70
69
  export function banner() {
@@ -0,0 +1,4 @@
1
+ export declare const PACKAGE_MANAGERS: string[];
2
+ export declare function isValidName(name: string): true | string;
3
+ export declare function resolveProjectDir(cwd: string, name: string): string | null;
4
+ export declare function isPackageManager(pm: string): boolean;
@@ -0,0 +1,19 @@
1
+ import path from 'node:path';
2
+ export const PACKAGE_MANAGERS = ['npm', 'pnpm', 'yarn', 'bun'];
3
+ export function isValidName(name) {
4
+ if (!name.trim())
5
+ return 'Please enter a project name.';
6
+ if (!/^[a-z0-9._@/-]+$/i.test(name))
7
+ return 'Use letters, numbers, dashes, dots or slashes.';
8
+ return true;
9
+ }
10
+ export function resolveProjectDir(cwd, name) {
11
+ const target = path.resolve(cwd, name);
12
+ const rel = path.relative(cwd, target);
13
+ if (rel.startsWith('..') || path.isAbsolute(rel))
14
+ return null;
15
+ return target;
16
+ }
17
+ export function isPackageManager(pm) {
18
+ return PACKAGE_MANAGERS.includes(pm);
19
+ }