toiljs 0.0.15 → 0.0.19

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 (273) hide show
  1. package/.babelrc +13 -13
  2. package/.gitattributes +2 -2
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -90
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -8
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  7. package/.github/PULL_REQUEST_TEMPLATE.md +43 -43
  8. package/.github/changelog-config.json +45 -45
  9. package/.github/dependabot.yml +27 -27
  10. package/.github/workflows/ci.yml +191 -191
  11. package/.prettierrc.json +11 -11
  12. package/.vscode/settings.json +9 -9
  13. package/CHANGELOG.md +116 -5
  14. package/LICENSE +187 -187
  15. package/README.md +524 -315
  16. package/as-pect.asconfig.json +34 -34
  17. package/as-pect.config.js +65 -65
  18. package/assets/logo.svg +36 -36
  19. package/build/backend/.tsbuildinfo +1 -1
  20. package/build/backend/index.d.ts +1 -0
  21. package/build/backend/index.js +20 -1
  22. package/build/cli/.tsbuildinfo +1 -1
  23. package/build/cli/index.js +1320 -696
  24. package/build/client/.tsbuildinfo +1 -1
  25. package/build/client/dev/devtools.d.ts +6 -0
  26. package/build/client/dev/devtools.js +479 -0
  27. package/build/client/dev/error-overlay.d.ts +9 -0
  28. package/build/client/dev/error-overlay.js +19 -4
  29. package/build/client/errors.d.ts +1 -0
  30. package/build/client/errors.js +3 -0
  31. package/build/client/index.d.ts +2 -0
  32. package/build/client/index.js +2 -0
  33. package/build/client/navigation/prefetch.d.ts +1 -0
  34. package/build/client/navigation/prefetch.js +35 -0
  35. package/build/client/routing/Router.js +1 -1
  36. package/build/client/routing/hooks.js +6 -2
  37. package/build/client/routing/loader.d.ts +23 -0
  38. package/build/client/routing/loader.js +53 -7
  39. package/build/client/routing/mount.js +4 -3
  40. package/build/client/rpc.d.ts +1 -0
  41. package/build/client/rpc.js +37 -0
  42. package/build/compiler/.tsbuildinfo +1 -1
  43. package/build/compiler/config.d.ts +16 -0
  44. package/build/compiler/config.js +9 -0
  45. package/build/compiler/docs.js +78 -21
  46. package/build/compiler/generate.js +5 -4
  47. package/build/compiler/index.d.ts +3 -2
  48. package/build/compiler/index.js +2 -2
  49. package/build/compiler/plugin.js +228 -0
  50. package/build/compiler/prerender.d.ts +1 -0
  51. package/build/compiler/prerender.js +1 -1
  52. package/build/compiler/seo.d.ts +1 -1
  53. package/build/compiler/seo.js +20 -5
  54. package/build/compiler/ssg.js +39 -2
  55. package/build/compiler/vite.js +25 -0
  56. package/build/io/.tsbuildinfo +1 -1
  57. package/build/io/codec.d.ts +54 -0
  58. package/build/io/codec.js +143 -0
  59. package/build/io/index.d.ts +1 -2
  60. package/build/io/index.js +1 -2
  61. package/build/logger/.tsbuildinfo +1 -1
  62. package/build/shared/.tsbuildinfo +1 -1
  63. package/eslint.config.js +48 -48
  64. package/examples/basic/client/404.tsx +11 -11
  65. package/examples/basic/client/components/.gitkeep +1 -1
  66. package/examples/basic/client/global-error.tsx +13 -13
  67. package/examples/basic/client/layout.tsx +25 -25
  68. package/examples/basic/client/public/images/.gitkeep +1 -1
  69. package/examples/basic/client/public/images/logo.svg +36 -36
  70. package/examples/basic/client/public/robots.txt +2 -2
  71. package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
  72. package/examples/basic/client/routes/features/error/error.tsx +16 -16
  73. package/examples/basic/client/routes/features/index.tsx +1 -1
  74. package/examples/basic/client/routes/features/template/b.tsx +14 -14
  75. package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
  76. package/examples/basic/client/routes/gallery/layout.tsx +13 -13
  77. package/examples/basic/client/routes/io.tsx +23 -24
  78. package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
  79. package/examples/basic/client/routes/rest.tsx +74 -0
  80. package/examples/basic/client/routes/rpc.tsx +43 -0
  81. package/examples/basic/client/routes/search.tsx +61 -61
  82. package/examples/basic/client/toil.tsx +5 -5
  83. package/package.json +167 -148
  84. package/presets/eslint.js +88 -88
  85. package/presets/no-uint8array-tostring.js +200 -200
  86. package/presets/prettier-plugin.js +51 -0
  87. package/presets/prettier.json +19 -18
  88. package/presets/tsconfig.json +37 -37
  89. package/server/runtime/README.md +97 -0
  90. package/server/runtime/abort/abort.ts +27 -0
  91. package/server/runtime/env/Server.ts +61 -0
  92. package/server/runtime/envelope.ts +191 -0
  93. package/server/runtime/exports/index.ts +52 -0
  94. package/server/runtime/handlers/ToilHandler.ts +34 -0
  95. package/server/runtime/index.ts +26 -0
  96. package/server/runtime/lang/Potential.ts +5 -0
  97. package/server/runtime/memory.ts +81 -0
  98. package/server/runtime/request.ts +55 -0
  99. package/server/runtime/response.ts +86 -0
  100. package/server/runtime/rest/Rest.ts +39 -0
  101. package/server/runtime/rest/RestHandler.ts +20 -0
  102. package/server/runtime/rest/RouteContext.ts +82 -0
  103. package/server/runtime/rest/match.ts +48 -0
  104. package/server/runtime/tsconfig.json +7 -0
  105. package/src/backend/index.ts +202 -160
  106. package/src/cli/create.ts +15 -5
  107. package/src/cli/diagnostics.ts +81 -0
  108. package/src/cli/doctor.ts +384 -7
  109. package/src/cli/index.ts +11 -2
  110. package/src/cli/proc.ts +50 -50
  111. package/src/cli/updates.ts +69 -69
  112. package/src/cli/validate.ts +31 -31
  113. package/src/client/channel/channel.ts +146 -146
  114. package/src/client/components/Form.tsx +65 -65
  115. package/src/client/components/Script.tsx +113 -113
  116. package/src/client/components/Slot.tsx +21 -21
  117. package/src/client/dev/devtools.tsx +1018 -0
  118. package/src/client/dev/error-overlay.tsx +30 -4
  119. package/src/client/errors.ts +11 -0
  120. package/src/client/head/head.ts +167 -167
  121. package/src/client/head/metadata.ts +112 -112
  122. package/src/client/index.ts +91 -89
  123. package/src/client/navigation/NavLink.tsx +86 -86
  124. package/src/client/navigation/navigation.ts +235 -235
  125. package/src/client/navigation/prefetch.ts +169 -130
  126. package/src/client/navigation/scroll.ts +53 -53
  127. package/src/client/routing/Router.tsx +8 -2
  128. package/src/client/routing/action.ts +122 -122
  129. package/src/client/routing/error-boundary.tsx +43 -43
  130. package/src/client/routing/hooks.ts +21 -6
  131. package/src/client/routing/loader.ts +325 -235
  132. package/src/client/routing/match.ts +47 -47
  133. package/src/client/routing/mount.tsx +54 -52
  134. package/src/client/routing/params-context.ts +10 -10
  135. package/src/client/routing/slot-context.ts +7 -7
  136. package/src/client/rpc.ts +64 -0
  137. package/src/client/search/search.ts +189 -189
  138. package/src/client/search/use-page-search.ts +73 -73
  139. package/src/client/types.ts +73 -73
  140. package/src/compiler/config.ts +221 -182
  141. package/src/compiler/docs.ts +285 -228
  142. package/src/compiler/generate.ts +395 -394
  143. package/src/compiler/index.ts +66 -57
  144. package/src/compiler/pages.ts +70 -70
  145. package/src/compiler/plugin.ts +258 -2
  146. package/src/compiler/prerender.ts +156 -156
  147. package/src/compiler/seo.ts +417 -390
  148. package/src/compiler/ssg.ts +171 -126
  149. package/src/compiler/vite.ts +34 -0
  150. package/src/io/FastMap.ts +151 -127
  151. package/src/io/FastSet.ts +15 -1
  152. package/src/io/codec.ts +217 -0
  153. package/src/io/index.ts +10 -11
  154. package/src/io/lengths.ts +14 -14
  155. package/src/io/types.ts +19 -18
  156. package/src/logger/index.ts +22 -22
  157. package/src/shared/index.ts +10 -10
  158. package/std/client/index.d.ts +15 -15
  159. package/std/client/package.json +3 -3
  160. package/test/assembly/example.spec.ts +17 -7
  161. package/test/channel.test.ts +21 -21
  162. package/test/doctor.test.ts +65 -0
  163. package/test/dom/Link.test.tsx +47 -47
  164. package/test/dom/NavLink.test.tsx +37 -37
  165. package/test/dom/error-overlay.test.tsx +44 -44
  166. package/test/dom/loader.test.tsx +121 -121
  167. package/test/dom/navigation.test.ts +59 -59
  168. package/test/dom/revalidate.test.tsx +38 -38
  169. package/test/dom/route-head.test.tsx +78 -78
  170. package/test/dom/router-loading.test.tsx +44 -44
  171. package/test/dom/scroll.test.ts +56 -56
  172. package/test/dom/use-metadata.test.tsx +58 -58
  173. package/test/errors.test.ts +21 -0
  174. package/test/io.test.ts +117 -93
  175. package/test/navlink.test.ts +28 -28
  176. package/test/placeholder.test.ts +9 -9
  177. package/test/prettier-plugin.test.ts +46 -0
  178. package/test/routes.test.ts +76 -76
  179. package/test/rpc.test.ts +50 -0
  180. package/test/seo.test.ts +175 -164
  181. package/test/slot-layouts.test.ts +69 -69
  182. package/test/ssg.test.ts +36 -36
  183. package/test/update.test.ts +44 -44
  184. package/test/validate.test.ts +42 -42
  185. package/tests/data-parity/generated-parity.ts +99 -0
  186. package/tests/data-parity/parity.ts +80 -0
  187. package/tests/data-parity/spec.ts +46 -0
  188. package/toil-routes.d.ts +7 -0
  189. package/tsconfig.backend.json +13 -13
  190. package/tsconfig.base.json +35 -35
  191. package/tsconfig.cli.json +13 -13
  192. package/tsconfig.client.json +14 -14
  193. package/tsconfig.compiler.json +13 -13
  194. package/tsconfig.io.json +12 -12
  195. package/tsconfig.json +22 -22
  196. package/tsconfig.logger.json +12 -12
  197. package/tsconfig.server.json +10 -10
  198. package/tsconfig.shared.json +12 -12
  199. package/vitest.config.ts +26 -26
  200. package/.idea/codeStyles/Project.xml +0 -54
  201. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  202. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  203. package/.idea/modules.xml +0 -8
  204. package/.idea/prettier.xml +0 -7
  205. package/.idea/toiljs.iml +0 -8
  206. package/.idea/vcs.xml +0 -6
  207. package/.toil/entry.tsx +0 -9
  208. package/.toil/index.html +0 -12
  209. package/.toil/routes.ts +0 -9
  210. package/build/cli/configure.d.ts +0 -16
  211. package/build/cli/configure.js +0 -272
  212. package/build/cli/create.d.ts +0 -16
  213. package/build/cli/create.js +0 -420
  214. package/build/cli/diagnostics.d.ts +0 -55
  215. package/build/cli/diagnostics.js +0 -333
  216. package/build/cli/doctor.d.ts +0 -6
  217. package/build/cli/doctor.js +0 -249
  218. package/build/cli/features.d.ts +0 -25
  219. package/build/cli/features.js +0 -107
  220. package/build/cli/index.d.ts +0 -2
  221. package/build/cli/proc.d.ts +0 -6
  222. package/build/cli/proc.js +0 -31
  223. package/build/cli/ui.d.ts +0 -9
  224. package/build/cli/ui.js +0 -75
  225. package/build/cli/update.d.ts +0 -7
  226. package/build/cli/update.js +0 -117
  227. package/build/cli/updates.d.ts +0 -10
  228. package/build/cli/updates.js +0 -45
  229. package/build/cli/validate.d.ts +0 -4
  230. package/build/cli/validate.js +0 -19
  231. package/build/client/Link.d.ts +0 -8
  232. package/build/client/Link.js +0 -44
  233. package/build/client/NavLink.d.ts +0 -14
  234. package/build/client/NavLink.js +0 -37
  235. package/build/client/Router.d.ts +0 -7
  236. package/build/client/Router.js +0 -55
  237. package/build/client/channel.d.ts +0 -23
  238. package/build/client/channel.js +0 -94
  239. package/build/client/error-boundary.d.ts +0 -16
  240. package/build/client/error-boundary.js +0 -19
  241. package/build/client/head.d.ts +0 -26
  242. package/build/client/head.js +0 -87
  243. package/build/client/hooks.d.ts +0 -17
  244. package/build/client/hooks.js +0 -48
  245. package/build/client/lazy.d.ts +0 -16
  246. package/build/client/lazy.js +0 -53
  247. package/build/client/match.d.ts +0 -2
  248. package/build/client/match.js +0 -32
  249. package/build/client/mount.d.ts +0 -2
  250. package/build/client/mount.js +0 -13
  251. package/build/client/navigation.d.ts +0 -13
  252. package/build/client/navigation.js +0 -97
  253. package/build/client/params-context.d.ts +0 -2
  254. package/build/client/params-context.js +0 -2
  255. package/build/client/prefetch.d.ts +0 -11
  256. package/build/client/prefetch.js +0 -100
  257. package/build/client/runtime.d.ts +0 -31
  258. package/build/client/runtime.js +0 -112
  259. package/build/client/scroll.d.ts +0 -8
  260. package/build/client/scroll.js +0 -36
  261. package/build/io/BinaryReader.d.ts +0 -44
  262. package/build/io/BinaryReader.js +0 -244
  263. package/build/io/BinaryWriter.d.ts +0 -44
  264. package/build/io/BinaryWriter.js +0 -297
  265. package/build/server/release.wasm +0 -0
  266. package/build/server/release.wat +0 -9
  267. package/src/io/BinaryReader.ts +0 -340
  268. package/src/io/BinaryWriter.ts +0 -385
  269. package/src/server/index.ts +0 -10
  270. package/src/server/main.ts +0 -13
  271. package/src/server/tsconfig.json +0 -4
  272. package/toil-env.d.ts +0 -16
  273. package/toilconfig.json +0 -30
