@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/src/use-loader.tsx
CHANGED
|
@@ -1,9 +1,117 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
isValidElement,
|
|
5
|
+
startTransition,
|
|
6
|
+
useCallback,
|
|
7
|
+
useContext,
|
|
8
|
+
useEffect,
|
|
9
|
+
useMemo,
|
|
10
|
+
useRef,
|
|
11
|
+
useState,
|
|
12
|
+
type ReactNode,
|
|
13
|
+
} from "react";
|
|
4
14
|
import { OutletContext, type OutletContextValue } from "./outlet-context.js";
|
|
15
|
+
import { loaderStore, type LoaderEntry } from "./loader-store.js";
|
|
5
16
|
import type { LoaderDefinition, LoadOptions } from "./types.js";
|
|
6
17
|
|
|
18
|
+
/**
|
|
19
|
+
* A shareable GET — a `load()` call that reads data (GET or defaulted method)
|
|
20
|
+
* with no request body. Params are allowed. This is the gate for keyed sharing:
|
|
21
|
+
* when a hook is given an explicit `key`, every shareable GET writes to the
|
|
22
|
+
* keyed bucket so co-keyed readers (including parameterized views) refresh
|
|
23
|
+
* together. Non-GET methods and body-bearing calls are mutations and stay local
|
|
24
|
+
* to the call site.
|
|
25
|
+
*/
|
|
26
|
+
function isShareableGet(options: LoadOptions | undefined): boolean {
|
|
27
|
+
if (!options) return true;
|
|
28
|
+
if (options.method && options.method !== "GET") return false;
|
|
29
|
+
if ("body" in options && (options as { body?: unknown }).body !== undefined) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Plain route-context refetch — a `load()` call with no options or a
|
|
37
|
+
* trivially-defaulted GET (no params, no body). Results from these are
|
|
38
|
+
* broadcast to every component reading the same loader id via the shared
|
|
39
|
+
* store, so a layout's refetch button updates page + parallel-slot reads
|
|
40
|
+
* automatically.
|
|
41
|
+
*
|
|
42
|
+
* Calls with explicit `params`, an explicit non-GET method, or a `body`
|
|
43
|
+
* stay local to the call site — that preserves the today-semantics of
|
|
44
|
+
* `useFetchLoader(SearchLoader).load({ params: { q } })` style code where
|
|
45
|
+
* each component owns its own fetched view. (An explicit `key` opts a
|
|
46
|
+
* parameterized GET back into sharing; see `isShareableGet`.)
|
|
47
|
+
*/
|
|
48
|
+
function isPlainRefetch(options: LoadOptions | undefined): boolean {
|
|
49
|
+
if (!isShareableGet(options)) return false;
|
|
50
|
+
if (options?.params && Object.keys(options.params).length > 0) return false;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Per-hook unique suffix for grouped reads that have no explicit `key`. Such a
|
|
55
|
+
// read must NOT share the bare `loader.$$id` bucket, or a cross-loader group
|
|
56
|
+
// refresh would leak into unrelated unkeyed readers of the same loader (which
|
|
57
|
+
// the contract keeps local). Sharing within a group is opt-in via an explicit
|
|
58
|
+
// `key`; without one, each grouped read gets its own private bucket. The value
|
|
59
|
+
// is only ever used as a client-side store bucket key (never rendered), so the
|
|
60
|
+
// counter has no SSR/hydration consistency requirement.
|
|
61
|
+
let privateGroupBucketSeq = 0;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Extract a specific loader's data from a content ReactNode.
|
|
65
|
+
*
|
|
66
|
+
* When a route registers loaders via loader(), the resolved data lives in
|
|
67
|
+
* the route's OutletProvider (rendered as <Outlet /> content). Parallel
|
|
68
|
+
* slots are siblings of <Outlet />, so they can't find it by walking
|
|
69
|
+
* the parent context chain. This helper traverses wrapper elements
|
|
70
|
+
* (MountContextProvider, ViewTransition, etc.) to reach the OutletProvider
|
|
71
|
+
* and extract the loader data directly.
|
|
72
|
+
*/
|
|
73
|
+
const NOT_FOUND = Symbol("not-found");
|
|
74
|
+
|
|
75
|
+
function extractContentLoaderData(
|
|
76
|
+
node: ReactNode,
|
|
77
|
+
loaderId: string,
|
|
78
|
+
): unknown | typeof NOT_FOUND {
|
|
79
|
+
if (!isValidElement(node)) return NOT_FOUND;
|
|
80
|
+
const props = node.props as Record<string, any> | undefined;
|
|
81
|
+
if (!props) return NOT_FOUND;
|
|
82
|
+
|
|
83
|
+
// Direct OutletProvider with loaderData
|
|
84
|
+
if (props.loaderData && loaderId in props.loaderData) {
|
|
85
|
+
return props.loaderData[loaderId];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// LoaderBoundary: loaderIds + loaderDataPromise (already resolved array).
|
|
89
|
+
// When the segment has loading(), loaderData is resolved inside
|
|
90
|
+
// LoaderBoundary via use(). If the promise was pre-awaited (forceAwait
|
|
91
|
+
// or isAction), the prop is a raw array we can index into.
|
|
92
|
+
if (
|
|
93
|
+
props.loaderIds &&
|
|
94
|
+
Array.isArray(props.loaderIds) &&
|
|
95
|
+
props.loaderDataPromise &&
|
|
96
|
+
!(props.loaderDataPromise instanceof Promise)
|
|
97
|
+
) {
|
|
98
|
+
const idx = (props.loaderIds as string[]).indexOf(loaderId);
|
|
99
|
+
if (idx !== -1) {
|
|
100
|
+
const data = (props.loaderDataPromise as any[])[idx];
|
|
101
|
+
// loaderDataPromise entries may be { ok, data } result objects
|
|
102
|
+
if (data && typeof data === "object" && "ok" in data) {
|
|
103
|
+
return data.ok ? data.data : NOT_FOUND;
|
|
104
|
+
}
|
|
105
|
+
return data;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Traverse into wrapper elements (MountContextProvider, ViewTransition,
|
|
110
|
+
// Suspense wrappers, etc.)
|
|
111
|
+
if (props.children) return extractContentLoaderData(props.children, loaderId);
|
|
112
|
+
return NOT_FOUND;
|
|
113
|
+
}
|
|
114
|
+
|
|
7
115
|
/**
|
|
8
116
|
* Payload returned by loader RSC requests
|
|
9
117
|
*/
|
|
@@ -13,12 +121,9 @@ interface LoaderRscPayload<T = unknown> {
|
|
|
13
121
|
}
|
|
14
122
|
|
|
15
123
|
/**
|
|
16
|
-
* Load function type
|
|
124
|
+
* Load function type for fetching loader data from the client
|
|
17
125
|
*/
|
|
18
|
-
export type LoadFunction<T> = (
|
|
19
|
-
/** Form action for progressive enhancement - can be passed to form action prop */
|
|
20
|
-
action: (formData: FormData) => Promise<void>;
|
|
21
|
-
};
|
|
126
|
+
export type LoadFunction<T> = (options?: LoadOptions) => Promise<T>;
|
|
22
127
|
|
|
23
128
|
/**
|
|
24
129
|
* Result type for useLoader hook (strict - data is required)
|
|
@@ -62,6 +167,40 @@ export interface UseLoaderOptions {
|
|
|
62
167
|
* @default true
|
|
63
168
|
*/
|
|
64
169
|
throwOnError?: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Client refresh key. Partitions the shared refresh store so that only hooks
|
|
172
|
+
* using the same `key` refresh together when one of them calls `load()`.
|
|
173
|
+
*
|
|
174
|
+
* Without a `key` (default), a plain `load()` on a route-registered loader
|
|
175
|
+
* broadcasts to every reader of that loader, and any parameterized / unregistered
|
|
176
|
+
* load stays local to the calling hook. With a `key`:
|
|
177
|
+
* - readers of the same loader that share a `key` form one refresh group —
|
|
178
|
+
* a `load()` from any of them updates the whole group, including
|
|
179
|
+
* parameterized GETs;
|
|
180
|
+
* - readers with different keys are independent;
|
|
181
|
+
* - it works even when the loader is NOT registered on the route (keyed
|
|
182
|
+
* `useFetchLoader`), letting unrelated components opt into sharing.
|
|
183
|
+
*
|
|
184
|
+
* This is a client-side refresh identity only. It is unrelated to the server
|
|
185
|
+
* `cache({ key })` option and to `revalidate()`; it never changes the request
|
|
186
|
+
* sent to the server.
|
|
187
|
+
*/
|
|
188
|
+
key?: string;
|
|
189
|
+
/**
|
|
190
|
+
* Cross-loader refresh group tag(s). Tag reads of DIFFERENT loaders with a
|
|
191
|
+
* shared name, then call `useRefreshLoaders()(name)` to refresh the whole group
|
|
192
|
+
* at once. Pass an array to tag one read into several groups — it is refreshed
|
|
193
|
+
* when ANY of its groups is refreshed, so a coarse tag can cover the whole set
|
|
194
|
+
* while a finer tag targets a subset. Each member is refreshed with a plain GET
|
|
195
|
+
* against the current route URL — no params, no body, no mutation methods —
|
|
196
|
+
* because a group spans heterogeneous loaders with different param/return
|
|
197
|
+
* shapes.
|
|
198
|
+
*
|
|
199
|
+
* For parameterized sharing of a SINGLE loader, use `key` instead; group
|
|
200
|
+
* members should be registered or non-parameterized-keyed reads (a plain-GET
|
|
201
|
+
* group refresh would drop any per-call params).
|
|
202
|
+
*/
|
|
203
|
+
refreshGroup?: string | string[];
|
|
65
204
|
}
|
|
66
205
|
|
|
67
206
|
/**
|
|
@@ -69,61 +208,288 @@ export interface UseLoaderOptions {
|
|
|
69
208
|
*/
|
|
70
209
|
function useLoaderInternal<T>(
|
|
71
210
|
loader: LoaderDefinition<T>,
|
|
72
|
-
options?: UseLoaderOptions
|
|
211
|
+
options?: UseLoaderOptions,
|
|
73
212
|
): UseFetchLoaderResult<T> {
|
|
74
213
|
const context = useContext(OutletContext);
|
|
75
214
|
|
|
76
|
-
// Get data from context (SSR/navigation)
|
|
77
|
-
|
|
215
|
+
// Get data from context (SSR/navigation). `hasContextData` distinguishes
|
|
216
|
+
// "loader registered on the route, value happens to be undefined" from
|
|
217
|
+
// "loader is not in any parent's context at all". The shared store is
|
|
218
|
+
// only consulted when the loader really is in route context — that
|
|
219
|
+
// preserves per-component isolation for ad-hoc useFetchLoader callers
|
|
220
|
+
// who use the same fetchable loader without registering it.
|
|
221
|
+
const { contextData, hasContextData } = useMemo((): {
|
|
222
|
+
contextData: T | undefined;
|
|
223
|
+
hasContextData: boolean;
|
|
224
|
+
} => {
|
|
78
225
|
let current: OutletContextValue | null | undefined = context;
|
|
79
226
|
while (current) {
|
|
80
227
|
if (current.loaderData && loader.$$id in current.loaderData) {
|
|
81
|
-
return
|
|
228
|
+
return {
|
|
229
|
+
contextData: current.loaderData[loader.$$id] as T,
|
|
230
|
+
hasContextData: true,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
// Check content element — the route's OutletProvider is rendered as
|
|
234
|
+
// <Outlet /> content (a child), so its loaderData isn't in the parent
|
|
235
|
+
// chain. Parallel slots need to reach into it to find route-level loaders.
|
|
236
|
+
const contentData = extractContentLoaderData(
|
|
237
|
+
current.content,
|
|
238
|
+
loader.$$id,
|
|
239
|
+
);
|
|
240
|
+
if (contentData !== NOT_FOUND) {
|
|
241
|
+
return { contextData: contentData as T, hasContextData: true };
|
|
82
242
|
}
|
|
83
243
|
current = current.parent;
|
|
84
244
|
}
|
|
85
|
-
return undefined;
|
|
245
|
+
return { contextData: undefined, hasContextData: false };
|
|
86
246
|
}, [context, loader.$$id]);
|
|
87
247
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
248
|
+
// Shared subscription: every component reading the same loader id sees
|
|
249
|
+
// the same snapshot, so a plain refetch from one component propagates to
|
|
250
|
+
// the others. Mirrors the convention used by useParams / useLinkStatus —
|
|
251
|
+
// useState seeded from the store, useEffect subscribes for updates and
|
|
252
|
+
// calls setState inside startTransition so subscriber re-renders don't
|
|
253
|
+
// trip Suspense fallbacks during a refetch (matches the per-hook
|
|
254
|
+
// startTransition the old code wrapped setFetchedData in).
|
|
255
|
+
const loaderId = loader.$$id;
|
|
256
|
+
// Client refresh key. The shared store is partitioned by bucket key so that
|
|
257
|
+
// only hooks with the same `key` refresh together. Default (no key) keeps the
|
|
258
|
+
// historical behavior: one bucket per loader id.
|
|
259
|
+
const key = options?.key;
|
|
260
|
+
// Normalize the refresh-group tag(s) to a stable, deduped, sorted list. The
|
|
261
|
+
// joined `groupKey` string is the subscribe effect's dependency, so passing an
|
|
262
|
+
// inline array literal (`refreshGroup={["a", "b"]}`) does not force a
|
|
263
|
+
// resubscribe on every render. An empty list means "no groups" — identical to
|
|
264
|
+
// omitting the option (`hasGroups` stays false, no private bucket is created).
|
|
265
|
+
const refreshGroupOption = options?.refreshGroup;
|
|
266
|
+
const groupKey =
|
|
267
|
+
refreshGroupOption === undefined
|
|
268
|
+
? ""
|
|
269
|
+
: JSON.stringify(
|
|
270
|
+
typeof refreshGroupOption === "string"
|
|
271
|
+
? [refreshGroupOption]
|
|
272
|
+
: [...new Set(refreshGroupOption)].sort(),
|
|
273
|
+
);
|
|
274
|
+
const groupList = useMemo<string[]>(
|
|
275
|
+
() => (groupKey === "" ? [] : (JSON.parse(groupKey) as string[])),
|
|
276
|
+
[groupKey],
|
|
277
|
+
);
|
|
278
|
+
const hasGroups = groupList.length > 0;
|
|
279
|
+
// A grouped reader with no explicit key gets a private per-hook bucket so a
|
|
280
|
+
// cross-loader group refresh cannot leak into the bare `loader.$$id` bucket
|
|
281
|
+
// shared by unrelated unkeyed readers. Sharing within a group is opt-in via
|
|
282
|
+
// an explicit `key`.
|
|
283
|
+
const privateBucketIdRef = useRef<string | null>(null);
|
|
284
|
+
if (hasGroups && key === undefined && privateBucketIdRef.current === null) {
|
|
285
|
+
privateBucketIdRef.current = `__rg${privateGroupBucketSeq++}`;
|
|
286
|
+
}
|
|
287
|
+
const effectiveKey =
|
|
288
|
+
key ?? (hasGroups ? privateBucketIdRef.current! : undefined);
|
|
289
|
+
const bucketKey =
|
|
290
|
+
effectiveKey === undefined ? loaderId : `${loaderId}::${effectiveKey}`;
|
|
291
|
+
|
|
292
|
+
// Plain-GET refresh thunk registered with the store for cross-loader group
|
|
293
|
+
// refresh (useRefreshLoaders). Always shares into this hook's bucket, never
|
|
294
|
+
// touches lastSharedRequestIdRef (so a group refresh never render-throws —
|
|
295
|
+
// errors surface via `error` and reject the refreshGroups() promise instead),
|
|
296
|
+
// and sends no params/body. Stable across navigations (depends only on
|
|
297
|
+
// loaderId + bucketKey), so the store keeps one current thunk per bucket.
|
|
298
|
+
const groupRefetch = useCallback(async (): Promise<void> => {
|
|
299
|
+
if (!loaderId) return;
|
|
300
|
+
const requestId = loaderStore.reserveRequestId(bucketKey);
|
|
301
|
+
loaderStore.beginRequest(bucketKey, requestId);
|
|
302
|
+
try {
|
|
303
|
+
const url = new URL(window.location.href);
|
|
304
|
+
url.searchParams.set("_rsc_loader", loaderId);
|
|
305
|
+
const response = fetch(url.toString(), {
|
|
306
|
+
method: "GET",
|
|
307
|
+
headers: { Accept: "text/x-component" },
|
|
308
|
+
});
|
|
309
|
+
const { createFromFetch } = await import("./deps/browser.js");
|
|
310
|
+
const payload = await createFromFetch<LoaderRscPayload<T>>(response);
|
|
311
|
+
if (payload.loaderError) {
|
|
312
|
+
throw new Error(payload.loaderError.message);
|
|
313
|
+
}
|
|
314
|
+
loaderStore.finishData(bucketKey, requestId, payload.loaderResult);
|
|
315
|
+
} catch (e) {
|
|
316
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
317
|
+
loaderStore.finishError(bucketKey, requestId, err);
|
|
318
|
+
throw err;
|
|
319
|
+
} finally {
|
|
320
|
+
loaderStore.setLoading(bucketKey, requestId, false);
|
|
321
|
+
}
|
|
322
|
+
}, [loaderId, bucketKey]);
|
|
323
|
+
|
|
324
|
+
const [sharedState, setSharedState] = useState<{
|
|
325
|
+
bucketKey: string;
|
|
326
|
+
snapshot: LoaderEntry;
|
|
327
|
+
}>(() => ({
|
|
328
|
+
bucketKey,
|
|
329
|
+
snapshot: loaderStore.getSnapshot(bucketKey),
|
|
330
|
+
}));
|
|
331
|
+
const sharedSnapshot =
|
|
332
|
+
sharedState.bucketKey === bucketKey
|
|
333
|
+
? sharedState.snapshot
|
|
334
|
+
: loaderStore.getSnapshot(bucketKey);
|
|
335
|
+
useEffect(() => {
|
|
336
|
+
// Sync any value the store committed between this hook's lazy
|
|
337
|
+
// initializer and effect-time (e.g. a sibling that mounted earlier
|
|
338
|
+
// already triggered a load()).
|
|
339
|
+
const initial = loaderStore.getSnapshot(bucketKey);
|
|
340
|
+
if (initial !== sharedSnapshot) {
|
|
341
|
+
startTransition(() => {
|
|
342
|
+
setSharedState({ bucketKey, snapshot: initial });
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
// ephemeral: a reader with no route context has no route-context reset
|
|
346
|
+
// trigger, so its keyed bucket is reference-counted by the store. A
|
|
347
|
+
// route-registered reader makes the bucket sticky (reset via clearFamily).
|
|
348
|
+
return loaderStore.subscribe(
|
|
349
|
+
bucketKey,
|
|
350
|
+
() => {
|
|
351
|
+
const next = loaderStore.getSnapshot(bucketKey);
|
|
352
|
+
startTransition(() => {
|
|
353
|
+
setSharedState({ bucketKey, snapshot: next });
|
|
354
|
+
});
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
loaderId,
|
|
358
|
+
ephemeral: !hasContextData,
|
|
359
|
+
group: hasGroups ? groupList : undefined,
|
|
360
|
+
refetch: hasGroups ? groupRefetch : undefined,
|
|
361
|
+
},
|
|
362
|
+
);
|
|
363
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- intentional:
|
|
364
|
+
// sharedSnapshot is captured for the one-shot init sync; we don't want
|
|
365
|
+
// to re-subscribe on every snapshot change. bucketKey, hasContextData,
|
|
366
|
+
// groupKey, and groupRefetch are the only inputs that require a fresh
|
|
367
|
+
// subscription (groupList is memoized on groupKey; groupRefetch is stable
|
|
368
|
+
// per bucketKey).
|
|
369
|
+
}, [bucketKey, hasContextData, groupKey, groupRefetch]);
|
|
370
|
+
|
|
371
|
+
// Local state holds the result of:
|
|
372
|
+
// - parameterized / mutation `load()` calls (load({ params }), POST,
|
|
373
|
+
// etc.) — stay scoped so concurrent same-loader different-params
|
|
374
|
+
// fetches don't clobber each other through the shared store;
|
|
375
|
+
// - any `load()` made by hooks that are NOT in route context (i.e.
|
|
376
|
+
// useFetchLoader of an unregistered loader) — keeping those local
|
|
377
|
+
// prevents two unrelated components from accidentally sharing data
|
|
378
|
+
// through the global store just because they reference the same
|
|
379
|
+
// loader id.
|
|
380
|
+
// `has` distinguishes a committed local result (including `null`/`undefined`)
|
|
381
|
+
// from "no local load yet", so a load() that resolves to a falsy value is not
|
|
382
|
+
// discarded in favor of the shared snapshot or the seeded context.
|
|
383
|
+
const [localFetchedData, setLocalFetchedData] = useState<{
|
|
384
|
+
has: boolean;
|
|
385
|
+
value: T | undefined;
|
|
386
|
+
}>({ has: false, value: undefined });
|
|
387
|
+
const [localIsLoading, setLocalIsLoading] = useState(false);
|
|
388
|
+
const [localError, setLocalError] = useState<Error | null>(null);
|
|
389
|
+
|
|
390
|
+
// Local request id, mirrors the per-hook gating the previous
|
|
391
|
+
// implementation provided. Two quick parameterized loads from the same
|
|
392
|
+
// hook (e.g. load({ params: { q: "a" } }) then load({ params: { q: "b" } }))
|
|
393
|
+
// can resolve out of order — only the latest must commit.
|
|
394
|
+
const localRequestIdRef = useRef(0);
|
|
395
|
+
|
|
396
|
+
// Tracks the request id of the most recent SHARED load() this hook
|
|
397
|
+
// initiated. The render-throw rule below uses it to scope the throw
|
|
398
|
+
// to the originating hook only — sibling readers see the error in
|
|
399
|
+
// `error` but don't blow up their own boundaries.
|
|
400
|
+
const lastSharedRequestIdRef = useRef<number | null>(null);
|
|
401
|
+
|
|
402
|
+
// Reset on navigation. clear() bumps the entry's latest request id so
|
|
403
|
+
// any pre-navigation load() promise that resolves later fails its gate
|
|
404
|
+
// and is dropped — fixes the race where a stale fetch overwrites the
|
|
405
|
+
// new route's context.
|
|
96
406
|
const prevContextDataRef = useRef(contextData);
|
|
97
407
|
useEffect(() => {
|
|
98
408
|
if (prevContextDataRef.current !== contextData) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
409
|
+
setLocalFetchedData({ has: false, value: undefined });
|
|
410
|
+
setLocalIsLoading(false);
|
|
411
|
+
setLocalError(null);
|
|
412
|
+
lastSharedRequestIdRef.current = null;
|
|
413
|
+
// Reset every sticky bucket of this loader (keyed or not). Ephemeral
|
|
414
|
+
// (unregistered keyed) buckets are left to their refcount lifecycle.
|
|
415
|
+
loaderStore.clearFamily(loaderId);
|
|
102
416
|
prevContextDataRef.current = contextData;
|
|
103
417
|
}
|
|
104
|
-
}, [contextData]);
|
|
105
|
-
|
|
106
|
-
//
|
|
107
|
-
|
|
418
|
+
}, [contextData, loaderId]);
|
|
419
|
+
|
|
420
|
+
// Read priority: a committed parameterized load() result overrides the shared
|
|
421
|
+
// snapshot; a committed shared snapshot overrides the server-seeded context.
|
|
422
|
+
// `has`/`hasValue` gate each level so a committed falsy value is not skipped.
|
|
423
|
+
const data = localFetchedData.has
|
|
424
|
+
? localFetchedData.value
|
|
425
|
+
: sharedSnapshot.hasValue
|
|
426
|
+
? (sharedSnapshot.value as T | undefined)
|
|
427
|
+
: contextData;
|
|
428
|
+
const isLoading = localIsLoading || sharedSnapshot.isLoading;
|
|
429
|
+
const error = localError ?? sharedSnapshot.error;
|
|
108
430
|
|
|
109
431
|
const throwOnError = options?.throwOnError ?? true;
|
|
110
432
|
|
|
111
|
-
//
|
|
433
|
+
// Refs for values used inside load() that should NOT cause callback identity
|
|
434
|
+
// churn. loader.$$id can change if a reusable component receives a different
|
|
435
|
+
// loader without remounting; data changes on every navigation. Refs keep the
|
|
436
|
+
// callback stable while always reading the latest values.
|
|
437
|
+
const loaderIdRef = useRef(loaderId);
|
|
438
|
+
loaderIdRef.current = loaderId;
|
|
439
|
+
const bucketKeyRef = useRef(bucketKey);
|
|
440
|
+
bucketKeyRef.current = bucketKey;
|
|
441
|
+
const dataRef = useRef(data);
|
|
442
|
+
dataRef.current = data;
|
|
443
|
+
const hasContextDataRef = useRef(hasContextData);
|
|
444
|
+
hasContextDataRef.current = hasContextData;
|
|
445
|
+
|
|
446
|
+
// Load function for fetching data via the ?_rsc_loader endpoint.
|
|
447
|
+
// Supports GET (data fetching) and POST/PUT/PATCH/DELETE (mutations).
|
|
112
448
|
const load = useCallback(
|
|
113
449
|
async (loadOptions?: LoadOptions): Promise<T> => {
|
|
114
|
-
|
|
115
|
-
if (!
|
|
450
|
+
const id = loaderIdRef.current;
|
|
451
|
+
if (!id) {
|
|
116
452
|
throw new Error(
|
|
117
|
-
`Loader is missing $$id. Make sure the exposeLoaderId Vite plugin is enabled
|
|
453
|
+
`Loader is missing $$id. Make sure the exposeLoaderId Vite plugin is enabled.`,
|
|
118
454
|
);
|
|
119
455
|
}
|
|
120
456
|
|
|
121
|
-
|
|
122
|
-
|
|
457
|
+
const bucket = bucketKeyRef.current;
|
|
458
|
+
// A dedicated bucket means this read owns a bucket distinct from the bare
|
|
459
|
+
// loader id — either an explicit `key` (`$$id::key`) or a refreshGroup's
|
|
460
|
+
// private bucket (`$$id::<private>`).
|
|
461
|
+
const hasDedicatedBucket = bucket !== id;
|
|
462
|
+
|
|
463
|
+
// Deciding shared vs local:
|
|
464
|
+
// - With a dedicated bucket, every shareable GET (params allowed) writes
|
|
465
|
+
// to that bucket — the key/group is an explicit opt-in to sharing, and
|
|
466
|
+
// a direct load() must land in the same bucket a group refresh uses.
|
|
467
|
+
// - On the bare loader-id bucket, sharing is only correct when the
|
|
468
|
+
// loader is registered on the route and the call is a plain refetch —
|
|
469
|
+
// otherwise two unrelated components calling load() on the same
|
|
470
|
+
// fetchable loader would overwrite each other's local view.
|
|
471
|
+
// Mutations (non-GET / body) stay local in both cases.
|
|
472
|
+
const shared = hasDedicatedBucket
|
|
473
|
+
? isShareableGet(loadOptions)
|
|
474
|
+
: isPlainRefetch(loadOptions) && hasContextDataRef.current;
|
|
475
|
+
let sharedRequestId = -1;
|
|
476
|
+
let localRequestId = -1;
|
|
477
|
+
if (shared) {
|
|
478
|
+
sharedRequestId = loaderStore.reserveRequestId(bucket);
|
|
479
|
+
lastSharedRequestIdRef.current = sharedRequestId;
|
|
480
|
+
// beginRequest flips loading on AND clears any prior error so a
|
|
481
|
+
// throwOnError: false consumer doesn't keep showing the stale
|
|
482
|
+
// error during the retry. Gated on requestId === latest.
|
|
483
|
+
loaderStore.beginRequest(bucket, sharedRequestId);
|
|
484
|
+
} else {
|
|
485
|
+
localRequestId = ++localRequestIdRef.current;
|
|
486
|
+
setLocalIsLoading(true);
|
|
487
|
+
setLocalError(null);
|
|
488
|
+
}
|
|
123
489
|
|
|
124
490
|
try {
|
|
125
|
-
const url = new URL(window.location.
|
|
126
|
-
url.searchParams.set("_rsc_loader",
|
|
491
|
+
const url = new URL(window.location.href);
|
|
492
|
+
url.searchParams.set("_rsc_loader", id);
|
|
127
493
|
|
|
128
494
|
const method = loadOptions?.method ?? "GET";
|
|
129
495
|
const isBodyMethod = method !== "GET";
|
|
@@ -131,29 +497,58 @@ function useLoaderInternal<T>(
|
|
|
131
497
|
let fetchOptions: RequestInit;
|
|
132
498
|
|
|
133
499
|
if (isBodyMethod) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
500
|
+
const bodyValue =
|
|
501
|
+
"body" in (loadOptions ?? {})
|
|
502
|
+
? (loadOptions as any).body
|
|
503
|
+
: undefined;
|
|
504
|
+
const hasParams =
|
|
505
|
+
loadOptions?.params && Object.keys(loadOptions.params).length > 0;
|
|
506
|
+
|
|
507
|
+
if (bodyValue instanceof FormData) {
|
|
508
|
+
// FormData body — send as multipart/form-data (preserves File objects).
|
|
509
|
+
// Params are appended as a JSON string in a special field.
|
|
510
|
+
if (hasParams) {
|
|
511
|
+
bodyValue.set(
|
|
512
|
+
"_rsc_loader_params",
|
|
513
|
+
JSON.stringify(loadOptions!.params),
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
fetchOptions = {
|
|
517
|
+
method,
|
|
518
|
+
headers: { Accept: "text/x-component" },
|
|
519
|
+
body: bodyValue,
|
|
520
|
+
};
|
|
521
|
+
} else {
|
|
522
|
+
// JSON body — send params and body as JSON
|
|
523
|
+
const bodyPayload: {
|
|
524
|
+
params?: Record<string, string>;
|
|
525
|
+
body?: unknown;
|
|
526
|
+
} = {};
|
|
527
|
+
if (hasParams) {
|
|
528
|
+
bodyPayload.params = loadOptions!.params;
|
|
529
|
+
}
|
|
530
|
+
if (bodyValue !== undefined) {
|
|
531
|
+
bodyPayload.body = bodyValue;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
fetchOptions = {
|
|
535
|
+
method,
|
|
536
|
+
headers: {
|
|
537
|
+
Accept: "text/x-component",
|
|
538
|
+
"Content-Type": "application/json",
|
|
539
|
+
},
|
|
540
|
+
body: JSON.stringify(bodyPayload),
|
|
541
|
+
};
|
|
141
542
|
}
|
|
142
|
-
|
|
143
|
-
fetchOptions = {
|
|
144
|
-
method,
|
|
145
|
-
headers: {
|
|
146
|
-
Accept: "text/x-component",
|
|
147
|
-
"Content-Type": "application/json",
|
|
148
|
-
},
|
|
149
|
-
body: JSON.stringify(bodyPayload),
|
|
150
|
-
};
|
|
151
543
|
} else {
|
|
152
544
|
// GET - send params in query string
|
|
153
|
-
if (
|
|
545
|
+
if (
|
|
546
|
+
loadOptions?.params &&
|
|
547
|
+
Object.keys(loadOptions.params).length > 0
|
|
548
|
+
) {
|
|
154
549
|
url.searchParams.set(
|
|
155
550
|
"_rsc_loader_params",
|
|
156
|
-
JSON.stringify(loadOptions.params)
|
|
551
|
+
JSON.stringify(loadOptions.params),
|
|
157
552
|
);
|
|
158
553
|
}
|
|
159
554
|
|
|
@@ -175,73 +570,67 @@ function useLoaderInternal<T>(
|
|
|
175
570
|
}
|
|
176
571
|
|
|
177
572
|
const result = payload.loaderResult;
|
|
178
|
-
|
|
573
|
+
if (shared) {
|
|
574
|
+
// finishData is gated on requestId; a stale response is dropped.
|
|
575
|
+
loaderStore.finishData(bucket, sharedRequestId, result);
|
|
576
|
+
} else if (localRequestId === localRequestIdRef.current) {
|
|
577
|
+
// Local-branch gate, mirrors the shared-branch requestId check:
|
|
578
|
+
// if a newer load() was issued from this hook before this one
|
|
579
|
+
// resolved, drop the stale result.
|
|
580
|
+
startTransition(() => {
|
|
581
|
+
setLocalFetchedData({ has: true, value: result });
|
|
582
|
+
setLocalIsLoading(false);
|
|
583
|
+
});
|
|
584
|
+
}
|
|
179
585
|
return result;
|
|
180
586
|
} catch (e) {
|
|
181
587
|
const err = e instanceof Error ? e : new Error(String(e));
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
588
|
+
if (shared) {
|
|
589
|
+
loaderStore.finishError(bucket, sharedRequestId, err);
|
|
590
|
+
} else if (localRequestId === localRequestIdRef.current) {
|
|
591
|
+
setLocalError(err);
|
|
592
|
+
setLocalIsLoading(false);
|
|
185
593
|
}
|
|
186
|
-
// When throwOnError is false, return the current data (previous successful
|
|
187
|
-
// value or undefined). Caller should check error state for error handling.
|
|
188
|
-
return data as T;
|
|
189
|
-
} finally {
|
|
190
|
-
setIsLoading(false);
|
|
191
|
-
}
|
|
192
|
-
},
|
|
193
|
-
[throwOnError]
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
// Form action for progressive enhancement
|
|
197
|
-
// This wrapper is for useFetchLoader's load.action - it manages state internally
|
|
198
|
-
// and doesn't use React's useActionState. For true PE, use loader.action directly
|
|
199
|
-
// with useActionState.
|
|
200
|
-
const action = useCallback(
|
|
201
|
-
async (formData: FormData): Promise<void> => {
|
|
202
|
-
if (!loader.action) {
|
|
203
|
-
throw new Error(
|
|
204
|
-
`Loader "${loader.$$id}" does not have an action. ` +
|
|
205
|
-
`Make sure the loader is created with fetchable: true.`
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
setIsLoading(true);
|
|
210
|
-
setError(null);
|
|
211
|
-
|
|
212
|
-
try {
|
|
213
|
-
// Pass null as prevState - this wrapper manages state internally
|
|
214
|
-
const result = await loader.action(null, formData);
|
|
215
|
-
setFetchedData(result);
|
|
216
|
-
} catch (e) {
|
|
217
|
-
const err = e instanceof Error ? e : new Error(String(e));
|
|
218
|
-
setError(err);
|
|
219
594
|
if (throwOnError) {
|
|
220
595
|
throw err;
|
|
221
596
|
}
|
|
597
|
+
// When throwOnError is false, return the latest data snapshot (previous
|
|
598
|
+
// successful value or undefined). Caller should check error state.
|
|
599
|
+
return dataRef.current as T;
|
|
222
600
|
} finally {
|
|
223
|
-
|
|
601
|
+
if (shared) {
|
|
602
|
+
// setLoading is gated; only the latest request flips the flag off.
|
|
603
|
+
loaderStore.setLoading(bucket, sharedRequestId, false);
|
|
604
|
+
}
|
|
224
605
|
}
|
|
225
606
|
},
|
|
226
|
-
[throwOnError]
|
|
607
|
+
[throwOnError],
|
|
227
608
|
);
|
|
228
609
|
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
|
|
236
|
-
|
|
610
|
+
// Throw during render if there's an error and throwOnError is true.
|
|
611
|
+
// - Local errors always belong to this hook, so always throw on opt-in.
|
|
612
|
+
// - Shared errors throw only when this hook initiated the failing
|
|
613
|
+
// request (entry.requestId matches lastSharedRequestIdRef). Sibling
|
|
614
|
+
// readers expose the error via `error` but do not throw, so a
|
|
615
|
+
// throwOnError: true reader never explodes because of someone else's
|
|
616
|
+
// throwOnError: false load() failure.
|
|
617
|
+
if (throwOnError) {
|
|
618
|
+
if (localError) throw localError;
|
|
619
|
+
if (
|
|
620
|
+
sharedSnapshot.error &&
|
|
621
|
+
lastSharedRequestIdRef.current !== null &&
|
|
622
|
+
sharedSnapshot.requestId === lastSharedRequestIdRef.current
|
|
623
|
+
) {
|
|
624
|
+
throw sharedSnapshot.error;
|
|
625
|
+
}
|
|
237
626
|
}
|
|
238
627
|
|
|
239
628
|
return {
|
|
240
629
|
data,
|
|
241
630
|
isLoading,
|
|
242
631
|
error,
|
|
243
|
-
load
|
|
244
|
-
refetch:
|
|
632
|
+
load,
|
|
633
|
+
refetch: load,
|
|
245
634
|
};
|
|
246
635
|
}
|
|
247
636
|
|
|
@@ -276,8 +665,8 @@ function useLoaderInternal<T>(
|
|
|
276
665
|
*/
|
|
277
666
|
export function useLoader<T>(
|
|
278
667
|
loader: LoaderDefinition<T>,
|
|
279
|
-
options?: UseLoaderOptions
|
|
280
|
-
): UseLoaderResult<T
|
|
668
|
+
options?: UseLoaderOptions,
|
|
669
|
+
): UseLoaderResult<Rango.FlightSerialize<T>> {
|
|
281
670
|
const result = useLoaderInternal(loader, options);
|
|
282
671
|
|
|
283
672
|
// Strict mode: throw if data is not in context
|
|
@@ -285,11 +674,11 @@ export function useLoader<T>(
|
|
|
285
674
|
throw new Error(
|
|
286
675
|
`useLoader: Loader "${loader.$$id}" data not found in context. ` +
|
|
287
676
|
`Make sure the loader is registered on the route with loader(). ` +
|
|
288
|
-
`If you need on-demand fetching, use useFetchLoader() instead
|
|
677
|
+
`If you need on-demand fetching, use useFetchLoader() instead.`,
|
|
289
678
|
);
|
|
290
679
|
}
|
|
291
680
|
|
|
292
|
-
return result as UseLoaderResult<T
|
|
681
|
+
return result as UseLoaderResult<Rango.FlightSerialize<T>>;
|
|
293
682
|
}
|
|
294
683
|
|
|
295
684
|
/**
|
|
@@ -340,7 +729,69 @@ export function useLoader<T>(
|
|
|
340
729
|
*/
|
|
341
730
|
export function useFetchLoader<T>(
|
|
342
731
|
loader: LoaderDefinition<T>,
|
|
343
|
-
options?: UseLoaderOptions
|
|
344
|
-
): UseFetchLoaderResult<T
|
|
345
|
-
return useLoaderInternal(loader, options)
|
|
732
|
+
options?: UseLoaderOptions,
|
|
733
|
+
): UseFetchLoaderResult<Rango.FlightSerialize<T>> {
|
|
734
|
+
return useLoaderInternal(loader, options) as UseFetchLoaderResult<
|
|
735
|
+
Rango.FlightSerialize<T>
|
|
736
|
+
>;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Get a stable function that refreshes loaders by cross-loader group tag.
|
|
741
|
+
*
|
|
742
|
+
* The returned `refresh(groups)` takes one group name or an array of names and
|
|
743
|
+
* re-runs every currently-mounted read tagged with ANY of them, with a plain GET
|
|
744
|
+
* against the current route URL. This is the cross-loader counterpart to the
|
|
745
|
+
* single-loader `key`: use it to refresh a set of DIFFERENT loaders together
|
|
746
|
+
* (e.g. profile + orders after an account switch). Members are tagged via
|
|
747
|
+
* `useLoader(Loader, { refreshGroup })` / `useFetchLoader(Loader, { refreshGroup })`,
|
|
748
|
+
* where `refreshGroup` is one name or several.
|
|
749
|
+
*
|
|
750
|
+
* Passing the group(s) to the returned function rather than to the hook lets a
|
|
751
|
+
* single `useRefreshLoaders()` instance refresh different groups depending on
|
|
752
|
+
* context, and lets one call refresh several groups at once — their members are
|
|
753
|
+
* unioned and deduped, so a loader tagged into two of the named groups is fetched
|
|
754
|
+
* exactly once.
|
|
755
|
+
*
|
|
756
|
+
* Group refresh never render-throws: a failing member surfaces its error via
|
|
757
|
+
* that read's `error` state, and the returned promise rejects with an
|
|
758
|
+
* `AggregateError` of the failures so the caller can handle them at the await
|
|
759
|
+
* site. Each loader is refreshed in place — no params, no body, no mutations.
|
|
760
|
+
*
|
|
761
|
+
* @example
|
|
762
|
+
* ```tsx
|
|
763
|
+
* "use client";
|
|
764
|
+
* import { useLoader, useRefreshLoaders } from "rsc-router/client";
|
|
765
|
+
*
|
|
766
|
+
* function Profile() {
|
|
767
|
+
* const { data } = useLoader(ProfileLoader, { key: userId, refreshGroup: "account" });
|
|
768
|
+
* return <span>{data.name}</span>;
|
|
769
|
+
* }
|
|
770
|
+
* function Orders() {
|
|
771
|
+
* // Tagged into two groups: refreshed by "account" (the whole set) or "orders".
|
|
772
|
+
* const { data } = useLoader(OrdersLoader, {
|
|
773
|
+
* key: userId,
|
|
774
|
+
* refreshGroup: ["account", "orders"],
|
|
775
|
+
* });
|
|
776
|
+
* return <span>{data.count} orders</span>;
|
|
777
|
+
* }
|
|
778
|
+
* function RefreshButtons() {
|
|
779
|
+
* const refresh = useRefreshLoaders();
|
|
780
|
+
* return (
|
|
781
|
+
* <>
|
|
782
|
+
* <button onClick={() => refresh("account")}>Refresh account</button>
|
|
783
|
+
* <button onClick={() => refresh("orders")}>Refresh orders</button>
|
|
784
|
+
* <button onClick={() => refresh(["account", "orders"])}>Refresh both</button>
|
|
785
|
+
* </>
|
|
786
|
+
* );
|
|
787
|
+
* }
|
|
788
|
+
* ```
|
|
789
|
+
*/
|
|
790
|
+
export function useRefreshLoaders(): (
|
|
791
|
+
groups: string | string[],
|
|
792
|
+
) => Promise<void> {
|
|
793
|
+
return useCallback(
|
|
794
|
+
(groups: string | string[]) => loaderStore.refreshGroups(groups),
|
|
795
|
+
[],
|
|
796
|
+
);
|
|
346
797
|
}
|