@rangojs/router 0.20.0 → 0.22.0
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/dist/bin/rango.js +39 -15
- package/dist/types/browser/event-controller.d.ts +49 -0
- package/dist/types/browser/history-state.d.ts +16 -4
- package/dist/types/browser/navigation-store.d.ts +9 -0
- package/dist/types/browser/navigation-transaction.d.ts +7 -0
- package/dist/types/browser/partial-update.d.ts +2 -1
- package/dist/types/browser/prefetch/default-strategy.d.ts +16 -20
- package/dist/types/browser/rango-state.d.ts +3 -1
- package/dist/types/browser/react/NavigationProvider.d.ts +14 -1
- package/dist/types/browser/react/context.d.ts +25 -0
- package/dist/types/browser/react/location-state-shared.d.ts +84 -10
- package/dist/types/browser/react/location-state.d.ts +7 -2
- package/dist/types/browser/rsc-router.d.ts +13 -2
- package/dist/types/browser/types.d.ts +10 -0
- package/dist/types/build/generate-manifest.d.ts +2 -0
- package/dist/types/cache/background-task.d.ts +22 -0
- package/dist/types/cache/cache-key-utils.d.ts +50 -5
- package/dist/types/cache/cache-policy.d.ts +17 -0
- package/dist/types/cache/cache-scope.d.ts +5 -6
- package/dist/types/cache/cf/cf-cache-store.d.ts +34 -7
- package/dist/types/cache/cf/cf-cache-types.d.ts +12 -4
- package/dist/types/cache/document-cache.d.ts +8 -5
- package/dist/types/cache/handle-snapshot.d.ts +59 -50
- package/dist/types/cache/index.d.ts +3 -1
- package/dist/types/cache/invalidation-order.d.ts +14 -0
- package/dist/types/cache/memory-segment-store.d.ts +33 -1
- package/dist/types/cache/shell-snapshot.d.ts +29 -4
- package/dist/types/cache/store-scope.d.ts +22 -0
- package/dist/types/cache/tag-invalidation.d.ts +7 -6
- package/dist/types/cache/types.d.ts +84 -24
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +35 -17
- package/dist/types/client-urls/navigation.d.ts +7 -1
- package/dist/types/client-urls/optimistic-location.d.ts +10 -4
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/handles/deferred-resolution.d.ts +18 -1
- package/dist/types/internal-suspense-audit.d.ts +1 -0
- package/dist/types/loader-store.d.ts +4 -8
- package/dist/types/outlet-provider.d.ts +2 -1
- package/dist/types/prerender/build-shell-capture.d.ts +8 -6
- package/dist/types/prerender/cloudflare.d.ts +49 -0
- package/dist/types/prerender/create-prerender-trigger.d.ts +121 -0
- package/dist/types/prerender/index.d.ts +12 -0
- package/dist/types/prerender/memory-prerender-store.d.ts +29 -0
- package/dist/types/prerender/on-demand.d.ts +272 -0
- package/dist/types/prerender/producer-guard.d.ts +33 -0
- package/dist/types/prerender/shell-manifest-key.d.ts +1 -18
- package/dist/types/prerender/warm-request.d.ts +65 -0
- package/dist/types/prerender/warm.d.ts +65 -0
- package/dist/types/prerender/writable-store.d.ts +170 -0
- package/dist/types/prerender.d.ts +27 -0
- package/dist/types/reverse.d.ts +1 -1
- package/dist/types/route-content-wrapper.d.ts +3 -1
- package/dist/types/router/error-handling.d.ts +2 -0
- package/dist/types/router/handler-context.d.ts +1 -1
- package/dist/types/router/match-middleware/cache-lookup.d.ts +15 -1
- package/dist/types/router/navigation-snapshot.d.ts +8 -1
- package/dist/types/router/pattern-matching.d.ts +2 -0
- package/dist/types/router/prefetch-default.d.ts +4 -4
- package/dist/types/router/prerender-match.d.ts +23 -1
- package/dist/types/router/route-trie-builder.d.ts +8 -1
- package/dist/types/router/router-context.d.ts +1 -0
- package/dist/types/router/router-interfaces.d.ts +32 -1
- package/dist/types/router/router-options.d.ts +39 -5
- package/dist/types/router/segment-resolution/fresh.d.ts +7 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +23 -10
- package/dist/types/router/segment-resolution/revalidation.d.ts +5 -1
- package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +43 -0
- package/dist/types/router/trie-matching.d.ts +2 -0
- package/dist/types/router-versions.d.ts +39 -0
- package/dist/types/rsc/handler-context.d.ts +5 -0
- package/dist/types/rsc/shell-build-manifest.d.ts +9 -6
- package/dist/types/rsc/shell-capture-constants.d.ts +20 -5
- package/dist/types/rsc/shell-capture.d.ts +14 -1
- package/dist/types/rsc/shell-serve.d.ts +2 -2
- package/dist/types/rsc/ssr-module-loader.d.ts +15 -0
- package/dist/types/rsc/types.d.ts +12 -6
- package/dist/types/segment-boundary-content.d.ts +17 -0
- package/dist/types/segment-loader-promise.d.ts +2 -6
- package/dist/types/server/build-version-table.d.ts +53 -0
- package/dist/types/server/context.d.ts +12 -4
- package/dist/types/server/handle-store.d.ts +89 -46
- package/dist/types/server/request-context.d.ts +84 -9
- package/dist/types/suspense-audit-react.d.ts +26 -0
- package/dist/types/suspense-audit.d.ts +157 -0
- package/dist/types/testing/action-form.d.ts +34 -0
- package/dist/types/testing/build-versions.d.ts +32 -0
- package/dist/types/testing/dom.entry.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +3 -1
- package/dist/types/testing/index.d.ts +6 -0
- package/dist/types/testing/internal/seed-vars.d.ts +7 -2
- package/dist/types/testing/internal/server-modules.d.ts +8 -0
- package/dist/types/testing/location-state-key.d.ts +5 -1
- package/dist/types/testing/render-route.d.ts +77 -6
- package/dist/types/testing/serve-shell-request.d.ts +55 -4
- package/dist/types/testing/shell-status.d.ts +14 -6
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +9 -6
- package/dist/types/testing/vitest-stubs/version.d.ts +1 -0
- package/dist/types/thenable-status.d.ts +6 -0
- package/dist/types/types/handler-context.d.ts +15 -5
- package/dist/types/types/route-entry.d.ts +5 -0
- package/dist/types/urls/path-helper.d.ts +18 -0
- package/dist/types/vite/discovery/build-versions.d.ts +393 -0
- package/dist/types/vite/discovery/installed-packages.d.ts +26 -0
- package/dist/types/vite/discovery/router-versions-phase.d.ts +52 -0
- package/dist/types/vite/discovery/shell-prerender-phase.d.ts +7 -17
- package/dist/types/vite/discovery/state.d.ts +25 -0
- package/dist/types/vite/encryption-key.d.ts +18 -0
- package/dist/types/vite/inject-client-debug.d.ts +6 -25
- package/dist/types/vite/plugin-types.d.ts +27 -0
- package/dist/types/vite/plugins/{version-injector.d.ts → entry-bootstrap-injector.d.ts} +4 -6
- package/dist/types/vite/plugins/expose-ids/export-analysis.d.ts +1 -0
- package/dist/types/vite/plugins/expose-ids/router-transform.d.ts +14 -0
- package/dist/types/vite/plugins/stable-rsc-output.d.ts +51 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +9 -11
- package/dist/types/vite/plugins/virtual-entries.d.ts +18 -1
- package/dist/types/vite/router-discovery.d.ts +6 -0
- package/dist/types/vite/utils/bundle-analysis.d.ts +6 -2
- package/dist/types/vite/utils/client-chunks.d.ts +2 -0
- package/dist/types/vite/utils/compare-strings.d.ts +7 -0
- package/dist/types/vite/utils/package-resolution.d.ts +8 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +2 -0
- package/dist/vite/index.js +1707 -931
- package/package.json +12 -3
- package/skills/cache-guide/SKILL.md +102 -37
- package/skills/caching/SKILL.md +56 -9
- package/skills/catalog.json +1 -1
- package/skills/client-urls/SKILL.md +16 -0
- package/skills/cloudflare/SKILL.md +133 -1
- package/skills/comparison/references/framework-comparison.md +17 -13
- package/skills/deployment-caching/SKILL.md +33 -12
- package/skills/document-cache/SKILL.md +16 -14
- package/skills/hooks/SKILL.md +25 -0
- package/skills/hooks/handle-and-actions.md +5 -0
- package/skills/hooks/navigation.md +38 -0
- package/skills/hooks/state.md +213 -11
- package/skills/hooks/urls.md +40 -1
- package/skills/host-router/SKILL.md +31 -0
- package/skills/intercept/SKILL.md +6 -0
- package/skills/loader/SKILL.md +25 -5
- package/skills/middleware/SKILL.md +2 -0
- package/skills/migrate-nextjs/SKILL.md +82 -9
- package/skills/ppr/SKILL.md +150 -48
- package/skills/prerender/SKILL.md +651 -10
- package/skills/rango/SKILL.md +9 -7
- package/skills/response-routes/SKILL.md +5 -5
- package/skills/route/SKILL.md +29 -0
- package/skills/router-setup/SKILL.md +15 -1
- package/skills/testing/SKILL.md +32 -27
- package/skills/testing/cache-prerender.md +18 -17
- package/skills/testing/client-components.md +193 -8
- package/skills/testing/handles.md +2 -0
- package/skills/testing/loader.md +1 -1
- package/skills/testing/middleware.md +1 -1
- package/skills/testing/render-handler.md +18 -18
- package/skills/testing/serve-shell-request.md +167 -22
- package/skills/testing/server-actions.md +17 -17
- package/skills/testing/server-tree.md +1 -1
- package/skills/typesafety/generated-files-and-cli.md +1 -1
- package/skills/use-cache/SKILL.md +25 -10
- package/skills/vercel/SKILL.md +5 -3
- package/skills/view-transitions/SKILL.md +9 -4
- package/src/bin/rango.ts +1 -1
- package/src/browser/event-controller.ts +119 -2
- package/src/browser/history-state.ts +39 -17
- package/src/browser/link-interceptor.ts +2 -2
- package/src/browser/navigation-bridge.ts +104 -41
- package/src/browser/navigation-store.ts +26 -0
- package/src/browser/navigation-transaction.ts +24 -12
- package/src/browser/network-error-handler.ts +2 -0
- package/src/browser/partial-update.ts +58 -14
- package/src/browser/prefetch/default-strategy.ts +22 -42
- package/src/browser/rango-state.ts +3 -1
- package/src/browser/react/Link.tsx +37 -43
- package/src/browser/react/NavigationProvider.tsx +85 -1
- package/src/browser/react/context.ts +30 -0
- package/src/browser/react/location-state-shared.ts +200 -34
- package/src/browser/react/location-state.ts +28 -77
- package/src/browser/react/use-action.ts +4 -1
- package/src/browser/react/use-handle.ts +3 -0
- package/src/browser/react/use-link-status.ts +4 -3
- package/src/browser/react/use-navigation.ts +4 -1
- package/src/browser/react/use-params.ts +4 -1
- package/src/browser/react/use-pathname.ts +4 -1
- package/src/browser/react/use-search-params.ts +5 -3
- package/src/browser/react/use-segments.ts +36 -54
- package/src/browser/rsc-router.tsx +93 -31
- package/src/browser/segment-reconciler.ts +3 -3
- package/src/browser/server-action-bridge.ts +43 -7
- package/src/browser/types.ts +11 -0
- package/src/build/generate-manifest.ts +17 -0
- package/src/build/merge-full-manifests.ts +5 -0
- package/src/build/route-trie.ts +1 -0
- package/src/cache/background-task.ts +61 -0
- package/src/cache/cache-key-utils.ts +91 -12
- package/src/cache/cache-policy.ts +11 -2
- package/src/cache/cache-runtime.ts +23 -23
- package/src/cache/cache-scope.ts +48 -36
- package/src/cache/cf/cf-cache-store.ts +91 -66
- package/src/cache/cf/cf-cache-types.ts +12 -4
- package/src/cache/document-cache.ts +35 -14
- package/src/cache/handle-snapshot.ts +118 -86
- package/src/cache/index.ts +5 -0
- package/src/cache/invalidation-order.ts +53 -0
- package/src/cache/memory-segment-store.ts +52 -1
- package/src/cache/shell-snapshot.ts +52 -5
- package/src/cache/store-scope.ts +36 -0
- package/src/cache/tag-invalidation.ts +7 -5
- package/src/cache/types.ts +90 -24
- package/src/cache/vercel/vercel-cache-store.ts +68 -26
- package/src/client-urls/client-root.tsx +1 -0
- package/src/client-urls/navigation.ts +10 -0
- package/src/client-urls/optimistic-location.ts +10 -4
- package/src/client.tsx +40 -3
- package/src/errors.ts +13 -6
- package/src/handles/deferred-resolution.ts +36 -0
- package/src/internal-suspense-audit.ts +12 -0
- package/src/loader-store.ts +4 -9
- package/src/outlet-provider.tsx +25 -1
- package/src/prerender/build-shell-capture.ts +11 -9
- package/src/prerender/cloudflare.ts +130 -0
- package/src/prerender/create-prerender-trigger.ts +780 -0
- package/src/prerender/index.ts +39 -0
- package/src/prerender/memory-prerender-store.ts +115 -0
- package/src/prerender/on-demand.ts +339 -0
- package/src/prerender/producer-guard.ts +66 -0
- package/src/prerender/shell-manifest-key.ts +12 -17
- package/src/prerender/warm-request.ts +154 -0
- package/src/prerender/warm.ts +193 -0
- package/src/prerender/writable-store.ts +278 -0
- package/src/prerender.ts +29 -0
- package/src/reverse.ts +1 -1
- package/src/route-content-wrapper.tsx +107 -13
- package/src/router/error-handling.ts +12 -12
- package/src/router/find-match.ts +1 -0
- package/src/router/handler-context.ts +2 -0
- package/src/router/intercept-resolution.ts +15 -8
- package/src/router/loader-resolution.ts +2 -10
- package/src/router/manifest.ts +2 -0
- package/src/router/match-middleware/background-revalidation.ts +2 -0
- package/src/router/match-middleware/cache-lookup.ts +239 -54
- package/src/router/navigation-snapshot.ts +25 -6
- package/src/router/pattern-matching.ts +14 -0
- package/src/router/prefetch-default.ts +4 -4
- package/src/router/prerender-match.ts +460 -352
- package/src/router/request-classification.ts +15 -12
- package/src/router/route-trie-builder.ts +9 -0
- package/src/router/router-context.ts +1 -0
- package/src/router/router-interfaces.ts +35 -1
- package/src/router/router-options.ts +45 -5
- package/src/router/segment-resolution/fresh.ts +20 -19
- package/src/router/segment-resolution/loader-cache.ts +110 -77
- package/src/router/segment-resolution/revalidation.ts +34 -24
- package/src/router/segment-resolution/streamed-handler-boundary.ts +133 -0
- package/src/router/trie-matching.ts +3 -0
- package/src/router-versions.ts +60 -0
- package/src/router.ts +107 -1
- package/src/rsc/full-payload.ts +6 -2
- package/src/rsc/handler-context.ts +5 -0
- package/src/rsc/handler.ts +64 -7
- package/src/rsc/progressive-enhancement.ts +5 -1
- package/src/rsc/response-cache-serve.ts +10 -4
- package/src/rsc/rsc-rendering.ts +65 -12
- package/src/rsc/shell-build-manifest.ts +17 -12
- package/src/rsc/shell-capture-constants.ts +39 -7
- package/src/rsc/shell-capture.ts +144 -45
- package/src/rsc/shell-serve.ts +12 -6
- package/src/rsc/ssr-module-loader.ts +26 -0
- package/src/rsc/types.ts +12 -6
- package/src/segment-boundary-content.ts +25 -0
- package/src/segment-loader-promise.ts +28 -38
- package/src/segment-system.tsx +117 -57
- package/src/server/build-version-table.ts +130 -0
- package/src/server/context.ts +40 -17
- package/src/server/cookie-store.ts +5 -0
- package/src/server/handle-store.ts +357 -127
- package/src/server/request-context.ts +149 -12
- package/src/ssr/ssr-root.tsx +32 -13
- package/src/suspense-audit-react.tsx +98 -0
- package/src/suspense-audit.ts +1030 -0
- package/src/testing/action-form.ts +66 -0
- package/src/testing/build-versions.ts +64 -0
- package/src/testing/dispatch.ts +6 -0
- package/src/testing/dom.entry.ts +1 -0
- package/src/testing/flight-runtime.d.ts +27 -0
- package/src/testing/flight.entry.ts +4 -0
- package/src/testing/index.ts +22 -0
- package/src/testing/internal/context.ts +2 -1
- package/src/testing/internal/seed-vars.ts +14 -2
- package/src/testing/internal/server-modules.ts +32 -0
- package/src/testing/location-state-key.ts +18 -8
- package/src/testing/render-handler.ts +2 -1
- package/src/testing/render-route.tsx +293 -46
- package/src/testing/serve-shell-request.ts +262 -37
- package/src/testing/shell-status.ts +17 -6
- package/src/testing/vitest-stubs/plugin-rsc.ts +37 -11
- package/src/testing/vitest-stubs/version.ts +4 -1
- package/src/thenable-status.ts +10 -0
- package/src/types/handler-context.ts +15 -5
- package/src/types/route-entry.ts +6 -0
- package/src/urls/path-helper.ts +69 -9
- package/src/use-loader.tsx +57 -30
- package/src/vite/discovery/build-versions.ts +1281 -0
- package/src/vite/discovery/bundle-postprocess.ts +4 -0
- package/src/vite/discovery/discover-routers.ts +15 -0
- package/src/vite/discovery/installed-packages.ts +159 -0
- package/src/vite/discovery/prerender-collection.ts +38 -1
- package/src/vite/discovery/router-versions-phase.ts +336 -0
- package/src/vite/discovery/shell-prerender-phase.ts +33 -43
- package/src/vite/discovery/state.ts +36 -1
- package/src/vite/discovery/virtual-module-codegen.ts +7 -2
- package/src/vite/encryption-key.ts +101 -9
- package/src/vite/inject-client-debug.ts +42 -20
- package/src/vite/plugin-types.ts +28 -0
- package/src/vite/plugins/{version-injector.ts → entry-bootstrap-injector.ts} +7 -22
- package/src/vite/plugins/expose-ids/export-analysis.ts +1 -1
- package/src/vite/plugins/expose-ids/router-transform.ts +36 -15
- package/src/vite/plugins/expose-internal-ids.ts +12 -3
- package/src/vite/plugins/stable-rsc-output.ts +147 -0
- package/src/vite/plugins/version-plugin.ts +19 -24
- package/src/vite/plugins/version.d.ts +17 -2
- package/src/vite/plugins/virtual-entries.ts +39 -6
- package/src/vite/rango.ts +28 -3
- package/src/vite/router-discovery.ts +96 -13
- package/src/vite/utils/bundle-analysis.ts +39 -7
- package/src/vite/utils/client-chunks.ts +5 -1
- package/src/vite/utils/compare-strings.ts +9 -0
- package/src/vite/utils/package-resolution.ts +9 -0
- package/src/vite/utils/prerender-utils.ts +4 -1
- package/src/vite/utils/shared-utils.ts +1 -1
- package/dist/types/segment-content-promise.d.ts +0 -13
- package/src/segment-content-promise.ts +0 -67
package/skills/rango/SKILL.md
CHANGED
|
@@ -116,6 +116,7 @@ stated, greppable contract.
|
|
|
116
116
|
| set meta/breadcrumbs from loader data | `ctx.use(Handle)` in the loader | /loader |
|
|
117
117
|
| guarantee loader output in the SSR HTML | `loader(L, { ssr: false })` | /loader |
|
|
118
118
|
| pre-render a route at build time | `Prerender(...)` wrapper | /prerender |
|
|
119
|
+
| make a route ready before traffic | `router.prerender({ env })(url)` | /prerender |
|
|
119
120
|
| feed live loaders from a cached shell | replayed handle + `ctx.rendered()` | /shell-manifest |
|
|
120
121
|
| cache HTML shell, live loaders as holes | `ppr` path option | /ppr |
|
|
121
122
|
| choose in-function vs CDN caching | deployment cache boundary | /deployment-caching |
|
|
@@ -157,8 +158,9 @@ stated, greppable contract.
|
|
|
157
158
|
`cacheTag(...tags)`, then `updateTag(...tags)` (awaitable) or `revalidateTag(...tags)`
|
|
158
159
|
(background). Built-in stores index by tag.
|
|
159
160
|
- `useLoader` / `useHandle` / `useFetchLoader` are client-only.
|
|
160
|
-
- Caches are correctness-first: persistent store keys are version-segmented
|
|
161
|
-
|
|
161
|
+
- Caches are correctness-first: persistent store keys are version-segmented per
|
|
162
|
+
`createRouter()` by a hash of its built code (a deploy that does not change a
|
|
163
|
+
router keeps its cache; one that does reads under new keys), the forward/back cache is mutation-aware, and
|
|
162
164
|
`createVar({ cache: false })` throws on a **direct** read inside a `cache()`
|
|
163
165
|
boundary or a `"use cache"` function (a deliberately non-propagating guard). See `/cache-guide` →
|
|
164
166
|
"Correctness & invalidation".
|
|
@@ -422,11 +424,11 @@ npx rango generate src/urls.tsx src/api/
|
|
|
422
424
|
|
|
423
425
|
Three modes:
|
|
424
426
|
|
|
425
|
-
| Flag | Behavior
|
|
426
|
-
| ----------- |
|
|
427
|
-
| (none) | Static parser. Exits with an error, writing nothing, if an `include()` can't be resolved statically (factory or dynamic).
|
|
428
|
-
| `--static` | Static parser, but writes partial output and prints the unresolvable includes as warnings.
|
|
429
|
-
| `--runtime` | Vite-based runtime discovery (full coverage; needs `vite
|
|
427
|
+
| Flag | Behavior |
|
|
428
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
429
|
+
| (none) | Static parser. Exits with an error, writing nothing, if an `include()` can't be resolved statically (factory or dynamic). |
|
|
430
|
+
| `--static` | Static parser, but writes partial output and prints the unresolvable includes as warnings. |
|
|
431
|
+
| `--runtime` | Vite-based runtime discovery (full coverage; needs `vite`; `@vitejs/plugin-rsc` comes with the router). `--config <path>` picks the config. |
|
|
430
432
|
|
|
431
433
|
### Auto-detection
|
|
432
434
|
|
|
@@ -422,11 +422,11 @@ path.json("/api/users", handler, { name: "users" }, () => [
|
|
|
422
422
|
Response-route `cache()` stores whole `Response`s. The serve leaf
|
|
423
423
|
(`serveResponseRouteWithCache`) applies the same safety gates as document cache:
|
|
424
424
|
|
|
425
|
-
| Gate | Behavior
|
|
426
|
-
| ---------------------- |
|
|
427
|
-
| **GET/HEAD only** | Non-GET/HEAD methods skip the cache (handler runs uncached).
|
|
428
|
-
| **Per-client signals** | A response with `Set-Cookie` or `x-rango-keep-cache` is returned live but **not** stored (MISS + SWR revalidation also skip put).
|
|
429
|
-
| **Default key** | `response:{type}:{
|
|
425
|
+
| Gate | Behavior |
|
|
426
|
+
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
427
|
+
| **GET/HEAD only** | Non-GET/HEAD methods skip the cache (handler runs uncached). |
|
|
428
|
+
| **Per-client signals** | A response with `Set-Cookie` or `x-rango-keep-cache` is returned live but **not** stored (MISS + SWR revalidation also skip put). |
|
|
429
|
+
| **Default key** | `response:{type}:{routerId}@{host}{path}[?search]` — the serving router's id, sorted search, reserved `_rsc*` / allowlisted `__*` params excluded. Custom `key()` / store `keyGenerator` still override. |
|
|
430
430
|
|
|
431
431
|
## CSRF
|
|
432
432
|
|
package/skills/route/SKILL.md
CHANGED
|
@@ -404,6 +404,35 @@ path("/checkout", CheckoutPage, { name: "checkout" }, () => [
|
|
|
404
404
|
]);
|
|
405
405
|
```
|
|
406
406
|
|
|
407
|
+
## Errors in a streamed handler
|
|
408
|
+
|
|
409
|
+
A handler under `loading()` (a route, or a parallel slot) streams: it settles
|
|
410
|
+
after the response started. When it rejects, the nearest `errorBoundary()`
|
|
411
|
+
renders in place of that segment; `notFound()` renders the nearest
|
|
412
|
+
`notFoundBoundary()`. A slot finds boundaries declared on its owning layout or
|
|
413
|
+
route. Layouts and nav stay, on the document load and on a client navigation.
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
path("/product/:slug", ProductPage, { name: "product" }, () => [
|
|
417
|
+
loading(<ProductSkeleton />),
|
|
418
|
+
errorBoundary(({ error }) => <ProductError message={error.message} />),
|
|
419
|
+
notFoundBoundary(() => <ProductNotFound />),
|
|
420
|
+
]);
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
- The HTTP status stays what the stream already sent (200), `notFound()`
|
|
424
|
+
included; a failure before the flush (no `loading()`, or
|
|
425
|
+
`loading(fallback, { ssr: false })` on a document load) still sets 500 / 404.
|
|
426
|
+
A loader's 404 is likewise only set when its rejection settles before the
|
|
427
|
+
response is built.
|
|
428
|
+
- `onError` fires once per failure.
|
|
429
|
+
- A failed render is never stored: `cache()` skips the write for the scope that
|
|
430
|
+
holds the failed segment, a `ppr` shell and the document cache refuse the
|
|
431
|
+
whole document, and a Prerender route still fails the build.
|
|
432
|
+
- With no declared boundary the rejection reaches the client and
|
|
433
|
+
`RootErrorBoundary` replaces the page. A `redirect()` thrown from a streamed
|
|
434
|
+
handler is not recovered either (see "Redirects").
|
|
435
|
+
|
|
407
436
|
## Redirects
|
|
408
437
|
|
|
409
438
|
`redirect(url, statusOrOptions?)` returns a `Response` (default status `302`).
|
|
@@ -170,7 +170,7 @@ interface RangoOptions<TEnv> {
|
|
|
170
170
|
request: Request,
|
|
171
171
|
env: TEnv,
|
|
172
172
|
) => string | boolean | Promise<string | boolean>;
|
|
173
|
-
version?: string; //
|
|
173
|
+
version?: string; // Cache version and client/server version; replaces both computed versions (data and document); defaults to the versions `vite build` computes per router
|
|
174
174
|
originCheck?:
|
|
175
175
|
| boolean
|
|
176
176
|
| ((
|
|
@@ -215,6 +215,7 @@ rango({
|
|
|
215
215
|
headScripts: "preinit", // "preinit" (executing head module scripts) | "preload" (modulepreload hints only)
|
|
216
216
|
prerender: { onError: "fail" }, // "fail" | "warn" when a Prerender/Static render throws (/prerender)
|
|
217
217
|
buildEnv: false, // Build-time ctx.env for Prerender/Static handlers (/prerender)
|
|
218
|
+
encryptionKey: process.env.RANGO_ENCRYPTION_KEY, // Stable server-action encryption key (see Notes)
|
|
218
219
|
});
|
|
219
220
|
```
|
|
220
221
|
|
|
@@ -254,6 +255,19 @@ Notes:
|
|
|
254
255
|
renders and PPR shell capture. Unset, documents whose route has a
|
|
255
256
|
`loader(Def, { ssr: false })` raise it automatically so that content stays
|
|
256
257
|
in place; see `/loader`.
|
|
258
|
+
- `encryptionKey` is the key that encrypts inline server-action bound
|
|
259
|
+
arguments: base64-encoded 32 bytes (`openssl rand -base64 32`). Pass it as
|
|
260
|
+
`rango({ encryptionKey: process.env.RANGO_ENCRYPTION_KEY })`, never as a
|
|
261
|
+
literal. It is validated when `rango()` is called (invalid base64 or a wrong
|
|
262
|
+
size throws). `undefined` falls back to the `RANGO_ENCRYPTION_KEY`
|
|
263
|
+
environment variable, then to a key generated per build. The key is part of
|
|
264
|
+
the cache version of every router whose server code encrypts inline-action
|
|
265
|
+
bound arguments, so without a stable key those routers get a new version (and
|
|
266
|
+
a cleared cache) on every build; the build prints one note when that applies.
|
|
267
|
+
A router that renders no such action keeps its cache without one (`/use-cache`,
|
|
268
|
+
`/cache-guide`).
|
|
269
|
+
- `createRouter({ version })` takes effect on every preset, including `node`
|
|
270
|
+
and `vercel`. It replaces both computed cache versions with that exact value.
|
|
257
271
|
- `@rangojs/router/vite` also exports `poke()`, a dev-server plugin: type `e`
|
|
258
272
|
then Enter (or Ctrl+R where the terminal passes it through) to full-reload
|
|
259
273
|
the browser.
|
package/skills/testing/SKILL.md
CHANGED
|
@@ -89,32 +89,36 @@ The single rule that drives everything:
|
|
|
89
89
|
|
|
90
90
|
Each primitive links to its sub-file (API + recipe + caveats).
|
|
91
91
|
|
|
92
|
-
| The behavior is… | Layer | Primitive
|
|
93
|
-
| ---------------------------------------------------------------------------------------------------------------------------------- | ------------ |
|
|
94
|
-
| a `reverse` / `href` / params / env TYPE contract (a wrong name or missing param must not compile) | types (tsc) | [`@ts-expect-error` / `expectTypeOf`](./reverse-and-types.md)
|
|
95
|
-
| one loader's data logic | unit (node) | [`runLoader`](./loader.md)
|
|
96
|
-
| a loader's cookie / header / thrown `redirect()`/`notFound()` / handle-push output | unit (node) | [`runLoaderResult`](./loader.md)
|
|
97
|
-
| one middleware's ordering / short-circuit / cookie+header merge | unit (node) | [`runMiddleware`](./middleware.md)
|
|
98
|
-
| a `"use server"` action's cookie / header / flash output (even on `throw redirect()`) | unit (node) | [`runInRequestContext`](./server-actions.md)
|
|
99
|
-
| a `transition({ when })` browser predicate against `{ kind, from, to, action }` | unit (node) | [`runTransitionWhen`](./predicates.md) (`{ applied, gatedOff, context }`)
|
|
100
|
-
| a `clientUrls()` `revalidate()` / `isAction(ref)` predicate | unit (node) | [`runClientRevalidate`](./predicates.md) (production chain evaluator + locked defaults)
|
|
101
|
-
| a handle's `collect`/accumulator, a seeded handle read, or a loader handle write | unit | [`collectHandle` / seeded `handles` / `handlePushes`](./handles.md)
|
|
102
|
-
| a CLIENT component reading router context (`useParams`/`useReverse`/`Outlet`/`useNavigation`/`useLoader`) | unit (DOM) | [`renderRoute`](./client-components.md)
|
|
103
|
-
| a stale indicator from `useLoader().isLoading` while a `transition()` navigation re-runs the loader | unit (DOM) | [`renderRoute` + `navigate(url, { loaders })`](./client-components.md#held-navigation)
|
|
104
|
-
| a component reading `useLocationState(Def)` after `router.push(url, { state: [Def(value)] })` | unit (DOM) | [`renderRoute` + `withLocationStateKey`](./client-components.md#location-state)
|
|
105
|
-
|
|
|
106
|
-
| a
|
|
107
|
-
|
|
|
108
|
-
| a
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
| a
|
|
112
|
-
|
|
|
113
|
-
| cache hit
|
|
114
|
-
| a `
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
| a
|
|
92
|
+
| The behavior is… | Layer | Primitive | Import root |
|
|
93
|
+
| ---------------------------------------------------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
|
|
94
|
+
| a `reverse` / `href` / params / env TYPE contract (a wrong name or missing param must not compile) | types (tsc) | [`@ts-expect-error` / `expectTypeOf`](./reverse-and-types.md) | `@rangojs/router/client` + `tsc` |
|
|
95
|
+
| one loader's data logic | unit (node) | [`runLoader`](./loader.md) | `@rangojs/router/testing` |
|
|
96
|
+
| a loader's cookie / header / thrown `redirect()`/`notFound()` / handle-push output | unit (node) | [`runLoaderResult`](./loader.md) | `@rangojs/router/testing` |
|
|
97
|
+
| one middleware's ordering / short-circuit / cookie+header merge | unit (node) | [`runMiddleware`](./middleware.md) | `@rangojs/router/testing` |
|
|
98
|
+
| a `"use server"` action's cookie / header / flash output (even on `throw redirect()`) | unit (node) | [`runInRequestContext`](./server-actions.md) | `@rangojs/router/testing` |
|
|
99
|
+
| a `transition({ when })` browser predicate against `{ kind, from, to, action }` | unit (node) | [`runTransitionWhen`](./predicates.md) (`{ applied, gatedOff, context }`) | `@rangojs/router/testing` |
|
|
100
|
+
| a `clientUrls()` `revalidate()` / `isAction(ref)` predicate | unit (node) | [`runClientRevalidate`](./predicates.md) (production chain evaluator + locked defaults) | `@rangojs/router/testing` |
|
|
101
|
+
| a handle's `collect`/accumulator, a seeded handle read, or a loader handle write | unit | [`collectHandle` / seeded `handles` / `handlePushes`](./handles.md) | `@rangojs/router/testing` |
|
|
102
|
+
| a CLIENT component reading router context (`useParams`/`useReverse`/`Outlet`/`useNavigation`/`useLoader`) | unit (DOM) | [`renderRoute`](./client-components.md) | `@rangojs/router/testing/dom` |
|
|
103
|
+
| a stale indicator from `useLoader().isLoading` while a `transition()` navigation re-runs the loader | unit (DOM) | [`renderRoute` + `navigate(url, { loaders })`](./client-components.md#held-navigation) | `@rangojs/router/testing/dom` |
|
|
104
|
+
| a component reading `useLocationState(Def)` after `router.push(url, { state: [Def(value)] })` | unit (DOM) | [`renderRoute` + `withLocationStateKey`](./client-components.md#location-state) | `@rangojs/router/testing[/dom]` |
|
|
105
|
+
| location state while a navigation is pending (a loader the test holds), or after a back/forward | unit (DOM) | [`navigate(url, { state, loaders })`, a `popstate` event](./client-components.md#state-while-a-navigation-is-pending) | `@rangojs/router/testing[/dom]` |
|
|
106
|
+
| a CLIENT component's hydration: its first client render against its own server HTML (`typeof window`, a late `<Suspense>`) | unit (DOM) | [`renderRoute` + `hydrate: true`](./client-components.md#hydration) | `@rangojs/router/testing/dom` |
|
|
107
|
+
| location state with `clearOnReload`: state after a refresh vs a client navigation | unit (DOM) | [`renderRoute` seeds, with and without `hydrate: true`](./client-components.md#location-state) | `@rangojs/router/testing[/dom]` |
|
|
108
|
+
| a redirect / status / headers / cookies / **response route** (json/text/html/xml/md), no Flight | integration | [`dispatch`](./response-routes.md) | `@rangojs/router/testing` |
|
|
109
|
+
| a real async **Server Component** (assert what it rendered: typed boundary props, server-rendered host content, inlined-vs-island) | RSC unit | [`renderServerTree` + `findClientBoundaries`/`findElements`](./server-tree.md) | `@rangojs/router/testing/flight` |
|
|
110
|
+
| the exact Flight **wire payload** shape (a drift snapshot) | RSC unit | [`renderToFlightString` + `toMatchFlightSnapshot`](./flight.md) | `@rangojs/router/testing/flight` |
|
|
111
|
+
| a real route **handler** `(ctx) => rsc` (params/loaders/vars -> rendered RSC + effects) | RSC unit | [`renderHandler`](./render-handler.md) | `@rangojs/router/testing/flight` |
|
|
112
|
+
| navigation, hydration, PE parity, view transitions, real SSR | e2e | [`createRangoE2E` -> `parityDescribe`/`expectParity`](./e2e-parity.md) | `@rangojs/router/testing/e2e` |
|
|
113
|
+
| a `"use cache"` hit in a handler (the body runs once across renders; the value round-trips) | RSC unit | [`renderHandler` + seeded `cacheStore`](./render-handler.md#a-use-cache-hit) | `@rangojs/router/testing/flight` |
|
|
114
|
+
| a `"use cache"` hit in a loader (the same, in the react-server project) | RSC unit | [`runLoader` + seeded `cacheStore`](./loader.md) | `@rangojs/router/testing` |
|
|
115
|
+
| a loader's own `cache()` (HIT, `updateTag()` of a tag its body recorded) | RSC unit | [`runLoader` + `cache` + seeded `cacheStore`](./loader.md) | `@rangojs/router/testing` |
|
|
116
|
+
| cache hit/miss/stale, prerender (= a cache hit by design) | e2e + signal | [`assertCacheStatus` (header) / `assertCacheDecision` (telemetry sink)](./cache-prerender.md) | `@rangojs/router/testing[/e2e]` |
|
|
117
|
+
| a `ppr` route's shell: MISS -> capture -> HIT, what the shell froze vs what a HIT renders live, tag eviction, navigation replay | RSC unit | [`serveShellRequest`](./serve-shell-request.md) | `@rangojs/router/testing/flight` |
|
|
118
|
+
| a form submitted before hydration: a `useActionState` result the no-JS POST renders, the form state its payload carries | RSC unit | [`createActionForm` + `serveShellRequest({ form })`](./serve-shell-request.md) | `@rangojs/router/testing/flight` |
|
|
119
|
+
| PPR shell HIT/MISS in real HTML (`ppr` path option), shell store key / getShell after flush | e2e + signal | [`assertShellStatus` / `shellCacheKey` + store](./cache-prerender.md#ppr-shell-and-navigation-replay) | `@rangojs/router/testing[/e2e]` |
|
|
120
|
+
| generated route map drift vs runtime | unit (node) | [`assertGeneratedRoutesMatch`](./reverse-and-types.md) | `@rangojs/router/testing` |
|
|
121
|
+
| a platform binding (`env.DB` / Durable Object / `env.R2`) | unit/integr. | [your own double via `env`](./bindings.md) | (any primitive's `env` option) |
|
|
118
122
|
|
|
119
123
|
Cross-references to the DSL skills: `/loader`, `/middleware`, `/server-actions`,
|
|
120
124
|
`/handler-use`, `/hooks`, `/response-routes`, `/route`, `/caching`, `/prerender`,
|
|
@@ -147,6 +151,7 @@ beside their function):
|
|
|
147
151
|
| | `collectHandle` | [`handles.md`](./handles.md) |
|
|
148
152
|
| | `withLocationStateKey` | [`client-components.md`](./client-components.md) |
|
|
149
153
|
| | `dispatch` | [`response-routes.md`](./response-routes.md) |
|
|
154
|
+
| | `setBuildVersions` | [`serve-shell-request.md`](./serve-shell-request.md) |
|
|
150
155
|
| | `assertCacheStatus`, `assertCacheDecision`, `parseCacheHeader`, `createCacheSink`, `filterCacheDecisions` | [`cache-prerender.md`](./cache-prerender.md) |
|
|
151
156
|
| | `assertShellStatus`, `parseShellStatus`, `shellCacheKey`, `SHELL_STATUS_HEADER`, `assertPprReplayStatus`, `parsePprReplayStatus`, `PPR_REPLAY_STATUS_HEADER` | [`cache-prerender.md`](./cache-prerender.md) |
|
|
152
157
|
| | `assertGeneratedRoutesMatch`, `diffGeneratedRoutes` | [`reverse-and-types.md`](./reverse-and-types.md) |
|
|
@@ -154,7 +159,7 @@ beside their function):
|
|
|
154
159
|
| `@rangojs/router/testing/flight` | `renderToFlightString`, `normalizeFlight`, `assertFlightRuntimeAvailable` | [`flight.md`](./flight.md) |
|
|
155
160
|
| | `renderServerTree`, `findClientBoundaries`, `findElements`, `textContent`, `assertFlightTreeRuntimeAvailable` | [`server-tree.md`](./server-tree.md) |
|
|
156
161
|
| | `renderHandler` | [`render-handler.md`](./render-handler.md) |
|
|
157
|
-
| | `serveShellRequest`, `resetShellTestState`
|
|
162
|
+
| | `serveShellRequest`, `resetShellTestState`, `createActionForm` | [`serve-shell-request.md`](./serve-shell-request.md) |
|
|
158
163
|
| `@rangojs/router/testing/flight-matchers` | `flightMatchers` (`toMatchFlight`, `toMatchFlightSnapshot`) | [`flight.md`](./flight.md) |
|
|
159
164
|
| `@rangojs/router/testing/vitest` | `rangoTestConfig`, `rangoTestAliases`, `rangoInlineDeps`, `rangoUseClientTransform`, `rangoUseCacheTransform` | [`setup.md`](./setup.md) |
|
|
160
165
|
| `@rangojs/router/testing/e2e` | `createRangoE2E` and its standalone helpers; the cache/shell status helpers above are re-exported here | [`e2e-parity.md`](./e2e-parity.md) |
|
|
@@ -121,25 +121,25 @@ expect(decision.segments?.[0].shouldRevalidate).toBe(true);
|
|
|
121
121
|
|
|
122
122
|
**DSL:** `ppr: true | PartialPrerenderProps` on a page route (see `/ppr`). **Not** the same header as `X-Rango-Cache` — the shell is cached separately from the segments.
|
|
123
123
|
|
|
124
|
-
| Helper
|
|
125
|
-
|
|
|
126
|
-
| `assertShellStatus(res, "HIT" \| "MISS")`
|
|
127
|
-
| `parseShellStatus(res)`
|
|
128
|
-
| `shellCacheKey(url, searchParams?, partition?)` | same | Production shell store key (`host+pathname+sorted search+:shell`, then `\|partition`) for `store.getShell` / custom stores. Pass your router's `cache.searchParams` config as the second argument when it sets one — the production key applies it. For a route whose `cache({ key })` partitions its record, pass that function's result for the request as `partition`: the shell is partitioned the same way, the result namespaced as production stores it (`key:` plus its URI encoding). Under nested keyed `cache()` boundaries, pass their `key()` results as an array, outermost first. For a store `keyGenerator` that partitions it, pass `{ keys, generated }` (`ShellCachePartition`): `generated` lists the `keyGenerator` results one per store, outermost first: leave them out when every one returns the default key, else keep each position and pass `""` for one that returns it. |
|
|
129
|
-
| `SHELL_STATUS_HEADER`
|
|
130
|
-
| `assertPprReplayStatus(res, expected)`
|
|
131
|
-
| `parsePprReplayStatus(res)`
|
|
132
|
-
| `PPR_REPLAY_STATUS_HEADER`
|
|
124
|
+
| Helper | Import | Role |
|
|
125
|
+
| ------------------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
126
|
+
| `assertShellStatus(res, "HIT" \| "MISS")` | `@rangojs/router/testing` or `…/e2e` | Assert `x-rango-shell` on a **real document** Response |
|
|
127
|
+
| `parseShellStatus(res)` | same | `"HIT" \| "MISS" \| null` (null = header absent / unrecognized) |
|
|
128
|
+
| `shellCacheKey(router, url, searchParams?, partition?)` | same | Production shell store key (`routerId@host+pathname+sorted search+:shell`, then `\|partition`) for `store.getShell` / custom stores. `router` is the router that serves the URL, or `{ id }` where it cannot be imported (a Playwright test): a shell belongs to one router. Pass your router's `cache.searchParams` config as the second argument when it sets one — the production key applies it. For a route whose `cache({ key })` partitions its record, pass that function's result for the request as `partition`: the shell is partitioned the same way, the result namespaced as production stores it (`key:` plus its URI encoding). Under nested keyed `cache()` boundaries, pass their `key()` results as an array, outermost first. For a store `keyGenerator` that partitions it, pass `{ keys, generated }` (`ShellCachePartition`): `generated` lists the `keyGenerator` results one per store, outermost first: leave them out when every one returns the default key, else keep each position and pass `""` for one that returns it. |
|
|
129
|
+
| `SHELL_STATUS_HEADER` | same | `"x-rango-shell"` constant |
|
|
130
|
+
| `assertPprReplayStatus(res, expected)` | same | Assert fresh/stale replay or a bounded bypass decision |
|
|
131
|
+
| `parsePprReplayStatus(res)` | same | Structured replay/bypass status, or null for an absent/unrecognized header |
|
|
132
|
+
| `PPR_REPLAY_STATUS_HEADER` | same | `"x-rango-ppr-replay"` constant |
|
|
133
133
|
|
|
134
134
|
### What unit can prove vs e2e
|
|
135
135
|
|
|
136
|
-
| Layer | What you assert | How
|
|
137
|
-
| -------- | --------------------------- |
|
|
138
|
-
| **Unit** | store family + key identity | `MemorySegmentCacheStore` + `shellCacheKey(url)` + `putShell`/`getShell` / tag eviction — dogfood in `e2e/mini/test/shell-store-family.test.ts` and `src/testing/__tests__/shell-status.test.ts` |
|
|
139
|
-
| **Unit** | header helper contract | `assertShellStatus` on a Response that already carries the header (characterizes the helper; **never** invent a HIT to claim capture worked)
|
|
140
|
-
| **Unit** | real capture → HIT, replay | `serveShellRequest(router, url, { cacheStore })` (react-server project); only the HTML step is stubbed — [`./serve-shell-request.md`](./serve-shell-request.md)
|
|
141
|
-
| **E2E** | live MISS → capture → HIT | document GET, poll until `x-rango-shell: HIT` (background capture) — `e2e/shell-cache.test.ts`
|
|
142
|
-
| **E2E** | partial replay decision | soft navigation to a warmed shell and `assertPprReplayStatus(response, { outcome: "HIT", freshness: "fresh" })`
|
|
136
|
+
| Layer | What you assert | How |
|
|
137
|
+
| -------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
138
|
+
| **Unit** | store family + key identity | `MemorySegmentCacheStore` + `shellCacheKey(router, url)` + `putShell`/`getShell` / tag eviction — dogfood in `e2e/mini/test/shell-store-family.test.ts` and `src/testing/__tests__/shell-status.test.ts` |
|
|
139
|
+
| **Unit** | header helper contract | `assertShellStatus` on a Response that already carries the header (characterizes the helper; **never** invent a HIT to claim capture worked) |
|
|
140
|
+
| **Unit** | real capture → HIT, replay | `serveShellRequest(router, url, { cacheStore })` (react-server project); only the HTML step is stubbed — [`./serve-shell-request.md`](./serve-shell-request.md) |
|
|
141
|
+
| **E2E** | live MISS → capture → HIT | document GET, poll until `x-rango-shell: HIT` (background capture) — `e2e/shell-cache.test.ts` |
|
|
142
|
+
| **E2E** | partial replay decision | soft navigation to a warmed shell and `assertPprReplayStatus(response, { outcome: "HIT", freshness: "fresh" })` |
|
|
143
143
|
|
|
144
144
|
`dispatch` is RSC-free: it never runs shell serve/capture. `renderHandler` only surfaces `ctx.dynamic()` opt-out, not bake/serve. The HIT contract — no handler runs, the handler output is the capture's copy, live loaders re-run — is asserted through `serveShellRequest`: count your handler's runs and a live loader's across a MISS and the HITs after it, and check that only the loader's moves ([`./serve-shell-request.md`](./serve-shell-request.md)). A route partitioned by `cache({ key })` or a store `keyGenerator` has a shell per partition: `serveShellRequest` reports the key the serve path resolved (`result.key`), and `shellCacheKey` takes the partition as its third argument.
|
|
145
145
|
|
|
@@ -175,10 +175,11 @@ parityDescribe("product shell", (f) => {
|
|
|
175
175
|
// Unit (Vitest): the key the serve path uses, against your own store instance
|
|
176
176
|
import { expect, it } from "vitest";
|
|
177
177
|
import { shellCacheKey } from "@rangojs/router/testing";
|
|
178
|
+
import { router } from "../src/router";
|
|
178
179
|
|
|
179
180
|
it("stores the shell under the production key", async () => {
|
|
180
181
|
// ...after your code under test captured a shell into `store`...
|
|
181
|
-
const key = shellCacheKey(new URL("http://localhost/products/1"));
|
|
182
|
+
const key = shellCacheKey(router, new URL("http://localhost/products/1"));
|
|
182
183
|
expect(await store.getShell(key)).not.toBeNull();
|
|
183
184
|
});
|
|
184
185
|
```
|