@nifrajs/web 5.5.0 → 5.6.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 +162 -0
- 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 +9 -0
- package/dist/build.js.map +1 -1
- package/dist/client.d.ts +2 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +140 -12
- 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 +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- 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 +65 -8
- 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 +179 -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 +96 -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 +14 -1
- package/dist/internal/page-execution.d.ts.map +1 -1
- package/dist/internal/page-execution.js +415 -31
- package/dist/internal/page-execution.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 +32 -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 +1407 -0
- package/dist/internal/ppr/server.js.map +1 -0
- package/dist/internal/ppr/shell-store.d.ts +38 -0
- package/dist/internal/ppr/shell-store.d.ts.map +1 -0
- package/dist/internal/ppr/shell-store.js +90 -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/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 +28 -1
- package/dist/internal/render-document.d.ts.map +1 -1
- package/dist/internal/render-document.js +83 -18
- 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/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 +25 -0
- package/dist/internal/web-app.d.ts.map +1 -1
- package/dist/internal/web-app.js +78 -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 +1069 -0
- package/dist/keep-alive.js.map +1 -0
- package/dist/live/bus.d.ts +56 -0
- package/dist/live/bus.d.ts.map +1 -0
- package/dist/live/bus.js +32 -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 +181 -0
- package/dist/live/hub.d.ts.map +1 -0
- package/dist/live/hub.js +539 -0
- package/dist/live/hub.js.map +1 -0
- package/dist/live/keyring.d.ts +87 -0
- package/dist/live/keyring.d.ts.map +1 -0
- package/dist/live/keyring.js +260 -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 +840 -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 +48 -0
- package/dist/live-redis.d.ts.map +1 -0
- package/dist/live-redis.js +201 -0
- package/dist/live-redis.js.map +1 -0
- package/dist/live.d.ts +94 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +869 -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 +30 -0
- package/dist/render-seam.d.ts.map +1 -1
- package/dist/render-seam.js +5 -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 +374 -99
- 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/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 +86 -28
- 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/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 +19 -1
- package/src/client.ts +147 -10
- 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 +19 -0
- package/src/internal/cdn/cloudflare.ts +2 -1
- package/src/internal/certified-components.ts +1 -1
- package/src/internal/codegen.ts +87 -8
- package/src/internal/dev-websocket.ts +230 -0
- package/src/internal/hole-runtime.ts +286 -0
- package/src/internal/identity-epoch.ts +235 -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 +106 -0
- package/src/internal/live-queries.ts +60 -0
- package/src/internal/page-events.ts +27 -0
- package/src/internal/page-execution.ts +579 -40
- 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 +36 -0
- package/src/internal/ppr/server.ts +1764 -0
- package/src/internal/ppr/shell-store.ts +139 -0
- package/src/internal/prerendered-pages.ts +7 -4
- 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 +149 -22
- 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/store-signature.ts +149 -0
- package/src/internal/vite-plugin-compat.ts +2 -2
- package/src/internal/web-app.ts +121 -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 +1315 -0
- package/src/live/bus.ts +77 -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 +615 -0
- package/src/live/keyring.ts +379 -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 +973 -0
- package/src/live-hub.ts +658 -0
- package/src/live-redis.ts +259 -0
- package/src/live.ts +1096 -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 +35 -0
- package/src/route-types.ts +3 -1
- package/src/router.ts +494 -101
- package/src/server-components/build.ts +9 -3
- package/src/server-components/client.ts +89 -5
- 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 +112 -30
- package/src/server-components/state.ts +66 -44
- package/src/server-components/types.ts +16 -0
- 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
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { onPageRelease, PAGE_HIDE_EVENT, PAGE_SHOW_EVENT } from "./page-events.js";
|
|
2
|
+
/** The error slot a failed, timed-out or refused hole shows. Constant: no thrown message reaches it. */
|
|
3
|
+
export const HOLE_ERROR_HTML = '<p data-nifra-hole-error="">This section is unavailable.</p>';
|
|
4
|
+
const ERROR_FRAME = { v: 1, error: true, html: HOLE_ERROR_HTML };
|
|
5
|
+
/** The runtime the shell's inline script defines, when this document has one. */
|
|
6
|
+
const pprRuntime = () => {
|
|
7
|
+
const runtime = Reflect.get(globalThis, "__nifraPpr");
|
|
8
|
+
return typeof runtime === "function" &&
|
|
9
|
+
"get" in runtime &&
|
|
10
|
+
"subscribe" in runtime &&
|
|
11
|
+
"put" in runtime
|
|
12
|
+
? // biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: the shell's constant inline runtime defines exactly this shape.
|
|
13
|
+
runtime
|
|
14
|
+
: undefined;
|
|
15
|
+
};
|
|
16
|
+
let components;
|
|
17
|
+
/** What `holeComponents` registers; `undefined` forgets it. */
|
|
18
|
+
export function setHoleComponents(next) {
|
|
19
|
+
components = next;
|
|
20
|
+
}
|
|
21
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
22
|
+
/** A fill the server deferred: the NDJSON stream settles its promise. */
|
|
23
|
+
const settledFill = (fill) => isRecord(fill) && fill.__nifra_deferred === true && fill.promise instanceof Promise
|
|
24
|
+
? fill.promise
|
|
25
|
+
: Promise.resolve(fill);
|
|
26
|
+
/**
|
|
27
|
+
* What a host renders with: a blocking render's settled fill puts the server's HTML in it, which a
|
|
28
|
+
* crawler reads with no script; any other state leaves it empty. A host reads it once, so no later
|
|
29
|
+
* render changes what the runtime put there.
|
|
30
|
+
*/
|
|
31
|
+
export const initialHtml = (fill) => isRecord(fill) && fill.__nifra_deferred !== true && typeof fill.html === "string" ? fill.html : "";
|
|
32
|
+
/** The record of the server component a fill shows, its HTML put back, not yet checked. */
|
|
33
|
+
const recordOf = (fill) => isRecord(fill.component) && typeof fill.html === "string"
|
|
34
|
+
? { ...fill.component, html: fill.html }
|
|
35
|
+
: undefined;
|
|
36
|
+
/** The error slot, built without HTML parsing, for a document with no runtime to put it. */
|
|
37
|
+
const errorSlot = (host) => {
|
|
38
|
+
const slot = host.ownerDocument.createElement("p");
|
|
39
|
+
slot.setAttribute("data-nifra-hole-error", "");
|
|
40
|
+
slot.textContent = "This section is unavailable.";
|
|
41
|
+
host.replaceChildren(slot);
|
|
42
|
+
host.setAttribute("data-nifra-hole-error", "");
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* The islands of the server component in `host`: hydrated over the server's HTML, or with `fresh`,
|
|
46
|
+
* put into the host from the record. `failed` runs when they cannot mount, as when the record fails
|
|
47
|
+
* the protocol check.
|
|
48
|
+
*/
|
|
49
|
+
function componentRoot(host, unchecked, fresh, failed) {
|
|
50
|
+
const registered = components;
|
|
51
|
+
let current = true;
|
|
52
|
+
const valid = () => current;
|
|
53
|
+
const mounted = (async () => {
|
|
54
|
+
if (registered === undefined) {
|
|
55
|
+
throw new Error("[nifra/web] ppr: a hole shows a server component, but no holeComponents client");
|
|
56
|
+
}
|
|
57
|
+
const { client } = registered;
|
|
58
|
+
const record = registered.record(unchecked);
|
|
59
|
+
const mount = fresh ? client.create : client.hydrate;
|
|
60
|
+
if (mount === undefined)
|
|
61
|
+
throw new Error("[nifra/web] ppr: the component client cannot create");
|
|
62
|
+
const prepared = await client.prepare(record, valid, host, { records: [record] });
|
|
63
|
+
if (!current)
|
|
64
|
+
return undefined;
|
|
65
|
+
const root = await mount.call(client, host, record, prepared, valid);
|
|
66
|
+
if (!current) {
|
|
67
|
+
await root.dispose();
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
host.setAttribute("aria-busy", "false");
|
|
71
|
+
return root;
|
|
72
|
+
})().catch((error) => {
|
|
73
|
+
if (current) {
|
|
74
|
+
console.error("[nifra/web] ppr: a server component hole's islands did not mount", error);
|
|
75
|
+
failed();
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
update: () => false,
|
|
81
|
+
dispose() {
|
|
82
|
+
current = false;
|
|
83
|
+
return mounted.then((root) => root?.dispose());
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Drive the host of hole `name`. `hydrate` makes an interactive hole's root over the server HTML in
|
|
89
|
+
* `host`; a hole without one only ever shows server HTML, or a server component's.
|
|
90
|
+
*/
|
|
91
|
+
export function holeHost(name, host, hydrate) {
|
|
92
|
+
const runtime = pprRuntime();
|
|
93
|
+
let root;
|
|
94
|
+
let disposed = false;
|
|
95
|
+
let latest = 0;
|
|
96
|
+
// The kept page hiding the host, and what disposes the host if that page is dropped.
|
|
97
|
+
let hiddenBy;
|
|
98
|
+
let release;
|
|
99
|
+
const put = (frame) => {
|
|
100
|
+
if (runtime !== undefined)
|
|
101
|
+
runtime.put(name, frame, host);
|
|
102
|
+
else
|
|
103
|
+
errorSlot(host);
|
|
104
|
+
host.setAttribute("aria-busy", "false");
|
|
105
|
+
};
|
|
106
|
+
const showError = () => {
|
|
107
|
+
root = undefined;
|
|
108
|
+
put(ERROR_FRAME);
|
|
109
|
+
};
|
|
110
|
+
const start = (fill) => {
|
|
111
|
+
if (disposed || root !== undefined || fill.error)
|
|
112
|
+
return;
|
|
113
|
+
const record = recordOf({ component: fill.component, html: fill.html });
|
|
114
|
+
if (record !== undefined)
|
|
115
|
+
root = componentRoot(host, record, false, showError);
|
|
116
|
+
else if (hydrate !== undefined)
|
|
117
|
+
root = hydrate(host, fill.props);
|
|
118
|
+
};
|
|
119
|
+
const now = runtime?.get(name);
|
|
120
|
+
const unsubscribe = now === undefined && (hydrate !== undefined || components !== undefined)
|
|
121
|
+
? runtime?.subscribe(name, start)
|
|
122
|
+
: undefined;
|
|
123
|
+
if (now !== undefined)
|
|
124
|
+
start(now);
|
|
125
|
+
// A `keepAlive` page hidden behind another has been left: the document's holes stop filling and
|
|
126
|
+
// the ones still loading are cancelled, and a refill already on its way is dropped. The page's
|
|
127
|
+
// reload when it is shown again refills the host.
|
|
128
|
+
const hidden = (event) => {
|
|
129
|
+
if (!(event.target instanceof Element) || !event.target.contains(host))
|
|
130
|
+
return;
|
|
131
|
+
hiddenBy = event.target;
|
|
132
|
+
latest++;
|
|
133
|
+
runtime?.leave?.();
|
|
134
|
+
root?.hide?.(true);
|
|
135
|
+
};
|
|
136
|
+
const shown = (event) => {
|
|
137
|
+
if (event.target !== hiddenBy)
|
|
138
|
+
return;
|
|
139
|
+
hiddenBy = undefined;
|
|
140
|
+
root?.hide?.(false);
|
|
141
|
+
};
|
|
142
|
+
host.ownerDocument.addEventListener(PAGE_HIDE_EVENT, hidden);
|
|
143
|
+
host.ownerDocument.addEventListener(PAGE_SHOW_EVENT, shown);
|
|
144
|
+
const apply = (frame, mine, inPlace) => {
|
|
145
|
+
if (!isRecord(frame))
|
|
146
|
+
return;
|
|
147
|
+
const failed = frame.error === true;
|
|
148
|
+
const record = failed ? undefined : recordOf(frame);
|
|
149
|
+
if (!failed && record === undefined && root?.update(frame.props) === true) {
|
|
150
|
+
host.setAttribute("aria-busy", "false");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// An error shows the error slot, never content the action that reloaded it may have changed.
|
|
154
|
+
const gone = root?.dispose(false);
|
|
155
|
+
root = undefined;
|
|
156
|
+
const fill = () => {
|
|
157
|
+
if (disposed || mine !== latest)
|
|
158
|
+
return;
|
|
159
|
+
host.removeAttribute("data-nifra-hole-error");
|
|
160
|
+
if (record !== undefined) {
|
|
161
|
+
host.setAttribute("data-nifra-filled", "");
|
|
162
|
+
root = componentRoot(host, record, !inPlace, showError);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
put(frame);
|
|
166
|
+
if (!failed && hydrate !== undefined)
|
|
167
|
+
root = hydrate(host, frame.props);
|
|
168
|
+
};
|
|
169
|
+
if (gone instanceof Promise)
|
|
170
|
+
gone.then(fill, fill);
|
|
171
|
+
else
|
|
172
|
+
fill();
|
|
173
|
+
};
|
|
174
|
+
const dispose = () => {
|
|
175
|
+
disposed = true;
|
|
176
|
+
release?.();
|
|
177
|
+
release = undefined;
|
|
178
|
+
host.ownerDocument.removeEventListener(PAGE_HIDE_EVENT, hidden);
|
|
179
|
+
host.ownerDocument.removeEventListener(PAGE_SHOW_EVENT, shown);
|
|
180
|
+
unsubscribe?.();
|
|
181
|
+
Promise.resolve(root?.dispose(true)).catch(() => { });
|
|
182
|
+
root = undefined;
|
|
183
|
+
};
|
|
184
|
+
return {
|
|
185
|
+
refill(fill) {
|
|
186
|
+
// A blocking render's settled fill is the server HTML the host already shows.
|
|
187
|
+
const inPlace = latest === 0 && root === undefined && initialHtml(fill) !== "";
|
|
188
|
+
const mine = ++latest;
|
|
189
|
+
host.setAttribute("aria-busy", "true");
|
|
190
|
+
settledFill(fill).then((frame) => {
|
|
191
|
+
if (!disposed && mine === latest)
|
|
192
|
+
apply(frame, mine, inPlace);
|
|
193
|
+
}, () => {
|
|
194
|
+
if (!disposed && mine === latest)
|
|
195
|
+
apply(ERROR_FRAME, mine, false);
|
|
196
|
+
});
|
|
197
|
+
},
|
|
198
|
+
dispose,
|
|
199
|
+
park() {
|
|
200
|
+
if (disposed || hiddenBy === undefined)
|
|
201
|
+
return false;
|
|
202
|
+
release ??= onPageRelease(hiddenBy, dispose);
|
|
203
|
+
return true;
|
|
204
|
+
},
|
|
205
|
+
unpark() {
|
|
206
|
+
release?.();
|
|
207
|
+
release = undefined;
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=hole-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hole-runtime.js","sourceRoot":"","sources":["../../src/internal/hole-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server half of the identity epoch: a response that signs a visitor in or out also rotates the
|
|
3
|
+
* readable epoch cookie, so every tab drops the pages it kept alive for the previous visitor.
|
|
4
|
+
*
|
|
5
|
+
* A header-only hook reads each response's `Set-Cookie`: when an identity cookie's value differs from
|
|
6
|
+
* the request's, or the cookie is deleted, the response also sets a fresh epoch with the same lifetime,
|
|
7
|
+
* so the epoch expires with an idle session. A rolling session re-sending the same value with a new
|
|
8
|
+
* lifetime re-sends the epoch it holds with that lifetime, so the two keep expiring together.
|
|
9
|
+
*/
|
|
10
|
+
import { type CookieOptions } from "@nifrajs/core/server";
|
|
11
|
+
/** `createWebApp`'s `keepAlive` option: which cookies say who is signed in. */
|
|
12
|
+
export interface KeepAliveServerOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Cookies whose change means a different visitor, on top of the session cookies of
|
|
15
|
+
* `@nifrajs/auth`, Better Auth and Auth.js under their default names. Name a custom session cookie
|
|
16
|
+
* here, or kept pages survive a sign-in or sign-out through it.
|
|
17
|
+
*/
|
|
18
|
+
readonly identityCookies?: readonly string[];
|
|
19
|
+
/** `HttpOnly` cookies that say nothing about who is signed in; development stops asking about them. */
|
|
20
|
+
readonly ignoreCookies?: readonly string[];
|
|
21
|
+
}
|
|
22
|
+
/** The request and response a header hook sees. */
|
|
23
|
+
interface HeaderView {
|
|
24
|
+
get(name: string): string | null;
|
|
25
|
+
append(name: string, value: string): void;
|
|
26
|
+
}
|
|
27
|
+
interface RequestView {
|
|
28
|
+
readonly url: string;
|
|
29
|
+
header(name: string): string | null | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The response hook `createWebApp` installs for an app with a `keepAlive` route. With `development`,
|
|
33
|
+
* it also says once per cookie when an `HttpOnly` cookie it does not know changes.
|
|
34
|
+
*/
|
|
35
|
+
export declare function identityEpochHook(options: KeepAliveServerOptions, development: boolean): (headers: HeaderView, request: RequestView) => void;
|
|
36
|
+
/** The response-cookie surface {@link rotateIdentityEpoch} needs: nifra's handler context. */
|
|
37
|
+
export interface IdentityEpochContext {
|
|
38
|
+
readonly request: Request;
|
|
39
|
+
readonly set: {
|
|
40
|
+
cookie(name: string, value: string, options?: CookieOptions): void;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Rotate the identity epoch from a flow that changes who is signed in without changing a cookie
|
|
45
|
+
* `createWebApp` watches - say, a session kept server-side under a cookie whose value stays the
|
|
46
|
+
* same. Every tab then drops the pages it kept alive for the previous visitor.
|
|
47
|
+
*/
|
|
48
|
+
export declare function rotateIdentityEpoch(c: IdentityEpochContext): void;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=identity-epoch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-epoch.d.ts","sourceRoot":"","sources":["../../src/internal/identity-epoch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,KAAK,aAAa,EAAgB,MAAM,sBAAsB,CAAA;AAGvE,+EAA+E;AAC/E,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5C,uGAAuG;IACvG,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC3C;AAED,mDAAmD;AACnD,UAAU,UAAU;IAClB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAChC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1C;AACD,UAAU,WAAW;IACnB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAChD;AA8GD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,sBAAsB,EAC/B,WAAW,EAAE,OAAO,GACnB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,KAAK,IAAI,CA4DrD;AAED,8FAA8F;AAC9F,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,GAAG,EAAE;QAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;KAAE,CAAA;CACrF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAYjE"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server half of the identity epoch: a response that signs a visitor in or out also rotates the
|
|
3
|
+
* readable epoch cookie, so every tab drops the pages it kept alive for the previous visitor.
|
|
4
|
+
*
|
|
5
|
+
* A header-only hook reads each response's `Set-Cookie`: when an identity cookie's value differs from
|
|
6
|
+
* the request's, or the cookie is deleted, the response also sets a fresh epoch with the same lifetime,
|
|
7
|
+
* so the epoch expires with an idle session. A rolling session re-sending the same value with a new
|
|
8
|
+
* lifetime re-sends the epoch it holds with that lifetime, so the two keep expiring together.
|
|
9
|
+
*/
|
|
10
|
+
import { parseCookies } from "@nifrajs/core/server";
|
|
11
|
+
import { EPOCH_COOKIE, LOCAL_EPOCH_COOKIE } from "../identity.js";
|
|
12
|
+
// Session cookies by their default names, without a `__Secure-` / `__Host-` prefix.
|
|
13
|
+
const IDENTITY_DEFAULTS = [
|
|
14
|
+
"nifra_session",
|
|
15
|
+
"better-auth.session_token",
|
|
16
|
+
"authjs.session-token",
|
|
17
|
+
"next-auth.session-token",
|
|
18
|
+
];
|
|
19
|
+
// `HttpOnly` cookies the same integrations write that carry no identity of their own.
|
|
20
|
+
const IGNORE_DEFAULTS = [
|
|
21
|
+
"better-auth.session_data",
|
|
22
|
+
"better-auth.dont_remember",
|
|
23
|
+
"authjs.csrf-token",
|
|
24
|
+
"authjs.callback-url",
|
|
25
|
+
"authjs.pkce.code_verifier",
|
|
26
|
+
"authjs.state",
|
|
27
|
+
"authjs.nonce",
|
|
28
|
+
"next-auth.csrf-token",
|
|
29
|
+
"next-auth.callback-url",
|
|
30
|
+
"next-auth.pkce.code_verifier",
|
|
31
|
+
"next-auth.state",
|
|
32
|
+
"next-auth.nonce",
|
|
33
|
+
"__nifra_draft",
|
|
34
|
+
];
|
|
35
|
+
// `__Secure-a.0` and `__Host-a` are the cookie `a`: a prefix, then Auth.js's chunk index.
|
|
36
|
+
const baseName = (name) => name.replace(/^__(?:secure|host)-/i, "").replace(/\.\d+$/, "");
|
|
37
|
+
// Splits a `Set-Cookie` list joined with ", ": only a comma followed by `name=` starts a cookie, so
|
|
38
|
+
// the comma inside an `Expires` date stays where it is.
|
|
39
|
+
const SPLIT = /,\s*(?=[!#$%&'*+\-.^_`|~0-9A-Za-z]+=)/;
|
|
40
|
+
const parseSetCookies = (joined, now) => {
|
|
41
|
+
const cookies = [];
|
|
42
|
+
for (const line of joined.split(SPLIT)) {
|
|
43
|
+
const [pair = "", ...attributes] = line.split(";");
|
|
44
|
+
const at = pair.indexOf("=");
|
|
45
|
+
if (at <= 0)
|
|
46
|
+
continue;
|
|
47
|
+
let maxAge;
|
|
48
|
+
let expires;
|
|
49
|
+
let httpOnly = false;
|
|
50
|
+
let secure = false;
|
|
51
|
+
for (const attribute of attributes) {
|
|
52
|
+
const eq = attribute.indexOf("=");
|
|
53
|
+
const key = (eq === -1 ? attribute : attribute.slice(0, eq)).trim().toLowerCase();
|
|
54
|
+
const value = eq === -1 ? "" : attribute.slice(eq + 1).trim();
|
|
55
|
+
if (key === "max-age")
|
|
56
|
+
maxAge = value;
|
|
57
|
+
else if (key === "expires")
|
|
58
|
+
expires = value;
|
|
59
|
+
else if (key === "httponly")
|
|
60
|
+
httpOnly = true;
|
|
61
|
+
else if (key === "secure")
|
|
62
|
+
secure = true;
|
|
63
|
+
}
|
|
64
|
+
const name = pair.slice(0, at).trim();
|
|
65
|
+
const age = maxAge === undefined ? Number.NaN : Number(maxAge);
|
|
66
|
+
const until = expires === undefined ? Number.NaN : Date.parse(expires);
|
|
67
|
+
cookies.push({
|
|
68
|
+
name,
|
|
69
|
+
// Decoded as core decodes the request's cookies, so an encoded value compares equal to itself.
|
|
70
|
+
value: parseCookies(pair.trim())[name] ?? "",
|
|
71
|
+
deleted: age <= 0 || until <= now,
|
|
72
|
+
httpOnly,
|
|
73
|
+
secure: secure || /^__(?:secure|host)-/i.test(name),
|
|
74
|
+
maxAge,
|
|
75
|
+
expires,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return cookies;
|
|
79
|
+
};
|
|
80
|
+
const randomEpoch = () => {
|
|
81
|
+
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
82
|
+
let hex = "";
|
|
83
|
+
for (const byte of bytes)
|
|
84
|
+
hex += byte.toString(16).padStart(2, "0");
|
|
85
|
+
return hex;
|
|
86
|
+
};
|
|
87
|
+
const EPOCH_VALUE = /^[0-9a-f]{32}$/;
|
|
88
|
+
// A forwarded protocol only picks the cookie's name: a client that lies about it loses its own epoch.
|
|
89
|
+
// A browser sends a `__Host-` cookie only over https, so carrying one says so behind a TLS proxy that
|
|
90
|
+
// forwards nothing, and the client, which reads that one first, must see the new value there.
|
|
91
|
+
const servedOverHttps = (request, sent) => {
|
|
92
|
+
if (request.url.startsWith("https:") || sent[EPOCH_COOKIE] !== undefined)
|
|
93
|
+
return true;
|
|
94
|
+
const forwarded = request.header("x-forwarded-proto");
|
|
95
|
+
return forwarded?.split(",")[0]?.trim().toLowerCase() === "https";
|
|
96
|
+
};
|
|
97
|
+
const epochCookie = (secure, value, lifetime) => {
|
|
98
|
+
let cookie = `${secure ? EPOCH_COOKIE : LOCAL_EPOCH_COOKIE}=${value}; Path=/; SameSite=Lax`;
|
|
99
|
+
if (secure)
|
|
100
|
+
cookie += "; Secure";
|
|
101
|
+
if (lifetime.maxAge !== undefined)
|
|
102
|
+
cookie += `; Max-Age=${lifetime.maxAge}`;
|
|
103
|
+
if (lifetime.expires !== undefined)
|
|
104
|
+
cookie += `; Expires=${lifetime.expires}`;
|
|
105
|
+
return cookie;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* The response hook `createWebApp` installs for an app with a `keepAlive` route. With `development`,
|
|
109
|
+
* it also says once per cookie when an `HttpOnly` cookie it does not know changes.
|
|
110
|
+
*/
|
|
111
|
+
export function identityEpochHook(options, development) {
|
|
112
|
+
const identity = new Set([...IDENTITY_DEFAULTS, ...(options.identityCookies ?? []).map(baseName)]);
|
|
113
|
+
const ignored = new Set([...IGNORE_DEFAULTS, ...(options.ignoreCookies ?? []).map(baseName)]);
|
|
114
|
+
const reported = new Set();
|
|
115
|
+
return (headers, request) => {
|
|
116
|
+
const joined = headers.get("set-cookie");
|
|
117
|
+
if (joined === null || joined === "")
|
|
118
|
+
return;
|
|
119
|
+
const sent = parseCookies(request.header("cookie") ?? null);
|
|
120
|
+
let changed;
|
|
121
|
+
let renewed;
|
|
122
|
+
for (const cookie of parseSetCookies(joined, Date.now())) {
|
|
123
|
+
if (cookie.name === EPOCH_COOKIE || cookie.name === LOCAL_EPOCH_COOKIE)
|
|
124
|
+
return;
|
|
125
|
+
const now = cookie.deleted ? "" : cookie.value;
|
|
126
|
+
const base = baseName(cookie.name);
|
|
127
|
+
if (now === (sent[cookie.name] ?? "")) {
|
|
128
|
+
if (renewed === undefined &&
|
|
129
|
+
!cookie.deleted &&
|
|
130
|
+
(cookie.maxAge !== undefined || cookie.expires !== undefined) &&
|
|
131
|
+
identity.has(base))
|
|
132
|
+
renewed = cookie;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (identity.has(base)) {
|
|
136
|
+
// The first identity cookie still set gives the lifetime; a sign-out deletes them all.
|
|
137
|
+
if (changed === undefined || (changed.deleted && !cookie.deleted))
|
|
138
|
+
changed = cookie;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (!development || !cookie.httpOnly || ignored.has(base) || reported.has(base))
|
|
142
|
+
continue;
|
|
143
|
+
reported.add(base);
|
|
144
|
+
console.warn(`[nifra/web] NIFRA_KEEPALIVE_IDENTITY_COOKIE: this app keeps pages alive, and a response changed the HttpOnly cookie "${cookie.name}", which nifra does not know as a sign-in cookie. If it says who is signed in, add it to createWebApp({ keepAlive: { identityCookies: ["${base}"] } }) so a sign-in or sign-out drops the pages kept for the previous visitor; if it does not, add it to keepAlive.ignoreCookies.`);
|
|
145
|
+
}
|
|
146
|
+
if (changed !== undefined) {
|
|
147
|
+
headers.append("set-cookie", epochCookie(changed.secure || servedOverHttps(request, sent), randomEpoch(), changed.deleted ? {} : { maxAge: changed.maxAge, expires: changed.expires }));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (renewed === undefined)
|
|
151
|
+
return;
|
|
152
|
+
const lifetime = { maxAge: renewed.maxAge, expires: renewed.expires };
|
|
153
|
+
for (const secure of [true, false]) {
|
|
154
|
+
const held = sent[secure ? EPOCH_COOKIE : LOCAL_EPOCH_COOKIE];
|
|
155
|
+
if (held === undefined || !EPOCH_VALUE.test(held))
|
|
156
|
+
continue;
|
|
157
|
+
headers.append("set-cookie", epochCookie(secure, held, lifetime));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// An epoch that already expired, or was never set: a fresh one, so pages kept without one drop.
|
|
161
|
+
headers.append("set-cookie", epochCookie(renewed.secure || servedOverHttps(request, sent), randomEpoch(), lifetime));
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Rotate the identity epoch from a flow that changes who is signed in without changing a cookie
|
|
166
|
+
* `createWebApp` watches - say, a session kept server-side under a cookie whose value stays the
|
|
167
|
+
* same. Every tab then drops the pages it kept alive for the previous visitor.
|
|
168
|
+
*/
|
|
169
|
+
export function rotateIdentityEpoch(c) {
|
|
170
|
+
const request = c.request;
|
|
171
|
+
const secure = servedOverHttps({ url: request.url, header: (name) => request.headers.get(name) }, parseCookies(request.headers.get("cookie")));
|
|
172
|
+
c.set.cookie(secure ? EPOCH_COOKIE : LOCAL_EPOCH_COOKIE, randomEpoch(), {
|
|
173
|
+
path: "/",
|
|
174
|
+
sameSite: "lax",
|
|
175
|
+
secure,
|
|
176
|
+
httpOnly: false,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=identity-epoch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-epoch.js","sourceRoot":"","sources":["../../src/internal/identity-epoch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seam between `createWebApp` and a cache wrapper for an action's invalidation: types and one
|
|
3
|
+
* symbol, so an app pays for the pipeline only once something runs it.
|
|
4
|
+
*/
|
|
5
|
+
import type { RevalidateResult } from "./render-document.js";
|
|
6
|
+
export interface InvalidationOp {
|
|
7
|
+
/** Names the operation in logs; never key text. */
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly paths: readonly string[];
|
|
10
|
+
readonly tags: readonly string[];
|
|
11
|
+
readonly keys: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
/** What a `createWebApp` app hands a cache wrapper that owns its invalidation. */
|
|
14
|
+
export interface InvalidationHandoff {
|
|
15
|
+
/** The operation the action behind `request` recorded, once. */
|
|
16
|
+
take(request: Request): InvalidationOp | undefined;
|
|
17
|
+
/** The app's live publish, when it configures `live`. */
|
|
18
|
+
readonly publish: ((keys: readonly string[]) => Promise<void>) | undefined;
|
|
19
|
+
}
|
|
20
|
+
export declare const INVALIDATION: unique symbol;
|
|
21
|
+
/** The operation an action's `revalidate()` names: its paths, cache tags and live keys. */
|
|
22
|
+
export declare function invalidationOf(revalidation: RevalidateResult<unknown>): InvalidationOp;
|
|
23
|
+
//# sourceMappingURL=invalidation-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invalidation-contract.d.ts","sourceRoot":"","sources":["../../src/internal/invalidation-contract.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CACjC;AAED,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAAA;IAClD,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAA;CAC3E;AAED,eAAO,MAAM,YAAY,EAAE,OAAO,MAA6C,CAAA;AAE/E,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,YAAY,EAAE,gBAAgB,CAAC,OAAO,CAAC,GAAG,cAAc,CAStF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const INVALIDATION = Symbol.for("nifra.web.invalidation");
|
|
2
|
+
/** The operation an action's `revalidate()` names: its paths, cache tags and live keys. */
|
|
3
|
+
export function invalidationOf(revalidation) {
|
|
4
|
+
return {
|
|
5
|
+
id: crypto.randomUUID(),
|
|
6
|
+
paths: revalidation.__nifraRevalidate.filter((path) => typeof path === "string" && path.startsWith("/")),
|
|
7
|
+
tags: revalidation.__nifraInvalidate?.tags ?? [],
|
|
8
|
+
keys: revalidation.__nifraInvalidate?.keys ?? [],
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=invalidation-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invalidation-contract.js","sourceRoot":"","sources":["../../src/internal/invalidation-contract.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,MAAM,YAAY,GAAkB,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;AAE/E,2FAA2F;AAC3F,MAAM,UAAU,cAAc,CAAC,YAAuC;IACpE,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;QACvB,KAAK,EAAE,YAAY,CAAC,iBAAiB,CAAC,MAAM,CAC1C,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAC3D;QACD,IAAI,EAAE,YAAY,CAAC,iBAAiB,EAAE,IAAI,IAAI,EAAE;QAChD,IAAI,EAAE,YAAY,CAAC,iBAAiB,EAAE,IAAI,IAAI,EAAE;KACjD,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One invalidation pipeline for everything a write makes stale, in a fixed order: data caches (tags),
|
|
3
|
+
* then the page store (paths and tags), then the live publish (keys and tags), then the CDN. A failure
|
|
4
|
+
* in either cache stage stops before the publish: clients told to reload would read the stale data and
|
|
5
|
+
* move their watermarks past the change. Every stage is idempotent, so a retry repeats from the stage
|
|
6
|
+
* that failed.
|
|
7
|
+
*
|
|
8
|
+
* `withISR` owns the pipeline when it wraps the app; without it, `createWebApp` runs the publish
|
|
9
|
+
* stage alone. Never both.
|
|
10
|
+
*/
|
|
11
|
+
import type { CdnPurgeTarget, ISRPlatform } from "../isr.js";
|
|
12
|
+
import type { InvalidationOp } from "./invalidation-contract.js";
|
|
13
|
+
export type { InvalidationOp } from "./invalidation-contract.js";
|
|
14
|
+
export type InvalidationStage = "data" | "pages" | "publish" | "cdn";
|
|
15
|
+
export interface StageReport {
|
|
16
|
+
readonly stage: InvalidationStage;
|
|
17
|
+
readonly ok: boolean;
|
|
18
|
+
readonly retryable: boolean;
|
|
19
|
+
readonly error?: string;
|
|
20
|
+
/** The CDN took the purge but has not applied it yet (rate limit or retry). */
|
|
21
|
+
readonly queued?: true;
|
|
22
|
+
}
|
|
23
|
+
export interface InvalidationReport {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly ok: boolean;
|
|
26
|
+
readonly stages: readonly StageReport[];
|
|
27
|
+
}
|
|
28
|
+
/** What the pipeline calls on a page store: any {@link CacheStore} fits. */
|
|
29
|
+
export interface PagePurge {
|
|
30
|
+
delete(key: string): Promise<void>;
|
|
31
|
+
readonly invalidateTag?: ((tag: string) => Promise<void>) | undefined;
|
|
32
|
+
}
|
|
33
|
+
export interface InvalidationTargets {
|
|
34
|
+
readonly dataCaches?: readonly {
|
|
35
|
+
invalidateTag(tag: string): unknown;
|
|
36
|
+
}[] | undefined;
|
|
37
|
+
readonly store?: PagePurge | undefined;
|
|
38
|
+
/** The page store key of a path, as the cache wrapper computes it; `null` when never stored. */
|
|
39
|
+
readonly keyOf?: ((path: string, req: Request) => string | null) | undefined;
|
|
40
|
+
readonly publish?: ((keys: readonly string[]) => Promise<void>) | undefined;
|
|
41
|
+
readonly cdn?: CdnPurgeTarget | undefined;
|
|
42
|
+
}
|
|
43
|
+
export declare const INLINE_DEADLINE_MS = 2000;
|
|
44
|
+
/** Run the stages from `from` once. */
|
|
45
|
+
export declare function runInvalidation(op: InvalidationOp, targets: InvalidationTargets, req: Request, platform: ISRPlatform | undefined, from?: InvalidationStage): Promise<InvalidationReport>;
|
|
46
|
+
export interface SettleOptions {
|
|
47
|
+
readonly onError?: ((report: InvalidationReport) => void) | undefined;
|
|
48
|
+
/** Tests drive time; production waits on timers. */
|
|
49
|
+
readonly clock?: {
|
|
50
|
+
now(): number;
|
|
51
|
+
sleep(ms: number): Promise<void>;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Run the pipeline for a write; never throws and never changes the response. A retryable failure
|
|
56
|
+
* retries from the failed stage, under `waitUntil` when the platform has it, else inline until
|
|
57
|
+
* {@link INLINE_DEADLINE_MS}. A failure that remains is reported once.
|
|
58
|
+
*/
|
|
59
|
+
export declare function settleInvalidation(op: InvalidationOp, targets: InvalidationTargets, req: Request, platform: ISRPlatform | undefined, options?: SettleOptions): Promise<InvalidationReport>;
|
|
60
|
+
/** The default report: the operation id and the stage, never a path, tag or key. */
|
|
61
|
+
export declare function logInvalidation(report: InvalidationReport): void;
|
|
62
|
+
//# sourceMappingURL=invalidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invalidation.d.ts","sourceRoot":"","sources":["../../src/internal/invalidation.ts"],"names":[],"mappings":"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"}
|