@rivetjs/router 0.0.0-stage → 0.1.0-alpha.0

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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/adapters/assemble.d.ts +32 -0
  4. package/adapters/assemble.js +32 -0
  5. package/adapters/build.d.ts +24 -0
  6. package/adapters/build.js +43 -0
  7. package/adapters/bun.d.ts +18 -0
  8. package/adapters/bun.js +44 -0
  9. package/adapters/cloudflare.d.ts +5 -0
  10. package/adapters/cloudflare.js +8 -0
  11. package/adapters/cluster.d.ts +7 -0
  12. package/adapters/cluster.js +130 -0
  13. package/adapters/csr.d.ts +12 -0
  14. package/adapters/csr.js +11 -0
  15. package/adapters/deno.d.ts +13 -0
  16. package/adapters/deno.js +35 -0
  17. package/adapters/fetch.d.ts +55 -0
  18. package/adapters/fetch.js +72 -0
  19. package/adapters/files.d.ts +7 -0
  20. package/adapters/files.js +103 -0
  21. package/adapters/idle-memory.d.ts +23 -0
  22. package/adapters/idle-memory.js +91 -0
  23. package/adapters/netlify.d.ts +13 -0
  24. package/adapters/netlify.js +15 -0
  25. package/adapters/node.d.ts +163 -0
  26. package/adapters/node.js +940 -0
  27. package/adapters/pack.d.ts +39 -0
  28. package/adapters/pack.js +360 -0
  29. package/adapters/server-target.d.ts +17 -0
  30. package/adapters/server-target.js +8 -0
  31. package/adapters/static.d.ts +84 -0
  32. package/adapters/static.js +231 -0
  33. package/adapters/target-build.d.ts +92 -0
  34. package/adapters/target-build.js +118 -0
  35. package/adapters/vercel-edge.d.ts +7 -0
  36. package/adapters/vercel-edge.js +9 -0
  37. package/adapters/vercel.d.ts +33 -0
  38. package/adapters/vercel.js +45 -0
  39. package/build/codegen.d.ts +84 -0
  40. package/build/codegen.js +920 -0
  41. package/build/dev-errors.d.ts +19 -0
  42. package/build/dev-errors.js +236 -0
  43. package/build/migrate.d.ts +15 -0
  44. package/build/migrate.js +146 -0
  45. package/build/route-css.d.ts +54 -0
  46. package/build/route-css.js +216 -0
  47. package/build/routes.d.ts +50 -0
  48. package/build/routes.js +202 -0
  49. package/build/sync.d.ts +20 -0
  50. package/build/sync.js +16 -0
  51. package/build/vite.d.ts +195 -0
  52. package/build/vite.js +703 -0
  53. package/cli/rivet.d.ts +2 -0
  54. package/cli/rivet.js +100 -0
  55. package/client/active.d.ts +6 -0
  56. package/client/active.js +22 -0
  57. package/client/announce.d.ts +2 -0
  58. package/client/announce.js +21 -0
  59. package/client/dev.d.ts +41 -0
  60. package/client/dev.js +74 -0
  61. package/client/index.d.ts +152 -0
  62. package/client/index.js +680 -0
  63. package/client/layouts.d.ts +110 -0
  64. package/client/layouts.js +310 -0
  65. package/client/leave.d.ts +40 -0
  66. package/client/leave.js +75 -0
  67. package/client/link.d.ts +48 -0
  68. package/client/link.jsx +65 -0
  69. package/client/live.d.ts +57 -0
  70. package/client/live.js +170 -0
  71. package/client/navigate.d.ts +71 -0
  72. package/client/navigate.js +120 -0
  73. package/client/navigation.d.ts +28 -0
  74. package/client/navigation.js +14 -0
  75. package/client/params.d.ts +16 -0
  76. package/client/params.js +28 -0
  77. package/client/route-context.d.ts +32 -0
  78. package/client/route-context.js +21 -0
  79. package/client/scroll.d.ts +16 -0
  80. package/client/scroll.js +80 -0
  81. package/client/search.d.ts +8 -0
  82. package/client/search.js +17 -0
  83. package/client/tailwind.css +8 -0
  84. package/client/transition-helpers.d.ts +28 -0
  85. package/client/transition-helpers.js +63 -0
  86. package/client/transitions.css +90 -0
  87. package/client/transitions.d.ts +21 -0
  88. package/client/transitions.js +156 -0
  89. package/index.d.ts +138 -0
  90. package/index.js +7 -0
  91. package/package.json +156 -4
  92. package/server/app.d.ts +169 -0
  93. package/server/app.js +302 -0
  94. package/server/body.d.ts +20 -0
  95. package/server/body.js +8 -0
  96. package/server/early-hints.d.ts +34 -0
  97. package/server/early-hints.js +63 -0
  98. package/server/handler.d.ts +196 -0
  99. package/server/handler.js +623 -0
  100. package/server/index.d.ts +9 -0
  101. package/server/index.js +6 -0
  102. package/server/inline-styles.d.ts +21 -0
  103. package/server/inline-styles.js +28 -0
  104. package/server/module.d.ts +14 -0
  105. package/server/module.js +78 -0
  106. package/server/render.d.ts +94 -0
  107. package/server/render.js +489 -0
  108. package/server/route-cache.d.ts +175 -0
  109. package/server/route-cache.js +742 -0
  110. package/server/security.d.ts +18 -0
  111. package/server/security.js +47 -0
  112. package/server/strict-csp.d.ts +7 -0
  113. package/server/strict-csp.js +18 -0
  114. package/server-only.d.ts +1 -0
  115. package/server-only.js +3 -0
  116. package/shared/actions.d.ts +10 -0
  117. package/shared/actions.js +18 -0
  118. package/shared/base.d.ts +8 -0
  119. package/shared/base.js +20 -0
  120. package/shared/cookie.d.ts +7 -0
  121. package/shared/cookie.js +32 -0
  122. package/shared/csp-directives.d.ts +9 -0
  123. package/shared/csp-directives.js +85 -0
  124. package/shared/csp-hash.d.ts +39 -0
  125. package/shared/csp-hash.js +121 -0
  126. package/shared/csp.d.ts +26 -0
  127. package/shared/csp.js +13 -0
  128. package/shared/data.d.ts +175 -0
  129. package/shared/data.js +22 -0
  130. package/shared/errors.d.ts +31 -0
  131. package/shared/errors.js +51 -0
  132. package/shared/head.d.ts +57 -0
  133. package/shared/head.js +242 -0
  134. package/shared/nonce.d.ts +2 -0
  135. package/shared/nonce.js +23 -0
  136. package/shared/prefetch-fallback.min.d.ts +1 -0
  137. package/shared/prefetch-fallback.min.js +2 -0
  138. package/shared/prefetch.d.ts +54 -0
  139. package/shared/prefetch.js +74 -0
  140. package/shared/redirect.d.ts +6 -0
  141. package/shared/redirect.js +25 -0
  142. package/shared/slash.d.ts +8 -0
  143. package/shared/slash.js +24 -0
