@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,165 @@
1
+ import type {
2
+ NavigationClient,
3
+ FetchPartialOptions,
4
+ FetchPartialResult,
5
+ RscPayload,
6
+ RscBrowserDependencies,
7
+ } from "./types.js";
8
+ import { NetworkError, isNetworkError } from "../errors.js";
9
+
10
+ /**
11
+ * Create a navigation client for fetching RSC payloads
12
+ *
13
+ * The client handles building URLs with RSC parameters and
14
+ * deserializing the response using the RSC runtime.
15
+ *
16
+ * @param deps - RSC browser dependencies (createFromFetch)
17
+ * @returns NavigationClient instance
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { createFromFetch } from "@vitejs/plugin-rsc/browser";
22
+ *
23
+ * const client = createNavigationClient({ createFromFetch });
24
+ *
25
+ * const payload = await client.fetchPartial({
26
+ * targetUrl: "/shop/products",
27
+ * segmentIds: ["root", "shop"],
28
+ * previousUrl: "/",
29
+ * });
30
+ * ```
31
+ */
32
+ export function createNavigationClient(
33
+ deps: Pick<RscBrowserDependencies, "createFromFetch">,
34
+ ): NavigationClient {
35
+
36
+ return {
37
+ /**
38
+ * Fetch a partial RSC payload for navigation
39
+ *
40
+ * Sends current segment IDs to the server so it can determine
41
+ * which segments need to be re-rendered (diff).
42
+ *
43
+ * @param options - Fetch options
44
+ * @returns RSC payload with segments and metadata, plus stream completion promise
45
+ */
46
+ async fetchPartial(
47
+ options: FetchPartialOptions,
48
+ ): Promise<FetchPartialResult> {
49
+ const {
50
+ targetUrl,
51
+ segmentIds,
52
+ previousUrl,
53
+ signal,
54
+ staleRevalidation,
55
+ interceptSourceUrl,
56
+ version,
57
+ hmr,
58
+ } = options;
59
+
60
+ console.log(`\n[Browser] >>> NAVIGATION`);
61
+ console.log(`[Browser] From: ${previousUrl}`);
62
+ console.log(`[Browser] To: ${targetUrl}`);
63
+ console.log(`[Browser] Segments to send: ${segmentIds.join(", ")}`);
64
+ if (staleRevalidation) {
65
+ console.log(`[Browser] Stale revalidation request`);
66
+ }
67
+
68
+ // Build fetch URL with partial rendering params
69
+ const fetchUrl = new URL(targetUrl, window.location.origin);
70
+ fetchUrl.searchParams.set("_rsc_partial", "true");
71
+ fetchUrl.searchParams.set("_rsc_segments", segmentIds.join(","));
72
+ if (staleRevalidation) {
73
+ fetchUrl.searchParams.set("_rsc_stale", "true");
74
+ }
75
+ if (version) {
76
+ fetchUrl.searchParams.set("_rsc_v", version);
77
+ }
78
+
79
+ console.log(`[Browser] Fetching: ${fetchUrl.pathname}${fetchUrl.search}`);
80
+
81
+ // Track when the stream completes
82
+ let resolveStreamComplete: () => void;
83
+ const streamComplete = new Promise<void>((resolve) => {
84
+ resolveStreamComplete = resolve;
85
+ });
86
+
87
+ // Create a response promise that tracks stream completion
88
+ const responsePromise = fetch(fetchUrl, {
89
+ headers: {
90
+ "X-RSC-Router-Client-Path": previousUrl,
91
+ ...(interceptSourceUrl && {
92
+ "X-RSC-Router-Intercept-Source": interceptSourceUrl,
93
+ }),
94
+ ...(hmr && { "X-RSC-HMR": "1" }),
95
+ },
96
+ signal,
97
+ }).then((response) => {
98
+ // Check for version mismatch - server wants us to reload
99
+ const reloadUrl = response.headers.get("X-RSC-Reload");
100
+ if (reloadUrl) {
101
+ console.log(`[Browser] Version mismatch - reloading: ${reloadUrl}`);
102
+ window.location.href = reloadUrl;
103
+ // Return a never-resolving promise to prevent further processing
104
+ return new Promise<Response>(() => {});
105
+ }
106
+
107
+ if (!response.body) {
108
+ // No body means stream is already complete
109
+ resolveStreamComplete();
110
+ return response;
111
+ }
112
+
113
+ // Tee the stream: one for RSC runtime, one for tracking completion
114
+ const [rscStream, trackingStream] = response.body.tee();
115
+
116
+ // Consume the tracking stream to detect when it closes
117
+ (async () => {
118
+ const reader = trackingStream.getReader();
119
+
120
+ // Cancel tracking if navigation is aborted
121
+ const onAbort = reader.cancel.bind(reader);
122
+ signal?.addEventListener("abort", onAbort, { once: true });
123
+
124
+ try {
125
+ while (true) {
126
+ const { done } = await reader.read();
127
+ if (done) break;
128
+ }
129
+ } finally {
130
+ signal?.removeEventListener("abort", onAbort);
131
+ reader.releaseLock();
132
+ console.log("[STREAMING] RSC stream complete");
133
+ resolveStreamComplete();
134
+ }
135
+ })();
136
+
137
+ // Return response with the RSC stream
138
+ return new Response(rscStream, {
139
+ headers: response.headers,
140
+ status: response.status,
141
+ statusText: response.statusText,
142
+ });
143
+ });
144
+
145
+ try {
146
+ // Deserialize RSC payload
147
+ const payload = await deps.createFromFetch<RscPayload>(responsePromise);
148
+ return { payload, streamComplete };
149
+ } catch (error) {
150
+ // Convert network-level errors to NetworkError for proper handling
151
+ if (isNetworkError(error)) {
152
+ throw new NetworkError(
153
+ "Unable to connect to server. Please check your connection.",
154
+ {
155
+ cause: error,
156
+ url: fetchUrl.toString(),
157
+ operation: staleRevalidation ? "revalidation" : "navigation",
158
+ },
159
+ );
160
+ }
161
+ throw error;
162
+ }
163
+ },
164
+ };
165
+ }