toiljs 0.0.4 → 0.0.6
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.
- package/.idea/prettier.xml +1 -0
- package/as-pect.config.js +1 -1
- package/build/backend/.tsbuildinfo +1 -1
- package/build/backend/index.js +1 -2
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/configure.d.ts +15 -0
- package/build/cli/configure.js +201 -0
- package/build/cli/create.d.ts +4 -0
- package/build/cli/create.js +193 -68
- package/build/cli/features.d.ts +23 -0
- package/build/cli/features.js +85 -0
- package/build/cli/index.js +42 -2
- package/build/cli/proc.d.ts +1 -0
- package/build/cli/proc.js +11 -0
- package/build/cli/ui.js +1 -2
- package/build/cli/validate.d.ts +4 -0
- package/build/cli/validate.js +19 -0
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/Link.d.ts +8 -0
- package/build/client/Link.js +44 -0
- package/build/client/NavLink.d.ts +14 -0
- package/build/client/NavLink.js +37 -0
- package/build/client/Router.d.ts +7 -0
- package/build/client/Router.js +55 -0
- package/build/client/channel/channel.d.ts +23 -0
- package/build/client/channel/channel.js +94 -0
- package/build/client/error-boundary.d.ts +16 -0
- package/build/client/error-boundary.js +19 -0
- package/build/client/head/head.d.ts +26 -0
- package/build/client/head/head.js +87 -0
- package/build/client/head.d.ts +26 -0
- package/build/client/head.js +87 -0
- package/build/client/hooks.d.ts +17 -0
- package/build/client/hooks.js +48 -0
- package/build/client/index.d.ts +18 -6
- package/build/client/index.js +10 -3
- package/build/client/lazy.d.ts +16 -0
- package/build/client/lazy.js +53 -0
- package/build/client/match.js +7 -0
- package/build/client/mount.d.ts +2 -0
- package/build/client/mount.js +13 -0
- package/build/client/navigation/Link.d.ts +8 -0
- package/build/client/navigation/Link.js +44 -0
- package/build/client/navigation/NavLink.d.ts +14 -0
- package/build/client/navigation/NavLink.js +37 -0
- package/build/client/navigation/navigation.d.ts +13 -0
- package/build/client/navigation/navigation.js +97 -0
- package/build/client/navigation/prefetch.d.ts +11 -0
- package/build/client/navigation/prefetch.js +100 -0
- package/build/client/navigation/scroll.d.ts +8 -0
- package/build/client/navigation/scroll.js +36 -0
- package/build/client/navigation.d.ts +13 -0
- package/build/client/navigation.js +97 -0
- package/build/client/params-context.d.ts +2 -0
- package/build/client/params-context.js +2 -0
- package/build/client/prefetch.d.ts +11 -0
- package/build/client/prefetch.js +100 -0
- package/build/client/routing/Router.d.ts +7 -0
- package/build/client/routing/Router.js +55 -0
- package/build/client/routing/error-boundary.d.ts +16 -0
- package/build/client/routing/error-boundary.js +19 -0
- package/build/client/routing/hooks.d.ts +17 -0
- package/build/client/routing/hooks.js +48 -0
- package/build/client/routing/lazy.d.ts +16 -0
- package/build/client/routing/lazy.js +53 -0
- package/build/client/routing/match.d.ts +2 -0
- package/build/client/routing/match.js +32 -0
- package/build/client/routing/mount.d.ts +2 -0
- package/build/client/routing/mount.js +13 -0
- package/build/client/routing/params-context.d.ts +2 -0
- package/build/client/routing/params-context.js +2 -0
- package/build/client/scroll.d.ts +8 -0
- package/build/client/scroll.js +36 -0
- package/build/client/types.d.ts +27 -0
- package/build/client/types.js +1 -0
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/config.d.ts +2 -0
- package/build/compiler/config.js +14 -2
- package/build/compiler/docs.d.ts +10 -0
- package/build/compiler/docs.js +59 -0
- package/build/compiler/generate.js +144 -16
- package/build/compiler/index.d.ts +4 -2
- package/build/compiler/index.js +4 -3
- package/build/compiler/plugin.js +16 -1
- package/build/compiler/routes.js +5 -1
- package/build/compiler/vite.d.ts +1 -1
- package/build/compiler/vite.js +17 -1
- package/build/io/.tsbuildinfo +1 -1
- package/build/io/BinaryWriter.js +2 -2
- package/eslint.config.js +1 -1
- package/examples/basic/.toil/docs/cli.md +3 -0
- package/examples/basic/.toil/docs/client.md +3 -0
- package/examples/basic/.toil/docs/index.md +3 -0
- package/examples/basic/.toil/docs/routing.md +3 -0
- package/examples/basic/.toil/docs/server.md +3 -0
- package/examples/basic/.toil/docs/styling.md +3 -0
- package/examples/basic/.toil/entry.tsx +3 -8
- package/examples/basic/.toil/globals.ts +6 -0
- package/examples/basic/.toil/index.html +16 -12
- package/examples/basic/.toil/public/images/.gitkeep +1 -0
- package/examples/basic/.toil/public/images/logo.svg +37 -0
- package/examples/basic/.toil/public/robots.txt +2 -0
- package/examples/basic/.toil/routes.ts +9 -7
- package/examples/basic/build/client/assets/404-Bq0jNTUo.js +1 -0
- package/examples/basic/build/client/assets/_...slug_-CXKf6qnB.js +1 -0
- package/examples/basic/build/client/assets/_id_-BadAyQnb.js +1 -0
- package/examples/basic/build/client/assets/about-BOhoEcEO.js +1 -0
- package/examples/basic/build/client/assets/get-started-BIXpcjkT.js +9 -0
- package/examples/basic/build/client/assets/index-BmqcTaBB.js +1 -0
- package/examples/basic/build/client/assets/io-DEVjjaJj.js +1 -0
- package/examples/basic/build/client/assets/layout-DJegirdz.js +1 -0
- package/examples/basic/build/client/assets/react-DEQrz1q7.js +9 -0
- package/examples/basic/build/client/assets/rolldown-runtime-KL5VtC6j.js +1 -0
- package/examples/basic/build/client/assets/routes-BYWn6TxK.js +1 -0
- package/examples/basic/build/client/css/style.css +2 -0
- package/examples/basic/build/client/images/.gitkeep +1 -0
- package/examples/basic/build/client/images/logo.svg +37 -0
- package/examples/basic/build/client/index.html +17 -0
- package/examples/basic/build/client/robots.txt +2 -0
- package/examples/basic/client/404.tsx +2 -5
- package/examples/basic/client/components/.gitkeep +1 -0
- package/examples/basic/client/components/Footer.tsx +8 -0
- package/examples/basic/client/components/HoneycombBackground.tsx +162 -0
- package/examples/basic/client/layout.tsx +43 -26
- package/examples/basic/client/public/favicon.ico +0 -0
- package/examples/basic/client/public/images/.gitkeep +1 -0
- package/examples/basic/client/public/images/logo.svg +37 -0
- package/examples/basic/client/public/index.html +16 -0
- package/examples/basic/client/public/robots.txt +2 -0
- package/examples/basic/client/routes/about.tsx +1 -3
- package/examples/basic/client/routes/blog/[id].tsx +2 -4
- package/examples/basic/client/routes/docs/[...slug].tsx +3 -6
- package/examples/basic/client/routes/get-started.tsx +84 -0
- package/examples/basic/client/routes/index.tsx +74 -7
- package/examples/basic/client/routes/io.tsx +3 -7
- package/examples/basic/client/styles/main.css +461 -0
- package/examples/basic/client/toil.tsx +7 -0
- package/examples/basic/node_modules/.bin/toilinit +16 -0
- package/examples/basic/node_modules/.bin/toilinit.cmd +17 -0
- package/examples/basic/node_modules/.bin/toilinit.ps1 +28 -0
- package/examples/basic/node_modules/.bin/toilscript +16 -0
- package/examples/basic/node_modules/.bin/toilscript.cmd +17 -0
- package/examples/basic/node_modules/.bin/toilscript.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm-as +16 -0
- package/examples/basic/node_modules/.bin/wasm-as.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm-as.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm-ctor-eval +16 -0
- package/examples/basic/node_modules/.bin/wasm-ctor-eval.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm-ctor-eval.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm-dis +16 -0
- package/examples/basic/node_modules/.bin/wasm-dis.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm-dis.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm-merge +16 -0
- package/examples/basic/node_modules/.bin/wasm-merge.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm-merge.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm-metadce +16 -0
- package/examples/basic/node_modules/.bin/wasm-metadce.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm-metadce.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm-opt +16 -0
- package/examples/basic/node_modules/.bin/wasm-opt.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm-opt.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm-reduce +16 -0
- package/examples/basic/node_modules/.bin/wasm-reduce.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm-reduce.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm-shell +16 -0
- package/examples/basic/node_modules/.bin/wasm-shell.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm-shell.ps1 +28 -0
- package/examples/basic/node_modules/.bin/wasm2js +16 -0
- package/examples/basic/node_modules/.bin/wasm2js.cmd +17 -0
- package/examples/basic/node_modules/.bin/wasm2js.ps1 +28 -0
- package/examples/basic/node_modules/.package-lock.json +49 -1
- package/examples/basic/node_modules/.vite/deps/_metadata.json +9 -9
- package/examples/basic/node_modules/binaryen/LICENSE +201 -0
- package/examples/basic/node_modules/binaryen/README.md +1362 -0
- package/examples/basic/node_modules/binaryen/bin/package.json +3 -0
- package/examples/basic/node_modules/binaryen/bin/wasm-as +0 -0
- package/examples/basic/node_modules/binaryen/bin/wasm-ctor-eval +0 -0
- package/examples/basic/node_modules/binaryen/bin/wasm-dis +0 -0
- package/examples/basic/node_modules/binaryen/bin/wasm-merge +0 -0
- package/examples/basic/node_modules/binaryen/bin/wasm-metadce +0 -0
- package/examples/basic/node_modules/binaryen/bin/wasm-opt +0 -0
- package/examples/basic/node_modules/binaryen/bin/wasm-reduce +0 -0
- package/examples/basic/node_modules/binaryen/bin/wasm-shell +0 -0
- package/examples/basic/node_modules/binaryen/bin/wasm2js +0 -0
- package/examples/basic/node_modules/binaryen/index.d.ts +2371 -0
- package/examples/basic/node_modules/binaryen/index.js +30552 -0
- package/examples/basic/node_modules/binaryen/package.json +50 -0
- package/examples/basic/node_modules/long/LICENSE +202 -0
- package/examples/basic/node_modules/long/README.md +286 -0
- package/examples/basic/node_modules/long/index.d.ts +2 -0
- package/examples/basic/node_modules/long/index.js +1581 -0
- package/examples/basic/node_modules/long/package.json +58 -0
- package/examples/basic/node_modules/long/types.d.ts +474 -0
- package/examples/basic/node_modules/long/umd/index.d.ts +3 -0
- package/examples/basic/node_modules/long/umd/index.js +1622 -0
- package/examples/basic/node_modules/long/umd/package.json +3 -0
- package/examples/basic/node_modules/long/umd/types.d.ts +474 -0
- package/examples/basic/node_modules/toilscript/LICENSE +201 -0
- package/examples/basic/node_modules/toilscript/NOTICE +94 -0
- package/examples/basic/node_modules/toilscript/README.md +66 -0
- package/examples/basic/node_modules/toilscript/bin/toilinit.js +468 -0
- package/examples/basic/node_modules/toilscript/bin/toilscript.js +35 -0
- package/examples/basic/node_modules/toilscript/dist/cli.d.ts +4 -0
- package/examples/basic/node_modules/toilscript/dist/cli.generated.d.ts +10027 -0
- package/examples/basic/node_modules/toilscript/dist/cli.js +24474 -0
- package/examples/basic/node_modules/toilscript/dist/cli.js.map +7 -0
- package/examples/basic/node_modules/toilscript/dist/importmap.json +9 -0
- package/examples/basic/node_modules/toilscript/dist/toilscript.d.ts +4 -0
- package/examples/basic/node_modules/toilscript/dist/toilscript.generated.d.ts +11242 -0
- package/examples/basic/node_modules/toilscript/dist/toilscript.js +337 -0
- package/examples/basic/node_modules/toilscript/dist/toilscript.js.map +7 -0
- package/examples/basic/node_modules/toilscript/dist/transform.cjs +1 -0
- package/examples/basic/node_modules/toilscript/dist/transform.d.ts +1 -0
- package/examples/basic/node_modules/toilscript/dist/transform.js +1 -0
- package/examples/basic/node_modules/toilscript/dist/web.js +22 -0
- package/examples/basic/node_modules/toilscript/lib/binaryen.d.ts +2 -0
- package/examples/basic/node_modules/toilscript/lib/binaryen.js +2 -0
- package/examples/basic/node_modules/toilscript/package.json +115 -0
- package/examples/basic/node_modules/toilscript/std/README.md +6 -0
- package/examples/basic/node_modules/toilscript/std/assembly/array.ts +550 -0
- package/examples/basic/node_modules/toilscript/std/assembly/arraybuffer.ts +77 -0
- package/examples/basic/node_modules/toilscript/std/assembly/atomics.ts +127 -0
- package/examples/basic/node_modules/toilscript/std/assembly/bindings/asyncify.ts +16 -0
- package/examples/basic/node_modules/toilscript/std/assembly/bindings/dom.ts +291 -0
- package/examples/basic/node_modules/toilscript/std/assembly/bindings/node.ts +6 -0
- package/examples/basic/node_modules/toilscript/std/assembly/bitflags.ts +53 -0
- package/examples/basic/node_modules/toilscript/std/assembly/builtins.ts +2650 -0
- package/examples/basic/node_modules/toilscript/std/assembly/byteslice.ts +177 -0
- package/examples/basic/node_modules/toilscript/std/assembly/compat.ts +2 -0
- package/examples/basic/node_modules/toilscript/std/assembly/console.ts +42 -0
- package/examples/basic/node_modules/toilscript/std/assembly/crypto.ts +9 -0
- package/examples/basic/node_modules/toilscript/std/assembly/dataview.ts +181 -0
- package/examples/basic/node_modules/toilscript/std/assembly/date.ts +375 -0
- package/examples/basic/node_modules/toilscript/std/assembly/diagnostics.ts +11 -0
- package/examples/basic/node_modules/toilscript/std/assembly/encoding.ts +151 -0
- package/examples/basic/node_modules/toilscript/std/assembly/endian.ts +45 -0
- package/examples/basic/node_modules/toilscript/std/assembly/error.ts +44 -0
- package/examples/basic/node_modules/toilscript/std/assembly/fixedarray.ts +173 -0
- package/examples/basic/node_modules/toilscript/std/assembly/fixedmap.ts +326 -0
- package/examples/basic/node_modules/toilscript/std/assembly/fixedset.ts +275 -0
- package/examples/basic/node_modules/toilscript/std/assembly/function.ts +42 -0
- package/examples/basic/node_modules/toilscript/std/assembly/index.d.ts +2892 -0
- package/examples/basic/node_modules/toilscript/std/assembly/iterator.ts +35 -0
- package/examples/basic/node_modules/toilscript/std/assembly/map.ts +269 -0
- package/examples/basic/node_modules/toilscript/std/assembly/math.ts +3289 -0
- package/examples/basic/node_modules/toilscript/std/assembly/memory.ts +123 -0
- package/examples/basic/node_modules/toilscript/std/assembly/number.ts +388 -0
- package/examples/basic/node_modules/toilscript/std/assembly/object.ts +36 -0
- package/examples/basic/node_modules/toilscript/std/assembly/performance.ts +9 -0
- package/examples/basic/node_modules/toilscript/std/assembly/pointer.ts +80 -0
- package/examples/basic/node_modules/toilscript/std/assembly/polyfills.ts +27 -0
- package/examples/basic/node_modules/toilscript/std/assembly/process.ts +50 -0
- package/examples/basic/node_modules/toilscript/std/assembly/reference.ts +48 -0
- package/examples/basic/node_modules/toilscript/std/assembly/regexp.ts +12 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/README.md +83 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/common.ts +81 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/index-incremental.ts +2 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/index-memory.ts +1 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/index-minimal.ts +2 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/index-stub.ts +1 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/index.d.ts +37 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/itcms.ts +419 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/memory-runtime.ts +94 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/rtrace.ts +15 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/stub.ts +133 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/tcms.ts +254 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt/tlsf.ts +592 -0
- package/examples/basic/node_modules/toilscript/std/assembly/rt.ts +90 -0
- package/examples/basic/node_modules/toilscript/std/assembly/set.ts +225 -0
- package/examples/basic/node_modules/toilscript/std/assembly/shared/feature.ts +68 -0
- package/examples/basic/node_modules/toilscript/std/assembly/shared/runtime.ts +13 -0
- package/examples/basic/node_modules/toilscript/std/assembly/shared/target.ts +11 -0
- package/examples/basic/node_modules/toilscript/std/assembly/shared/tsconfig.json +11 -0
- package/examples/basic/node_modules/toilscript/std/assembly/shared/typeinfo.ts +72 -0
- package/examples/basic/node_modules/toilscript/std/assembly/staticarray.ts +423 -0
- package/examples/basic/node_modules/toilscript/std/assembly/string.ts +850 -0
- package/examples/basic/node_modules/toilscript/std/assembly/symbol.ts +114 -0
- package/examples/basic/node_modules/toilscript/std/assembly/table.ts +16 -0
- package/examples/basic/node_modules/toilscript/std/assembly/toilscript.ts +16 -0
- package/examples/basic/node_modules/toilscript/std/assembly/tsconfig.json +6 -0
- package/examples/basic/node_modules/toilscript/std/assembly/typedarray.ts +1954 -0
- package/examples/basic/node_modules/toilscript/std/assembly/uri.ts +17 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/bytes.ts +107 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/casemap.ts +497 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/error.ts +58 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/hash.ts +117 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/math.ts +1922 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/memory.ts +290 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/number.ts +873 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/sort.ts +313 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/string.ts +1202 -0
- package/examples/basic/node_modules/toilscript/std/assembly/util/uri.ts +275 -0
- package/examples/basic/node_modules/toilscript/std/assembly/vector.ts +4 -0
- package/examples/basic/node_modules/toilscript/std/assembly.json +16 -0
- package/examples/basic/node_modules/toilscript/std/portable/index.d.ts +461 -0
- package/examples/basic/node_modules/toilscript/std/portable/index.js +416 -0
- package/examples/basic/node_modules/toilscript/std/portable.json +11 -0
- package/examples/basic/node_modules/toilscript/std/types/assembly/index.d.ts +1 -0
- package/examples/basic/node_modules/toilscript/std/types/assembly/package.json +3 -0
- package/examples/basic/node_modules/toilscript/std/types/portable/index.d.ts +1 -0
- package/examples/basic/node_modules/toilscript/std/types/portable/package.json +3 -0
- package/examples/basic/node_modules/toilscript/tsconfig-base.json +13 -0
- package/examples/basic/node_modules/toilscript/util/README.md +23 -0
- package/examples/basic/node_modules/toilscript/util/browser/fs.js +1 -0
- package/examples/basic/node_modules/toilscript/util/browser/module.js +5 -0
- package/examples/basic/node_modules/toilscript/util/browser/path.js +520 -0
- package/examples/basic/node_modules/toilscript/util/browser/process.js +59 -0
- package/examples/basic/node_modules/toilscript/util/browser/url.js +23 -0
- package/examples/basic/node_modules/toilscript/util/cpu.d.ts +9 -0
- package/examples/basic/node_modules/toilscript/util/cpu.js +42 -0
- package/examples/basic/node_modules/toilscript/util/find.d.ts +6 -0
- package/examples/basic/node_modules/toilscript/util/find.js +20 -0
- package/examples/basic/node_modules/toilscript/util/node.d.ts +21 -0
- package/examples/basic/node_modules/toilscript/util/node.js +34 -0
- package/examples/basic/node_modules/toilscript/util/options.d.ts +70 -0
- package/examples/basic/node_modules/toilscript/util/options.js +262 -0
- package/examples/basic/node_modules/toilscript/util/terminal.d.ts +52 -0
- package/examples/basic/node_modules/toilscript/util/terminal.js +35 -0
- package/examples/basic/node_modules/toilscript/util/text.d.ts +26 -0
- package/examples/basic/node_modules/toilscript/util/text.js +114 -0
- package/examples/basic/node_modules/toilscript/util/tsconfig.json +9 -0
- package/examples/basic/node_modules/toilscript/util/web.d.ts +11 -0
- package/examples/basic/node_modules/toilscript/util/web.js +33 -0
- package/examples/basic/package-lock.json +50 -1
- package/examples/basic/package.json +5 -2
- package/examples/basic/server/index.ts +3 -0
- package/examples/basic/server/main.ts +6 -0
- package/examples/basic/server/tsconfig.json +7 -0
- package/examples/basic/toil-env.d.ts +20 -1
- package/examples/basic/toil.config.ts +2 -5
- package/examples/basic/toilconfig.json +30 -0
- package/package.json +2 -2
- package/presets/eslint.js +2 -7
- package/presets/no-uint8array-tostring.js +4 -5
- package/presets/prettier.json +8 -1
- package/src/backend/index.ts +11 -18
- package/src/cli/configure.ts +272 -0
- package/src/cli/create.ts +267 -82
- package/src/cli/features.ts +128 -0
- package/src/cli/index.ts +44 -3
- package/src/cli/proc.ts +20 -0
- package/src/cli/ui.ts +4 -6
- package/src/cli/validate.ts +31 -0
- package/src/client/head/head.ts +140 -0
- package/src/client/index.ts +39 -9
- package/src/client/navigation/Link.tsx +99 -0
- package/src/client/navigation/NavLink.tsx +86 -0
- package/src/client/navigation/navigation.ts +142 -0
- package/src/client/navigation/prefetch.ts +130 -0
- package/src/client/navigation/scroll.ts +53 -0
- package/src/client/routing/Router.tsx +95 -0
- package/src/client/routing/error-boundary.tsx +43 -0
- package/src/client/routing/hooks.ts +115 -0
- package/src/client/routing/lazy.ts +93 -0
- package/src/client/{match.ts → routing/match.ts} +11 -3
- package/src/client/routing/mount.tsx +28 -0
- package/src/client/routing/params-context.ts +10 -0
- package/src/client/types.ts +36 -0
- package/src/compiler/config.ts +26 -10
- package/src/compiler/docs.ts +87 -0
- package/src/compiler/generate.ts +180 -23
- package/src/compiler/index.ts +6 -4
- package/src/compiler/plugin.ts +22 -1
- package/src/compiler/routes.ts +13 -7
- package/src/compiler/vite.ts +28 -5
- package/src/io/BinaryReader.ts +1 -5
- package/src/io/BinaryWriter.ts +3 -3
- package/src/server/index.ts +3 -4
- package/src/server/tsconfig.json +4 -0
- package/templates/app/client/404.tsx +11 -0
- package/templates/app/client/components/.gitkeep +1 -0
- package/templates/app/client/components/Footer.tsx +8 -0
- package/templates/app/client/components/HoneycombBackground.tsx +162 -0
- package/templates/app/client/layout.tsx +53 -0
- package/templates/app/client/public/favicon.ico +0 -0
- package/templates/app/client/public/images/.gitkeep +1 -0
- package/templates/app/client/public/images/logo.svg +37 -0
- package/templates/app/client/public/index.html +16 -0
- package/templates/app/client/public/robots.txt +2 -0
- package/templates/app/client/routes/about.tsx +11 -0
- package/templates/app/client/routes/blog/[id].tsx +12 -0
- package/templates/app/client/routes/docs/[...slug].tsx +12 -0
- package/templates/app/client/routes/get-started.tsx +84 -0
- package/templates/app/client/routes/index.tsx +80 -0
- package/templates/app/client/routes/io.tsx +24 -0
- package/templates/app/client/styles/main.css +461 -0
- package/templates/app/client/toil.tsx +7 -0
- package/test/channel.test.ts +1 -1
- package/test/configure.test.ts +90 -0
- package/test/features.test.ts +111 -0
- package/test/head.test.ts +35 -0
- package/test/io.test.ts +8 -0
- package/test/navlink.test.ts +28 -0
- package/test/routes.test.ts +16 -1
- package/test/validate.test.ts +42 -0
- package/vitest.config.ts +1 -1
- package/examples/basic/dist/assets/404-D1bS2aH_.js +0 -1
- package/examples/basic/dist/assets/_...slug_-wR3shlWn.js +0 -1
- package/examples/basic/dist/assets/_id_-EWYvHfi2.js +0 -1
- package/examples/basic/dist/assets/about-Ddvj1tjF.js +0 -1
- package/examples/basic/dist/assets/index-CdG0me90.js +0 -1
- package/examples/basic/dist/assets/io-CODNJU57.js +0 -1
- package/examples/basic/dist/assets/layout-C15ZTPYI.js +0 -1
- package/examples/basic/dist/assets/react-JbAfoxYe.js +0 -9
- package/examples/basic/dist/assets/rolldown-runtime-1VNLd2iN.js +0 -1
- package/examples/basic/dist/assets/routes-GoydenoY.js +0 -1
- package/examples/basic/dist/index.html +0 -12
- package/src/client/runtime.tsx +0 -190
- /package/src/client/{channel.ts → channel/channel.ts} +0 -0
package/src/cli/create.ts
CHANGED
|
@@ -3,18 +3,63 @@
|
|
|
3
3
|
* app to the enforced toiljs presets (tsconfig / eslint / prettier) and file-based routing.
|
|
4
4
|
* Supports a non-interactive path via flags (`--yes`, `--template`, …) for scripting/CI.
|
|
5
5
|
*/
|
|
6
|
-
import { spawn } from 'node:child_process';
|
|
7
6
|
import fs from 'node:fs/promises';
|
|
8
7
|
import path from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
|
|
10
|
+
import {
|
|
11
|
+
intro,
|
|
12
|
+
outro,
|
|
13
|
+
text,
|
|
14
|
+
select,
|
|
15
|
+
multiselect,
|
|
16
|
+
confirm,
|
|
17
|
+
isCancel,
|
|
18
|
+
cancel,
|
|
19
|
+
spinner,
|
|
20
|
+
note,
|
|
21
|
+
} from '@clack/prompts';
|
|
22
|
+
import { AI_HELPERS, AI_HELPER_IDS, aiHelperFiles, TOIL_DOCS, TOIL_ENV_DTS } from 'toiljs/compiler';
|
|
12
23
|
import pc from 'picocolors';
|
|
13
24
|
|
|
25
|
+
import {
|
|
26
|
+
PKG_VERSION,
|
|
27
|
+
PREPROCESSORS,
|
|
28
|
+
requiredPackages,
|
|
29
|
+
setStyleImports,
|
|
30
|
+
styleEntry,
|
|
31
|
+
styleImportLines,
|
|
32
|
+
TAILWIND_CSS,
|
|
33
|
+
TAILWIND_ENTRY,
|
|
34
|
+
type Preprocessor,
|
|
35
|
+
type StyleFeatures,
|
|
36
|
+
} from './features.js';
|
|
37
|
+
import { run } from './proc.js';
|
|
14
38
|
import { accent, dim, version } from './ui.js';
|
|
39
|
+
import { isPackageManager, isValidName, resolveProjectDir } from './validate.js';
|
|
15
40
|
|
|
16
41
|
export type Template = 'app' | 'minimal';
|
|
17
42
|
|
|
43
|
+
/** Human label for each preprocessor in the styling picker. */
|
|
44
|
+
const PREPROCESSOR_LABEL: Record<Preprocessor, string> = {
|
|
45
|
+
css: 'Plain CSS',
|
|
46
|
+
sass: 'Sass (SCSS)',
|
|
47
|
+
less: 'Less',
|
|
48
|
+
stylus: 'Stylus',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Default global stylesheet contents (palette base styles), shared by every preprocessor. */
|
|
52
|
+
const DEFAULT_STYLE_CONTENT =
|
|
53
|
+
':root {\n color-scheme: dark;\n}\n\n' +
|
|
54
|
+
'body {\n margin: 0;\n background: #080d11;\n color: #f5f6fa;\n' +
|
|
55
|
+
' font-family: system-ui, -apple-system, sans-serif;\n line-height: 1.6;\n}\n\n' +
|
|
56
|
+
'a {\n color: #2563ff;\n text-decoration: none;\n}\n\n' +
|
|
57
|
+
'a:hover {\n color: #22e3ab;\n}\n\n' +
|
|
58
|
+
'code {\n background: #11161f;\n color: #22e3ab;\n padding: 0.1rem 0.4rem;\n' +
|
|
59
|
+
' border-radius: 4px;\n font-size: 0.9em;\n}\n\n' +
|
|
60
|
+
'h1 {\n background: linear-gradient(90deg, #2563ff, #7c3aed, #22e3ab);\n' +
|
|
61
|
+
' -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n}\n';
|
|
62
|
+
|
|
18
63
|
/** A selectable template in the `create` wizard. */
|
|
19
64
|
interface TemplateOption {
|
|
20
65
|
readonly value: Template;
|
|
@@ -25,6 +70,10 @@ interface TemplateOption {
|
|
|
25
70
|
export interface CreateOptions {
|
|
26
71
|
readonly name?: string;
|
|
27
72
|
readonly template?: Template;
|
|
73
|
+
readonly preprocessor?: Preprocessor;
|
|
74
|
+
readonly tailwind?: boolean;
|
|
75
|
+
/** AI assistant files to scaffold: `true` = all, `false` = none, omitted = ask. */
|
|
76
|
+
readonly ai?: boolean;
|
|
28
77
|
readonly install?: boolean;
|
|
29
78
|
readonly git?: boolean;
|
|
30
79
|
readonly pm?: string;
|
|
@@ -40,79 +89,184 @@ function bail<T>(value: T | symbol): asserts value is T {
|
|
|
40
89
|
}
|
|
41
90
|
}
|
|
42
91
|
|
|
43
|
-
function isValidName(name: string): true | string {
|
|
44
|
-
if (!name.trim()) return 'Please enter a project name.';
|
|
45
|
-
if (!/^[a-z0-9._@/-]+$/i.test(name)) return 'Use letters, numbers, dashes, dots or slashes.';
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
92
|
async function isEmptyDir(dir: string): Promise<boolean> {
|
|
50
93
|
try {
|
|
51
94
|
const entries = await fs.readdir(dir);
|
|
52
95
|
return entries.length === 0;
|
|
53
96
|
} catch {
|
|
54
|
-
return true;
|
|
97
|
+
return true;
|
|
55
98
|
}
|
|
56
99
|
}
|
|
57
100
|
|
|
58
101
|
/** Builds the full file map (relative path → contents) for a scaffolded project. */
|
|
59
|
-
function scaffold(
|
|
102
|
+
function scaffold(
|
|
103
|
+
name: string,
|
|
104
|
+
template: Template,
|
|
105
|
+
features: StyleFeatures,
|
|
106
|
+
aiTools: readonly string[],
|
|
107
|
+
): Record<string, string> {
|
|
60
108
|
const toilVersion = version();
|
|
109
|
+
const devDependencies: Record<string, string> = {
|
|
110
|
+
'@types/react': '^19.2.15',
|
|
111
|
+
'@types/react-dom': '^19.2.3',
|
|
112
|
+
eslint: '^10.2.0',
|
|
113
|
+
prettier: '^3.8.1',
|
|
114
|
+
toilscript: '^0.1.2',
|
|
115
|
+
typescript: '^6.0.3',
|
|
116
|
+
};
|
|
117
|
+
for (const dep of requiredPackages(features).sort()) {
|
|
118
|
+
devDependencies[dep] = PKG_VERSION[dep] ?? 'latest';
|
|
119
|
+
}
|
|
61
120
|
const pkg = {
|
|
62
121
|
name: path.basename(name),
|
|
63
122
|
private: true,
|
|
64
123
|
type: 'module',
|
|
65
124
|
scripts: {
|
|
66
125
|
dev: 'toiljs dev',
|
|
67
|
-
build: 'toiljs build',
|
|
126
|
+
build: 'toiljs build && toilscript --target release',
|
|
127
|
+
'build:client': 'toiljs build',
|
|
128
|
+
'build:server': 'toilscript --target release',
|
|
68
129
|
lint: 'eslint client',
|
|
69
130
|
typecheck: 'tsc --noEmit',
|
|
70
|
-
format: 'prettier --write "client/**/*.{ts,tsx}"',
|
|
131
|
+
format: 'prettier --write "client/**/*.{ts,tsx,css,scss,less}" "client/public/**/*.html"',
|
|
71
132
|
},
|
|
72
133
|
dependencies: {
|
|
73
134
|
toiljs: `^${toilVersion}`,
|
|
74
135
|
react: '^19.2.6',
|
|
75
136
|
'react-dom': '^19.2.6',
|
|
76
137
|
},
|
|
77
|
-
devDependencies
|
|
78
|
-
'@types/react': '^19.2.15',
|
|
79
|
-
'@types/react-dom': '^19.2.3',
|
|
80
|
-
eslint: '^10.2.0',
|
|
81
|
-
prettier: '^3.8.1',
|
|
82
|
-
typescript: '^6.0.3',
|
|
83
|
-
},
|
|
138
|
+
devDependencies,
|
|
84
139
|
};
|
|
85
140
|
|
|
86
141
|
const files: Record<string, string> = {
|
|
87
142
|
'package.json': JSON.stringify(pkg, null, 4) + '\n',
|
|
88
143
|
'toil.config.ts':
|
|
89
144
|
"import { defineConfig } from 'toiljs/compiler';\n\n" +
|
|
90
|
-
'export default defineConfig({
|
|
145
|
+
'export default defineConfig({});\n',
|
|
91
146
|
'tsconfig.json':
|
|
92
147
|
'{\n "extends": "toiljs/tsconfig",\n "include": ["client", "toil-env.d.ts"]\n}\n',
|
|
93
148
|
'eslint.config.js': "import toiljs from 'toiljs/eslint';\n\nexport default toiljs;\n",
|
|
94
149
|
'.prettierrc': '"toiljs/prettier"\n',
|
|
95
|
-
'.gitignore': 'node_modules\
|
|
96
|
-
// Written upfront so the project type-checks before its first build; regenerated by build/dev.
|
|
150
|
+
'.gitignore': 'node_modules\nbuild\n.toil\ntoil-env.d.ts\n',
|
|
97
151
|
'toil-env.d.ts': TOIL_ENV_DTS,
|
|
152
|
+
'toilconfig.json':
|
|
153
|
+
JSON.stringify(
|
|
154
|
+
{
|
|
155
|
+
entries: ['server/main.ts'],
|
|
156
|
+
targets: {
|
|
157
|
+
release: {
|
|
158
|
+
outFile: 'build/server/release.wasm',
|
|
159
|
+
textFile: 'build/server/release.wat',
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
options: {
|
|
163
|
+
sourceMap: false,
|
|
164
|
+
optimizeLevel: 3,
|
|
165
|
+
shrinkLevel: 1,
|
|
166
|
+
converge: true,
|
|
167
|
+
noAssert: false,
|
|
168
|
+
enable: [
|
|
169
|
+
'sign-extension',
|
|
170
|
+
'mutable-globals',
|
|
171
|
+
'nontrapping-f2i',
|
|
172
|
+
'bulk-memory',
|
|
173
|
+
'simd',
|
|
174
|
+
'reference-types',
|
|
175
|
+
'multi-value',
|
|
176
|
+
],
|
|
177
|
+
runtime: 'stub',
|
|
178
|
+
memoryBase: 0,
|
|
179
|
+
initialMemory: 1,
|
|
180
|
+
debug: false,
|
|
181
|
+
trapMode: 'allow',
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
null,
|
|
185
|
+
4,
|
|
186
|
+
) + '\n',
|
|
187
|
+
'server/tsconfig.json':
|
|
188
|
+
JSON.stringify(
|
|
189
|
+
{
|
|
190
|
+
extends: 'toilscript/std/assembly.json',
|
|
191
|
+
include: ['./**/*.ts'],
|
|
192
|
+
},
|
|
193
|
+
null,
|
|
194
|
+
4,
|
|
195
|
+
) + '\n',
|
|
196
|
+
'server/index.ts': 'export function add(a: i32, b: i32): i32 {\n return a + b;\n}\n',
|
|
197
|
+
'server/main.ts':
|
|
198
|
+
"import { add } from './index';\n\n" +
|
|
199
|
+
'@main\nfunction run(): i32 {\n return add(40, 2);\n}\n',
|
|
98
200
|
'README.md': ['# ' + path.basename(name), '', 'A [toiljs](https://toil.org) app.', '', '## Develop', '', ' npm install', ' npm run dev', '', '## Build', '', ' npm run build', ''].join('\n'),
|
|
99
|
-
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// The `app` template's client UI is copied from templates/app at runtime; `minimal` ships an
|
|
204
|
+
// inline client here.
|
|
205
|
+
if (template === 'minimal') Object.assign(files, minimalClient(name, features));
|
|
100
206
|
|
|
101
|
-
|
|
207
|
+
// Selected AI-assistant pointer files at the root (committed). The real docs are always seeded
|
|
208
|
+
// under .toil/docs (gitignored; regenerated by dev/build) since the framework manages them.
|
|
209
|
+
Object.assign(files, aiHelperFiles(aiTools));
|
|
210
|
+
for (const [docName, content] of Object.entries(TOIL_DOCS)) {
|
|
211
|
+
files[`.toil/docs/${docName}`] = content;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return files;
|
|
215
|
+
}
|
|
102
216
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
217
|
+
/** The inline client UI for the `minimal` template (the `app` template copies templates/app). */
|
|
218
|
+
function minimalClient(name: string, features: StyleFeatures): Record<string, string> {
|
|
219
|
+
const files: Record<string, string> = {
|
|
220
|
+
'client/public/index.html':
|
|
221
|
+
'<!doctype html>\n<html lang="en">\n <head>\n' +
|
|
222
|
+
' <meta charset="utf-8" />\n' +
|
|
223
|
+
' <meta name="viewport" content="width=device-width, initial-scale=1" />\n' +
|
|
224
|
+
' <meta name="theme-color" content="#080D11" />\n' +
|
|
225
|
+
' <meta name="description" content="" />\n' +
|
|
226
|
+
' <link rel="icon" type="image/svg+xml" href="/favicon.svg" />\n' +
|
|
227
|
+
' <link rel="manifest" href="/manifest.webmanifest" />\n' +
|
|
228
|
+
` <title>${path.basename(name)}</title>\n` +
|
|
229
|
+
' </head>\n <body>\n <div id="root"></div>\n </body>\n</html>\n',
|
|
230
|
+
'client/public/favicon.svg':
|
|
231
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">\n' +
|
|
232
|
+
' <defs>\n' +
|
|
233
|
+
' <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">\n' +
|
|
234
|
+
' <stop offset="0" stop-color="#2563FF" />\n' +
|
|
235
|
+
' <stop offset="0.5" stop-color="#7C3AED" />\n' +
|
|
236
|
+
' <stop offset="1" stop-color="#22E3AB" />\n' +
|
|
237
|
+
' </linearGradient>\n' +
|
|
238
|
+
' </defs>\n' +
|
|
239
|
+
' <rect width="32" height="32" rx="7" fill="#080D11" />\n' +
|
|
240
|
+
' <path d="M9 10h14v3.2h-5.4V24h-3.2V13.2H9z" fill="url(#g)" />\n' +
|
|
241
|
+
'</svg>\n',
|
|
242
|
+
'client/public/robots.txt': 'User-agent: *\nAllow: /\n',
|
|
243
|
+
'client/public/manifest.webmanifest':
|
|
244
|
+
JSON.stringify(
|
|
245
|
+
{
|
|
246
|
+
name: path.basename(name),
|
|
247
|
+
short_name: path.basename(name),
|
|
248
|
+
start_url: '/',
|
|
249
|
+
display: 'standalone',
|
|
250
|
+
background_color: '#080D11',
|
|
251
|
+
theme_color: '#080D11',
|
|
252
|
+
icons: [{ src: '/favicon.svg', type: 'image/svg+xml', sizes: 'any' }],
|
|
253
|
+
},
|
|
254
|
+
null,
|
|
255
|
+
4,
|
|
256
|
+
) + '\n',
|
|
257
|
+
'client/public/images/.gitkeep': '# Place images and other static assets here; served at /images/*.\n',
|
|
258
|
+
'client/toil.tsx':
|
|
259
|
+
"import { routes, layout, notFound } from 'toiljs/routes';\n\n" +
|
|
260
|
+
styleImportLines(features).join('\n') +
|
|
261
|
+
'\n\n' +
|
|
262
|
+
'Toil.mount(routes, layout, notFound);\n',
|
|
263
|
+
[`client/${styleEntry(features.preprocessor)}`]: DEFAULT_STYLE_CONTENT,
|
|
264
|
+
'client/components/.gitkeep': '# Place shared React components here.\n',
|
|
265
|
+
'client/layout.tsx': `import { type ReactNode } from 'react';
|
|
111
266
|
|
|
112
267
|
export default function Layout({ children }: { children?: ReactNode }) {
|
|
113
268
|
return (
|
|
114
269
|
<div style={{ maxWidth: 680, margin: '0 auto', padding: '3rem 1.5rem' }}>
|
|
115
|
-
<style>{styles}</style>
|
|
116
270
|
<header
|
|
117
271
|
style={{
|
|
118
272
|
display: 'flex',
|
|
@@ -124,7 +278,7 @@ export default function Layout({ children }: { children?: ReactNode }) {
|
|
|
124
278
|
}}>
|
|
125
279
|
<strong style={{ color: '#2563FF', fontSize: '1.1rem' }}>${path.basename(name)}</strong>
|
|
126
280
|
<nav style={{ display: 'flex', gap: '1rem' }}>
|
|
127
|
-
<Link href="/">home</Link
|
|
281
|
+
<Toil.Link href="/">home</Toil.Link>
|
|
128
282
|
</nav>
|
|
129
283
|
</header>
|
|
130
284
|
{children}
|
|
@@ -133,34 +287,37 @@ export default function Layout({ children }: { children?: ReactNode }) {
|
|
|
133
287
|
}
|
|
134
288
|
`,
|
|
135
289
|
'client/routes/index.tsx':
|
|
136
|
-
"import { Link } from 'toiljs/client';\n\n" +
|
|
137
290
|
'export default function Home() {\n' +
|
|
138
291
|
' return (\n <main>\n' +
|
|
139
292
|
' <h1>Welcome to toiljs</h1>\n' +
|
|
140
293
|
' <p>File-based routing, bundled by Vite, zero config.</p>\n' +
|
|
141
|
-
(template === 'app'
|
|
142
|
-
? ' <p>\n <Link href="/about">About</Link> · <Link href="/blog/42">Blog post 42</Link>\n </p>\n'
|
|
143
|
-
: '') +
|
|
144
294
|
' </main>\n );\n}\n',
|
|
145
295
|
};
|
|
296
|
+
if (features.tailwind) files[`client/${TAILWIND_ENTRY}`] = TAILWIND_CSS;
|
|
297
|
+
return files;
|
|
298
|
+
}
|
|
146
299
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
' return (\n <main>\n <h1>About</h1>\n' +
|
|
152
|
-
' <p>\n This page is served by <code>client/routes/about.tsx</code>.\n </p>\n' +
|
|
153
|
-
' <Link href="/">Back home</Link>\n </main>\n );\n}\n';
|
|
154
|
-
files['client/routes/blog/[id].tsx'] =
|
|
155
|
-
"import { Link, useParams } from 'toiljs/client';\n\n" +
|
|
156
|
-
'export default function BlogPost() {\n' +
|
|
157
|
-
' const { id } = useParams();\n' +
|
|
158
|
-
' return (\n <main>\n <h1>Blog post {id}</h1>\n' +
|
|
159
|
-
' <p>\n Dynamic route from <code>client/routes/blog/[id].tsx</code>.\n </p>\n' +
|
|
160
|
-
' <Link href="/">Back home</Link>\n </main>\n );\n}\n';
|
|
161
|
-
}
|
|
300
|
+
/** Absolute path to a shipped template directory (e.g. `templates/app`). */
|
|
301
|
+
function templateDir(template: Template): string {
|
|
302
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'templates', template);
|
|
303
|
+
}
|
|
162
304
|
|
|
163
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Applies the chosen styling to a copied template's client dir: renames the stylesheet to the
|
|
307
|
+
* preprocessor's extension, adds the Tailwind entry, and rewrites `toil.tsx`'s style imports.
|
|
308
|
+
*/
|
|
309
|
+
async function applyStyling(clientDir: string, features: StyleFeatures): Promise<void> {
|
|
310
|
+
// Plain CSS without Tailwind is exactly what the template ships — leave it byte-for-byte.
|
|
311
|
+
if (features.preprocessor === 'css' && !features.tailwind) return;
|
|
312
|
+
const entry = styleEntry(features.preprocessor);
|
|
313
|
+
if (entry !== 'styles/main.css') {
|
|
314
|
+
await fs.rename(path.join(clientDir, 'styles', 'main.css'), path.join(clientDir, entry));
|
|
315
|
+
}
|
|
316
|
+
if (features.tailwind) {
|
|
317
|
+
await fs.writeFile(path.join(clientDir, TAILWIND_ENTRY), TAILWIND_CSS, 'utf8');
|
|
318
|
+
}
|
|
319
|
+
const toilPath = path.join(clientDir, 'toil.tsx');
|
|
320
|
+
await fs.writeFile(toilPath, setStyleImports(await fs.readFile(toilPath, 'utf8'), features), 'utf8');
|
|
164
321
|
}
|
|
165
322
|
|
|
166
323
|
async function writeFiles(dir: string, files: Record<string, string>): Promise<void> {
|
|
@@ -171,27 +328,10 @@ async function writeFiles(dir: string, files: Record<string, string>): Promise<v
|
|
|
171
328
|
}
|
|
172
329
|
}
|
|
173
330
|
|
|
174
|
-
function run(cmd: string, args: string[], cwd: string): Promise<void> {
|
|
175
|
-
return new Promise((resolve, reject) => {
|
|
176
|
-
// On Windows `npm`/`pnpm`/`yarn` are `.cmd` shims that need a shell to launch. Passing an
|
|
177
|
-
// args array together with `shell: true` is deprecated (DEP0190), so pass the whole command
|
|
178
|
-
// as one string there (the args are fixed, not user input). POSIX runs it directly.
|
|
179
|
-
const onWindows = process.platform === 'win32';
|
|
180
|
-
const child = onWindows
|
|
181
|
-
? spawn([cmd, ...args].join(' '), { cwd, stdio: 'ignore', shell: true })
|
|
182
|
-
: spawn(cmd, args, { cwd, stdio: 'ignore' });
|
|
183
|
-
child.on('error', reject);
|
|
184
|
-
child.on('close', (code) =>
|
|
185
|
-
code === 0 ? resolve() : reject(new Error(`${cmd} exited with code ${String(code)}`)),
|
|
186
|
-
);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
331
|
/** Runs the create flow (interactive unless `--yes`). */
|
|
191
332
|
export async function runCreate(opts: CreateOptions): Promise<void> {
|
|
192
333
|
intro(accent(' toiljs create '));
|
|
193
334
|
|
|
194
|
-
// 1. Project name
|
|
195
335
|
let name = opts.name;
|
|
196
336
|
if (!name) {
|
|
197
337
|
if (opts.yes) {
|
|
@@ -216,10 +356,13 @@ export async function runCreate(opts: CreateOptions): Promise<void> {
|
|
|
216
356
|
process.exit(1);
|
|
217
357
|
}
|
|
218
358
|
|
|
219
|
-
const targetDir =
|
|
359
|
+
const targetDir = resolveProjectDir(opts.cwd, name);
|
|
360
|
+
if (targetDir === null) {
|
|
361
|
+
cancel('Project name must stay inside the current directory (no "..", no absolute paths).');
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
220
364
|
const rel = path.relative(opts.cwd, targetDir) || '.';
|
|
221
365
|
|
|
222
|
-
// 2. Guard against clobbering a non-empty dir
|
|
223
366
|
if (!(await isEmptyDir(targetDir))) {
|
|
224
367
|
if (opts.yes) {
|
|
225
368
|
cancel(`Directory ${pc.cyan(rel)} is not empty.`);
|
|
@@ -236,11 +379,10 @@ export async function runCreate(opts: CreateOptions): Promise<void> {
|
|
|
236
379
|
}
|
|
237
380
|
}
|
|
238
381
|
|
|
239
|
-
// 3. Template
|
|
240
382
|
let template: Template = opts.template ?? 'app';
|
|
241
383
|
if (!opts.template && !opts.yes) {
|
|
242
384
|
const templateOptions: TemplateOption[] = [
|
|
243
|
-
{ value: 'app', label: 'App', hint: '
|
|
385
|
+
{ value: 'app', label: 'App', hint: 'the full ToilJS starter — landing page, layout, styles, demo routes' },
|
|
244
386
|
{ value: 'minimal', label: 'Minimal', hint: 'just a layout and a home route' },
|
|
245
387
|
];
|
|
246
388
|
const choice = await select({ message: 'Which template?', options: templateOptions, initialValue: 'app' });
|
|
@@ -248,10 +390,46 @@ export async function runCreate(opts: CreateOptions): Promise<void> {
|
|
|
248
390
|
template = choice === 'minimal' ? 'minimal' : 'app';
|
|
249
391
|
}
|
|
250
392
|
|
|
251
|
-
|
|
393
|
+
let preprocessor: Preprocessor = opts.preprocessor ?? 'css';
|
|
394
|
+
let tailwind = opts.tailwind ?? false;
|
|
395
|
+
if (!opts.yes) {
|
|
396
|
+
if (opts.preprocessor === undefined) {
|
|
397
|
+
const choice = await select<Preprocessor>({
|
|
398
|
+
message: 'Styling',
|
|
399
|
+
options: PREPROCESSORS.map((value) => ({ value, label: PREPROCESSOR_LABEL[value] })),
|
|
400
|
+
initialValue: 'css',
|
|
401
|
+
});
|
|
402
|
+
bail(choice);
|
|
403
|
+
preprocessor = choice;
|
|
404
|
+
}
|
|
405
|
+
if (opts.tailwind === undefined) {
|
|
406
|
+
const tw = await confirm({ message: 'Add Tailwind CSS?', initialValue: false });
|
|
407
|
+
bail(tw);
|
|
408
|
+
tailwind = tw;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
const features: StyleFeatures = { preprocessor, tailwind };
|
|
412
|
+
|
|
413
|
+
// AI assistant files: --ai = all, --no-ai = none, otherwise ask (default: all selected).
|
|
414
|
+
let aiTools: string[] = opts.ai === false ? [] : [...AI_HELPER_IDS];
|
|
415
|
+
if (opts.ai === undefined && !opts.yes) {
|
|
416
|
+
const picked = await multiselect<string>({
|
|
417
|
+
message: 'AI assistant files (read by Claude, Cursor, Codex, Copilot)',
|
|
418
|
+
options: AI_HELPERS.map((h) => ({ value: h.id, label: h.label })),
|
|
419
|
+
initialValues: [...AI_HELPER_IDS],
|
|
420
|
+
required: false,
|
|
421
|
+
});
|
|
422
|
+
bail(picked);
|
|
423
|
+
aiTools = picked;
|
|
424
|
+
}
|
|
425
|
+
|
|
252
426
|
let initGit = opts.git ?? false;
|
|
253
427
|
let install = opts.install ?? false;
|
|
254
428
|
const pm = opts.pm ?? 'npm';
|
|
429
|
+
if (!isPackageManager(pm)) {
|
|
430
|
+
cancel(`Unsupported package manager: ${pm} (use npm, pnpm, yarn, or bun).`);
|
|
431
|
+
process.exit(1);
|
|
432
|
+
}
|
|
255
433
|
if (!opts.yes) {
|
|
256
434
|
if (opts.git === undefined) {
|
|
257
435
|
const g = await confirm({ message: 'Initialize a git repository?', initialValue: true });
|
|
@@ -265,13 +443,22 @@ export async function runCreate(opts: CreateOptions): Promise<void> {
|
|
|
265
443
|
}
|
|
266
444
|
}
|
|
267
445
|
|
|
268
|
-
// 5. Scaffold
|
|
269
446
|
const s = spinner();
|
|
270
447
|
s.start('Scaffolding project');
|
|
271
|
-
await writeFiles(targetDir, scaffold(name, template));
|
|
448
|
+
await writeFiles(targetDir, scaffold(name, template, features, aiTools));
|
|
449
|
+
if (template === 'app') {
|
|
450
|
+
// Copy the full ToilJS starter UI, set its <title> to the project name, then apply styling.
|
|
451
|
+
await fs.cp(templateDir('app'), targetDir, { recursive: true });
|
|
452
|
+
const indexHtml = path.join(targetDir, 'client', 'public', 'index.html');
|
|
453
|
+
const html = await fs.readFile(indexHtml, 'utf8');
|
|
454
|
+
await fs.writeFile(
|
|
455
|
+
indexHtml,
|
|
456
|
+
html.replace(/<title>[^<]*<\/title>/, `<title>${path.basename(name)}</title>`),
|
|
457
|
+
);
|
|
458
|
+
await applyStyling(path.join(targetDir, 'client'), features);
|
|
459
|
+
}
|
|
272
460
|
s.stop(`Scaffolded ${pc.cyan(rel)}`);
|
|
273
461
|
|
|
274
|
-
// 6. git init (best-effort)
|
|
275
462
|
if (initGit) {
|
|
276
463
|
const g = spinner();
|
|
277
464
|
g.start('Initializing git repository');
|
|
@@ -284,7 +471,6 @@ export async function runCreate(opts: CreateOptions): Promise<void> {
|
|
|
284
471
|
}
|
|
285
472
|
}
|
|
286
473
|
|
|
287
|
-
// 7. Install (best-effort)
|
|
288
474
|
if (install) {
|
|
289
475
|
const i = spinner();
|
|
290
476
|
i.start(`Installing dependencies with ${pm}`);
|
|
@@ -297,7 +483,6 @@ export async function runCreate(opts: CreateOptions): Promise<void> {
|
|
|
297
483
|
}
|
|
298
484
|
}
|
|
299
485
|
|
|
300
|
-
// 8. Next steps
|
|
301
486
|
const steps: string[] = [];
|
|
302
487
|
if (rel !== '.') steps.push(`cd ${rel}`);
|
|
303
488
|
if (!install) steps.push('npm install');
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure description of toiljs's optional client styling features — a CSS preprocessor and Tailwind —
|
|
3
|
+
* shared by `create` (scaffold) and `configure` (toggle on existing projects). Dependency-light
|
|
4
|
+
* (no node IO) so it can be unit-tested; the file writes and package-manager calls live in the
|
|
5
|
+
* commands. Preprocessor and Tailwind are independent: Tailwind lives in its own `.css` entry so
|
|
6
|
+
* it never passes through (and breaks on) a preprocessor's `@import` resolution.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Supported CSS preprocessor (`css` = none). */
|
|
10
|
+
export type Preprocessor = 'css' | 'sass' | 'less' | 'stylus';
|
|
11
|
+
|
|
12
|
+
/** The two independently-toggleable styling features of a project. */
|
|
13
|
+
export interface StyleFeatures {
|
|
14
|
+
readonly preprocessor: Preprocessor;
|
|
15
|
+
readonly tailwind: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const PREPROCESSORS: readonly Preprocessor[] = ['css', 'sass', 'less', 'stylus'];
|
|
19
|
+
|
|
20
|
+
/** Main stylesheet extension for each preprocessor. */
|
|
21
|
+
export const STYLE_EXT: Record<Preprocessor, string> = {
|
|
22
|
+
css: 'css',
|
|
23
|
+
sass: 'scss',
|
|
24
|
+
less: 'less',
|
|
25
|
+
stylus: 'styl',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** npm package that enables each preprocessor in Vite (plain CSS needs none). */
|
|
29
|
+
export const PREPROCESSOR_PKG: Record<Preprocessor, string | null> = {
|
|
30
|
+
css: null,
|
|
31
|
+
sass: 'sass',
|
|
32
|
+
less: 'less',
|
|
33
|
+
stylus: 'stylus',
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Tailwind v4 packages. The framework auto-wires the Vite plugin when `@tailwindcss/vite` resolves. */
|
|
37
|
+
export const TAILWIND_PKGS: readonly string[] = ['tailwindcss', '@tailwindcss/vite'];
|
|
38
|
+
|
|
39
|
+
/** Pinned versions for every package these features may install. */
|
|
40
|
+
export const PKG_VERSION: Record<string, string> = {
|
|
41
|
+
sass: '^1.83.0',
|
|
42
|
+
less: '^4.2.1',
|
|
43
|
+
stylus: '^0.64.0',
|
|
44
|
+
tailwindcss: '^4.0.0',
|
|
45
|
+
'@tailwindcss/vite': '^4.0.0',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/** Dedicated Tailwind entry (kept `.css` so no preprocessor touches its `@import`). */
|
|
49
|
+
export const TAILWIND_ENTRY = 'styles/tailwind.css';
|
|
50
|
+
export const TAILWIND_CSS = `@import 'tailwindcss';\n`;
|
|
51
|
+
|
|
52
|
+
/** Path (relative to `client/`) of the main stylesheet for a preprocessor. */
|
|
53
|
+
export function styleEntry(p: Preprocessor): string {
|
|
54
|
+
return `styles/main.${STYLE_EXT[p]}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** The preprocessor whose main stylesheet uses `ext` (with or without a leading dot), or null. */
|
|
58
|
+
export function preprocessorForExt(ext: string): Preprocessor | null {
|
|
59
|
+
const e = ext.replace(/^\./, '');
|
|
60
|
+
if (e === 'sass') return 'sass';
|
|
61
|
+
return PREPROCESSORS.find((p) => STYLE_EXT[p] === e) ?? null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Packages required by a feature set (preprocessor package + Tailwind packages). */
|
|
65
|
+
export function requiredPackages(f: StyleFeatures): string[] {
|
|
66
|
+
const pkgs: string[] = [];
|
|
67
|
+
const pp = PREPROCESSOR_PKG[f.preprocessor];
|
|
68
|
+
if (pp) pkgs.push(pp);
|
|
69
|
+
if (f.tailwind) pkgs.push(...TAILWIND_PKGS);
|
|
70
|
+
return pkgs;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Managed packages to add and remove when moving from `from` to `to`. */
|
|
74
|
+
export function packageDiff(
|
|
75
|
+
from: StyleFeatures,
|
|
76
|
+
to: StyleFeatures,
|
|
77
|
+
): { add: string[]; remove: string[] } {
|
|
78
|
+
const want = new Set(requiredPackages(to));
|
|
79
|
+
const had = new Set(requiredPackages(from));
|
|
80
|
+
return {
|
|
81
|
+
add: [...want].filter((p) => !had.has(p)),
|
|
82
|
+
remove: [...had].filter((p) => !want.has(p)),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The side-effect style imports for the app entry, Tailwind first so app CSS can override it. */
|
|
87
|
+
export function styleImportLines(f: StyleFeatures): string[] {
|
|
88
|
+
const lines: string[] = [];
|
|
89
|
+
if (f.tailwind) lines.push(`import './${TAILWIND_ENTRY}';`);
|
|
90
|
+
lines.push(`import './${styleEntry(f.preprocessor)}';`);
|
|
91
|
+
return lines;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Rewrites the `./styles/*` side-effect imports in an app entry (`client/toil.tsx`) to match
|
|
96
|
+
* `features`, preserving the rest of the file. Existing style imports are removed and the new
|
|
97
|
+
* block is placed after the `toiljs/routes` import (or the last import, or the top).
|
|
98
|
+
*/
|
|
99
|
+
export function setStyleImports(source: string, f: StyleFeatures): string {
|
|
100
|
+
const stripped = source.replace(/^[ \t]*import\s+['"]\.\/styles\/[^'"]+['"];?[ \t]*\r?\n/gm, '');
|
|
101
|
+
const block = styleImportLines(f).join('\n') + '\n';
|
|
102
|
+
|
|
103
|
+
const lines = stripped.split('\n');
|
|
104
|
+
const routesIdx = lines.findIndex((l) => /from\s+['"]toiljs\/routes['"]/.test(l));
|
|
105
|
+
let insertAt: number;
|
|
106
|
+
if (routesIdx !== -1) {
|
|
107
|
+
insertAt = routesIdx + 1;
|
|
108
|
+
} else {
|
|
109
|
+
const lastImport = lines.reduce((acc, l, i) => (/^\s*import\s/.test(l) ? i : acc), -1);
|
|
110
|
+
insertAt = lastImport + 1;
|
|
111
|
+
}
|
|
112
|
+
const head = lines.slice(0, insertAt).join('\n');
|
|
113
|
+
const tail = lines.slice(insertAt).join('\n');
|
|
114
|
+
return `${head}\n\n${block}\n${tail}`.replace(/\n{3,}/g, '\n\n');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Detects the active preprocessor from a project's combined dependency map. */
|
|
118
|
+
export function detectPreprocessor(deps: Record<string, string>): Preprocessor {
|
|
119
|
+
if ('sass' in deps) return 'sass';
|
|
120
|
+
if ('less' in deps) return 'less';
|
|
121
|
+
if ('stylus' in deps) return 'stylus';
|
|
122
|
+
return 'css';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Whether Tailwind is installed in a project's combined dependency map. */
|
|
126
|
+
export function detectTailwind(deps: Record<string, string>): boolean {
|
|
127
|
+
return '@tailwindcss/vite' in deps || 'tailwindcss' in deps;
|
|
128
|
+
}
|