@rangojs/router 0.0.0-experimental.10

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 (172) hide show
  1. package/CLAUDE.md +43 -0
  2. package/README.md +19 -0
  3. package/dist/bin/rango.js +227 -0
  4. package/dist/vite/index.js +3039 -0
  5. package/package.json +171 -0
  6. package/skills/caching/SKILL.md +191 -0
  7. package/skills/debug-manifest/SKILL.md +108 -0
  8. package/skills/document-cache/SKILL.md +180 -0
  9. package/skills/fonts/SKILL.md +165 -0
  10. package/skills/hooks/SKILL.md +442 -0
  11. package/skills/intercept/SKILL.md +190 -0
  12. package/skills/layout/SKILL.md +213 -0
  13. package/skills/links/SKILL.md +180 -0
  14. package/skills/loader/SKILL.md +246 -0
  15. package/skills/middleware/SKILL.md +202 -0
  16. package/skills/mime-routes/SKILL.md +124 -0
  17. package/skills/parallel/SKILL.md +228 -0
  18. package/skills/prerender/SKILL.md +283 -0
  19. package/skills/rango/SKILL.md +54 -0
  20. package/skills/response-routes/SKILL.md +358 -0
  21. package/skills/route/SKILL.md +173 -0
  22. package/skills/router-setup/SKILL.md +346 -0
  23. package/skills/tailwind/SKILL.md +129 -0
  24. package/skills/theme/SKILL.md +78 -0
  25. package/skills/typesafety/SKILL.md +394 -0
  26. package/src/__internal.ts +175 -0
  27. package/src/bin/rango.ts +24 -0
  28. package/src/browser/event-controller.ts +876 -0
  29. package/src/browser/index.ts +18 -0
  30. package/src/browser/link-interceptor.ts +121 -0
  31. package/src/browser/lru-cache.ts +69 -0
  32. package/src/browser/merge-segment-loaders.ts +126 -0
  33. package/src/browser/navigation-bridge.ts +913 -0
  34. package/src/browser/navigation-client.ts +165 -0
  35. package/src/browser/navigation-store.ts +823 -0
  36. package/src/browser/partial-update.ts +600 -0
  37. package/src/browser/react/Link.tsx +248 -0
  38. package/src/browser/react/NavigationProvider.tsx +346 -0
  39. package/src/browser/react/ScrollRestoration.tsx +94 -0
  40. package/src/browser/react/context.ts +53 -0
  41. package/src/browser/react/index.ts +52 -0
  42. package/src/browser/react/location-state-shared.ts +120 -0
  43. package/src/browser/react/location-state.ts +62 -0
  44. package/src/browser/react/mount-context.ts +32 -0
  45. package/src/browser/react/use-action.ts +240 -0
  46. package/src/browser/react/use-client-cache.ts +56 -0
  47. package/src/browser/react/use-handle.ts +203 -0
  48. package/src/browser/react/use-href.tsx +40 -0
  49. package/src/browser/react/use-link-status.ts +134 -0
  50. package/src/browser/react/use-mount.ts +31 -0
  51. package/src/browser/react/use-navigation.ts +140 -0
  52. package/src/browser/react/use-segments.ts +188 -0
  53. package/src/browser/request-controller.ts +164 -0
  54. package/src/browser/rsc-router.tsx +352 -0
  55. package/src/browser/scroll-restoration.ts +324 -0
  56. package/src/browser/segment-structure-assert.ts +67 -0
  57. package/src/browser/server-action-bridge.ts +762 -0
  58. package/src/browser/shallow.ts +35 -0
  59. package/src/browser/types.ts +478 -0
  60. package/src/build/generate-manifest.ts +377 -0
  61. package/src/build/generate-route-types.ts +828 -0
  62. package/src/build/index.ts +36 -0
  63. package/src/build/route-trie.ts +239 -0
  64. package/src/cache/cache-scope.ts +563 -0
  65. package/src/cache/cf/cf-cache-store.ts +428 -0
  66. package/src/cache/cf/index.ts +19 -0
  67. package/src/cache/document-cache.ts +340 -0
  68. package/src/cache/index.ts +58 -0
  69. package/src/cache/memory-segment-store.ts +150 -0
  70. package/src/cache/memory-store.ts +253 -0
  71. package/src/cache/types.ts +392 -0
  72. package/src/client.rsc.tsx +83 -0
  73. package/src/client.tsx +643 -0
  74. package/src/component-utils.ts +76 -0
  75. package/src/components/DefaultDocument.tsx +23 -0
  76. package/src/debug.ts +233 -0
  77. package/src/default-error-boundary.tsx +88 -0
  78. package/src/deps/browser.ts +8 -0
  79. package/src/deps/html-stream-client.ts +2 -0
  80. package/src/deps/html-stream-server.ts +2 -0
  81. package/src/deps/rsc.ts +10 -0
  82. package/src/deps/ssr.ts +2 -0
  83. package/src/errors.ts +295 -0
  84. package/src/handle.ts +130 -0
  85. package/src/handles/MetaTags.tsx +193 -0
  86. package/src/handles/index.ts +6 -0
  87. package/src/handles/meta.ts +247 -0
  88. package/src/host/cookie-handler.ts +159 -0
  89. package/src/host/errors.ts +97 -0
  90. package/src/host/index.ts +56 -0
  91. package/src/host/pattern-matcher.ts +214 -0
  92. package/src/host/router.ts +330 -0
  93. package/src/host/testing.ts +79 -0
  94. package/src/host/types.ts +138 -0
  95. package/src/host/utils.ts +25 -0
  96. package/src/href-client.ts +202 -0
  97. package/src/href-context.ts +33 -0
  98. package/src/index.rsc.ts +121 -0
  99. package/src/index.ts +165 -0
  100. package/src/loader.rsc.ts +207 -0
  101. package/src/loader.ts +47 -0
  102. package/src/network-error-thrower.tsx +21 -0
  103. package/src/outlet-context.ts +15 -0
  104. package/src/prerender/param-hash.ts +35 -0
  105. package/src/prerender/store.ts +40 -0
  106. package/src/prerender.ts +156 -0
  107. package/src/reverse.ts +267 -0
  108. package/src/root-error-boundary.tsx +277 -0
  109. package/src/route-content-wrapper.tsx +193 -0
  110. package/src/route-definition.ts +1431 -0
  111. package/src/route-map-builder.ts +242 -0
  112. package/src/route-types.ts +220 -0
  113. package/src/router/error-handling.ts +287 -0
  114. package/src/router/handler-context.ts +158 -0
  115. package/src/router/intercept-resolution.ts +387 -0
  116. package/src/router/loader-resolution.ts +327 -0
  117. package/src/router/manifest.ts +216 -0
  118. package/src/router/match-api.ts +621 -0
  119. package/src/router/match-context.ts +264 -0
  120. package/src/router/match-middleware/background-revalidation.ts +236 -0
  121. package/src/router/match-middleware/cache-lookup.ts +382 -0
  122. package/src/router/match-middleware/cache-store.ts +276 -0
  123. package/src/router/match-middleware/index.ts +81 -0
  124. package/src/router/match-middleware/intercept-resolution.ts +281 -0
  125. package/src/router/match-middleware/segment-resolution.ts +184 -0
  126. package/src/router/match-pipelines.ts +214 -0
  127. package/src/router/match-result.ts +213 -0
  128. package/src/router/metrics.ts +62 -0
  129. package/src/router/middleware.ts +791 -0
  130. package/src/router/pattern-matching.ts +407 -0
  131. package/src/router/revalidation.ts +190 -0
  132. package/src/router/router-context.ts +301 -0
  133. package/src/router/segment-resolution.ts +1315 -0
  134. package/src/router/trie-matching.ts +172 -0
  135. package/src/router/types.ts +163 -0
  136. package/src/router.gen.ts +6 -0
  137. package/src/router.ts +2423 -0
  138. package/src/rsc/handler.ts +1443 -0
  139. package/src/rsc/helpers.ts +64 -0
  140. package/src/rsc/index.ts +56 -0
  141. package/src/rsc/nonce.ts +18 -0
  142. package/src/rsc/types.ts +236 -0
  143. package/src/segment-system.tsx +442 -0
  144. package/src/server/context.ts +466 -0
  145. package/src/server/handle-store.ts +229 -0
  146. package/src/server/loader-registry.ts +174 -0
  147. package/src/server/request-context.ts +554 -0
  148. package/src/server/root-layout.tsx +10 -0
  149. package/src/server/tsconfig.json +14 -0
  150. package/src/server.ts +171 -0
  151. package/src/ssr/index.tsx +296 -0
  152. package/src/theme/ThemeProvider.tsx +291 -0
  153. package/src/theme/ThemeScript.tsx +61 -0
  154. package/src/theme/constants.ts +59 -0
  155. package/src/theme/index.ts +58 -0
  156. package/src/theme/theme-context.ts +70 -0
  157. package/src/theme/theme-script.ts +152 -0
  158. package/src/theme/types.ts +182 -0
  159. package/src/theme/use-theme.ts +44 -0
  160. package/src/types.ts +1757 -0
  161. package/src/urls.gen.ts +8 -0
  162. package/src/urls.ts +1282 -0
  163. package/src/use-loader.tsx +346 -0
  164. package/src/vite/expose-action-id.ts +344 -0
  165. package/src/vite/expose-handle-id.ts +209 -0
  166. package/src/vite/expose-loader-id.ts +426 -0
  167. package/src/vite/expose-location-state-id.ts +177 -0
  168. package/src/vite/expose-prerender-handler-id.ts +429 -0
  169. package/src/vite/index.ts +2068 -0
  170. package/src/vite/package-resolution.ts +125 -0
  171. package/src/vite/version.d.ts +12 -0
  172. package/src/vite/virtual-entries.ts +114 -0
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Shallow comparison utility for selector optimization
3
+ *
4
+ * Used by useNavigation hook to prevent unnecessary re-renders
5
+ * when the selected value hasn't changed.
6
+ *
7
+ * @param a - First value
8
+ * @param b - Second value
9
+ * @returns true if values are shallowly equal
10
+ */
11
+ export function shallow<T>(a: T, b: T): boolean {
12
+ // Same reference or primitive equality
13
+ if (Object.is(a, b)) return true;
14
+
15
+ // Different types or non-objects
16
+ if (typeof a !== "object" || typeof b !== "object") return false;
17
+
18
+ // Null checks
19
+ if (a === null || b === null) return false;
20
+
21
+ // Compare object keys
22
+ const keysA = Object.keys(a);
23
+ const keysB = Object.keys(b);
24
+
25
+ if (keysA.length !== keysB.length) return false;
26
+
27
+ // Check each key's value with Object.is
28
+ for (const key of keysA) {
29
+ if (!Object.is((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key])) {
30
+ return false;
31
+ }
32
+ }
33
+
34
+ return true;
35
+ }
@@ -0,0 +1,478 @@
1
+ import type { ReactNode, ComponentType } from "react";
2
+ import type { ResolvedSegment, SlotState } from "../types.js";
3
+ import type { ResolvedThemeConfig, Theme } from "../theme/types.js";
4
+ import type { RenderSegmentsOptions } from "../segment-system.js";
5
+
6
+ // ============================================================================
7
+ // RSC Payload Types
8
+ // ============================================================================
9
+
10
+ /**
11
+ * RSC payload received from server
12
+ */
13
+ export interface RscPayload<TMetadata = RscMetadata> {
14
+ root: ReactNode | Promise<ReactNode> | null;
15
+ metadata?: TMetadata;
16
+ returnValue?: ActionResult;
17
+ formState?: unknown;
18
+ }
19
+
20
+ /**
21
+ * Handle data structure: handleName -> segmentId -> entries[]
22
+ *
23
+ * @internal This type is an implementation detail and may change without notice.
24
+ */
25
+ export type HandleData = Record<string, Record<string, unknown[]>>;
26
+
27
+ /**
28
+ * Metadata included in RSC responses
29
+ *
30
+ * @internal This type is an implementation detail and may change without notice.
31
+ */
32
+ export interface RscMetadata {
33
+ pathname: string;
34
+ segments: ResolvedSegment[];
35
+ isPartial?: boolean;
36
+ isError?: boolean;
37
+ matched?: string[];
38
+ diff?: string[];
39
+ /**
40
+ * State of named slots for this route match
41
+ * Key is slot name (e.g., "@modal"), value is slot state
42
+ * Slots are used for intercepting routes during soft navigation
43
+ */
44
+ slots?: Record<string, SlotState>;
45
+ /** Root layout component for browser-side re-renders */
46
+ rootLayout?: ComponentType<{ children: ReactNode }>;
47
+ /** Handle data accumulated across route segments (async generator that yields on each push) */
48
+ handles?: AsyncGenerator<HandleData, void, unknown>;
49
+ /** Cached handle data (for back/forward navigation from cache) */
50
+ cachedHandleData?: HandleData;
51
+ /**
52
+ * RSC version string from the server.
53
+ * Used to detect version mismatches after HMR/deployment.
54
+ */
55
+ version?: string;
56
+ /**
57
+ * Theme configuration from router.
58
+ * Included when theme is enabled in router config.
59
+ */
60
+ themeConfig?: ResolvedThemeConfig | null;
61
+ /**
62
+ * Initial theme from cookie (for SSR hydration).
63
+ * Included when theme is enabled in router config.
64
+ */
65
+ initialTheme?: Theme;
66
+ /** Whether connection warmup is enabled */
67
+ warmupEnabled?: boolean;
68
+ }
69
+
70
+ /**
71
+ * Result from server action execution
72
+ *
73
+ * @internal This type is an implementation detail and may change without notice.
74
+ */
75
+ export interface ActionResult {
76
+ ok: boolean;
77
+ data: unknown;
78
+ }
79
+
80
+ // ============================================================================
81
+ // Navigation State Types
82
+ // ============================================================================
83
+
84
+ /**
85
+ * Location object representing current URL
86
+ * Uses URL for full URL parsing (origin, host, hostname, port, protocol, searchParams, etc.)
87
+ */
88
+ export type NavigationLocation = URL;
89
+
90
+ /**
91
+ * Inflight server action being tracked
92
+ *
93
+ * @internal This type is an implementation detail and may change without notice.
94
+ */
95
+ export interface InflightAction {
96
+ /** Unique identifier for this action invocation */
97
+ id: string;
98
+ /** Server action function ID */
99
+ actionId: string;
100
+ /** Action arguments */
101
+ payload: unknown[];
102
+ /** Timestamp when action started */
103
+ startedAt: number;
104
+ }
105
+
106
+ /**
107
+ * Internal navigation state (includes inflight actions for store use)
108
+ *
109
+ * @internal This type is an implementation detail. Use PublicNavigationState instead.
110
+ */
111
+ export interface NavigationState {
112
+ /** Navigation lifecycle state (idle or loading during navigation) */
113
+ state: "idle" | "loading";
114
+
115
+ /** Whether RSC data is currently streaming (initial load or navigation) */
116
+ isStreaming: boolean;
117
+
118
+ /** Current location (updated optimistically) */
119
+ location: NavigationLocation;
120
+
121
+ /** URL being navigated to (null when idle) */
122
+ pendingUrl: string | null;
123
+
124
+ /** List of inflight server actions (internal use only) */
125
+ inflightActions: InflightAction[];
126
+ }
127
+
128
+ /**
129
+ * Public navigation state exposed via useNavigation hook
130
+ * Excludes internal properties like inflightActions
131
+ */
132
+ export type PublicNavigationState = Omit<NavigationState, "inflightActions">;
133
+
134
+ // ============================================================================
135
+ // Action State Types (for useAction hook)
136
+ // ============================================================================
137
+
138
+ /**
139
+ * Action lifecycle state
140
+ */
141
+ export type ActionLifecycleState = "idle" | "loading" | "streaming";
142
+
143
+ /**
144
+ * State for a tracked server action
145
+ * Used by useAction hook to observe action lifecycle
146
+ *
147
+ * @internal This type is an implementation detail and may change without notice.
148
+ */
149
+ export interface TrackedActionState {
150
+ /** Current lifecycle state of the action */
151
+ state: ActionLifecycleState;
152
+
153
+ /** Server action function ID (e.g., "addToCart") */
154
+ actionId: string | null;
155
+
156
+ /** Action arguments (array for JSON, FormData for form submissions) */
157
+ payload: unknown[] | FormData | null;
158
+
159
+ /** Error if action failed */
160
+ error: unknown | null;
161
+
162
+ /** Result data from the action (preserved after completion) */
163
+ result: unknown | null;
164
+ }
165
+
166
+ /**
167
+ * Listener for action state changes
168
+ *
169
+ * @internal This type is an implementation detail and may change without notice.
170
+ */
171
+ export type ActionStateListener = (state: TrackedActionState) => void;
172
+
173
+ /**
174
+ * Cache interface for storing segments
175
+ * Compatible with both Map and LRUCache
176
+ *
177
+ * @internal This type is an implementation detail and may change without notice.
178
+ */
179
+ export interface SegmentCache {
180
+ get(key: string): ResolvedSegment | undefined;
181
+ set(key: string, value: ResolvedSegment): void;
182
+ has(key: string): boolean;
183
+ delete(key: string): boolean;
184
+ keys(): IterableIterator<string>;
185
+ readonly size: number;
186
+ }
187
+
188
+ /**
189
+ * Internal segment state managed by the store
190
+ *
191
+ * @internal This type is an implementation detail and may change without notice.
192
+ */
193
+ export interface SegmentState {
194
+ path: string;
195
+ currentUrl: string;
196
+ currentSegmentIds: string[];
197
+ }
198
+
199
+ /**
200
+ * Navigation update emitted when UI should re-render
201
+ *
202
+ * @internal This type is an implementation detail and may change without notice.
203
+ */
204
+ export interface NavigationUpdate {
205
+ root: ReactNode | Promise<ReactNode>;
206
+ metadata: RscMetadata;
207
+ }
208
+
209
+ /**
210
+ * State value for navigate/Link
211
+ * - LocationStateEntry[]: Type-safe state entries (recommended)
212
+ * - unknown: Legacy format for backwards compatibility
213
+ */
214
+ export type HistoryState = import("./react/location-state-shared.js").LocationStateEntry[] | unknown;
215
+
216
+ /**
217
+ * Options for navigation operations
218
+ */
219
+ export interface NavigateOptions {
220
+ replace?: boolean;
221
+ scroll?: boolean;
222
+ /**
223
+ * State to pass to history.pushState/replaceState
224
+ * Accessible via useLocationState() hook.
225
+ *
226
+ * @example
227
+ * ```tsx
228
+ * // Type-safe state (recommended)
229
+ * const ProductState = createLocationState<{ name: string }>("product");
230
+ * navigate("/product/123", { state: [ProductState({ name: "Widget" })] });
231
+ *
232
+ * // Multiple states
233
+ * navigate("/checkout", { state: [ProductState(p), CartState(c)] });
234
+ *
235
+ * // Legacy format (backwards compatible)
236
+ * navigate("/product", { state: { from: "list" } });
237
+ * ```
238
+ */
239
+ state?: HistoryState;
240
+ }
241
+
242
+ // ============================================================================
243
+ // RSC Browser Dependencies
244
+ // ============================================================================
245
+
246
+ /**
247
+ * RSC runtime functions from @vitejs/plugin-rsc/browser
248
+ *
249
+ * These are injected as dependencies to avoid direct coupling
250
+ * to the RSC runtime implementation.
251
+ */
252
+ export interface RscBrowserDependencies {
253
+ createFromFetch: <T>(
254
+ response: Promise<Response>,
255
+ options?: { temporaryReferences?: any }
256
+ ) => Promise<T>;
257
+ createFromReadableStream: <T>(stream: ReadableStream) => Promise<T>;
258
+ encodeReply: (
259
+ args: any[],
260
+ options?: { temporaryReferences?: any }
261
+ ) => Promise<FormData | string>;
262
+ setServerCallback: (
263
+ callback: (id: string, args: any[]) => Promise<any>
264
+ ) => void;
265
+ createTemporaryReferenceSet: () => any;
266
+ }
267
+
268
+ // ============================================================================
269
+ // Store Types
270
+ // ============================================================================
271
+
272
+ /**
273
+ * Update subscriber callback for UI updates
274
+ */
275
+ export type UpdateSubscriber = (update: NavigationUpdate) => void;
276
+
277
+ /**
278
+ * State change listener for useNavigation hook subscriptions
279
+ */
280
+ export type StateListener = () => void;
281
+
282
+ /**
283
+ * Navigation store interface
284
+ *
285
+ * Manages both:
286
+ * - NavigationState: Public state exposed via useNavigation hook
287
+ * - SegmentState: Internal segment management for partial updates
288
+ */
289
+ export interface NavigationStore {
290
+ // Public state (for useNavigation hook)
291
+ getState(): NavigationState;
292
+ setState(partial: Partial<NavigationState>): void;
293
+ subscribe(listener: StateListener): () => void;
294
+
295
+ // Inflight action management
296
+ addInflightAction(action: InflightAction): void;
297
+ removeInflightAction(id: string): void;
298
+
299
+ // Action state (for controlling update behavior during server actions)
300
+ isActionInProgress(): boolean;
301
+ setActionInProgress(value: boolean): void;
302
+
303
+ // Internal segment state (for bridges)
304
+ getSegmentState(): SegmentState;
305
+ setPath(path: string): void;
306
+ setCurrentUrl(url: string): void;
307
+ setSegmentIds(ids: string[]): void;
308
+
309
+ // History-based segment cache (for back/forward navigation and partial merging)
310
+ getHistoryKey(): string;
311
+ setHistoryKey(key: string): void;
312
+ cacheSegmentsForHistory(
313
+ historyKey: string,
314
+ segments: ResolvedSegment[],
315
+ handleData?: HandleData
316
+ ): void;
317
+ getCachedSegments(
318
+ historyKey: string
319
+ ): { segments: ResolvedSegment[]; stale: boolean; handleData?: HandleData } | undefined;
320
+ hasHistoryCache(historyKey: string): boolean;
321
+ updateCacheHandleData(historyKey: string, handleData: HandleData): void;
322
+ markCacheAsStale(): void;
323
+ markCacheAsStaleAndBroadcast(): void;
324
+ clearHistoryCache(): void;
325
+ broadcastCacheInvalidation(): void;
326
+
327
+ // Cross-tab refresh callback (set by navigation bridge)
328
+ setCrossTabRefreshCallback(callback: () => void): void;
329
+
330
+ // Intercept context tracking (for action revalidation)
331
+ getInterceptSourceUrl(): string | null;
332
+ setInterceptSourceUrl(url: string | null): void;
333
+
334
+ // UI update notifications
335
+ onUpdate(callback: UpdateSubscriber): () => void;
336
+ emitUpdate(update: NavigationUpdate): void;
337
+
338
+ // Action state tracking (for useAction hook)
339
+ getActionState(actionId: string): TrackedActionState;
340
+ setActionState(actionId: string, state: Partial<TrackedActionState>): void;
341
+ subscribeToAction(
342
+ actionId: string,
343
+ listener: ActionStateListener
344
+ ): () => void;
345
+ }
346
+
347
+ // ============================================================================
348
+ // Request Controller Types
349
+ // ============================================================================
350
+
351
+ /**
352
+ * Disposable abort controller with automatic cleanup
353
+ */
354
+ export interface DisposableAbortController extends Disposable {
355
+ controller: AbortController;
356
+ }
357
+
358
+ /**
359
+ * Request controller for managing concurrent requests
360
+ *
361
+ * Separates navigation requests (aborted on new navigation) from
362
+ * action requests (complete independently of navigation).
363
+ */
364
+ export interface RequestController {
365
+ create(): AbortController;
366
+ createDisposable(): DisposableAbortController;
367
+ /** Create a disposable controller for actions (not aborted by navigation) */
368
+ createActionDisposable(): DisposableAbortController;
369
+ /** Abort all navigation requests (not actions) */
370
+ abortAll(): void;
371
+ /** Abort all action requests (used for error handling) */
372
+ abortAllActions(): void;
373
+ remove(controller: AbortController): void;
374
+ }
375
+
376
+ // ============================================================================
377
+ // Navigation Client Types
378
+ // ============================================================================
379
+
380
+ /**
381
+ * Options for partial navigation fetch
382
+ */
383
+ export interface FetchPartialOptions {
384
+ targetUrl: string;
385
+ segmentIds: string[];
386
+ previousUrl: string;
387
+ signal?: AbortSignal;
388
+ /** If true, this is a stale cache revalidation request - server should force revalidators */
389
+ staleRevalidation?: boolean;
390
+ interceptSourceUrl?: string;
391
+ /** RSC version for cache invalidation detection */
392
+ version?: string;
393
+ /** If true, this is an HMR refetch - server should invalidate manifest cache */
394
+ hmr?: boolean;
395
+ }
396
+
397
+ /**
398
+ * Result of a partial fetch including stream completion tracking
399
+ */
400
+ export interface FetchPartialResult {
401
+ payload: RscPayload;
402
+ /** Promise that resolves when the response stream is fully consumed */
403
+ streamComplete: Promise<void>;
404
+ }
405
+
406
+ /**
407
+ * Navigation client for fetching RSC payloads
408
+ */
409
+ export interface NavigationClient {
410
+ fetchPartial(options: FetchPartialOptions): Promise<FetchPartialResult>;
411
+ }
412
+
413
+ // ============================================================================
414
+ // Link Interceptor Types
415
+ // ============================================================================
416
+
417
+ /**
418
+ * Options for link interception
419
+ */
420
+ export interface LinkInterceptorOptions {
421
+ shouldIntercept?: (link: HTMLAnchorElement) => boolean;
422
+ }
423
+
424
+ // ============================================================================
425
+ // Server Action Bridge Types
426
+ // ============================================================================
427
+
428
+ /**
429
+ * Server action bridge for handling server actions
430
+ */
431
+ export interface ServerActionBridge {
432
+ register(): void;
433
+ unregister(): void;
434
+ }
435
+
436
+ /**
437
+ * Configuration for server action bridge
438
+ */
439
+ export interface ServerActionBridgeConfig {
440
+ store: NavigationStore;
441
+ client: NavigationClient;
442
+ deps: RscBrowserDependencies;
443
+ onUpdate: UpdateSubscriber;
444
+ renderSegments: (
445
+ segments: ResolvedSegment[],
446
+ options?: RenderSegmentsOptions
447
+ ) => Promise<ReactNode> | ReactNode;
448
+ }
449
+
450
+ // ============================================================================
451
+ // Navigation Bridge Types
452
+ // ============================================================================
453
+
454
+ /**
455
+ * Navigation bridge for handling client-side navigation
456
+ */
457
+ export interface NavigationBridge {
458
+ navigate(url: string, options?: NavigateOptions): Promise<void>;
459
+ refresh(): Promise<void>;
460
+ handlePopstate(): Promise<void>;
461
+ registerLinkInterception(): () => void;
462
+ }
463
+
464
+ /**
465
+ * Configuration for navigation bridge
466
+ */
467
+ export interface NavigationBridgeConfig {
468
+ store: NavigationStore;
469
+ client: NavigationClient;
470
+ onUpdate: UpdateSubscriber;
471
+ renderSegments: (
472
+ segments: ResolvedSegment[],
473
+ options?: RenderSegmentsOptions
474
+ ) => Promise<ReactNode> | ReactNode;
475
+ }
476
+
477
+ // Re-export ResolvedSegment for convenience
478
+ export type { ResolvedSegment };