@rangojs/router 0.0.0-experimental.d20dd405 → 0.0.0-experimental.dacec167

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 (212) hide show
  1. package/README.md +8 -8
  2. package/dist/bin/rango.js +147 -57
  3. package/dist/testing/vitest.js +82 -0
  4. package/dist/vite/index.js +914 -485
  5. package/package.json +55 -11
  6. package/skills/bundle-analysis/SKILL.md +159 -0
  7. package/skills/cache-guide/SKILL.md +220 -30
  8. package/skills/caching/SKILL.md +116 -8
  9. package/skills/composability/SKILL.md +27 -2
  10. package/skills/document-cache/SKILL.md +78 -55
  11. package/skills/handler-use/SKILL.md +1 -1
  12. package/skills/hooks/SKILL.md +196 -21
  13. package/skills/host-router/SKILL.md +45 -20
  14. package/skills/intercept/SKILL.md +1 -4
  15. package/skills/layout/SKILL.md +4 -7
  16. package/skills/links/SKILL.md +22 -10
  17. package/skills/loader/SKILL.md +149 -6
  18. package/skills/middleware/SKILL.md +13 -9
  19. package/skills/migrate-nextjs/SKILL.md +1 -1
  20. package/skills/mime-routes/SKILL.md +27 -0
  21. package/skills/observability/SKILL.md +137 -0
  22. package/skills/parallel/SKILL.md +3 -6
  23. package/skills/prerender/SKILL.md +14 -33
  24. package/skills/rango/SKILL.md +242 -26
  25. package/skills/react-compiler/SKILL.md +168 -0
  26. package/skills/response-routes/SKILL.md +58 -9
  27. package/skills/route/SKILL.md +9 -4
  28. package/skills/router-setup/SKILL.md +3 -3
  29. package/skills/server-actions/SKILL.md +53 -41
  30. package/skills/testing/SKILL.md +778 -0
  31. package/skills/typesafety/SKILL.md +310 -26
  32. package/skills/use-cache/SKILL.md +34 -5
  33. package/skills/view-transitions/SKILL.md +85 -3
  34. package/src/__augment-tests__/augment.ts +81 -0
  35. package/src/__augment-tests__/augmented.check.ts +117 -0
  36. package/src/browser/action-coordinator.ts +53 -36
  37. package/src/browser/event-controller.ts +42 -66
  38. package/src/browser/history-state.ts +21 -0
  39. package/src/browser/index.ts +3 -3
  40. package/src/browser/navigation-bridge.ts +9 -67
  41. package/src/browser/navigation-client.ts +12 -15
  42. package/src/browser/navigation-store.ts +7 -8
  43. package/src/browser/navigation-transaction.ts +10 -28
  44. package/src/browser/partial-update.ts +8 -16
  45. package/src/browser/react/NavigationProvider.tsx +55 -65
  46. package/src/browser/react/location-state-shared.ts +175 -4
  47. package/src/browser/react/location-state.ts +39 -13
  48. package/src/browser/react/use-handle.ts +17 -9
  49. package/src/browser/react/use-params.ts +3 -4
  50. package/src/browser/react/use-reverse.ts +19 -12
  51. package/src/browser/react/use-router.ts +14 -1
  52. package/src/browser/response-adapter.ts +25 -0
  53. package/src/browser/rsc-router.tsx +30 -16
  54. package/src/browser/scroll-restoration.ts +30 -25
  55. package/src/browser/segment-structure-assert.ts +2 -2
  56. package/src/browser/server-action-bridge.ts +23 -30
  57. package/src/browser/types.ts +2 -0
  58. package/src/build/collect-fallback-refs.ts +107 -0
  59. package/src/build/generate-manifest.ts +60 -35
  60. package/src/build/generate-route-types.ts +2 -0
  61. package/src/build/index.ts +2 -0
  62. package/src/build/route-types/codegen.ts +4 -4
  63. package/src/build/route-types/include-resolution.ts +1 -1
  64. package/src/build/route-types/per-module-writer.ts +7 -4
  65. package/src/build/route-types/router-processing.ts +55 -14
  66. package/src/build/route-types/scan-filter.ts +1 -1
  67. package/src/build/route-types/source-scan.ts +118 -0
  68. package/src/build/runtime-discovery.ts +9 -20
  69. package/src/cache/cache-scope.ts +28 -42
  70. package/src/cache/cf/cf-cache-store.ts +49 -6
  71. package/src/client.tsx +5 -7
  72. package/src/context-var.ts +5 -5
  73. package/src/decode-loader-results.ts +36 -0
  74. package/src/errors.ts +30 -1
  75. package/src/handle.ts +26 -13
  76. package/src/host/index.ts +2 -2
  77. package/src/host/router.ts +129 -57
  78. package/src/host/types.ts +31 -2
  79. package/src/host/utils.ts +1 -1
  80. package/src/href-client.ts +136 -19
  81. package/src/index.rsc.ts +6 -4
  82. package/src/index.ts +13 -6
  83. package/src/loader-store.ts +500 -0
  84. package/src/loader.rsc.ts +21 -6
  85. package/src/loader.ts +3 -10
  86. package/src/missing-id-error.ts +68 -0
  87. package/src/prerender.ts +4 -4
  88. package/src/response-utils.ts +9 -0
  89. package/src/reverse.ts +16 -13
  90. package/src/route-content-wrapper.tsx +6 -28
  91. package/src/route-definition/dsl-helpers.ts +238 -263
  92. package/src/route-definition/helper-factories.ts +29 -139
  93. package/src/route-definition/helpers-types.ts +37 -14
  94. package/src/route-definition/use-item-types.ts +32 -0
  95. package/src/route-types.ts +19 -41
  96. package/src/router/basename.ts +14 -0
  97. package/src/router/content-negotiation.ts +15 -2
  98. package/src/router/error-handling.ts +1 -1
  99. package/src/router/intercept-resolution.ts +4 -18
  100. package/src/router/lazy-includes.ts +2 -2
  101. package/src/router/loader-resolution.ts +16 -2
  102. package/src/router/match-handlers.ts +62 -20
  103. package/src/router/match-middleware/cache-lookup.ts +44 -91
  104. package/src/router/match-middleware/cache-store.ts +3 -2
  105. package/src/router/match-result.ts +32 -30
  106. package/src/router/metrics.ts +1 -1
  107. package/src/router/middleware-types.ts +1 -1
  108. package/src/router/middleware.ts +46 -78
  109. package/src/router/prerender-match.ts +1 -1
  110. package/src/router/preview-match.ts +3 -1
  111. package/src/router/request-classification.ts +4 -28
  112. package/src/router/revalidation.ts +43 -1
  113. package/src/router/router-interfaces.ts +45 -28
  114. package/src/router/router-options.ts +40 -1
  115. package/src/router/router-registry.ts +2 -5
  116. package/src/router/segment-resolution/fresh.ts +19 -6
  117. package/src/router/segment-resolution/revalidation.ts +19 -6
  118. package/src/router/segment-resolution/view-transition-default.ts +36 -0
  119. package/src/router/telemetry.ts +99 -0
  120. package/src/router/types.ts +8 -0
  121. package/src/router.ts +37 -21
  122. package/src/rsc/handler-context.ts +2 -2
  123. package/src/rsc/handler.ts +20 -65
  124. package/src/rsc/helpers.ts +22 -2
  125. package/src/rsc/index.ts +1 -1
  126. package/src/rsc/origin-guard.ts +28 -10
  127. package/src/rsc/response-route-handler.ts +32 -52
  128. package/src/rsc/rsc-rendering.ts +27 -53
  129. package/src/rsc/runtime-warnings.ts +9 -10
  130. package/src/rsc/server-action.ts +13 -37
  131. package/src/rsc/ssr-setup.ts +16 -0
  132. package/src/rsc/types.ts +2 -2
  133. package/src/search-params.ts +4 -4
  134. package/src/segment-system.tsx +64 -49
  135. package/src/serialize.ts +243 -0
  136. package/src/server/context.ts +118 -51
  137. package/src/server/cookie-store.ts +28 -4
  138. package/src/server/request-context.ts +10 -0
  139. package/src/static-handler.ts +1 -1
  140. package/src/testing/cache-status.ts +166 -0
  141. package/src/testing/collect-handle.ts +63 -0
  142. package/src/testing/dispatch.ts +440 -0
  143. package/src/testing/dom.entry.ts +22 -0
  144. package/src/testing/e2e/fixture.ts +154 -0
  145. package/src/testing/e2e/index.ts +149 -0
  146. package/src/testing/e2e/matchers.ts +51 -0
  147. package/src/testing/e2e/page-helpers.ts +272 -0
  148. package/src/testing/e2e/parity.ts +306 -0
  149. package/src/testing/e2e/server.ts +183 -0
  150. package/src/testing/flight-matchers.ts +104 -0
  151. package/src/testing/flight-runtime.d.ts +57 -0
  152. package/src/testing/flight-tree.ts +320 -0
  153. package/src/testing/flight.entry.ts +39 -0
  154. package/src/testing/flight.ts +197 -0
  155. package/src/testing/generated-routes.ts +223 -0
  156. package/src/testing/index.ts +106 -0
  157. package/src/testing/internal/context.ts +331 -0
  158. package/src/testing/internal/flight-client-globals.ts +30 -0
  159. package/src/testing/render-route.tsx +565 -0
  160. package/src/testing/run-loader.ts +341 -0
  161. package/src/testing/run-middleware.ts +188 -0
  162. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  163. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  164. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  165. package/src/testing/vitest-stubs/version.ts +5 -0
  166. package/src/testing/vitest.ts +270 -0
  167. package/src/types/global-namespace.ts +39 -26
  168. package/src/types/handler-context.ts +56 -11
  169. package/src/types/index.ts +1 -0
  170. package/src/types/segments.ts +18 -1
  171. package/src/urls/include-helper.ts +10 -53
  172. package/src/urls/index.ts +0 -3
  173. package/src/urls/path-helper-types.ts +11 -3
  174. package/src/urls/path-helper.ts +17 -52
  175. package/src/urls/pattern-types.ts +36 -19
  176. package/src/urls/response-types.ts +20 -19
  177. package/src/urls/type-extraction.ts +26 -116
  178. package/src/urls/urls-function.ts +1 -5
  179. package/src/use-loader.tsx +413 -42
  180. package/src/vite/debug.ts +1 -0
  181. package/src/vite/discovery/bundle-postprocess.ts +6 -6
  182. package/src/vite/discovery/discover-routers.ts +70 -48
  183. package/src/vite/discovery/discovery-errors.ts +194 -0
  184. package/src/vite/discovery/prerender-collection.ts +19 -25
  185. package/src/vite/discovery/route-types-writer.ts +40 -84
  186. package/src/vite/discovery/state.ts +33 -0
  187. package/src/vite/discovery/virtual-module-codegen.ts +13 -23
  188. package/src/vite/index.ts +2 -0
  189. package/src/vite/plugin-types.ts +67 -0
  190. package/src/vite/plugins/cjs-to-esm.ts +3 -7
  191. package/src/vite/plugins/client-ref-hashing.ts +12 -1
  192. package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -1
  193. package/src/vite/plugins/expose-action-id.ts +2 -2
  194. package/src/vite/plugins/expose-id-utils.ts +12 -8
  195. package/src/vite/plugins/expose-ids/export-analysis.ts +100 -20
  196. package/src/vite/plugins/expose-ids/handler-transform.ts +8 -61
  197. package/src/vite/plugins/expose-ids/loader-transform.ts +3 -5
  198. package/src/vite/plugins/expose-internal-ids.ts +47 -67
  199. package/src/vite/plugins/performance-tracks.ts +12 -16
  200. package/src/vite/plugins/use-cache-transform.ts +13 -11
  201. package/src/vite/plugins/version-injector.ts +2 -12
  202. package/src/vite/plugins/version-plugin.ts +59 -2
  203. package/src/vite/plugins/virtual-entries.ts +2 -2
  204. package/src/vite/rango.ts +67 -15
  205. package/src/vite/router-discovery.ts +208 -63
  206. package/src/vite/utils/ast-handler-extract.ts +15 -15
  207. package/src/vite/utils/bundle-analysis.ts +4 -2
  208. package/src/vite/utils/client-chunks.ts +190 -0
  209. package/src/vite/utils/forward-user-plugins.ts +193 -0
  210. package/src/vite/utils/manifest-utils.ts +21 -5
  211. package/src/vite/utils/shared-utils.ts +107 -26
  212. package/src/browser/action-response-classifier.ts +0 -99
