@rangojs/router 0.0.0-experimental.10 → 0.0.0-experimental.100

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 (329) hide show
  1. package/AGENTS.md +9 -0
  2. package/README.md +1037 -4
  3. package/dist/bin/rango.js +1619 -157
  4. package/dist/vite/index.js +5762 -2301
  5. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  6. package/package.json +71 -63
  7. package/skills/breadcrumbs/SKILL.md +252 -0
  8. package/skills/cache-guide/SKILL.md +294 -0
  9. package/skills/caching/SKILL.md +93 -23
  10. package/skills/composability/SKILL.md +172 -0
  11. package/skills/debug-manifest/SKILL.md +12 -8
  12. package/skills/document-cache/SKILL.md +18 -16
  13. package/skills/fonts/SKILL.md +6 -4
  14. package/skills/handler-use/SKILL.md +364 -0
  15. package/skills/hooks/SKILL.md +367 -71
  16. package/skills/host-router/SKILL.md +218 -0
  17. package/skills/i18n/SKILL.md +276 -0
  18. package/skills/intercept/SKILL.md +176 -8
  19. package/skills/layout/SKILL.md +124 -3
  20. package/skills/links/SKILL.md +304 -25
  21. package/skills/loader/SKILL.md +474 -47
  22. package/skills/middleware/SKILL.md +207 -37
  23. package/skills/migrate-nextjs/SKILL.md +562 -0
  24. package/skills/migrate-react-router/SKILL.md +769 -0
  25. package/skills/mime-routes/SKILL.md +15 -11
  26. package/skills/parallel/SKILL.md +272 -1
  27. package/skills/prerender/SKILL.md +467 -65
  28. package/skills/rango/SKILL.md +89 -21
  29. package/skills/response-routes/SKILL.md +152 -91
  30. package/skills/route/SKILL.md +305 -14
  31. package/skills/router-setup/SKILL.md +210 -32
  32. package/skills/server-actions/SKILL.md +739 -0
  33. package/skills/streams-and-websockets/SKILL.md +283 -0
  34. package/skills/theme/SKILL.md +9 -8
  35. package/skills/typesafety/SKILL.md +333 -86
  36. package/skills/use-cache/SKILL.md +324 -0
  37. package/skills/view-transitions/SKILL.md +212 -0
  38. package/src/__internal.ts +102 -4
  39. package/src/bin/rango.ts +312 -15
  40. package/src/browser/action-coordinator.ts +97 -0
  41. package/src/browser/action-response-classifier.ts +99 -0
  42. package/src/browser/app-shell.ts +52 -0
  43. package/src/browser/app-version.ts +14 -0
  44. package/src/browser/event-controller.ts +136 -68
  45. package/src/browser/history-state.ts +80 -0
  46. package/src/browser/intercept-utils.ts +52 -0
  47. package/src/browser/link-interceptor.ts +24 -4
  48. package/src/browser/logging.ts +55 -0
  49. package/src/browser/merge-segment-loaders.ts +20 -12
  50. package/src/browser/navigation-bridge.ts +374 -561
  51. package/src/browser/navigation-client.ts +228 -70
  52. package/src/browser/navigation-store.ts +97 -55
  53. package/src/browser/navigation-transaction.ts +297 -0
  54. package/src/browser/network-error-handler.ts +61 -0
  55. package/src/browser/partial-update.ts +376 -315
  56. package/src/browser/prefetch/cache.ts +314 -0
  57. package/src/browser/prefetch/fetch.ts +282 -0
  58. package/src/browser/prefetch/observer.ts +65 -0
  59. package/src/browser/prefetch/policy.ts +48 -0
  60. package/src/browser/prefetch/queue.ts +191 -0
  61. package/src/browser/prefetch/resource-ready.ts +77 -0
  62. package/src/browser/rango-state.ts +152 -0
  63. package/src/browser/react/Link.tsx +255 -71
  64. package/src/browser/react/NavigationProvider.tsx +152 -24
  65. package/src/browser/react/context.ts +11 -0
  66. package/src/browser/react/filter-segment-order.ts +55 -0
  67. package/src/browser/react/index.ts +15 -12
  68. package/src/browser/react/location-state-shared.ts +95 -53
  69. package/src/browser/react/location-state.ts +60 -15
  70. package/src/browser/react/mount-context.ts +6 -1
  71. package/src/browser/react/nonce-context.ts +23 -0
  72. package/src/browser/react/shallow-equal.ts +27 -0
  73. package/src/browser/react/use-action.ts +29 -51
  74. package/src/browser/react/use-client-cache.ts +5 -3
  75. package/src/browser/react/use-handle.ts +30 -120
  76. package/src/browser/react/use-link-status.ts +6 -5
  77. package/src/browser/react/use-navigation.ts +44 -65
  78. package/src/browser/react/use-params.ts +78 -0
  79. package/src/browser/react/use-pathname.ts +47 -0
  80. package/src/browser/react/use-reverse.ts +99 -0
  81. package/src/browser/react/use-router.ts +83 -0
  82. package/src/browser/react/use-search-params.ts +56 -0
  83. package/src/browser/react/use-segments.ts +85 -99
  84. package/src/browser/response-adapter.ts +73 -0
  85. package/src/browser/rsc-router.tsx +246 -64
  86. package/src/browser/scroll-restoration.ts +127 -52
  87. package/src/browser/segment-reconciler.ts +243 -0
  88. package/src/browser/segment-structure-assert.ts +16 -0
  89. package/src/browser/server-action-bridge.ts +510 -603
  90. package/src/browser/shallow.ts +6 -1
  91. package/src/browser/types.ts +158 -48
  92. package/src/browser/validate-redirect-origin.ts +29 -0
  93. package/src/build/generate-manifest.ts +84 -23
  94. package/src/build/generate-route-types.ts +39 -828
  95. package/src/build/index.ts +4 -5
  96. package/src/build/route-trie.ts +85 -32
  97. package/src/build/route-types/ast-helpers.ts +25 -0
  98. package/src/build/route-types/ast-route-extraction.ts +98 -0
  99. package/src/build/route-types/codegen.ts +102 -0
  100. package/src/build/route-types/include-resolution.ts +418 -0
  101. package/src/build/route-types/param-extraction.ts +48 -0
  102. package/src/build/route-types/per-module-writer.ts +128 -0
  103. package/src/build/route-types/router-processing.ts +618 -0
  104. package/src/build/route-types/scan-filter.ts +85 -0
  105. package/src/build/runtime-discovery.ts +231 -0
  106. package/src/cache/background-task.ts +34 -0
  107. package/src/cache/cache-key-utils.ts +44 -0
  108. package/src/cache/cache-policy.ts +125 -0
  109. package/src/cache/cache-runtime.ts +342 -0
  110. package/src/cache/cache-scope.ts +167 -307
  111. package/src/cache/cf/cf-cache-store.ts +573 -21
  112. package/src/cache/cf/index.ts +13 -3
  113. package/src/cache/document-cache.ts +116 -77
  114. package/src/cache/handle-capture.ts +81 -0
  115. package/src/cache/handle-snapshot.ts +41 -0
  116. package/src/cache/index.ts +1 -15
  117. package/src/cache/memory-segment-store.ts +191 -13
  118. package/src/cache/profile-registry.ts +73 -0
  119. package/src/cache/read-through-swr.ts +134 -0
  120. package/src/cache/segment-codec.ts +256 -0
  121. package/src/cache/taint.ts +153 -0
  122. package/src/cache/types.ts +72 -122
  123. package/src/client.rsc.tsx +6 -1
  124. package/src/client.tsx +118 -302
  125. package/src/component-utils.ts +4 -4
  126. package/src/components/DefaultDocument.tsx +5 -1
  127. package/src/context-var.ts +156 -0
  128. package/src/debug.ts +19 -9
  129. package/src/errors.ts +77 -7
  130. package/src/handle.ts +55 -10
  131. package/src/handles/MetaTags.tsx +73 -20
  132. package/src/handles/breadcrumbs.ts +66 -0
  133. package/src/handles/index.ts +1 -0
  134. package/src/handles/meta.ts +30 -13
  135. package/src/host/cookie-handler.ts +21 -15
  136. package/src/host/errors.ts +8 -8
  137. package/src/host/index.ts +4 -7
  138. package/src/host/pattern-matcher.ts +27 -27
  139. package/src/host/router.ts +61 -39
  140. package/src/host/testing.ts +8 -8
  141. package/src/host/types.ts +15 -7
  142. package/src/host/utils.ts +1 -1
  143. package/src/href-client.ts +65 -45
  144. package/src/index.rsc.ts +138 -21
  145. package/src/index.ts +206 -51
  146. package/src/internal-debug.ts +11 -0
  147. package/src/loader.rsc.ts +25 -143
  148. package/src/loader.ts +27 -10
  149. package/src/network-error-thrower.tsx +3 -1
  150. package/src/outlet-context.ts +1 -1
  151. package/src/outlet-provider.tsx +45 -0
  152. package/src/prerender/param-hash.ts +4 -2
  153. package/src/prerender/store.ts +159 -13
  154. package/src/prerender.ts +397 -29
  155. package/src/response-utils.ts +28 -0
  156. package/src/reverse.ts +231 -121
  157. package/src/root-error-boundary.tsx +41 -29
  158. package/src/route-content-wrapper.tsx +7 -4
  159. package/src/route-definition/dsl-helpers.ts +1134 -0
  160. package/src/route-definition/helper-factories.ts +200 -0
  161. package/src/route-definition/helpers-types.ts +483 -0
  162. package/src/route-definition/index.ts +55 -0
  163. package/src/route-definition/redirect.ts +101 -0
  164. package/src/route-definition/resolve-handler-use.ts +155 -0
  165. package/src/route-definition.ts +1 -1431
  166. package/src/route-map-builder.ts +162 -123
  167. package/src/route-name.ts +53 -0
  168. package/src/route-types.ts +66 -9
  169. package/src/router/content-negotiation.ts +215 -0
  170. package/src/router/debug-manifest.ts +72 -0
  171. package/src/router/error-handling.ts +9 -9
  172. package/src/router/find-match.ts +160 -0
  173. package/src/router/handler-context.ts +418 -86
  174. package/src/router/intercept-resolution.ts +35 -20
  175. package/src/router/lazy-includes.ts +237 -0
  176. package/src/router/loader-resolution.ts +359 -128
  177. package/src/router/logging.ts +251 -0
  178. package/src/router/manifest.ts +98 -32
  179. package/src/router/match-api.ts +196 -261
  180. package/src/router/match-context.ts +4 -2
  181. package/src/router/match-handlers.ts +441 -0
  182. package/src/router/match-middleware/background-revalidation.ts +108 -93
  183. package/src/router/match-middleware/cache-lookup.ts +415 -86
  184. package/src/router/match-middleware/cache-store.ts +91 -29
  185. package/src/router/match-middleware/intercept-resolution.ts +48 -21
  186. package/src/router/match-middleware/segment-resolution.ts +73 -9
  187. package/src/router/match-pipelines.ts +10 -45
  188. package/src/router/match-result.ts +154 -35
  189. package/src/router/metrics.ts +240 -15
  190. package/src/router/middleware-cookies.ts +55 -0
  191. package/src/router/middleware-types.ts +209 -0
  192. package/src/router/middleware.ts +373 -371
  193. package/src/router/navigation-snapshot.ts +182 -0
  194. package/src/router/pattern-matching.ts +292 -52
  195. package/src/router/prerender-match.ts +502 -0
  196. package/src/router/preview-match.ts +98 -0
  197. package/src/router/request-classification.ts +310 -0
  198. package/src/router/revalidation.ts +152 -39
  199. package/src/router/route-snapshot.ts +245 -0
  200. package/src/router/router-context.ts +41 -21
  201. package/src/router/router-interfaces.ts +484 -0
  202. package/src/router/router-options.ts +618 -0
  203. package/src/router/router-registry.ts +24 -0
  204. package/src/router/segment-resolution/fresh.ts +756 -0
  205. package/src/router/segment-resolution/helpers.ts +268 -0
  206. package/src/router/segment-resolution/loader-cache.ts +199 -0
  207. package/src/router/segment-resolution/revalidation.ts +1407 -0
  208. package/src/router/segment-resolution/static-store.ts +67 -0
  209. package/src/router/segment-resolution.ts +21 -1315
  210. package/src/router/segment-wrappers.ts +291 -0
  211. package/src/router/substitute-pattern-params.ts +56 -0
  212. package/src/router/telemetry-otel.ts +299 -0
  213. package/src/router/telemetry.ts +300 -0
  214. package/src/router/timeout.ts +148 -0
  215. package/src/router/trie-matching.ts +111 -39
  216. package/src/router/types.ts +17 -9
  217. package/src/router/url-params.ts +49 -0
  218. package/src/router.ts +642 -2011
  219. package/src/rsc/handler-context.ts +45 -0
  220. package/src/rsc/handler.ts +864 -1114
  221. package/src/rsc/helpers.ts +181 -19
  222. package/src/rsc/index.ts +0 -20
  223. package/src/rsc/loader-fetch.ts +229 -0
  224. package/src/rsc/manifest-init.ts +90 -0
  225. package/src/rsc/nonce.ts +14 -0
  226. package/src/rsc/origin-guard.ts +141 -0
  227. package/src/rsc/progressive-enhancement.ts +395 -0
  228. package/src/rsc/response-error.ts +37 -0
  229. package/src/rsc/response-route-handler.ts +360 -0
  230. package/src/rsc/rsc-rendering.ts +256 -0
  231. package/src/rsc/runtime-warnings.ts +42 -0
  232. package/src/rsc/server-action.ts +360 -0
  233. package/src/rsc/ssr-setup.ts +128 -0
  234. package/src/rsc/types.ts +52 -11
  235. package/src/search-params.ts +230 -0
  236. package/src/segment-content-promise.ts +67 -0
  237. package/src/segment-loader-promise.ts +122 -0
  238. package/src/segment-system.tsx +187 -38
  239. package/src/server/context.ts +333 -59
  240. package/src/server/cookie-store.ts +190 -0
  241. package/src/server/fetchable-loader-store.ts +37 -0
  242. package/src/server/handle-store.ts +113 -15
  243. package/src/server/loader-registry.ts +24 -64
  244. package/src/server/request-context.ts +603 -109
  245. package/src/server.ts +35 -155
  246. package/src/ssr/index.tsx +107 -30
  247. package/src/static-handler.ts +126 -0
  248. package/src/theme/ThemeProvider.tsx +21 -15
  249. package/src/theme/ThemeScript.tsx +5 -5
  250. package/src/theme/constants.ts +5 -2
  251. package/src/theme/index.ts +4 -14
  252. package/src/theme/theme-context.ts +4 -30
  253. package/src/theme/theme-script.ts +21 -18
  254. package/src/types/boundaries.ts +158 -0
  255. package/src/types/cache-types.ts +198 -0
  256. package/src/types/error-types.ts +192 -0
  257. package/src/types/global-namespace.ts +100 -0
  258. package/src/types/handler-context.ts +764 -0
  259. package/src/types/index.ts +88 -0
  260. package/src/types/loader-types.ts +209 -0
  261. package/src/types/request-scope.ts +126 -0
  262. package/src/types/route-config.ts +170 -0
  263. package/src/types/route-entry.ts +120 -0
  264. package/src/types/segments.ts +167 -0
  265. package/src/types.ts +1 -1757
  266. package/src/urls/include-helper.ts +207 -0
  267. package/src/urls/index.ts +53 -0
  268. package/src/urls/path-helper-types.ts +372 -0
  269. package/src/urls/path-helper.ts +364 -0
  270. package/src/urls/pattern-types.ts +107 -0
  271. package/src/urls/response-types.ts +108 -0
  272. package/src/urls/type-extraction.ts +372 -0
  273. package/src/urls/urls-function.ts +98 -0
  274. package/src/urls.ts +1 -1282
  275. package/src/use-loader.tsx +161 -81
  276. package/src/vite/debug.ts +184 -0
  277. package/src/vite/discovery/bundle-postprocess.ts +181 -0
  278. package/src/vite/discovery/discover-routers.ts +376 -0
  279. package/src/vite/discovery/gate-state.ts +171 -0
  280. package/src/vite/discovery/prerender-collection.ts +486 -0
  281. package/src/vite/discovery/route-types-writer.ts +258 -0
  282. package/src/vite/discovery/self-gen-tracking.ts +73 -0
  283. package/src/vite/discovery/state.ts +117 -0
  284. package/src/vite/discovery/virtual-module-codegen.ts +203 -0
  285. package/src/vite/index.ts +15 -2063
  286. package/src/vite/plugin-types.ts +103 -0
  287. package/src/vite/plugins/cjs-to-esm.ts +98 -0
  288. package/src/vite/plugins/client-ref-dedup.ts +131 -0
  289. package/src/vite/plugins/client-ref-hashing.ts +117 -0
  290. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  291. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  292. package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
  293. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +107 -64
  294. package/src/vite/plugins/expose-id-utils.ts +299 -0
  295. package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
  296. package/src/vite/plugins/expose-ids/handler-transform.ts +209 -0
  297. package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
  298. package/src/vite/plugins/expose-ids/router-transform.ts +127 -0
  299. package/src/vite/plugins/expose-ids/types.ts +45 -0
  300. package/src/vite/plugins/expose-internal-ids.ts +816 -0
  301. package/src/vite/plugins/performance-tracks.ts +96 -0
  302. package/src/vite/plugins/refresh-cmd.ts +127 -0
  303. package/src/vite/plugins/use-cache-transform.ts +336 -0
  304. package/src/vite/plugins/version-injector.ts +109 -0
  305. package/src/vite/plugins/version-plugin.ts +266 -0
  306. package/src/vite/{virtual-entries.ts → plugins/virtual-entries.ts} +23 -14
  307. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  308. package/src/vite/rango.ts +497 -0
  309. package/src/vite/router-discovery.ts +1423 -0
  310. package/src/vite/utils/ast-handler-extract.ts +517 -0
  311. package/src/vite/utils/banner.ts +36 -0
  312. package/src/vite/utils/bundle-analysis.ts +137 -0
  313. package/src/vite/utils/manifest-utils.ts +70 -0
  314. package/src/vite/utils/package-resolution.ts +161 -0
  315. package/src/vite/utils/prerender-utils.ts +222 -0
  316. package/src/vite/utils/shared-utils.ts +170 -0
  317. package/CLAUDE.md +0 -43
  318. package/src/browser/lru-cache.ts +0 -69
  319. package/src/browser/request-controller.ts +0 -164
  320. package/src/cache/memory-store.ts +0 -253
  321. package/src/href-context.ts +0 -33
  322. package/src/router.gen.ts +0 -6
  323. package/src/urls.gen.ts +0 -8
  324. package/src/vite/expose-handle-id.ts +0 -209
  325. package/src/vite/expose-loader-id.ts +0 -426
  326. package/src/vite/expose-location-state-id.ts +0 -177
  327. package/src/vite/expose-prerender-handler-id.ts +0 -429
  328. package/src/vite/package-resolution.ts +0 -125
  329. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
