@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
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shells and shared hole frames in a store shared by processes (Workers KV, Redis): a second level
|
|
3
|
+
* behind the in-process map. Whoever can write the store could put script into every visitor's page,
|
|
4
|
+
* so each entry is signed with the app's secret over its key, deployment and contents; anything that
|
|
5
|
+
* fails the check is a miss.
|
|
6
|
+
*/
|
|
7
|
+
import type { CachedResponse, CacheStore } from "../../isr.ts"
|
|
8
|
+
import { DATE_TAG } from "../revive-dates.ts"
|
|
9
|
+
import { storeSigner } from "../store-signature.ts"
|
|
10
|
+
import { wireDate } from "../wire-date.ts"
|
|
11
|
+
|
|
12
|
+
/** A shell or a shared hole's frame as the shared store holds it: everything a process needs to
|
|
13
|
+
* serve it. */
|
|
14
|
+
export interface StoredEntry {
|
|
15
|
+
readonly routeId: string
|
|
16
|
+
/** A shell's document up to the request script's end, with room for the token at `tokenAt`
|
|
17
|
+
* (bytes); or a hole's frame. */
|
|
18
|
+
readonly html: string
|
|
19
|
+
readonly tokenAt: number
|
|
20
|
+
readonly data: unknown
|
|
21
|
+
readonly builtAt: number
|
|
22
|
+
readonly tags: readonly string[]
|
|
23
|
+
/** A shared hole's live keys. */
|
|
24
|
+
readonly keys?: readonly string[]
|
|
25
|
+
/** The shell loader's `notFound()`. */
|
|
26
|
+
readonly notFound: boolean
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface SharedShellStore {
|
|
30
|
+
get(key: string): Promise<StoredEntry | undefined>
|
|
31
|
+
/** Skipped by the store when the key or one of its tags was purged after `fence`. */
|
|
32
|
+
set(
|
|
33
|
+
key: string,
|
|
34
|
+
entry: StoredEntry,
|
|
35
|
+
keepSeconds: number,
|
|
36
|
+
fence: number | undefined,
|
|
37
|
+
): Promise<void>
|
|
38
|
+
fence(): Promise<number | undefined>
|
|
39
|
+
/** Absent when the store cannot drop entries by tag. */
|
|
40
|
+
readonly invalidateTag: ((tag: string) => Promise<void>) | undefined
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const MAC_HEADER = "x-nifra-ppr-mac"
|
|
44
|
+
|
|
45
|
+
const isStrings = (value: unknown): value is readonly string[] =>
|
|
46
|
+
Array.isArray(value) && value.every((item) => typeof item === "string")
|
|
47
|
+
|
|
48
|
+
const field = (value: object, name: string): unknown => Reflect.get(value, name)
|
|
49
|
+
|
|
50
|
+
const isStoredEntry = (value: unknown): value is StoredEntry => {
|
|
51
|
+
if (typeof value !== "object" || value === null) return false
|
|
52
|
+
const tokenAt = field(value, "tokenAt")
|
|
53
|
+
const keys = field(value, "keys")
|
|
54
|
+
return (
|
|
55
|
+
typeof field(value, "routeId") === "string" &&
|
|
56
|
+
typeof field(value, "html") === "string" &&
|
|
57
|
+
typeof tokenAt === "number" &&
|
|
58
|
+
Number.isSafeInteger(tokenAt) &&
|
|
59
|
+
typeof field(value, "builtAt") === "number" &&
|
|
60
|
+
isStrings(field(value, "tags")) &&
|
|
61
|
+
(keys === undefined || isStrings(keys)) &&
|
|
62
|
+
typeof field(value, "notFound") === "boolean"
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Read and write signed deployment-scoped PPR entries, treating malformed data as cache misses. */
|
|
67
|
+
export function sharedShellStore(
|
|
68
|
+
store: CacheStore,
|
|
69
|
+
secret: string,
|
|
70
|
+
deployment: string,
|
|
71
|
+
): SharedShellStore {
|
|
72
|
+
const signer = storeSigner(secret)
|
|
73
|
+
const invalidateTag = store.invalidateTag
|
|
74
|
+
return {
|
|
75
|
+
async get(entryKey) {
|
|
76
|
+
const cached = await store.get(entryKey)
|
|
77
|
+
if (cached === undefined) return undefined
|
|
78
|
+
// One part, where ISR signs two: under a shared secret neither entry verifies as the other.
|
|
79
|
+
if (!(await signer.verify([cached.body], cached.headers[MAC_HEADER]))) {
|
|
80
|
+
console.error("[nifra/web] ppr: a shared store entry failed its signature check", {
|
|
81
|
+
key: entryKey,
|
|
82
|
+
})
|
|
83
|
+
return undefined
|
|
84
|
+
}
|
|
85
|
+
let payload: unknown
|
|
86
|
+
try {
|
|
87
|
+
// Match page-data revival, but keep the server's tagged toJSON for subsequent responses.
|
|
88
|
+
// JSON.parse defines own properties (including __proto__) without invoking setters.
|
|
89
|
+
payload = JSON.parse(cached.body, (_key, value: unknown) => {
|
|
90
|
+
if (typeof value !== "object" || value === null) return value
|
|
91
|
+
const tagged: unknown = Reflect.get(value, DATE_TAG)
|
|
92
|
+
if (typeof tagged !== "string" || Object.keys(value).length !== 1) return value
|
|
93
|
+
const time = Date.parse(tagged)
|
|
94
|
+
// An invalid wireDate would throw later from toJSON, outside this cache-miss boundary.
|
|
95
|
+
if (!Number.isFinite(time)) throw new RangeError("invalid cached date tag")
|
|
96
|
+
return wireDate(time)
|
|
97
|
+
})
|
|
98
|
+
} catch {
|
|
99
|
+
return undefined
|
|
100
|
+
}
|
|
101
|
+
if (typeof payload !== "object" || payload === null) return undefined
|
|
102
|
+
// The key and deployment are signed too, so an entry copied to another key or kept from
|
|
103
|
+
// another deployment never verifies as this one.
|
|
104
|
+
if (
|
|
105
|
+
field(payload, "v") !== 1 ||
|
|
106
|
+
field(payload, "key") !== entryKey ||
|
|
107
|
+
field(payload, "deployment") !== deployment
|
|
108
|
+
) {
|
|
109
|
+
return undefined
|
|
110
|
+
}
|
|
111
|
+
const entry = field(payload, "entry")
|
|
112
|
+
return isStoredEntry(entry) ? entry : undefined
|
|
113
|
+
},
|
|
114
|
+
async set(entryKey, entry, keepSeconds, fence) {
|
|
115
|
+
const body = JSON.stringify({ v: 1, key: entryKey, deployment, entry })
|
|
116
|
+
const mac = await signer.sign([body])
|
|
117
|
+
const value: CachedResponse = {
|
|
118
|
+
body,
|
|
119
|
+
status: entry.notFound ? 404 : 200,
|
|
120
|
+
headers: { [MAC_HEADER]: mac },
|
|
121
|
+
storedAt: entry.builtAt,
|
|
122
|
+
revalidate: keepSeconds * 1000,
|
|
123
|
+
tags: entry.tags,
|
|
124
|
+
fence,
|
|
125
|
+
}
|
|
126
|
+
await store.set(entryKey, value)
|
|
127
|
+
},
|
|
128
|
+
async fence() {
|
|
129
|
+
return store.fence === undefined ? undefined : await store.fence()
|
|
130
|
+
},
|
|
131
|
+
invalidateTag:
|
|
132
|
+
invalidateTag === undefined ? undefined : (tag) => invalidateTag.call(store, tag),
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* A short, stable digest of `text` (FNV-1a, 64 bits as hex). It names a deployment inside cache keys;
|
|
138
|
+
* nothing an attacker controls goes into it, so it needs no collision resistance.
|
|
139
|
+
*/
|
|
140
|
+
export function digest(text: string): string {
|
|
141
|
+
let high = 0xcbf29ce4
|
|
142
|
+
let low = 0x84222325
|
|
143
|
+
for (let at = 0; at < text.length; at++) {
|
|
144
|
+
low = (low ^ text.charCodeAt(at)) >>> 0
|
|
145
|
+
// Multiply the 64-bit value by the FNV prime 0x100000001b3 in two 32-bit halves.
|
|
146
|
+
const lowProduct = low * 0x1b3
|
|
147
|
+
const carry = Math.floor(lowProduct / 0x100000000)
|
|
148
|
+
high = (high * 0x1b3 + low * 0x100 + carry) >>> 0
|
|
149
|
+
low = lowProduct >>> 0
|
|
150
|
+
}
|
|
151
|
+
return high.toString(16).padStart(8, "0") + low.toString(16).padStart(8, "0")
|
|
152
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { pathnameOf } from "@nifrajs/core/server"
|
|
2
2
|
import { isDraftEnabled } from "../draft.ts"
|
|
3
|
+
import { SWAP_HEADER } from "../render-seam.ts"
|
|
3
4
|
import { DATA_HEADER } from "../router.ts"
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -21,10 +22,11 @@ const REPLAYED = [
|
|
|
21
22
|
"content-language",
|
|
22
23
|
"content-security-policy",
|
|
23
24
|
"content-security-policy-report-only",
|
|
25
|
+
"vary",
|
|
24
26
|
]
|
|
25
|
-
// Vary values a file still answers correctly: compression is negotiated by the host, and a data
|
|
26
|
-
// never reaches the file.
|
|
27
|
-
const STATIC_VARY = new Set(["accept-encoding", DATA_HEADER])
|
|
27
|
+
// Vary values a file still answers correctly: compression is negotiated by the host, and a data or
|
|
28
|
+
// slot-swap request never reaches the file.
|
|
29
|
+
const STATIC_VARY = new Set(["accept-encoding", DATA_HEADER, SWAP_HEADER])
|
|
28
30
|
|
|
29
31
|
/**
|
|
30
32
|
* The headers a self-hosted server replays with a prerendered page, or `undefined` when its build-time
|
|
@@ -84,7 +86,7 @@ export function servablePrerenderedPages(
|
|
|
84
86
|
/**
|
|
85
87
|
* Wrap a page route's GET handler so a plain document request for a prerendered path is answered from
|
|
86
88
|
* its file. Anything a file cannot answer the way a render would renders on demand: a query string, a
|
|
87
|
-
* navigation data or
|
|
89
|
+
* navigation data, component or slot-swap request, a draft-mode visitor, or a file the reader cannot return.
|
|
88
90
|
*/
|
|
89
91
|
export function servePrerenderedPages(
|
|
90
92
|
prerendered: PrerenderedPages,
|
|
@@ -102,6 +104,7 @@ export function servePrerenderedPages(
|
|
|
102
104
|
req.url.includes("?") ||
|
|
103
105
|
req.headers.has(DATA_HEADER) ||
|
|
104
106
|
req.headers.has("x-nifra-component") ||
|
|
107
|
+
req.headers.has(SWAP_HEADER) ||
|
|
105
108
|
(draftSecret !== undefined && (await isDraftEnabled(req, draftSecret)))
|
|
106
109
|
) {
|
|
107
110
|
return render(c)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a client navigation's page swap reaches the screen. The router loads a page first and hands only
|
|
3
|
+
* the swap here, so the history layer can wrap the swap alone in a view transition rather than the
|
|
4
|
+
* whole load. Module-scoped: one app per page; unset on the server and without `installHistory`.
|
|
5
|
+
*/
|
|
6
|
+
export type Presenter = (swap: () => void) => Promise<void>
|
|
7
|
+
|
|
8
|
+
let presenter: Presenter | undefined
|
|
9
|
+
|
|
10
|
+
/** Set (or clear, with `undefined`) the presenter - called by `installHistory`. */
|
|
11
|
+
export function setPresenter(next: Presenter | undefined): void {
|
|
12
|
+
presenter = next
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Run `swap` through the presenter, or at once when none is set. */
|
|
16
|
+
export function present(swap: () => void): Promise<void> | undefined {
|
|
17
|
+
if (presenter !== undefined) return presenter(swap)
|
|
18
|
+
swap()
|
|
19
|
+
return undefined
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The digest a live load gives each granted key for query hooks: HMAC-SHA-256 under a salt fresh per
|
|
3
|
+
* load, the first 16 bytes in base64url. A page's queries name the keys they read and find the load's
|
|
4
|
+
* tag for each one without the load ever sending key text. Shared by the server and the browser.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const TEXT = new TextEncoder()
|
|
8
|
+
const DIGEST_BYTES = 16
|
|
9
|
+
const SALT_BYTES = 16
|
|
10
|
+
|
|
11
|
+
export function querySalt(): string {
|
|
12
|
+
return base64url(crypto.getRandomValues(new Uint8Array(SALT_BYTES)))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Digests keys under one salt, importing the salt once. */
|
|
16
|
+
export async function queryDigester(salt: string): Promise<(key: string) => Promise<string>> {
|
|
17
|
+
const secret = await crypto.subtle.importKey(
|
|
18
|
+
"raw",
|
|
19
|
+
TEXT.encode(salt),
|
|
20
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
21
|
+
false,
|
|
22
|
+
["sign"],
|
|
23
|
+
)
|
|
24
|
+
return async (key) =>
|
|
25
|
+
base64url(
|
|
26
|
+
new Uint8Array(await crypto.subtle.sign("HMAC", secret, TEXT.encode(key)), 0, DIGEST_BYTES),
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function base64url(bytes: Uint8Array): string {
|
|
31
|
+
let binary = ""
|
|
32
|
+
for (const byte of bytes) binary += String.fromCharCode(byte)
|
|
33
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "")
|
|
34
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { QueryClient, QueryState } from "../query.ts"
|
|
1
|
+
import type { QueryClient, QueryHandle, QueryState } from "../query.ts"
|
|
2
2
|
import { createQueryClient } from "../query.ts"
|
|
3
3
|
|
|
4
4
|
/** Stable idle state shared by every framework query binding. */
|
|
@@ -23,6 +23,19 @@ export function getQueryClientSingleton(): QueryClient | undefined {
|
|
|
23
23
|
return singleton
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export const noop = (): void => {}
|
|
27
|
+
|
|
28
|
+
/** Stable no-op subscription for a binding with no client (server, pre-hydration). */
|
|
29
|
+
export const noopSubscribe = (): (() => void) => noop
|
|
30
|
+
|
|
31
|
+
/** A binding's fetch on mount. A failed fetch shows as the query's `error`, so its promise is let go. */
|
|
32
|
+
export const fetchOnMount = (handle: QueryHandle<unknown> | undefined): (() => void) =>
|
|
33
|
+
handle === undefined
|
|
34
|
+
? noop
|
|
35
|
+
: () => {
|
|
36
|
+
handle.fetch().catch(noop)
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
/** Create the refetch fallback used when a binding has no client-side query cache. */
|
|
27
40
|
export function createNoClientRefetch<T>(tag: string, operation: string): () => Promise<T> {
|
|
28
41
|
return async () => {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a query client tells the live client. `@nifrajs/web/live-client` installs the seam; a page
|
|
3
|
+
* without live refresh never does, so its queries keep no live state and ship none of it.
|
|
4
|
+
*/
|
|
5
|
+
import type { QueryClient } from "../query.ts"
|
|
6
|
+
|
|
7
|
+
export interface LiveQuery {
|
|
8
|
+
/** The live keys its data depends on, as the page's loaders declare them. */
|
|
9
|
+
keys(): readonly string[]
|
|
10
|
+
/** The {@link QuerySeam.tick} its data was asked for at: the start of the fetch in flight, else of
|
|
11
|
+
* the fetch that produced it. */
|
|
12
|
+
tick(): number
|
|
13
|
+
/** Drop its data's freshness and refetch, superseding a fetch in flight. */
|
|
14
|
+
refresh(): void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface QuerySeam {
|
|
18
|
+
/** The live tick now, read as each fetch starts. */
|
|
19
|
+
tick(): number
|
|
20
|
+
/** A query was mounted or unmounted; only a mounted one with live keys is watched. */
|
|
21
|
+
track(query: LiveQuery, mounted: boolean): void
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// On the global, so a query engine and a live client from two copies of the package still meet.
|
|
25
|
+
const SEAM = Symbol.for("nifra.web.querySeam")
|
|
26
|
+
const CLIENTS = Symbol.for("nifra.web.queryClients")
|
|
27
|
+
|
|
28
|
+
export const querySeam = (): QuerySeam | undefined => Reflect.get(globalThis, SEAM)
|
|
29
|
+
|
|
30
|
+
export function installQuerySeam(seam: QuerySeam): void {
|
|
31
|
+
if (querySeam() === undefined) Reflect.set(globalThis, SEAM, seam)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The browser query clients the page made, held weakly: a viewer switch clears each one still alive,
|
|
36
|
+
* whether it was made before or after the live client loaded.
|
|
37
|
+
*/
|
|
38
|
+
export const queryClients = (): readonly WeakRef<QueryClient>[] =>
|
|
39
|
+
Reflect.get(globalThis, CLIENTS) ?? []
|
|
40
|
+
|
|
41
|
+
export function adoptClient(client: QueryClient): void {
|
|
42
|
+
// A server builds a client per request; none of them outlives it or sees a viewer switch.
|
|
43
|
+
if (typeof Reflect.get(globalThis, "window") === "undefined") return
|
|
44
|
+
// Each new client sheds the ones the page let go, so the list never outgrows the live clients.
|
|
45
|
+
const clients = queryClients().filter((ref) => ref.deref() !== undefined)
|
|
46
|
+
clients.push(new WeakRef(client))
|
|
47
|
+
Reflect.set(globalThis, CLIENTS, clients)
|
|
48
|
+
}
|