toiljs 0.0.54 → 0.0.56

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 (105) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/build/backend/.tsbuildinfo +1 -1
  3. package/build/cli/.tsbuildinfo +1 -1
  4. package/build/cli/index.js +9 -5
  5. package/build/client/.tsbuildinfo +1 -1
  6. package/build/client/auth.js +1 -1
  7. package/build/client/components/Image.d.ts +1 -1
  8. package/build/client/dev/devtools.js +3 -1
  9. package/build/client/index.d.ts +2 -2
  10. package/build/client/index.js +2 -2
  11. package/build/client/routing/Router.js +1 -1
  12. package/build/client/routing/mount.js +1 -1
  13. package/build/compiler/.tsbuildinfo +1 -1
  14. package/build/compiler/docs.js +1 -1
  15. package/build/compiler/seo.js +1 -3
  16. package/build/compiler/template-build.js +1 -1
  17. package/build/devserver/.tsbuildinfo +1 -1
  18. package/build/devserver/cache.js +0 -0
  19. package/build/devserver/crypto.js +45 -17
  20. package/build/devserver/database.d.ts +8 -0
  21. package/build/devserver/database.js +416 -0
  22. package/build/devserver/email/caps.js +0 -0
  23. package/build/devserver/email/config.js +7 -2
  24. package/build/devserver/email/validate.js +1 -4
  25. package/build/devserver/host.d.ts +2 -0
  26. package/build/devserver/host.js +3 -2
  27. package/build/devserver/index.d.ts +1 -1
  28. package/build/devserver/index.js +3 -2
  29. package/build/devserver/module.js +52 -7
  30. package/build/devserver/proxy.js +2 -1
  31. package/build/io/.tsbuildinfo +1 -1
  32. package/build/io/codec.d.ts +5 -5
  33. package/build/io/codec.js +193 -77
  34. package/examples/basic/client/components/HoneycombBackground.tsx +1 -1
  35. package/examples/basic/client/public/images/logo.svg +37 -34
  36. package/examples/basic/client/public/index.html +14 -14
  37. package/examples/basic/client/routes/auth.tsx +18 -10
  38. package/examples/basic/client/routes/cookies.tsx +15 -24
  39. package/examples/basic/client/routes/crypto.tsx +4 -5
  40. package/examples/basic/client/routes/features/template/template.tsx +1 -1
  41. package/examples/basic/client/routes/hello.tsx +1 -1
  42. package/examples/basic/client/routes/pq.tsx +14 -14
  43. package/examples/basic/client/routes/rest.tsx +50 -1
  44. package/examples/basic/client/styles/main.css +25 -22
  45. package/examples/basic/client/toil.tsx +1 -1
  46. package/examples/basic/server/README.md +8 -8
  47. package/examples/basic/server/core/AppHandler.ts +4 -7
  48. package/examples/basic/server/main.ts +1 -0
  49. package/examples/basic/server/models/GuestEntry.ts +12 -0
  50. package/examples/basic/server/models/GuestbookView.ts +10 -0
  51. package/examples/basic/server/models/NewMessage.ts +6 -0
  52. package/examples/basic/server/routes/Auth.ts +50 -106
  53. package/examples/basic/server/routes/EnvDemo.ts +9 -3
  54. package/examples/basic/server/routes/Guestbook.ts +62 -0
  55. package/package.json +2 -2
  56. package/server/globals/auth.ts +3 -3
  57. package/server/globals/twofactor.ts +2 -1
  58. package/server/runtime/http/securecookies.ts +3 -2
  59. package/src/backend/index.ts +4 -2
  60. package/src/cli/doctor.ts +10 -3
  61. package/src/cli/notify.ts +1 -6
  62. package/src/cli/ui.ts +3 -3
  63. package/src/cli/version-check.ts +5 -1
  64. package/src/client/auth.ts +33 -10
  65. package/src/client/components/Form.tsx +2 -2
  66. package/src/client/components/Image.tsx +1 -1
  67. package/src/client/components/Script.tsx +1 -1
  68. package/src/client/components/Slot.tsx +1 -1
  69. package/src/client/dev/devtools.tsx +121 -54
  70. package/src/client/dev/error-overlay.tsx +7 -1
  71. package/src/client/head/metadata.ts +1 -1
  72. package/src/client/index.ts +13 -2
  73. package/src/client/routing/Router.tsx +2 -2
  74. package/src/client/routing/error-boundary.tsx +1 -1
  75. package/src/client/routing/loader.ts +2 -2
  76. package/src/client/routing/mount.tsx +5 -6
  77. package/src/compiler/docs.ts +1 -1
  78. package/src/compiler/email-preview.ts +1 -1
  79. package/src/compiler/generate.ts +1 -1
  80. package/src/compiler/seo.ts +1 -3
  81. package/src/compiler/ssg.ts +10 -4
  82. package/src/compiler/template-build.ts +2 -7
  83. package/src/compiler/template.ts +1 -4
  84. package/src/compiler/vite.ts +1 -1
  85. package/src/devserver/cache.ts +0 -0
  86. package/src/devserver/crypto.ts +140 -51
  87. package/src/devserver/database.ts +600 -0
  88. package/src/devserver/dotenv.ts +10 -2
  89. package/src/devserver/email/caps.ts +0 -0
  90. package/src/devserver/email/config.ts +8 -2
  91. package/src/devserver/email/index.ts +3 -3
  92. package/src/devserver/email/validate.ts +1 -4
  93. package/src/devserver/envelope.ts +3 -3
  94. package/src/devserver/host.ts +22 -9
  95. package/src/devserver/index.ts +15 -6
  96. package/src/devserver/module.ts +59 -11
  97. package/src/devserver/proxy.ts +5 -7
  98. package/src/io/codec.ts +226 -83
  99. package/test/devserver-database.test.ts +364 -0
  100. package/test/devserver-pqauth.test.ts +5 -65
  101. package/test/example-guestbook.test.ts +78 -0
  102. package/test/pqauth-e2e.test.ts +6 -6
  103. package/build/devserver/kv.d.ts +0 -3
  104. package/build/devserver/kv.js +0 -53
  105. package/src/devserver/kv.ts +0 -93
