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,73 +1,73 @@
1
- /**
2
- * Public router types shared across the client runtime. Kept dependency-free (type-only React
3
- * imports) so any module can import them without pulling in component or DOM code.
4
- */
5
- import type { ComponentType, ReactNode } from 'react';
6
-
7
- /**
8
- * Augmentation point for the project's generated route types. The compiler emits (into
9
- * `toil-routes.d.ts`) `declare module 'toiljs/client' { interface Register { routePath: <union> } }`,
10
- * which narrows {@link RoutePath} from `string` to the project's actual routes.
11
- */
12
- export interface Register {}
13
-
14
- /**
15
- * Union of the project's route paths, static routes as literals, dynamic/catch-all as
16
- * `` `…/${string}` `` templates. Falls back to `string` before the types are generated.
17
- */
18
- export type RoutePath = Register extends { routePath: infer P }
19
- ? P extends string
20
- ? P
21
- : string
22
- : string;
23
-
24
- /**
25
- * An href accepted by `Link` / `NavLink` / `navigate`: a known {@link RoutePath} (optionally with
26
- * `?query` or `#hash`), or an absolute/protocol URL (`https:`, `mailto:`, …). When routes haven't
27
- * been generated yet, this is just `string`.
28
- */
29
- export type Href =
30
- | RoutePath
31
- | `${RoutePath}?${string}`
32
- | `${RoutePath}#${string}`
33
- | `${string}:${string}`;
34
-
35
- /** Lazy loader for a layout component (wraps children). */
36
- export type LayoutComponentLoader = () => Promise<{
37
- default: ComponentType<{ children?: ReactNode }>;
38
- }>;
39
-
40
- /** Props passed to an `error.tsx` / `global-error.tsx` component. */
41
- export interface RouteErrorProps {
42
- readonly error: Error;
43
- readonly reset: () => void;
44
- }
45
-
46
- /** Lazy loader for an error component (`error.tsx` / `global-error.tsx`), or `null` if none. */
47
- export type ErrorComponentLoader =
48
- | (() => Promise<{ default: ComponentType<RouteErrorProps> }>)
49
- | null;
50
-
51
- /**
52
- * A route entry produced by the compiler: a URL pattern, a lazy loader for its page component, and
53
- * the chain of nested layout loaders (shallowest → deepest, from nested `layout.tsx` files) that wrap it.
54
- */
55
- export interface RouteDef {
56
- readonly pattern: string;
57
- readonly load: () => Promise<{ default: ComponentType }>;
58
- readonly layouts?: readonly LayoutComponentLoader[];
59
- /** `template.tsx` chain (root → nested), like layouts, but re-mounted on each navigation. */
60
- readonly templates?: readonly LayoutComponentLoader[];
61
- /** Nearest `loading.tsx`, shown as the Suspense fallback while this route loads. */
62
- readonly loading?: () => Promise<{ default: ComponentType }>;
63
- /** Nearest `error.tsx`, rendered by an error boundary around this route. */
64
- readonly errorComponent?: () => Promise<{ default: ComponentType<RouteErrorProps> }>;
65
- /** Intercepting route (`(.)`/`(..)`/`(...)`), matched in its slot only on soft navigation. */
66
- readonly intercept?: boolean;
67
- }
68
-
69
- /** Optional root layout loader (wraps every page). `null` when the project defines no layout. */
70
- export type LayoutLoader = LayoutComponentLoader | null;
71
-
72
- /** Optional custom not-found (404) page loader, rendered when no route matches. */
73
- export type NotFoundLoader = (() => Promise<{ default: ComponentType }>) | null;
1
+ /**
2
+ * Public router types shared across the client runtime. Kept dependency-free (type-only React
3
+ * imports) so any module can import them without pulling in component or DOM code.
4
+ */
5
+ import type { ComponentType, ReactNode } from 'react';
6
+
7
+ /**
8
+ * Augmentation point for the project's generated route types. The compiler emits (into
9
+ * `toil-routes.d.ts`) `declare module 'toiljs/client' { interface Register { routePath: <union> } }`,
10
+ * which narrows {@link RoutePath} from `string` to the project's actual routes.
11
+ */
12
+ export interface Register {}
13
+
14
+ /**
15
+ * Union of the project's route paths, static routes as literals, dynamic/catch-all as
16
+ * `` `…/${string}` `` templates. Falls back to `string` before the types are generated.
17
+ */
18
+ export type RoutePath = Register extends { routePath: infer P }
19
+ ? P extends string
20
+ ? P
21
+ : string
22
+ : string;
23
+
24
+ /**
25
+ * An href accepted by `Link` / `NavLink` / `navigate`: a known {@link RoutePath} (optionally with
26
+ * `?query` or `#hash`), or an absolute/protocol URL (`https:`, `mailto:`, …). When routes haven't
27
+ * been generated yet, this is just `string`.
28
+ */
29
+ export type Href =
30
+ | RoutePath
31
+ | `${RoutePath}?${string}`
32
+ | `${RoutePath}#${string}`
33
+ | `${string}:${string}`;
34
+
35
+ /** Lazy loader for a layout component (wraps children). */
36
+ export type LayoutComponentLoader = () => Promise<{
37
+ default: ComponentType<{ children?: ReactNode }>;
38
+ }>;
39
+
40
+ /** Props passed to an `error.tsx` / `global-error.tsx` component. */
41
+ export interface RouteErrorProps {
42
+ readonly error: Error;
43
+ readonly reset: () => void;
44
+ }
45
+
46
+ /** Lazy loader for an error component (`error.tsx` / `global-error.tsx`), or `null` if none. */
47
+ export type ErrorComponentLoader =
48
+ | (() => Promise<{ default: ComponentType<RouteErrorProps> }>)
49
+ | null;
50
+
51
+ /**
52
+ * A route entry produced by the compiler: a URL pattern, a lazy loader for its page component, and
53
+ * the chain of nested layout loaders (shallowest → deepest, from nested `layout.tsx` files) that wrap it.
54
+ */
55
+ export interface RouteDef {
56
+ readonly pattern: string;
57
+ readonly load: () => Promise<{ default: ComponentType }>;
58
+ readonly layouts?: readonly LayoutComponentLoader[];
59
+ /** `template.tsx` chain (root → nested), like layouts, but re-mounted on each navigation. */
60
+ readonly templates?: readonly LayoutComponentLoader[];
61
+ /** Nearest `loading.tsx`, shown as the Suspense fallback while this route loads. */
62
+ readonly loading?: () => Promise<{ default: ComponentType }>;
63
+ /** Nearest `error.tsx`, rendered by an error boundary around this route. */
64
+ readonly errorComponent?: () => Promise<{ default: ComponentType<RouteErrorProps> }>;
65
+ /** Intercepting route (`(.)`/`(..)`/`(...)`), matched in its slot only on soft navigation. */
66
+ readonly intercept?: boolean;
67
+ }
68
+
69
+ /** Optional root layout loader (wraps every page). `null` when the project defines no layout. */
70
+ export type LayoutLoader = LayoutComponentLoader | null;
71
+
72
+ /** Optional custom not-found (404) page loader, rendered when no route matches. */
73
+ export type NotFoundLoader = (() => Promise<{ default: ComponentType }>) | null;
@@ -1,182 +1,221 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { fileURLToPath, pathToFileURL } from 'node:url';
4
-
5
- import { type InlineConfig } from 'vite';
6
-
7
- import { type SeoConfig } from './seo.js';
8
-
9
- export type { SeoConfig } from './seo.js';
10
-
11
- /**
12
- * Client-side (TSX/React/Vite) configuration. All fields optional; sensible defaults applied.
13
- */
14
- export interface ClientConfig {
15
- /** Client source directory, relative to root. Default `client`. */
16
- readonly srcDir?: string;
17
- /** Routes directory, relative to `srcDir`. Default `routes`. */
18
- readonly routesDir?: string;
19
- /**
20
- * Static assets directory, relative to root. Default `<srcDir>/public` (e.g. `client/public`).
21
- * Holds the `index.html` template (owned and edited by you) plus any files served as-is at the
22
- * base path (favicons, images, …).
23
- */
24
- readonly publicDir?: string;
25
- /** Production output directory, relative to root. Default `build/client`. */
26
- readonly outDir?: string;
27
- /** Public base path. Default `/`. */
28
- readonly base?: string;
29
- /** Dev server port. Default `3000`. */
30
- readonly port?: number;
31
- /**
32
- * Optimize imported images at build time (resize/convert via `vite-imagetools` + sharp): an
33
- * import like `logo.png?w=400;800&format=webp&as=srcset` emits resized, compressed variants.
34
- * Default `true`. Set `false` to disable the pipeline (images are then served as-is).
35
- */
36
- readonly images?: boolean;
37
- /**
38
- * Preload bundled fonts at build time: injects `<link rel="preload" as="font">` for each
39
- * `@font-face` font so it loads in parallel with the CSS (faster text paint). Default `true`.
40
- */
41
- readonly fonts?: boolean;
42
- /**
43
- * Animate cross-page navigations with the browser View Transitions API (a crossfade by default;
44
- * add `view-transition-name` in CSS for shared-element transitions). Respects
45
- * `prefers-reduced-motion`. Default `false`.
46
- */
47
- readonly viewTransitions?: boolean;
48
- /**
49
- * Wrap client navigations in a React transition, keeping the current page visible while the next
50
- * route's loader runs instead of showing its `loading.tsx` right away. Default `false` (a
51
- * navigation commits eagerly, so the loading state appears immediately).
52
- */
53
- readonly transitions?: boolean;
54
- /**
55
- * Build-time SEO: bakes site-level metadata into the HTML `<head>` (so JS-less crawlers and AI
56
- * bots see real tags) and generates `robots.txt`, `sitemap.xml`, and `llms.txt`. Omit to skip.
57
- */
58
- readonly seo?: SeoConfig;
59
- /**
60
- * Raw Vite escape hatch, deep-merged over the framework's opinionated config.
61
- * This is NOT the client config itself, toil owns the Vite setup; use this only
62
- * to override specific Vite options.
63
- */
64
- readonly vite?: InlineConfig;
65
- }
66
-
67
- /**
68
- * Server-side (toilscript → WASM) configuration. Reserved: the compiler does not yet
69
- * build the server target via `toil build`; today it is compiled by `toilscript` directly.
70
- */
71
- export interface ServerConfig {
72
- /** Server source directory, relative to root. Default `server`. */
73
- readonly srcDir?: string;
74
- /** Server build output directory, relative to root. Default `build/server`. */
75
- readonly outDir?: string;
76
- }
77
-
78
- /**
79
- * The `toil.config` schema. All fields optional; sensible defaults applied.
80
- * Client and server are configured in separate sections.
81
- */
82
- export interface ToilConfig {
83
- /** Project root. Defaults to the current working directory. */
84
- readonly root?: string;
85
- /** Client (TSX/React/Vite) configuration. */
86
- readonly client?: ClientConfig;
87
- /** Server (toilscript/WASM) configuration. */
88
- readonly server?: ServerConfig;
89
- }
90
-
91
- /** Fully-resolved config with absolute paths, used internally by the compiler. */
92
- export interface ResolvedToilConfig {
93
- readonly root: string;
94
- readonly srcDir: string;
95
- readonly clientAbsDir: string;
96
- readonly routesAbsDir: string;
97
- /** Absolute path to the static-assets dir (holds the `index.html` template). */
98
- readonly publicDir: string;
99
- readonly toilDir: string;
100
- readonly outDir: string;
101
- readonly base: string;
102
- readonly port: number;
103
- /** Whether build-time image optimization (`vite-imagetools`) is enabled. */
104
- readonly images: boolean;
105
- /** Whether build-time font preloading is enabled. */
106
- readonly fonts: boolean;
107
- /** Whether animated View Transitions are enabled for navigation. */
108
- readonly viewTransitions: boolean;
109
- /** Whether navigations are wrapped in a React transition (keep current page while loading). */
110
- readonly transitions: boolean;
111
- /** Build-time SEO config, or `null` when not configured. */
112
- readonly seo: SeoConfig | null;
113
- /** Absolute path to the framework client runtime (`toiljs/client`). */
114
- readonly runtimePath: string;
115
- readonly vite: InlineConfig;
116
- }
117
-
118
- /** Identity helper for typed config files: `export default defineConfig({ ... })`. */
119
- export function defineConfig(config: ToilConfig): ToilConfig {
120
- return config;
121
- }
122
-
123
- const CONFIG_NAMES = [
124
- 'toil.config.ts',
125
- 'toil.config.mts',
126
- 'toil.config.js',
127
- 'toil.config.mjs',
128
- 'toiljs.config.ts',
129
- 'toiljs.config.mts',
130
- 'toiljs.config.js',
131
- 'toiljs.config.mjs',
132
- ];
133
-
134
- /** Path to the built client runtime (`build/client/index.js`), sibling to `build/compiler`. */
135
- function resolveRuntimePath(): string {
136
- return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../client/index.js');
137
- }
138
-
139
- /** Finds and loads `toil.config.*` or `toiljs.config.*` from `root`, then resolves defaults. */
140
- export async function loadConfig(
141
- opts: { root?: string; port?: number } = {},
142
- ): Promise<ResolvedToilConfig> {
143
- const root = path.resolve(opts.root ?? process.cwd());
144
-
145
- let user: ToilConfig = {};
146
- for (const name of CONFIG_NAMES) {
147
- const candidate = path.join(root, name);
148
- if (fs.existsSync(candidate)) {
149
- const loaded = (await import(pathToFileURL(candidate).href)) as {
150
- default?: ToilConfig;
151
- };
152
- if (loaded.default) user = loaded.default;
153
- break;
154
- }
155
- }
156
-
157
- const client = user.client ?? {};
158
- const srcDir = client.srcDir ?? 'client';
159
- const routesDir = client.routesDir ?? 'routes';
160
- const clientAbsDir = path.join(root, srcDir);
161
-
162
- return {
163
- root,
164
- srcDir,
165
- clientAbsDir,
166
- routesAbsDir: path.join(clientAbsDir, routesDir),
167
- publicDir: client.publicDir
168
- ? path.resolve(root, client.publicDir)
169
- : path.join(clientAbsDir, 'public'),
170
- toilDir: path.join(root, '.toil'),
171
- outDir: client.outDir ?? 'build/client',
172
- base: client.base ?? '/',
173
- port: opts.port ?? client.port ?? 3000,
174
- images: client.images ?? true,
175
- fonts: client.fonts ?? true,
176
- viewTransitions: client.viewTransitions ?? false,
177
- transitions: client.transitions ?? false,
178
- seo: client.seo ?? null,
179
- runtimePath: resolveRuntimePath(),
180
- vite: client.vite ?? {},
181
- };
182
- }
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
4
+
5
+ import { type InlineConfig } from 'vite';
6
+
7
+ import { type SeoConfig } from './seo.js';
8
+
9
+ export type { SeoConfig } from './seo.js';
10
+
11
+ /** Built-in AI providers the dev toolbar can proxy to. */
12
+ export enum AiProvider {
13
+ Anthropic = 'anthropic',
14
+ OpenAI = 'openai',
15
+ }
16
+
17
+ /** Dev toolbar AI integration (dev only; the key stays server-side). */
18
+ export interface DevtoolsAiConfig {
19
+ /** Built-in provider. With `endpoint` set, that takes precedence. */
20
+ readonly provider?: AiProvider;
21
+ /** Model id (e.g. `claude-sonnet-4-6`, `gpt-4o`). */
22
+ readonly model?: string;
23
+ /** Name of the env var holding the API key (read by the dev server, never sent to the client). */
24
+ readonly apiKeyEnv?: string;
25
+ /** Custom POST endpoint (`{ prompt }` in, `{ text }` out); overrides `provider`. */
26
+ readonly endpoint?: string;
27
+ }
28
+
29
+ /** Dev toolbar configuration. */
30
+ export interface DevtoolsConfig {
31
+ readonly ai?: DevtoolsAiConfig;
32
+ }
33
+
34
+ /**
35
+ * Client-side (TSX/React/Vite) configuration. All fields optional; sensible defaults applied.
36
+ */
37
+ export interface ClientConfig {
38
+ /** Client source directory, relative to root. Default `client`. */
39
+ readonly srcDir?: string;
40
+ /** Routes directory, relative to `srcDir`. Default `routes`. */
41
+ readonly routesDir?: string;
42
+ /**
43
+ * Static assets directory, relative to root. Default `<srcDir>/public` (e.g. `client/public`).
44
+ * Holds the `index.html` template (owned and edited by you) plus any files served as-is at the
45
+ * base path (favicons, images, and the like).
46
+ */
47
+ readonly publicDir?: string;
48
+ /** Production output directory, relative to root. Default `build/client`. */
49
+ readonly outDir?: string;
50
+ /** Public base path. Default `/`. */
51
+ readonly base?: string;
52
+ /** Dev server port. Default `3000`. */
53
+ readonly port?: number;
54
+ /**
55
+ * Optimize imported images at build time (resize/convert via `vite-imagetools` + sharp): an
56
+ * import like `logo.png?w=400;800&format=webp&as=srcset` emits resized, compressed variants.
57
+ * Default `true`. Set `false` to disable the pipeline (images are then served as-is).
58
+ */
59
+ readonly images?: boolean;
60
+ /**
61
+ * Preload bundled fonts at build time: injects `<link rel="preload" as="font">` for each
62
+ * `@font-face` font so it loads in parallel with the CSS (faster text paint). Default `true`.
63
+ */
64
+ readonly fonts?: boolean;
65
+ /**
66
+ * Animate cross-page navigations with the browser View Transitions API (a crossfade by default;
67
+ * add `view-transition-name` in CSS for shared-element transitions). Respects
68
+ * `prefers-reduced-motion`. Default `false`.
69
+ */
70
+ readonly viewTransitions?: boolean;
71
+ /**
72
+ * Wrap client navigations in a React transition, keeping the current page visible while the next
73
+ * route's loader runs instead of showing its `loading.tsx` right away. Default `false` (a
74
+ * navigation commits eagerly, so the loading state appears immediately).
75
+ */
76
+ readonly transitions?: boolean;
77
+ /**
78
+ * The dev toolbar (a floating panel in `toiljs dev` with route/build info, errors, and live
79
+ * controls). `true` (default) / `false` to disable, or an object to configure its AI integration.
80
+ * Never included in production builds. The AI key is read server-side from `apiKeyEnv` and never
81
+ * reaches the browser; the toolbar always offers Claude/ChatGPT hand-off links regardless.
82
+ */
83
+ readonly devtools?: boolean | DevtoolsConfig;
84
+ /**
85
+ * Build-time SEO: bakes site-level metadata into the HTML `<head>` (so JS-less crawlers and AI
86
+ * bots see real tags) and generates `robots.txt`, `sitemap.xml`, and `llms.txt`. Omit to skip.
87
+ */
88
+ readonly seo?: SeoConfig;
89
+ /**
90
+ * Raw Vite escape hatch, deep-merged over the framework's opinionated config.
91
+ * This is NOT the client config itself, toil owns the Vite setup; use this only
92
+ * to override specific Vite options.
93
+ */
94
+ readonly vite?: InlineConfig;
95
+ }
96
+
97
+ /**
98
+ * Server-side (toilscript → WASM) configuration. Reserved: the compiler does not yet
99
+ * build the server target via `toil build`; today it is compiled by `toilscript` directly.
100
+ */
101
+ export interface ServerConfig {
102
+ /** Server source directory, relative to root. Default `server`. */
103
+ readonly srcDir?: string;
104
+ /** Server build output directory, relative to root. Default `build/server`. */
105
+ readonly outDir?: string;
106
+ }
107
+
108
+ /**
109
+ * The `toil.config` schema. All fields optional; sensible defaults applied.
110
+ * Client and server are configured in separate sections.
111
+ */
112
+ export interface ToilConfig {
113
+ /** Project root. Defaults to the current working directory. */
114
+ readonly root?: string;
115
+ /** Client (TSX/React/Vite) configuration. */
116
+ readonly client?: ClientConfig;
117
+ /** Server (toilscript/WASM) configuration. */
118
+ readonly server?: ServerConfig;
119
+ }
120
+
121
+ /** Fully-resolved config with absolute paths, used internally by the compiler. */
122
+ export interface ResolvedToilConfig {
123
+ readonly root: string;
124
+ readonly srcDir: string;
125
+ readonly clientAbsDir: string;
126
+ readonly routesAbsDir: string;
127
+ /** Absolute path to the static-assets dir (holds the `index.html` template). */
128
+ readonly publicDir: string;
129
+ readonly toilDir: string;
130
+ readonly outDir: string;
131
+ readonly base: string;
132
+ readonly port: number;
133
+ /** Whether build-time image optimization (`vite-imagetools`) is enabled. */
134
+ readonly images: boolean;
135
+ /** Whether build-time font preloading is enabled. */
136
+ readonly fonts: boolean;
137
+ /** Whether animated View Transitions are enabled for navigation. */
138
+ readonly viewTransitions: boolean;
139
+ /** Whether navigations are wrapped in a React transition (keep current page while loading). */
140
+ readonly transitions: boolean;
141
+ /** Whether the dev toolbar is enabled (dev only). */
142
+ readonly devtools: boolean;
143
+ /** Dev toolbar AI config (dev only), or `null` when not configured. */
144
+ readonly devtoolsAi: DevtoolsAiConfig | null;
145
+ /** Build-time SEO config, or `null` when not configured. */
146
+ readonly seo: SeoConfig | null;
147
+ /** Absolute path to the framework client runtime (`toiljs/client`). */
148
+ readonly runtimePath: string;
149
+ readonly vite: InlineConfig;
150
+ }
151
+
152
+ /** Identity helper for typed config files: `export default defineConfig({ ... })`. */
153
+ export function defineConfig(config: ToilConfig): ToilConfig {
154
+ return config;
155
+ }
156
+
157
+ const CONFIG_NAMES = [
158
+ 'toil.config.ts',
159
+ 'toil.config.mts',
160
+ 'toil.config.js',
161
+ 'toil.config.mjs',
162
+ 'toiljs.config.ts',
163
+ 'toiljs.config.mts',
164
+ 'toiljs.config.js',
165
+ 'toiljs.config.mjs',
166
+ ];
167
+
168
+ /** Path to the built client runtime (`build/client/index.js`), sibling to `build/compiler`. */
169
+ function resolveRuntimePath(): string {
170
+ return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../client/index.js');
171
+ }
172
+
173
+ /** Finds and loads `toil.config.*` or `toiljs.config.*` from `root`, then resolves defaults. */
174
+ export async function loadConfig(
175
+ opts: { root?: string; port?: number } = {},
176
+ ): Promise<ResolvedToilConfig> {
177
+ const root = path.resolve(opts.root ?? process.cwd());
178
+
179
+ let user: ToilConfig = {};
180
+ for (const name of CONFIG_NAMES) {
181
+ const candidate = path.join(root, name);
182
+ if (fs.existsSync(candidate)) {
183
+ const loaded = (await import(pathToFileURL(candidate).href)) as {
184
+ default?: ToilConfig;
185
+ };
186
+ if (loaded.default) user = loaded.default;
187
+ break;
188
+ }
189
+ }
190
+
191
+ const client = user.client ?? {};
192
+ const srcDir = client.srcDir ?? 'client';
193
+ const routesDir = client.routesDir ?? 'routes';
194
+ const clientAbsDir = path.join(root, srcDir);
195
+
196
+ return {
197
+ root,
198
+ srcDir,
199
+ clientAbsDir,
200
+ routesAbsDir: path.join(clientAbsDir, routesDir),
201
+ publicDir: client.publicDir
202
+ ? path.resolve(root, client.publicDir)
203
+ : path.join(clientAbsDir, 'public'),
204
+ toilDir: path.join(root, '.toil'),
205
+ outDir: client.outDir ?? 'build/client',
206
+ base: client.base ?? '/',
207
+ port: opts.port ?? client.port ?? 3000,
208
+ images: client.images ?? true,
209
+ fonts: client.fonts ?? true,
210
+ viewTransitions: client.viewTransitions ?? false,
211
+ transitions: client.transitions ?? false,
212
+ devtools: client.devtools !== false,
213
+ devtoolsAi:
214
+ client.devtools != null && typeof client.devtools === 'object'
215
+ ? (client.devtools.ai ?? null)
216
+ : null,
217
+ seo: client.seo ?? null,
218
+ runtimePath: resolveRuntimePath(),
219
+ vite: client.vite ?? {},
220
+ };
221
+ }