@rangojs/router 0.0.0-experimental.2 → 0.0.0-experimental.204030a9
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/__internal.d.ts +83 -0
- package/dist/__internal.d.ts.map +1 -0
- package/dist/__internal.js +19 -0
- package/dist/__internal.js.map +1 -0
- package/dist/__mocks__/version.d.ts +7 -0
- package/dist/__mocks__/version.d.ts.map +1 -0
- package/{src/__mocks__/version.ts → dist/__mocks__/version.js} +1 -0
- package/dist/__mocks__/version.js.map +1 -0
- package/dist/__tests__/client-href.test.d.ts +2 -0
- package/dist/__tests__/client-href.test.d.ts.map +1 -0
- package/dist/__tests__/client-href.test.js +74 -0
- package/dist/__tests__/client-href.test.js.map +1 -0
- package/dist/__tests__/component-utils.test.d.ts +2 -0
- package/dist/__tests__/component-utils.test.d.ts.map +1 -0
- package/dist/__tests__/component-utils.test.js +51 -0
- package/dist/__tests__/component-utils.test.js.map +1 -0
- package/dist/__tests__/event-controller.test.d.ts +2 -0
- package/dist/__tests__/event-controller.test.d.ts.map +1 -0
- package/dist/__tests__/event-controller.test.js +538 -0
- package/dist/__tests__/event-controller.test.js.map +1 -0
- package/dist/__tests__/helpers/route-tree.d.ts +118 -0
- package/dist/__tests__/helpers/route-tree.d.ts.map +1 -0
- package/dist/__tests__/helpers/route-tree.js +374 -0
- package/dist/__tests__/helpers/route-tree.js.map +1 -0
- package/dist/__tests__/match-result.test.d.ts +2 -0
- package/dist/__tests__/match-result.test.d.ts.map +1 -0
- package/dist/__tests__/match-result.test.js +154 -0
- package/dist/__tests__/match-result.test.js.map +1 -0
- package/dist/__tests__/navigation-store.test.d.ts +2 -0
- package/dist/__tests__/navigation-store.test.d.ts.map +1 -0
- package/dist/__tests__/navigation-store.test.js +440 -0
- package/dist/__tests__/navigation-store.test.js.map +1 -0
- package/dist/__tests__/partial-update.test.d.ts +2 -0
- package/dist/__tests__/partial-update.test.d.ts.map +1 -0
- package/dist/__tests__/partial-update.test.js +1009 -0
- package/dist/__tests__/partial-update.test.js.map +1 -0
- package/dist/__tests__/reverse-types.test.d.ts +8 -0
- package/dist/__tests__/reverse-types.test.d.ts.map +1 -0
- package/dist/__tests__/reverse-types.test.js +656 -0
- package/dist/__tests__/reverse-types.test.js.map +1 -0
- package/dist/__tests__/route-definition.test.d.ts +2 -0
- package/dist/__tests__/route-definition.test.d.ts.map +1 -0
- package/dist/__tests__/route-definition.test.js +55 -0
- package/dist/__tests__/route-definition.test.js.map +1 -0
- package/dist/__tests__/router-helpers.test.d.ts +2 -0
- package/dist/__tests__/router-helpers.test.d.ts.map +1 -0
- package/dist/__tests__/router-helpers.test.js +377 -0
- package/dist/__tests__/router-helpers.test.js.map +1 -0
- package/dist/__tests__/router-integration-2.test.d.ts +2 -0
- package/dist/__tests__/router-integration-2.test.d.ts.map +1 -0
- package/dist/__tests__/router-integration-2.test.js +426 -0
- package/dist/__tests__/router-integration-2.test.js.map +1 -0
- package/dist/__tests__/router-integration.test.d.ts +2 -0
- package/dist/__tests__/router-integration.test.d.ts.map +1 -0
- package/dist/__tests__/router-integration.test.js +1051 -0
- package/dist/__tests__/router-integration.test.js.map +1 -0
- package/dist/__tests__/search-params.test.d.ts +5 -0
- package/dist/__tests__/search-params.test.d.ts.map +1 -0
- package/dist/__tests__/search-params.test.js +306 -0
- package/dist/__tests__/search-params.test.js.map +1 -0
- package/dist/__tests__/segment-system.test.d.ts +2 -0
- package/dist/__tests__/segment-system.test.d.ts.map +1 -0
- package/dist/__tests__/segment-system.test.js +627 -0
- package/dist/__tests__/segment-system.test.js.map +1 -0
- package/dist/__tests__/static-handler-types.test.d.ts +8 -0
- package/dist/__tests__/static-handler-types.test.d.ts.map +1 -0
- package/dist/__tests__/static-handler-types.test.js +63 -0
- package/dist/__tests__/static-handler-types.test.js.map +1 -0
- package/dist/__tests__/urls.test.d.ts +2 -0
- package/dist/__tests__/urls.test.d.ts.map +1 -0
- package/dist/__tests__/urls.test.js +421 -0
- package/dist/__tests__/urls.test.js.map +1 -0
- package/dist/__tests__/use-mount.test.d.ts +2 -0
- package/dist/__tests__/use-mount.test.d.ts.map +1 -0
- package/dist/__tests__/use-mount.test.js +35 -0
- package/dist/__tests__/use-mount.test.js.map +1 -0
- package/dist/bin/rango.d.ts +2 -0
- package/dist/bin/rango.d.ts.map +1 -0
- package/dist/bin/rango.js +1779 -0
- package/dist/bin/rango.js.map +1 -0
- package/dist/browser/event-controller.d.ts +191 -0
- package/dist/browser/event-controller.d.ts.map +1 -0
- package/dist/browser/event-controller.js +559 -0
- package/dist/browser/event-controller.js.map +1 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +14 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/link-interceptor.d.ts +38 -0
- package/dist/browser/link-interceptor.d.ts.map +1 -0
- package/dist/browser/link-interceptor.js +99 -0
- package/dist/browser/link-interceptor.js.map +1 -0
- package/dist/browser/logging.d.ts +10 -0
- package/dist/browser/logging.d.ts.map +1 -0
- package/dist/browser/logging.js +29 -0
- package/dist/browser/logging.js.map +1 -0
- package/dist/browser/lru-cache.d.ts +17 -0
- package/dist/browser/lru-cache.d.ts.map +1 -0
- package/dist/browser/lru-cache.js +50 -0
- package/dist/browser/lru-cache.js.map +1 -0
- package/dist/browser/merge-segment-loaders.d.ts +39 -0
- package/dist/browser/merge-segment-loaders.d.ts.map +1 -0
- package/dist/browser/merge-segment-loaders.js +102 -0
- package/dist/browser/merge-segment-loaders.js.map +1 -0
- package/dist/browser/navigation-bridge.d.ts +102 -0
- package/dist/browser/navigation-bridge.d.ts.map +1 -0
- package/dist/browser/navigation-bridge.js +708 -0
- package/dist/browser/navigation-bridge.js.map +1 -0
- package/dist/browser/navigation-client.d.ts +25 -0
- package/dist/browser/navigation-client.d.ts.map +1 -0
- package/dist/browser/navigation-client.js +157 -0
- package/dist/browser/navigation-client.js.map +1 -0
- package/dist/browser/navigation-store.d.ts +101 -0
- package/dist/browser/navigation-store.d.ts.map +1 -0
- package/dist/browser/navigation-store.js +625 -0
- package/dist/browser/navigation-store.js.map +1 -0
- package/dist/browser/partial-update.d.ts +75 -0
- package/dist/browser/partial-update.d.ts.map +1 -0
- package/dist/browser/partial-update.js +426 -0
- package/dist/browser/partial-update.js.map +1 -0
- package/dist/browser/react/Link.d.ts +86 -0
- package/dist/browser/react/Link.d.ts.map +1 -0
- package/dist/browser/react/Link.js +128 -0
- package/dist/browser/react/Link.js.map +1 -0
- package/dist/browser/react/NavigationProvider.d.ts +63 -0
- package/dist/browser/react/NavigationProvider.d.ts.map +1 -0
- package/dist/browser/react/NavigationProvider.js +216 -0
- package/dist/browser/react/NavigationProvider.js.map +1 -0
- package/dist/browser/react/ScrollRestoration.d.ts +75 -0
- package/dist/browser/react/ScrollRestoration.d.ts.map +1 -0
- package/dist/browser/react/ScrollRestoration.js +57 -0
- package/dist/browser/react/ScrollRestoration.js.map +1 -0
- package/dist/browser/react/context.d.ts +46 -0
- package/dist/browser/react/context.d.ts.map +1 -0
- package/dist/browser/react/context.js +10 -0
- package/dist/browser/react/context.js.map +1 -0
- package/dist/browser/react/index.d.ts +11 -0
- package/dist/browser/react/index.d.ts.map +1 -0
- package/dist/browser/react/index.js +22 -0
- package/dist/browser/react/index.js.map +1 -0
- package/dist/browser/react/location-state-shared.d.ts +63 -0
- package/dist/browser/react/location-state-shared.d.ts.map +1 -0
- package/dist/browser/react/location-state-shared.js +81 -0
- package/dist/browser/react/location-state-shared.js.map +1 -0
- package/dist/browser/react/location-state.d.ts +23 -0
- package/dist/browser/react/location-state.d.ts.map +1 -0
- package/dist/browser/react/location-state.js +29 -0
- package/dist/browser/react/location-state.js.map +1 -0
- package/dist/browser/react/mount-context.d.ts +24 -0
- package/dist/browser/react/mount-context.d.ts.map +1 -0
- package/dist/browser/react/mount-context.js +24 -0
- package/dist/browser/react/mount-context.js.map +1 -0
- package/dist/browser/react/use-action.d.ts +64 -0
- package/dist/browser/react/use-action.d.ts.map +1 -0
- package/dist/browser/react/use-action.js +134 -0
- package/dist/browser/react/use-action.js.map +1 -0
- package/dist/browser/react/use-client-cache.d.ts +41 -0
- package/dist/browser/react/use-client-cache.d.ts.map +1 -0
- package/dist/browser/react/use-client-cache.js +39 -0
- package/dist/browser/react/use-client-cache.js.map +1 -0
- package/dist/browser/react/use-handle.d.ts +31 -0
- package/dist/browser/react/use-handle.d.ts.map +1 -0
- package/dist/browser/react/use-handle.js +144 -0
- package/dist/browser/react/use-handle.js.map +1 -0
- package/dist/browser/react/use-href.d.ts +33 -0
- package/dist/browser/react/use-href.d.ts.map +1 -0
- package/dist/browser/react/use-href.js +39 -0
- package/dist/browser/react/use-href.js.map +1 -0
- package/dist/browser/react/use-link-status.d.ts +37 -0
- package/dist/browser/react/use-link-status.d.ts.map +1 -0
- package/dist/browser/react/use-link-status.js +99 -0
- package/dist/browser/react/use-link-status.js.map +1 -0
- package/dist/browser/react/use-mount.d.ts +25 -0
- package/dist/browser/react/use-mount.d.ts.map +1 -0
- package/dist/browser/react/use-mount.js +30 -0
- package/dist/browser/react/use-mount.js.map +1 -0
- package/dist/browser/react/use-navigation.d.ts +27 -0
- package/dist/browser/react/use-navigation.d.ts.map +1 -0
- package/dist/browser/react/use-navigation.js +87 -0
- package/dist/browser/react/use-navigation.js.map +1 -0
- package/dist/browser/react/use-segments.d.ts +38 -0
- package/dist/browser/react/use-segments.d.ts.map +1 -0
- package/dist/browser/react/use-segments.js +130 -0
- package/dist/browser/react/use-segments.js.map +1 -0
- package/dist/browser/request-controller.d.ts +26 -0
- package/dist/browser/request-controller.d.ts.map +1 -0
- package/dist/browser/request-controller.js +147 -0
- package/dist/browser/request-controller.js.map +1 -0
- package/dist/browser/rsc-router.d.ts +129 -0
- package/dist/browser/rsc-router.d.ts.map +1 -0
- package/dist/browser/rsc-router.js +195 -0
- package/dist/browser/rsc-router.js.map +1 -0
- package/dist/browser/scroll-restoration.d.ts +93 -0
- package/dist/browser/scroll-restoration.d.ts.map +1 -0
- package/dist/browser/scroll-restoration.js +321 -0
- package/dist/browser/scroll-restoration.js.map +1 -0
- package/dist/browser/segment-structure-assert.d.ts +17 -0
- package/dist/browser/segment-structure-assert.d.ts.map +1 -0
- package/dist/browser/segment-structure-assert.js +59 -0
- package/dist/browser/segment-structure-assert.js.map +1 -0
- package/dist/browser/server-action-bridge.d.ts +26 -0
- package/dist/browser/server-action-bridge.d.ts.map +1 -0
- package/dist/browser/server-action-bridge.js +668 -0
- package/dist/browser/server-action-bridge.js.map +1 -0
- package/dist/browser/shallow.d.ts +12 -0
- package/dist/browser/shallow.d.ts.map +1 -0
- package/dist/browser/shallow.js +34 -0
- package/dist/browser/shallow.js.map +1 -0
- package/dist/browser/types.d.ts +369 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/build/__tests__/generate-cli.test.d.ts +2 -0
- package/dist/build/__tests__/generate-cli.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-cli.test.js +237 -0
- package/dist/build/__tests__/generate-cli.test.js.map +1 -0
- package/dist/build/__tests__/generate-manifest.test.d.ts +2 -0
- package/dist/build/__tests__/generate-manifest.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-manifest.test.js +119 -0
- package/dist/build/__tests__/generate-manifest.test.js.map +1 -0
- package/dist/build/__tests__/generate-route-types.test.d.ts +2 -0
- package/dist/build/__tests__/generate-route-types.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-route-types.test.js +620 -0
- package/dist/build/__tests__/generate-route-types.test.js.map +1 -0
- package/dist/build/__tests__/per-router-manifest.test.d.ts +2 -0
- package/dist/build/__tests__/per-router-manifest.test.d.ts.map +1 -0
- package/dist/build/__tests__/per-router-manifest.test.js +308 -0
- package/dist/build/__tests__/per-router-manifest.test.js.map +1 -0
- package/dist/build/generate-manifest.d.ts +81 -0
- package/dist/build/generate-manifest.d.ts.map +1 -0
- package/dist/build/generate-manifest.js +276 -0
- package/dist/build/generate-manifest.js.map +1 -0
- package/dist/build/generate-route-types.d.ts +115 -0
- package/dist/build/generate-route-types.d.ts.map +1 -0
- package/dist/build/generate-route-types.js +740 -0
- package/dist/build/generate-route-types.js.map +1 -0
- package/dist/build/index.d.ts +21 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +21 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/route-trie.d.ts +71 -0
- package/dist/build/route-trie.d.ts.map +1 -0
- package/dist/build/route-trie.js +175 -0
- package/dist/build/route-trie.js.map +1 -0
- package/dist/cache/__tests__/cache-scope.test.d.ts +2 -0
- package/dist/cache/__tests__/cache-scope.test.d.ts.map +1 -0
- package/dist/cache/__tests__/cache-scope.test.js +208 -0
- package/dist/cache/__tests__/cache-scope.test.js.map +1 -0
- package/dist/cache/__tests__/document-cache.test.d.ts +2 -0
- package/dist/cache/__tests__/document-cache.test.d.ts.map +1 -0
- package/dist/cache/__tests__/document-cache.test.js +345 -0
- package/dist/cache/__tests__/document-cache.test.js.map +1 -0
- package/dist/cache/__tests__/memory-segment-store.test.d.ts +2 -0
- package/dist/cache/__tests__/memory-segment-store.test.d.ts.map +1 -0
- package/dist/cache/__tests__/memory-segment-store.test.js +425 -0
- package/dist/cache/__tests__/memory-segment-store.test.js.map +1 -0
- package/dist/cache/__tests__/memory-store.test.d.ts +2 -0
- package/dist/cache/__tests__/memory-store.test.d.ts.map +1 -0
- package/dist/cache/__tests__/memory-store.test.js +367 -0
- package/dist/cache/__tests__/memory-store.test.js.map +1 -0
- package/dist/cache/cache-scope.d.ts +102 -0
- package/dist/cache/cache-scope.d.ts.map +1 -0
- package/dist/cache/cache-scope.js +440 -0
- package/dist/cache/cache-scope.js.map +1 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts +2 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts.map +1 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.js +330 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.js.map +1 -0
- package/dist/cache/cf/cf-cache-store.d.ts +165 -0
- package/dist/cache/cf/cf-cache-store.d.ts.map +1 -0
- package/dist/cache/cf/cf-cache-store.js +242 -0
- package/dist/cache/cf/cf-cache-store.js.map +1 -0
- package/dist/cache/cf/index.d.ts +14 -0
- package/dist/cache/cf/index.d.ts.map +1 -0
- package/dist/cache/cf/index.js +17 -0
- package/dist/cache/cf/index.js.map +1 -0
- package/dist/cache/document-cache.d.ts +64 -0
- package/dist/cache/document-cache.d.ts.map +1 -0
- package/dist/cache/document-cache.js +228 -0
- package/dist/cache/document-cache.js.map +1 -0
- package/dist/cache/index.d.ts +19 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +21 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/memory-segment-store.d.ts +110 -0
- package/dist/cache/memory-segment-store.d.ts.map +1 -0
- package/dist/cache/memory-segment-store.js +117 -0
- package/dist/cache/memory-segment-store.js.map +1 -0
- package/dist/cache/memory-store.d.ts +41 -0
- package/dist/cache/memory-store.d.ts.map +1 -0
- package/dist/cache/memory-store.js +191 -0
- package/dist/cache/memory-store.js.map +1 -0
- package/dist/cache/types.d.ts +317 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +12 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/client.d.ts +248 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +367 -0
- package/dist/client.js.map +1 -0
- package/dist/client.rsc.d.ts +26 -0
- package/dist/client.rsc.d.ts.map +1 -0
- package/dist/client.rsc.js +46 -0
- package/dist/client.rsc.js.map +1 -0
- package/dist/component-utils.d.ts +36 -0
- package/dist/component-utils.d.ts.map +1 -0
- package/dist/component-utils.js +61 -0
- package/dist/component-utils.js.map +1 -0
- package/dist/components/DefaultDocument.d.ts +13 -0
- package/dist/components/DefaultDocument.d.ts.map +1 -0
- package/dist/components/DefaultDocument.js +15 -0
- package/dist/components/DefaultDocument.js.map +1 -0
- package/dist/debug.d.ts +58 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +157 -0
- package/dist/debug.js.map +1 -0
- package/dist/default-error-boundary.d.ts +11 -0
- package/dist/default-error-boundary.d.ts.map +1 -0
- package/dist/default-error-boundary.js +45 -0
- package/dist/default-error-boundary.js.map +1 -0
- package/dist/deps/browser.d.ts +2 -0
- package/dist/deps/browser.d.ts.map +1 -0
- package/dist/deps/browser.js +3 -0
- package/dist/deps/browser.js.map +1 -0
- package/dist/deps/html-stream-client.d.ts +2 -0
- package/dist/deps/html-stream-client.d.ts.map +1 -0
- package/dist/deps/html-stream-client.js +3 -0
- package/dist/deps/html-stream-client.js.map +1 -0
- package/dist/deps/html-stream-server.d.ts +2 -0
- package/dist/deps/html-stream-server.d.ts.map +1 -0
- package/dist/deps/html-stream-server.js +3 -0
- package/dist/deps/html-stream-server.js.map +1 -0
- package/dist/deps/rsc.d.ts +2 -0
- package/dist/deps/rsc.d.ts.map +1 -0
- package/dist/deps/rsc.js +4 -0
- package/dist/deps/rsc.js.map +1 -0
- package/dist/deps/ssr.d.ts +2 -0
- package/dist/deps/ssr.d.ts.map +1 -0
- package/dist/deps/ssr.js +3 -0
- package/dist/deps/ssr.js.map +1 -0
- package/dist/errors.d.ts +174 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +241 -0
- package/dist/errors.js.map +1 -0
- package/dist/handle.d.ts +78 -0
- package/dist/handle.d.ts.map +1 -0
- package/dist/handle.js +82 -0
- package/dist/handle.js.map +1 -0
- package/dist/handles/MetaTags.d.ts +14 -0
- package/dist/handles/MetaTags.d.ts.map +1 -0
- package/dist/handles/MetaTags.js +136 -0
- package/dist/handles/MetaTags.js.map +1 -0
- package/dist/handles/index.d.ts +6 -0
- package/dist/handles/index.d.ts.map +1 -0
- package/dist/handles/index.js +6 -0
- package/dist/handles/index.js.map +1 -0
- package/dist/handles/meta.d.ts +39 -0
- package/dist/handles/meta.d.ts.map +1 -0
- package/dist/handles/meta.js +202 -0
- package/dist/handles/meta.js.map +1 -0
- package/dist/host/__tests__/errors.test.d.ts +2 -0
- package/dist/host/__tests__/errors.test.d.ts.map +1 -0
- package/dist/host/__tests__/errors.test.js +76 -0
- package/dist/host/__tests__/errors.test.js.map +1 -0
- package/dist/host/__tests__/pattern-comprehensive.test.d.ts +2 -0
- package/dist/host/__tests__/pattern-comprehensive.test.d.ts.map +1 -0
- package/dist/host/__tests__/pattern-comprehensive.test.js +732 -0
- package/dist/host/__tests__/pattern-comprehensive.test.js.map +1 -0
- package/dist/host/__tests__/pattern-matcher.test.d.ts +2 -0
- package/dist/host/__tests__/pattern-matcher.test.d.ts.map +1 -0
- package/dist/host/__tests__/pattern-matcher.test.js +251 -0
- package/dist/host/__tests__/pattern-matcher.test.js.map +1 -0
- package/dist/host/__tests__/router.test.d.ts +2 -0
- package/dist/host/__tests__/router.test.d.ts.map +1 -0
- package/dist/host/__tests__/router.test.js +241 -0
- package/dist/host/__tests__/router.test.js.map +1 -0
- package/dist/host/__tests__/testing.test.d.ts +2 -0
- package/dist/host/__tests__/testing.test.d.ts.map +1 -0
- package/dist/host/__tests__/testing.test.js +64 -0
- package/dist/host/__tests__/testing.test.js.map +1 -0
- package/dist/host/__tests__/utils.test.d.ts +2 -0
- package/dist/host/__tests__/utils.test.d.ts.map +1 -0
- package/dist/host/__tests__/utils.test.js +29 -0
- package/dist/host/__tests__/utils.test.js.map +1 -0
- package/dist/host/cookie-handler.d.ts +34 -0
- package/dist/host/cookie-handler.d.ts.map +1 -0
- package/dist/host/cookie-handler.js +124 -0
- package/dist/host/cookie-handler.js.map +1 -0
- package/dist/host/errors.d.ts +56 -0
- package/dist/host/errors.d.ts.map +1 -0
- package/dist/host/errors.js +79 -0
- package/dist/host/errors.js.map +1 -0
- package/dist/host/index.d.ts +29 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +32 -0
- package/dist/host/index.js.map +1 -0
- package/dist/host/pattern-matcher.d.ts +36 -0
- package/dist/host/pattern-matcher.d.ts.map +1 -0
- package/dist/host/pattern-matcher.js +172 -0
- package/dist/host/pattern-matcher.js.map +1 -0
- package/dist/host/router.d.ts +26 -0
- package/dist/host/router.d.ts.map +1 -0
- package/dist/host/router.js +218 -0
- package/dist/host/router.js.map +1 -0
- package/dist/host/testing.d.ts +36 -0
- package/dist/host/testing.d.ts.map +1 -0
- package/dist/host/testing.js +55 -0
- package/dist/host/testing.js.map +1 -0
- package/dist/host/types.d.ts +115 -0
- package/dist/host/types.d.ts.map +1 -0
- package/dist/host/types.js +7 -0
- package/dist/host/types.js.map +1 -0
- package/dist/host/utils.d.ts +21 -0
- package/dist/host/utils.d.ts.map +1 -0
- package/dist/host/utils.js +23 -0
- package/dist/host/utils.js.map +1 -0
- package/dist/href-client.d.ts +131 -0
- package/dist/href-client.d.ts.map +1 -0
- package/dist/href-client.js +64 -0
- package/dist/href-client.js.map +1 -0
- package/{src/href-context.ts → dist/href-context.d.ts} +7 -11
- package/dist/href-context.d.ts.map +1 -0
- package/dist/href-context.js +21 -0
- package/dist/href-context.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/index.rsc.d.ts +32 -0
- package/dist/index.rsc.d.ts.map +1 -0
- package/dist/index.rsc.js +40 -0
- package/dist/index.rsc.js.map +1 -0
- package/dist/internal-debug.d.ts +2 -0
- package/dist/internal-debug.d.ts.map +1 -0
- package/dist/internal-debug.js +5 -0
- package/dist/internal-debug.js.map +1 -0
- package/dist/loader.d.ts +14 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +20 -0
- package/dist/loader.js.map +1 -0
- package/dist/loader.rsc.d.ts +19 -0
- package/dist/loader.rsc.d.ts.map +1 -0
- package/dist/loader.rsc.js +99 -0
- package/dist/loader.rsc.js.map +1 -0
- package/dist/network-error-thrower.d.ts +17 -0
- package/dist/network-error-thrower.d.ts.map +1 -0
- package/dist/network-error-thrower.js +14 -0
- package/dist/network-error-thrower.js.map +1 -0
- package/dist/outlet-context.d.ts +13 -0
- package/dist/outlet-context.d.ts.map +1 -0
- package/dist/outlet-context.js +3 -0
- package/dist/outlet-context.js.map +1 -0
- package/dist/prerender/__tests__/param-hash.test.d.ts +2 -0
- package/dist/prerender/__tests__/param-hash.test.d.ts.map +1 -0
- package/dist/prerender/__tests__/param-hash.test.js +148 -0
- package/dist/prerender/__tests__/param-hash.test.js.map +1 -0
- package/dist/prerender/param-hash.d.ts +16 -0
- package/dist/prerender/param-hash.d.ts.map +1 -0
- package/dist/prerender/param-hash.js +36 -0
- package/dist/prerender/param-hash.js.map +1 -0
- package/dist/prerender/store.d.ts +38 -0
- package/dist/prerender/store.d.ts.map +1 -0
- package/dist/prerender/store.js +61 -0
- package/dist/prerender/store.js.map +1 -0
- package/dist/prerender.d.ts +66 -0
- package/dist/prerender.d.ts.map +1 -0
- package/dist/prerender.js +57 -0
- package/dist/prerender.js.map +1 -0
- package/dist/reverse.d.ts +196 -0
- package/dist/reverse.d.ts.map +1 -0
- package/dist/reverse.js +78 -0
- package/dist/reverse.js.map +1 -0
- package/dist/root-error-boundary.d.ts +33 -0
- package/dist/root-error-boundary.d.ts.map +1 -0
- package/dist/root-error-boundary.js +165 -0
- package/dist/root-error-boundary.js.map +1 -0
- package/dist/route-content-wrapper.d.ts +46 -0
- package/dist/route-content-wrapper.d.ts.map +1 -0
- package/dist/route-content-wrapper.js +77 -0
- package/dist/route-content-wrapper.js.map +1 -0
- package/dist/route-definition.d.ts +421 -0
- package/dist/route-definition.d.ts.map +1 -0
- package/dist/route-definition.js +868 -0
- package/dist/route-definition.js.map +1 -0
- package/dist/route-map-builder.d.ts +155 -0
- package/dist/route-map-builder.d.ts.map +1 -0
- package/dist/route-map-builder.js +237 -0
- package/dist/route-map-builder.js.map +1 -0
- package/dist/route-types.d.ts +165 -0
- package/dist/route-types.d.ts.map +1 -0
- package/dist/route-types.js +7 -0
- package/dist/route-types.js.map +1 -0
- package/dist/router/__tests__/handler-context.test.d.ts +2 -0
- package/dist/router/__tests__/handler-context.test.d.ts.map +1 -0
- package/dist/router/__tests__/handler-context.test.js +65 -0
- package/dist/router/__tests__/handler-context.test.js.map +1 -0
- package/dist/router/__tests__/loader-cycle-detection.test.d.ts +2 -0
- package/dist/router/__tests__/loader-cycle-detection.test.d.ts.map +1 -0
- package/dist/router/__tests__/loader-cycle-detection.test.js +221 -0
- package/dist/router/__tests__/loader-cycle-detection.test.js.map +1 -0
- package/dist/router/__tests__/match-context.test.d.ts +2 -0
- package/dist/router/__tests__/match-context.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-context.test.js +92 -0
- package/dist/router/__tests__/match-context.test.js.map +1 -0
- package/dist/router/__tests__/match-pipelines.test.d.ts +2 -0
- package/dist/router/__tests__/match-pipelines.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-pipelines.test.js +417 -0
- package/dist/router/__tests__/match-pipelines.test.js.map +1 -0
- package/dist/router/__tests__/match-result.test.d.ts +2 -0
- package/dist/router/__tests__/match-result.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-result.test.js +457 -0
- package/dist/router/__tests__/match-result.test.js.map +1 -0
- package/dist/router/__tests__/on-error.test.d.ts +2 -0
- package/dist/router/__tests__/on-error.test.d.ts.map +1 -0
- package/dist/router/__tests__/on-error.test.js +678 -0
- package/dist/router/__tests__/on-error.test.js.map +1 -0
- package/dist/router/__tests__/pattern-matching.test.d.ts +2 -0
- package/dist/router/__tests__/pattern-matching.test.d.ts.map +1 -0
- package/dist/router/__tests__/pattern-matching.test.js +629 -0
- package/dist/router/__tests__/pattern-matching.test.js.map +1 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts +2 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts.map +1 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.js +155 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.js.map +1 -0
- package/dist/router/error-handling.d.ts +77 -0
- package/dist/router/error-handling.d.ts.map +1 -0
- package/dist/router/error-handling.js +202 -0
- package/dist/router/error-handling.js.map +1 -0
- package/dist/router/handler-context.d.ts +20 -0
- package/dist/router/handler-context.d.ts.map +1 -0
- package/dist/router/handler-context.js +198 -0
- package/dist/router/handler-context.js.map +1 -0
- package/dist/router/intercept-resolution.d.ts +66 -0
- package/dist/router/intercept-resolution.d.ts.map +1 -0
- package/dist/router/intercept-resolution.js +246 -0
- package/dist/router/intercept-resolution.js.map +1 -0
- package/dist/router/loader-resolution.d.ts +64 -0
- package/dist/router/loader-resolution.d.ts.map +1 -0
- package/dist/router/loader-resolution.js +284 -0
- package/dist/router/loader-resolution.js.map +1 -0
- package/dist/router/logging.d.ts +15 -0
- package/dist/router/logging.d.ts.map +1 -0
- package/dist/router/logging.js +99 -0
- package/dist/router/logging.js.map +1 -0
- package/dist/router/manifest.d.ts +22 -0
- package/dist/router/manifest.d.ts.map +1 -0
- package/dist/router/manifest.js +181 -0
- package/dist/router/manifest.js.map +1 -0
- package/dist/router/match-api.d.ts +35 -0
- package/dist/router/match-api.d.ts.map +1 -0
- package/dist/router/match-api.js +406 -0
- package/dist/router/match-api.js.map +1 -0
- package/dist/router/match-context.d.ts +206 -0
- package/dist/router/match-context.d.ts.map +1 -0
- package/dist/router/match-context.js +17 -0
- package/dist/router/match-context.js.map +1 -0
- package/dist/router/match-middleware/background-revalidation.d.ts +127 -0
- package/dist/router/match-middleware/background-revalidation.d.ts.map +1 -0
- package/dist/router/match-middleware/background-revalidation.js +75 -0
- package/dist/router/match-middleware/background-revalidation.js.map +1 -0
- package/dist/router/match-middleware/cache-lookup.d.ts +112 -0
- package/dist/router/match-middleware/cache-lookup.d.ts.map +1 -0
- package/dist/router/match-middleware/cache-lookup.js +257 -0
- package/dist/router/match-middleware/cache-lookup.js.map +1 -0
- package/dist/router/match-middleware/cache-store.d.ts +113 -0
- package/dist/router/match-middleware/cache-store.d.ts.map +1 -0
- package/dist/router/match-middleware/cache-store.js +108 -0
- package/dist/router/match-middleware/cache-store.js.map +1 -0
- package/dist/router/match-middleware/index.d.ts +81 -0
- package/dist/router/match-middleware/index.d.ts.map +1 -0
- package/dist/router/match-middleware/index.js +80 -0
- package/dist/router/match-middleware/index.js.map +1 -0
- package/dist/router/match-middleware/intercept-resolution.d.ts +117 -0
- package/dist/router/match-middleware/intercept-resolution.d.ts.map +1 -0
- package/dist/router/match-middleware/intercept-resolution.js +134 -0
- package/dist/router/match-middleware/intercept-resolution.js.map +1 -0
- package/dist/router/match-middleware/segment-resolution.d.ts +99 -0
- package/dist/router/match-middleware/segment-resolution.d.ts.map +1 -0
- package/dist/router/match-middleware/segment-resolution.js +53 -0
- package/dist/router/match-middleware/segment-resolution.js.map +1 -0
- package/dist/router/match-pipelines.d.ts +147 -0
- package/dist/router/match-pipelines.d.ts.map +1 -0
- package/dist/router/match-pipelines.js +82 -0
- package/dist/router/match-pipelines.js.map +1 -0
- package/dist/router/match-result.d.ts +126 -0
- package/dist/router/match-result.d.ts.map +1 -0
- package/dist/router/match-result.js +93 -0
- package/dist/router/match-result.js.map +1 -0
- package/dist/router/metrics.d.ts +20 -0
- package/dist/router/metrics.d.ts.map +1 -0
- package/dist/router/metrics.js +47 -0
- package/dist/router/metrics.js.map +1 -0
- package/dist/router/middleware.d.ts +249 -0
- package/dist/router/middleware.d.ts.map +1 -0
- package/dist/router/middleware.js +434 -0
- package/dist/router/middleware.js.map +1 -0
- package/dist/router/middleware.test.d.ts +2 -0
- package/dist/router/middleware.test.d.ts.map +1 -0
- package/dist/router/middleware.test.js +816 -0
- package/dist/router/middleware.test.js.map +1 -0
- package/dist/router/pattern-matching.d.ts +149 -0
- package/dist/router/pattern-matching.d.ts.map +1 -0
- package/dist/router/pattern-matching.js +349 -0
- package/dist/router/pattern-matching.js.map +1 -0
- package/dist/router/revalidation.d.ts +44 -0
- package/dist/router/revalidation.d.ts.map +1 -0
- package/dist/router/revalidation.js +147 -0
- package/dist/router/revalidation.js.map +1 -0
- package/dist/router/router-context.d.ts +135 -0
- package/dist/router/router-context.d.ts.map +1 -0
- package/dist/router/router-context.js +36 -0
- package/dist/router/router-context.js.map +1 -0
- package/dist/router/segment-resolution.d.ts +127 -0
- package/dist/router/segment-resolution.d.ts.map +1 -0
- package/dist/router/segment-resolution.js +919 -0
- package/dist/router/segment-resolution.js.map +1 -0
- package/dist/router/trie-matching.d.ts +40 -0
- package/dist/router/trie-matching.d.ts.map +1 -0
- package/dist/router/trie-matching.js +127 -0
- package/dist/router/trie-matching.js.map +1 -0
- package/dist/router/types.d.ts +136 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +7 -0
- package/dist/router/types.js.map +1 -0
- package/dist/router.d.ts +753 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.gen.d.ts +6 -0
- package/dist/router.gen.d.ts.map +1 -0
- package/dist/router.gen.js +6 -0
- package/dist/router.gen.js.map +1 -0
- package/dist/router.js +1304 -0
- package/dist/router.js.map +1 -0
- package/dist/rsc/__tests__/helpers.test.d.ts +2 -0
- package/dist/rsc/__tests__/helpers.test.d.ts.map +1 -0
- package/dist/rsc/__tests__/helpers.test.js +140 -0
- package/dist/rsc/__tests__/helpers.test.js.map +1 -0
- package/dist/rsc/handler.d.ts +45 -0
- package/dist/rsc/handler.d.ts.map +1 -0
- package/dist/rsc/handler.js +1172 -0
- package/dist/rsc/handler.js.map +1 -0
- package/dist/rsc/helpers.d.ts +16 -0
- package/dist/rsc/helpers.d.ts.map +1 -0
- package/dist/rsc/helpers.js +55 -0
- package/dist/rsc/helpers.js.map +1 -0
- package/dist/rsc/index.d.ts +22 -0
- package/dist/rsc/index.d.ts.map +1 -0
- package/dist/rsc/index.js +23 -0
- package/dist/rsc/index.js.map +1 -0
- package/dist/rsc/nonce.d.ts +9 -0
- package/dist/rsc/nonce.d.ts.map +1 -0
- package/dist/rsc/nonce.js +18 -0
- package/dist/rsc/nonce.js.map +1 -0
- package/dist/rsc/types.d.ts +206 -0
- package/dist/rsc/types.d.ts.map +1 -0
- package/dist/rsc/types.js +8 -0
- package/dist/rsc/types.js.map +1 -0
- package/dist/search-params.d.ts +103 -0
- package/dist/search-params.d.ts.map +1 -0
- package/dist/search-params.js +74 -0
- package/dist/search-params.js.map +1 -0
- package/dist/segment-system.d.ts +75 -0
- package/dist/segment-system.d.ts.map +1 -0
- package/dist/segment-system.js +336 -0
- package/dist/segment-system.js.map +1 -0
- package/dist/server/context.d.ts +245 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +197 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/fetchable-loader-store.d.ts +18 -0
- package/dist/server/fetchable-loader-store.d.ts.map +1 -0
- package/dist/server/fetchable-loader-store.js +18 -0
- package/dist/server/fetchable-loader-store.js.map +1 -0
- package/dist/server/handle-store.d.ts +85 -0
- package/dist/server/handle-store.d.ts.map +1 -0
- package/dist/server/handle-store.js +142 -0
- package/dist/server/handle-store.js.map +1 -0
- package/dist/server/loader-registry.d.ts +55 -0
- package/dist/server/loader-registry.d.ts.map +1 -0
- package/dist/server/loader-registry.js +132 -0
- package/dist/server/loader-registry.js.map +1 -0
- package/dist/server/request-context.d.ts +226 -0
- package/dist/server/request-context.d.ts.map +1 -0
- package/dist/server/request-context.js +290 -0
- package/dist/server/request-context.js.map +1 -0
- package/dist/server/root-layout.d.ts +4 -0
- package/dist/server/root-layout.d.ts.map +1 -0
- package/dist/server/root-layout.js +5 -0
- package/dist/server/root-layout.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +20 -0
- package/dist/server.js.map +1 -0
- package/dist/ssr/__tests__/ssr-handler.test.d.ts +2 -0
- package/dist/ssr/__tests__/ssr-handler.test.d.ts.map +1 -0
- package/dist/ssr/__tests__/ssr-handler.test.js +132 -0
- package/dist/ssr/__tests__/ssr-handler.test.js.map +1 -0
- package/dist/ssr/index.d.ts +98 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/index.js +158 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/static-handler.d.ts +50 -0
- package/dist/static-handler.d.ts.map +1 -0
- package/dist/static-handler.gen.d.ts +5 -0
- package/dist/static-handler.gen.d.ts.map +1 -0
- package/dist/static-handler.gen.js +5 -0
- package/dist/static-handler.gen.js.map +1 -0
- package/dist/static-handler.js +29 -0
- package/dist/static-handler.js.map +1 -0
- package/dist/theme/ThemeProvider.d.ts +20 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +240 -0
- package/dist/theme/ThemeProvider.js.map +1 -0
- package/dist/theme/ThemeScript.d.ts +48 -0
- package/dist/theme/ThemeScript.d.ts.map +1 -0
- package/dist/theme/ThemeScript.js +13 -0
- package/dist/theme/ThemeScript.js.map +1 -0
- package/dist/theme/__tests__/theme.test.d.ts +2 -0
- package/dist/theme/__tests__/theme.test.d.ts.map +1 -0
- package/dist/theme/__tests__/theme.test.js +103 -0
- package/dist/theme/__tests__/theme.test.js.map +1 -0
- package/dist/theme/constants.d.ts +29 -0
- package/dist/theme/constants.d.ts.map +1 -0
- package/dist/theme/constants.js +48 -0
- package/dist/theme/constants.js.map +1 -0
- package/dist/theme/index.d.ts +31 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +36 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/theme-context.d.ts +40 -0
- package/dist/theme/theme-context.d.ts.map +1 -0
- package/dist/theme/theme-context.js +60 -0
- package/dist/theme/theme-context.js.map +1 -0
- package/dist/theme/theme-script.d.ts +27 -0
- package/dist/theme/theme-script.d.ts.map +1 -0
- package/dist/theme/theme-script.js +147 -0
- package/dist/theme/theme-script.js.map +1 -0
- package/dist/theme/types.d.ts +163 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +11 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/theme/use-theme.d.ts +12 -0
- package/dist/theme/use-theme.d.ts.map +1 -0
- package/dist/theme/use-theme.js +40 -0
- package/dist/theme/use-theme.js.map +1 -0
- package/dist/types.d.ts +1479 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/urls.d.ts +441 -0
- package/dist/urls.d.ts.map +1 -0
- package/dist/urls.gen.d.ts +8 -0
- package/dist/urls.gen.d.ts.map +1 -0
- package/dist/urls.gen.js +8 -0
- package/dist/urls.gen.js.map +1 -0
- package/dist/urls.js +443 -0
- package/dist/urls.js.map +1 -0
- package/dist/use-loader.d.ts +127 -0
- package/dist/use-loader.d.ts.map +1 -0
- package/dist/use-loader.js +237 -0
- package/dist/use-loader.js.map +1 -0
- package/dist/vite/__tests__/ast-handler-extract.test.d.ts +2 -0
- package/dist/vite/__tests__/ast-handler-extract.test.d.ts.map +1 -0
- package/dist/vite/__tests__/ast-handler-extract.test.js +294 -0
- package/dist/vite/__tests__/ast-handler-extract.test.js.map +1 -0
- package/dist/vite/__tests__/expose-id-utils.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-id-utils.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-id-utils.test.js +224 -0
- package/dist/vite/__tests__/expose-id-utils.test.js.map +1 -0
- package/dist/vite/__tests__/expose-internal-ids.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-internal-ids.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-internal-ids.test.js +647 -0
- package/dist/vite/__tests__/expose-internal-ids.test.js.map +1 -0
- package/dist/vite/__tests__/expose-router-id.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-router-id.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-router-id.test.js +39 -0
- package/dist/vite/__tests__/expose-router-id.test.js.map +1 -0
- package/dist/vite/ast-handler-extract.d.ts +49 -0
- package/dist/vite/ast-handler-extract.d.ts.map +1 -0
- package/dist/vite/ast-handler-extract.js +249 -0
- package/dist/vite/ast-handler-extract.js.map +1 -0
- package/dist/vite/expose-action-id.d.ts +19 -0
- package/dist/vite/expose-action-id.d.ts.map +1 -0
- package/dist/vite/expose-action-id.js +250 -0
- package/dist/vite/expose-action-id.js.map +1 -0
- package/dist/vite/expose-id-utils.d.ts +69 -0
- package/dist/vite/expose-id-utils.d.ts.map +1 -0
- package/dist/vite/expose-id-utils.js +289 -0
- package/dist/vite/expose-id-utils.js.map +1 -0
- package/dist/vite/expose-internal-ids.d.ts +22 -0
- package/dist/vite/expose-internal-ids.d.ts.map +1 -0
- package/dist/vite/expose-internal-ids.js +886 -0
- package/dist/vite/expose-internal-ids.js.map +1 -0
- package/dist/vite/index.d.ts +149 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +6440 -809
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/index.named-routes.gen.ts +103 -0
- package/dist/vite/package-resolution.d.ts +43 -0
- package/dist/vite/package-resolution.d.ts.map +1 -0
- package/{src/vite/package-resolution.ts → dist/vite/package-resolution.js} +53 -66
- package/dist/vite/package-resolution.js.map +1 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/dist/vite/virtual-entries.d.ts +25 -0
- package/dist/vite/virtual-entries.d.ts.map +1 -0
- package/{src/vite/virtual-entries.ts → dist/vite/virtual-entries.js} +18 -17
- package/dist/vite/virtual-entries.js.map +1 -0
- package/package.json +140 -57
- package/skills/breadcrumbs/SKILL.md +252 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +484 -0
- package/skills/caching/SKILL.md +276 -226
- package/skills/composability/SKILL.md +197 -0
- package/skills/debug-manifest/SKILL.md +112 -0
- package/skills/document-cache/SKILL.md +106 -53
- package/skills/fonts/SKILL.md +167 -0
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +621 -67
- package/skills/host-router/SKILL.md +243 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +265 -202
- package/skills/layout/SKILL.md +261 -146
- package/skills/links/SKILL.md +471 -0
- package/skills/loader/SKILL.md +701 -250
- package/skills/middleware/SKILL.md +254 -320
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +155 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +399 -158
- package/skills/prerender/SKILL.md +666 -0
- package/skills/rango/SKILL.md +338 -0
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +468 -0
- package/skills/route/SKILL.md +417 -89
- package/skills/router-setup/SKILL.md +389 -268
- package/skills/server-actions/SKILL.md +751 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +129 -0
- package/skills/testing/SKILL.md +549 -0
- package/skills/theme/SKILL.md +36 -11
- package/skills/typesafety/SKILL.md +747 -174
- package/skills/use-cache/SKILL.md +353 -0
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +117 -0
- package/src/__internal.ts +273 -0
- package/src/bin/rango.ts +321 -0
- package/src/browser/action-coordinator.ts +114 -0
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +172 -128
- package/src/browser/history-state.ts +101 -0
- package/src/browser/index.ts +3 -3
- 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 +390 -557
- package/src/browser/navigation-client.ts +228 -70
- package/src/browser/navigation-store.ts +104 -63
- package/src/browser/navigation-transaction.ts +279 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +397 -303
- 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 +258 -74
- package/src/browser/react/NavigationProvider.tsx +237 -49
- 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 +269 -56
- package/src/browser/react/location-state.ts +90 -19
- package/src/browser/react/mount-context.ts +37 -0
- 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 +41 -98
- package/src/browser/react/use-href.tsx +20 -188
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-mount.ts +31 -0
- package/src/browser/react/use-navigation.ts +49 -80
- package/src/browser/react/use-params.ts +77 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +96 -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 +98 -0
- package/src/browser/rsc-router.tsx +273 -78
- package/src/browser/scroll-restoration.ts +132 -49
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +83 -0
- package/src/browser/server-action-bridge.ts +504 -589
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +184 -58
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +463 -0
- package/src/build/generate-route-types.ts +41 -0
- package/src/build/index.ts +37 -0
- package/src/build/route-trie.ts +292 -0
- 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 +131 -0
- package/src/build/route-types/router-processing.ts +659 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +220 -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 +150 -306
- package/src/cache/cf/cf-cache-store.ts +619 -24
- 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 +76 -121
- package/src/client.rsc.tsx +15 -15
- package/src/client.tsx +145 -309
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +6 -2
- package/src/context-var.ts +156 -0
- package/src/debug.ts +243 -0
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +138 -3
- package/src/handle.ts +90 -22
- package/src/handles/MetaTags.tsx +76 -23
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/handles/meta.ts +32 -15
- package/src/host/cookie-handler.ts +165 -0
- package/src/host/errors.ts +97 -0
- package/src/host/index.ts +53 -0
- package/src/host/pattern-matcher.ts +214 -0
- package/src/host/router.ts +424 -0
- package/src/host/testing.ts +79 -0
- package/src/host/types.ts +175 -0
- package/src/host/utils.ts +25 -0
- package/src/href-client.ts +263 -49
- package/src/index.rsc.ts +190 -29
- package/src/index.ts +278 -38
- package/src/internal-debug.ts +11 -0
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +24 -142
- package/src/loader.ts +21 -11
- package/src/missing-id-error.ts +68 -0
- 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 +37 -0
- package/src/prerender/store.ts +186 -0
- package/src/prerender.ts +524 -0
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +380 -0
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +15 -39
- package/src/route-definition/dsl-helpers.ts +1109 -0
- package/src/route-definition/helper-factories.ts +90 -0
- package/src/route-definition/helpers-types.ts +506 -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/use-item-types.ts +32 -0
- package/src/route-definition.ts +1 -1371
- package/src/route-map-builder.ts +247 -112
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +99 -42
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +228 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +10 -10
- package/src/router/find-match.ts +160 -0
- package/src/router/handler-context.ts +420 -88
- package/src/router/intercept-resolution.ts +388 -0
- package/src/router/lazy-includes.ts +237 -0
- package/src/router/loader-resolution.ts +374 -128
- package/src/router/logging.ts +251 -0
- package/src/router/manifest.ts +187 -43
- package/src/router/match-api.ts +556 -0
- package/src/router/match-context.ts +6 -4
- package/src/router/match-handlers.ts +483 -0
- package/src/router/match-middleware/background-revalidation.ts +108 -93
- package/src/router/match-middleware/cache-lookup.ts +413 -10
- package/src/router/match-middleware/cache-store.ts +99 -26
- package/src/router/match-middleware/intercept-resolution.ts +57 -17
- package/src/router/match-middleware/segment-resolution.ts +80 -6
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +156 -36
- package/src/router/metrics.ts +241 -16
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +209 -0
- package/src/router/middleware.ts +359 -346
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +416 -41
- package/src/router/prerender-match.ts +502 -0
- package/src/router/preview-match.ts +100 -0
- package/src/router/request-classification.ts +286 -0
- package/src/router/revalidation.ts +195 -40
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +45 -23
- package/src/router/router-interfaces.ts +501 -0
- package/src/router/router-options.ts +657 -0
- package/src/router/router-registry.ts +21 -0
- package/src/router/segment-resolution/fresh.ts +769 -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 +1420 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/segment-resolution.ts +21 -0
- 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 +399 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +244 -0
- package/src/router/types.ts +87 -4
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +768 -3574
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +894 -806
- package/src/rsc/helpers.ts +201 -19
- package/src/rsc/index.ts +5 -25
- 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 +159 -0
- package/src/rsc/progressive-enhancement.ts +395 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +340 -0
- package/src/rsc/rsc-rendering.ts +230 -0
- package/src/rsc/runtime-warnings.ts +41 -0
- package/src/rsc/server-action.ts +336 -0
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/types.ts +54 -14
- 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 +265 -115
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +480 -90
- package/src/server/cookie-store.ts +214 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +117 -20
- package/src/server/loader-registry.ts +24 -64
- package/src/server/request-context.ts +613 -109
- package/src/server.ts +36 -131
- package/src/ssr/index.tsx +164 -25
- package/src/static-handler.ts +126 -0
- package/src/testing/cache-status.ts +166 -0
- package/src/testing/collect-handle.ts +63 -0
- package/src/testing/dispatch.ts +440 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +154 -0
- package/src/testing/e2e/index.ts +149 -0
- package/src/testing/e2e/matchers.ts +51 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +306 -0
- package/src/testing/e2e/server.ts +183 -0
- package/src/testing/flight-matchers.ts +104 -0
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/flight.entry.ts +22 -0
- package/src/testing/flight.ts +182 -0
- package/src/testing/generated-routes.ts +223 -0
- package/src/testing/index.ts +98 -0
- package/src/testing/internal/context.ts +151 -0
- package/src/testing/render-route.tsx +536 -0
- package/src/testing/run-loader.ts +296 -0
- package/src/testing/run-middleware.ts +170 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +112 -0
- package/src/theme/ThemeProvider.tsx +21 -15
- package/src/theme/ThemeScript.tsx +5 -5
- package/src/theme/constants.ts +11 -4
- package/src/theme/index.ts +4 -14
- package/src/theme/theme-context.ts +5 -31
- package/src/theme/theme-script.ts +21 -18
- package/src/theme/types.ts +1 -1
- 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 +113 -0
- package/src/types/handler-context.ts +809 -0
- package/src/types/index.ts +89 -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 +184 -0
- package/src/types.ts +1 -1561
- package/src/urls/include-helper.ts +164 -0
- package/src/urls/index.ts +50 -0
- package/src/urls/path-helper-types.ts +380 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +124 -0
- package/src/urls/response-types.ts +109 -0
- package/src/urls/type-extraction.ts +282 -0
- package/src/urls/urls-function.ts +94 -0
- package/src/urls.ts +1 -726
- package/src/use-loader.tsx +559 -108
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +181 -0
- package/src/vite/discovery/discover-routers.ts +398 -0
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +480 -0
- package/src/vite/discovery/route-types-writer.ts +214 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +150 -0
- package/src/vite/discovery/virtual-module-codegen.ts +193 -0
- package/src/vite/index.ts +20 -785
- package/src/vite/plugin-types.ts +170 -0
- package/src/vite/plugins/cjs-to-esm.ts +94 -0
- package/src/vite/plugins/client-ref-dedup.ts +131 -0
- package/src/vite/plugins/client-ref-hashing.ts +128 -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} +109 -66
- package/src/vite/plugins/expose-id-utils.ts +303 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +376 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +156 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +72 -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 +796 -0
- package/src/vite/plugins/performance-tracks.ts +92 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +338 -0
- package/src/vite/plugins/version-injector.ts +99 -0
- package/src/vite/plugins/version-plugin.ts +323 -0
- package/src/vite/plugins/virtual-entries.ts +123 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +549 -0
- package/src/vite/router-discovery.ts +1568 -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 +139 -0
- package/src/vite/utils/client-chunks.ts +190 -0
- package/src/vite/utils/forward-user-plugins.ts +193 -0
- package/src/vite/utils/manifest-utils.ts +86 -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 +251 -0
- package/CLAUDE.md +0 -7
- package/src/__tests__/component-utils.test.ts +0 -76
- package/src/__tests__/route-definition.test.ts +0 -63
- package/src/__tests__/urls.test.tsx +0 -436
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/request-controller.ts +0 -164
- package/src/cache/__tests__/document-cache.test.ts +0 -522
- package/src/cache/__tests__/memory-segment-store.test.ts +0 -487
- package/src/cache/__tests__/memory-store.test.ts +0 -484
- package/src/cache/cf/__tests__/cf-cache-store.test.ts +0 -428
- package/src/cache/memory-store.ts +0 -253
- package/src/href.ts +0 -177
- package/src/route-utils.ts +0 -89
- package/src/router/__tests__/match-context.test.ts +0 -104
- package/src/router/__tests__/match-pipelines.test.ts +0 -537
- package/src/router/__tests__/match-result.test.ts +0 -566
- package/src/router/__tests__/on-error.test.ts +0 -935
- package/src/router/__tests__/pattern-matching.test.ts +0 -577
- package/src/router/middleware.test.ts +0 -1355
- package/src/rsc/__tests__/helpers.test.ts +0 -175
- package/src/server/__tests__/request-context.test.ts +0 -171
- package/src/ssr/__tests__/ssr-handler.test.tsx +0 -188
- package/src/theme/__tests__/theme.test.ts +0 -120
- package/src/vite/__tests__/expose-loader-id.test.ts +0 -117
- package/src/vite/expose-handle-id.ts +0 -209
- package/src/vite/expose-loader-id.ts +0 -357
- package/src/vite/expose-location-state-id.ts +0 -177
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
package/skills/loader/SKILL.md
CHANGED
|
@@ -1,365 +1,816 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: loader
|
|
3
3
|
description: Define data loaders for fetching data in routes with createLoader
|
|
4
|
-
argument-hint: [loader
|
|
4
|
+
argument-hint: [loader]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Data Loaders
|
|
7
|
+
# Data Loaders with loader()
|
|
8
8
|
|
|
9
|
-
Loaders fetch data
|
|
9
|
+
Loaders fetch data on the server and stream it to the client. For mutations
|
|
10
|
+
(writes triggered by forms or buttons), use server actions instead — see
|
|
11
|
+
`/server-actions`. Loaders re-resolve after an action runs, so the typical
|
|
12
|
+
flow is _action mutates → loader re-reads → UI updates_.
|
|
10
13
|
|
|
11
14
|
## Creating a Loader
|
|
12
15
|
|
|
13
16
|
```typescript
|
|
14
|
-
import { createLoader
|
|
17
|
+
import { createLoader } from "@rangojs/router";
|
|
15
18
|
|
|
16
19
|
export const ProductLoader = createLoader(async (ctx) => {
|
|
17
|
-
|
|
18
|
-
where: { slug: ctx.params.slug },
|
|
19
|
-
});
|
|
20
|
+
"use server";
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
const product = await ctx.env.DB.prepare(
|
|
23
|
+
"SELECT * FROM products WHERE slug = ?",
|
|
24
|
+
)
|
|
25
|
+
.bind(ctx.params.slug)
|
|
26
|
+
.first();
|
|
24
27
|
|
|
25
|
-
return product;
|
|
28
|
+
return { product };
|
|
26
29
|
});
|
|
27
30
|
```
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
### Supported export patterns
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
All of the following are equivalent and fully supported by the Vite transform:
|
|
32
35
|
|
|
33
36
|
```typescript
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
ctx.query; // Query string parameters
|
|
37
|
-
ctx.url; // Full URL object
|
|
38
|
-
ctx.pathname; // Current path
|
|
39
|
-
ctx.method; // HTTP method
|
|
40
|
-
ctx.request; // Raw Request object
|
|
41
|
-
|
|
42
|
-
// Variables from middleware
|
|
43
|
-
const user = ctx.get("user");
|
|
37
|
+
// Direct export (most common)
|
|
38
|
+
export const ProductLoader = createLoader(handler);
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
// Separate declaration + named export
|
|
41
|
+
const ProductLoader = createLoader(handler);
|
|
42
|
+
export { ProductLoader };
|
|
47
43
|
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
// Aliased export
|
|
45
|
+
const InternalLoader = createLoader(handler);
|
|
46
|
+
export { InternalLoader as ProductLoader };
|
|
47
|
+
|
|
48
|
+
// Aliased import
|
|
49
|
+
import { createLoader as cl } from "@rangojs/router";
|
|
50
|
+
export const ProductLoader = cl(handler);
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
The `export const` form and the `const + export { }` form both work for
|
|
54
|
+
client stubs, ID injection, and loader manifest tracking.
|
|
55
|
+
|
|
56
|
+
## Using Loaders in Routes
|
|
53
57
|
|
|
54
58
|
```typescript
|
|
55
|
-
import {
|
|
56
|
-
import { ProductLoader } from "
|
|
57
|
-
|
|
58
|
-
export
|
|
59
|
-
|
|
60
|
-
const product = await ctx.use(ProductLoader);
|
|
61
|
-
return <ProductPage product={product} />;
|
|
62
|
-
}, () => [
|
|
59
|
+
import { urls } from "@rangojs/router";
|
|
60
|
+
import { ProductLoader } from "./loaders/product";
|
|
61
|
+
|
|
62
|
+
export const urlpatterns = urls(({ path, loader }) => [
|
|
63
|
+
path("/product/:slug", ProductPage, { name: "product" }, () => [
|
|
63
64
|
loader(ProductLoader),
|
|
64
|
-
loading(<ProductSkeleton />),
|
|
65
65
|
]),
|
|
66
66
|
]);
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
## Loader
|
|
69
|
+
## Consuming Loader Data
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
Register loaders with `loader()` in the DSL and consume them in client
|
|
72
|
+
components with `useLoader()`. This is the recommended pattern — it keeps
|
|
73
|
+
data fetching on the server and consumption on the client, with a clean
|
|
74
|
+
separation that works correctly with `cache()`.
|
|
72
75
|
|
|
73
76
|
```typescript
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return db.users.findUnique({ where: { id: userId } });
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
middleware: [
|
|
81
|
-
async (ctx, next) => {
|
|
82
|
-
const userId = ctx.params.id;
|
|
83
|
-
|
|
84
|
-
// Validate user ID
|
|
85
|
-
if (!isValidUUID(userId)) {
|
|
86
|
-
throw new Error("Invalid user ID");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
ctx.set("validatedUserId", userId);
|
|
90
|
-
await next();
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
}
|
|
94
|
-
);
|
|
95
|
-
```
|
|
77
|
+
"use client";
|
|
78
|
+
import { useLoader } from "@rangojs/router/client";
|
|
79
|
+
import { ProductLoader } from "./loaders/product";
|
|
96
80
|
|
|
97
|
-
|
|
81
|
+
function ProductDetails() {
|
|
82
|
+
const { data } = useLoader(ProductLoader);
|
|
83
|
+
return <div>{data.product.description}</div>;
|
|
84
|
+
}
|
|
85
|
+
```
|
|
98
86
|
|
|
99
87
|
```typescript
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
88
|
+
// Route definition — loader() registration required
|
|
89
|
+
path("/product/:slug", ProductPage, { name: "product" }, () => [
|
|
90
|
+
loader(ProductLoader),
|
|
91
|
+
]);
|
|
92
|
+
```
|
|
103
93
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
94
|
+
> **Client refresh `key` vs. server `cache({ key })` vs. `revalidate()`.** Three
|
|
95
|
+
> different "what refreshes" knobs that are easy to confuse:
|
|
96
|
+
>
|
|
97
|
+
> - `useLoader(Loader, { key })` / `useFetchLoader(Loader, { key })` — a
|
|
98
|
+
> **client** refresh identity. It groups which mounted reads of one loader
|
|
99
|
+
> refresh together when one calls `load()`. It never touches the server
|
|
100
|
+
> request. For refreshing **different** loaders together, tag them with
|
|
101
|
+
> `{ refreshGroup }` (one name or several) and call `useRefreshLoaders()(name)`
|
|
102
|
+
> (plain GET only). See the hooks skill ("Scoping refetch with a `key`" and
|
|
103
|
+
> "Refreshing multiple loaders together").
|
|
104
|
+
> - `cache({ key })` — a **server** cache identity (storage hit/miss/ttl/swr).
|
|
105
|
+
> - `revalidate()` — which **server** segments/loaders recompute during
|
|
106
|
+
> navigation and action refreshes.
|
|
107
|
+
|
|
108
|
+
DSL loaders are the **live data layer** — they resolve fresh on every
|
|
109
|
+
request, even when the route is inside a `cache()` boundary. The router
|
|
110
|
+
excludes them from the segment cache at storage time and re-resolves them
|
|
111
|
+
on retrieval. This means `cache()` gives you cached UI + fresh data by
|
|
112
|
+
default.
|
|
113
|
+
|
|
114
|
+
### Cache safety
|
|
115
|
+
|
|
116
|
+
DSL loaders can safely read `createVar({ cache: false })` variables
|
|
117
|
+
because they are always resolved fresh. The read guard is bypassed for
|
|
118
|
+
loader functions — they never produce stale data.
|
|
119
|
+
|
|
120
|
+
### ctx.use(Loader) — escape hatch
|
|
121
|
+
|
|
122
|
+
For cases where you need loader data in the server handler itself (e.g.,
|
|
123
|
+
to set ctx variables or make routing decisions), use `ctx.use(Loader)`:
|
|
110
124
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
)
|
|
118
|
-
}, () => [
|
|
119
|
-
loader(ProductLoader),
|
|
120
|
-
loader(ReviewsLoader),
|
|
121
|
-
loader(RelatedProductsLoader),
|
|
125
|
+
```typescript
|
|
126
|
+
path("/product/:slug", async (ctx) => {
|
|
127
|
+
const { product } = await ctx.use(ProductLoader);
|
|
128
|
+
ctx.set(Product, product); // make available to children
|
|
129
|
+
return <ProductPage />;
|
|
130
|
+
}, { name: "product" }, () => [
|
|
131
|
+
loader(ProductLoader), // still register for client consumption
|
|
122
132
|
])
|
|
123
133
|
```
|
|
124
134
|
|
|
125
|
-
|
|
135
|
+
When you register with `loader()` in the DSL, `ctx.use()` returns the
|
|
136
|
+
same memoized result — loaders never run twice per request.
|
|
137
|
+
|
|
138
|
+
**Limitations of ctx.use(Loader):**
|
|
139
|
+
|
|
140
|
+
- The handler output depends on the loader data. If the route is inside
|
|
141
|
+
`cache()`, the handler is cached with the loader result baked in —
|
|
142
|
+
defeating the live data guarantee.
|
|
143
|
+
- Non-cacheable variable reads (`createVar({ cache: false })`) inside the
|
|
144
|
+
handler still throw, even if the data came from a loader.
|
|
145
|
+
- Prefer DSL `loader()` + client `useLoader()` for data that depends on
|
|
146
|
+
non-cacheable context variables.
|
|
147
|
+
|
|
148
|
+
**Never use `useLoader()` in server components** — it is a client-only API.
|
|
149
|
+
|
|
150
|
+
### Summary
|
|
126
151
|
|
|
127
|
-
|
|
152
|
+
| Pattern | API | Cache-safe | Recommended |
|
|
153
|
+
| ---------------------- | ------------------- | ---------- | ----------- |
|
|
154
|
+
| DSL + client component | `useLoader(Loader)` | Yes | Yes |
|
|
155
|
+
| Handler escape hatch | `ctx.use(Loader)` | No | When needed |
|
|
156
|
+
|
|
157
|
+
## Loader Context
|
|
158
|
+
|
|
159
|
+
Loaders receive the same context shape as route handlers.
|
|
160
|
+
|
|
161
|
+
### Full field surface
|
|
162
|
+
|
|
163
|
+
| Field | Type | Notes |
|
|
164
|
+
| -------------- | ------------------------------ | --------------------------------------------------------------------------------------------------- |
|
|
165
|
+
| `params` | `TParams` | Merged route + explicit loader params; overridable by fetchable `load({ params })`. |
|
|
166
|
+
| `routeParams` | `Record<string, string>` | Server-trusted route params from URL pattern matching; cannot be overridden. |
|
|
167
|
+
| `request` | `Request` | The incoming `Request` (headers, method, body, `signal` for abort). |
|
|
168
|
+
| `url` | `URL` | Parsed request URL. |
|
|
169
|
+
| `pathname` | `string` | URL pathname (shortcut for `ctx.url.pathname`). |
|
|
170
|
+
| `searchParams` | `URLSearchParams` | Shortcut for `ctx.url.searchParams`. |
|
|
171
|
+
| `search` | `ResolveSearchSchema<TSearch>` | Typed query params when a search schema is declared on the route; `{}` otherwise. |
|
|
172
|
+
| `env` | `TEnv` | Plain bindings from `createRouter<TEnv>()` (DB, KV, secrets, etc.). |
|
|
173
|
+
| `get` | `(key \| ContextVar) => value` | Reads variables/context-vars set by middleware. |
|
|
174
|
+
| `use` | `(loader \| handle) => T` | Access another loader's data (Promise) or a handle's collected data (after `await ctx.rendered()`). |
|
|
175
|
+
| `rendered` | `() => Promise<void>` | **Experimental.** DSL loaders only — waits for non-loader segments before reading handle data. |
|
|
176
|
+
| `method` | `string` | HTTP method. `"GET"` for SSR loader runs; reflects real method for fetchable loaders. |
|
|
177
|
+
| `body` | `TBody \| undefined` | Parsed request body for fetchable POST/PUT/PATCH/DELETE calls. |
|
|
178
|
+
| `formData` | `FormData \| undefined` | Present when a fetchable loader is invoked via form submission. |
|
|
179
|
+
| `reverse` | `ScopedReverseFunction` | Generate type-checked URLs from route names (same scoped semantics as route handlers). |
|
|
180
|
+
|
|
181
|
+
### Example
|
|
128
182
|
|
|
129
183
|
```typescript
|
|
130
|
-
|
|
131
|
-
|
|
184
|
+
export const ProductLoader = createLoader(async (ctx) => {
|
|
185
|
+
"use server";
|
|
132
186
|
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
currentParams.slug !== nextParams.slug
|
|
136
|
-
),
|
|
187
|
+
// URL params (may include client-provided overrides for fetchable loaders)
|
|
188
|
+
const { slug } = ctx.params;
|
|
137
189
|
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
190
|
+
// Server-trusted route params (from URL pattern matching, cannot be overridden)
|
|
191
|
+
const { slug: trustedSlug } = ctx.routeParams;
|
|
192
|
+
|
|
193
|
+
// Query params
|
|
194
|
+
const variant = ctx.url.searchParams.get("variant");
|
|
195
|
+
|
|
196
|
+
// Platform bindings (DB, KV, etc.) — plain bindings from createRouter<TEnv>()
|
|
197
|
+
const db = ctx.env.DB;
|
|
198
|
+
|
|
199
|
+
// Request headers
|
|
200
|
+
const auth = ctx.request.headers.get("Authorization");
|
|
201
|
+
|
|
202
|
+
// Variables set by middleware (from Rango.Vars augmentation)
|
|
203
|
+
const user = ctx.get("user");
|
|
204
|
+
|
|
205
|
+
// Type-checked URLs for payloads. `.name` resolves within the current
|
|
206
|
+
// include() scope; a bare `name` resolves globally. See /route and
|
|
207
|
+
// /typesafety for scope rules and route-name autocomplete.
|
|
208
|
+
const detailUrl = ctx.reverse(".detail", { slug });
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
product: await fetchProduct(slug),
|
|
212
|
+
links: { self: detailUrl },
|
|
213
|
+
};
|
|
214
|
+
});
|
|
143
215
|
```
|
|
144
216
|
|
|
145
|
-
|
|
217
|
+
See `/route` for the full handler-context contract (shared with loaders) and
|
|
218
|
+
`/typesafety` for route-name typing that powers `ctx.reverse` autocomplete.
|
|
219
|
+
|
|
220
|
+
### params vs routeParams
|
|
221
|
+
|
|
222
|
+
- `ctx.params` — merged route params + explicit loader params. For fetchable
|
|
223
|
+
loaders called with `load(Loader, { params: { ... } })`, explicit params
|
|
224
|
+
override route-matched params.
|
|
225
|
+
- `ctx.routeParams` — server-trusted route params from URL pattern matching.
|
|
226
|
+
Cannot be overridden by client-provided params.
|
|
227
|
+
|
|
228
|
+
Use `ctx.routeParams` when you need trusted route identity for authorization
|
|
229
|
+
or resource scoping:
|
|
146
230
|
|
|
147
231
|
```typescript
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return currentParams.id !== nextParams.id; // boolean
|
|
151
|
-
});
|
|
232
|
+
export const OrderLoader = createLoader(async (ctx) => {
|
|
233
|
+
"use server";
|
|
152
234
|
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
235
|
+
// Use routeParams for auth checks — client cannot spoof the URL-matched ID
|
|
236
|
+
const { orderId } = ctx.routeParams;
|
|
237
|
+
const user = ctx.get("user");
|
|
238
|
+
|
|
239
|
+
const order = await db.orders.get(orderId);
|
|
240
|
+
if (order.userId !== user.id)
|
|
241
|
+
throw new Response("Forbidden", { status: 403 });
|
|
242
|
+
|
|
243
|
+
return { order };
|
|
160
244
|
});
|
|
161
245
|
```
|
|
162
246
|
|
|
163
|
-
##
|
|
247
|
+
## Loader with Children
|
|
164
248
|
|
|
165
|
-
|
|
249
|
+
Add caching or revalidation to specific loaders:
|
|
166
250
|
|
|
167
|
-
```
|
|
168
|
-
"
|
|
169
|
-
|
|
170
|
-
|
|
251
|
+
```typescript
|
|
252
|
+
path("/product/:slug", ProductPage, { name: "product" }, () => [
|
|
253
|
+
// Cached loader
|
|
254
|
+
loader(ProductLoader, () => [cache({ ttl: 300 })]),
|
|
171
255
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
256
|
+
// Loader with revalidation control
|
|
257
|
+
loader(RelatedProductsLoader, () => [
|
|
258
|
+
revalidate(() => false), // Never revalidate
|
|
259
|
+
]),
|
|
260
|
+
|
|
261
|
+
// Loader that revalidates after cart actions (defer otherwise — keeps the
|
|
262
|
+
// permissive loader defaults for navigation and other actions intact)
|
|
263
|
+
loader(CartLoader, () => [
|
|
264
|
+
revalidate(({ actionId }) => actionId?.includes("Cart") || undefined),
|
|
265
|
+
]),
|
|
266
|
+
]);
|
|
177
267
|
```
|
|
178
268
|
|
|
179
|
-
###
|
|
269
|
+
### `revalidate()` return shapes
|
|
180
270
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
271
|
+
> **Scope: `revalidate()` is a partial-render concern, not a cache concern.**
|
|
272
|
+
> It decides whether a segment (here, a loader) re-runs and streams to the
|
|
273
|
+
> client on a navigation or action — never whether a cached value is stale. The
|
|
274
|
+
> cache decides hit/miss/ttl/swr independently and never reads `revalidate()`.
|
|
275
|
+
> Caching a loader is a separate, opt-in step (`loader(Fn, () => [cache({...})])`).
|
|
276
|
+
> See `/cache-guide` → "Two axes" and `/rango` → "The shape of rango".
|
|
185
277
|
|
|
186
|
-
|
|
187
|
-
|
|
278
|
+
A `revalidate(fn)` callback can return one of four shapes. The chain
|
|
279
|
+
processes revalidators in order; each call's return controls how the
|
|
280
|
+
chain continues:
|
|
188
281
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
282
|
+
```typescript
|
|
283
|
+
// 1) Hard decision — short-circuits the chain, used as the final answer.
|
|
284
|
+
revalidate(() => true);
|
|
285
|
+
revalidate(({ actionId }) => actionId?.includes("Cart") ?? false);
|
|
286
|
+
|
|
287
|
+
// 2) Soft decision — updates the running suggestion for downstream
|
|
288
|
+
// revalidators on the same segment, chain continues.
|
|
289
|
+
revalidate(({ defaultShouldRevalidate }) => ({
|
|
290
|
+
defaultShouldRevalidate: !defaultShouldRevalidate,
|
|
291
|
+
}));
|
|
292
|
+
|
|
293
|
+
// 3) Defer (no opinion) — leaves the running suggestion unchanged and
|
|
294
|
+
// continues to the next revalidator. Implicit return / null /
|
|
295
|
+
// undefined are all equivalent and consumer-friendly.
|
|
296
|
+
revalidate(({ actionId }) => {
|
|
297
|
+
if (actionId?.includes("Cart")) return true; // hard for this branch only
|
|
298
|
+
// implicit return — let downstream revalidators or the segment default decide
|
|
299
|
+
});
|
|
300
|
+
revalidate(() => undefined); // explicit defer
|
|
301
|
+
revalidate(() => null); // explicit defer
|
|
302
|
+
```
|
|
192
303
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
304
|
+
If every revalidator on a segment defers, the segment-type default
|
|
305
|
+
(e.g. params-changed for routes, `false` for parallels) is used.
|
|
306
|
+
|
|
307
|
+
#### `|| undefined` (defer) vs `?? false` (hard) — pick deliberately
|
|
308
|
+
|
|
309
|
+
A boolean return — including `false` — is a **hard** decision: it short-circuits
|
|
310
|
+
the chain and overrides the segment default. `undefined` **defers** to the
|
|
311
|
+
running suggestion / segment default. They are not interchangeable:
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
// Defer: "revalidate on match, otherwise let the default/downstream decide."
|
|
315
|
+
revalidate(({ actionId }) => actionId?.includes("Cart") || undefined);
|
|
316
|
+
|
|
317
|
+
// Hard: "revalidate ONLY on match, suppress everything else."
|
|
318
|
+
revalidate(({ actionId }) => actionId?.includes("Cart") ?? false);
|
|
201
319
|
```
|
|
202
320
|
|
|
203
|
-
|
|
321
|
+
This matters most for loaders, whose defaults are permissive: a loader defaults
|
|
322
|
+
to revalidating on **any** action (`POST`) and on **param/search changes**
|
|
323
|
+
during navigation. So `?? false` on a loader silently suppresses both — the
|
|
324
|
+
loader will not refetch when you navigate to a different `:id`. Use
|
|
325
|
+
`|| undefined` when you want to _add_ a revalidation signal on top of the
|
|
326
|
+
sensible defaults, and reserve `?? false` for the rare case where you genuinely
|
|
327
|
+
want the loader to refetch on nothing but your matched action.
|
|
328
|
+
|
|
329
|
+
When **composing multiple revalidators** on one segment (see below), defer is
|
|
330
|
+
mandatory: the first hard `?? false` ends the chain and the later contracts
|
|
331
|
+
never run.
|
|
204
332
|
|
|
205
|
-
|
|
333
|
+
#### Matching actions: `ctx.isAction()`
|
|
334
|
+
|
|
335
|
+
To revalidate after specific server actions, match them by **reference** with
|
|
336
|
+
`ctx.isAction()` rather than hand-written `actionId` substrings. A rename or
|
|
337
|
+
moved file then becomes a type error instead of silently failing to match:
|
|
206
338
|
|
|
207
339
|
```typescript
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
// Immediate data
|
|
211
|
-
product: await db.products.findUnique({ where: { id: ctx.params.id } }),
|
|
340
|
+
import { addToCart, removeFromCart } from "../actions/cart";
|
|
341
|
+
import * as CartActions from "../actions/cart";
|
|
212
342
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
343
|
+
loader(CartLoader, () => [
|
|
344
|
+
revalidate((ctx) => ctx.isAction(addToCart) || undefined), // one action
|
|
345
|
+
]);
|
|
346
|
+
revalidate((ctx) => ctx.isAction(addToCart, removeFromCart) || undefined); // several
|
|
347
|
+
revalidate((ctx) => ctx.isAction(CartActions) || undefined); // any action in the module
|
|
217
348
|
```
|
|
218
349
|
|
|
219
|
-
|
|
350
|
+
`isAction()` is a method on the revalidate predicate's **context argument** —
|
|
351
|
+
there is no standalone `isAction` import; you always reach it through the callback
|
|
352
|
+
parameter (`revalidate((ctx) => ctx.isAction(...))`). It returns a raw boolean, so
|
|
353
|
+
pair it with `|| undefined` for the usual "revalidate on match, else defer"
|
|
354
|
+
intent. It returns `false` on plain navigation and on non-matches, and resolves
|
|
355
|
+
the reference the same way the router derives `actionId` (`$id` in production,
|
|
356
|
+
`$$id` in dev), so it matches in both modes. The raw `actionId` string stays
|
|
357
|
+
available on the same context as an escape hatch.
|
|
358
|
+
|
|
359
|
+
### Revalidation Contracts for Loader Dependencies
|
|
360
|
+
|
|
361
|
+
If a loader reads `ctx.get()` data produced by an outer handler/layout, share
|
|
362
|
+
the same named revalidation contract across producer and consumer segments.
|
|
220
363
|
|
|
221
364
|
```typescript
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
365
|
+
// revalidation-contracts.ts
|
|
366
|
+
import * as AccountActions from "./actions/account";
|
|
367
|
+
|
|
368
|
+
// Match by reference with ctx.isAction() (rename-safe), and defer (|| undefined)
|
|
369
|
+
// so these contracts compose — a hard `false` would short-circuit the rest.
|
|
370
|
+
export const revalidateAccountScope = (ctx) =>
|
|
371
|
+
ctx.isAction(AccountActions) || undefined;
|
|
372
|
+
|
|
373
|
+
layout(AccountLayout, () => [
|
|
374
|
+
revalidate(revalidateAccountScope), // producer reruns
|
|
375
|
+
path("/account/orders", OrdersPage, { name: "account.orders" }, () => [
|
|
376
|
+
loader(OrdersLoader, () => [
|
|
377
|
+
revalidate(revalidateAccountScope), // consumer reruns
|
|
378
|
+
]),
|
|
228
379
|
]),
|
|
229
|
-
])
|
|
380
|
+
]);
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
For segments that depend on multiple upstream domains, compose multiple
|
|
384
|
+
contracts on both sides.
|
|
385
|
+
|
|
386
|
+
To keep loader route trees concise, export helper wrappers:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
import { revalidate } from "@rangojs/router";
|
|
390
|
+
|
|
391
|
+
export const revalidateAccount = () => [revalidate(revalidateAccountScope)];
|
|
392
|
+
|
|
393
|
+
layout(AccountLayout, () => [
|
|
394
|
+
revalidateAccount(),
|
|
395
|
+
path("/account/orders", OrdersPage, { name: "account.orders" }, () => [
|
|
396
|
+
loader(OrdersLoader, () => [revalidateAccount()]),
|
|
397
|
+
]),
|
|
398
|
+
]);
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## Loaders: The Live Data Layer
|
|
402
|
+
|
|
403
|
+
Loaders are the live data layer of the router. They resolve fresh on every
|
|
404
|
+
request, even when the route's UI segments are served from cache. This is a
|
|
405
|
+
core design principle — route-level `cache()` caches rendered components but
|
|
406
|
+
never caches loader data. Loaders are excluded at storage time and re-resolved
|
|
407
|
+
on retrieval.
|
|
408
|
+
|
|
409
|
+
This means `cache()` gives you cached UI + fresh data by default. Pre-rendering
|
|
410
|
+
follows the same rule: at build time, loaders are skipped entirely (there is no
|
|
411
|
+
real request context), and at runtime the worker resolves them fresh against
|
|
412
|
+
the live database.
|
|
413
|
+
|
|
414
|
+
### Parallel and streaming — latency overlaps first paint
|
|
415
|
+
|
|
416
|
+
Loaders do not block the page. As the render pass begins — the pass that route
|
|
417
|
+
middleware wraps, so loaders run right after middleware, not in a later
|
|
418
|
+
phase — every matched loader is kicked off **concurrently** (their promises start in the
|
|
419
|
+
same tick), and each result is **streamed** to the client as its own RSC Flight
|
|
420
|
+
chunk rather than awaited up front. Pair a loader with `loading()` (or a
|
|
421
|
+
client `<Suspense>`) and the shell paints immediately while the data streams in.
|
|
422
|
+
|
|
423
|
+
This is why **"cached UI still pays full data latency" is the wrong intuition**:
|
|
424
|
+
on a `cache()` hit the UI segments stream instantly from cache while the live
|
|
425
|
+
loaders resolve fresh **in parallel** — data latency _overlaps_ first paint
|
|
426
|
+
instead of being added on top of it. (Without a `loading()` / `<Suspense>`
|
|
427
|
+
boundary a parallel loader blocks its parent, so add one to keep the overlap.)
|
|
428
|
+
|
|
429
|
+
If you come from a framework where the loader is a blocking step that runs
|
|
430
|
+
before the response is built, this is the shift to internalize: here the
|
|
431
|
+
response starts streaming first and loader data fills in.
|
|
432
|
+
|
|
433
|
+
### See it: `debugPerformance`
|
|
434
|
+
|
|
435
|
+
Turn on the per-request performance timeline early — it is the fastest way to
|
|
436
|
+
confirm loaders overlap rather than serialize, and to find the real bottleneck
|
|
437
|
+
locally instead of guessing:
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
const router = createRouter({ document: Document, debugPerformance: true });
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Or enable it per-request from middleware (e.g. only when `?debug` is present) by
|
|
444
|
+
calling `ctx.debugPerformance()` **before** `await next()`. Each HTML request
|
|
445
|
+
then prints a shared-axis waterfall (and emits a `Server-Timing` header):
|
|
446
|
+
|
|
447
|
+
```
|
|
448
|
+
[RSC Perf] GET /product/widget (24.53ms)
|
|
449
|
+
start dur span timeline
|
|
450
|
+
0.08ms 3.20ms route-matching |#####...................................|
|
|
451
|
+
3.40ms 8.70ms ssr-render-html |.....##############.....................|
|
|
452
|
+
3.42ms 11.90ms loader:…#ProductLoader |.....###################................|
|
|
453
|
+
3.45ms 11.40ms loader:…#ReviewsLoader |.....##################.................|
|
|
454
|
+
0.00ms 24.53ms handler:total |########################################|
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
How to read it:
|
|
458
|
+
|
|
459
|
+
- **Humans:** scan the `#` bars on the shared axis. Bars that start at the same
|
|
460
|
+
offset and run side by side are executing **in parallel** — loaders should
|
|
461
|
+
overlap `ssr-render-html` / `render:total`, not sit alone to the right of
|
|
462
|
+
everything. A lone `loader:*` bar past the render bar is serialized latency to
|
|
463
|
+
chase. `handler:total` is the whole request; `render:total` is the render pass.
|
|
464
|
+
- **LLMs / programmatic:** read each row as `{ start, dur, label }`. A loader
|
|
465
|
+
overlaps paint when its `[start, start+dur]` interval intersects
|
|
466
|
+
`render:total` / `ssr-render-html`. Flag a regression when a `loader:*`
|
|
467
|
+
interval is **disjoint from and starts after** `render:total`, or when its
|
|
468
|
+
`dur` approaches `handler:total` — that loader is on the critical path instead
|
|
469
|
+
of overlapping it. Two `loader:*` rows with near-equal `start` confirm
|
|
470
|
+
parallel execution.
|
|
471
|
+
|
|
472
|
+
### Opting a Loader into Caching
|
|
473
|
+
|
|
474
|
+
To cache a specific loader's data, attach a `cache()` child:
|
|
230
475
|
|
|
231
|
-
|
|
232
|
-
cache({ ttl:
|
|
476
|
+
```typescript
|
|
477
|
+
loader(ProductLoader, () => [cache({ ttl: 300 })]),
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
The loader's data is cached independently from the route's segment cache,
|
|
481
|
+
using the same `SegmentCacheStore` (app-level or per-loader override).
|
|
482
|
+
|
|
483
|
+
Values are serialized through RSC Flight, so loaders can return ReactNode,
|
|
484
|
+
Promises, null, and any RSC-serializable type — all round-trip correctly
|
|
485
|
+
through the cache.
|
|
486
|
+
|
|
487
|
+
### Cache Key
|
|
488
|
+
|
|
489
|
+
The default cache key is `loader:{loaderId}:{pathname}:{sortedParams}`.
|
|
490
|
+
This can be customized at two levels:
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
// Full override — key function replaces the default entirely
|
|
494
|
+
loader(ProductLoader, () => [
|
|
495
|
+
cache({
|
|
496
|
+
ttl: 300,
|
|
497
|
+
key: (ctx) => `product:${ctx.params.slug}:${cookies().get("locale")?.value ?? "en"}`,
|
|
498
|
+
}),
|
|
499
|
+
]),
|
|
500
|
+
|
|
501
|
+
// Store-level keyGenerator — modifies the default key (e.g., adds a region prefix)
|
|
502
|
+
// Set in the store configuration, applies to all entries in that store
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
Resolution priority (same as route-level `cache()`):
|
|
506
|
+
|
|
507
|
+
1. `key(ctx)` from cache options — full override
|
|
508
|
+
2. `store.keyGenerator(ctx, defaultKey)` — store-level modification
|
|
509
|
+
3. Default key — `loader:{id}:{pathname}:{params}`
|
|
510
|
+
|
|
511
|
+
If a custom key function throws, it falls back to the default key silently
|
|
512
|
+
(logged to console.error).
|
|
513
|
+
|
|
514
|
+
### Tags for Invalidation
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
// Static tags
|
|
518
|
+
loader(ProductLoader, () => [
|
|
519
|
+
cache({ ttl: 300, tags: ["products", "catalog"] }),
|
|
520
|
+
]),
|
|
521
|
+
|
|
522
|
+
// Dynamic tags
|
|
523
|
+
loader(ProductLoader, () => [
|
|
524
|
+
cache({
|
|
525
|
+
ttl: 300,
|
|
526
|
+
tags: (ctx) => [`product:${ctx.params.slug}`, "products"],
|
|
527
|
+
}),
|
|
528
|
+
]),
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Stale-While-Revalidate
|
|
532
|
+
|
|
533
|
+
```typescript
|
|
534
|
+
loader(ProductLoader, () => [
|
|
535
|
+
cache({ ttl: 60, swr: 300 }),
|
|
536
|
+
]),
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
During the SWR window (60-360s), stale data is returned immediately while
|
|
540
|
+
fresh data is fetched in the background via `waitUntil`. After the SWR window
|
|
541
|
+
expires (360s+), the entry is treated as a cache miss.
|
|
542
|
+
|
|
543
|
+
### Conditional Caching
|
|
544
|
+
|
|
545
|
+
Skip the cache at runtime based on request properties:
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
loader(ProductLoader, () => [
|
|
549
|
+
cache({
|
|
550
|
+
ttl: 300,
|
|
551
|
+
condition: (ctx) => !ctx.request.headers.has("authorization"),
|
|
552
|
+
}),
|
|
553
|
+
]),
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
When `condition` returns false, the loader runs fresh and the cache is bypassed
|
|
557
|
+
entirely (no read, no write).
|
|
558
|
+
|
|
559
|
+
### Per-Loader Store Override
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
const hotStore = new MemorySegmentCacheStore({ defaults: { ttl: 10 } });
|
|
563
|
+
|
|
564
|
+
loader(PricingLoader, () => [
|
|
565
|
+
cache({ store: hotStore }),
|
|
566
|
+
]),
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
Without an explicit store, the loader uses the app-level store from the
|
|
570
|
+
handler config (`cache.store`).
|
|
571
|
+
|
|
572
|
+
## Multiple Loaders
|
|
573
|
+
|
|
574
|
+
Routes can have multiple loaders that run in parallel:
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
path("/product/:slug", ProductPage, { name: "product" }, () => [
|
|
233
578
|
loader(ProductLoader),
|
|
234
|
-
|
|
579
|
+
loader(RelatedProductsLoader),
|
|
580
|
+
loader(ReviewsLoader),
|
|
581
|
+
]);
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
## Layout Loaders
|
|
585
|
+
|
|
586
|
+
Loaders on layouts are shared by all child routes:
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
layout(<ShopLayout />, () => [
|
|
590
|
+
// These loaders are available to all shop routes
|
|
591
|
+
loader(CartLoader),
|
|
592
|
+
loader(CategoriesLoader),
|
|
593
|
+
|
|
594
|
+
path("/shop", ShopIndex, { name: "index" }),
|
|
595
|
+
path("/shop/product/:slug", ProductPage, { name: "product" }),
|
|
235
596
|
])
|
|
236
597
|
```
|
|
237
598
|
|
|
238
|
-
##
|
|
599
|
+
## Passing Loaders as Props
|
|
600
|
+
|
|
601
|
+
Loaders can be passed as props from server to client components. RSC serialization
|
|
602
|
+
uses `toJSON()` to send only `{ __brand, $$id }` — the loader function is stripped.
|
|
239
603
|
|
|
240
604
|
```typescript
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const product = await db.products.findUnique({
|
|
244
|
-
where: { slug: ctx.params.slug },
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
if (!product) {
|
|
248
|
-
throw notFound("Product not found");
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return product;
|
|
252
|
-
} catch (error) {
|
|
253
|
-
if (error instanceof DatabaseError) {
|
|
254
|
-
throw new Error("Failed to load product");
|
|
255
|
-
}
|
|
256
|
-
throw error;
|
|
257
|
-
}
|
|
258
|
-
});
|
|
605
|
+
// Server component (route handler)
|
|
606
|
+
import { SlowLoader } from "../loaders";
|
|
259
607
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
errorBoundary(({ error, reset }) => (
|
|
264
|
-
<div>
|
|
265
|
-
<p>Error loading product: {error.message}</p>
|
|
266
|
-
<button onClick={reset}>Retry</button>
|
|
267
|
-
</div>
|
|
268
|
-
)),
|
|
608
|
+
path("/dashboard", () => <DashboardContent loader={SlowLoader} />, { name: "dashboard" }, () => [
|
|
609
|
+
loader(SlowLoader),
|
|
610
|
+
loading(<DashboardSkeleton />),
|
|
269
611
|
])
|
|
612
|
+
|
|
613
|
+
// Client component — use typeof for type-safe props
|
|
614
|
+
"use client";
|
|
615
|
+
import { useLoader } from "@rangojs/router/client";
|
|
616
|
+
import type { SlowLoader } from "../loaders";
|
|
617
|
+
|
|
618
|
+
function DashboardContent({ loader }: { loader: typeof SlowLoader }) {
|
|
619
|
+
const { data } = useLoader(loader);
|
|
620
|
+
return <div>{data.message}</div>;
|
|
621
|
+
}
|
|
270
622
|
```
|
|
271
623
|
|
|
272
|
-
|
|
624
|
+
Use `typeof MyLoader` for the prop type — it infers the full generic automatically.
|
|
625
|
+
|
|
626
|
+
## Streaming with Suspense
|
|
627
|
+
|
|
628
|
+
Loaders stream data. Use Suspense for loading states:
|
|
273
629
|
|
|
274
630
|
```typescript
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
)
|
|
631
|
+
// In route definition
|
|
632
|
+
path("/product/:slug", ProductPage, { name: "product" }, () => [
|
|
633
|
+
loader(ProductLoader),
|
|
634
|
+
loading(<ProductSkeleton />), // Shows while loader streams
|
|
635
|
+
])
|
|
636
|
+
|
|
637
|
+
// Or in component
|
|
638
|
+
function ProductPage() {
|
|
639
|
+
return (
|
|
640
|
+
<Suspense fallback={<ProductSkeleton />}>
|
|
641
|
+
<ProductDetails />
|
|
642
|
+
</Suspense>
|
|
643
|
+
);
|
|
644
|
+
}
|
|
288
645
|
```
|
|
289
646
|
|
|
290
|
-
##
|
|
647
|
+
## Fetchable Loaders
|
|
648
|
+
|
|
649
|
+
By default, loaders only run during SSR and navigation. Pass `true` as the second
|
|
650
|
+
argument to `createLoader` to make a loader **fetchable** — callable from the client
|
|
651
|
+
via `useFetchLoader()` and `load()`:
|
|
291
652
|
|
|
292
653
|
```typescript
|
|
293
|
-
|
|
294
|
-
export const UserLoader = createLoader(async (ctx) => {
|
|
295
|
-
return db.users.findUnique({ where: { id: ctx.get("userId") } });
|
|
296
|
-
});
|
|
654
|
+
import { createLoader } from "@rangojs/router";
|
|
297
655
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const user = await ctx.use(UserLoader);
|
|
301
|
-
const orders = await db.orders.findMany({
|
|
302
|
-
where: { userId: user.id },
|
|
303
|
-
});
|
|
656
|
+
export const SearchLoader = createLoader(async (ctx) => {
|
|
657
|
+
"use server";
|
|
304
658
|
|
|
305
|
-
|
|
306
|
-
|
|
659
|
+
const query = ctx.params.query ?? "";
|
|
660
|
+
const results = await ctx.env.DB.prepare(
|
|
661
|
+
"SELECT * FROM products WHERE name LIKE ?",
|
|
662
|
+
)
|
|
663
|
+
.bind(`%${query}%`)
|
|
664
|
+
.all();
|
|
665
|
+
|
|
666
|
+
return { results: results.results ?? [] };
|
|
667
|
+
}, true); // true = fetchable
|
|
307
668
|
```
|
|
308
669
|
|
|
309
|
-
|
|
670
|
+
### Fetchable Loader with Middleware
|
|
671
|
+
|
|
672
|
+
Pass an options object instead of `true` to attach per-loader middleware.
|
|
673
|
+
This middleware runs only on `_rsc_loader` fetch requests (client-side
|
|
674
|
+
`load()` / `useFetchLoader()` calls), not during SSR `ctx.use()` execution:
|
|
310
675
|
|
|
311
676
|
```typescript
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
});
|
|
677
|
+
import { createLoader } from "@rangojs/router";
|
|
678
|
+
import { authMiddleware } from "../middleware/auth";
|
|
679
|
+
import { rateLimitMiddleware } from "../middleware/rate-limit";
|
|
316
680
|
|
|
317
|
-
|
|
318
|
-
|
|
681
|
+
export const ProtectedLoader = createLoader(
|
|
682
|
+
async (ctx) => {
|
|
683
|
+
"use server";
|
|
319
684
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
685
|
+
const user = ctx.get("user");
|
|
686
|
+
return { orders: await db.orders.list(user.id) };
|
|
687
|
+
},
|
|
688
|
+
{ middleware: [authMiddleware, rateLimitMiddleware] },
|
|
689
|
+
);
|
|
323
690
|
```
|
|
324
691
|
|
|
325
|
-
|
|
692
|
+
The middleware uses the same `MiddlewareFn` signature as route/app middleware,
|
|
693
|
+
so you can reuse existing middleware functions directly.
|
|
694
|
+
|
|
695
|
+
Fetchable loaders support both GET and POST (PUT, PATCH, DELETE) from the client.
|
|
696
|
+
The `load()` function auto-detects the body type:
|
|
326
697
|
|
|
327
|
-
|
|
698
|
+
- **JSON body** (`body: { ... }`) — sent as `application/json`, available as `ctx.body`
|
|
699
|
+
- **FormData body** (`body: formData`) — sent as `multipart/form-data`, available as `ctx.formData`
|
|
700
|
+
|
|
701
|
+
### Mutation Context
|
|
702
|
+
|
|
703
|
+
When a fetchable loader receives a POST/PUT/PATCH/DELETE request, the context
|
|
704
|
+
includes additional fields depending on the body type:
|
|
328
705
|
|
|
329
706
|
```typescript
|
|
330
|
-
export const
|
|
331
|
-
|
|
332
|
-
const limit = 20;
|
|
333
|
-
|
|
334
|
-
const [products, total] = await Promise.all([
|
|
335
|
-
db.products.findMany({
|
|
336
|
-
skip: (page - 1) * limit,
|
|
337
|
-
take: limit,
|
|
338
|
-
}),
|
|
339
|
-
db.products.count(),
|
|
340
|
-
]);
|
|
707
|
+
export const MutationLoader = createLoader(async (ctx) => {
|
|
708
|
+
"use server";
|
|
341
709
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
710
|
+
// JSON body — available as ctx.body (parsed object)
|
|
711
|
+
const data = ctx.body as { name: string; email: string };
|
|
712
|
+
|
|
713
|
+
// FormData body — available as ctx.formData
|
|
714
|
+
const file = ctx.formData?.get("file") as File | null;
|
|
715
|
+
const name = ctx.formData?.get("name") as string | null;
|
|
716
|
+
|
|
717
|
+
// Route params are always available
|
|
718
|
+
const { slug } = ctx.params;
|
|
719
|
+
|
|
720
|
+
return { success: true };
|
|
721
|
+
}, true);
|
|
351
722
|
```
|
|
352
723
|
|
|
353
|
-
###
|
|
724
|
+
### File Upload Example
|
|
354
725
|
|
|
355
726
|
```typescript
|
|
356
|
-
|
|
357
|
-
|
|
727
|
+
// loaders/upload.ts
|
|
728
|
+
import { createLoader } from "@rangojs/router";
|
|
729
|
+
|
|
730
|
+
export const FileUploadLoader = createLoader(async (ctx) => {
|
|
731
|
+
"use server";
|
|
358
732
|
|
|
359
|
-
|
|
360
|
-
|
|
733
|
+
const file = ctx.formData?.get("file") as File | null;
|
|
734
|
+
if (file && file.size > 0) {
|
|
735
|
+
// Save to R2, D1, etc.
|
|
736
|
+
await ctx.env.BUCKET.put(file.name, file.stream());
|
|
737
|
+
return { uploaded: { name: file.name, size: file.size, type: file.type } };
|
|
361
738
|
}
|
|
739
|
+
return { uploaded: null };
|
|
740
|
+
}, true);
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
Client usage — see `/hooks useFetchLoader` for the full client-side pattern.
|
|
744
|
+
|
|
745
|
+
> **Refetch sharing**: when the loader is registered on the route via
|
|
746
|
+
> `loader()`, a plain `load()` call (no `params`, no `body`) broadcasts
|
|
747
|
+
> the new value to every component reading the same loader id —
|
|
748
|
+
> `useLoader` reads in layouts, pages, and parallel slots all converge.
|
|
749
|
+
> Calls with `params` or a non-GET method stay local to the call site.
|
|
750
|
+
> See `/hooks` → "Shared refetch behavior" for the full contract.
|
|
751
|
+
|
|
752
|
+
## Complete Example
|
|
753
|
+
|
|
754
|
+
```typescript
|
|
755
|
+
// loaders/shop.ts
|
|
756
|
+
import { createLoader } from "@rangojs/router";
|
|
757
|
+
|
|
758
|
+
export const ProductLoader = createLoader(async (ctx) => {
|
|
759
|
+
"use server";
|
|
362
760
|
|
|
363
|
-
|
|
761
|
+
const product = await ctx.env.DB
|
|
762
|
+
.prepare("SELECT * FROM products WHERE slug = ?")
|
|
763
|
+
.bind(ctx.params.slug)
|
|
764
|
+
.first();
|
|
765
|
+
|
|
766
|
+
if (!product) {
|
|
767
|
+
notFound("Product not found");
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
return { product };
|
|
364
771
|
});
|
|
772
|
+
|
|
773
|
+
export const CartLoader = createLoader(async (ctx) => {
|
|
774
|
+
"use server";
|
|
775
|
+
|
|
776
|
+
const user = ctx.get("user");
|
|
777
|
+
if (!user) return { cart: null };
|
|
778
|
+
|
|
779
|
+
const cart = await ctx.env.KV.get(`cart:${user.id}`, "json");
|
|
780
|
+
return { cart };
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
// urls.tsx — register loaders in the DSL
|
|
784
|
+
export const urlpatterns = urls(({ path, layout, loader, loading, cache, revalidate }) => [
|
|
785
|
+
layout(<ShopLayout />, () => [
|
|
786
|
+
loader(CartLoader, () => [
|
|
787
|
+
revalidate(({ actionId }) => actionId?.includes("Cart") || undefined),
|
|
788
|
+
]),
|
|
789
|
+
|
|
790
|
+
path("/shop/product/:slug", ProductPage, { name: "product" }, () => [
|
|
791
|
+
loader(ProductLoader, () => [cache({ ttl: 60 })]),
|
|
792
|
+
loading(<ProductSkeleton />),
|
|
793
|
+
]),
|
|
794
|
+
]),
|
|
795
|
+
]);
|
|
796
|
+
|
|
797
|
+
// components/ProductDetails.tsx — consume in client component
|
|
798
|
+
"use client";
|
|
799
|
+
import { useLoader } from "@rangojs/router/client";
|
|
800
|
+
import { ProductLoader, CartLoader } from "./loaders/shop";
|
|
801
|
+
|
|
802
|
+
function ProductDetails() {
|
|
803
|
+
const { data: { product } } = useLoader(ProductLoader);
|
|
804
|
+
const { data: { cart } } = useLoader(CartLoader);
|
|
805
|
+
|
|
806
|
+
return (
|
|
807
|
+
<div>
|
|
808
|
+
<h1>{product.name}</h1>
|
|
809
|
+
<AddToCartButton
|
|
810
|
+
productId={product.id}
|
|
811
|
+
inCart={cart?.items.includes(product.id)}
|
|
812
|
+
/>
|
|
813
|
+
</div>
|
|
814
|
+
);
|
|
815
|
+
}
|
|
365
816
|
```
|