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.
- package/CHANGELOG.md +10 -0
- package/README.md +16 -7
- package/TYPESCRIPT_LAW.md +1946 -2073
- package/build/backend/.tsbuildinfo +1 -1
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/index.js +2375 -258
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/dev/devtools.js +1 -1
- package/build/client/dev/error-overlay.js +1 -1
- package/build/client/routing/mount.js +1 -1
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/auth-emails.js +7 -3
- package/build/compiler/emails.js +1 -1
- package/build/compiler/index.d.ts +1 -0
- package/build/compiler/index.js +25 -4
- package/build/compiler/pages.js +2 -3
- package/build/compiler/prerender.d.ts +3 -8
- package/build/compiler/prerender.js +88 -127
- package/build/compiler/ssg.js +3 -4
- package/build/compiler/template-build.js +3 -4
- package/build/compiler/toil-docs.generated.js +6 -5
- package/build/compiler/vite.js +3 -6
- package/build/devserver/.tsbuildinfo +1 -1
- package/build/devserver/db/database.js +7 -3
- package/build/devserver/db/types.js +1 -1
- package/build/devserver/production.js +4 -3
- package/build/devserver/runtime/crypto.d.ts +1 -1
- package/build/io/.tsbuildinfo +1 -1
- package/build/logger/.tsbuildinfo +1 -1
- package/build/shared/.tsbuildinfo +1 -1
- package/examples/basic/client/routes/analytics.tsx +7 -5
- package/examples/basic/server/tsconfig.json +1 -3
- package/package.json +45 -44
- package/presets/no-uint8array-tostring.js +120 -153
- package/presets/oxlint.d.ts +5 -0
- package/presets/oxlint.js +224 -0
- package/server/runtime/tsconfig.json +1 -3
- package/tsconfig.json +2 -11
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -43
- package/.github/changelog-config.json +0 -45
- package/.github/dependabot.yml +0 -27
- package/.github/workflows/ci.yml +0 -222
- package/.vscode/settings.json +0 -10
- package/docs/README.md +0 -107
- package/docs/auth/README.md +0 -104
- package/docs/auth/configuration.md +0 -105
- package/docs/auth/emails.md +0 -92
- package/docs/auth/extending.md +0 -202
- package/docs/auth/how-it-works.md +0 -138
- package/docs/auth/usage.md +0 -188
- package/docs/backend/README.md +0 -143
- package/docs/backend/data.md +0 -351
- package/docs/backend/rest.md +0 -402
- package/docs/backend/rpc.md +0 -226
- package/docs/background/README.md +0 -114
- package/docs/background/daemons.md +0 -276
- package/docs/background/derive.md +0 -179
- package/docs/cli/README.md +0 -379
- package/docs/concepts/ai-guide.md +0 -132
- package/docs/concepts/config.md +0 -416
- package/docs/concepts/decorators.md +0 -127
- package/docs/concepts/security.md +0 -108
- package/docs/concepts/tiers.md +0 -166
- package/docs/concepts/types.md +0 -216
- package/docs/database/README.md +0 -143
- package/docs/database/capacity.md +0 -350
- package/docs/database/counters.md +0 -174
- package/docs/database/documents.md +0 -277
- package/docs/database/events.md +0 -307
- package/docs/database/membership.md +0 -246
- package/docs/database/setup.md +0 -155
- package/docs/database/unique.md +0 -216
- package/docs/database/views.md +0 -246
- package/docs/frontend/README.md +0 -104
- package/docs/frontend/components.md +0 -286
- package/docs/frontend/data-fetching.md +0 -260
- package/docs/frontend/images.md +0 -148
- package/docs/frontend/metadata.md +0 -344
- package/docs/frontend/navigation.md +0 -296
- package/docs/frontend/rendering.md +0 -236
- package/docs/frontend/routing.md +0 -346
- package/docs/frontend/scripts.md +0 -118
- package/docs/frontend/search.md +0 -191
- package/docs/frontend/styling.md +0 -147
- package/docs/frontend/toil-global.md +0 -216
- package/docs/getting-started/README.md +0 -81
- package/docs/getting-started/create-project.md +0 -131
- package/docs/getting-started/deploy.md +0 -101
- package/docs/getting-started/first-app.md +0 -215
- package/docs/getting-started/installation.md +0 -124
- package/docs/getting-started/migrating.md +0 -125
- package/docs/getting-started/project-structure.md +0 -163
- package/docs/introduction/README.md +0 -66
- package/docs/introduction/design-principles.md +0 -81
- package/docs/introduction/distributed.md +0 -91
- package/docs/introduction/how-it-works.md +0 -121
- package/docs/introduction/hyperscale.md +0 -70
- package/docs/introduction/modern-stack.md +0 -85
- package/docs/introduction/vs-other-frameworks.md +0 -64
- package/docs/introduction/why-toil.md +0 -99
- package/docs/llms.txt +0 -95
- package/docs/realtime/README.md +0 -102
- package/docs/realtime/channels.md +0 -211
- package/docs/realtime/streams.md +0 -369
- package/docs/services/README.md +0 -60
- package/docs/services/analytics.md +0 -279
- package/docs/services/caching.md +0 -175
- package/docs/services/cookies.md +0 -235
- package/docs/services/crypto.md +0 -209
- package/docs/services/email.md +0 -289
- package/docs/services/environment.md +0 -141
- package/docs/services/ratelimit.md +0 -174
- package/docs/services/time.md +0 -85
- package/eslint.config.js +0 -57
- package/examples/basic/client/routes/docs/[...slug].tsx +0 -12
- package/presets/eslint.js +0 -88
- package/src/backend/index.ts +0 -204
- package/src/cli/configure.ts +0 -363
- package/src/cli/create.ts +0 -924
- package/src/cli/db.ts +0 -158
- package/src/cli/diagnostics.ts +0 -665
- package/src/cli/doctor.ts +0 -982
- package/src/cli/features.ts +0 -170
- package/src/cli/index.ts +0 -326
- package/src/cli/notify.ts +0 -120
- package/src/cli/proc.ts +0 -56
- package/src/cli/ui.ts +0 -169
- package/src/cli/update.ts +0 -248
- package/src/cli/updates.ts +0 -92
- package/src/cli/validate.ts +0 -31
- package/src/cli/version-check.ts +0 -125
- package/src/client/auth.ts +0 -869
- package/src/client/channel/channel.ts +0 -146
- package/src/client/components/Form.tsx +0 -65
- package/src/client/components/Image.tsx +0 -160
- package/src/client/components/Script.tsx +0 -113
- package/src/client/components/Slot.tsx +0 -21
- package/src/client/dev/devtools.tsx +0 -1089
- package/src/client/dev/error-overlay.tsx +0 -225
- package/src/client/errors.ts +0 -11
- package/src/client/head/head.ts +0 -182
- package/src/client/head/metadata.ts +0 -110
- package/src/client/index.ts +0 -130
- package/src/client/navigation/Link.tsx +0 -108
- package/src/client/navigation/NavLink.tsx +0 -86
- package/src/client/navigation/navigation.ts +0 -235
- package/src/client/navigation/prefetch.ts +0 -169
- package/src/client/navigation/scroll.ts +0 -53
- package/src/client/routing/Router.tsx +0 -216
- package/src/client/routing/action.ts +0 -122
- package/src/client/routing/error-boundary.tsx +0 -43
- package/src/client/routing/hooks.ts +0 -140
- package/src/client/routing/lazy.ts +0 -77
- package/src/client/routing/loader.ts +0 -381
- package/src/client/routing/match.ts +0 -47
- package/src/client/routing/mount.tsx +0 -90
- package/src/client/routing/params-context.ts +0 -10
- package/src/client/routing/slot-context.ts +0 -7
- package/src/client/rpc.ts +0 -97
- package/src/client/search/search.ts +0 -189
- package/src/client/search/use-page-search.ts +0 -73
- package/src/client/ssr/markers.tsx +0 -172
- package/src/client/stream/client.ts +0 -237
- package/src/client/types.ts +0 -73
- package/src/compiler/auth-emails.ts +0 -312
- package/src/compiler/config.ts +0 -369
- package/src/compiler/docs.ts +0 -127
- package/src/compiler/email-preview.ts +0 -314
- package/src/compiler/emails.ts +0 -404
- package/src/compiler/fonts.ts +0 -89
- package/src/compiler/generate.ts +0 -471
- package/src/compiler/image-blur.ts +0 -42
- package/src/compiler/image-report.ts +0 -88
- package/src/compiler/index.ts +0 -1362
- package/src/compiler/pages.ts +0 -49
- package/src/compiler/plugin.ts +0 -391
- package/src/compiler/prerender.ts +0 -263
- package/src/compiler/routes.ts +0 -170
- package/src/compiler/seo.ts +0 -415
- package/src/compiler/sri.ts +0 -144
- package/src/compiler/ssg.ts +0 -177
- package/src/compiler/ssr-codegen.ts +0 -85
- package/src/compiler/template-build.ts +0 -676
- package/src/compiler/template.ts +0 -262
- package/src/compiler/toil-docs.generated.ts +0 -77
- package/src/compiler/vite.ts +0 -245
- package/src/devserver/analytics/index.ts +0 -317
- package/src/devserver/config/dotenv.ts +0 -102
- package/src/devserver/config/env.ts +0 -30
- package/src/devserver/config/ratelimit.ts +0 -123
- package/src/devserver/daemon/catalog.ts +0 -120
- package/src/devserver/daemon/cron.ts +0 -87
- package/src/devserver/daemon/host.ts +0 -134
- package/src/devserver/daemon/index.ts +0 -369
- package/src/devserver/daemon/runtime.ts +0 -48
- package/src/devserver/db/catalog.ts +0 -109
- package/src/devserver/db/database.ts +0 -1834
- package/src/devserver/db/derives.ts +0 -121
- package/src/devserver/db/index.ts +0 -20
- package/src/devserver/db/routeKinds.ts +0 -191
- package/src/devserver/db/types.ts +0 -168
- package/src/devserver/email/caps.ts +0 -0
- package/src/devserver/email/config.ts +0 -141
- package/src/devserver/email/console.ts +0 -348
- package/src/devserver/email/index.ts +0 -155
- package/src/devserver/email/providers.ts +0 -131
- package/src/devserver/email/status.ts +0 -23
- package/src/devserver/email/validate.ts +0 -37
- package/src/devserver/email/wire.ts +0 -55
- package/src/devserver/http/cache.ts +0 -0
- package/src/devserver/http/envelope.ts +0 -157
- package/src/devserver/http/proxy.ts +0 -172
- package/src/devserver/http/runtime.ts +0 -387
- package/src/devserver/index.ts +0 -43
- package/src/devserver/production-ipc.ts +0 -63
- package/src/devserver/production-worker.ts +0 -83
- package/src/devserver/production.ts +0 -718
- package/src/devserver/runtime/crypto.ts +0 -587
- package/src/devserver/runtime/host.ts +0 -427
- package/src/devserver/runtime/module.ts +0 -442
- package/src/devserver/server.ts +0 -251
- package/src/devserver/ssr.ts +0 -208
- package/src/devserver/stream/catalog.ts +0 -106
- package/src/devserver/stream/host.ts +0 -42
- package/src/devserver/stream/index.ts +0 -301
- package/src/devserver/stream/manager.ts +0 -167
- package/src/devserver/stream/router.ts +0 -101
- package/src/devserver/stream/wire.ts +0 -58
- package/src/devserver/stream/ws.ts +0 -78
- package/src/devserver/wasm/sections.ts +0 -59
- package/src/devserver/wasm/surface.ts +0 -115
- package/src/io/FastMap.ts +0 -151
- package/src/io/FastSet.ts +0 -113
- package/src/io/codec.ts +0 -362
- package/src/io/index.ts +0 -10
- package/src/io/lengths.ts +0 -14
- package/src/io/types.ts +0 -19
- package/src/logger/index.ts +0 -22
- package/src/shared/index.ts +0 -46
- package/test/analytics-dev.test.ts +0 -113
- package/test/assembly/aspect-shim.ts +0 -33
- package/test/assembly/cookie.spec.ts +0 -303
- package/test/assembly/example.spec.ts +0 -22
- package/test/assembly/ssr.spec.ts +0 -95
- package/test/assembly.test.ts +0 -59
- package/test/auth-emails.test.ts +0 -118
- package/test/built-ssr.test.ts +0 -148
- package/test/channel.test.ts +0 -21
- package/test/config-host-port.test.ts +0 -59
- package/test/configure.test.ts +0 -94
- package/test/daemon-build.test.ts +0 -278
- package/test/daemon-catalog.test.ts +0 -349
- package/test/daemon-emulation.test.ts +0 -256
- package/test/db.test.ts +0 -0
- package/test/devserver-database.test.ts +0 -1102
- package/test/devserver-email.test.ts +0 -306
- package/test/devserver-pqauth.test.ts +0 -93
- package/test/devserver-secrets.test.ts +0 -63
- package/test/devserver.test.ts +0 -259
- package/test/doctor.test.ts +0 -298
- package/test/dom/Image.test.tsx +0 -144
- package/test/dom/Link.test.tsx +0 -67
- package/test/dom/NavLink.test.tsx +0 -37
- package/test/dom/Script.test.tsx +0 -48
- package/test/dom/action.test.tsx +0 -146
- package/test/dom/error-overlay.test.tsx +0 -44
- package/test/dom/loader.test.tsx +0 -121
- package/test/dom/navigation.test.ts +0 -59
- package/test/dom/revalidate.test.tsx +0 -38
- package/test/dom/route-head.test.tsx +0 -56
- package/test/dom/router-loading.test.tsx +0 -44
- package/test/dom/scroll.test.ts +0 -56
- package/test/dom/slot.test.tsx +0 -131
- package/test/dom/use-metadata.test.tsx +0 -58
- package/test/dom/view-transitions.test.tsx +0 -53
- package/test/dynamic-routing.test.ts +0 -132
- package/test/email-console.test.ts +0 -86
- package/test/email-preview.test.ts +0 -73
- package/test/emails.test.ts +0 -58
- package/test/errors.test.ts +0 -21
- package/test/example-guestbook.test.ts +0 -123
- package/test/features.test.ts +0 -149
- package/test/fixtures/bignum-wire/spec.ts +0 -25
- package/test/fixtures/daemon-app.ts +0 -65
- package/test/fixtures/stream-echo.ts +0 -26
- package/test/fixtures/stream-gate.ts +0 -28
- package/test/fixtures/stream-trap.ts +0 -18
- package/test/fixtures/stream-typed.ts +0 -41
- package/test/fonts.test.ts +0 -28
- package/test/global-setup.ts +0 -17
- package/test/head.test.ts +0 -42
- package/test/image-blur.test.ts +0 -50
- package/test/io.test.ts +0 -117
- package/test/metadata.test.ts +0 -40
- package/test/navlink.test.ts +0 -28
- package/test/pages.test.ts +0 -105
- package/test/placeholder.test.ts +0 -9
- package/test/pqauth-e2e.test.ts +0 -216
- package/test/pqauth-email.test.ts +0 -801
- package/test/prerender.test.ts +0 -116
- package/test/prettier-plugin.test.ts +0 -46
- package/test/routes.test.ts +0 -76
- package/test/rpc-bignum-wire.test.ts +0 -164
- package/test/rpc-dispatch.test.ts +0 -132
- package/test/rpc-kinds.test.ts +0 -18
- package/test/rpc.test.ts +0 -66
- package/test/search.test.ts +0 -114
- package/test/seo.test.ts +0 -175
- package/test/slot-layouts.test.ts +0 -69
- package/test/sri.test.ts +0 -129
- package/test/ssg.test.ts +0 -36
- package/test/ssr-hydration.test.tsx +0 -122
- package/test/ssr-render.test.ts +0 -197
- package/test/ssr-template.test.tsx +0 -482
- package/test/stream-emulation.test.ts +0 -479
- package/test/ui.test.ts +0 -40
- package/test/update.test.ts +0 -58
- package/test/validate.test.ts +0 -42
- package/test/version-check.test.ts +0 -130
- package/tests/data-parity/generated-parity.ts +0 -99
- package/tests/data-parity/parity.ts +0 -80
- package/tests/data-parity/spec.ts +0 -46
package/src/compiler/ssg.ts
DELETED
|
@@ -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
|
-
}
|