toiljs 0.0.15 → 0.0.16

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 (217) 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 +5 -5
  14. package/LICENSE +187 -187
  15. package/README.md +339 -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/cli/.tsbuildinfo +1 -1
  21. package/build/cli/index.js +0 -0
  22. package/build/client/.tsbuildinfo +1 -1
  23. package/build/client/dev/devtools.d.ts +6 -0
  24. package/build/client/dev/devtools.js +442 -0
  25. package/build/client/dev/error-overlay.d.ts +9 -0
  26. package/build/client/dev/error-overlay.js +19 -4
  27. package/build/client/navigation/prefetch.d.ts +1 -0
  28. package/build/client/navigation/prefetch.js +35 -0
  29. package/build/client/routing/Router.js +1 -1
  30. package/build/client/routing/hooks.js +6 -2
  31. package/build/client/routing/loader.d.ts +23 -0
  32. package/build/client/routing/loader.js +53 -7
  33. package/build/client/routing/mount.js +4 -3
  34. package/build/compiler/.tsbuildinfo +1 -1
  35. package/build/compiler/config.d.ts +16 -0
  36. package/build/compiler/config.js +7 -0
  37. package/build/compiler/docs.js +16 -16
  38. package/build/compiler/index.d.ts +2 -2
  39. package/build/compiler/index.js +1 -1
  40. package/build/compiler/plugin.js +156 -0
  41. package/build/compiler/prerender.d.ts +1 -0
  42. package/build/compiler/prerender.js +1 -1
  43. package/build/compiler/seo.d.ts +1 -1
  44. package/build/compiler/seo.js +5 -4
  45. package/build/compiler/ssg.js +32 -1
  46. package/build/io/.tsbuildinfo +1 -1
  47. package/build/logger/.tsbuildinfo +1 -1
  48. package/build/shared/.tsbuildinfo +1 -1
  49. package/eslint.config.js +48 -48
  50. package/examples/basic/client/404.tsx +11 -11
  51. package/examples/basic/client/components/.gitkeep +1 -1
  52. package/examples/basic/client/global-error.tsx +13 -13
  53. package/examples/basic/client/layout.tsx +25 -25
  54. package/examples/basic/client/public/images/.gitkeep +1 -1
  55. package/examples/basic/client/public/images/logo.svg +36 -36
  56. package/examples/basic/client/public/robots.txt +2 -2
  57. package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
  58. package/examples/basic/client/routes/features/error/error.tsx +16 -16
  59. package/examples/basic/client/routes/features/template/b.tsx +14 -14
  60. package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
  61. package/examples/basic/client/routes/gallery/layout.tsx +13 -13
  62. package/examples/basic/client/routes/io.tsx +24 -24
  63. package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
  64. package/examples/basic/client/routes/search.tsx +61 -61
  65. package/examples/basic/client/toil.tsx +5 -5
  66. package/package.json +155 -148
  67. package/presets/eslint.js +88 -88
  68. package/presets/no-uint8array-tostring.js +200 -200
  69. package/presets/prettier.json +18 -18
  70. package/presets/tsconfig.json +37 -37
  71. package/src/backend/index.ts +160 -160
  72. package/src/cli/proc.ts +50 -50
  73. package/src/cli/updates.ts +69 -69
  74. package/src/cli/validate.ts +31 -31
  75. package/src/client/channel/channel.ts +146 -146
  76. package/src/client/components/Form.tsx +65 -65
  77. package/src/client/components/Script.tsx +113 -113
  78. package/src/client/components/Slot.tsx +21 -21
  79. package/src/client/dev/devtools.tsx +973 -0
  80. package/src/client/dev/error-overlay.tsx +30 -4
  81. package/src/client/head/head.ts +167 -167
  82. package/src/client/head/metadata.ts +112 -112
  83. package/src/client/index.ts +89 -89
  84. package/src/client/navigation/NavLink.tsx +86 -86
  85. package/src/client/navigation/navigation.ts +235 -235
  86. package/src/client/navigation/prefetch.ts +169 -130
  87. package/src/client/navigation/scroll.ts +53 -53
  88. package/src/client/routing/Router.tsx +8 -2
  89. package/src/client/routing/action.ts +122 -122
  90. package/src/client/routing/error-boundary.tsx +43 -43
  91. package/src/client/routing/hooks.ts +21 -6
  92. package/src/client/routing/loader.ts +325 -235
  93. package/src/client/routing/match.ts +47 -47
  94. package/src/client/routing/mount.tsx +54 -52
  95. package/src/client/routing/params-context.ts +10 -10
  96. package/src/client/routing/slot-context.ts +7 -7
  97. package/src/client/search/search.ts +189 -189
  98. package/src/client/search/use-page-search.ts +73 -73
  99. package/src/client/types.ts +73 -73
  100. package/src/compiler/config.ts +219 -182
  101. package/src/compiler/docs.ts +228 -228
  102. package/src/compiler/generate.ts +394 -394
  103. package/src/compiler/index.ts +64 -57
  104. package/src/compiler/pages.ts +70 -70
  105. package/src/compiler/plugin.ts +170 -2
  106. package/src/compiler/prerender.ts +156 -156
  107. package/src/compiler/seo.ts +397 -390
  108. package/src/compiler/ssg.ts +162 -126
  109. package/src/io/BinaryReader.ts +340 -340
  110. package/src/io/BinaryWriter.ts +385 -385
  111. package/src/io/FastMap.ts +127 -127
  112. package/src/io/index.ts +11 -11
  113. package/src/io/lengths.ts +14 -14
  114. package/src/io/types.ts +18 -18
  115. package/src/logger/index.ts +22 -22
  116. package/src/server/index.ts +10 -10
  117. package/src/server/main.ts +13 -13
  118. package/src/server/tsconfig.json +4 -4
  119. package/src/shared/index.ts +10 -10
  120. package/std/client/index.d.ts +15 -15
  121. package/std/client/package.json +3 -3
  122. package/test/assembly/example.spec.ts +7 -7
  123. package/test/channel.test.ts +21 -21
  124. package/test/dom/Link.test.tsx +47 -47
  125. package/test/dom/NavLink.test.tsx +37 -37
  126. package/test/dom/error-overlay.test.tsx +44 -44
  127. package/test/dom/loader.test.tsx +121 -121
  128. package/test/dom/navigation.test.ts +59 -59
  129. package/test/dom/revalidate.test.tsx +38 -38
  130. package/test/dom/route-head.test.tsx +78 -78
  131. package/test/dom/router-loading.test.tsx +44 -44
  132. package/test/dom/scroll.test.ts +56 -56
  133. package/test/dom/use-metadata.test.tsx +58 -58
  134. package/test/io.test.ts +93 -93
  135. package/test/navlink.test.ts +28 -28
  136. package/test/placeholder.test.ts +9 -9
  137. package/test/routes.test.ts +76 -76
  138. package/test/seo.test.ts +175 -164
  139. package/test/slot-layouts.test.ts +69 -69
  140. package/test/ssg.test.ts +36 -36
  141. package/test/update.test.ts +44 -44
  142. package/test/validate.test.ts +42 -42
  143. package/toil-routes.d.ts +7 -0
  144. package/toilconfig.json +30 -30
  145. package/tsconfig.backend.json +13 -13
  146. package/tsconfig.base.json +35 -35
  147. package/tsconfig.cli.json +13 -13
  148. package/tsconfig.client.json +14 -14
  149. package/tsconfig.compiler.json +13 -13
  150. package/tsconfig.io.json +12 -12
  151. package/tsconfig.json +22 -22
  152. package/tsconfig.logger.json +12 -12
  153. package/tsconfig.server.json +10 -10
  154. package/tsconfig.shared.json +12 -12
  155. package/vitest.config.ts +26 -26
  156. package/.idea/codeStyles/Project.xml +0 -54
  157. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  158. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  159. package/.idea/modules.xml +0 -8
  160. package/.idea/prettier.xml +0 -7
  161. package/.idea/toiljs.iml +0 -8
  162. package/.idea/vcs.xml +0 -6
  163. package/.toil/entry.tsx +0 -9
  164. package/.toil/index.html +0 -12
  165. package/.toil/routes.ts +0 -9
  166. package/build/cli/configure.d.ts +0 -16
  167. package/build/cli/configure.js +0 -272
  168. package/build/cli/create.d.ts +0 -16
  169. package/build/cli/create.js +0 -420
  170. package/build/cli/diagnostics.d.ts +0 -55
  171. package/build/cli/diagnostics.js +0 -333
  172. package/build/cli/doctor.d.ts +0 -6
  173. package/build/cli/doctor.js +0 -249
  174. package/build/cli/features.d.ts +0 -25
  175. package/build/cli/features.js +0 -107
  176. package/build/cli/index.d.ts +0 -2
  177. package/build/cli/proc.d.ts +0 -6
  178. package/build/cli/proc.js +0 -31
  179. package/build/cli/ui.d.ts +0 -9
  180. package/build/cli/ui.js +0 -75
  181. package/build/cli/update.d.ts +0 -7
  182. package/build/cli/update.js +0 -117
  183. package/build/cli/updates.d.ts +0 -10
  184. package/build/cli/updates.js +0 -45
  185. package/build/cli/validate.d.ts +0 -4
  186. package/build/cli/validate.js +0 -19
  187. package/build/client/Link.d.ts +0 -8
  188. package/build/client/Link.js +0 -44
  189. package/build/client/NavLink.d.ts +0 -14
  190. package/build/client/NavLink.js +0 -37
  191. package/build/client/Router.d.ts +0 -7
  192. package/build/client/Router.js +0 -55
  193. package/build/client/channel.d.ts +0 -23
  194. package/build/client/channel.js +0 -94
  195. package/build/client/error-boundary.d.ts +0 -16
  196. package/build/client/error-boundary.js +0 -19
  197. package/build/client/head.d.ts +0 -26
  198. package/build/client/head.js +0 -87
  199. package/build/client/hooks.d.ts +0 -17
  200. package/build/client/hooks.js +0 -48
  201. package/build/client/lazy.d.ts +0 -16
  202. package/build/client/lazy.js +0 -53
  203. package/build/client/match.d.ts +0 -2
  204. package/build/client/match.js +0 -32
  205. package/build/client/mount.d.ts +0 -2
  206. package/build/client/mount.js +0 -13
  207. package/build/client/navigation.d.ts +0 -13
  208. package/build/client/navigation.js +0 -97
  209. package/build/client/params-context.d.ts +0 -2
  210. package/build/client/params-context.js +0 -2
  211. package/build/client/prefetch.d.ts +0 -11
  212. package/build/client/prefetch.js +0 -100
  213. package/build/client/runtime.d.ts +0 -31
  214. package/build/client/runtime.js +0 -112
  215. package/build/client/scroll.d.ts +0 -8
  216. package/build/client/scroll.js +0 -36
  217. package/toil-env.d.ts +0 -16
@@ -1,182 +1,219 @@
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
+ typeof client.devtools === 'object' && client.devtools.ai ? client.devtools.ai : null,
215
+ seo: client.seo ?? null,
216
+ runtimePath: resolveRuntimePath(),
217
+ vite: client.vite ?? {},
218
+ };
219
+ }