@rangojs/router 0.0.0-experimental.2
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/CLAUDE.md +7 -0
- package/README.md +19 -0
- package/dist/vite/index.js +1298 -0
- package/package.json +140 -0
- package/skills/caching/SKILL.md +319 -0
- package/skills/document-cache/SKILL.md +152 -0
- package/skills/hooks/SKILL.md +359 -0
- package/skills/intercept/SKILL.md +292 -0
- package/skills/layout/SKILL.md +216 -0
- package/skills/loader/SKILL.md +365 -0
- package/skills/middleware/SKILL.md +442 -0
- package/skills/parallel/SKILL.md +255 -0
- package/skills/route/SKILL.md +141 -0
- package/skills/router-setup/SKILL.md +403 -0
- package/skills/theme/SKILL.md +54 -0
- package/skills/typesafety/SKILL.md +352 -0
- package/src/__mocks__/version.ts +6 -0
- package/src/__tests__/component-utils.test.ts +76 -0
- package/src/__tests__/route-definition.test.ts +63 -0
- package/src/__tests__/urls.test.tsx +436 -0
- package/src/browser/event-controller.ts +876 -0
- package/src/browser/index.ts +18 -0
- package/src/browser/link-interceptor.ts +121 -0
- package/src/browser/lru-cache.ts +69 -0
- package/src/browser/merge-segment-loaders.ts +126 -0
- package/src/browser/navigation-bridge.ts +893 -0
- package/src/browser/navigation-client.ts +162 -0
- package/src/browser/navigation-store.ts +823 -0
- package/src/browser/partial-update.ts +559 -0
- package/src/browser/react/Link.tsx +248 -0
- package/src/browser/react/NavigationProvider.tsx +275 -0
- package/src/browser/react/ScrollRestoration.tsx +94 -0
- package/src/browser/react/context.ts +53 -0
- package/src/browser/react/index.ts +52 -0
- package/src/browser/react/location-state-shared.ts +120 -0
- package/src/browser/react/location-state.ts +62 -0
- package/src/browser/react/use-action.ts +240 -0
- package/src/browser/react/use-client-cache.ts +56 -0
- package/src/browser/react/use-handle.ts +178 -0
- package/src/browser/react/use-href.tsx +208 -0
- package/src/browser/react/use-link-status.ts +134 -0
- package/src/browser/react/use-navigation.ts +150 -0
- package/src/browser/react/use-segments.ts +188 -0
- package/src/browser/request-controller.ts +164 -0
- package/src/browser/rsc-router.tsx +353 -0
- package/src/browser/scroll-restoration.ts +324 -0
- package/src/browser/server-action-bridge.ts +747 -0
- package/src/browser/shallow.ts +35 -0
- package/src/browser/types.ts +464 -0
- package/src/cache/__tests__/document-cache.test.ts +522 -0
- package/src/cache/__tests__/memory-segment-store.test.ts +487 -0
- package/src/cache/__tests__/memory-store.test.ts +484 -0
- package/src/cache/cache-scope.ts +565 -0
- package/src/cache/cf/__tests__/cf-cache-store.test.ts +428 -0
- package/src/cache/cf/cf-cache-store.ts +428 -0
- package/src/cache/cf/index.ts +19 -0
- package/src/cache/document-cache.ts +340 -0
- package/src/cache/index.ts +58 -0
- package/src/cache/memory-segment-store.ts +150 -0
- package/src/cache/memory-store.ts +253 -0
- package/src/cache/types.ts +387 -0
- package/src/client.rsc.tsx +88 -0
- package/src/client.tsx +621 -0
- package/src/component-utils.ts +76 -0
- package/src/components/DefaultDocument.tsx +23 -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 +259 -0
- package/src/handle.ts +120 -0
- package/src/handles/MetaTags.tsx +193 -0
- package/src/handles/index.ts +6 -0
- package/src/handles/meta.ts +247 -0
- package/src/href-client.ts +128 -0
- package/src/href-context.ts +33 -0
- package/src/href.ts +177 -0
- package/src/index.rsc.ts +79 -0
- package/src/index.ts +87 -0
- package/src/loader.rsc.ts +204 -0
- package/src/loader.ts +47 -0
- package/src/network-error-thrower.tsx +21 -0
- package/src/outlet-context.ts +15 -0
- package/src/root-error-boundary.tsx +277 -0
- package/src/route-content-wrapper.tsx +198 -0
- package/src/route-definition.ts +1371 -0
- package/src/route-map-builder.ts +146 -0
- package/src/route-types.ts +198 -0
- package/src/route-utils.ts +89 -0
- package/src/router/__tests__/match-context.test.ts +104 -0
- package/src/router/__tests__/match-pipelines.test.ts +537 -0
- package/src/router/__tests__/match-result.test.ts +566 -0
- package/src/router/__tests__/on-error.test.ts +935 -0
- package/src/router/__tests__/pattern-matching.test.ts +577 -0
- package/src/router/error-handling.ts +287 -0
- package/src/router/handler-context.ts +158 -0
- package/src/router/loader-resolution.ts +326 -0
- package/src/router/manifest.ts +138 -0
- package/src/router/match-context.ts +264 -0
- package/src/router/match-middleware/background-revalidation.ts +236 -0
- package/src/router/match-middleware/cache-lookup.ts +261 -0
- package/src/router/match-middleware/cache-store.ts +266 -0
- package/src/router/match-middleware/index.ts +81 -0
- package/src/router/match-middleware/intercept-resolution.ts +268 -0
- package/src/router/match-middleware/segment-resolution.ts +174 -0
- package/src/router/match-pipelines.ts +214 -0
- package/src/router/match-result.ts +214 -0
- package/src/router/metrics.ts +62 -0
- package/src/router/middleware.test.ts +1355 -0
- package/src/router/middleware.ts +748 -0
- package/src/router/pattern-matching.ts +272 -0
- package/src/router/revalidation.ts +190 -0
- package/src/router/router-context.ts +299 -0
- package/src/router/types.ts +96 -0
- package/src/router.ts +3876 -0
- package/src/rsc/__tests__/helpers.test.ts +175 -0
- package/src/rsc/handler.ts +1060 -0
- package/src/rsc/helpers.ts +64 -0
- package/src/rsc/index.ts +56 -0
- package/src/rsc/nonce.ts +18 -0
- package/src/rsc/types.ts +237 -0
- package/src/segment-system.tsx +456 -0
- package/src/server/__tests__/request-context.test.ts +171 -0
- package/src/server/context.ts +417 -0
- package/src/server/handle-store.ts +230 -0
- package/src/server/loader-registry.ts +174 -0
- package/src/server/request-context.ts +554 -0
- package/src/server/root-layout.tsx +10 -0
- package/src/server/tsconfig.json +14 -0
- package/src/server.ts +146 -0
- package/src/ssr/__tests__/ssr-handler.test.tsx +188 -0
- package/src/ssr/index.tsx +234 -0
- package/src/theme/ThemeProvider.tsx +291 -0
- package/src/theme/ThemeScript.tsx +61 -0
- package/src/theme/__tests__/theme.test.ts +120 -0
- package/src/theme/constants.ts +55 -0
- package/src/theme/index.ts +58 -0
- package/src/theme/theme-context.ts +70 -0
- package/src/theme/theme-script.ts +152 -0
- package/src/theme/types.ts +182 -0
- package/src/theme/use-theme.ts +44 -0
- package/src/types.ts +1561 -0
- package/src/urls.ts +726 -0
- package/src/use-loader.tsx +346 -0
- package/src/vite/__tests__/expose-loader-id.test.ts +117 -0
- package/src/vite/expose-action-id.ts +344 -0
- package/src/vite/expose-handle-id.ts +209 -0
- package/src/vite/expose-loader-id.ts +357 -0
- package/src/vite/expose-location-state-id.ts +177 -0
- package/src/vite/index.ts +787 -0
- package/src/vite/package-resolution.ts +125 -0
- package/src/vite/version.d.ts +12 -0
- package/src/vite/virtual-entries.ts +109 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side loader registry for GET-based fetching
|
|
3
|
+
*
|
|
4
|
+
* Loaders are loaded lazily via dynamic imports when first requested.
|
|
5
|
+
* The RSC handler looks up loaders by $$id to execute them.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { LoaderFn } from "../types.js";
|
|
9
|
+
import type { MiddlewareFn } from "../router/middleware.js";
|
|
10
|
+
import { getFetchableLoader } from "../loader.rsc.js";
|
|
11
|
+
|
|
12
|
+
interface RegisteredLoader {
|
|
13
|
+
fn: LoaderFn<any, any, any>;
|
|
14
|
+
middleware: MiddlewareFn[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Server-side cache - maps loader $$id to function and middleware
|
|
18
|
+
// This is a CACHE populated by getLoaderLazy() when loaders are first accessed.
|
|
19
|
+
// The source of truth is fetchableLoaderRegistry in loader.ts, which is populated
|
|
20
|
+
// when createLoader() runs. This cache exists to:
|
|
21
|
+
// 1. Avoid repeated lookups/imports for the same loader
|
|
22
|
+
// 2. Support lazy loading in production (loaders imported on-demand)
|
|
23
|
+
// 3. Provide a stable reference for the RSC handler
|
|
24
|
+
const loaderRegistry = new Map<string, RegisteredLoader>();
|
|
25
|
+
|
|
26
|
+
// Lazy import map - set by the loader manifest
|
|
27
|
+
// Maps loader $$id to a function that imports the loader module
|
|
28
|
+
type LazyLoaderImport = () => Promise<{ $$id: string }>;
|
|
29
|
+
let lazyLoaderImports: Map<string, LazyLoaderImport> | null = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Set the lazy loader imports map (called by the loader manifest)
|
|
33
|
+
*/
|
|
34
|
+
export function setLoaderImports(
|
|
35
|
+
imports: Record<string, LazyLoaderImport>
|
|
36
|
+
): void {
|
|
37
|
+
lazyLoaderImports = new Map(Object.entries(imports));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Register a fetchable loader by $$id
|
|
42
|
+
* Called by createLoader when fetchable option is provided
|
|
43
|
+
*/
|
|
44
|
+
export function registerLoader(
|
|
45
|
+
id: string,
|
|
46
|
+
fn: LoaderFn<any, any, any>,
|
|
47
|
+
middleware: MiddlewareFn[] = []
|
|
48
|
+
): void {
|
|
49
|
+
if (loaderRegistry.has(id)) {
|
|
50
|
+
// Already registered (can happen during HMR)
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
loaderRegistry.set(id, { fn, middleware });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get a registered loader by $$id (synchronous)
|
|
58
|
+
* Returns undefined if loader is not registered
|
|
59
|
+
*/
|
|
60
|
+
export function getLoader(id: string): RegisteredLoader | undefined {
|
|
61
|
+
return loaderRegistry.get(id);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get a loader by $$id, loading it lazily if needed
|
|
66
|
+
* This is the primary method for the RSC handler to get loaders
|
|
67
|
+
*
|
|
68
|
+
* In production: IDs are hashed, looked up via the lazy import map
|
|
69
|
+
* In dev: IDs are "filePath#exportName", resolved via dynamic import
|
|
70
|
+
*/
|
|
71
|
+
export async function getLoaderLazy(
|
|
72
|
+
id: string
|
|
73
|
+
): Promise<RegisteredLoader | undefined> {
|
|
74
|
+
// Check if already cached in main registry
|
|
75
|
+
const existing = loaderRegistry.get(id);
|
|
76
|
+
if (existing) {
|
|
77
|
+
return existing;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check the fetchable loader registry (populated by createLoader)
|
|
81
|
+
const fetchable = getFetchableLoader(id);
|
|
82
|
+
if (fetchable) {
|
|
83
|
+
// Cache in main registry for future requests
|
|
84
|
+
loaderRegistry.set(id, fetchable);
|
|
85
|
+
return fetchable;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Try to lazy load from the import map (production mode)
|
|
89
|
+
if (lazyLoaderImports && lazyLoaderImports.size > 0) {
|
|
90
|
+
const lazyImport = lazyLoaderImports.get(id);
|
|
91
|
+
if (lazyImport) {
|
|
92
|
+
try {
|
|
93
|
+
// Import the loader module - this triggers createLoader which registers fn
|
|
94
|
+
await lazyImport();
|
|
95
|
+
|
|
96
|
+
// Now try to get from fetchable registry (createLoader registered it)
|
|
97
|
+
const registered = getFetchableLoader(id);
|
|
98
|
+
if (registered) {
|
|
99
|
+
loaderRegistry.set(id, registered);
|
|
100
|
+
return registered;
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error(`[LoaderRegistry] Failed to load loader "${id}":`, error);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Dev mode fallback: parse the ID and use Vite's dynamic import
|
|
109
|
+
// ID format in dev: "src/path/to/file.ts#ExportName"
|
|
110
|
+
const hashIndex = id.indexOf("#");
|
|
111
|
+
if (hashIndex !== -1) {
|
|
112
|
+
const filePath = id.slice(0, hashIndex);
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
// In dev mode, Vite handles dynamic imports
|
|
116
|
+
// Just importing the module triggers createLoader which registers the fn
|
|
117
|
+
await import(/* @vite-ignore */ `/${filePath}`);
|
|
118
|
+
|
|
119
|
+
// Now try to get from fetchable registry
|
|
120
|
+
const registered = getFetchableLoader(id);
|
|
121
|
+
if (registered) {
|
|
122
|
+
loaderRegistry.set(id, registered);
|
|
123
|
+
return registered;
|
|
124
|
+
}
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(`[LoaderRegistry] Failed to load loader "${id}":`, error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Check if a loader is registered by $$id
|
|
135
|
+
*/
|
|
136
|
+
export function hasLoader(id: string): boolean {
|
|
137
|
+
return loaderRegistry.has(id) || getFetchableLoader(id) !== undefined;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get all registered loader IDs (for debugging)
|
|
142
|
+
*/
|
|
143
|
+
export function getRegisteredLoaderIds(): string[] {
|
|
144
|
+
return Array.from(loaderRegistry.keys());
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Register a loader by its $$id (injected by Vite plugin)
|
|
149
|
+
* This is called during module loading to cache loaders
|
|
150
|
+
*/
|
|
151
|
+
export function registerLoaderById(loader: {
|
|
152
|
+
$$id: string;
|
|
153
|
+
fn?: LoaderFn<any, any, any>;
|
|
154
|
+
}): void {
|
|
155
|
+
if (!loader.$$id) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (loaderRegistry.has(loader.$$id)) {
|
|
159
|
+
// Already registered (can happen during HMR)
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// For fetchable loaders, fn is stored in the fetchable registry by $$id
|
|
164
|
+
const fetchable = getFetchableLoader(loader.$$id);
|
|
165
|
+
if (fetchable) {
|
|
166
|
+
loaderRegistry.set(loader.$$id, fetchable);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Fall back to using fn from the loader object (non-fetchable loaders)
|
|
171
|
+
if (loader.fn) {
|
|
172
|
+
loaderRegistry.set(loader.$$id, { fn: loader.fn, middleware: [] });
|
|
173
|
+
}
|
|
174
|
+
}
|