@@ -26,3 +26,12 @@ export function isWebSocketUpgradeResponse(response: Response): boolean {
26
26
  (response as unknown as { webSocket?: unknown }).webSocket != null
27
27
  );
28
28
  }
29
+
30
+ // Location truthiness (not presence) so an empty `Location: ""` is not a redirect.
31
+ export function isRedirectResponse(response: Response): boolean {
32
+ return (
33
+ response.status >= 300 &&
34
+ response.status < 400 &&
35
+ Boolean(response.headers.get("Location"))
36
+ );
37
+ }
package/src/reverse.ts CHANGED
@@ -231,47 +231,50 @@ export type LocalReverseParams<TPattern extends string> =
231
231
  };
232
232
 
233
233
  /**
234
- * Type-safe local reverse function with dot-prefixed names only.
234
+ * Type-safe local reverse function.
235
235
  *
236
236
  * Returned by `useReverse(routes)` on the client. The route map is the
237
237
  * exposure boundary (a generated `routes` from a `urls()` module) and the
238
- * scope is implicit from that import there is no global namespace, so
239
- * names must be dot-prefixed to mirror `ctx.reverse(".name")`.
238
+ * scope is implicit from that import. Names may be written with or without a
239
+ * leading dot `reverse("post")` and `reverse(".post")` are identical. The dot
240
+ * is a cosmetic readability convention (and parity with `ctx.reverse(".name")`);
241
+ * there is no separate global namespace here, so it carries no meaning.
240
242
  *
241
243
  * @example
242
244
  * ```typescript
243
245
  * const reverse = useReverse(blogRoutes);
244
- * reverse(".index"); // ✓ no params
245
- * reverse(".post", { postId: "hello" }); // ✓ with params
246
- * reverse(".search", {}, { q: "hi" }); // ✓ with search schema
247
- * reverse(".typo"); // compile error
246
+ * reverse("index"); // ✓ no params (dot optional)
247
+ * reverse(".index"); // ✓ identical to the above
248
+ * reverse("post", { postId: "hello" }); // ✓ with params
249
+ * reverse("search", {}, { q: "hi" }); // with search schema
250
+ * reverse("typo"); // ✗ compile error
248
251
  * ```
249
252
  */