@@ -1,420 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { cancel, confirm, intro, isCancel, multiselect, note, outro, select, spinner, text, } from '@clack/prompts';
5
- import { AI_HELPER_IDS, AI_HELPERS, aiHelperFiles, TOIL_DOCS, TOIL_ENV_DTS } from 'toiljs/compiler';
6
- import pc from 'picocolors';
7
- import { PKG_VERSION, PREPROCESSORS, requiredPackages, setStyleImports, styleEntry, styleImportLines, TAILWIND_CSS, TAILWIND_ENTRY, } from './features.js';
8
- import { run } from './proc.js';
9
- import { accent, dim, version } from './ui.js';
10
- import { isPackageManager, isValidName, resolveProjectDir } from './validate.js';
11
- const PREPROCESSOR_LABEL = {
12
- css: 'Plain CSS',
13
- sass: 'Sass (SCSS)',
14
- less: 'Less',
15
- stylus: 'Stylus',
16
- };
17
- const DEFAULT_STYLE_CONTENT = ':root {\n color-scheme: dark;\n}\n\n' +
18
- 'body {\n margin: 0;\n background: #080d11;\n color: #f5f6fa;\n' +
19
- ' font-family: system-ui, -apple-system, sans-serif;\n line-height: 1.6;\n}\n\n' +
20
- 'a {\n color: #2563ff;\n text-decoration: none;\n}\n\n' +
21
- 'a:hover {\n color: #22e3ab;\n}\n\n' +
22
- 'code {\n background: #11161f;\n color: #22e3ab;\n padding: 0.1rem 0.4rem;\n' +
23
- ' border-radius: 4px;\n font-size: 0.9em;\n}\n\n' +
24
- 'h1 {\n background: linear-gradient(90deg, #2563ff, #7c3aed, #22e3ab);\n' +
25
- ' -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n}\n';
26
- function bail(value) {
27
- if (isCancel(value)) {
28
- cancel('Scaffolding cancelled.');
29
- process.exit(0);
30
- }
31
- }
32
- async function isEmptyDir(dir) {
33
- try {
34
- const entries = await fs.readdir(dir);
35
- return entries.length === 0;
36
- }
37
- catch {
38
- return true;
39
- }
40
- }
41
- function scaffold(name, template, features, aiTools, images) {
42
- const toilVersion = version();
43
- const devDependencies = {
44
- '@types/react': '^19.2.15',
45
- '@types/react-dom': '^19.2.3',
46
- eslint: '^10.2.0',
47
- prettier: '^3.8.1',
48
- toilscript: '^0.1.2',
49
- typescript: '^6.0.3',
50
- };
51
- for (const dep of requiredPackages(features).sort()) {
52
- devDependencies[dep] = PKG_VERSION[dep] ?? 'latest';
53
- }
54
- const pkg = {
55
- name: path.basename(name),
56
- private: true,
57
- type: 'module',
58
- scripts: {
59
- dev: 'toiljs dev',
60
- build: 'toiljs build && toilscript --target release',
61
- 'build:client': 'toiljs build',
62
- 'build:server': 'toilscript --target release',
63
- lint: 'eslint client',
64
- typecheck: 'tsc --noEmit',
65
- format: 'prettier --write "client/**/*.{ts,tsx,css,scss,less}" "client/public/**/*.html"',
66
- },
67
- dependencies: {
68
- toiljs: `^${toilVersion}`,
69
- react: '^19.2.6',
70
- 'react-dom': '^19.2.6',
71
- },
72
- devDependencies,
73
- };
74
- const files = {
75
- 'package.json': JSON.stringify(pkg, null, 4) + '\n',
76
- 'toil.config.ts': "import { defineConfig } from 'toiljs/compiler';\n\n" +
77
- 'export default defineConfig({\n' +
78
- ' client: {\n' +
79
- ' // Optimize images at build time (resize/compress imported images).\n' +
80
- ` images: ${String(images)},\n` +
81
- ' },\n' +
82
- '});\n',
83
- 'tsconfig.json': '{\n "extends": "toiljs/tsconfig",\n "include": ["client", "toil-env.d.ts", "toil-routes.d.ts"]\n}\n',
84
- 'eslint.config.js': "import toiljs from 'toiljs/eslint';\n\nexport default toiljs;\n",
85
- '.prettierrc': '"toiljs/prettier"\n',
86
- '.gitignore': 'node_modules\nbuild\n.toil\ntoil-env.d.ts\ntoil-routes.d.ts\n',
87
- '.vscode/settings.json': JSON.stringify({ 'typescript.tsdk': 'node_modules/typescript/lib' }, null, 4) + '\n',
88
- 'toil-env.d.ts': TOIL_ENV_DTS,
89
- 'toil-routes.d.ts': '// AUTO-GENERATED by toil, do not edit.\nexport {};\n',
90
- 'toilconfig.json': JSON.stringify({
91
- entries: ['server/main.ts'],
92
- targets: {
93
- release: {
94
- outFile: 'build/server/release.wasm',
95
- textFile: 'build/server/release.wat',
96
- },
97
- },
98
- options: {
99
- sourceMap: false,
100
- optimizeLevel: 3,
101
- shrinkLevel: 1,
102
- converge: true,
103
- noAssert: false,
104
- enable: [
105
- 'sign-extension',
106
- 'mutable-globals',
107
- 'nontrapping-f2i',
108
- 'bulk-memory',
109
- 'simd',
110
- 'reference-types',
111
- 'multi-value',
112
- ],
113
- runtime: 'stub',
114
- memoryBase: 0,
115
- initialMemory: 1,
116
- debug: false,
117
- trapMode: 'allow',
118
- },
119
- }, null, 4) + '\n',
120
- 'server/tsconfig.json': JSON.stringify({
121
- extends: 'toilscript/std/assembly.json',
122
- include: ['./**/*.ts'],
123
- }, null, 4) + '\n',
124
- 'server/index.ts': 'export function add(a: i32, b: i32): i32 {\n return a + b;\n}\n',
125
- 'server/main.ts': "import { add } from './index';\n\n" +
126
- '@main\nfunction run(): i32 {\n return add(40, 2);\n}\n',
127
- 'README.md': [
128
- '# ' + path.basename(name),
129
- '',
130
- 'A [toiljs](https://toil.org) app.',
131
- '',
132
- '## Develop',
133
- '',
134
- ' npm install',
135
- ' npm run dev',
136
- '',
137
- '## Build',
138
- '',
139
- ' npm run build',
140
- '',
141
- ].join('\n'),
142
- };
143
- if (template === 'minimal')
144
- Object.assign(files, minimalClient(name, features));
145
- Object.assign(files, aiHelperFiles(aiTools));
146
- for (const [docName, content] of Object.entries(TOIL_DOCS)) {
147
- files[`.toil/docs/${docName}`] = content;
148
- }
149
- return files;
150
- }
151
- function minimalClient(name, features) {
152
- const files = {
153
- 'client/public/index.html': '<!doctype html>\n<html lang="en">\n <head>\n' +
154
- ' <meta charset="utf-8" />\n' +
155
- ' <meta name="viewport" content="width=device-width, initial-scale=1" />\n' +
156
- ' <meta name="theme-color" content="#080D11" />\n' +
157
- ' <meta name="description" content="" />\n' +
158
- ' <link rel="icon" type="image/svg+xml" href="/favicon.svg" />\n' +
159
- ' <link rel="manifest" href="/manifest.webmanifest" />\n' +
160
- ` <title>${path.basename(name)}</title>\n` +
161
- ' </head>\n <body>\n <div id="root"></div>\n </body>\n</html>\n',
162
- 'client/public/favicon.svg': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">\n' +
163
- ' <defs>\n' +
164
- ' <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">\n' +
165
- ' <stop offset="0" stop-color="#2563FF" />\n' +
166
- ' <stop offset="0.5" stop-color="#7C3AED" />\n' +
167
- ' <stop offset="1" stop-color="#22E3AB" />\n' +
168
- ' </linearGradient>\n' +
169
- ' </defs>\n' +
170
- ' <rect width="32" height="32" rx="7" fill="#080D11" />\n' +
171
- ' <path d="M9 10h14v3.2h-5.4V24h-3.2V13.2H9z" fill="url(#g)" />\n' +
172
- '</svg>\n',
173
- 'client/public/robots.txt': 'User-agent: *\nAllow: /\n',
174
- 'client/public/manifest.webmanifest': JSON.stringify({
175
- name: path.basename(name),
176
- short_name: path.basename(name),
177
- start_url: '/',
178
- display: 'standalone',
179
- background_color: '#080D11',
180
- theme_color: '#080D11',
181
- icons: [{ src: '/favicon.svg', type: 'image/svg+xml', sizes: 'any' }],
182
- }, null, 4) + '\n',
183
- 'client/public/images/.gitkeep': '# Place images and other static assets here; served at /images/*.\n',
184
- 'client/toil.tsx': "import { routes, layout, notFound, globalError, slots } from 'toiljs/routes';\n\n" +
185
- styleImportLines(features).join('\n') +
186
- '\n\n' +
187
- 'Toil.mount(routes, layout, notFound, globalError, slots);\n',
188
- [`client/${styleEntry(features.preprocessor)}`]: DEFAULT_STYLE_CONTENT,
189
- 'client/components/.gitkeep': '# Place shared React components here.\n',
190
- 'client/layout.tsx': `import { type ReactNode } from 'react';
191
-
192
- export default function Layout({ children }: { children?: ReactNode }) {
193
- return (
194
- <div style={{ maxWidth: 680, margin: '0 auto', padding: '3rem 1.5rem' }}>
195
- <header
196
- style={{
197
- display: 'flex',
198
- gap: '1rem',
199
- alignItems: 'baseline',
200
- borderBottom: '1px solid #1b2330',
201
- paddingBottom: '0.75rem',
202
- marginBottom: '1.5rem',
203
- }}>
204
- <strong style={{ color: '#2563FF', fontSize: '1.1rem' }}>${path.basename(name)}</strong>
205
- <nav style={{ display: 'flex', gap: '1rem' }}>
206
- <Toil.Link href="/">home</Toil.Link>
207
- </nav>
208
- </header>
209
- {children}
210
- </div>
211
- );
212
- }
213
- `,
214
- 'client/routes/index.tsx': 'export default function Home() {\n' +
215
- ' return (\n <main>\n' +
216
- ' <h1>Welcome to toiljs</h1>\n' +
217
- ' <p>File-based routing, bundled by Vite, zero config.</p>\n' +
218
- ' </main>\n );\n}\n',
219
- };
220
- if (features.tailwind)
221
- files[`client/${TAILWIND_ENTRY}`] = TAILWIND_CSS;
222
- return files;
223
- }
224
- function appClientDir() {
225
- return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'examples', 'basic', 'client');
226
- }
227
- async function applyStyling(clientDir, features) {
228
- if (features.preprocessor === 'css' && !features.tailwind)
229
- return;
230
- const entry = styleEntry(features.preprocessor);
231
- if (entry !== 'styles/main.css') {
232
- await fs.rename(path.join(clientDir, 'styles', 'main.css'), path.join(clientDir, entry));
233
- }
234
- if (features.tailwind) {
235
- await fs.writeFile(path.join(clientDir, TAILWIND_ENTRY), TAILWIND_CSS, 'utf8');
236
- }
237
- const toilPath = path.join(clientDir, 'toil.tsx');
238
- await fs.writeFile(toilPath, setStyleImports(await fs.readFile(toilPath, 'utf8'), features), 'utf8');
239
- }
240
- async function writeFiles(dir, files) {
241
- for (const [rel, contents] of Object.entries(files)) {
242
- const full = path.join(dir, rel);
243
- await fs.mkdir(path.dirname(full), { recursive: true });
244
- await fs.writeFile(full, contents, 'utf8');
245
- }
246
- }
247
- export async function runCreate(opts) {
248
- intro(accent(' toiljs create '));
249
- let name = opts.name;
250
- if (!name) {
251
- if (opts.yes) {
252
- name = 'my-toil-app';
253
- }
254
- else {
255
- const answer = await text({
256
- message: 'Project name',
257
- placeholder: 'my-toil-app',
258
- defaultValue: 'my-toil-app',
259
- validate: (v) => {
260
- const result = isValidName(v || 'my-toil-app');
261
- return result === true ? undefined : result;
262
- },
263
- });
264
- bail(answer);
265
- name = answer.trim() || 'my-toil-app';
266
- }
267
- }
268
- const valid = isValidName(name);
269
- if (valid !== true) {
270
- cancel(valid);
271
- process.exit(1);
272
- }
273
- const targetDir = resolveProjectDir(opts.cwd, name);
274
- if (targetDir === null) {
275
- cancel('Project name must stay inside the current directory (no "..", no absolute paths).');
276
- process.exit(1);
277
- }
278
- const rel = path.relative(opts.cwd, targetDir) || '.';
279
- if (!(await isEmptyDir(targetDir))) {
280
- if (opts.yes) {
281
- cancel(`Directory ${pc.cyan(rel)} is not empty.`);
282
- process.exit(1);
283
- }
284
- const proceed = await confirm({
285
- message: `Directory ${pc.cyan(rel)} is not empty. Scaffold into it anyway?`,
286
- initialValue: false,
287
- });
288
- bail(proceed);
289
- if (!proceed) {
290
- cancel('Scaffolding cancelled.');
291
- process.exit(0);
292
- }
293
- }
294
- let template = opts.template ?? 'app';
295
- if (!opts.template && !opts.yes) {
296
- const templateOptions = [
297
- {
298
- value: 'app',
299
- label: 'App',
300
- hint: 'the full ToilJS starter, landing page, layout, styles, demo routes',
301
- },
302
- { value: 'minimal', label: 'Minimal', hint: 'just a layout and a home route' },
303
- ];
304
- const choice = await select({
305
- message: 'Which template?',
306
- options: templateOptions,
307
- initialValue: 'app',
308
- });
309
- bail(choice);
310
- template = choice === 'minimal' ? 'minimal' : 'app';
311
- }
312
- let preprocessor = opts.preprocessor ?? 'css';
313
- let tailwind = opts.tailwind ?? false;
314
- if (!opts.yes) {
315
- if (opts.preprocessor === undefined) {
316
- const choice = await select({
317
- message: 'Styling',
318
- options: PREPROCESSORS.map((value) => ({
319
- value,
320
- label: PREPROCESSOR_LABEL[value],
321
- })),
322
- initialValue: 'css',
323
- });
324
- bail(choice);
325
- preprocessor = choice;
326
- }
327
- if (opts.tailwind === undefined) {
328
- const tw = await confirm({ message: 'Add Tailwind CSS?', initialValue: false });
329
- bail(tw);
330
- tailwind = tw;
331
- }
332
- }
333
- const features = { preprocessor, tailwind };
334
- let aiTools = opts.ai === false ? [] : [...AI_HELPER_IDS];
335
- if (opts.ai === undefined && !opts.yes) {
336
- const picked = await multiselect({
337
- message: 'AI assistant files (read by Claude, Cursor, Codex, Copilot)',
338
- options: [
339
- ...AI_HELPERS.map((h) => ({ value: h.id, label: h.label })),
340
- { value: 'none', label: 'None' },
341
- ],
342
- initialValues: [...AI_HELPER_IDS],
343
- required: false,
344
- });
345
- bail(picked);
346
- aiTools = picked.includes('none') ? [] : picked;
347
- }
348
- let images = opts.images ?? true;
349
- if (opts.images === undefined && !opts.yes) {
350
- const im = await confirm({ message: 'Optimize images at build time?', initialValue: true });
351
- bail(im);
352
- images = im;
353
- }
354
- let initGit = opts.git ?? false;
355
- let install = opts.install ?? false;
356
- const pm = opts.pm ?? 'npm';
357
- if (!isPackageManager(pm)) {
358
- cancel(`Unsupported package manager: ${pm} (use npm, pnpm, yarn, or bun).`);
359
- process.exit(1);
360
- }
361
- if (!opts.yes) {
362
- if (opts.git === undefined) {
363
- const g = await confirm({
364
- message: 'Initialize a git repository?',
365
- initialValue: true,
366
- });
367
- bail(g);
368
- initGit = g;
369
- }
370
- if (opts.install === undefined) {
371
- const i = await confirm({ message: 'Install dependencies now?', initialValue: false });
372
- bail(i);
373
- install = i;
374
- }
375
- }
376
- const s = spinner();
377
- s.start('Scaffolding project');
378
- await writeFiles(targetDir, scaffold(name, template, features, aiTools, images));
379
- if (template === 'app') {
380
- await fs.cp(appClientDir(), path.join(targetDir, 'client'), { recursive: true });
381
- const indexHtml = path.join(targetDir, 'client', 'public', 'index.html');
382
- const html = await fs.readFile(indexHtml, 'utf8');
383
- await fs.writeFile(indexHtml, html.replace(/<title>[^<]*<\/title>/, `<title>${path.basename(name)}</title>`));
384
- await applyStyling(path.join(targetDir, 'client'), features);
385
- }
386
- s.stop(`Scaffolded ${pc.cyan(rel)}`);
387
- if (initGit) {
388
- const g = spinner();
389
- g.start('Initializing git repository');
390
- try {
391
- await run('git', ['init', '-q'], targetDir);
392
- await run('git', ['add', '-A'], targetDir);
393
- g.stop('Initialized git repository');
394
- }
395
- catch {
396
- g.stop(pc.yellow('Skipped git init (git not available)'));
397
- }
398
- }
399
- if (install) {
400
- const i = spinner();
401
- i.start(`Installing dependencies with ${pm}`);
402
- try {
403
- await run(pm, ['install'], targetDir);
404
- i.stop('Installed dependencies');
405
- }
406
- catch {
407
- i.stop(pc.yellow(`Could not install with ${pm}, run it yourself later`));
408
- install = false;
409
- }
410
- }
411
- const steps = [];
412
- if (rel !== '.')
413
- steps.push(`cd ${rel}`);
414
- if (!install)
415
- steps.push('npm install');
416
- steps.push(`${accent('npm run dev')} ${dim('start the dev server')}`);
417
- steps.push(`${accent('npm run build')} ${dim('build for production')}`);
418
- note(steps.map((l) => dim(' ') + l).join('\n'), 'Next steps');
419
- outro(`Created ${accent(path.basename(name))}, happy building! ${dim('· v' + version())}`);
420
- }
@@ -1,55 +0,0 @@
1
- import { type Preprocessor } from './features.js';
2
- export type CheckStatus = 'pass' | 'warn' | 'fail';
3
- export interface Check {
4
- readonly id: string;
5
- readonly label: string;
6
- readonly status: CheckStatus;
7
- readonly detail?: string;
8
- readonly fix?: string;
9
- }
10
- export interface CheckGroup {
11
- readonly title: string;
12
- readonly checks: Check[];
13
- }
14
- export interface DoctorSummary {
15
- readonly pass: number;
16
- readonly warn: number;
17
- readonly fail: number;
18
- }
19
- export declare function satisfiesMin(version: string, range: string): boolean;
20
- export declare function checkNode(current: string, requiredRange: string): Check;
21
- export declare function checkPeer(name: string, installed: string | null, range: string): Check;
22
- export declare function checkPackageManager(lockfiles: readonly string[]): Check;
23
- export declare function checkToiljsInstalled(version: string | null): Check;
24
- export declare function checkDir(id: string, label: string, exists: boolean, fix: string): Check;
25
- export declare function checkMountSlots(entrySource: string | null): Check;
26
- export declare function checkRootElement(indexHtml: string | null): Check;
27
- export declare function checkRoutesPresent(routeCount: number): Check;
28
- export declare function checkDuplicatePatterns(patterns: readonly string[]): Check;
29
- export interface SourceFile {
30
- readonly path: string;
31
- readonly source: string;
32
- }
33
- export interface AssetIssue {
34
- readonly file: string;
35
- readonly line: number;
36
- readonly value: string;
37
- }
38
- export declare function findRelativeAssets(files: readonly SourceFile[]): AssetIssue[];
39
- export declare function checkRelativeAssets(issues: readonly AssetIssue[]): Check;
40
- export declare function checkConfigLoads(loaded: boolean, error?: string): Check;
41
- export declare function checkBasePath(base: string): Check;
42
- export declare function checkSeoUrl(seoConfigured: boolean, hasUrl: boolean): Check;
43
- export interface StylingFacts {
44
- readonly preprocessorImported: Preprocessor | null;
45
- readonly preprocessorInstalled: boolean;
46
- readonly tailwindImported: boolean;
47
- readonly tailwindInstalled: boolean;
48
- }
49
- export declare function checkStyling(f: StylingFacts): Check;
50
- export declare function checkToilconfig(present: boolean): Check;
51
- export declare function checkServerEntry(missing: readonly string[]): Check;
52
- export declare function checkToilscriptInstalled(installed: boolean): Check;
53
- export declare function checkWasmBuilt(exists: boolean): Check;
54
- export declare function summarize(groups: readonly CheckGroup[]): DoctorSummary;
55
- export declare function hasFailures(summary: DoctorSummary): boolean;