toiljs 0.0.115 → 0.0.117

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 (326) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +16 -7
  3. package/TYPESCRIPT_LAW.md +1946 -2073
  4. package/build/backend/.tsbuildinfo +1 -1
  5. package/build/cli/.tsbuildinfo +1 -1
  6. package/build/cli/index.js +2375 -258
  7. package/build/client/.tsbuildinfo +1 -1
  8. package/build/client/dev/devtools.js +1 -1
  9. package/build/client/dev/error-overlay.js +1 -1
  10. package/build/client/routing/mount.js +1 -1
  11. package/build/compiler/.tsbuildinfo +1 -1
  12. package/build/compiler/auth-emails.js +7 -3
  13. package/build/compiler/emails.js +1 -1
  14. package/build/compiler/index.d.ts +1 -0
  15. package/build/compiler/index.js +25 -4
  16. package/build/compiler/pages.js +2 -3
  17. package/build/compiler/prerender.d.ts +3 -8
  18. package/build/compiler/prerender.js +88 -127
  19. package/build/compiler/ssg.js +3 -4
  20. package/build/compiler/template-build.js +3 -4
  21. package/build/compiler/toil-docs.generated.js +6 -5
  22. package/build/compiler/vite.js +3 -6
  23. package/build/devserver/.tsbuildinfo +1 -1
  24. package/build/devserver/db/database.js +7 -3
  25. package/build/devserver/db/types.js +1 -1
  26. package/build/devserver/production.js +4 -3
  27. package/build/devserver/runtime/crypto.d.ts +1 -1
  28. package/build/io/.tsbuildinfo +1 -1
  29. package/build/logger/.tsbuildinfo +1 -1
  30. package/build/shared/.tsbuildinfo +1 -1
  31. package/examples/basic/client/routes/analytics.tsx +7 -5
  32. package/examples/basic/server/tsconfig.json +1 -3
  33. package/package.json +45 -44
  34. package/presets/no-uint8array-tostring.js +120 -153
  35. package/presets/oxlint.d.ts +5 -0
  36. package/presets/oxlint.js +224 -0
  37. package/server/runtime/tsconfig.json +1 -3
  38. package/tsconfig.json +2 -11
  39. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  40. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
  41. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  42. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  43. package/.github/PULL_REQUEST_TEMPLATE.md +0 -43
  44. package/.github/changelog-config.json +0 -45
  45. package/.github/dependabot.yml +0 -27
  46. package/.github/workflows/ci.yml +0 -222
  47. package/.vscode/settings.json +0 -10
  48. package/docs/README.md +0 -107
  49. package/docs/auth/README.md +0 -104
  50. package/docs/auth/configuration.md +0 -105
  51. package/docs/auth/emails.md +0 -92
  52. package/docs/auth/extending.md +0 -202
  53. package/docs/auth/how-it-works.md +0 -138
  54. package/docs/auth/usage.md +0 -188
  55. package/docs/backend/README.md +0 -143
  56. package/docs/backend/data.md +0 -351
  57. package/docs/backend/rest.md +0 -402
  58. package/docs/backend/rpc.md +0 -226
  59. package/docs/background/README.md +0 -114
  60. package/docs/background/daemons.md +0 -276
  61. package/docs/background/derive.md +0 -179
  62. package/docs/cli/README.md +0 -379
  63. package/docs/concepts/ai-guide.md +0 -132
  64. package/docs/concepts/config.md +0 -416
  65. package/docs/concepts/decorators.md +0 -127
  66. package/docs/concepts/security.md +0 -108
  67. package/docs/concepts/tiers.md +0 -166
  68. package/docs/concepts/types.md +0 -216
  69. package/docs/database/README.md +0 -143
  70. package/docs/database/capacity.md +0 -350
  71. package/docs/database/counters.md +0 -174
  72. package/docs/database/documents.md +0 -277
  73. package/docs/database/events.md +0 -307
  74. package/docs/database/membership.md +0 -246
  75. package/docs/database/setup.md +0 -155
  76. package/docs/database/unique.md +0 -216
  77. package/docs/database/views.md +0 -246
  78. package/docs/frontend/README.md +0 -104
  79. package/docs/frontend/components.md +0 -286
  80. package/docs/frontend/data-fetching.md +0 -260
  81. package/docs/frontend/images.md +0 -148
  82. package/docs/frontend/metadata.md +0 -344
  83. package/docs/frontend/navigation.md +0 -296
  84. package/docs/frontend/rendering.md +0 -236
  85. package/docs/frontend/routing.md +0 -346
  86. package/docs/frontend/scripts.md +0 -118
  87. package/docs/frontend/search.md +0 -191
  88. package/docs/frontend/styling.md +0 -147
  89. package/docs/frontend/toil-global.md +0 -216
  90. package/docs/getting-started/README.md +0 -81
  91. package/docs/getting-started/create-project.md +0 -131
  92. package/docs/getting-started/deploy.md +0 -101
  93. package/docs/getting-started/first-app.md +0 -215
  94. package/docs/getting-started/installation.md +0 -124
  95. package/docs/getting-started/migrating.md +0 -125
  96. package/docs/getting-started/project-structure.md +0 -163
  97. package/docs/introduction/README.md +0 -66
  98. package/docs/introduction/design-principles.md +0 -81
  99. package/docs/introduction/distributed.md +0 -91
  100. package/docs/introduction/how-it-works.md +0 -121
  101. package/docs/introduction/hyperscale.md +0 -70
  102. package/docs/introduction/modern-stack.md +0 -85
  103. package/docs/introduction/vs-other-frameworks.md +0 -64
  104. package/docs/introduction/why-toil.md +0 -99
  105. package/docs/llms.txt +0 -95
  106. package/docs/realtime/README.md +0 -102
  107. package/docs/realtime/channels.md +0 -211
  108. package/docs/realtime/streams.md +0 -369
  109. package/docs/services/README.md +0 -60
  110. package/docs/services/analytics.md +0 -279
  111. package/docs/services/caching.md +0 -175
  112. package/docs/services/cookies.md +0 -235
  113. package/docs/services/crypto.md +0 -209
  114. package/docs/services/email.md +0 -289
  115. package/docs/services/environment.md +0 -141
  116. package/docs/services/ratelimit.md +0 -174
  117. package/docs/services/time.md +0 -85
  118. package/eslint.config.js +0 -57
  119. package/examples/basic/client/routes/docs/[...slug].tsx +0 -12
  120. package/presets/eslint.js +0 -88
  121. package/src/backend/index.ts +0 -204
  122. package/src/cli/configure.ts +0 -363
  123. package/src/cli/create.ts +0 -924
  124. package/src/cli/db.ts +0 -158
  125. package/src/cli/diagnostics.ts +0 -665
  126. package/src/cli/doctor.ts +0 -982
  127. package/src/cli/features.ts +0 -170
  128. package/src/cli/index.ts +0 -326
  129. package/src/cli/notify.ts +0 -120
  130. package/src/cli/proc.ts +0 -56
  131. package/src/cli/ui.ts +0 -169
  132. package/src/cli/update.ts +0 -248
  133. package/src/cli/updates.ts +0 -92
  134. package/src/cli/validate.ts +0 -31
  135. package/src/cli/version-check.ts +0 -125
  136. package/src/client/auth.ts +0 -869
  137. package/src/client/channel/channel.ts +0 -146
  138. package/src/client/components/Form.tsx +0 -65
  139. package/src/client/components/Image.tsx +0 -160
  140. package/src/client/components/Script.tsx +0 -113
  141. package/src/client/components/Slot.tsx +0 -21
  142. package/src/client/dev/devtools.tsx +0 -1089
  143. package/src/client/dev/error-overlay.tsx +0 -225
  144. package/src/client/errors.ts +0 -11
  145. package/src/client/head/head.ts +0 -182
  146. package/src/client/head/metadata.ts +0 -110
  147. package/src/client/index.ts +0 -130
  148. package/src/client/navigation/Link.tsx +0 -108
  149. package/src/client/navigation/NavLink.tsx +0 -86
  150. package/src/client/navigation/navigation.ts +0 -235
  151. package/src/client/navigation/prefetch.ts +0 -169
  152. package/src/client/navigation/scroll.ts +0 -53
  153. package/src/client/routing/Router.tsx +0 -216
  154. package/src/client/routing/action.ts +0 -122
  155. package/src/client/routing/error-boundary.tsx +0 -43
  156. package/src/client/routing/hooks.ts +0 -140
  157. package/src/client/routing/lazy.ts +0 -77
  158. package/src/client/routing/loader.ts +0 -381
  159. package/src/client/routing/match.ts +0 -47
  160. package/src/client/routing/mount.tsx +0 -90
  161. package/src/client/routing/params-context.ts +0 -10
  162. package/src/client/routing/slot-context.ts +0 -7
  163. package/src/client/rpc.ts +0 -97
  164. package/src/client/search/search.ts +0 -189
  165. package/src/client/search/use-page-search.ts +0 -73
  166. package/src/client/ssr/markers.tsx +0 -172
  167. package/src/client/stream/client.ts +0 -237
  168. package/src/client/types.ts +0 -73
  169. package/src/compiler/auth-emails.ts +0 -312
  170. package/src/compiler/config.ts +0 -369
  171. package/src/compiler/docs.ts +0 -127
  172. package/src/compiler/email-preview.ts +0 -314
  173. package/src/compiler/emails.ts +0 -404
  174. package/src/compiler/fonts.ts +0 -89
  175. package/src/compiler/generate.ts +0 -471
  176. package/src/compiler/image-blur.ts +0 -42
  177. package/src/compiler/image-report.ts +0 -88
  178. package/src/compiler/index.ts +0 -1362
  179. package/src/compiler/pages.ts +0 -49
  180. package/src/compiler/plugin.ts +0 -391
  181. package/src/compiler/prerender.ts +0 -263
  182. package/src/compiler/routes.ts +0 -170
  183. package/src/compiler/seo.ts +0 -415
  184. package/src/compiler/sri.ts +0 -144
  185. package/src/compiler/ssg.ts +0 -177
  186. package/src/compiler/ssr-codegen.ts +0 -85
  187. package/src/compiler/template-build.ts +0 -676
  188. package/src/compiler/template.ts +0 -262
  189. package/src/compiler/toil-docs.generated.ts +0 -77
  190. package/src/compiler/vite.ts +0 -245
  191. package/src/devserver/analytics/index.ts +0 -317
  192. package/src/devserver/config/dotenv.ts +0 -102
  193. package/src/devserver/config/env.ts +0 -30
  194. package/src/devserver/config/ratelimit.ts +0 -123
  195. package/src/devserver/daemon/catalog.ts +0 -120
  196. package/src/devserver/daemon/cron.ts +0 -87
  197. package/src/devserver/daemon/host.ts +0 -134
  198. package/src/devserver/daemon/index.ts +0 -369
  199. package/src/devserver/daemon/runtime.ts +0 -48
  200. package/src/devserver/db/catalog.ts +0 -109
  201. package/src/devserver/db/database.ts +0 -1834
  202. package/src/devserver/db/derives.ts +0 -121
  203. package/src/devserver/db/index.ts +0 -20
  204. package/src/devserver/db/routeKinds.ts +0 -191
  205. package/src/devserver/db/types.ts +0 -168
  206. package/src/devserver/email/caps.ts +0 -0
  207. package/src/devserver/email/config.ts +0 -141
  208. package/src/devserver/email/console.ts +0 -348
  209. package/src/devserver/email/index.ts +0 -155
  210. package/src/devserver/email/providers.ts +0 -131
  211. package/src/devserver/email/status.ts +0 -23
  212. package/src/devserver/email/validate.ts +0 -37
  213. package/src/devserver/email/wire.ts +0 -55
  214. package/src/devserver/http/cache.ts +0 -0
  215. package/src/devserver/http/envelope.ts +0 -157
  216. package/src/devserver/http/proxy.ts +0 -172
  217. package/src/devserver/http/runtime.ts +0 -387
  218. package/src/devserver/index.ts +0 -43
  219. package/src/devserver/production-ipc.ts +0 -63
  220. package/src/devserver/production-worker.ts +0 -83
  221. package/src/devserver/production.ts +0 -718
  222. package/src/devserver/runtime/crypto.ts +0 -587
  223. package/src/devserver/runtime/host.ts +0 -427
  224. package/src/devserver/runtime/module.ts +0 -442
  225. package/src/devserver/server.ts +0 -251
  226. package/src/devserver/ssr.ts +0 -208
  227. package/src/devserver/stream/catalog.ts +0 -106
  228. package/src/devserver/stream/host.ts +0 -42
  229. package/src/devserver/stream/index.ts +0 -301
  230. package/src/devserver/stream/manager.ts +0 -167
  231. package/src/devserver/stream/router.ts +0 -101
  232. package/src/devserver/stream/wire.ts +0 -58
  233. package/src/devserver/stream/ws.ts +0 -78
  234. package/src/devserver/wasm/sections.ts +0 -59
  235. package/src/devserver/wasm/surface.ts +0 -115
  236. package/src/io/FastMap.ts +0 -151
  237. package/src/io/FastSet.ts +0 -113
  238. package/src/io/codec.ts +0 -362
  239. package/src/io/index.ts +0 -10
  240. package/src/io/lengths.ts +0 -14
  241. package/src/io/types.ts +0 -19
  242. package/src/logger/index.ts +0 -22
  243. package/src/shared/index.ts +0 -46
  244. package/test/analytics-dev.test.ts +0 -113
  245. package/test/assembly/aspect-shim.ts +0 -33
  246. package/test/assembly/cookie.spec.ts +0 -303
  247. package/test/assembly/example.spec.ts +0 -22
  248. package/test/assembly/ssr.spec.ts +0 -95
  249. package/test/assembly.test.ts +0 -59
  250. package/test/auth-emails.test.ts +0 -118
  251. package/test/built-ssr.test.ts +0 -148
  252. package/test/channel.test.ts +0 -21
  253. package/test/config-host-port.test.ts +0 -59
  254. package/test/configure.test.ts +0 -94
  255. package/test/daemon-build.test.ts +0 -278
  256. package/test/daemon-catalog.test.ts +0 -349
  257. package/test/daemon-emulation.test.ts +0 -256
  258. package/test/db.test.ts +0 -0
  259. package/test/devserver-database.test.ts +0 -1102
  260. package/test/devserver-email.test.ts +0 -306
  261. package/test/devserver-pqauth.test.ts +0 -93
  262. package/test/devserver-secrets.test.ts +0 -63
  263. package/test/devserver.test.ts +0 -259
  264. package/test/doctor.test.ts +0 -298
  265. package/test/dom/Image.test.tsx +0 -144
  266. package/test/dom/Link.test.tsx +0 -67
  267. package/test/dom/NavLink.test.tsx +0 -37
  268. package/test/dom/Script.test.tsx +0 -48
  269. package/test/dom/action.test.tsx +0 -146
  270. package/test/dom/error-overlay.test.tsx +0 -44
  271. package/test/dom/loader.test.tsx +0 -121
  272. package/test/dom/navigation.test.ts +0 -59
  273. package/test/dom/revalidate.test.tsx +0 -38
  274. package/test/dom/route-head.test.tsx +0 -56
  275. package/test/dom/router-loading.test.tsx +0 -44
  276. package/test/dom/scroll.test.ts +0 -56
  277. package/test/dom/slot.test.tsx +0 -131
  278. package/test/dom/use-metadata.test.tsx +0 -58
  279. package/test/dom/view-transitions.test.tsx +0 -53
  280. package/test/dynamic-routing.test.ts +0 -132
  281. package/test/email-console.test.ts +0 -86
  282. package/test/email-preview.test.ts +0 -73
  283. package/test/emails.test.ts +0 -58
  284. package/test/errors.test.ts +0 -21
  285. package/test/example-guestbook.test.ts +0 -123
  286. package/test/features.test.ts +0 -149
  287. package/test/fixtures/bignum-wire/spec.ts +0 -25
  288. package/test/fixtures/daemon-app.ts +0 -65
  289. package/test/fixtures/stream-echo.ts +0 -26
  290. package/test/fixtures/stream-gate.ts +0 -28
  291. package/test/fixtures/stream-trap.ts +0 -18
  292. package/test/fixtures/stream-typed.ts +0 -41
  293. package/test/fonts.test.ts +0 -28
  294. package/test/global-setup.ts +0 -17
  295. package/test/head.test.ts +0 -42
  296. package/test/image-blur.test.ts +0 -50
  297. package/test/io.test.ts +0 -117
  298. package/test/metadata.test.ts +0 -40
  299. package/test/navlink.test.ts +0 -28
  300. package/test/pages.test.ts +0 -105
  301. package/test/placeholder.test.ts +0 -9
  302. package/test/pqauth-e2e.test.ts +0 -216
  303. package/test/pqauth-email.test.ts +0 -801
  304. package/test/prerender.test.ts +0 -116
  305. package/test/prettier-plugin.test.ts +0 -46
  306. package/test/routes.test.ts +0 -76
  307. package/test/rpc-bignum-wire.test.ts +0 -164
  308. package/test/rpc-dispatch.test.ts +0 -132
  309. package/test/rpc-kinds.test.ts +0 -18
  310. package/test/rpc.test.ts +0 -66
  311. package/test/search.test.ts +0 -114
  312. package/test/seo.test.ts +0 -175
  313. package/test/slot-layouts.test.ts +0 -69
  314. package/test/sri.test.ts +0 -129
  315. package/test/ssg.test.ts +0 -36
  316. package/test/ssr-hydration.test.tsx +0 -122
  317. package/test/ssr-render.test.ts +0 -197
  318. package/test/ssr-template.test.tsx +0 -482
  319. package/test/stream-emulation.test.ts +0 -479
  320. package/test/ui.test.ts +0 -40
  321. package/test/update.test.ts +0 -58
  322. package/test/validate.test.ts +0 -42
  323. package/test/version-check.test.ts +0 -130
  324. package/tests/data-parity/generated-parity.ts +0 -99
  325. package/tests/data-parity/parity.ts +0 -80
  326. package/tests/data-parity/spec.ts +0 -46