@@ -7,7 +7,7 @@
7
7
  * It stays decoupled from the Router (it computes the current match itself via `matchRoute`) so it
8
8
  * renders even when the app tree has crashed.
9
9
  */
10
- import { useEffect, useState, useSyncExternalStore, type ReactNode } from 'react';
10
+ import { type ReactNode, useEffect, useState, useSyncExternalStore } from 'react';
11
11
 
12
12
  import { type DevError, getErrorLog, subscribeErrors } from './error-overlay.js';
13
13
  import {
@@ -21,10 +21,10 @@ import {
21
21
  import {
22
22
  clearLoaderData,
23
23
  inspectLoaderCache,
24
+ type LoaderCacheSnapshot,
24
25
  loaderKey,
25
26
  revalidate,
26
27
  subscribeLoaderCache,
27
- type LoaderCacheSnapshot,
28
28
  } from '../routing/loader.js';
29
29
  import { matchRoute } from '../routing/match.js';
30
30
  import { getPages } from '../search/search.js';
@@ -52,10 +52,22 @@ function ToilLogo({ size = 16 }: { size?: number }): ReactNode {
52
52
  x2="467.12"
53
53
  y2="467.12"
54
54
  gradientUnits="userSpaceOnUse">
55
- <stop offset="0" stopColor="#6990ff" />
56
- <stop offset=".28" stopColor="#521be0" />
57
- <stop offset=".66" stopColor="#6900f4" />
58
- <stop offset="1" stopColor="#7f00f6" />
55
+ <stop
56
+ offset="0"
57
+ stopColor="#6990ff"
58
+ />
59
+ <stop
60
+ offset=".28"
61
+ stopColor="#521be0"
62
+ />
63
+ <stop
64
+ offset=".66"
65
+ stopColor="#6900f4"
66
+ />
67
+ <stop
68
+ offset="1"
69
+ stopColor="#7f00f6"
70
+ />
59
71
  </linearGradient>
60
72
  <linearGradient
61
73
  id="toilDtB"
@@ -64,12 +76,28 @@ function ToilLogo({ size = 16 }: { size?: number }): ReactNode {
64
76
  x2="149.99"
65
77
  y2="0"
66
78
  gradientUnits="userSpaceOnUse">
67
- <stop offset=".15" stopColor="#6990ff" stopOpacity=".6" />
68
- <stop offset=".55" stopColor="#531ae1" />
79
+ <stop
80
+ offset=".15"
81
+ stopColor="#6990ff"
82
+ stopOpacity=".6"
83
+ />
84
+ <stop
85
+ offset=".55"
86
+ stopColor="#531ae1"
87
+ />
69
88
  </linearGradient>
70
89
  </defs>
71
- <rect width="500" height="500" rx="130" ry="130" fill="url(#toilDtA)" />
72
- <path d="M299.98,0L0,355.49v-225.49C0,58.2,58.2,0,130,0h169.98Z" fill="url(#toilDtB)" />
90
+ <rect
91
+ width="500"
92
+ height="500"
93
+ rx="130"
94
+ ry="130"
95
+ fill="url(#toilDtA)"
96
+ />
97
+ <path
98
+ d="M299.98,0L0,355.49v-225.49C0,58.2,58.2,0,130,0h169.98Z"
99
+ fill="url(#toilDtB)"
100
+ />
73
101
  <path
74
102
  d="M106.17,111.11h285.24c9.9,0,16.7,9.96,13.09,19.18l-17.98,45.96c-2.11,5.39-7.31,8.94-13.09,8.94h-74.65c-7.76,0-14.06,6.29-14.06,14.06v214.94c0,7.76-6.29,14.06-14.06,14.06h-45.96c-7.76,0-14.06-6.29-14.06-14.06v-217.25c0-7.76-6.29-14.06-14.06-14.06h-73.66c-5.82,0-11.04-3.59-13.12-9.02l-16.76-43.64c-3.54-9.21,3.26-19.1,13.12-19.1Z"
75
103
  fill="#fff"
@@ -194,7 +222,10 @@ function safeJson(value: unknown): string {
194
222
  }
195
223
 
196
224
  /** Reads the current document head's meta + link tags (live). */
197
- function readHead(): { metas: { name: string; content: string }[]; links: { rel: string; href: string }[] } {
225
+ function readHead(): {
226
+ metas: { name: string; content: string }[];
227
+ links: { rel: string; href: string }[];
228
+ } {
198
229
  const metas: { name: string; content: string }[] = [];
199
230
  const links: { rel: string; href: string }[] = [];
200
231
  if (typeof document === 'undefined') return { metas, links };
@@ -346,7 +377,9 @@ function RouteTab({
346
377
  <Row k="slots">{activeSlots.length ? activeSlots.join(', ') : 'none'}</Row>
347
378
  <Row k="navigating">{pending ? 'yes' : 'no'}</Row>
348
379
 
349
- <p className="toil-dt-sec" style={{ marginTop: 12 }}>
380
+ <p
381
+ className="toil-dt-sec"
382
+ style={{ marginTop: 12 }}>
350
383
  Routes ({routes.length})
351
384
  </p>
352
385
  {routes.map((r) => {
@@ -474,7 +507,9 @@ function HeadTab(): ReactNode {
474
507
  <div className="toil-dt-body">
475
508
  <Row k="title">{title || '(none)'}</Row>
476
509
 
477
- <p className="toil-dt-sec" style={{ marginTop: 10 }}>
510
+ <p
511
+ className="toil-dt-sec"
512
+ style={{ marginTop: 10 }}>
478
513
  OpenGraph preview
479
514
  </p>
480
515
  <div className="toil-dt-og">
@@ -491,23 +526,41 @@ function HeadTab(): ReactNode {
491
526
  </div>
492
527
  </div>
493
528
 
494
- <p className="toil-dt-sec" style={{ marginTop: 10 }}>
529
+ <p
530
+ className="toil-dt-sec"
531
+ style={{ marginTop: 10 }}>
495
532
  SEO checklist
496
533
  </p>
497
- <Check ok={Boolean(title)} label="Has a title" />
498
- <Check ok={meta('description') !== undefined} label="Has a meta description" />
499
- <Check ok={og.image !== undefined} label="Has an og:image" />
500
- <Check ok={links.some((l) => l.rel === 'canonical')} label="Has a canonical link" />
534
+ <Check
535
+ ok={Boolean(title)}
536
+ label="Has a title"
537
+ />
538
+ <Check
539
+ ok={meta('description') !== undefined}
540
+ label="Has a meta description"
541
+ />
542
+ <Check
543
+ ok={og.image !== undefined}
544
+ label="Has an og:image"
545
+ />
546
+ <Check
547
+ ok={links.some((l) => l.rel === 'canonical')}
548
+ label="Has a canonical link"
549
+ />
501
550
  <Check
502
551
  ok={pages.length === 0 || described === pages.length}
503
552
  label={`Pages with a description: ${String(described)}/${String(pages.length)}`}
504
553
  />
505
554
 
506
- <p className="toil-dt-sec" style={{ marginTop: 10 }}>
555
+ <p
556
+ className="toil-dt-sec"
557
+ style={{ marginTop: 10 }}>
507
558
  Meta ({metas.length})
508
559
  </p>
509
560
  {metas.map((m, i) => (
510
- <Row k={m.name} key={`${m.name}:${String(i)}`}>
561
+ <Row
562
+ k={m.name}
563
+ key={`${m.name}:${String(i)}`}>
511
564
  {m.content}
512
565
  </Row>
513
566
  ))}
@@ -546,7 +599,8 @@ function BuildTab({ info }: { info: DevInfo | null }): ReactNode {
546
599
 
547
600
  function ErrorsTab(): ReactNode {
548
601
  const errors = useErrors();
549
- if (errors.length === 0) return <p className="toil-dt-empty toil-dt-body">No errors captured.</p>;
602
+ if (errors.length === 0)
603
+ return <p className="toil-dt-empty toil-dt-body">No errors captured.</p>;
550
604
  return (
551
605
  <div className="toil-dt-body">
552
606
  {[...errors].reverse().map((e, i) => (
@@ -974,45 +1028,58 @@ export function DevToolbar({
974
1028
 
975
1029
  return (
976
1030
  <>
977
- <div className={`toil-dt ${p.side}`}>
978
- <div className="toil-dt-panel">
979
- <div className="toil-dt-head">
980
- <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
981
- <ToilLogo size={14} />
982
- <span className="toil-dt-logo">toiljs</span> devtools
983
- <span className={`toil-dt-dot ${dotClass}`} />
984
- </span>
985
- <button
986
- className="toil-dt-x"
987
- onClick={() => {
988
- setPrefs({ open: false });
989
- }}>
990
-
991
- </button>
992
- </div>
993
- <div className="toil-dt-tabs">
994
- {TABS.map((t) => (
1031
+ <div className={`toil-dt ${p.side}`}>
1032
+ <div className="toil-dt-panel">
1033
+ <div className="toil-dt-head">
1034
+ <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
1035
+ <ToilLogo size={14} />
1036
+ <span className="toil-dt-logo">toiljs</span> devtools
1037
+ <span className={`toil-dt-dot ${dotClass}`} />
1038
+ </span>
995
1039
  <button
996
- key={t.id}
997
- className={`toil-dt-tab ${p.tab === t.id ? 'active' : ''}`}
1040
+ className="toil-dt-x"
998
1041
  onClick={() => {
999
- setPrefs({ tab: t.id });
1042
+ setPrefs({ open: false });
1000
1043
  }}>
1001
- {t.label}
1002
- {t.id === 'errors' && errors.length > 0 ? ` (${String(errors.length)})` : ''}
1044
+
1003
1045
  </button>
1004
- ))}
1046
+ </div>
1047
+ <div className="toil-dt-tabs">
1048
+ {TABS.map((t) => (
1049
+ <button
1050
+ key={t.id}
1051
+ className={`toil-dt-tab ${p.tab === t.id ? 'active' : ''}`}
1052
+ onClick={() => {
1053
+ setPrefs({ tab: t.id });
1054
+ }}>
1055
+ {t.label}
1056
+ {t.id === 'errors' && errors.length > 0
1057
+ ? ` (${String(errors.length)})`
1058
+ : ''}
1059
+ </button>
1060
+ ))}
1061
+ </div>
1062
+ {p.tab === 'route' && (
1063
+ <RouteTab
1064
+ routes={routes}
1065
+ slots={slots}
1066
+ info={info}
1067
+ />
1068
+ )}
1069
+ {p.tab === 'data' && <DataTab />}
1070
+ {p.tab === 'head' && <HeadTab />}
1071
+ {p.tab === 'build' && <BuildTab info={info} />}
1072
+ {p.tab === 'errors' && <ErrorsTab />}
1073
+ {p.tab === 'ai' && (
1074
+ <AiTab
1075
+ info={info}
1076
+ routes={routes}
1077
+ />
1078
+ )}
1079
+ {p.tab === 'prefs' && <PrefsTab />}
1005
1080
  </div>
1006
- {p.tab === 'route' && <RouteTab routes={routes} slots={slots} info={info} />}
1007
- {p.tab === 'data' && <DataTab />}
1008
- {p.tab === 'head' && <HeadTab />}
1009
- {p.tab === 'build' && <BuildTab info={info} />}
1010
- {p.tab === 'errors' && <ErrorsTab />}
1011
- {p.tab === 'ai' && <AiTab info={info} routes={routes} />}
1012
- {p.tab === 'prefs' && <PrefsTab />}
1013
1081
  </div>
1014
- </div>
1015
- {pal}
1082
+ {pal}
1016
1083
  </>
1017
1084
  );
1018
1085
  }
@@ -4,7 +4,13 @@
4
4
  * plus `window` `error` / `unhandledrejection` events. Shows the message, stack, and (for render
5
5
  * errors) the React component stack, with Dismiss / Reload. Inert in production builds.
6
6
  */
7
- import { Component, type CSSProperties, type ErrorInfo, type ReactNode, useSyncExternalStore, } from 'react';
7
+ import {
8
+ Component,
9
+ type CSSProperties,
10
+ type ErrorInfo,
11
+ type ReactNode,
12
+ useSyncExternalStore,
13
+ } from 'react';
8
14
 
9
15
  /** A captured dev error. */
10
16
  export interface DevError {
@@ -4,7 +4,7 @@
4
4
  * data); the compiler-driven loader resolves it to a {@link HeadSpec} that the router applies as the
5
5
  * route's baseline head (component-level `useHead`/`<Head>` still compose on top and can override).
6
6
  */
7
- import { useHead, type HeadSpec, type LinkTag, type MetaTag } from './head.js';
7
+ import { type HeadSpec, type LinkTag, type MetaTag, useHead } from './head.js';
8
8
  import type { RouteParams } from '../routing/match.js';
9
9
 
10
10
  /** OpenGraph fields, expanded to `og:*` meta tags. */
@@ -10,7 +10,13 @@
10
10
 
11
11
  export { mount } from './routing/mount.js';
12
12
  export { Router } from './routing/Router.js';
13
- export { Auth, register as authRegister, login as authLogin, buildLoginMessage, LOGIN_CONTEXT } from './auth.js';
13
+ export {
14
+ Auth,
15
+ register as authRegister,
16
+ login as authLogin,
17
+ buildLoginMessage,
18
+ LOGIN_CONTEXT,
19
+ } from './auth.js';
14
20
  export type { KdfParams, AuthOptions } from './auth.js';
15
21
  export { Link } from './navigation/Link.js';
16
22
  export type { LinkProps } from './navigation/Link.js';
@@ -36,7 +42,12 @@ export {
36
42
  useNavigationPending,
37
43
  } from './routing/hooks.js';
38
44
  export type { RouterInstance } from './routing/hooks.js';
39
- export { useLoaderData, revalidate, invalidateLoaderData, LoaderDataContext } from './routing/loader.js';
45
+ export {
46
+ useLoaderData,
47
+ revalidate,
48
+ invalidateLoaderData,
49
+ LoaderDataContext,
50
+ } from './routing/loader.js';
40
51
  export type {
41
52
  LoaderArgs,
42
53
  LoaderFunction,
@@ -1,4 +1,4 @@
1
- import { createElement, Suspense, useLayoutEffect, type ReactNode } from 'react';
1
+ import { createElement, type ReactNode, Suspense, useLayoutEffect } from 'react';
2
2
 
3
3
  import { ErrorBoundary } from './error-boundary.js';
4
4
  import { useLocation } from './hooks.js';
@@ -9,7 +9,7 @@ import {
9
9
  resolveLayout,
10
10
  resolveNotFound,
11
11
  } from './lazy.js';
12
- import { loaderKey, LoaderDataContext, readRouteData } from './loader.js';
12
+ import { LoaderDataContext, loaderKey, readRouteData } from './loader.js';
13
13
  import { matchRoute, type RouteParams } from './match.js';
14
14
  import { useRouteHead } from '../head/head.js';
15
15
  import { ParamsContext } from './params-context.js';
@@ -1,4 +1,4 @@
1
- import { Component, Suspense, type ComponentType, type ReactNode } from 'react';
1
+ import { Component, type ComponentType, type ReactNode, Suspense } from 'react';
2
2
 
3
3
  import type { RouteErrorProps } from '../types.js';
4
4
 
@@ -10,10 +10,10 @@
10
10
  * a number keeps data fresh for that many seconds; `false` caches until manual invalidation.
11
11
  * `revalidate()` / `router.refresh()` bust the cache to force a refetch.
12
12
  */
13
- import { createContext, useContext, type ComponentType } from 'react';
13
+ import { type ComponentType, createContext, useContext } from 'react';
14
14
 
15
15
  import type { HeadSpec } from '../head/head.js';
16
- import { resolveMetadata, type GenerateMetadata, type Metadata } from '../head/metadata.js';
16
+ import { type GenerateMetadata, type Metadata, resolveMetadata } from '../head/metadata.js';
17
17
  import { navigationEpoch, refresh as rerender } from '../navigation/navigation.js';
18
18
  import type { RouteDef } from '../types.js';
19
19
  import type { RouteParams } from './match.js';
@@ -1,11 +1,7 @@
1
1
  import { createRoot, hydrateRoot } from 'react-dom/client';
2
2
 
3
3
  import { DevToolbar } from '../dev/devtools.js';
4
- import {
5
- DevErrorBoundary,
6
- DevErrorOverlay,
7
- initDevErrorOverlay,
8
- } from '../dev/error-overlay.js';
4
+ import { DevErrorBoundary, DevErrorOverlay, initDevErrorOverlay } from '../dev/error-overlay.js';
9
5
  import { initNavigation } from '../navigation/navigation.js';
10
6
  import { startPrefetcher } from '../navigation/prefetch.js';
11
7
  import { hydrateLoaderData } from './loader.js';
@@ -73,7 +69,10 @@ export function mount(
73
69
  <>
74
70
  <DevErrorBoundary>{app}</DevErrorBoundary>
75
71
  <DevErrorOverlay />
76
- <DevToolbar routes={routes} slots={slots} />
72
+ <DevToolbar
73
+ routes={routes}
74
+ slots={slots}
75
+ />
77
76
  </>,
78
77
  );
79
78
  } else if (isSsrDocument()) {
@@ -346,7 +346,7 @@ export const TOIL_DOCS: Record<string, string> = {
346
346
  ' an `<Island>`. A route that cannot render this way is skipped at build (with a warning) and',
347
347
  ' simply falls back to normal client rendering.',
348
348
  '- Hole values are HTML-escaped exactly as React escapes them, so hydration is byte-for-byte',
349
- ' clean. Keep a repeat row\'s structure the same across items (only the leaf hole values vary).',
349
+ " clean. Keep a repeat row's structure the same across items (only the leaf hole values vary).",
350
350
  '- Build output for an SSR route lands in `build/client/_ssr/` (the template + its manifest)',
351
351
  ' alongside the generated `Slot` module; routes without `ssr = true` are unaffected.',
352
352
  ]),
@@ -13,7 +13,7 @@ import path from 'node:path';
13
13
  import type { ViteDevServer } from 'vite';
14
14
 
15
15
  import type { ResolvedToilConfig } from './config.js';
16
- import { renderEmailFile, toPascal, type RenderedEmail } from './emails.js';
16
+ import { type RenderedEmail, renderEmailFile, toPascal } from './emails.js';
17
17
 
18
18
  /** One discoverable email: its generated `Emails.<name>` and its absolute file. */
19
19
  export interface EmailListItem {
@@ -4,7 +4,7 @@ import path from 'node:path';
4
4
  import { type ResolvedToilConfig } from './config.js';
5
5
  import { writeDocs } from './docs.js';
6
6
  import { buildPageIndex, pagesModuleSource } from './pages.js';
7
- import { scanRoutes, type ScannedRoute } from './routes.js';
7
+ import { type ScannedRoute, scanRoutes } from './routes.js';
8
8
  import { llmsTxt, robotsTxt, sitemapXml } from './seo.js';
9
9
 
10
10
  /**
@@ -407,9 +407,7 @@ export function llmsTxt(
407
407
  const title = escapeMarkdownInline(page.title);
408
408
  const url = escapeMarkdownUrl(page.url);
409
409
  const desc =
410
- page.description !== undefined
411
- ? `: ${escapeMarkdownInline(page.description)}`
412
- : '';
410
+ page.description !== undefined ? `: ${escapeMarkdownInline(page.description)}` : '';
413
411
  out.push(`- [${title}](${url})${desc}`);
414
412
  }
415
413
  }
@@ -16,7 +16,7 @@ import { createServer } from 'vite';
16
16
  import { type ResolvedToilConfig } from './config.js';
17
17
  import { extractStaticMetadata, loadTypeScript } from './prerender.js';
18
18
  import { scanRoutes } from './routes.js';
19
- import { injectSeoHtml, joinUrl, llmsTxt, routeSeo, sitemapXml, type LlmsPage } from './seo.js';
19
+ import { injectSeoHtml, joinUrl, type LlmsPage, llmsTxt, routeSeo, sitemapXml } from './seo.js';
20
20
  import { createViteConfig } from './vite.js';
21
21
 
22
22
  /** Reads a string field off a metadata record, or undefined. */
@@ -91,7 +91,9 @@ export async function prerenderStaticParams(cfg: ResolvedToilConfig): Promise<st
91
91
  try {
92
92
  mod = (await server.ssrLoadModule(route.file)) as RouteModule;
93
93
  } catch (err) {
94
- warn(`skipped ${route.pattern} (${err instanceof Error ? err.message : String(err)})`);
94
+ warn(
95
+ `skipped ${route.pattern} (${err instanceof Error ? err.message : String(err)})`,
96
+ );
95
97
  continue;
96
98
  }
97
99
  if (typeof mod.generateStaticParams !== 'function') continue;
@@ -116,12 +118,16 @@ export async function prerenderStaticParams(cfg: ResolvedToilConfig): Promise<st
116
118
  typeof mod.loader === 'function'
117
119
  ? await mod.loader({ params, searchParams })
118
120
  : undefined;
119
- metadata = asMetadata(await mod.generateMetadata({ params, searchParams, data }));
121
+ metadata = asMetadata(
122
+ await mod.generateMetadata({ params, searchParams, data }),
123
+ );
120
124
  } else if (mod.metadata) {
121
125
  metadata = asMetadata(mod.metadata);
122
126
  }
123
127
  } catch (err) {
124
- warn(`metadata failed for ${url} (${err instanceof Error ? err.message : String(err)})`);
128
+ warn(
129
+ `metadata failed for ${url} (${err instanceof Error ? err.message : String(err)})`,
130
+ );
125
131
  }
126
132
  const html = injectSeoHtml(shell, routeSeo(cfg.seo, metadata, url));
127
133
  fs.mkdirSync(path.dirname(target), { recursive: true });
@@ -19,12 +19,7 @@
19
19
  import fs from 'node:fs';
20
20
  import path from 'node:path';
21
21
 
22
- import {
23
- createElement,
24
- type ComponentType,
25
- type Context,
26
- type ReactNode,
27
- } from 'react';
22
+ import { type ComponentType, type Context, createElement, type ReactNode } from 'react';
28
23
  import { renderToStaticMarkup } from 'react-dom/server';
29
24
  import { createServer } from 'vite';
30
25
 
@@ -36,8 +31,8 @@ import {
36
31
  assignSlotIds,
37
32
  coherenceHash,
38
33
  encodeSlots,
39
- extractFromHtml,
40
34
  type Extracted,
35
+ extractFromHtml,
41
36
  } from './template.js';
42
37
  import { createViteConfig } from './vite.js';
43
38
 
@@ -249,10 +249,7 @@ export function reactEscapeHtml(s: string): string {
249
249
  * any tooling that needs to materialise a full page from a template + values).
250
250
  * `values` maps a byte offset to the bytes inserted there (offsets may repeat
251
251
  * is not allowed; pass them in `slots` order). */
252
- export function spliceTemplate(
253
- tmpl: Buffer,
254
- inserts: { offset: number; value: Buffer }[],
255
- ): Buffer {
252
+ export function spliceTemplate(tmpl: Buffer, inserts: { offset: number; value: Buffer }[]): Buffer {
256
253
  const parts: Buffer[] = [];
257
254
  let prev = 0;
258
255
  for (const ins of inserts) {
@@ -7,7 +7,7 @@ import pc from 'picocolors';
7
7
  import react from '@vitejs/plugin-react';
8
8
  import { imagetools } from 'vite-imagetools';
9
9
  import { nodePolyfills } from 'vite-plugin-node-polyfills';
10
- import { createLogger, mergeConfig, type InlineConfig, type Logger, type PluginOption } from 'vite';
10
+ import { createLogger, type InlineConfig, type Logger, mergeConfig, type PluginOption } from 'vite';
11
11
 
12
12
  import { type ResolvedToilConfig } from './config.js';
13
13
  import { fontPreloadPlugin } from './fonts.js';
Binary file