@rangojs/router 0.0.0-experimental.0f44aca1

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 (305) hide show
  1. package/AGENTS.md +5 -0
  2. package/README.md +899 -0
  3. package/dist/bin/rango.js +1601 -0
  4. package/dist/vite/index.js +5214 -0
  5. package/package.json +176 -0
  6. package/skills/breadcrumbs/SKILL.md +250 -0
  7. package/skills/cache-guide/SKILL.md +262 -0
  8. package/skills/caching/SKILL.md +220 -0
  9. package/skills/composability/SKILL.md +172 -0
  10. package/skills/debug-manifest/SKILL.md +112 -0
  11. package/skills/document-cache/SKILL.md +182 -0
  12. package/skills/fonts/SKILL.md +167 -0
  13. package/skills/hooks/SKILL.md +704 -0
  14. package/skills/host-router/SKILL.md +218 -0
  15. package/skills/intercept/SKILL.md +313 -0
  16. package/skills/layout/SKILL.md +310 -0
  17. package/skills/links/SKILL.md +239 -0
  18. package/skills/loader/SKILL.md +596 -0
  19. package/skills/middleware/SKILL.md +339 -0
  20. package/skills/mime-routes/SKILL.md +128 -0
  21. package/skills/parallel/SKILL.md +305 -0
  22. package/skills/prerender/SKILL.md +643 -0
  23. package/skills/rango/SKILL.md +118 -0
  24. package/skills/response-routes/SKILL.md +411 -0
  25. package/skills/route/SKILL.md +385 -0
  26. package/skills/router-setup/SKILL.md +439 -0
  27. package/skills/tailwind/SKILL.md +129 -0
  28. package/skills/theme/SKILL.md +79 -0
  29. package/skills/typesafety/SKILL.md +623 -0
  30. package/skills/use-cache/SKILL.md +324 -0
  31. package/src/__internal.ts +273 -0
  32. package/src/bin/rango.ts +321 -0
  33. package/src/browser/action-coordinator.ts +97 -0
  34. package/src/browser/action-response-classifier.ts +99 -0
  35. package/src/browser/event-controller.ts +899 -0
  36. package/src/browser/history-state.ts +80 -0
  37. package/src/browser/index.ts +18 -0
  38. package/src/browser/intercept-utils.ts +52 -0
  39. package/src/browser/link-interceptor.ts +141 -0
  40. package/src/browser/logging.ts +55 -0
  41. package/src/browser/merge-segment-loaders.ts +134 -0
  42. package/src/browser/navigation-bridge.ts +645 -0
  43. package/src/browser/navigation-client.ts +215 -0
  44. package/src/browser/navigation-store.ts +806 -0
  45. package/src/browser/navigation-transaction.ts +295 -0
  46. package/src/browser/network-error-handler.ts +61 -0
  47. package/src/browser/partial-update.ts +550 -0
  48. package/src/browser/prefetch/cache.ts +146 -0
  49. package/src/browser/prefetch/fetch.ts +135 -0
  50. package/src/browser/prefetch/observer.ts +65 -0
  51. package/src/browser/prefetch/policy.ts +42 -0
  52. package/src/browser/prefetch/queue.ts +88 -0
  53. package/src/browser/rango-state.ts +112 -0
  54. package/src/browser/react/Link.tsx +360 -0
  55. package/src/browser/react/NavigationProvider.tsx +386 -0
  56. package/src/browser/react/ScrollRestoration.tsx +94 -0
  57. package/src/browser/react/context.ts +59 -0
  58. package/src/browser/react/filter-segment-order.ts +11 -0
  59. package/src/browser/react/index.ts +52 -0
  60. package/src/browser/react/location-state-shared.ts +162 -0
  61. package/src/browser/react/location-state.ts +107 -0
  62. package/src/browser/react/mount-context.ts +37 -0
  63. package/src/browser/react/nonce-context.ts +23 -0
  64. package/src/browser/react/shallow-equal.ts +27 -0
  65. package/src/browser/react/use-action.ts +218 -0
  66. package/src/browser/react/use-client-cache.ts +58 -0
  67. package/src/browser/react/use-handle.ts +162 -0
  68. package/src/browser/react/use-href.tsx +40 -0
  69. package/src/browser/react/use-link-status.ts +135 -0
  70. package/src/browser/react/use-mount.ts +31 -0
  71. package/src/browser/react/use-navigation.ts +99 -0
  72. package/src/browser/react/use-params.ts +65 -0
  73. package/src/browser/react/use-pathname.ts +47 -0
  74. package/src/browser/react/use-router.ts +63 -0
  75. package/src/browser/react/use-search-params.ts +56 -0
  76. package/src/browser/react/use-segments.ts +171 -0
  77. package/src/browser/response-adapter.ts +73 -0
  78. package/src/browser/rsc-router.tsx +431 -0
  79. package/src/browser/scroll-restoration.ts +400 -0
  80. package/src/browser/segment-reconciler.ts +216 -0
  81. package/src/browser/segment-structure-assert.ts +83 -0
  82. package/src/browser/server-action-bridge.ts +667 -0
  83. package/src/browser/shallow.ts +40 -0
  84. package/src/browser/types.ts +538 -0
  85. package/src/browser/validate-redirect-origin.ts +29 -0
  86. package/src/build/generate-manifest.ts +438 -0
  87. package/src/build/generate-route-types.ts +36 -0
  88. package/src/build/index.ts +35 -0
  89. package/src/build/route-trie.ts +265 -0
  90. package/src/build/route-types/ast-helpers.ts +25 -0
  91. package/src/build/route-types/ast-route-extraction.ts +98 -0
  92. package/src/build/route-types/codegen.ts +102 -0
  93. package/src/build/route-types/include-resolution.ts +411 -0
  94. package/src/build/route-types/param-extraction.ts +48 -0
  95. package/src/build/route-types/per-module-writer.ts +128 -0
  96. package/src/build/route-types/router-processing.ts +469 -0
  97. package/src/build/route-types/scan-filter.ts +78 -0
  98. package/src/build/runtime-discovery.ts +231 -0
  99. package/src/cache/background-task.ts +34 -0
  100. package/src/cache/cache-key-utils.ts +44 -0
  101. package/src/cache/cache-policy.ts +125 -0
  102. package/src/cache/cache-runtime.ts +338 -0
  103. package/src/cache/cache-scope.ts +382 -0
  104. package/src/cache/cf/cf-cache-store.ts +540 -0
  105. package/src/cache/cf/index.ts +25 -0
  106. package/src/cache/document-cache.ts +369 -0
  107. package/src/cache/handle-capture.ts +81 -0
  108. package/src/cache/handle-snapshot.ts +41 -0
  109. package/src/cache/index.ts +43 -0
  110. package/src/cache/memory-segment-store.ts +328 -0
  111. package/src/cache/profile-registry.ts +73 -0
  112. package/src/cache/read-through-swr.ts +134 -0
  113. package/src/cache/segment-codec.ts +256 -0
  114. package/src/cache/taint.ts +98 -0
  115. package/src/cache/types.ts +342 -0
  116. package/src/client.rsc.tsx +85 -0
  117. package/src/client.tsx +601 -0
  118. package/src/component-utils.ts +76 -0
  119. package/src/components/DefaultDocument.tsx +27 -0
  120. package/src/context-var.ts +86 -0
  121. package/src/debug.ts +243 -0
  122. package/src/default-error-boundary.tsx +88 -0
  123. package/src/deps/browser.ts +8 -0
  124. package/src/deps/html-stream-client.ts +2 -0
  125. package/src/deps/html-stream-server.ts +2 -0
  126. package/src/deps/rsc.ts +10 -0
  127. package/src/deps/ssr.ts +2 -0
  128. package/src/errors.ts +365 -0
  129. package/src/handle.ts +135 -0
  130. package/src/handles/MetaTags.tsx +246 -0
  131. package/src/handles/breadcrumbs.ts +66 -0
  132. package/src/handles/index.ts +7 -0
  133. package/src/handles/meta.ts +264 -0
  134. package/src/host/cookie-handler.ts +165 -0
  135. package/src/host/errors.ts +97 -0
  136. package/src/host/index.ts +53 -0
  137. package/src/host/pattern-matcher.ts +214 -0
  138. package/src/host/router.ts +352 -0
  139. package/src/host/testing.ts +79 -0
  140. package/src/host/types.ts +146 -0
  141. package/src/host/utils.ts +25 -0
  142. package/src/href-client.ts +222 -0
  143. package/src/index.rsc.ts +233 -0
  144. package/src/index.ts +277 -0
  145. package/src/internal-debug.ts +11 -0
  146. package/src/loader.rsc.ts +89 -0
  147. package/src/loader.ts +64 -0
  148. package/src/network-error-thrower.tsx +23 -0
  149. package/src/outlet-context.ts +15 -0
  150. package/src/outlet-provider.tsx +45 -0
  151. package/src/prerender/param-hash.ts +37 -0
  152. package/src/prerender/store.ts +185 -0
  153. package/src/prerender.ts +463 -0
  154. package/src/reverse.ts +330 -0
  155. package/src/root-error-boundary.tsx +289 -0
  156. package/src/route-content-wrapper.tsx +196 -0
  157. package/src/route-definition/dsl-helpers.ts +934 -0
  158. package/src/route-definition/helper-factories.ts +200 -0
  159. package/src/route-definition/helpers-types.ts +430 -0
  160. package/src/route-definition/index.ts +52 -0
  161. package/src/route-definition/redirect.ts +93 -0
  162. package/src/route-definition.ts +1 -0
  163. package/src/route-map-builder.ts +275 -0
  164. package/src/route-name.ts +53 -0
  165. package/src/route-types.ts +259 -0
  166. package/src/router/content-negotiation.ts +116 -0
  167. package/src/router/debug-manifest.ts +72 -0
  168. package/src/router/error-handling.ts +287 -0
  169. package/src/router/find-match.ts +158 -0
  170. package/src/router/handler-context.ts +451 -0
  171. package/src/router/intercept-resolution.ts +395 -0
  172. package/src/router/lazy-includes.ts +234 -0
  173. package/src/router/loader-resolution.ts +420 -0
  174. package/src/router/logging.ts +248 -0
  175. package/src/router/manifest.ts +267 -0
  176. package/src/router/match-api.ts +620 -0
  177. package/src/router/match-context.ts +266 -0
  178. package/src/router/match-handlers.ts +440 -0
  179. package/src/router/match-middleware/background-revalidation.ts +223 -0
  180. package/src/router/match-middleware/cache-lookup.ts +634 -0
  181. package/src/router/match-middleware/cache-store.ts +295 -0
  182. package/src/router/match-middleware/index.ts +81 -0
  183. package/src/router/match-middleware/intercept-resolution.ts +306 -0
  184. package/src/router/match-middleware/segment-resolution.ts +192 -0
  185. package/src/router/match-pipelines.ts +179 -0
  186. package/src/router/match-result.ts +219 -0
  187. package/src/router/metrics.ts +282 -0
  188. package/src/router/middleware-cookies.ts +55 -0
  189. package/src/router/middleware-types.ts +222 -0
  190. package/src/router/middleware.ts +748 -0
  191. package/src/router/pattern-matching.ts +563 -0
  192. package/src/router/prerender-match.ts +402 -0
  193. package/src/router/preview-match.ts +170 -0
  194. package/src/router/revalidation.ts +289 -0
  195. package/src/router/router-context.ts +316 -0
  196. package/src/router/router-interfaces.ts +452 -0
  197. package/src/router/router-options.ts +592 -0
  198. package/src/router/router-registry.ts +24 -0
  199. package/src/router/segment-resolution/fresh.ts +570 -0
  200. package/src/router/segment-resolution/helpers.ts +263 -0
  201. package/src/router/segment-resolution/loader-cache.ts +198 -0
  202. package/src/router/segment-resolution/revalidation.ts +1239 -0
  203. package/src/router/segment-resolution/static-store.ts +67 -0
  204. package/src/router/segment-resolution.ts +21 -0
  205. package/src/router/segment-wrappers.ts +289 -0
  206. package/src/router/telemetry-otel.ts +299 -0
  207. package/src/router/telemetry.ts +300 -0
  208. package/src/router/timeout.ts +148 -0
  209. package/src/router/trie-matching.ts +239 -0
  210. package/src/router/types.ts +170 -0
  211. package/src/router.ts +1002 -0
  212. package/src/rsc/handler-context.ts +45 -0
  213. package/src/rsc/handler.ts +1089 -0
  214. package/src/rsc/helpers.ts +198 -0
  215. package/src/rsc/index.ts +36 -0
  216. package/src/rsc/loader-fetch.ts +209 -0
  217. package/src/rsc/manifest-init.ts +86 -0
  218. package/src/rsc/nonce.ts +32 -0
  219. package/src/rsc/origin-guard.ts +141 -0
  220. package/src/rsc/progressive-enhancement.ts +379 -0
  221. package/src/rsc/response-error.ts +37 -0
  222. package/src/rsc/response-route-handler.ts +347 -0
  223. package/src/rsc/rsc-rendering.ts +235 -0
  224. package/src/rsc/runtime-warnings.ts +42 -0
  225. package/src/rsc/server-action.ts +348 -0
  226. package/src/rsc/ssr-setup.ts +128 -0
  227. package/src/rsc/types.ts +263 -0
  228. package/src/search-params.ts +230 -0
  229. package/src/segment-system.tsx +454 -0
  230. package/src/server/context.ts +591 -0
  231. package/src/server/cookie-store.ts +190 -0
  232. package/src/server/fetchable-loader-store.ts +37 -0
  233. package/src/server/handle-store.ts +308 -0
  234. package/src/server/loader-registry.ts +133 -0
  235. package/src/server/request-context.ts +914 -0
  236. package/src/server/root-layout.tsx +10 -0
  237. package/src/server/tsconfig.json +14 -0
  238. package/src/server.ts +51 -0
  239. package/src/ssr/index.tsx +365 -0
  240. package/src/static-handler.ts +114 -0
  241. package/src/theme/ThemeProvider.tsx +297 -0
  242. package/src/theme/ThemeScript.tsx +61 -0
  243. package/src/theme/constants.ts +62 -0
  244. package/src/theme/index.ts +48 -0
  245. package/src/theme/theme-context.ts +44 -0
  246. package/src/theme/theme-script.ts +155 -0
  247. package/src/theme/types.ts +182 -0
  248. package/src/theme/use-theme.ts +44 -0
  249. package/src/types/boundaries.ts +158 -0
  250. package/src/types/cache-types.ts +198 -0
  251. package/src/types/error-types.ts +192 -0
  252. package/src/types/global-namespace.ts +100 -0
  253. package/src/types/handler-context.ts +687 -0
  254. package/src/types/index.ts +88 -0
  255. package/src/types/loader-types.ts +183 -0
  256. package/src/types/route-config.ts +170 -0
  257. package/src/types/route-entry.ts +102 -0
  258. package/src/types/segments.ts +148 -0
  259. package/src/types.ts +1 -0
  260. package/src/urls/include-helper.ts +197 -0
  261. package/src/urls/index.ts +53 -0
  262. package/src/urls/path-helper-types.ts +339 -0
  263. package/src/urls/path-helper.ts +329 -0
  264. package/src/urls/pattern-types.ts +95 -0
  265. package/src/urls/response-types.ts +106 -0
  266. package/src/urls/type-extraction.ts +372 -0
  267. package/src/urls/urls-function.ts +98 -0
  268. package/src/urls.ts +1 -0
  269. package/src/use-loader.tsx +354 -0
  270. package/src/vite/discovery/bundle-postprocess.ts +184 -0
  271. package/src/vite/discovery/discover-routers.ts +344 -0
  272. package/src/vite/discovery/prerender-collection.ts +385 -0
  273. package/src/vite/discovery/route-types-writer.ts +258 -0
  274. package/src/vite/discovery/self-gen-tracking.ts +47 -0
  275. package/src/vite/discovery/state.ts +110 -0
  276. package/src/vite/discovery/virtual-module-codegen.ts +203 -0
  277. package/src/vite/index.ts +16 -0
  278. package/src/vite/plugin-types.ts +131 -0
  279. package/src/vite/plugins/cjs-to-esm.ts +93 -0
  280. package/src/vite/plugins/client-ref-dedup.ts +115 -0
  281. package/src/vite/plugins/client-ref-hashing.ts +105 -0
  282. package/src/vite/plugins/expose-action-id.ts +365 -0
  283. package/src/vite/plugins/expose-id-utils.ts +287 -0
  284. package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
  285. package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
  286. package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
  287. package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
  288. package/src/vite/plugins/expose-ids/types.ts +45 -0
  289. package/src/vite/plugins/expose-internal-ids.ts +569 -0
  290. package/src/vite/plugins/refresh-cmd.ts +65 -0
  291. package/src/vite/plugins/use-cache-transform.ts +323 -0
  292. package/src/vite/plugins/version-injector.ts +83 -0
  293. package/src/vite/plugins/version-plugin.ts +254 -0
  294. package/src/vite/plugins/version.d.ts +12 -0
  295. package/src/vite/plugins/virtual-entries.ts +123 -0
  296. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  297. package/src/vite/rango.ts +510 -0
  298. package/src/vite/router-discovery.ts +785 -0
  299. package/src/vite/utils/ast-handler-extract.ts +517 -0
  300. package/src/vite/utils/banner.ts +36 -0
  301. package/src/vite/utils/bundle-analysis.ts +137 -0
  302. package/src/vite/utils/manifest-utils.ts +70 -0
  303. package/src/vite/utils/package-resolution.ts +121 -0
  304. package/src/vite/utils/prerender-utils.ts +189 -0
  305. package/src/vite/utils/shared-utils.ts +169 -0
