@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.
- package/AGENTS.md +9 -0
- package/README.md +1037 -4
- package/dist/bin/rango.js +1619 -157
- package/dist/vite/index.js +5762 -2301
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +71 -63
- package/skills/breadcrumbs/SKILL.md +252 -0
- package/skills/cache-guide/SKILL.md +294 -0
- package/skills/caching/SKILL.md +93 -23
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +12 -8
- package/skills/document-cache/SKILL.md +18 -16
- package/skills/fonts/SKILL.md +6 -4
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +367 -71
- package/skills/host-router/SKILL.md +218 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +176 -8
- package/skills/layout/SKILL.md +124 -3
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +474 -47
- package/skills/middleware/SKILL.md +207 -37
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +15 -11
- package/skills/parallel/SKILL.md +272 -1
- package/skills/prerender/SKILL.md +467 -65
- package/skills/rango/SKILL.md +89 -21
- package/skills/response-routes/SKILL.md +152 -91
- package/skills/route/SKILL.md +305 -14
- package/skills/router-setup/SKILL.md +210 -32
- package/skills/server-actions/SKILL.md +739 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +333 -86
- package/skills/use-cache/SKILL.md +324 -0
- package/skills/view-transitions/SKILL.md +212 -0
- package/src/__internal.ts +102 -4
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +136 -68
- package/src/browser/history-state.ts +80 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +374 -561
- package/src/browser/navigation-client.ts +228 -70
- package/src/browser/navigation-store.ts +97 -55
- package/src/browser/navigation-transaction.ts +297 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +376 -315
- package/src/browser/prefetch/cache.ts +314 -0
- package/src/browser/prefetch/fetch.ts +282 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +191 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +152 -0
- package/src/browser/react/Link.tsx +255 -71
- package/src/browser/react/NavigationProvider.tsx +152 -24
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +55 -0
- package/src/browser/react/index.ts +15 -12
- package/src/browser/react/location-state-shared.ts +95 -53
- package/src/browser/react/location-state.ts +60 -15
- package/src/browser/react/mount-context.ts +6 -1
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +29 -51
- package/src/browser/react/use-client-cache.ts +5 -3
- package/src/browser/react/use-handle.ts +30 -120
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-navigation.ts +44 -65
- package/src/browser/react/use-params.ts +78 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +99 -0
- package/src/browser/react/use-router.ts +83 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +85 -99
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +246 -64
- package/src/browser/scroll-restoration.ts +127 -52
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +16 -0
- package/src/browser/server-action-bridge.ts +510 -603
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +158 -48
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +84 -23
- package/src/build/generate-route-types.ts +39 -828
- package/src/build/index.ts +4 -5
- package/src/build/route-trie.ts +85 -32
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +418 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +618 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +342 -0
- package/src/cache/cache-scope.ts +167 -307
- package/src/cache/cf/cf-cache-store.ts +573 -21
- package/src/cache/cf/index.ts +13 -3
- package/src/cache/document-cache.ts +116 -77
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +1 -15
- package/src/cache/memory-segment-store.ts +191 -13
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +72 -122
- package/src/client.rsc.tsx +6 -1
- package/src/client.tsx +118 -302
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +5 -1
- package/src/context-var.ts +156 -0
- package/src/debug.ts +19 -9
- package/src/errors.ts +77 -7
- package/src/handle.ts +55 -10
- package/src/handles/MetaTags.tsx +73 -20
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/handles/meta.ts +30 -13
- package/src/host/cookie-handler.ts +21 -15
- package/src/host/errors.ts +8 -8
- package/src/host/index.ts +4 -7
- package/src/host/pattern-matcher.ts +27 -27
- package/src/host/router.ts +61 -39
- package/src/host/testing.ts +8 -8
- package/src/host/types.ts +15 -7
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +65 -45
- package/src/index.rsc.ts +138 -21
- package/src/index.ts +206 -51
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +25 -143
- package/src/loader.ts +27 -10
- package/src/network-error-thrower.tsx +3 -1
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +4 -2
- package/src/prerender/store.ts +159 -13
- package/src/prerender.ts +397 -29
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +231 -121
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +7 -4
- package/src/route-definition/dsl-helpers.ts +1134 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +483 -0
- package/src/route-definition/index.ts +55 -0
- package/src/route-definition/redirect.ts +101 -0
- package/src/route-definition/resolve-handler-use.ts +155 -0
- package/src/route-definition.ts +1 -1431
- package/src/route-map-builder.ts +162 -123
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +66 -9
- package/src/router/content-negotiation.ts +215 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +9 -9
- package/src/router/find-match.ts +160 -0
- package/src/router/handler-context.ts +418 -86
- package/src/router/intercept-resolution.ts +35 -20
- package/src/router/lazy-includes.ts +237 -0
- package/src/router/loader-resolution.ts +359 -128
- package/src/router/logging.ts +251 -0
- package/src/router/manifest.ts +98 -32
- package/src/router/match-api.ts +196 -261
- package/src/router/match-context.ts +4 -2
- package/src/router/match-handlers.ts +441 -0
- package/src/router/match-middleware/background-revalidation.ts +108 -93
- package/src/router/match-middleware/cache-lookup.ts +415 -86
- package/src/router/match-middleware/cache-store.ts +91 -29
- package/src/router/match-middleware/intercept-resolution.ts +48 -21
- package/src/router/match-middleware/segment-resolution.ts +73 -9
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +154 -35
- package/src/router/metrics.ts +240 -15
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +209 -0
- package/src/router/middleware.ts +373 -371
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +292 -52
- package/src/router/prerender-match.ts +502 -0
- package/src/router/preview-match.ts +98 -0
- package/src/router/request-classification.ts +310 -0
- package/src/router/revalidation.ts +152 -39
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +41 -21
- package/src/router/router-interfaces.ts +484 -0
- package/src/router/router-options.ts +618 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +756 -0
- package/src/router/segment-resolution/helpers.ts +268 -0
- package/src/router/segment-resolution/loader-cache.ts +199 -0
- package/src/router/segment-resolution/revalidation.ts +1407 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -1315
- package/src/router/segment-wrappers.ts +291 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +111 -39
- package/src/router/types.ts +17 -9
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +642 -2011
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +864 -1114
- package/src/rsc/helpers.ts +181 -19
- package/src/rsc/index.ts +0 -20
- package/src/rsc/loader-fetch.ts +229 -0
- package/src/rsc/manifest-init.ts +90 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +395 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +360 -0
- package/src/rsc/rsc-rendering.ts +256 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +360 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +52 -11
- package/src/search-params.ts +230 -0
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +187 -38
- package/src/server/context.ts +333 -59
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +113 -15
- package/src/server/loader-registry.ts +24 -64
- package/src/server/request-context.ts +603 -109
- package/src/server.ts +35 -155
- package/src/ssr/index.tsx +107 -30
- package/src/static-handler.ts +126 -0
- package/src/theme/ThemeProvider.tsx +21 -15
- package/src/theme/ThemeScript.tsx +5 -5
- package/src/theme/constants.ts +5 -2
- package/src/theme/index.ts +4 -14
- package/src/theme/theme-context.ts +4 -30
- package/src/theme/theme-script.ts +21 -18
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +764 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +209 -0
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +120 -0
- package/src/types/segments.ts +167 -0
- package/src/types.ts +1 -1757
- package/src/urls/include-helper.ts +207 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +372 -0
- package/src/urls/path-helper.ts +364 -0
- package/src/urls/pattern-types.ts +107 -0
- package/src/urls/response-types.ts +108 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -1282
- package/src/use-loader.tsx +161 -81
- package/src/vite/debug.ts +184 -0
- package/src/vite/discovery/bundle-postprocess.ts +181 -0
- package/src/vite/discovery/discover-routers.ts +376 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +486 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +117 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +15 -2063
- package/src/vite/plugin-types.ts +103 -0
- package/src/vite/plugins/cjs-to-esm.ts +98 -0
- package/src/vite/plugins/client-ref-dedup.ts +131 -0
- package/src/vite/plugins/client-ref-hashing.ts +117 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +107 -64
- package/src/vite/plugins/expose-id-utils.ts +299 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +209 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +127 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +816 -0
- package/src/vite/plugins/performance-tracks.ts +96 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +336 -0
- package/src/vite/plugins/version-injector.ts +109 -0
- package/src/vite/plugins/version-plugin.ts +266 -0
- package/src/vite/{virtual-entries.ts → plugins/virtual-entries.ts} +23 -14
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +497 -0
- package/src/vite/router-discovery.ts +1423 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/utils/package-resolution.ts +161 -0
- package/src/vite/utils/prerender-utils.ts +222 -0
- package/src/vite/utils/shared-utils.ts +170 -0
- package/CLAUDE.md +0 -43
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/request-controller.ts +0 -164
- package/src/cache/memory-store.ts +0 -253
- package/src/href-context.ts +0 -33
- package/src/router.gen.ts +0 -6
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-handle-id.ts +0 -209
- package/src/vite/expose-loader-id.ts +0 -426
- package/src/vite/expose-location-state-id.ts +0 -177
- package/src/vite/expose-prerender-handler-id.ts +0 -429
- package/src/vite/package-resolution.ts +0 -125
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: use-cache
|
|
3
|
+
description: Function-level caching with "use cache" directive for RSC data functions and components
|
|
4
|
+
argument-hint: [profile-name]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# "use cache" Directive
|
|
8
|
+
|
|
9
|
+
Function-level caching for async server functions and RSC components. Caches
|
|
10
|
+
return values with TTL + stale-while-revalidate. Complementary to the route-level
|
|
11
|
+
`cache()` DSL and build-time `Static()`/`Prerender()`.
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
### File-level (all exports cached with default profile)
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
"use cache";
|
|
19
|
+
|
|
20
|
+
export async function getProducts() {
|
|
21
|
+
return await db.query("SELECT * FROM products");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function getCategories() {
|
|
25
|
+
return await db.query("SELECT * FROM categories");
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Function-level (per-function profile)
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
export async function getProducts() {
|
|
33
|
+
"use cache: short";
|
|
34
|
+
return await db.query("SELECT * FROM products");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function getCategories() {
|
|
38
|
+
"use cache: long";
|
|
39
|
+
return await db.query("SELECT * FROM categories");
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### RSC component
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
export async function ProductCard({ id }: { id: string }) {
|
|
47
|
+
"use cache: products"
|
|
48
|
+
const product = await db.query('SELECT * FROM products WHERE id = ?', [id]);
|
|
49
|
+
return <div>{product.name}</div>;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Named Cache Profiles
|
|
54
|
+
|
|
55
|
+
Define profiles in createRouter. Profile names map to `"use cache: <name>"` and
|
|
56
|
+
`cache('<name>')` in the DSL.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
createRouter({
|
|
60
|
+
cacheProfiles: {
|
|
61
|
+
default: { ttl: 900, swr: 1800 },
|
|
62
|
+
short: { ttl: 60, swr: 120 },
|
|
63
|
+
long: { ttl: 3600, swr: 7200 },
|
|
64
|
+
products: { ttl: 300, swr: 600, tags: ["products"] },
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- `"use cache"` (no name) resolves to `default`.
|
|
70
|
+
- `"use cache: short"` resolves to the `short` profile.
|
|
71
|
+
- Unknown profile names throw at build/boot time.
|
|
72
|
+
|
|
73
|
+
## Cache Key
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
use-cache:{functionId}:{serializedArgs}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- `functionId` -- stable ID from Vite transform (module path + export name).
|
|
80
|
+
- `serializedArgs` -- non-tainted arguments serialized via RSC `encodeReply()`.
|
|
81
|
+
|
|
82
|
+
Different functions always produce different cache keys, even for the same route.
|
|
83
|
+
This is important for intercepted routes -- the path handler and intercept handler
|
|
84
|
+
each have their own `functionId` and therefore their own cache entries.
|
|
85
|
+
|
|
86
|
+
## Tainted Arguments (ctx, env, req)
|
|
87
|
+
|
|
88
|
+
Request-scoped objects are branded with `Symbol.for('rango:nocache')` at creation.
|
|
89
|
+
When detected:
|
|
90
|
+
|
|
91
|
+
1. **Excluded from cache key** -- request-scoped, not meaningful for keying.
|
|
92
|
+
2. **Handle data captured on miss** -- side effects via `ctx.use(Handle)` are recorded.
|
|
93
|
+
3. **Handle data replayed on hit** -- restored into the current request's HandleStore.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
export async function getProductData(ctx) {
|
|
97
|
+
"use cache: short";
|
|
98
|
+
const breadcrumb = ctx.use(Breadcrumbs);
|
|
99
|
+
breadcrumb({ label: "Products", href: "/products" });
|
|
100
|
+
return await db.query("SELECT * FROM products");
|
|
101
|
+
}
|
|
102
|
+
// On hit: return value restored, breadcrumb replayed.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Request-Scoped Guards
|
|
106
|
+
|
|
107
|
+
### Read Guards
|
|
108
|
+
|
|
109
|
+
`cookies()` and `headers()` **throw** inside a `"use cache"` function because
|
|
110
|
+
per-request values (cookies, headers) are not reflected in the cache key. Without
|
|
111
|
+
this guard, one user's data would be served to another.
|
|
112
|
+
|
|
113
|
+
Extract the value before the cached function and pass it as an argument:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const locale = cookies().get("locale")?.value ?? "en";
|
|
117
|
+
const data = await getCachedData(locale); // locale is now in the cache key
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Side-Effect Guards
|
|
121
|
+
|
|
122
|
+
These ctx methods **throw** inside a `"use cache"` function because their effects
|
|
123
|
+
are lost on cache hit (the function body is skipped):
|
|
124
|
+
|
|
125
|
+
- `ctx.set()` / `ctx.get()` for passing values to children
|
|
126
|
+
- `ctx.header()`
|
|
127
|
+
- `ctx.setTheme()`
|
|
128
|
+
- `ctx.setLocationState()`
|
|
129
|
+
- `ctx.onResponse()`
|
|
130
|
+
|
|
131
|
+
The error message recommends two alternatives:
|
|
132
|
+
|
|
133
|
+
1. Extract the data fetch into a separate cached function and call ctx methods outside it.
|
|
134
|
+
2. Use the route-level `cache()` DSL which caches all segments together.
|
|
135
|
+
|
|
136
|
+
**`ctx.use(Handle)` is NOT guarded** -- handle push is captured on miss and replayed
|
|
137
|
+
on hit. This is the correct way to pass data from cached functions.
|
|
138
|
+
|
|
139
|
+
### Pattern: Separate cached function from ctx side effects
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Cached data fetch (pure)
|
|
143
|
+
async function getNavData() {
|
|
144
|
+
"use cache: short"
|
|
145
|
+
return await db.query('SELECT * FROM nav_items');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Handler (uncached, calls ctx methods freely)
|
|
149
|
+
async function NavLayout(ctx) {
|
|
150
|
+
const navData = await getNavData();
|
|
151
|
+
ctx.set("navItems", navData); // Works -- outside "use cache"
|
|
152
|
+
return <Nav items={navData}><Outlet /></Nav>;
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Misuse Guards
|
|
157
|
+
|
|
158
|
+
### Cannot use as middleware
|
|
159
|
+
|
|
160
|
+
Cached functions cannot be passed to `middleware()`. Middleware runs on every
|
|
161
|
+
request (onion model) and must not be cached.
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// WRONG -- throws at boot time
|
|
165
|
+
middleware(cachedFn);
|
|
166
|
+
|
|
167
|
+
// RIGHT -- call cached function inside middleware
|
|
168
|
+
middleware(async (ctx, next) => {
|
|
169
|
+
const data = await getCachedData();
|
|
170
|
+
ctx.set("data", data);
|
|
171
|
+
await next();
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Cannot use as Static() handler
|
|
176
|
+
|
|
177
|
+
Static handlers render once at build time. `"use cache"` is redundant.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
// WRONG -- throws at boot time
|
|
181
|
+
export const Page = Static(cachedFn);
|
|
182
|
+
|
|
183
|
+
// RIGHT -- remove "use cache", Static already caches
|
|
184
|
+
export const Page = Static(async (ctx) => {
|
|
185
|
+
return <div>Built once</div>;
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Cannot use as Prerender() handler or getParams
|
|
190
|
+
|
|
191
|
+
Prerender handlers render at build time. `"use cache"` is redundant.
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// WRONG -- throws at boot time (handler)
|
|
195
|
+
export const Page = Prerender(getParams, cachedFn);
|
|
196
|
+
|
|
197
|
+
// WRONG -- throws at boot time (getParams)
|
|
198
|
+
export const Page = Prerender(cachedGetParams, handler);
|
|
199
|
+
|
|
200
|
+
// RIGHT -- remove "use cache"
|
|
201
|
+
export const Page = Prerender(
|
|
202
|
+
async () => [{ slug: "a" }],
|
|
203
|
+
async (ctx) => <Page slug={ctx.params.slug} />,
|
|
204
|
+
);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Performance: waitUntil
|
|
208
|
+
|
|
209
|
+
On cache miss, the function executes and the result is serialized inline (blocking).
|
|
210
|
+
The cache **store write** (`setItem`) is deferred to `waitUntil` and does NOT block
|
|
211
|
+
the response.
|
|
212
|
+
|
|
213
|
+
On stale hit, stale data is returned immediately. Background revalidation (re-execute
|
|
214
|
+
|
|
215
|
+
- store) runs entirely inside `waitUntil`.
|
|
216
|
+
|
|
217
|
+
| Phase | Blocks response? |
|
|
218
|
+
| ------------------------------------ | ---------------- |
|
|
219
|
+
| Function execution (miss) | Yes |
|
|
220
|
+
| Result serialization (miss) | Yes |
|
|
221
|
+
| Cache store write (miss) | No (waitUntil) |
|
|
222
|
+
| Stale value return (stale hit) | No (immediate) |
|
|
223
|
+
| Background revalidation (stale) | No (waitUntil) |
|
|
224
|
+
| Cache lookup + deserialization (hit) | Yes (fast) |
|
|
225
|
+
|
|
226
|
+
## Using with Loaders
|
|
227
|
+
|
|
228
|
+
`"use cache"` works inside loaders. The loader runs every request, but the inner
|
|
229
|
+
cached function returns cached data:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// Cached data function
|
|
233
|
+
export async function getProductData(slug: string) {
|
|
234
|
+
"use cache";
|
|
235
|
+
return await db.query("SELECT * FROM products WHERE slug = ?", [slug]);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Loader runs every request, but inner call is cached
|
|
239
|
+
export const ProductLoader = createLoader(async (ctx) => {
|
|
240
|
+
return getProductData(ctx.params.slug);
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Using with Intercepted Routes
|
|
245
|
+
|
|
246
|
+
Path handlers and intercept handlers have different `functionId` values from the
|
|
247
|
+
Vite transform, so they naturally get distinct cache entries even for the same URL:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// Path handler -- cached separately
|
|
251
|
+
path("/product/:id", async (ctx) => {
|
|
252
|
+
"use cache"
|
|
253
|
+
return <FullProductPage id={ctx.params.id} />;
|
|
254
|
+
}),
|
|
255
|
+
|
|
256
|
+
// Intercept handler -- cached separately (different functionId)
|
|
257
|
+
intercept("@modal", ".product", async (ctx) => {
|
|
258
|
+
"use cache"
|
|
259
|
+
return <ProductModal id={ctx.params.id} />;
|
|
260
|
+
}),
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Vite Transform
|
|
264
|
+
|
|
265
|
+
The `rango:use-cache` Vite plugin detects the directive and wraps exports with
|
|
266
|
+
`registerCachedFunction()`:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// Input
|
|
270
|
+
"use cache"
|
|
271
|
+
export async function getProducts() { ... }
|
|
272
|
+
|
|
273
|
+
// Output
|
|
274
|
+
import { registerCachedFunction } from '@rangojs/router/cache-runtime';
|
|
275
|
+
export const getProducts = registerCachedFunction(
|
|
276
|
+
async function getProducts() { ... },
|
|
277
|
+
"src/data/products.ts#getProducts",
|
|
278
|
+
"default"
|
|
279
|
+
);
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Function-level directives are hoisted:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
// Input
|
|
286
|
+
export async function getProducts() {
|
|
287
|
+
"use cache: short";
|
|
288
|
+
return await db.query("...");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Output
|
|
292
|
+
const __rango_cached_getProducts = registerCachedFunction(
|
|
293
|
+
async function getProducts() {
|
|
294
|
+
return await db.query("...");
|
|
295
|
+
},
|
|
296
|
+
"src/data/products.ts#getProducts",
|
|
297
|
+
"short",
|
|
298
|
+
);
|
|
299
|
+
export async function getProducts() {
|
|
300
|
+
return __rango_cached_getProducts();
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Backing Store
|
|
305
|
+
|
|
306
|
+
Writes to the same `SegmentCacheStore` as `cache()` DSL, `Static()`, and `Prerender()`.
|
|
307
|
+
One store, one configuration, one invalidation API. Tag-based invalidation
|
|
308
|
+
(`revalidateTag`) works across all mechanisms.
|
|
309
|
+
|
|
310
|
+
## Interaction with Other Caching
|
|
311
|
+
|
|
312
|
+
| Mechanism | Granularity | When | Use case |
|
|
313
|
+
| ------------------ | ------------------ | ---------- | ----------------------------------------------- |
|
|
314
|
+
| `"use cache"` | Function/component | Runtime | Cache individual data fetches or components |
|
|
315
|
+
| `cache()` DSL | Route segment | Runtime | Cache entire route subtrees with children |
|
|
316
|
+
| `cache('profile')` | Route segment | Runtime | Same as cache() with a named profile |
|
|
317
|
+
| `Static()` | Route segment | Build-time | Render once, never re-render |
|
|
318
|
+
| `Prerender()` | Route segment | Build-time | Pre-render known params, optional live fallback |
|
|
319
|
+
|
|
320
|
+
## Dev Mode
|
|
321
|
+
|
|
322
|
+
In development, the Vite transform still wraps functions, but the cache store is
|
|
323
|
+
a `MemorySegmentCacheStore` that works locally. Functions cache normally in dev
|
|
324
|
+
for testing cache behavior.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: view-transitions
|
|
3
|
+
description: Configure React View Transitions on layouts, routes, and parallel slots in @rangojs/router
|
|
4
|
+
argument-hint: [layout|route|parallel|intercept]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# View Transitions
|
|
8
|
+
|
|
9
|
+
Rango wires React's experimental `<ViewTransition>` into the segment tree via the `transition()` helper. Each segment can declare its own transition config; rango wraps it at the right tree position so navigations morph the right pieces and modals do not.
|
|
10
|
+
|
|
11
|
+
> Requires React experimental (the build that exports `<ViewTransition>` and `addTransitionType`). With stable React, `transition()` is a no-op — your routes still render, just without view-transition wrappers.
|
|
12
|
+
|
|
13
|
+
## What `transition()` does
|
|
14
|
+
|
|
15
|
+
`transition(config)` attaches a [`TransitionConfig`](#transitionconfig) to the surrounding entry. Where the wrap actually lands in the rendered React tree depends on the segment type:
|
|
16
|
+
|
|
17
|
+
| Segment type | Wrap location |
|
|
18
|
+
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `layout()` | Around the layout's **default outlet content** (what the layout's `<Outlet />` renders), recursively pushed past nested layouts. Parallel slots (`<ParallelOutlet />`) are siblings of the wrap, not subtree members. |
|
|
20
|
+
| `path()` / `route()` | Around the **route's component itself** (the leaf content). |
|
|
21
|
+
| `parallel()` / `intercept()` slot | `transition()` is accepted by the DSL today, but slot-level rendering does not currently apply a `<ViewTransition>` wrapper. Mount intercept slots in layouts so layout transitions stay scoped to the default outlet. For modal-specific morphs today, use an element-level React `<ViewTransition>` inside the modal component. |
|
|
22
|
+
|
|
23
|
+
The layout case is the important one: stacking a layout transition does **not** wrap the layout chrome (header, sidebar, modal slot); it only morphs whatever flows through that layout's `<Outlet />`.
|
|
24
|
+
|
|
25
|
+
## Basic Usage
|
|
26
|
+
|
|
27
|
+
A simple cross-fade between pages that share a layout:
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { urls } from "@rangojs/router";
|
|
31
|
+
import { Outlet } from "@rangojs/router/client";
|
|
32
|
+
|
|
33
|
+
function ShopShell({ children }: { children: React.ReactNode }) {
|
|
34
|
+
return (
|
|
35
|
+
<div className="shop">
|
|
36
|
+
<NavBar />
|
|
37
|
+
<main>
|
|
38
|
+
<Outlet /> {/* fade applies HERE */}
|
|
39
|
+
</main>
|
|
40
|
+
<Footer />
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const urlpatterns = urls(({ layout, path, transition }) => [
|
|
46
|
+
layout(<ShopShell />, () => [
|
|
47
|
+
transition({ default: "page-fade" }),
|
|
48
|
+
path("/", ShopIndex, { name: "index" }),
|
|
49
|
+
path("/about", AboutPage, { name: "about" }),
|
|
50
|
+
path("/contact", ContactPage, { name: "contact" }),
|
|
51
|
+
]),
|
|
52
|
+
]);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```css
|
|
56
|
+
::view-transition-old(root) {
|
|
57
|
+
animation: fade-out 200ms ease both;
|
|
58
|
+
}
|
|
59
|
+
::view-transition-new(root) {
|
|
60
|
+
animation: fade-in 200ms ease both;
|
|
61
|
+
}
|
|
62
|
+
.page-fade {
|
|
63
|
+
/* class hooks per phase */
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Navigating between `/`, `/about`, and `/contact` morphs the `<Outlet />` content with the `page-fade` class. The shell (NavBar, Footer) does not morph because the wrap sits inside the shell, not around it.
|
|
68
|
+
|
|
69
|
+
## Direction-aware transitions
|
|
70
|
+
|
|
71
|
+
`ViewTransitionClass` accepts an object form keyed by transition type. Rango tags forward navigations as `"navigation"` and back/forward popstate as `"navigation-back"`:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
layout(<ShopShell />, () => [
|
|
75
|
+
transition({
|
|
76
|
+
default: {
|
|
77
|
+
navigation: "slide-left",
|
|
78
|
+
"navigation-back": "slide-right",
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
path("/", ShopIndex, { name: "index" }),
|
|
82
|
+
path("/about", AboutPage, { name: "about" }),
|
|
83
|
+
]);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```css
|
|
87
|
+
.slide-left {
|
|
88
|
+
animation-name: slide-from-right;
|
|
89
|
+
}
|
|
90
|
+
.slide-right {
|
|
91
|
+
animation-name: slide-from-left;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
> Note: `"action"` is only tagged on partial-update action/refetch paths today; ordinary `server-action-bridge` commits (`useAction` / `useActionState` revalidations) are not currently tagged. Don't rely on an `action`-keyed class to fire on every form action.
|
|
96
|
+
|
|
97
|
+
## Wrapper form: applying transition to a group of routes
|
|
98
|
+
|
|
99
|
+
`transition(config, () => [...])` creates a transparent layout that applies the config to its children — useful when you want a transition without authoring a real layout component:
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
urls(({ path, transition }) => [
|
|
103
|
+
// No layout component, but every route inside gets the fade.
|
|
104
|
+
transition({ default: "fade" }, () => [
|
|
105
|
+
path("/", HomePage, { name: "home" }),
|
|
106
|
+
path("/about", AboutPage, { name: "about" }),
|
|
107
|
+
]),
|
|
108
|
+
// Outside the wrapper — no transition applied.
|
|
109
|
+
path("/admin", AdminPage, { name: "admin" }),
|
|
110
|
+
]);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Intercept (modal) interaction
|
|
114
|
+
|
|
115
|
+
This is where the rango-specific behavior pays off. A common shape:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import { urls } from "@rangojs/router";
|
|
119
|
+
import { Outlet, ParallelOutlet } from "@rangojs/router/client";
|
|
120
|
+
|
|
121
|
+
function GalleryShell() {
|
|
122
|
+
return (
|
|
123
|
+
<>
|
|
124
|
+
<NavBar />
|
|
125
|
+
<main>
|
|
126
|
+
<Outlet /> {/* page transition lands here */}
|
|
127
|
+
</main>
|
|
128
|
+
<ParallelOutlet name="@modal" />{" "}
|
|
129
|
+
{/* modal mounts here — sibling of the VT */}
|
|
130
|
+
</>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export const urlpatterns = urls(
|
|
135
|
+
({ layout, path, intercept, transition, loader, loading }) => [
|
|
136
|
+
layout(<GalleryShell />, () => [
|
|
137
|
+
transition({ default: "fade" }),
|
|
138
|
+
|
|
139
|
+
path("/", GalleryFeed, { name: "feed" }),
|
|
140
|
+
path("/photos/:id", PhotoPage, { name: "photo" }),
|
|
141
|
+
|
|
142
|
+
intercept("@modal", "photo", <PhotoModal />, () => [
|
|
143
|
+
loader(PhotoLoader),
|
|
144
|
+
loading(<PhotoModalSkeleton />),
|
|
145
|
+
]),
|
|
146
|
+
]),
|
|
147
|
+
],
|
|
148
|
+
);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
| Action | What fires |
|
|
152
|
+
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
153
|
+
| Navigate `/` ↔ `/about` (within `GalleryShell`) | Layout transition fires; `<Outlet />` content cross-fades |
|
|
154
|
+
| Click `<Link to="/photos/42" />` from `/` | Soft navigation opens `<PhotoModal />` in `@modal`; **no** view transition fires on the underlying feed |
|
|
155
|
+
| Submit a form action inside `<PhotoModal />` | Revalidation commits without firing the layout VT; modal subtree identity is preserved (no remount, `useActionState` survives) |
|
|
156
|
+
| Close modal via `router.back()` | Underlying page is restored; **no** view transition fires |
|
|
157
|
+
| Direct URL load `/photos/42` | Renders the full `<PhotoPage />` with no modal; the layout transition applies on subsequent in-layout navs |
|
|
158
|
+
|
|
159
|
+
The "no VT on modal open" guarantee holds at any depth — if the layout that owns `@modal` is itself nested inside another transitioned layout, the outer transition is pushed past the inner layout into its default outlet content, so the modal slot ends up outside both VTs.
|
|
160
|
+
|
|
161
|
+
## Per-route transition
|
|
162
|
+
|
|
163
|
+
Routes are leaves: their `transition()` wraps the route component itself.
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
urls(({ path, transition }) => [
|
|
167
|
+
path("/checkout", CheckoutPage, { name: "checkout" }, () => [
|
|
168
|
+
transition({ default: "fade-in" }),
|
|
169
|
+
]),
|
|
170
|
+
]);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
This is the right level for one-off route-specific morphs that should not propagate to siblings.
|
|
174
|
+
|
|
175
|
+
## TransitionConfig
|
|
176
|
+
|
|
177
|
+
`transition()` accepts the props of React's `<ViewTransition>` (minus `children`/refs). Each phase prop accepts either a plain class string or an object keyed by transition type:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import type { TransitionConfig } from "@rangojs/router";
|
|
181
|
+
|
|
182
|
+
interface TransitionConfig {
|
|
183
|
+
enter?: string | Record<string, string>;
|
|
184
|
+
exit?: string | Record<string, string>;
|
|
185
|
+
update?: string | Record<string, string>;
|
|
186
|
+
share?: string | Record<string, string>;
|
|
187
|
+
default?: string | Record<string, string>; // fallback for any phase
|
|
188
|
+
name?: string; // explicit view-transition-name
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- `default` is the catch-all if a phase-specific prop is unset.
|
|
193
|
+
- The object form keys are React transition types tagged by rango: `"navigation"` (forward navigations), `"navigation-back"` (popstate cache restores), and `"action"` (partial-update action/refetch paths only — see the caveat in "Direction-aware transitions").
|
|
194
|
+
- `name` lets you participate in cross-page morphs by name (advanced; you usually don't need this on a layout/route-level wrap).
|
|
195
|
+
|
|
196
|
+
## Recommendations
|
|
197
|
+
|
|
198
|
+
**Put `<ParallelOutlet />` in layouts, not routes.** A route-level `transition` wraps the route component itself, so a `<ParallelOutlet />` rendered directly inside that route component remains inside the route VT subtree — modal opens on a route with a parallel outlet _will_ trigger the route's VT walker. The narrowing fix only applies at layout boundaries. If you combine intercept modals with route-level transitions, mount the slot one level up in a layout.
|
|
199
|
+
|
|
200
|
+
**Don't stack `transition()` on every layout level.** When ancestor and descendant layouts both configure transitions, both wraps end up nested around the deepest default outlet content. Two VTs fire on every nav within the inner layout. That's usually not what you want — pick the level where the morph belongs and apply it once.
|
|
201
|
+
|
|
202
|
+
**Need a modal-only morph?** Per-slot `transition()` is currently a no-op at render time, so use an element-level React `<ViewTransition>` inside the modal component (or a CSS animation) for the modal-entrance effect.
|
|
203
|
+
|
|
204
|
+
**Action revalidation inside a modal is safe.** Server-action submits inside an open modal don't fire the underlying layout VT. Modal subtree identity is preserved across revalidation — so `useActionState`, focus, and scroll all survive the round-trip.
|
|
205
|
+
|
|
206
|
+
## Notes
|
|
207
|
+
|
|
208
|
+
- `transition()` is part of the route DSL. The allow-list table in [skills/handler-use](../handler-use/SKILL.md) permits it inside `layout()`, `path()`/`route()`, `parallel()` (per-slot or shared), and `intercept()`. At render time, only the layout and route wraps actually take effect today; `parallel()`/`intercept()` slot-level rendering does not currently apply the wrap.
|
|
209
|
+
- Wrap location for layouts: rango walks the rendered tree past `MountContextProvider`/`OutletProvider`/`LoaderBoundary` for layout segments and applies the wrap at the first non-layout target ([segment-system.tsx](../../src/segment-system.tsx) — `wrapDefaultOutletContent`). This is what keeps parallel slots out of the VT subtree.
|
|
210
|
+
- Tree consistency: the wrapper structure is identical across normal commits, intercept-active commits, and action revalidations — React never sees an element-type swap, so layout/modal subtrees are not remounted across these transitions.
|
|
211
|
+
- Element-level `<ViewTransition>` (importing it directly from React and using `name`/`share` to morph specific elements across pages) composes with rango's segment-level wraps as usual; rango doesn't intercept those.
|
|
212
|
+
- See also: [skills/intercept](../intercept/SKILL.md), [skills/parallel](../parallel/SKILL.md), [skills/layout](../layout/SKILL.md).
|
package/src/__internal.ts
CHANGED
|
@@ -108,7 +108,11 @@ export type {
|
|
|
108
108
|
* @internal
|
|
109
109
|
* Router context for AsyncLocalStorage.
|
|
110
110
|
*/
|
|
111
|
-
export type {
|
|
111
|
+
export type {
|
|
112
|
+
RouterContext,
|
|
113
|
+
RevalidationContext,
|
|
114
|
+
InterceptResult,
|
|
115
|
+
} from "./router/router-context.js";
|
|
112
116
|
|
|
113
117
|
// ============================================================================
|
|
114
118
|
// Match Pipeline (Internal)
|
|
@@ -118,7 +122,10 @@ export type { RouterContext, RevalidationContext, InterceptResult } from "./rout
|
|
|
118
122
|
* @internal
|
|
119
123
|
* Route match context during pipeline processing.
|
|
120
124
|
*/
|
|
121
|
-
export type {
|
|
125
|
+
export type {
|
|
126
|
+
MatchContext,
|
|
127
|
+
MatchPipelineState,
|
|
128
|
+
} from "./router/match-context.js";
|
|
122
129
|
|
|
123
130
|
/**
|
|
124
131
|
* @internal
|
|
@@ -153,10 +160,102 @@ export type {
|
|
|
153
160
|
/**
|
|
154
161
|
* @internal
|
|
155
162
|
* Internal handler context with additional props for router internals.
|
|
156
|
-
* Includes `
|
|
163
|
+
* Includes `_currentSegmentId` and `_responseType`.
|
|
157
164
|
*/
|
|
158
165
|
export type { InternalHandlerContext } from "./types.js";
|
|
159
166
|
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Rendering (Internal)
|
|
169
|
+
// ============================================================================
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @internal
|
|
173
|
+
* Builds React element trees from route segments.
|
|
174
|
+
*/
|
|
175
|
+
export { renderSegments } from "./segment-system.js";
|
|
176
|
+
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// Error Utilities (Internal)
|
|
179
|
+
// ============================================================================
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @internal
|
|
183
|
+
* Error sanitization and network error utilities.
|
|
184
|
+
*/
|
|
185
|
+
export { sanitizeError, NetworkError, isNetworkError } from "./errors.js";
|
|
186
|
+
|
|
187
|
+
// ============================================================================
|
|
188
|
+
// Type Utilities (Internal)
|
|
189
|
+
// ============================================================================
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @internal
|
|
193
|
+
* Scoped view of GeneratedRouteMap for Handler<"localName", ScopedRouteMap<"prefix">>.
|
|
194
|
+
*/
|
|
195
|
+
export type { ScopedRouteMap } from "./types.js";
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @internal
|
|
199
|
+
* Type-level utilities for reverse URL generation.
|
|
200
|
+
*/
|
|
201
|
+
export type { MergeRoutes, SanitizePrefix } from "./reverse.js";
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @internal
|
|
205
|
+
* Individual telemetry event types.
|
|
206
|
+
*/
|
|
207
|
+
export type {
|
|
208
|
+
RequestStartEvent,
|
|
209
|
+
RequestEndEvent,
|
|
210
|
+
RequestErrorEvent,
|
|
211
|
+
RequestTimeoutEvent,
|
|
212
|
+
LoaderStartEvent,
|
|
213
|
+
LoaderEndEvent,
|
|
214
|
+
LoaderErrorEvent,
|
|
215
|
+
HandlerErrorEvent,
|
|
216
|
+
CacheDecisionEvent,
|
|
217
|
+
RevalidationDecisionEvent,
|
|
218
|
+
} from "./router/telemetry.js";
|
|
219
|
+
|
|
220
|
+
// ============================================================================
|
|
221
|
+
// Pre-render / Static Handler Guards (Internal)
|
|
222
|
+
// ============================================================================
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @internal
|
|
226
|
+
* Type guard for prerender handler definitions.
|
|
227
|
+
*/
|
|
228
|
+
export { isPrerenderHandler, isPassthroughHandler } from "./prerender.js";
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @internal
|
|
232
|
+
* Type guard for static handler definitions.
|
|
233
|
+
*/
|
|
234
|
+
export { isStaticHandler } from "./static-handler.js";
|
|
235
|
+
|
|
236
|
+
// ============================================================================
|
|
237
|
+
// URL Pattern Internals
|
|
238
|
+
// ============================================================================
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @internal
|
|
242
|
+
* Sentinel used to tag response-type route entries.
|
|
243
|
+
*/
|
|
244
|
+
export { RESPONSE_TYPE } from "./urls.js";
|
|
245
|
+
|
|
246
|
+
// ============================================================================
|
|
247
|
+
// Route Match Debug (Internal)
|
|
248
|
+
// ============================================================================
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @internal
|
|
252
|
+
* Debug utilities for route matching performance analysis.
|
|
253
|
+
*/
|
|
254
|
+
export {
|
|
255
|
+
enableMatchDebug,
|
|
256
|
+
getMatchDebugStats,
|
|
257
|
+
} from "./router/pattern-matching.js";
|
|
258
|
+
|
|
160
259
|
// ============================================================================
|
|
161
260
|
// Debug Utilities (Internal)
|
|
162
261
|
// ============================================================================
|
|
@@ -172,4 +271,3 @@ export {
|
|
|
172
271
|
type SerializedEntry,
|
|
173
272
|
type SerializedManifest,
|
|
174
273
|
} from "./debug.js";
|
|
175
|
-
|