@rangojs/router 0.0.0-experimental.19 → 0.0.0-experimental.1b930379

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 (84) hide show
  1. package/README.md +46 -12
  2. package/dist/bin/rango.js +109 -15
  3. package/dist/vite/index.js +323 -121
  4. package/package.json +15 -16
  5. package/skills/breadcrumbs/SKILL.md +250 -0
  6. package/skills/caching/SKILL.md +4 -4
  7. package/skills/document-cache/SKILL.md +2 -2
  8. package/skills/hooks/SKILL.md +33 -31
  9. package/skills/host-router/SKILL.md +218 -0
  10. package/skills/loader/SKILL.md +55 -15
  11. package/skills/prerender/SKILL.md +2 -2
  12. package/skills/rango/SKILL.md +0 -1
  13. package/skills/route/SKILL.md +3 -4
  14. package/skills/router-setup/SKILL.md +8 -3
  15. package/skills/typesafety/SKILL.md +25 -23
  16. package/src/__internal.ts +92 -0
  17. package/src/bin/rango.ts +18 -0
  18. package/src/browser/link-interceptor.ts +4 -0
  19. package/src/browser/navigation-bridge.ts +95 -5
  20. package/src/browser/navigation-client.ts +97 -72
  21. package/src/browser/prefetch/cache.ts +112 -25
  22. package/src/browser/prefetch/fetch.ts +28 -30
  23. package/src/browser/prefetch/policy.ts +6 -0
  24. package/src/browser/react/Link.tsx +19 -7
  25. package/src/browser/rsc-router.tsx +11 -2
  26. package/src/browser/server-action-bridge.ts +448 -432
  27. package/src/browser/types.ts +24 -0
  28. package/src/build/generate-route-types.ts +2 -0
  29. package/src/build/route-trie.ts +19 -3
  30. package/src/build/route-types/router-processing.ts +125 -15
  31. package/src/client.rsc.tsx +2 -1
  32. package/src/client.tsx +1 -46
  33. package/src/handles/breadcrumbs.ts +66 -0
  34. package/src/handles/index.ts +1 -0
  35. package/src/host/index.ts +0 -3
  36. package/src/index.rsc.ts +5 -36
  37. package/src/index.ts +32 -66
  38. package/src/prerender/store.ts +56 -15
  39. package/src/route-definition/index.ts +0 -3
  40. package/src/router/handler-context.ts +30 -3
  41. package/src/router/loader-resolution.ts +1 -1
  42. package/src/router/match-api.ts +1 -1
  43. package/src/router/match-result.ts +0 -9
  44. package/src/router/metrics.ts +233 -13
  45. package/src/router/middleware-types.ts +53 -10
  46. package/src/router/middleware.ts +170 -81
  47. package/src/router/pattern-matching.ts +20 -5
  48. package/src/router/prerender-match.ts +4 -0
  49. package/src/router/revalidation.ts +27 -7
  50. package/src/router/router-interfaces.ts +14 -1
  51. package/src/router/router-options.ts +13 -8
  52. package/src/router/segment-resolution/fresh.ts +18 -0
  53. package/src/router/segment-resolution/helpers.ts +1 -1
  54. package/src/router/segment-resolution/revalidation.ts +22 -9
  55. package/src/router/trie-matching.ts +20 -2
  56. package/src/router.ts +29 -9
  57. package/src/rsc/handler.ts +106 -11
  58. package/src/rsc/index.ts +0 -20
  59. package/src/rsc/progressive-enhancement.ts +21 -8
  60. package/src/rsc/rsc-rendering.ts +30 -43
  61. package/src/rsc/server-action.ts +14 -10
  62. package/src/rsc/ssr-setup.ts +128 -0
  63. package/src/rsc/types.ts +2 -0
  64. package/src/search-params.ts +16 -13
  65. package/src/server/context.ts +8 -2
  66. package/src/server/request-context.ts +38 -16
  67. package/src/server.ts +6 -0
  68. package/src/theme/index.ts +4 -13
  69. package/src/types/handler-context.ts +12 -16
  70. package/src/types/route-config.ts +17 -8
  71. package/src/types/segments.ts +0 -5
  72. package/src/vite/discovery/bundle-postprocess.ts +31 -56
  73. package/src/vite/discovery/discover-routers.ts +18 -4
  74. package/src/vite/discovery/prerender-collection.ts +34 -14
  75. package/src/vite/discovery/state.ts +4 -7
  76. package/src/vite/index.ts +4 -3
  77. package/src/vite/plugins/client-ref-dedup.ts +115 -0
  78. package/src/vite/plugins/refresh-cmd.ts +65 -0
  79. package/src/vite/rango.ts +11 -0
  80. package/src/vite/router-discovery.ts +16 -0
  81. package/src/vite/utils/prerender-utils.ts +60 -0
  82. package/skills/testing/SKILL.md +0 -226
  83. package/src/route-definition/route-function.ts +0 -119
  84. /package/{CLAUDE.md → AGENTS.md} +0 -0