@@ -1,177 +0,0 @@
1
- /**
2
- * Build-time SSG for dynamic routes. After the client bundle is written, this loads each dynamic
3
- * route that exports `generateStaticParams`, enumerates its concrete URLs, runs the route's
4
- * `generateMetadata` per URL, and bakes a `<url>/index.html` (so JS-less crawlers get per-page tags)
5
- * plus a `sitemap.xml` entry. Opt-in: a route without `generateStaticParams` is untouched, and the
6
- * whole pass is skipped when no such route exists or `seo` is unconfigured. Build-only.
7
- *
8
- * Runs from `build()` (not the prerender Vite plugin) so it can reuse `createViteConfig` without the
9
- * `vite.ts` <-> `prerender.ts` import cycle; it spins up a short-lived SSR server to load route source.
10
- */
11
- import fs from 'node:fs';
12
- import path from 'node:path';
13
-
14
- import { createServer } from 'vite';
15
-
16
- import { type ResolvedToilConfig } from './config.js';
17
- import { extractStaticMetadata, loadTypeScript } from './prerender.js';
18
- import { scanRoutes } from './routes.js';
19
- import { injectSeoHtml, joinUrl, type LlmsPage, llmsTxt, routeSeo, sitemapXml } from './seo.js';
20
- import { createViteConfig } from './vite.js';
21
-
22
- /** Reads a string field off a metadata record, or undefined. */
23
- function metaString(meta: Record<string, unknown> | null, key: string): string | undefined {
24
- const value = meta?.[key];
25
- return typeof value === 'string' ? value : undefined;
26
- }
27
-
28
- type StaticParams = Record<string, string | string[]>;
29
-
30
- interface RouteModule {
31
- generateStaticParams?: () => StaticParams[] | Promise<StaticParams[]>;
32
- generateMetadata?: (args: {
33
- params: StaticParams;
34
- searchParams: URLSearchParams;
35
- data: unknown;
36
- }) => unknown;
37
- loader?: (args: { params: StaticParams; searchParams: URLSearchParams }) => unknown;
38
- metadata?: Record<string, unknown>;
39
- }
40
-
41
- /** Substitutes `:param` / `*catch-all` segments in a route pattern with concrete param values. */
42
- export function fillPattern(pattern: string, params: StaticParams): string {
43
- return pattern.replace(/[:*]([A-Za-z0-9_]+)/g, (_m, name: string) => {
44
- const value = params[name] as string | string[] | undefined;
45
- if (Array.isArray(value)) return value.join('/');
46
- return value ?? '';
47
- });
48
- }
49
-
50
- /** Coerces an unknown module export to a typed Metadata-ish record, or null. */
51
- function asMetadata(value: unknown): Record<string, unknown> | null {
52
- return typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : null;
53
- }
54
-
55
- /**
56
- * Pre-renders every dynamic route that opts in via `generateStaticParams`. Bakes per-URL HTML into
57
- * `outDir` and rewrites `sitemap.xml` with the generated URLs. Returns the list of generated URLs.
58
- */
59
- export async function prerenderStaticParams(cfg: ResolvedToilConfig): Promise<string[]> {
60
- if (!cfg.seo) return [];
61
- const outDir = path.resolve(cfg.root, cfg.outDir);
62
- // Prefer the clean shell stashed by the prerender plugin (no per-route SEO baked in); fall back
63
- // to the built index.html.
64
- const stashed = path.join(cfg.toilDir, 'shell.html');
65
- const shellPath = fs.existsSync(stashed) ? stashed : path.join(outDir, 'index.html');
66
- if (!fs.existsSync(shellPath)) return [];
67
-
68
- const allRoutes = scanRoutes(cfg.routesAbsDir);
69
- const dynamic = allRoutes.filter(
70
- (r) => r.slot === undefined && !r.intercept && /[:*]/.test(r.pattern),
71
- );
72
- if (dynamic.length === 0) return [];
73
-
74
- const shell = fs.readFileSync(shellPath, 'utf8');
75
- const server = await createServer({
76
- ...(await createViteConfig(cfg)),
77
- server: { middlewareMode: true, hmr: false },
78
- appType: 'custom',
79
- logLevel: 'silent',
80
- });
81
-
82
- const baseUrl = cfg.seo.url;
83
- const generated: string[] = [];
84
- const dynamicPages: LlmsPage[] = [];
85
- const warn = (msg: string): void => {
86
- process.stderr.write(` toil: SSG ${msg}\n`);
87
- };
88
- try {
89
- for (const route of dynamic) {
90
- let mod: RouteModule;
91
- try {
92
- mod = (await server.ssrLoadModule(route.file)) as RouteModule;
93
- } catch (err) {
94
- warn(
95
- `skipped ${route.pattern} (${err instanceof Error ? err.message : String(err)})`,
96
- );
97
- continue;
98
- }
99
- if (typeof mod.generateStaticParams !== 'function') continue;
100
- const paramSets = await mod.generateStaticParams();
101
- for (const params of paramSets) {
102
- const url = fillPattern(route.pattern, params);
103
- // Containment guard: a param value with `..`/separators could make `url` resolve the
104
- // output path outside `outDir`. Resolve the target up front and skip anything that
105
- // escapes, so a (possibly externally-derived) param can't clobber files elsewhere.
106
- const target = path.join(outDir, url.replace(/^\//, ''), 'index.html');
107
- const outRoot = path.resolve(outDir);
108
- const absTarget = path.resolve(target);
109
- if (absTarget !== outRoot && !absTarget.startsWith(outRoot + path.sep)) {
110
- warn(`skipped ${route.pattern}: params escape outDir (${url})`);
111
- continue;
112
- }
113
- let metadata: Record<string, unknown> | null = null;
114
- try {
115
- if (typeof mod.generateMetadata === 'function') {
116
- const searchParams = new URLSearchParams();
117
- const data =
118
- typeof mod.loader === 'function'
119
- ? await mod.loader({ params, searchParams })
120
- : undefined;
121
- metadata = asMetadata(
122
- await mod.generateMetadata({ params, searchParams, data }),
123
- );
124
- } else if (mod.metadata) {
125
- metadata = asMetadata(mod.metadata);
126
- }
127
- } catch (err) {
128
- warn(
129
- `metadata failed for ${url} (${err instanceof Error ? err.message : String(err)})`,
130
- );
131
- }
132
- const html = injectSeoHtml(shell, routeSeo(cfg.seo, metadata, url));
133
- fs.mkdirSync(path.dirname(target), { recursive: true });
134
- fs.writeFileSync(target, html);
135
- generated.push(url);
136
- dynamicPages.push({
137
- title: metaString(metadata, 'title') ?? url,
138
- url: baseUrl !== undefined ? joinUrl(baseUrl, url) : url,
139
- description: metaString(metadata, 'description'),
140
- });
141
- }
142
- }
143
- } finally {
144
- await server.close();
145
- }
146
-
147
- if (generated.length > 0) {
148
- const sitemap = sitemapXml(cfg.seo, allRoutes, generated);
149
- if (sitemap) fs.writeFileSync(path.join(outDir, 'sitemap.xml'), sitemap);
150
- process.stdout.write(
151
- ` ✓ prerendered ${String(generated.length)} dynamic route${generated.length === 1 ? '' : 's'}\n`,
152
- );
153
- }
154
-
155
- // Rewrite llms.txt with the full page index: every static route's resolved title/description plus
156
- // the enumerated dynamic pages, so AI crawlers get the whole site, not just the static paths.
157
- if (baseUrl !== undefined) {
158
- const ts = await loadTypeScript(cfg.root);
159
- const staticPages: LlmsPage[] = allRoutes
160
- .filter((r) => r.slot === undefined && !r.intercept && !/[:*]/.test(r.pattern))
161
- .map((r): LlmsPage => {
162
- const meta = ts ? extractStaticMetadata(ts, r.file) : null;
163
- return {
164
- title: metaString(meta, 'title') ?? (r.pattern === '/' ? 'Home' : r.pattern),
165
- url: joinUrl(baseUrl, r.pattern),
166
- description: metaString(meta, 'description'),
167
- };
168
- });
169
- const pages = [...staticPages, ...dynamicPages];
170
- if (pages.length > 0) {
171
- const llms = llmsTxt(cfg.seo, allRoutes, pages);
172
- if (llms) fs.writeFileSync(path.join(outDir, 'llms.txt'), llms);
173
- }
174
- }
175
-
176
- return generated;
177
- }
@@ -1,85 +0,0 @@
1
- /**
2
- * Build-time codegen of the AssemblyScript surface a route's guest `render`
3
- * uses. From the extracted holes (see `template.ts`) this emits:
4
- *
5
- * - a `Slot` enum (hole name -> stable numeric id, the SAME ids the host
6
- * `.slots` manifest carries), so host and guest agree by construction; and
7
- * - the coherence `HASH` (32 bytes) compiled into the guest and echoed in
8
- * every values envelope; the host 500s on a mismatch (deploy skew).
9
- *
10
- * The render BODY is authored against `SlotValues` (the typed, hand-writable
11
- * API). A route's `render(req)` derives its data from the request/edge and
12
- * fills the slots:
13
- *
14
- * ```ts
15
- * import { Request } from 'toiljs/server/runtime';
16
- * import { SlotValues } from 'toiljs/server/runtime/ssr/slots';
17
- * import { Slot, HASH } from './_ssr/u_name.slots';
18
- *
19
- * export function renderUName(req: Request): SlotValues {
20
- * const v = new SlotValues(HASH);
21
- * v.setText(Slot.username, pathParam(req, 'name'));
22
- * v.setRaw(Slot.bio, bio);
23
- * const rows = new HtmlBuilder();
24
- * for (let i = 0; i < posts.length; i++) rows.raw('<li>').text(posts[i]).raw('</li>');
25
- * v.setRepeat(Slot.posts, rows);
26
- * return v;
27
- * }
28
- * ```
29
- *
30
- * Generating that body automatically from the JSX-subset bindings is a later
31
- * phase; the typed enum + hash here are what make a hand-written or generated
32
- * body coherent with the deployed template.
33
- */
34
-
35
- import type { SlotRecord } from './template.js';
36
- import { assignSlotIds } from './template.js';
37
-
38
- /** Emit a `StaticArray<u8>` literal of the 32 hash bytes. */
39
- function hashLiteral(hash: Buffer): string {
40
- const bytes = Array.from(hash.values())
41
- .map((b) => `0x${b.toString(16).padStart(2, '0')}`)
42
- .join(', ');
43
- return `[${bytes}]`;
44
- }
45
-
46
- /** A slot name is a valid AS enum member iff it is a bare identifier; anything
47
- * else (e.g. a hyphenated id) is rejected so the generated module can't break
48
- * or smuggle code. */
49
- function isIdent(name: string): boolean {
50
- return /^[A-Za-z_$][\w$]*$/.test(name);
51
- }
52
-
53
- /**
54
- * Generate the `<route>.slots.ts` AssemblyScript module: the `Slot` enum and
55
- * the `HASH` constant. `slots` is the top-level slot list from
56
- * `extractFromHtml`; ids are assigned in document order to match the host
57
- * `.slots` manifest written by `encodeSlots`.
58
- */
59
- export function generateSlotsModule(routeName: string, slots: SlotRecord[], hash: Buffer): string {
60
- if (hash.length !== 32) throw new Error('toil ssr: coherence hash must be 32 bytes');
61
- const ids = assignSlotIds(slots);
62
- const members: string[] = [];
63
- for (const [name, id] of ids) {
64
- if (!isIdent(name)) {
65
- throw new Error(
66
- `toil ssr: hole id "${name}" in route "${routeName}" is not a valid identifier ` +
67
- `(use [A-Za-z_][\\w]*) so it can be a Slot enum member`,
68
- );
69
- }
70
- members.push(` ${name} = ${id},`);
71
- }
72
- return `// AUTO-GENERATED by toil (edge SSR). Do not edit.
73
- // Route: ${routeName}. Slot ids match the deployed .slots manifest; HASH is the
74
- // coherence hash the host checks against the template (deploy-skew guard).
75
-
76
- /** Stable hole ids for this route's template. */
77
- export enum Slot {
78
- ${members.join('\n')}
79
- }
80
-
81
- /** Coherence hash (32 bytes) baked into the guest and echoed in every values
82
- * envelope; the host rejects a response whose hash != the deployed template. */
83
- export const HASH: StaticArray<u8> = ${hashLiteral(hash)};
84
- `;
85
- }