package/src/index.ts ADDED
@@ -0,0 +1,277 @@
1
+ /**
2
+ * @rangojs/router
3
+ *
4
+ * Single user-facing entrypoint for all router APIs.
5
+ *
6
+ * The "react-server" export condition selects index.rsc.ts (real implementations)
7
+ * vs this file (client stubs for server-only functions).
8
+ *
9
+ * For client-only exports (Outlet, useOutlet, hooks, components):
10
+ * import from "@rangojs/router/client"
11
+ */
12
+
13
+ // Error classes (can be used on both server and client)
14
+ export {
15
+ RouteNotFoundError,
16
+ DataNotFoundError,
17
+ notFound,
18
+ MiddlewareError,
19
+ HandlerError,
20
+ BuildError,
21
+ InvalidHandlerError,
22
+ RouterError,
23
+ Skip,
24
+ isSkip,
25
+ } from "./errors.js";
26
+
27
+ // Types (safe to import anywhere - no runtime code)
28
+ export type {
29
+ // Configuration types
30
+ DocumentProps,
31
+ DefaultEnv,
32
+ RouteDefinition,
33
+ RouteConfig,
34
+ RouteDefinitionOptions,
35
+ TrailingSlashMode,
36
+ // Handler types
37
+ Handler, // Supports params object, path pattern, or route name
38
+ HandlerContext,
39
+ ExtractParams,
40
+ GenericParams,
41
+ // Middleware types
42
+ Middleware,
43
+ // Revalidation types
44
+ RevalidateParams,
45
+ Revalidate,
46
+ RouteKeys,
47
+ // Loader types
48
+ LoaderDefinition,
49
+ LoaderFn,
50
+ LoaderContext,
51
+ FetchableLoaderOptions,
52
+ LoadOptions,
53
+ // Error boundary types
54
+ ErrorInfo,
55
+ ErrorBoundaryFallbackProps,
56
+ ErrorBoundaryHandler,
57
+ ClientErrorBoundaryFallbackProps,
58
+ // NotFound boundary types
59
+ NotFoundInfo,
60
+ NotFoundBoundaryFallbackProps,
61
+ NotFoundBoundaryHandler,
62
+ // Error handling callback types
63
+ ErrorPhase,
64
+ OnErrorContext,
65
+ OnErrorCallback,
66
+ } from "./types.js";
67
+
68
+ // Search params schema types
69
+ export type {
70
+ SearchSchema,
71
+ SearchSchemaValue,
72
+ ResolveSearchSchema,
73
+ RouteSearchParams,
74
+ RouteParams,
75
+ } from "./search-params.js";
76
+
77
+ // Client-safe createLoader - only stores the $$id, function is not included
78
+ // Use this when defining loaders that will be imported by client components
79
+ export { createLoader } from "./loader.js";
80
+
81
+ // Route definition types (safe to import anywhere)
82
+ export type { RouteHelpers, RouteHandlers } from "./route-definition.js";
83
+ export type { TransitionConfig, ViewTransitionClass } from "./types.js";
84
+
85
+ // Composition types for reusable callback factories
86
+ export type {
87
+ RouteUseItem,
88
+ LayoutUseItem,
89
+ AllUseItems,
90
+ UseItems,
91
+ } from "./route-types.js";
92
+
93
+ // Response route types (usable in both server and client contexts)
94
+ export type {
95
+ ResponseHandler,
96
+ ResponseHandlerContext,
97
+ JsonResponseHandler,
98
+ TextResponseHandler,
99
+ JsonValue,
100
+ ResponsePathFn,
101
+ JsonResponsePathFn,
102
+ TextResponsePathFn,
103
+ RouteResponse,
104
+ ResponseError,
105
+ ResponseEnvelope,
106
+ } from "./urls.js";
107
+
108
+ // Middleware context types
109
+ export type { MiddlewareContext, CookieOptions } from "./router/middleware.js";
110
+
111
+ function serverOnlyStubError(name: string): Error {
112
+ return new Error(
113
+ `${name}() is only available from "@rangojs/router" in a react-server/RSC environment. ` +
114
+ `For client hooks and components, import from "@rangojs/router/client".`,
115
+ );
116
+ }
117
+
118
+ /**
119
+ * Error-throwing stub for server-only `urls` function.
120
+ */
121
+ export function urls(): never {
122
+ throw serverOnlyStubError("urls");
123
+ }
124
+
125
+ /**
126
+ * Error-throwing stub for server-only `createRouter` function.
127
+ */
128
+ export function createRouter(): never {
129
+ throw serverOnlyStubError("createRouter");
130
+ }
131
+
132
+ /**
133
+ * Error-throwing stub for server-only `redirect` function.
134
+ */
135
+ export function redirect(): never {
136
+ throw serverOnlyStubError("redirect");
137
+ }
138
+
139
+ // Handle API (universal - works on both server and client)
140
+ export { createHandle, isHandle, type Handle } from "./handle.js";
141
+
142
+ // Context variable API (typed ctx.set/ctx.get tokens)
143
+ export { createVar, type ContextVar } from "./context-var.js";
144
+
145
+ // CSP nonce token (use with ctx.get(nonce) in middleware/handlers)
146
+ export { nonce } from "./rsc/nonce.js";
147
+
148
+ /**
149
+ * Error-throwing stub for server-only `Prerender` function.
150
+ */
151
+ export function Prerender(): never {
152
+ throw serverOnlyStubError("Prerender");
153
+ }
154
+
155
+ /**
156
+ * Error-throwing stub for server-only `Static` function.
157
+ */
158
+ export function Static(): never {
159
+ throw serverOnlyStubError("Static");
160
+ }
161
+
162
+ /**
163
+ * Error-throwing stub for server-only `getRequestContext` function.
164
+ */
165
+ export function getRequestContext(): never {
166
+ throw serverOnlyStubError("getRequestContext");
167
+ }
168
+
169
+ /**
170
+ * Error-throwing stub for server-only `cookies` function.
171
+ */
172
+ export function cookies(): never {
173
+ throw serverOnlyStubError("cookies");
174
+ }
175
+
176
+ /**
177
+ * Error-throwing stub for server-only `headers` function.
178
+ */
179
+ export function headers(): never {
180
+ throw serverOnlyStubError("headers");
181
+ }
182
+
183
+ /**
184
+ * Error-throwing stub for server-only `createReverse` function.
185
+ */
186
+ export function createReverse(): never {
187
+ throw serverOnlyStubError("createReverse");
188
+ }
189
+
190
+ // Error-throwing stubs for server-only route helpers
191
+ export function layout(): never {
192
+ throw serverOnlyStubError("layout");
193
+ }
194
+ export function cache(): never {
195
+ throw serverOnlyStubError("cache");
196
+ }
197
+ export function middleware(): never {
198
+ throw serverOnlyStubError("middleware");
199
+ }
200
+ export function revalidate(): never {
201
+ throw serverOnlyStubError("revalidate");
202
+ }
203
+ export function loader(): never {
204
+ throw serverOnlyStubError("loader");
205
+ }
206
+ export function loading(): never {
207
+ throw serverOnlyStubError("loading");
208
+ }
209
+ export function parallel(): never {
210
+ throw serverOnlyStubError("parallel");
211
+ }
212
+ export function intercept(): never {
213
+ throw serverOnlyStubError("intercept");
214
+ }
215
+ export function when(): never {
216
+ throw serverOnlyStubError("when");
217
+ }
218
+ export function errorBoundary(): never {
219
+ throw serverOnlyStubError("errorBoundary");
220
+ }
221
+ export function notFoundBoundary(): never {
222
+ throw serverOnlyStubError("notFoundBoundary");
223
+ }
224
+ export function transition(): never {
225
+ throw serverOnlyStubError("transition");
226
+ }
227
+
228
+ // Request context type (safe for client)
229
+ export type { PublicRequestContext as RequestContext } from "./server/request-context.js";
230
+
231
+ // Cookie store types (safe for client)
232
+ export type {
233
+ CookieStore,
234
+ Cookie,
235
+ ReadonlyHeaders,
236
+ } from "./server/cookie-store.js";
237
+
238
+ // Meta types
239
+ export type { MetaDescriptor, MetaDescriptorBase } from "./router/types.js";
240
+
241
+ // Breadcrumb types
242
+ export type { BreadcrumbItem } from "./handles/breadcrumbs.js";
243
+
244
+ // Reverse type utilities for type-safe URL generation (Django-style URL reversal)
245
+ export type {
246
+ ScopedReverseFunction,
247
+ ReverseFunction,
248
+ ExtractLocalRoutes,
249
+ ParamsFor,
250
+ } from "./reverse.js";
251
+ // scopedReverse() helper for handlers to get locally-typed reverse
252
+ export { scopedReverse } from "./reverse.js";
253
+
254
+ // Location state (universal - works on both server and client)
255
+ export {
256
+ createLocationState,
257
+ type LocationStateDefinition,
258
+ type LocationStateEntry,
259
+ type LocationStateOptions,
260
+ } from "./browser/react/location-state-shared.js";
261
+
262
+ // Path-based response type lookup from RegisteredRoutes
263
+ export type { PathResponse } from "./href-client.js";
264
+
265
+ // Telemetry sink
266
+ export { createConsoleSink } from "./router/telemetry.js";
267
+ export { createOTelSink } from "./router/telemetry-otel.js";
268
+ export type { OTelTracer, OTelSpan } from "./router/telemetry-otel.js";
269
+ export type { TelemetrySink, TelemetryEvent } from "./router/telemetry.js";
270
+
271
+ // Timeout types and error class
272
+ export { RouterTimeoutError } from "./router/timeout.js";
273
+ export type {
274
+ RouterTimeouts,
275
+ TimeoutPhase,
276
+ TimeoutContext,
277
+ } from "./router/timeout.js";
@@ -0,0 +1,11 @@
1
+ // Internal debug gate. Enable with INTERNAL_RANGO_DEBUG=1 in the environment.
2
+ // Uses a Vite define (__RANGO_DEBUG__) for compile-time injection so it works
3
+ // in all runtimes including Cloudflare Workers where process.env is unavailable.
4
+ // Falls back to process.env for non-Vite contexts (tests, direct Node usage).
5
+ export const INTERNAL_RANGO_DEBUG: boolean =
6
+ typeof __RANGO_DEBUG__ !== "undefined"
7
+ ? __RANGO_DEBUG__
8
+ : typeof process !== "undefined" &&
9
+ Boolean((process as any).env?.INTERNAL_RANGO_DEBUG);
10
+
11
+ declare const __RANGO_DEBUG__: boolean;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * rsc-router/loader (RSC/server version)
3
+ *
4
+ * Server-side createLoader implementation with full loader functionality.
5
+ * Only used in react-server context via export conditions.
6
+ *
7
+ * For non-fetchable loaders: returns a loader definition with fn included
8
+ * For fetchable loaders: stores fn in registry and returns a serializable loader
9
+ *
10
+ * The $$id is injected by the Vite exposeInternalIds plugin as a hidden parameter.
11
+ * Users don't need to pass any name - IDs are auto-generated from file path.
12
+ */
13
+
14
+ import type {
15
+ FetchableLoaderOptions,
16
+ LoaderDefinition,
17
+ LoaderFn,
18
+ } from "./types.js";
19
+ import type { MiddlewareFn } from "./router/middleware.js";
20
+ import {
21
+ registerFetchableLoader,
22
+ getFetchableLoader,
23
+ } from "./server/fetchable-loader-store.js";
24
+
25
+ export { getFetchableLoader };
26
+
27
+ // Overload 1: With function only (not fetchable)
28
+ export function createLoader<T>(
29
+ fn: LoaderFn<T, Record<string, string | undefined>, any>,
30
+ ): LoaderDefinition<Awaited<T>, Record<string, string | undefined>>;
31
+
32
+ // Overload 2: Fetchable with `true` (no middleware)
33
+ export function createLoader<T>(
34
+ fn: LoaderFn<T, Record<string, string | undefined>, any>,
35
+ fetchable: true,
36
+ ): LoaderDefinition<Awaited<T>, Record<string, string | undefined>>;
37
+
38
+ // Overload 3: Fetchable with middleware options
39
+ export function createLoader<T>(
40
+ fn: LoaderFn<T, Record<string, string | undefined>, any>,
41
+ options: FetchableLoaderOptions,
42
+ ): LoaderDefinition<Awaited<T>, Record<string, string | undefined>>;
43
+
44
+ // Implementation - the $$id parameter is injected by Vite plugin, not user-provided
45
+ export function createLoader<T>(
46
+ fn: LoaderFn<T, Record<string, string | undefined>, any>,
47
+ fetchable?: true | FetchableLoaderOptions,
48
+ // Hidden parameter injected by Vite exposeInternalIds plugin
49
+ __injectedId?: string,
50
+ ): LoaderDefinition<Awaited<T>, Record<string, string | undefined>> {
51
+ // The $$id will be set on the returned object by Vite plugin
52
+ // For fetchable loaders, __injectedId is also passed as a parameter
53
+ const loaderId = __injectedId || "";
54
+
55
+ if (!loaderId && process.env.NODE_ENV === "development") {
56
+ throw new Error(
57
+ "[rsc-router] Loader is missing $$id. " +
58
+ "Make sure the exposeInternalIds Vite plugin is enabled and " +
59
+ "the loader is exported with: export const MyLoader = createLoader(...)",
60
+ );
61
+ }
62
+
63
+ // If not fetchable, store fn in registry (for SSR ctx.use() resolution)
64
+ // but mark fetchable=false so the _rsc_loader endpoint rejects it.
65
+ if (fetchable === undefined) {
66
+ if (fn && loaderId) {
67
+ registerFetchableLoader(loaderId, fn, [], false);
68
+ }
69
+ return {
70
+ __brand: "loader",
71
+ $$id: loaderId,
72
+ };
73
+ }
74
+
75
+ // Fetchable loader - store fn in registry and return a serializable object
76
+ const middleware: MiddlewareFn[] =
77
+ fetchable === true ? [] : fetchable?.middleware || [];
78
+
79
+ // Register the function in the internal registry by $$id (server-side only)
80
+ // The loader fetch handler looks it up by $$id when load() is called from the client.
81
+ if (fn && loaderId) {
82
+ registerFetchableLoader(loaderId, fn, middleware, true);
83
+ }
84
+
85
+ return {
86
+ __brand: "loader",
87
+ $$id: loaderId,
88
+ };
89
+ }
package/src/loader.ts ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * rsc-router/loader (client version)
3
+ *
4
+ * Client-only stub for createLoader. Returns a minimal loader definition
5
+ * ({ __brand, $$id }) that can be passed to hooks like useLoader.
6
+ * The actual loader function is not included -- it only exists on the server.
7
+ *
8
+ * For export-only loader files, the Vite plugin replaces the entire file with
9
+ * object literals (bypassing this function). Those stubs only contain
10
+ * { __brand, $$id }.
11
+ * This function only runs when loaders are in mixed files (not export-only).
12
+ *
13
+ * The $$id is injected by the Vite exposeInternalIds plugin.
14
+ */
15
+
16
+ import type {
17
+ FetchableLoaderOptions,
18
+ LoaderDefinition,
19
+ LoaderFn,
20
+ } from "./types.js";
21
+
22
+ // Overload 1: With function only (not fetchable)
23
+ export function createLoader<T>(
24
+ fn: LoaderFn<T, Record<string, string | undefined>, any>,
25
+ ): LoaderDefinition<Awaited<T>, Record<string, string | undefined>>;
26
+
27
+ // Overload 2: Fetchable with `true` (no middleware)
28
+ export function createLoader<T>(
29
+ fn: LoaderFn<T, Record<string, string | undefined>, any>,
30
+ fetchable: true,
31
+ ): LoaderDefinition<Awaited<T>, Record<string, string | undefined>>;
32
+
33
+ // Overload 3: Fetchable with middleware options
34
+ export function createLoader<T>(
35
+ fn: LoaderFn<T, Record<string, string | undefined>, any>,
36
+ options: FetchableLoaderOptions,
37
+ ): LoaderDefinition<Awaited<T>, Record<string, string | undefined>>;
38
+
39
+ // Implementation - client stub that just returns the loader definition
40
+ // The $$id parameter is injected by Vite plugin, not user-provided
41
+ //
42
+ // NOTE: For export-only loader files, the Vite plugin replaces the entire
43
+ // file with object literals (bypassing this function). This function only
44
+ // runs when loaders are in mixed files (not export-only).
45
+ export function createLoader<T>(
46
+ _fn: LoaderFn<T, Record<string, string | undefined>, any>,
47
+ _fetchable?: true | FetchableLoaderOptions,
48
+ __injectedId?: string,
49
+ ): LoaderDefinition<Awaited<T>, Record<string, string | undefined>> {
50
+ const loaderId = __injectedId || "";
51
+
52
+ if (!loaderId && process.env.NODE_ENV === "development") {
53
+ throw new Error(
54
+ "[rsc-router] Loader is missing $$id. " +
55
+ "Make sure the exposeInternalIds Vite plugin is enabled and " +
56
+ "the loader is exported with: export const MyLoader = createLoader(...)",
57
+ );
58
+ }
59
+
60
+ return {
61
+ __brand: "loader",
62
+ $$id: loaderId,
63
+ };
64
+ }
@@ -0,0 +1,23 @@
1
+ "use client";
2
+
3
+ import type { ReactNode } from "react";
4
+ import type { NetworkError } from "./errors.js";
5
+
6
+ interface NetworkErrorThrowerProps {
7
+ error: NetworkError;
8
+ }
9
+
10
+ /**
11
+ * Client component that throws a NetworkError during render.
12
+ * Used to trigger the root error boundary when a network error occurs
13
+ * during navigation or server actions.
14
+ *
15
+ * This must be a separate component because:
16
+ * 1. Errors must be thrown during React's render phase to be caught by error boundaries
17
+ * 2. The error occurs in async code (fetch), so we need to propagate it to React's render
18
+ */
19
+ export function NetworkErrorThrower({
20
+ error,
21
+ }: NetworkErrorThrowerProps): ReactNode {
22
+ throw error;
23
+ }
@@ -0,0 +1,15 @@
1
+ import { Context, createContext, type ReactNode } from "react";
2
+ import type { ResolvedSegment } from "./types";
3
+
4
+ export interface OutletContextValue {
5
+ content: ReactNode;
6
+ parallel?: ResolvedSegment[];
7
+ segment?: ResolvedSegment;
8
+ loaderData?: Record<string, any>;
9
+ parent?: OutletContextValue | null;
10
+ /** Loading component for Suspense fallback (from segment's loading() definition) */
11
+ loading?: ReactNode;
12
+ }
13
+
14
+ export const OutletContext: Context<OutletContextValue | null> =
15
+ createContext<OutletContextValue | null>(null);
@@ -0,0 +1,45 @@
1
+ "use client";
2
+
3
+ import { useContext, useMemo, type ReactNode } from "react";
4
+ import { OutletContext, type OutletContextValue } from "./outlet-context.js";
5
+ import type { ResolvedSegment } from "./types.js";
6
+
7
+ /**
8
+ * Provider for outlet content - used internally by renderSegments
9
+ *
10
+ * Stores a reference to parent context so useLoader can walk up the chain
11
+ * to find loader data from parent layouts. If this segment defines a loading
12
+ * component, Outlet will wrap content with Suspense using that as fallback.
13
+ */
14
+ export function OutletProvider({
15
+ content,
16
+ parallel,
17
+ segment,
18
+ loaderData,
19
+ children,
20
+ }: {
21
+ content: ReactNode;
22
+ parallel?: ResolvedSegment[];
23
+ segment?: ResolvedSegment;
24
+ loaderData?: Record<string, any>;
25
+ children: ReactNode;
26
+ }): ReactNode {
27
+ // Get parent context to enable walking up the chain for loader lookups
28
+ const parentContext = useContext(OutletContext);
29
+
30
+ const value = useMemo(
31
+ () => ({
32
+ content,
33
+ parallel,
34
+ segment,
35
+ loaderData,
36
+ parent: parentContext,
37
+ loading: segment?.loading,
38
+ }),
39
+ [content, parallel, segment, loaderData, parentContext],
40
+ );
41
+
42
+ return (
43
+ <OutletContext.Provider value={value}>{children}</OutletContext.Provider>
44
+ );
45
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Deterministic param hashing for prerender storage keys.
3
+ *
4
+ * Used at build time (child process) to generate filenames and at
5
+ * runtime (worker) to look up pre-rendered data. Both environments
6
+ * must produce identical hashes for the same params.
7
+ *
8
+ * Uses a simple DJB2-based hash that works in all JS environments
9
+ * (Node.js, Cloudflare Workers, browsers) without crypto imports.
10
+ */
11
+
12
+ /**
13
+ * Compute a deterministic hash string from route params.
14
+ * For static routes (no params), returns "_".
15
+ */
16
+ export function hashParams(params: Record<string, string>): string {
17
+ const entries = Object.entries(params);
18
+ if (entries.length === 0) return "_";
19
+
20
+ const sorted = entries.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
21
+ const str = sorted
22
+ .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
23
+ .join("&");
24
+ return djb2Hex(str);
25
+ }
26
+
27
+ /**
28
+ * DJB2 hash returning an 8-char hex string.
29
+ * Deterministic across all JS runtimes.
30
+ */
31
+ function djb2Hex(str: string): string {
32
+ let hash = 5381;
33
+ for (let i = 0; i < str.length; i++) {
34
+ hash = ((hash << 5) + hash + str.charCodeAt(i)) >>> 0;
35
+ }
36
+ return hash.toString(16).padStart(8, "0");
37
+ }