@@ -55,6 +55,11 @@ export interface RscMetadata {
55
55
  * Used to detect version mismatches after HMR/deployment.
56
56
  */
57
57
  version?: string;
58
+ /**
59
+ * TTL in milliseconds for the client-side in-memory prefetch cache.
60
+ * Sent on initial render so the browser can configure its cache duration.
61
+ */
62
+ prefetchCacheTTL?: number;
58
63
  /**
59
64
  * Theme configuration from router.
60
65
  * Included when theme is enabled in router config.
@@ -227,6 +232,25 @@ export type HistoryState =
227
232
  export interface NavigateOptions {
228
233
  replace?: boolean;
229
234
  scroll?: boolean;
235
+ /**
236
+ * Whether to revalidate server data on navigation.
237
+ * Set to `false` to skip the RSC server fetch and only update the URL.
238
+ *
239
+ * Only takes effect when the pathname stays the same (search param / hash changes).
240
+ * If the pathname changes, this option is ignored and a full navigation occurs.
241
+ *
242
+ * All location-aware hooks (`useSearchParams`, `useNavigation`, etc.) still update.
243
+ * Server components do not re-render.
244
+ *
245
+ * @default true
246
+ *
247
+ * @example
248
+ * ```tsx
249
+ * router.push("/products?color=blue", { revalidate: false });
250
+ * router.replace("/products?page=3", { revalidate: false });
251
+ * ```
252
+ */
253
+ revalidate?: boolean;
230
254
  /**
231
255
  * State to pass to history.pushState/replaceState
232
256
  * Accessible via useLocationState() hook.
@@ -28,6 +28,8 @@ export {
28
28
  buildCombinedRouteMapForRouterFile,
29
29
  detectUnresolvableIncludes,
30
30
  detectUnresolvableIncludesForUrlsFile,
31
+ findNestedRouterConflict,
32
+ formatNestedRouterConflictError,
31
33
  findRouterFiles,
32
34
  writeCombinedRouteTypes,
33
35
  } from "./route-types/router-processing.js";
@@ -47,6 +47,8 @@ export interface TrieNode {
47
47
  s?: Record<string, TrieNode>;
48
48
  /** Param child: { n: paramName, c: child node } */
49
49
  p?: { n: string; c: TrieNode };
50
+ /** Suffix-param children keyed by suffix (e.g., ".html" → { n: "productId", c: ... }) */
51
+ xp?: Record<string, { n: string; c: TrieNode }>;
50
52
  /** Wildcard terminal: leaf + paramName */
51
53
  w?: TrieLeaf & { pn: string };
52
54
  }
@@ -158,6 +160,11 @@ export function extractAncestryFromTrie(
158
160
  visit(child);
159
161
  }
160
162
  }
