@nifrajs/web 5.5.1 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +243 -0
- package/README.md +21 -11
- package/dist/boundary.d.ts +67 -7
- package/dist/boundary.d.ts.map +1 -1
- package/dist/boundary.js +6 -4
- package/dist/boundary.js.map +1 -1
- package/dist/build-plan.d.ts +3 -0
- package/dist/build-plan.d.ts.map +1 -1
- package/dist/build-plan.js.map +1 -1
- package/dist/build-vite.d.ts.map +1 -1
- package/dist/build-vite.js +2 -0
- package/dist/build-vite.js.map +1 -1
- package/dist/build.d.ts +9 -2
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +10 -0
- package/dist/build.js.map +1 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +174 -23
- package/dist/client.js.map +1 -1
- package/dist/csp.d.ts +8 -0
- package/dist/csp.d.ts.map +1 -1
- package/dist/csp.js +11 -2
- package/dist/csp.js.map +1 -1
- package/dist/deferred.d.ts +6 -4
- package/dist/deferred.d.ts.map +1 -1
- package/dist/deferred.js +10 -6
- package/dist/deferred.js.map +1 -1
- package/dist/dev-feed.d.ts.map +1 -1
- package/dist/dev-feed.js +11 -2
- package/dist/dev-feed.js.map +1 -1
- package/dist/dev-session.d.ts.map +1 -1
- package/dist/dev-session.js +13 -6
- package/dist/dev-session.js.map +1 -1
- package/dist/dev.d.ts +4 -1
- package/dist/dev.d.ts.map +1 -1
- package/dist/dev.js +12 -5
- package/dist/dev.js.map +1 -1
- package/dist/diagnostic-catalog.d.ts +4 -0
- package/dist/diagnostic-catalog.d.ts.map +1 -1
- package/dist/diagnostic-catalog.js +48 -0
- package/dist/diagnostic-catalog.js.map +1 -1
- package/dist/diagnostic.d.ts +1 -1
- package/dist/diagnostic.d.ts.map +1 -1
- package/dist/diagnostic.js +1 -1
- package/dist/diagnostic.js.map +1 -1
- package/dist/fn.d.ts +5 -3
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +20 -5
- package/dist/fn.js.map +1 -1
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +13 -3
- package/dist/fs.js.map +1 -1
- package/dist/identity.d.ts +22 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +60 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/internal/cdn/cloudflare.d.ts +2 -1
- package/dist/internal/cdn/cloudflare.d.ts.map +1 -1
- package/dist/internal/cdn/cloudflare.js +2 -1
- package/dist/internal/cdn/cloudflare.js.map +1 -1
- package/dist/internal/certified-components.d.ts +1 -1
- package/dist/internal/certified-components.js +1 -1
- package/dist/internal/codegen.d.ts +11 -10
- package/dist/internal/codegen.d.ts.map +1 -1
- package/dist/internal/codegen.js +73 -10
- package/dist/internal/codegen.js.map +1 -1
- package/dist/internal/dev-websocket.d.ts +73 -0
- package/dist/internal/dev-websocket.d.ts.map +1 -0
- package/dist/internal/dev-websocket.js +145 -0
- package/dist/internal/dev-websocket.js.map +1 -0
- package/dist/internal/hole-runtime.d.ts +66 -0
- package/dist/internal/hole-runtime.d.ts.map +1 -0
- package/dist/internal/hole-runtime.js +211 -0
- package/dist/internal/hole-runtime.js.map +1 -0
- package/dist/internal/identity-epoch.d.ts +50 -0
- package/dist/internal/identity-epoch.d.ts.map +1 -0
- package/dist/internal/identity-epoch.js +180 -0
- package/dist/internal/identity-epoch.js.map +1 -0
- package/dist/internal/invalidation-contract.d.ts +23 -0
- package/dist/internal/invalidation-contract.d.ts.map +1 -0
- package/dist/internal/invalidation-contract.js +11 -0
- package/dist/internal/invalidation-contract.js.map +1 -0
- package/dist/internal/invalidation.d.ts +62 -0
- package/dist/internal/invalidation.d.ts.map +1 -0
- package/dist/internal/invalidation.js +149 -0
- package/dist/internal/invalidation.js.map +1 -0
- package/dist/internal/island-bindings.d.ts +51 -0
- package/dist/internal/island-bindings.d.ts.map +1 -0
- package/dist/internal/island-bindings.js +147 -0
- package/dist/internal/island-bindings.js.map +1 -0
- package/dist/internal/island-list.d.ts +26 -0
- package/dist/internal/island-list.d.ts.map +1 -0
- package/dist/internal/island-list.js +78 -0
- package/dist/internal/island-list.js.map +1 -0
- package/dist/internal/island-mount.d.ts +4 -0
- package/dist/internal/island-mount.d.ts.map +1 -0
- package/dist/internal/island-mount.js +66 -0
- package/dist/internal/island-mount.js.map +1 -0
- package/dist/internal/island-owner.d.ts +5 -0
- package/dist/internal/island-owner.d.ts.map +1 -0
- package/dist/internal/island-owner.js +20 -0
- package/dist/internal/island-owner.js.map +1 -0
- package/dist/internal/island-resource.d.ts +30 -0
- package/dist/internal/island-resource.d.ts.map +1 -0
- package/dist/internal/island-resource.js +57 -0
- package/dist/internal/island-resource.js.map +1 -0
- package/dist/internal/island-signals.d.ts +51 -0
- package/dist/internal/island-signals.d.ts.map +1 -0
- package/dist/internal/island-signals.js +220 -0
- package/dist/internal/island-signals.js.map +1 -0
- package/dist/internal/keep-alive-table.d.ts +23 -0
- package/dist/internal/keep-alive-table.d.ts.map +1 -0
- package/dist/internal/keep-alive-table.js +53 -0
- package/dist/internal/keep-alive-table.js.map +1 -0
- package/dist/internal/live-contract.d.ts +101 -0
- package/dist/internal/live-contract.d.ts.map +1 -0
- package/dist/internal/live-contract.js +5 -0
- package/dist/internal/live-contract.js.map +1 -0
- package/dist/internal/live-queries.d.ts +22 -0
- package/dist/internal/live-queries.d.ts.map +1 -0
- package/dist/internal/live-queries.js +54 -0
- package/dist/internal/live-queries.js.map +1 -0
- package/dist/internal/page-events.d.ts +10 -0
- package/dist/internal/page-events.d.ts.map +1 -0
- package/dist/internal/page-events.js +26 -0
- package/dist/internal/page-events.js.map +1 -0
- package/dist/internal/page-execution.d.ts +16 -1
- package/dist/internal/page-execution.d.ts.map +1 -1
- package/dist/internal/page-execution.js +432 -31
- package/dist/internal/page-execution.js.map +1 -1
- package/dist/internal/parity.d.ts +3 -0
- package/dist/internal/parity.d.ts.map +1 -1
- package/dist/internal/parity.js +28 -5
- package/dist/internal/parity.js.map +1 -1
- package/dist/internal/ppr/admission.d.ts +83 -0
- package/dist/internal/ppr/admission.d.ts.map +1 -0
- package/dist/internal/ppr/admission.js +221 -0
- package/dist/internal/ppr/admission.js.map +1 -0
- package/dist/internal/ppr/canary.d.ts +24 -0
- package/dist/internal/ppr/canary.d.ts.map +1 -0
- package/dist/internal/ppr/canary.js +102 -0
- package/dist/internal/ppr/canary.js.map +1 -0
- package/dist/internal/ppr/compile-shell.d.ts +39 -0
- package/dist/internal/ppr/compile-shell.d.ts.map +1 -0
- package/dist/internal/ppr/compile-shell.js +298 -0
- package/dist/internal/ppr/compile-shell.js.map +1 -0
- package/dist/internal/ppr/contract.d.ts +177 -0
- package/dist/internal/ppr/contract.d.ts.map +1 -0
- package/dist/internal/ppr/contract.js +80 -0
- package/dist/internal/ppr/contract.js.map +1 -0
- package/dist/internal/ppr/frames.d.ts +71 -0
- package/dist/internal/ppr/frames.d.ts.map +1 -0
- package/dist/internal/ppr/frames.js +119 -0
- package/dist/internal/ppr/frames.js.map +1 -0
- package/dist/internal/ppr/integration.d.ts +19 -0
- package/dist/internal/ppr/integration.d.ts.map +1 -0
- package/dist/internal/ppr/integration.js +106 -0
- package/dist/internal/ppr/integration.js.map +1 -0
- package/dist/internal/ppr/options.d.ts +96 -0
- package/dist/internal/ppr/options.d.ts.map +1 -0
- package/dist/internal/ppr/options.js +125 -0
- package/dist/internal/ppr/options.js.map +1 -0
- package/dist/internal/ppr/route-rules.d.ts +12 -0
- package/dist/internal/ppr/route-rules.d.ts.map +1 -0
- package/dist/internal/ppr/route-rules.js +53 -0
- package/dist/internal/ppr/route-rules.js.map +1 -0
- package/dist/internal/ppr/runtime.d.ts +29 -0
- package/dist/internal/ppr/runtime.d.ts.map +1 -0
- package/dist/internal/ppr/runtime.js +35 -0
- package/dist/internal/ppr/runtime.js.map +1 -0
- package/dist/internal/ppr/server.d.ts +29 -0
- package/dist/internal/ppr/server.d.ts.map +1 -0
- package/dist/internal/ppr/server.js +1409 -0
- package/dist/internal/ppr/server.js.map +1 -0
- package/dist/internal/ppr/shell-store.d.ts +39 -0
- package/dist/internal/ppr/shell-store.d.ts.map +1 -0
- package/dist/internal/ppr/shell-store.js +106 -0
- package/dist/internal/ppr/shell-store.js.map +1 -0
- package/dist/internal/prerendered-pages.d.ts +1 -1
- package/dist/internal/prerendered-pages.d.ts.map +1 -1
- package/dist/internal/prerendered-pages.js +7 -4
- package/dist/internal/prerendered-pages.js.map +1 -1
- package/dist/internal/present.d.ts +11 -0
- package/dist/internal/present.d.ts.map +1 -0
- package/dist/internal/present.js +13 -0
- package/dist/internal/present.js.map +1 -0
- package/dist/internal/query-digest.d.ts +9 -0
- package/dist/internal/query-digest.d.ts.map +1 -0
- package/dist/internal/query-digest.js +23 -0
- package/dist/internal/query-digest.js.map +1 -0
- package/dist/internal/query-runtime.d.ts +6 -1
- package/dist/internal/query-runtime.d.ts.map +1 -1
- package/dist/internal/query-runtime.js +9 -0
- package/dist/internal/query-runtime.js.map +1 -1
- package/dist/internal/query-seam.d.ts +29 -0
- package/dist/internal/query-seam.d.ts.map +1 -0
- package/dist/internal/query-seam.js +23 -0
- package/dist/internal/query-seam.js.map +1 -0
- package/dist/internal/render-document.d.ts +34 -64
- package/dist/internal/render-document.d.ts.map +1 -1
- package/dist/internal/render-document.js +82 -64
- package/dist/internal/render-document.js.map +1 -1
- package/dist/internal/request-abort.d.ts +8 -0
- package/dist/internal/request-abort.d.ts.map +1 -0
- package/dist/internal/request-abort.js +22 -0
- package/dist/internal/request-abort.js.map +1 -0
- package/dist/internal/server-boundary.d.ts +2 -0
- package/dist/internal/server-boundary.d.ts.map +1 -1
- package/dist/internal/server-boundary.js +8 -1
- package/dist/internal/server-boundary.js.map +1 -1
- package/dist/internal/share-data.d.ts +10 -0
- package/dist/internal/share-data.d.ts.map +1 -0
- package/dist/internal/share-data.js +135 -0
- package/dist/internal/share-data.js.map +1 -0
- package/dist/internal/status-page.d.ts +68 -0
- package/dist/internal/status-page.d.ts.map +1 -0
- package/dist/internal/status-page.js +66 -0
- package/dist/internal/status-page.js.map +1 -0
- package/dist/internal/store-signature.d.ts +15 -0
- package/dist/internal/store-signature.d.ts.map +1 -0
- package/dist/internal/store-signature.js +114 -0
- package/dist/internal/store-signature.js.map +1 -0
- package/dist/internal/vite-plugin-compat.d.ts +2 -2
- package/dist/internal/vite-plugin-compat.js +2 -2
- package/dist/internal/web-app.d.ts +26 -0
- package/dist/internal/web-app.d.ts.map +1 -1
- package/dist/internal/web-app.js +79 -3
- package/dist/internal/web-app.js.map +1 -1
- package/dist/islands-swap.d.ts +41 -0
- package/dist/islands-swap.d.ts.map +1 -0
- package/dist/islands-swap.js +270 -0
- package/dist/islands-swap.js.map +1 -0
- package/dist/islands.d.ts +86 -24
- package/dist/islands.d.ts.map +1 -1
- package/dist/islands.js +138 -78
- package/dist/islands.js.map +1 -1
- package/dist/isr.d.ts +67 -13
- package/dist/isr.d.ts.map +1 -1
- package/dist/isr.js +247 -99
- package/dist/isr.js.map +1 -1
- package/dist/keep-alive.d.ts +147 -0
- package/dist/keep-alive.d.ts.map +1 -0
- package/dist/keep-alive.js +1102 -0
- package/dist/keep-alive.js.map +1 -0
- package/dist/live/bus.d.ts +70 -0
- package/dist/live/bus.d.ts.map +1 -0
- package/dist/live/bus.js +55 -0
- package/dist/live/bus.js.map +1 -0
- package/dist/live/core.d.ts +25 -0
- package/dist/live/core.d.ts.map +1 -0
- package/dist/live/core.js +29 -0
- package/dist/live/core.js.map +1 -0
- package/dist/live/history.d.ts +38 -0
- package/dist/live/history.d.ts.map +1 -0
- package/dist/live/history.js +104 -0
- package/dist/live/history.js.map +1 -0
- package/dist/live/hub-protocol.d.ts +46 -0
- package/dist/live/hub-protocol.d.ts.map +1 -0
- package/dist/live/hub-protocol.js +108 -0
- package/dist/live/hub-protocol.js.map +1 -0
- package/dist/live/hub.d.ts +185 -0
- package/dist/live/hub.d.ts.map +1 -0
- package/dist/live/hub.js +544 -0
- package/dist/live/hub.js.map +1 -0
- package/dist/live/keyring.d.ts +92 -0
- package/dist/live/keyring.d.ts.map +1 -0
- package/dist/live/keyring.js +265 -0
- package/dist/live/keyring.js.map +1 -0
- package/dist/live/read-capped.d.ts +6 -0
- package/dist/live/read-capped.d.ts.map +1 -0
- package/dist/live/read-capped.js +42 -0
- package/dist/live/read-capped.js.map +1 -0
- package/dist/live/revocations.d.ts +52 -0
- package/dist/live/revocations.d.ts.map +1 -0
- package/dist/live/revocations.js +116 -0
- package/dist/live/revocations.js.map +1 -0
- package/dist/live/settings.d.ts +14 -0
- package/dist/live/settings.d.ts.map +1 -0
- package/dist/live/settings.js +38 -0
- package/dist/live/settings.js.map +1 -0
- package/dist/live-client.d.ts +34 -0
- package/dist/live-client.d.ts.map +1 -0
- package/dist/live-client.js +878 -0
- package/dist/live-client.js.map +1 -0
- package/dist/live-hub.d.ts +130 -0
- package/dist/live-hub.d.ts.map +1 -0
- package/dist/live-hub.js +507 -0
- package/dist/live-hub.js.map +1 -0
- package/dist/live-redis.d.ts +60 -0
- package/dist/live-redis.d.ts.map +1 -0
- package/dist/live-redis.js +212 -0
- package/dist/live-redis.js.map +1 -0
- package/dist/live.d.ts +150 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +972 -0
- package/dist/live.js.map +1 -0
- package/dist/manifest.d.ts +113 -2
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +109 -5
- package/dist/manifest.js.map +1 -1
- package/dist/navigation.d.ts +9 -3
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +13 -3
- package/dist/navigation.js.map +1 -1
- package/dist/plugins/vite-zone-guard.d.ts +6 -0
- package/dist/plugins/vite-zone-guard.d.ts.map +1 -1
- package/dist/plugins/vite-zone-guard.js +8 -2
- package/dist/plugins/vite-zone-guard.js.map +1 -1
- package/dist/ppr.d.ts +73 -0
- package/dist/ppr.d.ts.map +1 -0
- package/dist/ppr.js +76 -0
- package/dist/ppr.js.map +1 -0
- package/dist/query.d.ts +8 -13
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +112 -18
- package/dist/query.js.map +1 -1
- package/dist/render-seam.d.ts +32 -0
- package/dist/render-seam.d.ts.map +1 -1
- package/dist/render-seam.js +7 -0
- package/dist/render-seam.js.map +1 -1
- package/dist/route-types.d.ts.map +1 -1
- package/dist/route-types.js +2 -2
- package/dist/route-types.js.map +1 -1
- package/dist/router.d.ts +72 -4
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +416 -129
- package/dist/router.js.map +1 -1
- package/dist/server-components/build.d.ts.map +1 -1
- package/dist/server-components/build.js +3 -3
- package/dist/server-components/build.js.map +1 -1
- package/dist/server-components/client.d.ts +23 -1
- package/dist/server-components/client.d.ts.map +1 -1
- package/dist/server-components/client.js +92 -5
- package/dist/server-components/client.js.map +1 -1
- package/dist/server-components/definition.d.ts.map +1 -1
- package/dist/server-components/definition.js +2 -1
- package/dist/server-components/definition.js.map +1 -1
- package/dist/server-components/hole.d.ts +8 -0
- package/dist/server-components/hole.d.ts.map +1 -0
- package/dist/server-components/hole.js +20 -0
- package/dist/server-components/hole.js.map +1 -0
- package/dist/server-components/html-policy.d.ts.map +1 -1
- package/dist/server-components/html-policy.js +62 -4
- package/dist/server-components/html-policy.js.map +1 -1
- package/dist/server-components/html-scan.d.ts +17 -0
- package/dist/server-components/html-scan.d.ts.map +1 -0
- package/dist/server-components/html-scan.js +180 -0
- package/dist/server-components/html-scan.js.map +1 -0
- package/dist/server-components/html.d.ts.map +1 -1
- package/dist/server-components/html.js +19 -4
- package/dist/server-components/html.js.map +1 -1
- package/dist/server-components/router-integration.d.ts +4 -1
- package/dist/server-components/router-integration.d.ts.map +1 -1
- package/dist/server-components/router-integration.js +23 -2
- package/dist/server-components/router-integration.js.map +1 -1
- package/dist/server-components/runtime.d.ts +6 -1
- package/dist/server-components/runtime.d.ts.map +1 -1
- package/dist/server-components/runtime.js +88 -29
- package/dist/server-components/runtime.js.map +1 -1
- package/dist/server-components/state.d.ts +3 -1
- package/dist/server-components/state.d.ts.map +1 -1
- package/dist/server-components/state.js +50 -38
- package/dist/server-components/state.js.map +1 -1
- package/dist/server-components/types.d.ts +9 -0
- package/dist/server-components/types.d.ts.map +1 -1
- package/dist/server-components/vite.d.ts.map +1 -1
- package/dist/server-components/vite.js +26 -9
- package/dist/server-components/vite.js.map +1 -1
- package/dist/vite.d.ts +5 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +58 -4
- package/dist/vite.js.map +1 -1
- package/package.json +48 -8
- package/src/boundary.ts +77 -5
- package/src/build-plan.ts +3 -0
- package/src/build-vite.ts +2 -0
- package/src/build.ts +20 -1
- package/src/client.ts +183 -23
- package/src/csp.ts +16 -2
- package/src/deferred.ts +11 -5
- package/src/dev-feed.ts +11 -2
- package/src/dev-session.ts +22 -11
- package/src/dev.ts +29 -8
- package/src/diagnostic-catalog.ts +53 -0
- package/src/diagnostic.ts +1 -0
- package/src/fn.ts +24 -7
- package/src/fs.ts +22 -8
- package/src/identity.ts +61 -0
- package/src/index.ts +20 -4
- package/src/internal/cdn/cloudflare.ts +2 -1
- package/src/internal/certified-components.ts +1 -1
- package/src/internal/codegen.ts +95 -9
- package/src/internal/dev-websocket.ts +230 -0
- package/src/internal/hole-runtime.ts +286 -0
- package/src/internal/identity-epoch.ts +239 -0
- package/src/internal/invalidation-contract.ts +35 -0
- package/src/internal/invalidation.ts +213 -0
- package/src/internal/island-bindings.ts +191 -0
- package/src/internal/island-list.ts +92 -0
- package/src/internal/island-mount.ts +68 -0
- package/src/internal/island-owner.ts +20 -0
- package/src/internal/island-resource.ts +76 -0
- package/src/internal/island-signals.ts +249 -0
- package/src/internal/keep-alive-table.ts +72 -0
- package/src/internal/live-contract.ts +111 -0
- package/src/internal/live-queries.ts +60 -0
- package/src/internal/page-events.ts +27 -0
- package/src/internal/page-execution.ts +605 -45
- package/src/internal/parity.ts +35 -6
- package/src/internal/ppr/admission.ts +300 -0
- package/src/internal/ppr/canary.ts +122 -0
- package/src/internal/ppr/compile-shell.ts +379 -0
- package/src/internal/ppr/contract.ts +265 -0
- package/src/internal/ppr/frames.ts +170 -0
- package/src/internal/ppr/integration.ts +137 -0
- package/src/internal/ppr/options.ts +221 -0
- package/src/internal/ppr/route-rules.ts +77 -0
- package/src/internal/ppr/runtime.ts +39 -0
- package/src/internal/ppr/server.ts +1766 -0
- package/src/internal/ppr/shell-store.ts +152 -0
- package/src/internal/prerendered-pages.ts +7 -4
- package/src/internal/present.ts +20 -0
- package/src/internal/query-digest.ts +34 -0
- package/src/internal/query-runtime.ts +14 -1
- package/src/internal/query-seam.ts +48 -0
- package/src/internal/render-document.ts +158 -113
- package/src/internal/request-abort.ts +26 -0
- package/src/internal/server-boundary.ts +10 -1
- package/src/internal/share-data.ts +136 -0
- package/src/internal/status-page.ts +95 -0
- package/src/internal/store-signature.ts +149 -0
- package/src/internal/vite-plugin-compat.ts +2 -2
- package/src/internal/web-app.ts +123 -3
- package/src/islands-swap.ts +283 -0
- package/src/islands.ts +169 -72
- package/src/isr.ts +348 -106
- package/src/keep-alive.ts +1354 -0
- package/src/live/bus.ts +104 -0
- package/src/live/core.ts +52 -0
- package/src/live/history.ts +109 -0
- package/src/live/hub-protocol.ts +133 -0
- package/src/live/hub.ts +620 -0
- package/src/live/keyring.ts +384 -0
- package/src/live/read-capped.ts +36 -0
- package/src/live/revocations.ts +155 -0
- package/src/live/settings.ts +46 -0
- package/src/live-client.ts +1011 -0
- package/src/live-hub.ts +658 -0
- package/src/live-redis.ts +284 -0
- package/src/live.ts +1257 -0
- package/src/manifest.ts +274 -6
- package/src/navigation.ts +14 -2
- package/src/plugins/vite-zone-guard.ts +15 -2
- package/src/ppr.ts +153 -0
- package/src/query.ts +147 -20
- package/src/render-seam.ts +37 -0
- package/src/route-types.ts +3 -1
- package/src/router.ts +534 -132
- package/src/server-components/build.ts +9 -3
- package/src/server-components/client.ts +89 -5
- package/src/server-components/definition.ts +2 -1
- package/src/server-components/hole.ts +23 -0
- package/src/server-components/html-policy.ts +63 -4
- package/src/server-components/html-scan.ts +159 -0
- package/src/server-components/html.ts +18 -4
- package/src/server-components/router-integration.ts +21 -2
- package/src/server-components/runtime.ts +114 -31
- package/src/server-components/state.ts +66 -44
- package/src/server-components/types.ts +16 -0
- package/src/server-components/vite.ts +33 -14
- package/src/vite.ts +75 -6
- package/dist/nano.d.ts +0 -125
- package/dist/nano.d.ts.map +0 -1
- package/dist/nano.js +0 -190
- package/dist/nano.js.map +0 -1
- package/src/nano.ts +0 -246
|
@@ -5,19 +5,125 @@ import { DEFAULT_CSS_LOADING, normalizeCssLoading } from "../css-contract.js";
|
|
|
5
5
|
import { defer, ndjsonStream, prepareDeferred } from "../deferred.js";
|
|
6
6
|
import { isDraftEnabled } from "../draft.js";
|
|
7
7
|
import { routeTags } from "../isr.js";
|
|
8
|
-
import {
|
|
8
|
+
import { SWAP_HEADER } from "../render-seam.js";
|
|
9
|
+
import { createMatcher, DATA_HEADER, HOLE_FILL_HEADER, KEEP_HOLES_HEADER, NAV_FROM_HEADER, PREFETCH_HEADER, REDIRECT_HEADER, RETAIN_HEADER, REVALIDATE_HEADER, STATUS_HEADER, } from "../router.js";
|
|
9
10
|
import { searchOf, searchOfChain } from "../search.js";
|
|
10
11
|
import { mergeHeads, resolveChainMeta } from "./head-merge.js";
|
|
12
|
+
import { keepAliveTable, slotDepths } from "./keep-alive-table.js";
|
|
13
|
+
import { holeOwner, } from "./live-contract.js";
|
|
11
14
|
import { prepareModules } from "./module-preparation.js";
|
|
12
|
-
import {
|
|
15
|
+
import { isHole, serverHoleComponent, } from "./ppr/contract.js";
|
|
16
|
+
import { EMPTY_RETAIN, isControlFlow, isResponseResult, isRevalidateResult, layoutErrorId, redirect, renderPageResult, STATUS_TEXT, scopeParams, tagLayoutError, withDuplicateInstanceHint, } from "./render-document.js";
|
|
13
17
|
import { originFor, urlPartsFor } from "./request-url.js";
|
|
14
18
|
import { ACTION_SCOPE, DATA_RESPONSE_HEADERS, MIDDLEWARE_SCOPE, PAGE_SCOPE, PageResponseControls, PRIVATE_NO_STORE, PRIVATE_PAGE_HEADERS, privateOutcome, varyOnDataHeader, } from "./response-controls.js";
|
|
19
|
+
import { isStatusSignal, notFound, STATUS_SIGNAL, } from "./status-page.js";
|
|
15
20
|
/** Whether `c` is a client navigation's data request. On Node, `req.headers` builds every header. */
|
|
21
|
+
// The slot name is echoed in a response header, so only a plain identifier is honored.
|
|
22
|
+
const SLOT_NAME = /^[A-Za-z][\w-]{0,63}$/;
|
|
23
|
+
/** The slot an `x-nifra-swap` request names, when it is a valid slot name. */
|
|
24
|
+
function swapSlotOf(req) {
|
|
25
|
+
const name = req.headers.get(SWAP_HEADER);
|
|
26
|
+
return name !== null && SLOT_NAME.test(name) ? name : undefined;
|
|
27
|
+
}
|
|
28
|
+
/** The `swapSlot` render option for `req`, empty when it is not a swap request. */
|
|
29
|
+
function swapOption(req) {
|
|
30
|
+
const swapSlot = swapSlotOf(req);
|
|
31
|
+
return swapSlot === undefined ? {} : { swapSlot };
|
|
32
|
+
}
|
|
33
|
+
const headerOf = (c, name) => c.header !== undefined ? c.header(name) : c.req.headers.get(name);
|
|
16
34
|
function isDataRequest(c) {
|
|
17
|
-
return (c
|
|
35
|
+
return headerOf(c, DATA_HEADER) !== null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A data request's hole refresh: the hosts the client holds, which reload as fills, the holes it
|
|
39
|
+
* keeps, and in a live load each hole's owner. A name the route does not declare is a 400.
|
|
40
|
+
*/
|
|
41
|
+
function holeRefresh(c, request, live) {
|
|
42
|
+
if (!isDataRequest(c))
|
|
43
|
+
return { request };
|
|
44
|
+
const declared = new Set(request.holes.map((hole) => hole.name));
|
|
45
|
+
const namesOf = (header) => {
|
|
46
|
+
const value = headerOf(c, header);
|
|
47
|
+
const names = new Set();
|
|
48
|
+
if (value === null)
|
|
49
|
+
return names;
|
|
50
|
+
for (const name of value.split(",")) {
|
|
51
|
+
const trimmed = name.trim();
|
|
52
|
+
if (declared.has(trimmed))
|
|
53
|
+
names.add(trimmed);
|
|
54
|
+
// A live load's names come from a grant this server sealed and the page's own client: one
|
|
55
|
+
// naming a hole an older build declared is skipped.
|
|
56
|
+
else if (live === undefined)
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
return names;
|
|
60
|
+
};
|
|
61
|
+
const kept = namesOf(KEEP_HOLES_HEADER);
|
|
62
|
+
const fill = namesOf(HOLE_FILL_HEADER);
|
|
63
|
+
if (kept === undefined || fill === undefined) {
|
|
64
|
+
return new Response("Bad Request: the route has no such hole", {
|
|
65
|
+
status: 400,
|
|
66
|
+
headers: { "content-type": "text/plain; charset=utf-8", "cache-control": "no-store" },
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const refreshed = {
|
|
70
|
+
...request,
|
|
71
|
+
...(fill.size === 0 ? {} : { fill }),
|
|
72
|
+
...(kept.size === 0 ? {} : { kept }),
|
|
73
|
+
};
|
|
74
|
+
if (live === undefined)
|
|
75
|
+
return { request: refreshed };
|
|
76
|
+
const routeId = request.routeId;
|
|
77
|
+
let finish = () => { };
|
|
78
|
+
const loaded = new Promise((resolve) => {
|
|
79
|
+
finish = resolve;
|
|
80
|
+
});
|
|
81
|
+
const holeLive = {
|
|
82
|
+
collector: (hole) => live.collector(holeOwner(hole, routeId)),
|
|
83
|
+
seal: (hole) => live.seal(holeOwner(hole, routeId)),
|
|
84
|
+
done: (names) => finish(names.map((hole) => holeOwner(hole, routeId))),
|
|
85
|
+
};
|
|
86
|
+
return {
|
|
87
|
+
request: { ...refreshed, live: holeLive },
|
|
88
|
+
owners: { kept: [...kept].map((hole) => holeOwner(hole, routeId)), loaded },
|
|
89
|
+
};
|
|
18
90
|
}
|
|
19
91
|
/** The page slot of an `ssr = false` route with no `HydrateFallback`: a component that renders nothing. */
|
|
20
92
|
const EMPTY_LEAF = () => null;
|
|
93
|
+
/** `ctx.live` outside a live load: keys are declared for nobody. */
|
|
94
|
+
const NO_LIVE = () => { };
|
|
95
|
+
const headersSent = () => {
|
|
96
|
+
throw new TypeError("[nifra/web] ppr: a hole's server component cannot set a cookie: the shell already sent the headers");
|
|
97
|
+
};
|
|
98
|
+
/** A hole's response headers went out with the shell, so its server component sets none. */
|
|
99
|
+
const SENT_CONTROLS = Object.freeze({
|
|
100
|
+
headers: Object.freeze({}),
|
|
101
|
+
cookie: headersSent,
|
|
102
|
+
deleteCookie: headersSent,
|
|
103
|
+
});
|
|
104
|
+
/**
|
|
105
|
+
* The envelope's `live` member. With holes running it trails them: one grant, issued once the last hole
|
|
106
|
+
* settled, holding each hole that loaded and each the client kept.
|
|
107
|
+
*/
|
|
108
|
+
const liveEnvelopeOf = (live, owners, holes) => holes === undefined
|
|
109
|
+
? live.finish(owners)
|
|
110
|
+
: defer(holes.loaded.then((loaded) => live.finish({
|
|
111
|
+
...owners,
|
|
112
|
+
fresh: [...owners.fresh, ...loaded],
|
|
113
|
+
retained: [...owners.retained, ...holes.kept],
|
|
114
|
+
})));
|
|
115
|
+
/** Run one owner's loader with its `ctx.live`, closing the collector once the loader settles. */
|
|
116
|
+
const runLiveLoader = (live, owner, loader, ctx) => {
|
|
117
|
+
let value;
|
|
118
|
+
try {
|
|
119
|
+
value = loader({ ...ctx, live: live.collector(owner) });
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
live.seal(owner);
|
|
123
|
+
return Promise.reject(err);
|
|
124
|
+
}
|
|
125
|
+
return Promise.resolve(value).finally(() => live.seal(owner));
|
|
126
|
+
};
|
|
21
127
|
/** The request-scoping seam of an in-process `api` (see `inProcessClient`), if it carries one. */
|
|
22
128
|
function platformBinderOf(api) {
|
|
23
129
|
if ((typeof api !== "object" && typeof api !== "function") || api === null)
|
|
@@ -140,12 +246,13 @@ export function createPageRequestExecutor(options) {
|
|
|
140
246
|
const { i18n } = options;
|
|
141
247
|
const pageLocales = new Map(i18n?.locales.locales.map((locale) => [locale.key, locale]));
|
|
142
248
|
/** The request's locale for a document, with the served locales the client names locales from. */
|
|
143
|
-
const
|
|
249
|
+
const localeFor = (key) => {
|
|
144
250
|
if (i18n === undefined)
|
|
145
251
|
return {};
|
|
146
|
-
const locale = pageLocales.get(
|
|
252
|
+
const locale = pageLocales.get(key);
|
|
147
253
|
return locale === undefined ? { locales: i18n.locales } : { locale, locales: i18n.locales };
|
|
148
254
|
};
|
|
255
|
+
const localeOption = (req) => i18n === undefined ? {} : localeFor(i18n.localeOf(pathOf(req)));
|
|
149
256
|
/** Whether a route sits under a `[lang]` or `[[lang]]` directory, which the locale routing checks. */
|
|
150
257
|
const localeGuarded = (route) => {
|
|
151
258
|
if (i18n === undefined)
|
|
@@ -158,6 +265,49 @@ export function createPageRequestExecutor(options) {
|
|
|
158
265
|
};
|
|
159
266
|
const matchManifestRoute = createMatcher(manifest.routes.map((route) => ({ routeId: route.id, pattern: route.pattern })));
|
|
160
267
|
const routeById = new Map(manifest.routes.map((route) => [route.id, route]));
|
|
268
|
+
const liveLoadOf = options.liveLoadOf;
|
|
269
|
+
const liveSeedOf = options.liveSeedOf;
|
|
270
|
+
/** A live load holds one admission slot from before its middleware until its body is complete. */
|
|
271
|
+
const admitLive = (run) => async (c, controls) => {
|
|
272
|
+
const live = liveLoadOf?.(c.req);
|
|
273
|
+
if (live === undefined)
|
|
274
|
+
return run(c, controls);
|
|
275
|
+
const refused = live.admit();
|
|
276
|
+
if (refused !== undefined)
|
|
277
|
+
return refused;
|
|
278
|
+
let outcome;
|
|
279
|
+
try {
|
|
280
|
+
outcome = await run(c, controls);
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
live.release();
|
|
284
|
+
throw err;
|
|
285
|
+
}
|
|
286
|
+
if (outcome instanceof Response)
|
|
287
|
+
return live.settle(outcome);
|
|
288
|
+
live.release();
|
|
289
|
+
return outcome;
|
|
290
|
+
};
|
|
291
|
+
/** Which owners a successful live load ran and which it kept, by their wire ids. */
|
|
292
|
+
const liveOwners = (route, modules, layoutData, retained, mod, skipPage, ctx) => {
|
|
293
|
+
const fresh = [];
|
|
294
|
+
const kept = [];
|
|
295
|
+
for (let i = 0; i < (modules?.length ?? 0); i++) {
|
|
296
|
+
if (modules?.[i]?.loader === undefined)
|
|
297
|
+
continue;
|
|
298
|
+
const owner = `L:${route.layoutIds[i]}`;
|
|
299
|
+
if (retained.includes(i))
|
|
300
|
+
kept.push(owner);
|
|
301
|
+
// A layout that answered with a status declared keys for data nobody is shown.
|
|
302
|
+
else if (!isStatusSignal(layoutData?.[i]))
|
|
303
|
+
fresh.push(owner);
|
|
304
|
+
}
|
|
305
|
+
if (skipPage)
|
|
306
|
+
kept.push(`P:${route.id}`);
|
|
307
|
+
else if (mod.loader !== undefined)
|
|
308
|
+
fresh.push(`P:${route.id}`);
|
|
309
|
+
return { fresh, retained: kept, ctx };
|
|
310
|
+
};
|
|
161
311
|
// A nested `_404` answers an unmatched URL from inside the catch-all, never as a route of its own:
|
|
162
312
|
// a registered `/admin/*` would take URLs from a route the router only reaches by backtracking.
|
|
163
313
|
// Param names are indexed by position, so two directories that name one segment differently share
|
|
@@ -197,6 +347,16 @@ export function createPageRequestExecutor(options) {
|
|
|
197
347
|
const draftFlag = (req) => options.draftSecret === undefined
|
|
198
348
|
? Promise.resolve(false)
|
|
199
349
|
: isDraftEnabled(req, options.draftSecret);
|
|
350
|
+
// Where the browser's keep-alive view puts slot wrappers, so the document it hydrates has them:
|
|
351
|
+
// nothing outside an app with a `keepAlive` route.
|
|
352
|
+
const keepTable = keepAliveTable(manifest);
|
|
353
|
+
const slotsFor = (layoutIds, routeId) => {
|
|
354
|
+
// Every page of a keep-alive app renders through the adapter's keep-alive root, wrappers or none,
|
|
355
|
+
// as the browser hydrates it.
|
|
356
|
+
if (keepTable === undefined)
|
|
357
|
+
return {};
|
|
358
|
+
return { slots: slotDepths(keepTable, layoutIds, routeId) };
|
|
359
|
+
};
|
|
200
360
|
const preloadOf = (id) => {
|
|
201
361
|
const chunks = options.routePreload?.[id];
|
|
202
362
|
return chunks ? { preload: chunks } : {};
|
|
@@ -274,7 +434,7 @@ export function createPageRequestExecutor(options) {
|
|
|
274
434
|
* Run layout loaders, awaiting gates before starting the page loader and retaining only safe data.
|
|
275
435
|
* `gated` carries gates that already ran for this request, so none runs twice.
|
|
276
436
|
*/
|
|
277
|
-
const runLayoutChain = async (route, ctx, controls, retain, gated) => {
|
|
437
|
+
const runLayoutChain = async (route, ctx, controls, retain, gated, live) => {
|
|
278
438
|
if (route.layoutIds.length === 0)
|
|
279
439
|
return emptyLayoutRun;
|
|
280
440
|
const modules = gated?.modules ?? (await loadLayoutModules(route));
|
|
@@ -308,14 +468,19 @@ export function createPageRequestExecutor(options) {
|
|
|
308
468
|
params: scopeParams(ctx.params, route.layoutParams?.[i]),
|
|
309
469
|
set: controls.scope(i),
|
|
310
470
|
};
|
|
471
|
+
const layoutId = route.layoutIds[i];
|
|
311
472
|
if (modules[i]?.gate === true) {
|
|
312
|
-
results[i] =
|
|
473
|
+
results[i] =
|
|
474
|
+
gated !== undefined
|
|
475
|
+
? gated.gates[i]
|
|
476
|
+
: await runGate(route, i, live === undefined
|
|
477
|
+
? loader
|
|
478
|
+
: (gateCtx) => runLiveLoader(live, `L:${layoutId}`, loader, gateCtx), scoped);
|
|
313
479
|
continue;
|
|
314
480
|
}
|
|
315
|
-
const layoutId = route.layoutIds[i];
|
|
316
481
|
const index = i;
|
|
317
482
|
try {
|
|
318
|
-
const value = loader(scoped);
|
|
483
|
+
const value = live === undefined ? loader(scoped) : runLiveLoader(live, `L:${layoutId}`, loader, scoped);
|
|
319
484
|
// Scalars settle synchronously. Objects keep await's intrinsic promise/thenable
|
|
320
485
|
// assimilation: property-presence and prototype probes are unsafe for proxies.
|
|
321
486
|
if (value !== null && (typeof value === "object" || typeof value === "function")) {
|
|
@@ -512,6 +677,11 @@ export function createPageRequestExecutor(options) {
|
|
|
512
677
|
handles: [...layoutModules.map((layout) => layout.handle), page.handle],
|
|
513
678
|
});
|
|
514
679
|
const dirOfId = (id, suffix) => id === suffix ? "" : id.slice(0, id.length - suffix.length - 1);
|
|
680
|
+
/** The server's error log for one request, where a rejected `defer()` value is written. */
|
|
681
|
+
const deferredLogOf = (req) => {
|
|
682
|
+
const log = options.logBoundaryError;
|
|
683
|
+
return log === undefined ? undefined : (error) => log(error, req);
|
|
684
|
+
};
|
|
515
685
|
const boundaryFor = (route, err) => {
|
|
516
686
|
const ids = route.errorIds ?? [];
|
|
517
687
|
const failing = layoutErrorId(err);
|
|
@@ -568,6 +738,8 @@ export function createPageRequestExecutor(options) {
|
|
|
568
738
|
routeId: errorId,
|
|
569
739
|
status: 500,
|
|
570
740
|
hydrate: false,
|
|
741
|
+
signal: req.signal,
|
|
742
|
+
logError: deferredLogOf(req),
|
|
571
743
|
...(layoutData === undefined ? {} : { layoutData }),
|
|
572
744
|
...(personalized || layoutData !== undefined ? { headers: PRIVATE_PAGE_HEADERS } : {}),
|
|
573
745
|
...(nonce === undefined ? {} : { nonce }),
|
|
@@ -645,6 +817,7 @@ export function createPageRequestExecutor(options) {
|
|
|
645
817
|
draft,
|
|
646
818
|
search: loaderSearch(page.searchSchema, c.req),
|
|
647
819
|
set: controls.scope(PAGE_SCOPE),
|
|
820
|
+
live: NO_LIVE,
|
|
648
821
|
};
|
|
649
822
|
if (route.middlewareIds !== undefined)
|
|
650
823
|
await runMiddleware(route, ctx, controls);
|
|
@@ -689,6 +862,8 @@ export function createPageRequestExecutor(options) {
|
|
|
689
862
|
search: searchChainOf(modules, loaded, req),
|
|
690
863
|
path: pathOf(req),
|
|
691
864
|
status,
|
|
865
|
+
signal: req.signal,
|
|
866
|
+
logError: deferredLogOf(req),
|
|
692
867
|
// The browser renders this page inside the root layout, so a page that had to render alone
|
|
693
868
|
// stays server-only, as a nested `_404` does.
|
|
694
869
|
...(wraps && chain === undefined ? { hydrate: false } : {}),
|
|
@@ -703,6 +878,7 @@ export function createPageRequestExecutor(options) {
|
|
|
703
878
|
...copyOption,
|
|
704
879
|
...localeOption(req),
|
|
705
880
|
...titleOption,
|
|
881
|
+
...slotsFor(layoutIds, routeId),
|
|
706
882
|
};
|
|
707
883
|
if (chain === undefined)
|
|
708
884
|
return renderPageResult(statusPage);
|
|
@@ -748,7 +924,7 @@ export function createPageRequestExecutor(options) {
|
|
|
748
924
|
// A faulty reporter must never break error rendering.
|
|
749
925
|
}
|
|
750
926
|
};
|
|
751
|
-
const handleDataOrDocument = async (req, isData, env, route, params, mod, data, layoutData, layoutModules, layoutRetained, boundaryStates, assemblyCache, responseHeaders, personalized, serverComponents) => {
|
|
927
|
+
const handleDataOrDocument = async (req, isData, env, route, params, mod, data, layoutData, layoutModules, layoutRetained, boundaryStates, assemblyCache, responseHeaders, personalized, serverComponents, live, liveSeed) => {
|
|
752
928
|
// Every layout loader settled before the page rendered, so a status or error page can reuse them.
|
|
753
929
|
const settled = async (_page, count) => settledLayouts(layoutModules, layoutData, count);
|
|
754
930
|
if (isStatusSignal(data))
|
|
@@ -770,7 +946,14 @@ export function createPageRequestExecutor(options) {
|
|
|
770
946
|
...deferred,
|
|
771
947
|
...(boundarySplit === undefined ? [] : boundarySplit.deferred),
|
|
772
948
|
];
|
|
773
|
-
|
|
949
|
+
// Deferred when holes run: their owners are known only once the last one settles.
|
|
950
|
+
const liveSplit = live === undefined ? undefined : prepareDeferred(live, allDeferred.length);
|
|
951
|
+
if (liveSplit !== undefined)
|
|
952
|
+
allDeferred.push(...liveSplit.deferred);
|
|
953
|
+
const payload = layoutData === undefined &&
|
|
954
|
+
boundarySplit === undefined &&
|
|
955
|
+
serverComponents === undefined &&
|
|
956
|
+
live === undefined
|
|
774
957
|
? pageSplit.forClient
|
|
775
958
|
: {
|
|
776
959
|
v: 1,
|
|
@@ -779,11 +962,12 @@ export function createPageRequestExecutor(options) {
|
|
|
779
962
|
retained: layoutRetained,
|
|
780
963
|
...(boundarySplit === undefined ? {} : { boundaries: boundarySplit.forClient }),
|
|
781
964
|
...(serverComponents === undefined ? {} : { serverComponents }),
|
|
965
|
+
...(liveSplit === undefined ? {} : { live: liveSplit.forClient }),
|
|
782
966
|
};
|
|
783
967
|
if (allDeferred.length === 0) {
|
|
784
968
|
return Response.json(payload ?? null, { headers: DATA_RESPONSE_HEADERS });
|
|
785
969
|
}
|
|
786
|
-
return new Response(ndjsonStream(payload, allDeferred), {
|
|
970
|
+
return new Response(ndjsonStream(payload, allDeferred, undefined, req.signal, deferredLogOf(req)), {
|
|
787
971
|
headers: {
|
|
788
972
|
"content-type": "application/x-ndjson; charset=utf-8",
|
|
789
973
|
...DATA_RESPONSE_HEADERS,
|
|
@@ -813,6 +997,8 @@ export function createPageRequestExecutor(options) {
|
|
|
813
997
|
search: searchChainOf(layoutModules, mod, req),
|
|
814
998
|
matchChain: matchChainOf(route.layoutIds, layoutModules, route.id, mod),
|
|
815
999
|
hydrate: mod.hydrate !== false,
|
|
1000
|
+
signal: req.signal,
|
|
1001
|
+
logError: deferredLogOf(req),
|
|
816
1002
|
...preloadOf(route.id),
|
|
817
1003
|
...stylesOf(route.id),
|
|
818
1004
|
...appDocumentOptions,
|
|
@@ -820,8 +1006,15 @@ export function createPageRequestExecutor(options) {
|
|
|
820
1006
|
};
|
|
821
1007
|
if (serverComponents !== undefined)
|
|
822
1008
|
page.serverComponents = serverComponents;
|
|
1009
|
+
if (liveSeed?.grant !== undefined)
|
|
1010
|
+
page.live = liveSeed;
|
|
823
1011
|
if (progressiveActionData.has(req))
|
|
824
1012
|
page.actionData = progressiveActionData.get(req);
|
|
1013
|
+
const swapSlot = swapSlotOf(req);
|
|
1014
|
+
if (swapSlot !== undefined)
|
|
1015
|
+
page.swapSlot = swapSlot;
|
|
1016
|
+
if (keepTable !== undefined)
|
|
1017
|
+
Object.assign(page, slotsFor(route.layoutIds, route.id));
|
|
825
1018
|
if (layoutData !== undefined)
|
|
826
1019
|
page.layoutData = layoutData;
|
|
827
1020
|
if (boundaryStates !== undefined)
|
|
@@ -919,6 +1112,8 @@ export function createPageRequestExecutor(options) {
|
|
|
919
1112
|
matchChain: matchChainOf(page.layoutIds, layoutModules, id, mod),
|
|
920
1113
|
status: 404,
|
|
921
1114
|
hydrate: false,
|
|
1115
|
+
signal: req.signal,
|
|
1116
|
+
logError: deferredLogOf(req),
|
|
922
1117
|
...localeOption(req),
|
|
923
1118
|
...(layoutData !== undefined ? { layoutData } : {}),
|
|
924
1119
|
...stylesOf(id),
|
|
@@ -984,6 +1179,86 @@ export function createPageRequestExecutor(options) {
|
|
|
984
1179
|
controls.seal();
|
|
985
1180
|
}
|
|
986
1181
|
};
|
|
1182
|
+
const pprRequestFor = (c, route, mod, layouts, boundaries, shellLoader, requestApi, draft, search) => {
|
|
1183
|
+
const path = urlPartsFor(c.req).pathname;
|
|
1184
|
+
const locale = i18n?.localeOf(path);
|
|
1185
|
+
const params = c.params;
|
|
1186
|
+
const shellOrigin = options.ppr?.origin;
|
|
1187
|
+
const variations = options.ppr?.variationsOf(mod.shellVariations, urlPartsFor(c.req).search) ?? {};
|
|
1188
|
+
const shellSearch = options.ppr?.variationQuery(variations) ?? "";
|
|
1189
|
+
// What a shared entry's tags read: its key's parts, never the Host or an undeclared query, which
|
|
1190
|
+
// the first visitor of a key could set so a later purge misses the entry.
|
|
1191
|
+
const shellUrl = () => {
|
|
1192
|
+
const url = new URL(shellOrigin ?? "http://shell.invalid");
|
|
1193
|
+
url.pathname = path;
|
|
1194
|
+
url.search = shellSearch;
|
|
1195
|
+
return url;
|
|
1196
|
+
};
|
|
1197
|
+
// The unbound `api`: a shell is built for every visitor, so no visitor's platform reaches it.
|
|
1198
|
+
const shellContext = shellOrigin === undefined
|
|
1199
|
+
? { phase: "shell", params, locale, variations, api }
|
|
1200
|
+
: { phase: "shell", params, locale, variations, api, origin: shellOrigin };
|
|
1201
|
+
return {
|
|
1202
|
+
routeId: route.id,
|
|
1203
|
+
path,
|
|
1204
|
+
locale,
|
|
1205
|
+
variations,
|
|
1206
|
+
request: c.req,
|
|
1207
|
+
holes: boundaries.filter(isHole),
|
|
1208
|
+
holeContext: { request: c.req, params, api: requestApi, env: c.env, draft, search },
|
|
1209
|
+
shellContext,
|
|
1210
|
+
revalidate: mod.revalidate,
|
|
1211
|
+
waitUntil: c.waitUntil,
|
|
1212
|
+
tags: () => mod.revalidateTags === undefined
|
|
1213
|
+
? []
|
|
1214
|
+
: routeTags(mod.revalidateTags, { params, url: shellUrl() }, route.id),
|
|
1215
|
+
holeTags: (hole) => hole.revalidateTags === undefined
|
|
1216
|
+
? []
|
|
1217
|
+
: routeTags(hole.revalidateTags, { params, url: shellUrl() }, `${route.id}#${hole.name}`),
|
|
1218
|
+
loadShell: async (signal) => shellLoader({ ...shellContext, signal }),
|
|
1219
|
+
renderShellDocument: async (shellData, states) => {
|
|
1220
|
+
const statics = boundaries.some((boundary) => boundary.mode === "static")
|
|
1221
|
+
? await resolveStaticBoundaries(boundaries, { phase: "build" }, options.staticBoundaryCache)
|
|
1222
|
+
: undefined;
|
|
1223
|
+
const { chain, head } = resolveChainAndHead(layouts, undefined, mod,
|
|
1224
|
+
// A Host header is the client's to choose, so a shared shell's meta gets the configured one.
|
|
1225
|
+
{ data: shellData, pageData: shellData, params, origin: shellOrigin ?? "" }, serverLeafOf(route, mod));
|
|
1226
|
+
// Nothing here reads the request beyond its pathname: no origin, search, nonce or headers.
|
|
1227
|
+
const page = {
|
|
1228
|
+
adapter,
|
|
1229
|
+
chain,
|
|
1230
|
+
data: shellData,
|
|
1231
|
+
head,
|
|
1232
|
+
clientEntry,
|
|
1233
|
+
routeId: route.id,
|
|
1234
|
+
params,
|
|
1235
|
+
path,
|
|
1236
|
+
search: searchOfChain([...layouts.map((m) => m.searchSchema), mod.searchSchema], shellSearch === "" ? "" : `?${shellSearch}`),
|
|
1237
|
+
matchChain: matchChainOf(route.layoutIds, layouts, route.id, mod),
|
|
1238
|
+
hydrate: mod.hydrate !== false,
|
|
1239
|
+
boundaries: { ...statics, ...states },
|
|
1240
|
+
...preloadOf(route.id),
|
|
1241
|
+
...stylesOf(route.id),
|
|
1242
|
+
...appDocumentOptions,
|
|
1243
|
+
...(locale === undefined ? {} : localeFor(locale)),
|
|
1244
|
+
...slotsFor(route.layoutIds, route.id),
|
|
1245
|
+
};
|
|
1246
|
+
if (mod.islandScripts !== undefined)
|
|
1247
|
+
page.islandScripts = mod.islandScripts;
|
|
1248
|
+
const result = await renderPageResult(page);
|
|
1249
|
+
// A buffered page hands over its string: a Response round trip to read it back cost more.
|
|
1250
|
+
const rendered = result.toNodeBody?.() ?? result.toResponse();
|
|
1251
|
+
if (rendered.status !== 200) {
|
|
1252
|
+
throw new Error(`[nifra/web] ppr: the shell of "${route.id}" rendered status ${rendered.status}`);
|
|
1253
|
+
}
|
|
1254
|
+
if (rendered instanceof Response)
|
|
1255
|
+
return rendered.text();
|
|
1256
|
+
return typeof rendered.body === "string"
|
|
1257
|
+
? rendered.body
|
|
1258
|
+
: new TextDecoder().decode(rendered.body);
|
|
1259
|
+
},
|
|
1260
|
+
};
|
|
1261
|
+
};
|
|
987
1262
|
return {
|
|
988
1263
|
get: (route) => {
|
|
989
1264
|
const is404Fallback = options.staticFallbacks?.[route.pattern] === "404";
|
|
@@ -1013,7 +1288,8 @@ export function createPageRequestExecutor(options) {
|
|
|
1013
1288
|
}
|
|
1014
1289
|
return slot;
|
|
1015
1290
|
};
|
|
1016
|
-
|
|
1291
|
+
const page = async (c, controls) => {
|
|
1292
|
+
let live = liveLoadOf?.(c.req);
|
|
1017
1293
|
const componentRuntime = options.serverComponents;
|
|
1018
1294
|
const componentOwner = componentRuntime?.owns(route.id) === true;
|
|
1019
1295
|
let componentRequest;
|
|
@@ -1030,6 +1306,17 @@ export function createPageRequestExecutor(options) {
|
|
|
1030
1306
|
}
|
|
1031
1307
|
const loaded = loadModule(route);
|
|
1032
1308
|
const mod = cacheModules && !(loaded instanceof Promise) ? loaded : await loaded;
|
|
1309
|
+
// A document's loaders declare their keys into a seed, which the page exchanges for a grant
|
|
1310
|
+
// once its socket opens, instead of loading itself again. Partially prerendered pages, whose
|
|
1311
|
+
// holes settle after the shell, and server-component routes load as before.
|
|
1312
|
+
const seeding = live === undefined &&
|
|
1313
|
+
liveSeedOf !== undefined &&
|
|
1314
|
+
!componentOwner &&
|
|
1315
|
+
componentRequest === undefined &&
|
|
1316
|
+
(options.ppr === undefined || mod.shellLoader === undefined) &&
|
|
1317
|
+
!isDataRequest(c);
|
|
1318
|
+
if (seeding)
|
|
1319
|
+
live = liveSeedOf(c.req, route.id);
|
|
1033
1320
|
const draft = await draftFlag(c.req);
|
|
1034
1321
|
// Unpublished content is the editor's alone: whatever cache-control a loader sets, no cache keeps it.
|
|
1035
1322
|
if (draft)
|
|
@@ -1043,6 +1330,9 @@ export function createPageRequestExecutor(options) {
|
|
|
1043
1330
|
let componentState;
|
|
1044
1331
|
const requestApi = apiFor(c);
|
|
1045
1332
|
let run;
|
|
1333
|
+
let skipPage = false;
|
|
1334
|
+
let liveCtx;
|
|
1335
|
+
let holeOwners;
|
|
1046
1336
|
try {
|
|
1047
1337
|
const ctx = {
|
|
1048
1338
|
params: c.params,
|
|
@@ -1053,11 +1343,20 @@ export function createPageRequestExecutor(options) {
|
|
|
1053
1343
|
draft,
|
|
1054
1344
|
search: loaderSearch(mod.searchSchema, c.req),
|
|
1055
1345
|
set: controls.scope(PAGE_SCOPE),
|
|
1346
|
+
live: NO_LIVE,
|
|
1056
1347
|
};
|
|
1057
1348
|
if (route.middlewareIds !== undefined || localeGuarded(route)) {
|
|
1058
1349
|
await runMiddleware(route, ctx, controls);
|
|
1059
1350
|
}
|
|
1060
|
-
|
|
1351
|
+
// After middleware, before any loader: a grant issued to another viewer keeps nothing.
|
|
1352
|
+
const retains = live === undefined || (await live.bind(ctx));
|
|
1353
|
+
skipPage =
|
|
1354
|
+
live !== undefined &&
|
|
1355
|
+
retains &&
|
|
1356
|
+
!componentOwner &&
|
|
1357
|
+
live.retainPage &&
|
|
1358
|
+
live.routeId === route.id;
|
|
1359
|
+
run = await runLayoutChain(route, ctx, controls, componentOwner || !retains ? undefined : retainContextOf(c), undefined, live);
|
|
1061
1360
|
layoutModules = run.modules;
|
|
1062
1361
|
layoutRetained = run.retained;
|
|
1063
1362
|
const boundaryDefinitions = componentRequest === undefined
|
|
@@ -1069,7 +1368,59 @@ export function createPageRequestExecutor(options) {
|
|
|
1069
1368
|
if (boundaryDefinitions.length > 0)
|
|
1070
1369
|
boundaryDescriptors(boundaryDefinitions);
|
|
1071
1370
|
const effectiveSearch = searchChainOf(run.modules, mod, c.req);
|
|
1072
|
-
const
|
|
1371
|
+
const ppr = options.ppr;
|
|
1372
|
+
const shellLoader = componentRequest === undefined && !componentOwner ? mod.shellLoader : undefined;
|
|
1373
|
+
let pprRequest;
|
|
1374
|
+
// How a document that renders whole gets its holes: complete, unless no shell exists yet.
|
|
1375
|
+
let wholeHoles = "settled";
|
|
1376
|
+
if (ppr !== undefined && shellLoader !== undefined) {
|
|
1377
|
+
ppr.assertRoute(route, run.modules, boundaryDefinitions);
|
|
1378
|
+
pprRequest = pprRequestFor(c, route, mod, run.modules, boundaryDefinitions, shellLoader, requestApi, draft, effectiveSearch);
|
|
1379
|
+
const refresh = holeRefresh(c, pprRequest, live);
|
|
1380
|
+
if (refresh instanceof Response)
|
|
1381
|
+
return refresh;
|
|
1382
|
+
pprRequest = refresh.request;
|
|
1383
|
+
holeOwners = refresh.owners;
|
|
1384
|
+
const components = options.serverComponents;
|
|
1385
|
+
const renderHole = components?.hosts?.(route.id) === true ? components.hole : undefined;
|
|
1386
|
+
if (renderHole === undefined &&
|
|
1387
|
+
pprRequest.holes.some((hole) => serverHoleComponent(hole.render) !== undefined)) {
|
|
1388
|
+
throw new Error(`[nifra/web] ppr: route "${route.id}" has a hole that shows a server component; list the component under createServerComponents({ holes }) for this route`);
|
|
1389
|
+
}
|
|
1390
|
+
if (renderHole !== undefined) {
|
|
1391
|
+
const loaderCtx = ctx;
|
|
1392
|
+
pprRequest = {
|
|
1393
|
+
...pprRequest,
|
|
1394
|
+
// The owner path's context, but with the hole's signal and no response to change.
|
|
1395
|
+
component: (name, component, input, signal) => renderHole.call(components, route.id, component, name, input, Object.create(c, Object.getOwnPropertyDescriptors({
|
|
1396
|
+
...loaderCtx,
|
|
1397
|
+
search: effectiveSearch,
|
|
1398
|
+
set: SENT_CONTROLS,
|
|
1399
|
+
signal,
|
|
1400
|
+
data: undefined,
|
|
1401
|
+
layoutData: [],
|
|
1402
|
+
}))),
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
// A draft is the editor's alone, so it never reads or fills the shared shell.
|
|
1406
|
+
if (!draft && !isDataRequest(c)) {
|
|
1407
|
+
const streamed = await ppr.stream(pprRequest, () => controls.documentHeaders());
|
|
1408
|
+
if (streamed instanceof Response)
|
|
1409
|
+
return streamed;
|
|
1410
|
+
wholeHoles = streamed;
|
|
1411
|
+
}
|
|
1412
|
+
// Its holes are one visitor's, so no cache may store the page they render into.
|
|
1413
|
+
controls.personalize();
|
|
1414
|
+
}
|
|
1415
|
+
// Every PPR hole runs through the PPR server, so each has admission and its own deadline.
|
|
1416
|
+
const holeStates = pprRequest === undefined || ppr === undefined
|
|
1417
|
+
? undefined
|
|
1418
|
+
: ppr.server.holeStates(pprRequest, !isDataRequest(c)
|
|
1419
|
+
? wholeHoles
|
|
1420
|
+
: c.req.headers.get(PREFETCH_HEADER) === null
|
|
1421
|
+
? "deferred"
|
|
1422
|
+
: "omitted", c.req.signal);
|
|
1423
|
+
const boundaryBatch = boundaryDefinitions.length === 0 || holeStates !== undefined
|
|
1073
1424
|
? undefined
|
|
1074
1425
|
: startDynamicBoundaries(boundaryDefinitions, {
|
|
1075
1426
|
request: c.req,
|
|
@@ -1079,18 +1430,33 @@ export function createPageRequestExecutor(options) {
|
|
|
1079
1430
|
draft,
|
|
1080
1431
|
search: effectiveSearch,
|
|
1081
1432
|
signal: c.req.signal,
|
|
1433
|
+
live: NO_LIVE,
|
|
1082
1434
|
});
|
|
1083
1435
|
const staticBoundaryPromise = boundaryDefinitions.length === 0
|
|
1084
1436
|
? undefined
|
|
1085
1437
|
: resolveStaticBoundaries(boundaryDefinitions, { phase: "build" }, options.staticBoundaryCache);
|
|
1086
|
-
const pageResult =
|
|
1438
|
+
const pageResult = pprRequest !== undefined && ppr !== undefined
|
|
1439
|
+
? // A key with no shell yet must not build one through its data either.
|
|
1440
|
+
draft || wholeHoles === "deferred"
|
|
1441
|
+
? pprRequest.loadShell(c.req.signal)
|
|
1442
|
+
: ppr.shellData(pprRequest, c.req.signal)
|
|
1443
|
+
: mod.loader === undefined || skipPage
|
|
1444
|
+
? null
|
|
1445
|
+
: live === undefined
|
|
1446
|
+
? mod.loader({ ...ctx, search: effectiveSearch })
|
|
1447
|
+
: runLiveLoader(live, `P:${route.id}`, mod.loader, {
|
|
1448
|
+
...ctx,
|
|
1449
|
+
search: effectiveSearch,
|
|
1450
|
+
});
|
|
1087
1451
|
const [pageData, , staticBoundaries] = run.pending === undefined && staticBoundaryPromise === undefined
|
|
1088
1452
|
? [await pageResult, undefined, undefined]
|
|
1089
1453
|
: staticBoundaryPromise === undefined
|
|
1090
1454
|
? await Promise.all([pageResult, run.pending])
|
|
1091
1455
|
: await Promise.all([pageResult, run.pending, staticBoundaryPromise]);
|
|
1092
1456
|
data = pageData;
|
|
1093
|
-
|
|
1457
|
+
// A gate on a PPR route runs for its redirect or refusal only. Its data reaches no response,
|
|
1458
|
+
// so a soft navigation renders the layouts exactly as the shared shell did.
|
|
1459
|
+
layoutData = pprRequest === undefined ? run.layoutData : undefined;
|
|
1094
1460
|
if (componentOwner) {
|
|
1095
1461
|
for (let i = 0; i < (layoutData?.length ?? 0); i++) {
|
|
1096
1462
|
const outcome = layoutData?.[i];
|
|
@@ -1110,8 +1476,17 @@ export function createPageRequestExecutor(options) {
|
|
|
1110
1476
|
}));
|
|
1111
1477
|
componentState = await componentRuntime.execute(route.id, componentContext, componentRequest, options.nonce === undefined ? undefined : await resolveNonce(c.req, c.env));
|
|
1112
1478
|
}
|
|
1113
|
-
if (
|
|
1114
|
-
|
|
1479
|
+
if (holeStates !== undefined) {
|
|
1480
|
+
// The static resolver names every boundary, leaving the dynamic ones to the holes.
|
|
1481
|
+
boundaryStates = { ...staticBoundaries, ...(await holeStates) };
|
|
1482
|
+
}
|
|
1483
|
+
else if (boundaryBatch !== undefined) {
|
|
1484
|
+
// Each resolver returns a state for every boundary and marks the other's modes
|
|
1485
|
+
// `unresolved`, so a slot takes its state from the resolver of its own mode.
|
|
1486
|
+
const streamed = { ...boundaryBatch.initial };
|
|
1487
|
+
for (const [name, state] of Object.entries(staticBoundaries ?? {}))
|
|
1488
|
+
if (state.mode === "static")
|
|
1489
|
+
streamed[name] = state;
|
|
1115
1490
|
for (const entry of boundaryBatch.pending) {
|
|
1116
1491
|
const initial = streamed[entry.name];
|
|
1117
1492
|
if (initial !== undefined)
|
|
@@ -1125,6 +1500,7 @@ export function createPageRequestExecutor(options) {
|
|
|
1125
1500
|
// Inside the loader `try`: a header the response cannot carry is a loader error, rendered
|
|
1126
1501
|
// by the same boundary as one.
|
|
1127
1502
|
responseHeaders = controls.documentHeaders();
|
|
1503
|
+
liveCtx = ctx;
|
|
1128
1504
|
}
|
|
1129
1505
|
catch (err) {
|
|
1130
1506
|
if (componentRequest !== undefined)
|
|
@@ -1148,8 +1524,15 @@ export function createPageRequestExecutor(options) {
|
|
|
1148
1524
|
if (nested !== undefined)
|
|
1149
1525
|
return nested;
|
|
1150
1526
|
}
|
|
1151
|
-
|
|
1152
|
-
|
|
1527
|
+
const isData = isDataRequest(c);
|
|
1528
|
+
const liveEnvelope = live === undefined || (!isData && !seeding) || isStatusSignal(data) || isControlFlow(data)
|
|
1529
|
+
? undefined
|
|
1530
|
+
: await liveEnvelopeOf(live, liveOwners(route, layoutModules, layoutData, layoutRetained, mod, skipPage, liveCtx), holeOwners);
|
|
1531
|
+
return handleDataOrDocument(c.req, isData, c.env, route, c.params, mod, data, layoutData, layoutModules ?? (await loadLayoutModules(route)), layoutRetained, boundaryStates, layoutModules === undefined ? undefined : assemblyCacheFor(mod, layoutModules, c.req), responseHeaders, controls.personalized, componentState, seeding ? undefined : liveEnvelope, seeding && liveEnvelope !== undefined && !("__nifra_deferred" in liveEnvelope)
|
|
1532
|
+
? liveEnvelope
|
|
1533
|
+
: undefined);
|
|
1534
|
+
};
|
|
1535
|
+
return withResponseControls(liveLoadOf === undefined ? page : admitLive(page));
|
|
1153
1536
|
},
|
|
1154
1537
|
post: (route) => withResponseControls(async (c, controls) => {
|
|
1155
1538
|
const loaded = loadModule(route);
|
|
@@ -1195,6 +1578,7 @@ export function createPageRequestExecutor(options) {
|
|
|
1195
1578
|
draft,
|
|
1196
1579
|
search: loaderSearch(mod.searchSchema, c.req),
|
|
1197
1580
|
set: controls.scope(ACTION_SCOPE),
|
|
1581
|
+
live: NO_LIVE,
|
|
1198
1582
|
};
|
|
1199
1583
|
let gated;
|
|
1200
1584
|
let result;
|
|
@@ -1210,13 +1594,16 @@ export function createPageRequestExecutor(options) {
|
|
|
1210
1594
|
return err;
|
|
1211
1595
|
throw err;
|
|
1212
1596
|
}
|
|
1213
|
-
const
|
|
1214
|
-
const actionResult =
|
|
1215
|
-
const revalidateHeader =
|
|
1216
|
-
? {
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1597
|
+
const revalidation = isRevalidateResult(result) ? result : undefined;
|
|
1598
|
+
const actionResult = revalidation === undefined ? result : revalidation.data;
|
|
1599
|
+
const revalidateHeader = revalidation === undefined
|
|
1600
|
+
? {}
|
|
1601
|
+
: { [REVALIDATE_HEADER]: revalidation.__nifraRevalidate.join(",") };
|
|
1602
|
+
// The write is done, whatever the action answers with (a redirect included): what it made
|
|
1603
|
+
// stale is invalidated before the answer leaves.
|
|
1604
|
+
const settling = revalidation === undefined ? undefined : options.invalidate?.(revalidation, c.req);
|
|
1605
|
+
if (settling !== undefined)
|
|
1606
|
+
await settling;
|
|
1220
1607
|
if (isControlFlow(actionResult))
|
|
1221
1608
|
return actionResult;
|
|
1222
1609
|
if (isDataRequest) {
|
|
@@ -1229,7 +1616,7 @@ export function createPageRequestExecutor(options) {
|
|
|
1229
1616
|
headers: { ...DATA_RESPONSE_HEADERS, ...revalidateHeader },
|
|
1230
1617
|
});
|
|
1231
1618
|
}
|
|
1232
|
-
return new Response(ndjsonStream(forClient, deferred), {
|
|
1619
|
+
return new Response(ndjsonStream(forClient, deferred, undefined, c.req.signal, deferredLogOf(c.req)), {
|
|
1233
1620
|
headers: {
|
|
1234
1621
|
"content-type": "application/x-ndjson; charset=utf-8",
|
|
1235
1622
|
...DATA_RESPONSE_HEADERS,
|
|
@@ -1308,6 +1695,7 @@ export function createPageRequestExecutor(options) {
|
|
|
1308
1695
|
draft,
|
|
1309
1696
|
search,
|
|
1310
1697
|
set: controls.scope(PAGE_SCOPE),
|
|
1698
|
+
live: NO_LIVE,
|
|
1311
1699
|
})
|
|
1312
1700
|
: null;
|
|
1313
1701
|
const [pageData] = run.pending === undefined
|
|
@@ -1344,7 +1732,7 @@ export function createPageRequestExecutor(options) {
|
|
|
1344
1732
|
origin: originFor(c.req),
|
|
1345
1733
|
...(nonce === undefined ? {} : { nonce }),
|
|
1346
1734
|
}, serverLeafOf(route, mod));
|
|
1347
|
-
|
|
1735
|
+
const page = {
|
|
1348
1736
|
adapter,
|
|
1349
1737
|
chain,
|
|
1350
1738
|
data,
|
|
@@ -1357,6 +1745,8 @@ export function createPageRequestExecutor(options) {
|
|
|
1357
1745
|
search,
|
|
1358
1746
|
matchChain: matchChainOf(route.layoutIds, layoutModules, route.id, mod),
|
|
1359
1747
|
hydrate: mod.hydrate !== false,
|
|
1748
|
+
signal: c.req.signal,
|
|
1749
|
+
logError: deferredLogOf(c.req),
|
|
1360
1750
|
...layoutProps,
|
|
1361
1751
|
...preloadOf(route.id),
|
|
1362
1752
|
...stylesOf(route.id),
|
|
@@ -1367,8 +1757,18 @@ export function createPageRequestExecutor(options) {
|
|
|
1367
1757
|
...(nonce === undefined ? {} : { nonce }),
|
|
1368
1758
|
...cspOption,
|
|
1369
1759
|
...titleOption,
|
|
1370
|
-
|
|
1760
|
+
...swapOption(c.req),
|
|
1761
|
+
...slotsFor(route.layoutIds, route.id),
|
|
1762
|
+
};
|
|
1763
|
+
if (mod.islandScripts !== undefined)
|
|
1764
|
+
page.islandScripts = mod.islandScripts;
|
|
1765
|
+
return renderPageResult(page);
|
|
1371
1766
|
}),
|
|
1767
|
+
matchRoute: (path) => {
|
|
1768
|
+
const matched = matchManifestRoute(path);
|
|
1769
|
+
const route = matched === null ? undefined : routeById.get(matched.routeId);
|
|
1770
|
+
return route === undefined ? null : { routeId: route.id, layoutIds: route.layoutIds };
|
|
1771
|
+
},
|
|
1372
1772
|
fallback: withResponseControls(async (c, controls) => {
|
|
1373
1773
|
const match = matchNotFoundScope?.(pathOf(c.req)) ?? null;
|
|
1374
1774
|
const target = match === null ? undefined : notFoundTargets[Number(match.routeId)];
|
|
@@ -1394,6 +1794,7 @@ export function createPageRequestExecutor(options) {
|
|
|
1394
1794
|
draft,
|
|
1395
1795
|
search: loaderSearch(mod.searchSchema, c.req),
|
|
1396
1796
|
set: controls.scope(PAGE_SCOPE),
|
|
1797
|
+
live: NO_LIVE,
|
|
1397
1798
|
};
|
|
1398
1799
|
if (target.route.middlewareIds !== undefined) {
|
|
1399
1800
|
await runMiddleware(target.route, ctx, controls);
|