@@ -1,69 +0,0 @@
1
- /**
2
- * Simple LRU (Least Recently Used) cache implementation
3
- * Used for caching navigation segments to enable instant back/forward
4
- */
5
- export class LRUCache<K, V> {
6
- private cache = new Map<K, V>();
7
- private maxSize: number;
8
-
9
- constructor(maxSize: number) {
10
- this.maxSize = maxSize;
11
- }
12
-
13
- get(key: K): V | undefined {
14
- if (!this.cache.has(key)) {
15
- return undefined;
16
- }
17
-
18
- // Move to end (most recently used)
19
- const value = this.cache.get(key)!;
20
- this.cache.delete(key);
21
- this.cache.set(key, value);
22
- return value;
23
- }
24
-
25
- set(key: K, value: V): void {
26
- // If key exists, delete it first to update position
27
- if (this.cache.has(key)) {
28
- this.cache.delete(key);
29
- }
30
-
31
- this.cache.set(key, value);
32
-
33
- // Evict oldest entries if over capacity
34
- while (this.cache.size > this.maxSize) {
35
- const oldestKey = this.cache.keys().next().value;
36
- if (oldestKey !== undefined) {
37
- this.cache.delete(oldestKey);
38
- }
39
- }
40
- }
41
-
42
- has(key: K): boolean {
43
- if (!this.cache.has(key)) {
44
- return false;
45
- }
46
-
47
- // Move to end (most recently used) - same as get()
48
- const value = this.cache.get(key)!;
49
- this.cache.delete(key);
50
- this.cache.set(key, value);
51
- return true;
52
- }
53
-
54
- delete(key: K): boolean {
55
- return this.cache.delete(key);
56
- }
57
-
58
- clear(): void {
59
- this.cache.clear();
60
- }
61
-
62
- keys(): IterableIterator<K> {
63
- return this.cache.keys();
64
- }
65
-
66
- get size(): number {
67
- return this.cache.size;
68
- }
69
- }
@@ -1,164 +0,0 @@
1
- import type { RequestController, DisposableAbortController } from "./types.js";
2
-
3
- // Polyfill Symbol.dispose for Safari and older browsers
4
- if (typeof Symbol.dispose === "undefined") {
5
- (Symbol as any).dispose = Symbol("Symbol.dispose");
6
- }
7
-
8
- /**
9
- * Create a request controller for managing concurrent abort controllers
10
- *
11
- * This utility helps manage concurrent navigation requests by providing
12
- * a way to abort all pending requests when a new navigation starts.
13
- *
14
- * @returns RequestController instance
15
- *
16
- * @example
17
- * ```typescript
18
- * const controller = createRequestController();
19
- *
20
- * // Start a new request
21
- * const abortController = controller.create();
22
- * fetch(url, { signal: abortController.signal });
23
- *
24
- * // Abort all pending requests (e.g., when starting new navigation)
25
- * controller.abortAll();
26
- *
27
- * // Clean up completed request
28
- * controller.remove(abortController);
29
- * ```
30
- */
31
- export function createRequestController(): RequestController {
32
- // Navigation controllers - aborted on new navigation
33
- // Using WeakRef to allow GC if controller is no longer referenced elsewhere
34
- const controllers: WeakRef<AbortController>[] = [];
35
- // Action controllers - NOT aborted by navigation, only by errors
36
- const actionControllers: WeakRef<AbortController>[] = [];
37
-
38
- /**
39
- * Remove stale (garbage collected) refs from an array
40
- */
41
- function pruneStaleRefs(refs: WeakRef<AbortController>[]): void {
42
- for (let i = refs.length - 1; i >= 0; i--) {
43
- if (!refs[i].deref()) {
44
- refs.splice(i, 1);
45
- }
46
- }
47
- }
48
-
49
- return {
50
- /**
51
- * Create a new abort controller and track it for navigation
52
- *
53
- * @returns A new AbortController
54
- */
55
- create(): AbortController {
56
- const controller = new AbortController();
57
- controllers.push(new WeakRef(controller));
58
- console.log(
59
- `[Browser] Created abort controller, total: ${controllers.length}`,
60
- );
61
- return controller;
62
- },
63
-
64
- /**
65
- * Create a disposable abort controller for navigation use with `using` keyword
66
- *
67
- * The controller will be automatically removed from tracking when
68
- * it goes out of scope, regardless of how the scope is exited.
69
- *
70
- * @returns A DisposableAbortController
71
- *
72
- * @example
73
- * ```typescript
74
- * async function handleNavigation() {
75
- * requestController.abortAll();
76
- * using { controller } = requestController.createDisposable();
77
- * // ... use controller.signal ...
78
- * // controller is automatically removed on scope exit
79
- * }
80
- * ```
81
- */
82
- createDisposable(): DisposableAbortController {
83
- const controller = this.create();
84
- return {
85
- controller,
86
- [Symbol.dispose]: () => {
87
- this.remove(controller);
88
- },
89
- };
90
- },
91
-
92
- /**
93
- * Create a disposable abort controller for actions
94
- *
95
- * Action controllers are NOT aborted by navigation - they complete
96
- * independently. Only aborted by abortAllActions() on error.
97
- *
98
- * @returns A DisposableAbortController
99
- */
100
- createActionDisposable(): DisposableAbortController {
101
- const controller = new AbortController();
102
- const ref = new WeakRef(controller);
103
- actionControllers.push(ref);
104
- console.log(
105
- `[Browser] Created action controller, total: ${actionControllers.length}`,
106
- );
107
- return {
108
- controller,
109
- [Symbol.dispose]: () => {
110
- const index = actionControllers.indexOf(ref);
111
- if (index !== -1) {
112
- actionControllers.splice(index, 1);
113
- console.log(
114
- `[Browser] Removed action controller, remaining: ${actionControllers.length}`,
115
- );
116
- }
117
- },
118
- };
119
- },
120
-
121
- /**
122
- * Abort all navigation controllers (NOT actions)
123
- *
124
- * Called when starting new navigation. Actions continue
125
- * to complete in the background.
126
- */
127
- abortAll(): void {
128
- controllers.forEach((ref) => ref.deref()?.abort());
129
- controllers.length = 0;
130
- console.log(`[Browser] Aborted all navigation controllers`);
131
- },
132
-
133
- /**
134
- * Abort all action controllers
135
- *
136
- * Called when an action error occurs - prevents other actions
137
- * from completing and overwriting the error UI.
138
- */
139
- abortAllActions(): void {
140
- actionControllers.forEach((ref) => ref.deref()?.abort());
141
- actionControllers.length = 0;
142
- console.log(`[Browser] Aborted all action controllers`);
143
- },
144
-
145
- /**
146
- * Remove a specific controller from tracking
147
- *
148
- * Call this when a request completes successfully.
149
- *
150
- * @param controller - The controller to remove
151
- */
152
- remove(controller: AbortController): void {
153
- // Prune any stale refs while searching
154
- pruneStaleRefs(controllers);
155
- const index = controllers.findIndex((ref) => ref.deref() === controller);
156
- if (index !== -1) {
157
- controllers.splice(index, 1);
158
- console.log(
159
- `[Browser] Removed abort controller, remaining: ${controllers.length}`,
160
- );
161
- }
162
- },
163
- };
164
- }
@@ -1,253 +0,0 @@
1
- /**
2
- * In-Memory Cache Store
3
- *
4
- * Simple implementation for development and testing.
5
- * Not suitable for production (no persistence, single-instance only).
6
- *
7
- * @internal This is reserved for future extensibility.
8
- * For segment caching, use MemorySegmentCacheStore instead.
9
- */
10
-
11
- import type {
12
- CacheStore,
13
- CacheEntry,
14
- CacheValue,
15
- CachePutOptions,
16
- CacheMetadata,
17
- CacheValueType,
18
- } from "./types.js";
19
-
20
- // ============================================================================
21
- // Constants
22
- // ============================================================================
23
-
24
- /** Default TTL when no explicit value is provided */
25
- const DEFAULT_TTL_SECONDS = 60;
26
-
27
- // ============================================================================
28
- // Types
29
- // ============================================================================
30
-
31
- interface StoredEntry {
32
- /** Stored value (streams/responses converted to ArrayBuffer) */
33
- value: ArrayBuffer | string | object;
34
- metadata: CacheMetadata;
35
- }
36
-
37
- /**
38
- * In-memory cache store implementation
39
- */
40
- export class MemoryCacheStore implements CacheStore {
41
- private cache = new Map<string, StoredEntry>();
42
-
43
- async match<T = CacheValue>(key: string): Promise<CacheEntry<T> | undefined> {
44
- const entry = this.cache.get(key);
45
-
46
- if (!entry) {
47
- return undefined;
48
- }
49
-
50
- // Check expiration
51
- if (entry.metadata.expiresAt && Date.now() > entry.metadata.expiresAt) {
52
- this.cache.delete(key);
53
- return undefined;
54
- }
55
-
56
- // Reconstruct value based on original type
57
- const value = this.reconstructValue(entry);
58
-
59
- return {
60
- value: value as T,
61
- metadata: entry.metadata,
62
- };
63
- }
64
-
65
- async put<T extends CacheValue>(
66
- key: string,
67
- value: T,
68
- options?: CachePutOptions
69
- ): Promise<void> {
70
- const ttl = options?.ttl ?? DEFAULT_TTL_SECONDS;
71
- const expiresAt = Date.now() + ttl * 1000;
72
-
73
- // Detect value type and convert for storage
74
- const { storedValue, valueType, responseHeaders, responseStatus } =
75
- await this.prepareForStorage(value);
76
-
77
- const metadata: CacheMetadata = {
78
- ...options?.metadata,
79
- expiresAt,
80
- valueType,
81
- responseHeaders,
82
- responseStatus,
83
- };
84
-
85
- this.cache.set(key, {
86
- value: storedValue,
87
- metadata,
88
- });
89
- }
90
-
91
- async delete(key: string): Promise<boolean> {
92
- return this.cache.delete(key);
93
- }
94
-
95
- /**
96
- * Clear all entries (useful for testing)
97
- */
98
- clear(): void {
99
- this.cache.clear();
100
- }
101
-
102
- /**
103
- * Get current cache size (useful for testing/debugging)
104
- */
105
- get size(): number {
106
- return this.cache.size;
107
- }
108
-
109
- /**
110
- * Manually purge expired entries
111
- */
112
- purgeExpired(): number {
113
- const now = Date.now();
114
- let purged = 0;
115
-
116
- for (const [key, entry] of this.cache) {
117
- if (entry.metadata.expiresAt && now > entry.metadata.expiresAt) {
118
- this.cache.delete(key);
119
- purged++;
120
- }
121
- }
122
-
123
- return purged;
124
- }
125
-
126
- /**
127
- * Prepare a value for storage
128
- * Converts streams and responses to ArrayBuffer, detects type
129
- */
130
- private async prepareForStorage(value: CacheValue): Promise<{
131
- storedValue: ArrayBuffer | string | object;
132
- valueType: CacheValueType;
133
- responseHeaders?: Record<string, string>;
134
- responseStatus?: number;
135
- }> {
136
- // ReadableStream -> ArrayBuffer
137
- if (value instanceof ReadableStream) {
138
- return {
139
- storedValue: await streamToArrayBuffer(value),
140
- valueType: "stream",
141
- };
142
- }
143
-
144
- // Response -> ArrayBuffer + headers/status
145
- if (value instanceof Response) {
146
- const headers: Record<string, string> = {};
147
- value.headers.forEach((v, k) => {
148
- headers[k] = v;
149
- });
150
-
151
- return {
152
- storedValue: await value.clone().arrayBuffer(),
153
- valueType: "response",
154
- responseHeaders: headers,
155
- responseStatus: value.status,
156
- };
157
- }
158
-
159
- // ArrayBuffer -> store as-is
160
- if (value instanceof ArrayBuffer) {
161
- return {
162
- storedValue: value,
163
- valueType: "arraybuffer",
164
- };
165
- }
166
-
167
- // String -> store as-is
168
- if (typeof value === "string") {
169
- return {
170
- storedValue: value,
171
- valueType: "string",
172
- };
173
- }
174
-
175
- // Object -> store as-is (JSON-serializable)
176
- return {
177
- storedValue: value,
178
- valueType: "object",
179
- };
180
- }
181
-
182
- /**
183
- * Reconstruct original value type from stored entry
184
- */
185
- private reconstructValue(entry: StoredEntry): CacheValue {
186
- const { value, metadata } = entry;
187
-
188
- switch (metadata.valueType) {
189
- case "stream":
190
- return arrayBufferToStream(value as ArrayBuffer);
191
-
192
- case "response": {
193
- const status = metadata.responseStatus ?? 200;
194
- // Status codes 204 (No Content) and 304 (Not Modified) cannot have a body
195
- const isNullBodyStatus = status === 204 || status === 304;
196
- return new Response(isNullBodyStatus ? null : (value as ArrayBuffer), {
197
- status,
198
- headers: metadata.responseHeaders,
199
- });
200
- }
201
-
202
- case "arraybuffer":
203
- case "string":
204
- case "object":
205
- default:
206
- return value as CacheValue;
207
- }
208
- }
209
- }
210
-
211
- /**
212
- * Convert a ReadableStream to ArrayBuffer.
213
- * @internal
214
- */
215
- async function streamToArrayBuffer(
216
- stream: ReadableStream<Uint8Array>
217
- ): Promise<ArrayBuffer> {
218
- const chunks: Uint8Array[] = [];
219
- const reader = stream.getReader();
220
-
221
- while (true) {
222
- const { done, value } = await reader.read();
223
- if (done) break;
224
- chunks.push(value);
225
- }
226
-
227
- // Concatenate chunks
228
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
229
- const result = new Uint8Array(totalLength);
230
- let offset = 0;
231
-
232
- for (const chunk of chunks) {
233
- result.set(chunk, offset);
234
- offset += chunk.length;
235
- }
236
-
237
- return result.buffer;
238
- }
239
-
240
- /**
241
- * Convert an ArrayBuffer to a ReadableStream.
242
- * @internal
243
- */
244
- function arrayBufferToStream(buffer: ArrayBuffer): ReadableStream<Uint8Array> {
245
- const uint8 = new Uint8Array(buffer);
246
-
247
- return new ReadableStream({
248
- start(controller) {
249
- controller.enqueue(uint8);
250
- controller.close();
251
- },
252
- });
253
- }
@@ -1,33 +0,0 @@
1
- "use client";
2
-
3
- /**
4
- * Href Context for route name resolution
5
- *
6
- * This module is marked "use client" so it can be imported by both:
7
- * - Server (segment-system): Gets a client reference for createElement
8
- * - Client (useHref): Uses the actual context for useContext
9
- *
10
- * The context stores:
11
- * - routeMap: Map of route names to URL patterns
12
- * - routeName: Current matched route name (for local name resolution)
13
- */
14
- import { createContext, type Context } from "react";
15
-
16
- /**
17
- * Context value for href resolution
18
- */
19
- export interface HrefContextValue {
20
- /** Route map: route name -> URL pattern */
21
- routeMap: Record<string, string>;
22
- /** Current matched route name (includes name prefix from include()) */
23
- routeName?: string;
24
- }
25
-
26
- /**
27
- * Context for href resolution (route map and current route name)
28
- *
29
- * On the server: Populated by renderSegments() via HrefContext.Provider
30
- * On the client: Populated by NavigationProvider from RSC metadata
31
- */
32
- export const HrefContext: Context<HrefContextValue | null> =
33
- createContext<HrefContextValue | null>(null);
package/src/router.gen.ts DELETED
@@ -1,6 +0,0 @@
1
- // Auto-generated by @rangojs/router - do not edit
2
- export const routes = {
3
- about: "/about",
4
- home: "/",
5
- } as const;
6
- export type routes = typeof routes;
package/src/urls.gen.ts DELETED
@@ -1,8 +0,0 @@
1
- // Auto-generated by @rangojs/router - do not edit
2
- export const routes = {
3
- health: "/health",
4
- home: "/",
5
- index: "/",
6
- post: "/:slug",
7
- } as const;
8
- export type routes = typeof routes;