163
+ if (node.xp) {
164
+ for (const child of Object.values(node.xp)) {
165
+ visit(child.c);
166
+ }
167
+ }
161
168
  if (node.p) {
162
169
  visit(node.p.c);
163
170
  }
@@ -235,10 +242,19 @@ function insertSegments(
235
242
  mergeLeaf(node, leaf);
236
243
  // AND continue with param child (param present)
237
244
  }
238
- if (!node.p) {
239
- node.p = { n: segment.value, c: {} };
245
+ if (segment.suffix) {
246
+ // Suffix param: keyed by suffix string (e.g., ".html")
247
+ if (!node.xp) node.xp = {};
248
+ if (!node.xp[segment.suffix]) {
249
+ node.xp[segment.suffix] = { n: segment.value, c: {} };
250
+ }
251
+ insertSegments(node.xp[segment.suffix].c, segments, index + 1, leaf);
252
+ } else {
253
+ if (!node.p) {
254
+ node.p = { n: segment.value, c: {} };
255
+ }
256
+ insertSegments(node.p.c, segments, index + 1, leaf);
240
257
  }
241
- insertSegments(node.p.c, segments, index + 1, leaf);
242
258
  } else if (segment.type === "wildcard") {
243
259
  // Wildcard consumes all remaining segments
244
260
  const wildLeaf = { ...leaf, pn: "*" };
@@ -1,9 +1,20 @@
1
- import { readFileSync, writeFileSync, existsSync, unlinkSync } from "node:fs";
2
- import { join, dirname, resolve, basename as pathBasename } from "node:path";
1
+ import {
2
+ readFileSync,
3
+ writeFileSync,
4
+ existsSync,
5
+ unlinkSync,
6
+ readdirSync,
7
+ } from "node:fs";
8
+ import {
9
+ join,
10
+ dirname,
11
+ resolve,
12
+ sep,
13
+ basename as pathBasename,
14
+ } from "node:path";
3
15
  import ts from "typescript";
4
16
  import { generateRouteTypesSource } from "./codegen.js";
5
17
  import type { ScanFilter } from "./scan-filter.js";
6
- import { findTsFiles } from "./scan-filter.js";
7
18
  import {
8
19
  resolveImportedVariable,
9
20
  resolveImportPath,
@@ -26,6 +37,111 @@ function countPublicRouteEntries(source: string): number {
26
37
  return count;
27
38
  }
28
39
 
40
+ const ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
41
+
42
+ function isRoutableSourceFile(name: string): boolean {
43
+ return (
44
+ (name.endsWith(".ts") ||
45
+ name.endsWith(".tsx") ||
46
+ name.endsWith(".js") ||
47
+ name.endsWith(".jsx")) &&
48
+ !name.includes(".gen.")
49
+ );
50
+ }
51
+
52
+ function findRouterFilesRecursive(
53
+ dir: string,
54
+ filter: ScanFilter | undefined,
55
+ results: string[],
56
+ ): void {
57
+ let entries;
58
+ try {
59
+ entries = readdirSync(dir, { withFileTypes: true });
60
+ } catch (err) {
61
+ console.warn(
62
+ `[rsc-router] Failed to scan directory ${dir}: ${(err as Error).message}`,
63
+ );
64
+ return;
65
+ }
66
+
67
+ const childDirs: string[] = [];
68
+ const routerFilesInDir: string[] = [];
69
+
70
+ for (const entry of entries) {
71
+ const fullPath = join(dir, entry.name);
72
+ if (entry.isDirectory()) {
73
+ if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
74
+ childDirs.push(fullPath);
75
+ continue;
76
+ }
77
+
78
+ if (!isRoutableSourceFile(entry.name)) continue;
79
+ if (filter && !filter(fullPath)) continue;
80
+
81
+ try {
82
+ const source = readFileSync(fullPath, "utf-8");
83
+ if (ROUTER_CALL_PATTERN.test(source)) {
84
+ routerFilesInDir.push(fullPath);
85
+ }
86
+ } catch {
87
+ continue;
88
+ }
89
+ }
90
+
91
+ // A directory that contains a router file is treated as a router root.
92
+ // Once found, deeper directories are skipped to avoid redundant scans.
93
+ if (routerFilesInDir.length > 0) {
94
+ results.push(...routerFilesInDir);
95
+ return;
96
+ }
97
+
98
+ for (const childDir of childDirs) {
99
+ findRouterFilesRecursive(childDir, filter, results);
100
+ }
101
+ }
102
+
103
+ export function findNestedRouterConflict(
104
+ routerFiles: string[],
105
+ ): { ancestor: string; nested: string } | null {
106
+ const routerDirs = [
107
+ ...new Set(routerFiles.map((filePath) => dirname(resolve(filePath)))),
108
+ ].sort((a, b) => a.length - b.length);
109
+
110
+ for (let i = 0; i < routerDirs.length; i++) {
111
+ const ancestorDir = routerDirs[i];
112
+ const prefix = ancestorDir.endsWith(sep)
113
+ ? ancestorDir
114
+ : `${ancestorDir}${sep}`;
115
+ for (let j = i + 1; j < routerDirs.length; j++) {
116
+ const nestedDir = routerDirs[j];
117
+ if (!nestedDir.startsWith(prefix)) continue;
118
+ const ancestorFile = routerFiles.find(
119
+ (filePath) => dirname(resolve(filePath)) === ancestorDir,
120
+ );
121
+ const nestedFile = routerFiles.find(
122
+ (filePath) => dirname(resolve(filePath)) === nestedDir,
123
+ );
124
+ if (ancestorFile && nestedFile) {
125
+ return { ancestor: ancestorFile, nested: nestedFile };
126
+ }
127
+ }
128
+ }
129
+
130
+ return null;
131
+ }
132
+
133
+ export function formatNestedRouterConflictError(
134
+ conflict: { ancestor: string; nested: string },
135
+ prefix = "[rsc-router]",
136
+ ): string {
137
+ return (
138
+ `${prefix} Nested router roots are not supported.\n` +
139
+ `Router root: ${conflict.ancestor}\n` +
140
+ `Nested router: ${conflict.nested}\n` +
141
+ `Move the nested router into a sibling directory or configure it as a separate app root.`
142
+ );
143
+ }
144
+
29
145
  // ---------------------------------------------------------------------------
30
146
  // Router file URL extraction
31
147
  // ---------------------------------------------------------------------------
@@ -235,19 +351,8 @@ export function detectUnresolvableIncludesForUrlsFile(
235
351
  * Call once at startup; the result can be reused on subsequent watcher triggers.
236
352
  */
237
353
  export function findRouterFiles(root: string, filter?: ScanFilter): string[] {
238
- const files = findTsFiles(root, filter);
239
354
  const result: string[] = [];
240
- for (const filePath of files) {
241
- if (filePath.includes(".gen.")) continue;
242
- try {
243
- const source = readFileSync(filePath, "utf-8");
244
- if (/\bcreateRouter\s*[<(]/.test(source)) {
245
- result.push(filePath);
246
- }
247
- } catch {
248
- continue;
249
- }
250
- }
355
+ findRouterFilesRecursive(root, filter, result);
251
356
  return result;
252
357
  }
253
358
 
@@ -276,6 +381,11 @@ export function writeCombinedRouteTypes(
276
381
  const routerFilePaths = knownRouterFiles ?? findRouterFiles(root);
277
382
  if (routerFilePaths.length === 0) return;
278
383
 
384
+ const nestedRouterConflict = findNestedRouterConflict(routerFilePaths);
385
+ if (nestedRouterConflict) {
386
+ throw new Error(formatNestedRouterConflictError(nestedRouterConflict));
387
+ }
388
+
279
389
  for (const routerFilePath of routerFilePaths) {
280
390
  let routerSource: string;
281
391
  try {
@@ -17,7 +17,6 @@ export {
17
17
  OutletProvider,
18
18
  useOutlet,
19
19
  useLoader,
20
- useLoaderData,
21
20
  ErrorBoundary,
22
21
  type ErrorBoundaryProps,
23
22
  } from "./client.js";
@@ -64,6 +63,8 @@ export { Meta } from "./handles/meta.js";
64
63
  // MetaTags is a "use client" component that can be imported from RSC
65
64
  export { MetaTags } from "./handles/MetaTags.js";
66
65
  export type { MetaDescriptor, MetaDescriptorBase } from "./router/types.js";
66
+ // Breadcrumbs handle works in RSC context
67
+ export { Breadcrumbs, type BreadcrumbItem } from "./handles/breadcrumbs.js";
67
68
 
68
69
  // Location state - createLocationState works in RSC (just creates definition)
69
70
  // useLocationState is NOT exported here as it uses client hooks
package/src/client.tsx CHANGED
@@ -313,52 +313,6 @@ export {
313
313
  type UseLoaderOptions,
314
314
  } from "./use-loader.js";
315
315
 
316
- /**
317
- * Hook to access all loader data in the current context
318
- *
319
- * Returns a record of all loader data available in the current outlet context
320
- * and all parent contexts. Useful for debugging or when you need access to
321
- * multiple loaders.
322
- *
323
- * @returns Record of loader name to data, or empty object if no loaders
324
- *
325
- * @example
326
- * ```tsx
327
- * "use client";
328
- * import { useLoaderData } from "rsc-router/client";
329
- *
330
- * export function DebugPanel() {
331
- * const loaderData = useLoaderData();
332
- * return <pre>{JSON.stringify(loaderData, null, 2)}</pre>;
333
- * }
334
- * ```
335
- */
336
- export function useLoaderData(): Record<string, any> {
337
- const context = useContext(OutletContext);
338
-
339
- // Collect all loader data from the context chain
340
- // Child loaders override parent loaders with the same name
341
- const result: Record<string, any> = {};
342
- const stack: OutletContextValue[] = [];
343
-
344
- // Build stack from current to root
345
- let current: OutletContextValue | null | undefined = context;
346
- while (current) {
347
- stack.push(current);
348
- current = current.parent;
349
- }
350
-
351
- // Apply from root to current (so children override parents)
352
- for (let i = stack.length - 1; i >= 0; i--) {
353
- const ctx = stack[i];
354
- if (ctx.loaderData) {
355
- Object.assign(result, ctx.loaderData);
356
- }
357
- }
358
-
359
- return result;
360
- }
361
-
362
316
  /**
363
317
  * Client-safe createLoader factory
364
318
  *
@@ -590,6 +544,7 @@ export { useHandle } from "./browser/react/use-handle.js";
590
544
  export { Meta } from "./handles/meta.js";
591
545
  export { MetaTags } from "./handles/MetaTags.js";
592
546
  export type { MetaDescriptor, MetaDescriptorBase } from "./router/types.js";
547
+ export { Breadcrumbs, type BreadcrumbItem } from "./handles/breadcrumbs.js";
593
548
 
594
549
  // Location state - type-safe navigation state
595
550
  export {
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Built-in Breadcrumbs handle for accumulating breadcrumb items across route segments.
3
+ *
4
+ * Each layout/route pushes breadcrumb items via `ctx.use(Breadcrumbs)`.
5
+ * Items are collected in parent-to-child order with automatic deduplication
6
+ * by `href` (last item for each href wins).
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * // In route handler
11
+ * route("/blog/:slug", (ctx) => {
12
+ * const breadcrumb = ctx.use(Breadcrumbs);
13
+ * breadcrumb({ label: "Blog", href: "/blog" });
14
+ * breadcrumb({ label: post.title, href: `/blog/${ctx.params.slug}` });
15
+ * });
16
+ *
17
+ * // In client component (consume with useHandle)
18
+ * const crumbs = useHandle(Breadcrumbs);
19
+ * crumbs.map((c) => <a href={c.href}>{c.label}</a>);
20
+ * ```
21
+ */
22
+
23
+ import type { ReactNode } from "react";
24
+ import { createHandle, type Handle } from "../handle.js";
25
+
26
+ /**
27
+ * A single breadcrumb item.
28
+ *
29
+ * @property label - Display text for the breadcrumb
30
+ * @property href - URL the breadcrumb links to
31
+ * @property content - Optional extra content (sync or async) rendered alongside the label
32
+ */
33
+ export interface BreadcrumbItem {
34
+ label: string;
35
+ href: string;
36
+ content?: ReactNode | Promise<ReactNode>;
37
+ }
38
+
39
+ /**
40
+ * Collect function for Breadcrumbs handle.
41
+ * Flattens segments in parent-to-child order with deduplication by href
42
+ * (last item for each href wins).
43
+ */
44
+ function collectBreadcrumbs(segments: BreadcrumbItem[][]): BreadcrumbItem[] {
45
+ const all = segments.flat();
46
+ const seen = new Map<string, number>();
47
+
48
+ for (let i = 0; i < all.length; i++) {
49
+ seen.set(all[i].href, i);
50
+ }
51
+
52
+ // Return items in order, keeping only the last occurrence per href
53
+ return all.filter((item, index) => seen.get(item.href) === index);
54
+ }
55
+
56
+ /**
57
+ * Built-in handle for accumulating breadcrumb navigation items.
58
+ *
59
+ * Use `ctx.use(Breadcrumbs)` in route handlers to push breadcrumb items.
60
+ * Use `useHandle(Breadcrumbs)` in client components to consume them.
61
+ */
62
+ export const Breadcrumbs: Handle<BreadcrumbItem, BreadcrumbItem[]> =
63
+ createHandle<BreadcrumbItem, BreadcrumbItem[]>(
64
+ collectBreadcrumbs,
65
+ "__rsc_router_breadcrumbs__",
66
+ );
@@ -4,3 +4,4 @@
4
4
 
5
5
  export { Meta } from "./meta.ts";
6
6
  export { MetaTags } from "./MetaTags.tsx";
7
+ export { Breadcrumbs, type BreadcrumbItem } from "./breadcrumbs.ts";
package/src/host/index.ts CHANGED
@@ -25,9 +25,6 @@
25
25
  // Core router
26
26
  export { createHostRouter } from "./router.js";
27
27
 
28
- // Host router registry for build-time discovery
29
- export { HostRouterRegistry, type HostRouterRegistryEntry } from "./router.js";
30
-
31
28
  // Utilities
32
29
  export { defineHosts } from "./utils.js";
33
30
 
package/src/index.rsc.ts CHANGED
@@ -11,8 +11,6 @@
11
11
 
12
12
  // Re-export all universal exports from index.ts
13
13
  export {
14
- // Universal rendering utilities
15
- renderSegments,
16
14
  // Error classes
17
15
  RouteNotFoundError,
18
16
  DataNotFoundError,
@@ -21,9 +19,6 @@ export {
21
19
  HandlerError,
22
20
  BuildError,
23
21
  InvalidHandlerError,
24
- NetworkError,
25
- isNetworkError,
26
- sanitizeError,
27
22
  RouterError,
28
23
  Skip,
29
24
  isSkip,
@@ -40,7 +35,6 @@ export type {
40
35
  TrailingSlashMode,
41
36
  // Handler types
42
37
  Handler,
43
- ScopedRouteMap,
44
38
  HandlerContext,
45
39
  ExtractParams,
46
40
  GenericParams,
@@ -120,7 +114,6 @@ export { nonce } from "./rsc/nonce.js";
120
114
  // Pre-render handler API
121
115
  export {
122
116
  Prerender,
123
- isPrerenderHandler,
124
117
  type PrerenderHandlerDefinition,
125
118
  type PrerenderPassthroughContext,
126
119
  type PrerenderOptions,
@@ -130,16 +123,11 @@ export {
130
123
  } from "./prerender.js";
131
124
 
132
125
  // Static handler API
133
- export {
134
- Static,
135
- isStaticHandler,
136
- type StaticHandlerDefinition,
137
- } from "./static-handler.js";
126
+ export { Static, type StaticHandlerDefinition } from "./static-handler.js";
138
127
 
139
128
  // Django-style URL patterns (RSC/server context)
140
129
  export {
141
130
  urls,
142
- RESPONSE_TYPE,
143
131
  type PathHelpers,
144
132
  type PathOptions,
145
133
  type UrlPatterns,
@@ -171,6 +159,7 @@ export type { HandlerCacheConfig } from "./rsc/types.js";
171
159
 
172
160
  // Built-in handles (server-side)
173
161
  export { Meta } from "./handles/meta.js";
162
+ export { Breadcrumbs, type BreadcrumbItem } from "./handles/breadcrumbs.js";
174
163
 
175
164
  // Request context (for accessing request data in server actions/components).
176
165
  // Re-exported with a narrowed return type so that public consumers only see
@@ -179,9 +168,10 @@ export { Meta } from "./handles/meta.js";
179
168
  import { getRequestContext as _getRequestContextInternal } from "./server/request-context.js";
180
169
  export type { PublicRequestContext as RequestContext } from "./server/request-context.js";
181
170
  import type { PublicRequestContext } from "./server/request-context.js";
171
+ import type { DefaultEnv } from "./types/global-namespace.js";
182
172
 
183
173
  export const getRequestContext: <
184
- TEnv = unknown,
174
+ TEnv = DefaultEnv,
185
175
  >() => PublicRequestContext<TEnv> = _getRequestContextInternal;
186
176
 
187
177
  // Request-scoped shorthands
@@ -205,8 +195,6 @@ export type {
205
195
  ReverseFunction,
206
196
  ExtractLocalRoutes,
207
197
  ParamsFor,
208
- SanitizePrefix,
209
- MergeRoutes,
210
198
  } from "./reverse.js";
211
199
  export { scopedReverse, createReverse } from "./reverse.js";
212
200
 
@@ -219,12 +207,6 @@ export type {
219
207
  RouteParams,
220
208
  } from "./search-params.js";
221
209
 
222
- // Debug utilities for route matching (development only)
223
- export {
224
- enableMatchDebug,
225
- getMatchDebugStats,
226
- } from "./router/pattern-matching.js";
227
-
228
210
  // Location state (universal)
229
211
  export {
230
212
  createLocationState,
@@ -240,20 +222,7 @@ export type { PathResponse } from "./href-client.js";
240
222
  export { createConsoleSink } from "./router/telemetry.js";
241
223
  export { createOTelSink } from "./router/telemetry-otel.js";
242
224
  export type { OTelTracer, OTelSpan } from "./router/telemetry-otel.js";
243
- export type {
244
- TelemetrySink,
245
- TelemetryEvent,
246
- RequestStartEvent,
247
- RequestEndEvent,
248
- RequestErrorEvent,
249
- RequestTimeoutEvent,
250
- LoaderStartEvent,
251
- LoaderEndEvent,
252
- LoaderErrorEvent,
253
- HandlerErrorEvent,
254
- CacheDecisionEvent,
255
- RevalidationDecisionEvent,
256
- } from "./router/telemetry.js";
225
+ export type { TelemetrySink, TelemetryEvent } from "./router/telemetry.js";
257
226
 
258
227
  // Timeout types and error class
259
228
  export { RouterTimeoutError } from "./router/timeout.js";