@@ -0,0 +1,28 @@
1
+ // Per-page stylesheet inlining (`rivetRouter({ inlineStylesheets })`): which of a page's stylesheet URLs the shell
2
+ // writes as `<style>` (`DocumentInput.inlineStyles`), from the client build's `.vite/rivet-inline-css.json`.
3
+ /**
4
+ * The subset of `styles` (URL → CSS) a page writes inline. `auto`: every listed sheet when their brotli total is at
5
+ * most `maxTotalBrotli` (one render-blocking round trip less: all of the page's sheets arrive with the HTML), else
6
+ * each listed sheet of at most `limit` raw bytes. Results are cached per stylesheet list (bounded by the routes).
7
+ */
8
+ export function inlineStylesFor(manifest) {
9
+ const cache = new Map();
10
+ const { sheets } = manifest;
11
+ return (styles) => {
12
+ const key = styles.join("\n");
13
+ if (cache.has(key))
14
+ return cache.get(key);
15
+ const listed = styles.filter((href) => Object.hasOwn(sheets, href));
16
+ let total = 0;
17
+ for (const href of listed)
18
+ total += sheets[href].br;
19
+ const all = manifest.mode === "always" || total <= manifest.maxTotalBrotli;
20
+ const out = {};
21
+ for (const href of listed)
22
+ if (all || sheets[href].bytes <= manifest.limit)
23
+ out[href] = sheets[href].css;
24
+ const result = Object.keys(out).length ? out : undefined;
25
+ cache.set(key, result);
26
+ return result;
27
+ };
28
+ }
@@ -0,0 +1,14 @@
1
+ import type { ServerModule } from "./handler.js";
2
+ /**
3
+ * Normalize one module's exports. `legacy`: a sibling `*.server.ts` (old names accepted; a module
4
+ * exporting both `load` and `serverLoad` is an error). In-file (page/layout) modules use the new names
5
+ * only: their `load`/`guard`… are ordinary exports.
6
+ */
7
+ export declare function serverExports(module: Record<string, unknown> | undefined, legacy: boolean, file?: string): ServerModule;
8
+ /** Merge a route module's in-file server exports with its sibling `*.server.ts`. */
9
+ export declare function mergeServer(inline: Record<string, unknown>, sibling: Record<string, unknown>, files?: readonly string[]): ServerModule;
10
+ /**
11
+ * Load and normalize a route table entry's server module. Generated loaders return in-file and merged
12
+ * modules normalized, and sibling `*.server.ts` modules raw (old names accepted).
13
+ */
14
+ export declare function loadServer(load: (() => Promise<unknown>) | undefined): Promise<ServerModule | undefined>;
@@ -0,0 +1,78 @@
1
+ /** In-file name → `ServerModule` key. */
2
+ const RENAMED = {
3
+ serverLoad: "load",
4
+ serverGuard: "guard",
5
+ serverActions: "actions",
6
+ serverEntries: "entries",
7
+ serverHeaders: "headers",
8
+ };
9
+ const KEPT = ["prerender", "csrf", "onRequest", "onGet", "onPost", "onPut", "onPatch", "onDelete", "onOptions"];
10
+ /** Sibling-only names (migration; `rivet migrate server-exports` renames them). */
11
+ const LEGACY = ["load", "guard", "actions", "entries", "headers", "GET", "POST", "PUT", "PATCH", "DELETE"];
12
+ const cache = new WeakMap();
13
+ const normalized = new WeakSet();
14
+ /**
15
+ * Normalize one module's exports. `legacy`: a sibling `*.server.ts` (old names accepted; a module
16
+ * exporting both `load` and `serverLoad` is an error). In-file (page/layout) modules use the new names
17
+ * only: their `load`/`guard`… are ordinary exports.
18
+ */
19
+ export function serverExports(module, legacy, file = "route module") {
20
+ if (!module)
21
+ return {};
22
+ const cached = cache.get(module);
23
+ if (cached)
24
+ return cached;
25
+ const out = {};
26
+ for (const [name, key] of Object.entries(RENAMED)) {
27
+ if (module[name] === undefined)
28
+ continue;
29
+ if (legacy && module[key] !== undefined)
30
+ throw new Error(`${file}: exports both \`${key}\` and \`${name}\`; keep \`${name}\``);
31
+ out[key] = module[name];
32
+ }
33
+ for (const name of KEPT)
34
+ if (module[name] !== undefined)
35
+ out[name] = module[name];
36
+ if (legacy)
37
+ for (const name of LEGACY)
38
+ if (module[name] !== undefined && out[name] === undefined)
39
+ out[name] = module[name];
40
+ const result = out;
41
+ cache.set(module, result);
42
+ normalized.add(result);
43
+ return result;
44
+ }
45
+ /**
46
+ * Merge a page/layout module's in-file server exports with its sibling `*.server.ts` (generated
47
+ * loaders call this for routes that have both). One export defined in both is an error.
48
+ */
49
+ const merges = new WeakMap();
50
+ /** Merge a route module's in-file server exports with its sibling `*.server.ts`. */
51
+ export function mergeServer(inline, sibling, files = ["page", "sibling"]) {
52
+ // Per (inline, sibling) module pair: a hot edit brings new module objects, hence a new merge.
53
+ const cached = merges.get(inline)?.get(sibling);
54
+ if (cached)
55
+ return cached;
56
+ const a = serverExports(inline, false, files[0]);
57
+ const b = serverExports(sibling, true, files[1]);
58
+ for (const key of Object.keys(b))
59
+ if (key in a)
60
+ throw new Error(`${files[0]} and ${files[1]} both define the route's \`${key}\`; keep one`);
61
+ const merged = { ...b, ...a };
62
+ normalized.add(merged);
63
+ let bySibling = merges.get(inline);
64
+ if (!bySibling)
65
+ merges.set(inline, (bySibling = new WeakMap()));
66
+ bySibling.set(sibling, merged);
67
+ return merged;
68
+ }
69
+ /**
70
+ * Load and normalize a route table entry's server module. Generated loaders return in-file and merged
71
+ * modules normalized, and sibling `*.server.ts` modules raw (old names accepted).
72
+ */
73
+ export async function loadServer(load) {
74
+ const module = (await load?.());
75
+ if (!module)
76
+ return undefined;
77
+ return normalized.has(module) ? module : serverExports(module, true, "server module");
78
+ }
@@ -0,0 +1,94 @@
1
+ import { type ServerValue } from "@rivetjs/runtime/server";
2
+ import { type ResumeManifest } from "@rivetjs/runtime/server-resume";
3
+ import type { Head } from "../shared/data.js";
4
+ import type { HeadManaged } from "../shared/head.js";
5
+ export { headTags, htmlAttributes, bodyAttributes, type HeadTagOptions, type HeadManaged } from "../shared/head.js";
6
+ /** Document around the app. `start` ends inside the app container; `end` closes it. */
7
+ export interface DocumentParts {
8
+ start: string;
9
+ end: string;
10
+ }
11
+ /** What a document shell receives: head, nonce, URL, status and stylesheets. */
12
+ export interface DocumentInput {
13
+ readonly head: Head | undefined;
14
+ readonly nonce: string | undefined;
15
+ readonly url: URL;
16
+ readonly status: number;
17
+ /** Stylesheet URLs to link (Vite manifest CSS in production, source paths in dev): global, then the route's. */
18
+ readonly styles: readonly string[];
19
+ /** Stylesheets of `styles` written as `<style>` (URL → CSS; `rivetRouter({ inlineStylesheets })`): `headTags` reads it. */
20
+ readonly inlineStyles?: Readonly<Record<string, string>>;
21
+ /** Request locale (i18n `locals.locale`); shells write `<html lang dir>` from it. */
22
+ readonly locale?: string;
23
+ readonly dir?: "ltr" | "rtl";
24
+ /** Head tags are client-managed (`@rivetjs/kit`): shells pass the input to `headTags(head, input)`. */
25
+ readonly managed?: HeadManaged;
26
+ }
27
+ /** Renders the HTML document around a page. */
28
+ export type DocumentShell = (input: DocumentInput) => DocumentParts;
29
+ /** Options of `renderPage()`. */
30
+ export interface RenderPageOptions {
31
+ /** Resume manifest (production client build). Without it the page renders without resumability. */
32
+ manifest?: ResumeManifest;
33
+ document: DocumentShell;
34
+ /** Out-of-order streaming for pending `Async` boundaries; `deadline` ms hands the rest to the browser. */
35
+ stream?: {
36
+ deadline?: number;
37
+ };
38
+ /**
39
+ * Preload planner (`renderResumable` `preload`): `background` byte budget of idle-time visible prefetch; `lean`: nothing
40
+ * before an interaction; `ahead`: bridge D-lean pages keep the runtime fetch-ahead.
41
+ */
42
+ preload?: {
43
+ background?: number;
44
+ lean?: boolean;
45
+ ahead?: boolean;
46
+ };
47
+ signal?: AbortSignal;
48
+ nonce?: string;
49
+ /**
50
+ * Failures after the response started (status already sent): this reports; a returned digest goes
51
+ * into the failure marker. The document then ends cleanly: a nonce'd script dispatching
52
+ * `rivet:resume-error` (`detail: { phase: "render", digest, error }`) and the shell's `end`.
53
+ */
54
+ onError?: (error: unknown) => string | void;
55
+ /** Markup written right before and after the app (dev: client mount container, data, scripts). */
56
+ around?: {
57
+ start: string;
58
+ end: string;
59
+ };
60
+ /** Locale variant index of translated templates (i18n; default 0). */
61
+ variant?: number;
62
+ /**
63
+ * Head hold (`@rivetjs/kit` components): app output is buffered until the shell has rendered, then
64
+ * the document starts with `head()` (route exports merged with what components pushed).
65
+ */
66
+ hold?: {
67
+ head(): Head | undefined;
68
+ };
69
+ /**
70
+ * Dev check (`AppConfig.devResume` mode `"check"`): the recorder runs, so its errors surface, but the
71
+ * page's root state and loader are cut (the browser client-renders). Not with `stream`.
72
+ */
73
+ discardState?: boolean;
74
+ }
75
+ /** Mid-stream failure marker: tells the page (and monitoring) the document is incomplete. */
76
+ export declare function failureMarker(nonce: string | undefined, digest: string | undefined): string;
77
+ /**
78
+ * Render `factory` between the document parts as a streamed UTF-8 body. Writes respect the
79
+ * consumer's pace: the renderer waits while the stream's queue is full. Always a `Response`: a
80
+ * failure before any byte left errors the body (`renderDocument` rejects instead).
81
+ */
82
+ export declare function renderPage(factory: () => ServerValue, input: DocumentInput, options: RenderPageOptions, init: {
83
+ status: number;
84
+ headers: Headers;
85
+ }): Response;
86
+ /**
87
+ * `renderPage`, but the `Response` is created once the first body bytes are ready (or the render
88
+ * ended): a failure before that throws / rejects, so the caller can answer with an error page and
89
+ * status instead of a 200 with a broken body. A synchronous page answers synchronously.
90
+ */
91
+ export declare function renderDocument(factory: () => ServerValue, input: DocumentInput, options: RenderPageOptions, init: {
92
+ status: number;
93
+ headers: Headers;
94
+ }): Response | Promise<Response>;