@rangojs/router 0.0.0-experimental.0f44aca1
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/AGENTS.md +5 -0
- package/README.md +899 -0
- package/dist/bin/rango.js +1601 -0
- package/dist/vite/index.js +5214 -0
- package/package.json +176 -0
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +262 -0
- package/skills/caching/SKILL.md +220 -0
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +112 -0
- package/skills/document-cache/SKILL.md +182 -0
- package/skills/fonts/SKILL.md +167 -0
- package/skills/hooks/SKILL.md +704 -0
- package/skills/host-router/SKILL.md +218 -0
- package/skills/intercept/SKILL.md +313 -0
- package/skills/layout/SKILL.md +310 -0
- package/skills/links/SKILL.md +239 -0
- package/skills/loader/SKILL.md +596 -0
- package/skills/middleware/SKILL.md +339 -0
- package/skills/mime-routes/SKILL.md +128 -0
- package/skills/parallel/SKILL.md +305 -0
- package/skills/prerender/SKILL.md +643 -0
- package/skills/rango/SKILL.md +118 -0
- package/skills/response-routes/SKILL.md +411 -0
- package/skills/route/SKILL.md +385 -0
- package/skills/router-setup/SKILL.md +439 -0
- package/skills/tailwind/SKILL.md +129 -0
- package/skills/theme/SKILL.md +79 -0
- package/skills/typesafety/SKILL.md +623 -0
- package/skills/use-cache/SKILL.md +324 -0
- package/src/__internal.ts +273 -0
- package/src/bin/rango.ts +321 -0
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/event-controller.ts +899 -0
- package/src/browser/history-state.ts +80 -0
- package/src/browser/index.ts +18 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +141 -0
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +134 -0
- package/src/browser/navigation-bridge.ts +645 -0
- package/src/browser/navigation-client.ts +215 -0
- package/src/browser/navigation-store.ts +806 -0
- package/src/browser/navigation-transaction.ts +295 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +550 -0
- package/src/browser/prefetch/cache.ts +146 -0
- package/src/browser/prefetch/fetch.ts +135 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +42 -0
- package/src/browser/prefetch/queue.ts +88 -0
- package/src/browser/rango-state.ts +112 -0
- package/src/browser/react/Link.tsx +360 -0
- package/src/browser/react/NavigationProvider.tsx +386 -0
- package/src/browser/react/ScrollRestoration.tsx +94 -0
- package/src/browser/react/context.ts +59 -0
- package/src/browser/react/filter-segment-order.ts +11 -0
- package/src/browser/react/index.ts +52 -0
- package/src/browser/react/location-state-shared.ts +162 -0
- package/src/browser/react/location-state.ts +107 -0
- package/src/browser/react/mount-context.ts +37 -0
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +218 -0
- package/src/browser/react/use-client-cache.ts +58 -0
- package/src/browser/react/use-handle.ts +162 -0
- package/src/browser/react/use-href.tsx +40 -0
- package/src/browser/react/use-link-status.ts +135 -0
- package/src/browser/react/use-mount.ts +31 -0
- package/src/browser/react/use-navigation.ts +99 -0
- package/src/browser/react/use-params.ts +65 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-router.ts +63 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +171 -0
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +431 -0
- package/src/browser/scroll-restoration.ts +400 -0
- package/src/browser/segment-reconciler.ts +216 -0
- package/src/browser/segment-structure-assert.ts +83 -0
- package/src/browser/server-action-bridge.ts +667 -0
- package/src/browser/shallow.ts +40 -0
- package/src/browser/types.ts +538 -0
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +438 -0
- package/src/build/generate-route-types.ts +36 -0
- package/src/build/index.ts +35 -0
- package/src/build/route-trie.ts +265 -0
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +411 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +469 -0
- package/src/build/route-types/scan-filter.ts +78 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +338 -0
- package/src/cache/cache-scope.ts +382 -0
- package/src/cache/cf/cf-cache-store.ts +540 -0
- package/src/cache/cf/index.ts +25 -0
- package/src/cache/document-cache.ts +369 -0
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +43 -0
- package/src/cache/memory-segment-store.ts +328 -0
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +98 -0
- package/src/cache/types.ts +342 -0
- package/src/client.rsc.tsx +85 -0
- package/src/client.tsx +601 -0
- package/src/component-utils.ts +76 -0
- package/src/components/DefaultDocument.tsx +27 -0
- package/src/context-var.ts +86 -0
- package/src/debug.ts +243 -0
- package/src/default-error-boundary.tsx +88 -0
- package/src/deps/browser.ts +8 -0
- package/src/deps/html-stream-client.ts +2 -0
- package/src/deps/html-stream-server.ts +2 -0
- package/src/deps/rsc.ts +10 -0
- package/src/deps/ssr.ts +2 -0
- package/src/errors.ts +365 -0
- package/src/handle.ts +135 -0
- package/src/handles/MetaTags.tsx +246 -0
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +7 -0
- package/src/handles/meta.ts +264 -0
- package/src/host/cookie-handler.ts +165 -0
- package/src/host/errors.ts +97 -0
- package/src/host/index.ts +53 -0
- package/src/host/pattern-matcher.ts +214 -0
- package/src/host/router.ts +352 -0
- package/src/host/testing.ts +79 -0
- package/src/host/types.ts +146 -0
- package/src/host/utils.ts +25 -0
- package/src/href-client.ts +222 -0
- package/src/index.rsc.ts +233 -0
- package/src/index.ts +277 -0
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +89 -0
- package/src/loader.ts +64 -0
- package/src/network-error-thrower.tsx +23 -0
- package/src/outlet-context.ts +15 -0
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +37 -0
- package/src/prerender/store.ts +185 -0
- package/src/prerender.ts +463 -0
- package/src/reverse.ts +330 -0
- package/src/root-error-boundary.tsx +289 -0
- package/src/route-content-wrapper.tsx +196 -0
- package/src/route-definition/dsl-helpers.ts +934 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +430 -0
- package/src/route-definition/index.ts +52 -0
- package/src/route-definition/redirect.ts +93 -0
- package/src/route-definition.ts +1 -0
- package/src/route-map-builder.ts +275 -0
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +259 -0
- package/src/router/content-negotiation.ts +116 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +287 -0
- package/src/router/find-match.ts +158 -0
- package/src/router/handler-context.ts +451 -0
- package/src/router/intercept-resolution.ts +395 -0
- package/src/router/lazy-includes.ts +234 -0
- package/src/router/loader-resolution.ts +420 -0
- package/src/router/logging.ts +248 -0
- package/src/router/manifest.ts +267 -0
- package/src/router/match-api.ts +620 -0
- package/src/router/match-context.ts +266 -0
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +223 -0
- package/src/router/match-middleware/cache-lookup.ts +634 -0
- package/src/router/match-middleware/cache-store.ts +295 -0
- package/src/router/match-middleware/index.ts +81 -0
- package/src/router/match-middleware/intercept-resolution.ts +306 -0
- package/src/router/match-middleware/segment-resolution.ts +192 -0
- package/src/router/match-pipelines.ts +179 -0
- package/src/router/match-result.ts +219 -0
- package/src/router/metrics.ts +282 -0
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +222 -0
- package/src/router/middleware.ts +748 -0
- package/src/router/pattern-matching.ts +563 -0
- package/src/router/prerender-match.ts +402 -0
- package/src/router/preview-match.ts +170 -0
- package/src/router/revalidation.ts +289 -0
- package/src/router/router-context.ts +316 -0
- package/src/router/router-interfaces.ts +452 -0
- package/src/router/router-options.ts +592 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +570 -0
- package/src/router/segment-resolution/helpers.ts +263 -0
- package/src/router/segment-resolution/loader-cache.ts +198 -0
- package/src/router/segment-resolution/revalidation.ts +1239 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -0
- package/src/router/segment-wrappers.ts +289 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +239 -0
- package/src/router/types.ts +170 -0
- package/src/router.ts +1002 -0
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +1089 -0
- package/src/rsc/helpers.ts +198 -0
- package/src/rsc/index.ts +36 -0
- package/src/rsc/loader-fetch.ts +209 -0
- package/src/rsc/manifest-init.ts +86 -0
- package/src/rsc/nonce.ts +32 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +379 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +347 -0
- package/src/rsc/rsc-rendering.ts +235 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +348 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +263 -0
- package/src/search-params.ts +230 -0
- package/src/segment-system.tsx +454 -0
- package/src/server/context.ts +591 -0
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +308 -0
- package/src/server/loader-registry.ts +133 -0
- package/src/server/request-context.ts +914 -0
- package/src/server/root-layout.tsx +10 -0
- package/src/server/tsconfig.json +14 -0
- package/src/server.ts +51 -0
- package/src/ssr/index.tsx +365 -0
- package/src/static-handler.ts +114 -0
- package/src/theme/ThemeProvider.tsx +297 -0
- package/src/theme/ThemeScript.tsx +61 -0
- package/src/theme/constants.ts +62 -0
- package/src/theme/index.ts +48 -0
- package/src/theme/theme-context.ts +44 -0
- package/src/theme/theme-script.ts +155 -0
- package/src/theme/types.ts +182 -0
- package/src/theme/use-theme.ts +44 -0
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +687 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +183 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +102 -0
- package/src/types/segments.ts +148 -0
- package/src/types.ts +1 -0
- package/src/urls/include-helper.ts +197 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +339 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +95 -0
- package/src/urls/response-types.ts +106 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -0
- package/src/use-loader.tsx +354 -0
- package/src/vite/discovery/bundle-postprocess.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +344 -0
- package/src/vite/discovery/prerender-collection.ts +385 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +47 -0
- package/src/vite/discovery/state.ts +110 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +16 -0
- package/src/vite/plugin-types.ts +131 -0
- package/src/vite/plugins/cjs-to-esm.ts +93 -0
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/client-ref-hashing.ts +105 -0
- package/src/vite/plugins/expose-action-id.ts +365 -0
- package/src/vite/plugins/expose-id-utils.ts +287 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +569 -0
- package/src/vite/plugins/refresh-cmd.ts +65 -0
- package/src/vite/plugins/use-cache-transform.ts +323 -0
- package/src/vite/plugins/version-injector.ts +83 -0
- package/src/vite/plugins/version-plugin.ts +254 -0
- package/src/vite/plugins/version.d.ts +12 -0
- package/src/vite/plugins/virtual-entries.ts +123 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +510 -0
- package/src/vite/router-discovery.ts +785 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/utils/package-resolution.ts +121 -0
- package/src/vite/utils/prerender-utils.ts +189 -0
- package/src/vite/utils/shared-utils.ts +169 -0
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
import type { ComponentType, ReactNode } from "react";
|
|
2
|
+
import type { SegmentCacheStore } from "../cache/types.js";
|
|
3
|
+
import type {
|
|
4
|
+
ErrorBoundaryHandler,
|
|
5
|
+
NotFoundBoundaryHandler,
|
|
6
|
+
OnErrorCallback,
|
|
7
|
+
} from "../types";
|
|
8
|
+
import type { NonceProvider } from "../rsc/types.js";
|
|
9
|
+
import type { ExecutionContext } from "../server/request-context.js";
|
|
10
|
+
import type { UrlPatterns } from "../urls.js";
|
|
11
|
+
import type { NamedRouteEntry } from "./content-negotiation.js";
|
|
12
|
+
import type { TelemetrySink } from "./telemetry.js";
|
|
13
|
+
import type { RouterTimeouts, OnTimeoutCallback } from "./timeout.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* SSR stream mode returned by resolveStreaming.
|
|
17
|
+
*
|
|
18
|
+
* - `"stream"` — start flushing HTML as soon as the shell is ready
|
|
19
|
+
* (default React SSR behavior via `renderToReadableStream`).
|
|
20
|
+
* - `"allReady"` — wait for every Suspense boundary to resolve before
|
|
21
|
+
* sending any bytes (equivalent to awaiting `stream.allReady`).
|
|
22
|
+
*/
|
|
23
|
+
export type SSRStreamMode = "stream" | "allReady";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Context passed to the resolveStreaming callback.
|
|
27
|
+
*/
|
|
28
|
+
export interface ResolveStreamingContext<TEnv = unknown> {
|
|
29
|
+
request: Request;
|
|
30
|
+
env: TEnv;
|
|
31
|
+
url: URL;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* SSR configuration options.
|
|
36
|
+
*/
|
|
37
|
+
export interface SSROptions<TEnv = unknown> {
|
|
38
|
+
/**
|
|
39
|
+
* Determine whether an HTML response should stream progressively or
|
|
40
|
+
* wait for full readiness before flushing.
|
|
41
|
+
*
|
|
42
|
+
* Called once per HTML request, before the HTML response is produced.
|
|
43
|
+
* Does NOT apply to RSC responses (`__rsc`, partial navigation, prefetch).
|
|
44
|
+
*
|
|
45
|
+
* Return `"stream"` (default) for progressive streaming or `"allReady"`
|
|
46
|
+
* to buffer the complete HTML before sending.
|
|
47
|
+
*
|
|
48
|
+
* @example Bot detection
|
|
49
|
+
* ```ts
|
|
50
|
+
* createRouter({
|
|
51
|
+
* ssr: {
|
|
52
|
+
* resolveStreaming: async ({ request, env }) => {
|
|
53
|
+
* const bot = await detectBot(request, env);
|
|
54
|
+
* return bot.isBot && !bot.supportsStreaming ? "allReady" : "stream";
|
|
55
|
+
* },
|
|
56
|
+
* },
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
resolveStreaming?: (
|
|
61
|
+
context: ResolveStreamingContext<TEnv>,
|
|
62
|
+
) => SSRStreamMode | Promise<SSRStreamMode>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Props passed to the root layout component
|
|
67
|
+
*/
|
|
68
|
+
export interface RootLayoutProps {
|
|
69
|
+
children: ReactNode;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Router configuration options
|
|
74
|
+
*/
|
|
75
|
+
export interface RSCRouterOptions<TEnv = any> {
|
|
76
|
+
/**
|
|
77
|
+
* Unique identifier for this router instance.
|
|
78
|
+
* Used to namespace static output files and route maps.
|
|
79
|
+
* Auto-generated if not provided.
|
|
80
|
+
*/
|
|
81
|
+
id?: string;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Injected by the Vite transform at compile time.
|
|
85
|
+
* Hash of filename + line number for stable cross-environment ID.
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
$$id?: string;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Injected by the Vite transform at compile time.
|
|
92
|
+
* Absolute path of the source file that defines this router,
|
|
93
|
+
* relative to project root. Eliminates runtime stack trace parsing.
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
$$sourceFile?: string;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Enable performance metrics collection
|
|
100
|
+
* When enabled, metrics are output to console and available via Server-Timing header
|
|
101
|
+
*/
|
|
102
|
+
debugPerformance?: boolean;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Allow the `?__debug_manifest` query parameter to return route manifest data as JSON.
|
|
106
|
+
* In development mode this is always enabled regardless of this setting.
|
|
107
|
+
* Defaults to false. Set to true to enable in production.
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
allowDebugManifest?: boolean;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Document component that wraps the entire application.
|
|
114
|
+
*
|
|
115
|
+
* This component provides the HTML structure for your app and wraps
|
|
116
|
+
* both normal route content AND error states, preventing the app shell
|
|
117
|
+
* from unmounting during errors (avoids FOUC).
|
|
118
|
+
*
|
|
119
|
+
* Must be a client component ("use client") that accepts { children }.
|
|
120
|
+
*
|
|
121
|
+
* If not provided, a default document with basic HTML structure is used:
|
|
122
|
+
* `<html><head><meta charset/viewport></head><body>{children}</body></html>`
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* // components/Document.tsx
|
|
127
|
+
* "use client";
|
|
128
|
+
* export function Document({ children }: { children: ReactNode }) {
|
|
129
|
+
* return (
|
|
130
|
+
* <html lang="en">
|
|
131
|
+
* <head>
|
|
132
|
+
* <link rel="stylesheet" href="/styles.css" />
|
|
133
|
+
* </head>
|
|
134
|
+
* <body>
|
|
135
|
+
* <nav>...</nav>
|
|
136
|
+
* {children}
|
|
137
|
+
* </body>
|
|
138
|
+
* </html>
|
|
139
|
+
* );
|
|
140
|
+
* }
|
|
141
|
+
*
|
|
142
|
+
* // router.tsx
|
|
143
|
+
* const router = createRouter<AppEnv>({
|
|
144
|
+
* document: Document,
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
document?: ComponentType<RootLayoutProps>;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Default error boundary fallback used when no error boundary is defined in the route tree
|
|
152
|
+
* If not provided, errors will propagate and crash the request
|
|
153
|
+
*/
|
|
154
|
+
defaultErrorBoundary?: ReactNode | ErrorBoundaryHandler;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Default not-found boundary fallback used when no notFoundBoundary is defined in the route tree
|
|
158
|
+
* If not provided, DataNotFoundError will be treated as a regular error
|
|
159
|
+
*/
|
|
160
|
+
defaultNotFoundBoundary?: ReactNode | NotFoundBoundaryHandler;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Component to render when no route matches the requested URL.
|
|
164
|
+
*
|
|
165
|
+
* This is rendered within your document/app shell with a 404 status code.
|
|
166
|
+
* Use this for a custom 404 page that maintains your app's look and feel.
|
|
167
|
+
*
|
|
168
|
+
* If not provided, a default "Page not found" component is rendered.
|
|
169
|
+
*
|
|
170
|
+
* Can be a static ReactNode or a function receiving the pathname.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* // Simple static component
|
|
175
|
+
* const router = createRouter<AppEnv>({
|
|
176
|
+
* document: Document,
|
|
177
|
+
* notFound: <NotFound404 />,
|
|
178
|
+
* });
|
|
179
|
+
*
|
|
180
|
+
* // Dynamic component with pathname
|
|
181
|
+
* const router = createRouter<AppEnv>({
|
|
182
|
+
* document: Document,
|
|
183
|
+
* notFound: ({ pathname }) => (
|
|
184
|
+
* <div>
|
|
185
|
+
* <h1>404 - Not Found</h1>
|
|
186
|
+
* <p>No page exists at {pathname}</p>
|
|
187
|
+
* <a href="/">Go home</a>
|
|
188
|
+
* </div>
|
|
189
|
+
* ),
|
|
190
|
+
* });
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
notFound?: ReactNode | ((props: { pathname: string }) => ReactNode);
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Callback invoked when an error occurs during request handling.
|
|
197
|
+
*
|
|
198
|
+
* This callback is for notification/logging purposes - it cannot modify
|
|
199
|
+
* the error handling flow. Use errorBoundary() in route definitions to
|
|
200
|
+
* customize error UI.
|
|
201
|
+
*
|
|
202
|
+
* The callback receives comprehensive context about the error including:
|
|
203
|
+
* - The error itself
|
|
204
|
+
* - Phase where it occurred (routing, middleware, loader, handler, etc.)
|
|
205
|
+
* - Request info (URL, method, params)
|
|
206
|
+
* - Route info (routeKey, segmentId)
|
|
207
|
+
* - Environment/bindings
|
|
208
|
+
* - Duration from request start
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```typescript
|
|
212
|
+
* const router = createRouter<AppEnv>({
|
|
213
|
+
* onError: (context) => {
|
|
214
|
+
* // Send to error tracking service
|
|
215
|
+
* Sentry.captureException(context.error, {
|
|
216
|
+
* tags: {
|
|
217
|
+
* phase: context.phase,
|
|
218
|
+
* route: context.routeKey,
|
|
219
|
+
* },
|
|
220
|
+
* extra: {
|
|
221
|
+
* url: context.url.toString(),
|
|
222
|
+
* params: context.params,
|
|
223
|
+
* duration: context.duration,
|
|
224
|
+
* },
|
|
225
|
+
* });
|
|
226
|
+
* },
|
|
227
|
+
* });
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
onError?: OnErrorCallback<TEnv>;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Cache store for segment caching.
|
|
234
|
+
*
|
|
235
|
+
* When provided, enables route-level caching via cache() boundaries.
|
|
236
|
+
* The store handles persistence (memory, KV, Redis, etc.).
|
|
237
|
+
*
|
|
238
|
+
* Can be a static config or a function receiving env for runtime bindings.
|
|
239
|
+
*
|
|
240
|
+
* @example Static config
|
|
241
|
+
* ```typescript
|
|
242
|
+
* import { MemorySegmentCacheStore } from "@rangojs/router/cache";
|
|
243
|
+
*
|
|
244
|
+
* const router = createRouter({
|
|
245
|
+
* cache: {
|
|
246
|
+
* store: new MemorySegmentCacheStore({ defaults: { ttl: 60 } }),
|
|
247
|
+
* },
|
|
248
|
+
* });
|
|
249
|
+
* ```
|
|
250
|
+
*
|
|
251
|
+
* @example Dynamic config with env (e.g., Cloudflare Workers with ExecutionContext)
|
|
252
|
+
* ```typescript
|
|
253
|
+
* const router = createRouter<AppBindings>({
|
|
254
|
+
* cache: (_env, ctx) => ({
|
|
255
|
+
* store: new CFCacheStore({
|
|
256
|
+
* defaults: { ttl: 60 },
|
|
257
|
+
* ctx: ctx!, // ExecutionContext for non-blocking writes
|
|
258
|
+
* }),
|
|
259
|
+
* }),
|
|
260
|
+
* });
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
cache?:
|
|
264
|
+
| { store: SegmentCacheStore; enabled?: boolean }
|
|
265
|
+
| ((
|
|
266
|
+
env: TEnv,
|
|
267
|
+
ctx?: ExecutionContext,
|
|
268
|
+
) => {
|
|
269
|
+
store: SegmentCacheStore;
|
|
270
|
+
enabled?: boolean;
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Named cache profiles for "use cache" directive.
|
|
275
|
+
* Profile names map to TTL/SWR configuration.
|
|
276
|
+
*
|
|
277
|
+
* - `"use cache"` (no name) resolves to the `default` profile.
|
|
278
|
+
* - `"use cache: short"` resolves to the `short` profile.
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript
|
|
282
|
+
* createRouter({
|
|
283
|
+
* cacheProfiles: {
|
|
284
|
+
* default: { ttl: 900, swr: 1800 },
|
|
285
|
+
* short: { ttl: 60, swr: 120 },
|
|
286
|
+
* long: { ttl: 3600, swr: 7200 },
|
|
287
|
+
* products: { ttl: 300, swr: 600, tags: ['products'] },
|
|
288
|
+
* },
|
|
289
|
+
* });
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
cacheProfiles?: Record<
|
|
293
|
+
string,
|
|
294
|
+
import("../cache/profile-registry.js").CacheProfile
|
|
295
|
+
>;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Theme configuration for automatic theme management.
|
|
299
|
+
*
|
|
300
|
+
* When provided, enables:
|
|
301
|
+
* - ctx.theme and ctx.setTheme() in route handlers
|
|
302
|
+
* - useTheme() hook for client components
|
|
303
|
+
* - FOUC prevention via inline script in MetaTags
|
|
304
|
+
* - Automatic ThemeProvider wrapping in NavigationProvider
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* const router = createRouter<AppEnv>({
|
|
309
|
+
* theme: {
|
|
310
|
+
* defaultTheme: "system",
|
|
311
|
+
* themes: ["light", "dark"],
|
|
312
|
+
* }
|
|
313
|
+
* });
|
|
314
|
+
*
|
|
315
|
+
* // In route handler:
|
|
316
|
+
* route("settings", (ctx) => {
|
|
317
|
+
* const theme = ctx.theme; // "light" | "dark" | "system"
|
|
318
|
+
* ctx.setTheme("dark"); // Sets cookie
|
|
319
|
+
* return <SettingsPage />;
|
|
320
|
+
* });
|
|
321
|
+
*
|
|
322
|
+
* // In client component:
|
|
323
|
+
* import { useTheme } from "@rangojs/router/theme";
|
|
324
|
+
*
|
|
325
|
+
* function ThemeToggle() {
|
|
326
|
+
* const { theme, setTheme, themes } = useTheme();
|
|
327
|
+
* return <select value={theme} onChange={e => setTheme(e.target.value)}>
|
|
328
|
+
* {themes.map(t => <option key={t}>{t}</option>)}
|
|
329
|
+
* </select>;
|
|
330
|
+
* }
|
|
331
|
+
* ```
|
|
332
|
+
*
|
|
333
|
+
* Use `theme: true` to enable with all defaults.
|
|
334
|
+
*/
|
|
335
|
+
theme?: import("../theme/types.js").ThemeConfig | true;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* URL patterns to register with the router.
|
|
339
|
+
*
|
|
340
|
+
* Alternative to calling `.routes()` method - allows passing patterns
|
|
341
|
+
* directly in the config for a more concise setup.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```typescript
|
|
345
|
+
* import { urls } from "@rangojs/router/server";
|
|
346
|
+
*
|
|
347
|
+
* const urlpatterns = urls(({ path, layout }) => [
|
|
348
|
+
* path("/", HomePage, { name: "home" }),
|
|
349
|
+
* path("/about", AboutPage, { name: "about" }),
|
|
350
|
+
* ]);
|
|
351
|
+
*
|
|
352
|
+
* const router = createRouter<AppEnv>({
|
|
353
|
+
* document: Document,
|
|
354
|
+
* urls: urlpatterns,
|
|
355
|
+
* });
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
urls?: UrlPatterns<TEnv, any>;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Injected by the Vite transform at compile time.
|
|
362
|
+
* Static import of NamedRoutes from the generated named-routes file.
|
|
363
|
+
* Used to seed reverse() with the full named route map.
|
|
364
|
+
* @internal
|
|
365
|
+
*/
|
|
366
|
+
$$routeNames?: Record<string, NamedRouteEntry>;
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Nonce provider for Content Security Policy (CSP).
|
|
370
|
+
*
|
|
371
|
+
* Can be:
|
|
372
|
+
* - A function that returns a nonce string
|
|
373
|
+
* - A function that returns `true` to auto-generate a nonce
|
|
374
|
+
* - Undefined to disable nonce (default)
|
|
375
|
+
*
|
|
376
|
+
* The nonce will be applied to inline scripts injected by the RSC payload.
|
|
377
|
+
* It's also available to middleware via the typed `nonce` token:
|
|
378
|
+
* `import { nonce } from "@rangojs/router"; ctx.get(nonce)`
|
|
379
|
+
*
|
|
380
|
+
* @example Auto-generate nonce
|
|
381
|
+
* ```tsx
|
|
382
|
+
* createRouter({
|
|
383
|
+
* nonce: () => true,
|
|
384
|
+
* });
|
|
385
|
+
* ```
|
|
386
|
+
*
|
|
387
|
+
* @example Custom nonce from request context
|
|
388
|
+
* ```tsx
|
|
389
|
+
* createRouter({
|
|
390
|
+
* nonce: (request, env) => env.nonce,
|
|
391
|
+
* });
|
|
392
|
+
* ```
|
|
393
|
+
*
|
|
394
|
+
* @example Access nonce in middleware
|
|
395
|
+
* ```tsx
|
|
396
|
+
* import { nonce } from "@rangojs/router";
|
|
397
|
+
*
|
|
398
|
+
* const cspMiddleware: Middleware = async (ctx, next) => {
|
|
399
|
+
* const value = ctx.get(nonce); // string | undefined
|
|
400
|
+
* await next();
|
|
401
|
+
* };
|
|
402
|
+
* ```
|
|
403
|
+
*/
|
|
404
|
+
nonce?: NonceProvider<TEnv>;
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* RSC version string included in metadata.
|
|
408
|
+
* The browser sends this back on partial requests to detect version mismatches.
|
|
409
|
+
*
|
|
410
|
+
* Defaults to the auto-generated VERSION from `@rangojs/router:version` virtual module.
|
|
411
|
+
* Only set this if you need a custom versioning strategy.
|
|
412
|
+
*
|
|
413
|
+
* @default VERSION from @rangojs/router:version
|
|
414
|
+
*/
|
|
415
|
+
version?: string;
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* TTL (in seconds) for the in-memory prefetch cache and the
|
|
419
|
+
* Cache-Control header on prefetch responses.
|
|
420
|
+
*
|
|
421
|
+
* Controls how long prefetch responses are kept in the client-side
|
|
422
|
+
* in-memory cache and sets `Cache-Control: private, max-age=<ttl>`
|
|
423
|
+
* on server responses for CDN/edge caching.
|
|
424
|
+
*
|
|
425
|
+
* The cache is automatically invalidated on server actions regardless
|
|
426
|
+
* of TTL, so this is primarily a staleness safety net.
|
|
427
|
+
*
|
|
428
|
+
* Set to `false` to disable prefetch caching entirely.
|
|
429
|
+
*
|
|
430
|
+
* @default 300 (5 minutes)
|
|
431
|
+
*/
|
|
432
|
+
prefetchCacheTTL?: number | false;
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Enable connection warmup to keep TCP+TLS alive after idle periods.
|
|
436
|
+
*
|
|
437
|
+
* When enabled, the client sends a HEAD request after the user returns
|
|
438
|
+
* from an idle period (60s+), prewarming the TLS connection before
|
|
439
|
+
* the next navigation.
|
|
440
|
+
*
|
|
441
|
+
* @default true
|
|
442
|
+
*/
|
|
443
|
+
warmup?: boolean;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Shorthand timeout (ms) applied to both action execution and render start.
|
|
447
|
+
* Does NOT apply to streamIdleMs.
|
|
448
|
+
* Overridden by individual values in `timeouts`.
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```typescript
|
|
452
|
+
* createRouter({ timeout: 10_000 });
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
timeout?: number;
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Structured timeout configuration per phase.
|
|
459
|
+
* Values here override the `timeout` shorthand.
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* ```typescript
|
|
463
|
+
* createRouter({
|
|
464
|
+
* timeouts: {
|
|
465
|
+
* actionMs: 10_000,
|
|
466
|
+
* renderStartMs: 8_000,
|
|
467
|
+
* },
|
|
468
|
+
* });
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
timeouts?: RouterTimeouts;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Custom handler invoked when a timeout occurs.
|
|
475
|
+
* Receives context about which phase timed out and must return a Response.
|
|
476
|
+
* If not provided, returns a plain 504 with "Request timed out" body
|
|
477
|
+
* and X-Rango-Timeout-Phase header.
|
|
478
|
+
*
|
|
479
|
+
* If the callback throws, the default 504 response is used as fallback.
|
|
480
|
+
*
|
|
481
|
+
* @example
|
|
482
|
+
* ```typescript
|
|
483
|
+
* createRouter({
|
|
484
|
+
* timeout: 10_000,
|
|
485
|
+
* onTimeout: (ctx) => {
|
|
486
|
+
* return new Response(
|
|
487
|
+
* JSON.stringify({ error: "timeout", phase: ctx.phase }),
|
|
488
|
+
* { status: 504, headers: { "Content-Type": "application/json" } },
|
|
489
|
+
* );
|
|
490
|
+
* },
|
|
491
|
+
* });
|
|
492
|
+
* ```
|
|
493
|
+
*/
|
|
494
|
+
onTimeout?: OnTimeoutCallback<TEnv>;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Telemetry sink for structured lifecycle events.
|
|
498
|
+
*
|
|
499
|
+
* When provided, the router emits events for request start/end,
|
|
500
|
+
* loader start/end/error, handler errors, cache decisions, and
|
|
501
|
+
* revalidation decisions.
|
|
502
|
+
*
|
|
503
|
+
* No-op when not configured (zero overhead).
|
|
504
|
+
*
|
|
505
|
+
* @example Console logging
|
|
506
|
+
* ```typescript
|
|
507
|
+
* import { createConsoleSink } from "@rangojs/router";
|
|
508
|
+
*
|
|
509
|
+
* const router = createRouter({
|
|
510
|
+
* telemetry: createConsoleSink(),
|
|
511
|
+
* });
|
|
512
|
+
* ```
|
|
513
|
+
*
|
|
514
|
+
* @example Custom sink
|
|
515
|
+
* ```typescript
|
|
516
|
+
* const router = createRouter({
|
|
517
|
+
* telemetry: {
|
|
518
|
+
* emit(event) {
|
|
519
|
+
* myTracer.record(event);
|
|
520
|
+
* },
|
|
521
|
+
* },
|
|
522
|
+
* });
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
telemetry?: TelemetrySink;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* SSR configuration options.
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* ```typescript
|
|
532
|
+
* createRouter({
|
|
533
|
+
* ssr: {
|
|
534
|
+
* resolveStreaming: async ({ request, env }) => {
|
|
535
|
+
* const bot = await detectBot(request, env);
|
|
536
|
+
* return bot.isBot ? "allReady" : "stream";
|
|
537
|
+
* },
|
|
538
|
+
* },
|
|
539
|
+
* });
|
|
540
|
+
* ```
|
|
541
|
+
*/
|
|
542
|
+
ssr?: SSROptions<TEnv>;
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Cross-origin request protection for server actions, loader fetches,
|
|
546
|
+
* and progressive enhancement form submissions.
|
|
547
|
+
*
|
|
548
|
+
* When enabled, the router validates that the request's Origin header
|
|
549
|
+
* (or Referer fallback) matches the Host before executing actions,
|
|
550
|
+
* loaders, or PE submissions. Requests without Origin/Referer are
|
|
551
|
+
* allowed (same-origin navigations, non-browser clients).
|
|
552
|
+
*
|
|
553
|
+
* The built-in check compares Origin against the Host header and
|
|
554
|
+
* url.protocol. It does NOT trust X-Forwarded-Host/Proto headers
|
|
555
|
+
* (they are client-controllable without a trusted proxy). On standard
|
|
556
|
+
* deployments (Cloudflare Workers, Node behind nginx/caddy) the Host
|
|
557
|
+
* header is already set to the public-facing host by the platform or
|
|
558
|
+
* proxy. For non-standard proxy setups where Host differs from the
|
|
559
|
+
* public origin, use a custom function that reads the appropriate
|
|
560
|
+
* forwarded headers from your trusted proxy.
|
|
561
|
+
*
|
|
562
|
+
* - `true` (default) -- enable built-in origin validation
|
|
563
|
+
* - `false` -- disable
|
|
564
|
+
* - function -- full custom control with access to env, phase,
|
|
565
|
+
* and the built-in check via `ctx.defaultCheck()`
|
|
566
|
+
*
|
|
567
|
+
* The callback receives `OriginCheckContext` with `request`, `url`,
|
|
568
|
+
* `env`, `routerId`, `phase` ("action" | "loader" | "pe-form"),
|
|
569
|
+
* and `defaultCheck()`. Return `true` to allow, `false` for default
|
|
570
|
+
* 403 rejection, or a `Response` for custom rejection.
|
|
571
|
+
*
|
|
572
|
+
* @default true
|
|
573
|
+
*
|
|
574
|
+
* @example Trusted proxy with X-Forwarded-Host
|
|
575
|
+
* ```ts
|
|
576
|
+
* createRouter({
|
|
577
|
+
* originCheck({ request, url, env, defaultCheck }) {
|
|
578
|
+
* if (env.TRUST_PROXY) {
|
|
579
|
+
* const origin = request.headers.get("origin");
|
|
580
|
+
* if (!origin) return true;
|
|
581
|
+
* if (origin === "null") return false;
|
|
582
|
+
* const host = request.headers.get("x-forwarded-host")
|
|
583
|
+
* ?? request.headers.get("host") ?? url.host;
|
|
584
|
+
* return origin.toLowerCase() === `${url.protocol}//${host}`.toLowerCase();
|
|
585
|
+
* }
|
|
586
|
+
* return defaultCheck();
|
|
587
|
+
* },
|
|
588
|
+
* });
|
|
589
|
+
* ```
|
|
590
|
+
*/
|
|
591
|
+
originCheck?: import("../rsc/origin-guard.js").OriginCheckConfig<TEnv>;
|
|
592
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RSCRouterInternal } from "./router-interfaces.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Brand marker for identifying router instances at build time.
|
|
5
|
+
* Used by the Vite plugin to auto-discover routers from module exports.
|
|
6
|
+
*/
|
|
7
|
+
export const RSC_ROUTER_BRAND = "__rsc_router__" as const;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Global registry of all router instances created via createRouter().
|
|
11
|
+
* Each router is keyed by its id (auto-generated or user-provided).
|
|
12
|
+
* Used by the Vite plugin at build time to discover routers and extract
|
|
13
|
+
* manifests, prefix trees, and pre-render candidates.
|
|
14
|
+
*/
|
|
15
|
+
export const RouterRegistry: Map<
|
|
16
|
+
string,
|
|
17
|
+
RSCRouterInternal<any, any>
|
|
18
|
+
> = new Map();
|
|
19
|
+
|
|
20
|
+
export let routerAutoId = 0;
|
|
21
|
+
|
|
22
|
+
export function nextRouterAutoId(): number {
|
|
23
|
+
return routerAutoId++;
|
|
24
|
+
}
|