250
253
  export type LocalReverseFunction<TLocalRoutes> = {
251
254
  /**
252
- * Dot-prefixed local route without params
255
+ * Route without params (leading dot optional)
253
256
  */
254
257
  <TName extends keyof TLocalRoutes & string>(
255
258
  name: IsEmptyObject<
256
259
  ExtractParams<RoutePatternFor<TLocalRoutes, TName>>
257
260
  > extends true
258
- ? `.${TName}`
261
+ ? TName | `.${TName}`
259
262
  : never,
260
263
  ): string;
261
264
 
262
265
  /**
263
- * Dot-prefixed local route with params
266
+ * Route with params (leading dot optional)
264
267
  */
265
268
  <TName extends keyof TLocalRoutes & string>(
266
- name: `.${TName}`,
269
+ name: TName | `.${TName}`,
267
270
  params: LocalReverseParams<RoutePatternFor<TLocalRoutes, TName>>,
268
271
  ): string;
269
272
 
270
273
  /**
271
- * Dot-prefixed local route with params and search
274
+ * Route with params and search (leading dot optional)
272
275
  */
273
276
  <TName extends keyof TLocalRoutes & string>(
274
- name: `.${TName}`,
277
+ name: TName | `.${TName}`,
275
278
  params: LocalReverseParams<RoutePatternFor<TLocalRoutes, TName>>,
276
279
  search: ResolveSearchSchema<ExtractSearchSchema<TLocalRoutes, TName>>,
277
280
  ): string;
@@ -4,7 +4,7 @@ import { Suspense, use, useId } from "react";
4
4
  import { invariant } from "./errors";
5
5
  import { OutletProvider } from "./outlet-provider.js";
6
6
  import type { ResolvedSegment } from "./types.js";
7
- import { isLoaderDataResult } from "./types.js";
7
+ import { decodeLoaderResults } from "./decode-loader-results.js";
8
8
 
9
9
  /**
10
10
  * Stable async wrapper component for route content
@@ -26,10 +26,6 @@ export function RouteContentWrapper({
26
26
  fallback?: ReactNode;
27
27
  segmentId?: string;
28
28
  }): ReactNode {
29
- if (!content) {
30
- // Already resolved
31
- return content as ReactNode;
32
- }
33
29
  return (
34
30
  <Suspense
35
31
  fallback={fallback ?? null}
@@ -159,28 +155,10 @@ function LoaderResolver({
159
155
  ? use(loaderDataPromise)
160
156
  : loaderDataPromise;
161
157
 
162
- // Build loaderData record from resolved values
163
- const loaderData: Record<string, any> = {};
164
- let loaderErrorFallback: ReactNode = null;
165
-
166
- loaderIds.forEach((id, i) => {
167
- const result = resolvedData[i];
168
-
169
- if (isLoaderDataResult(result)) {
170
- if (result.ok) {
171
- loaderData[id] = result.data;
172
- } else {
173
- if (result.fallback) {
174
- loaderErrorFallback = result.fallback;
175
- } else {
176
- throw new Error(result.error.message);
177
- }
178
- }
179
- } else {
180
- // Legacy format - direct data
181
- loaderData[id] = result;
182
- }
183
- });
158
+ const { loaderData, errorFallback } = decodeLoaderResults(
159
+ resolvedData,
160
+ loaderIds,
161
+ );
184
162
 
185
163
  return (
186
164
  <OutletProvider
@@ -190,7 +168,7 @@ function LoaderResolver({
190
168
  parallel={parallel}
191
169
  loaderData={Object.keys(loaderData).length > 0 ? loaderData : undefined}
192
170
  >
193
- {loaderErrorFallback ?? children}
171
+ {errorFallback ?? children}
194
172
  </OutletProvider>
195
173
  );
196
174
  }