@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
package/src/fn.ts
CHANGED
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
type StandardSchemaV1,
|
|
55
55
|
} from "@nifrajs/core/server"
|
|
56
56
|
import { guardChannel, outputGuard } from "./internal/output-guard.ts"
|
|
57
|
+
import { SERVER_FN_NAMESPACE } from "./internal/server-boundary.ts"
|
|
57
58
|
|
|
58
59
|
/** The URL prefix every mounted function lives under. Namespaced per mount, then by export name. */
|
|
59
60
|
export const SERVER_FN_PREFIX = "/_nifra/fn"
|
|
@@ -78,8 +79,9 @@ export interface ServerFnConfig<Input> {
|
|
|
78
79
|
|
|
79
80
|
/**
|
|
80
81
|
* A declared server function. Callable directly on the server (the same value your own server-side
|
|
81
|
-
* code can await);
|
|
82
|
-
*
|
|
82
|
+
* code can await); in a client build, this module becomes typed stubs that POST under its
|
|
83
|
+
* file's name (`todos.fn.ts` posts under `todos`), so {@link serverFunctions} must mount it
|
|
84
|
+
* under that name.
|
|
83
85
|
*
|
|
84
86
|
* This is the SERVER declaration type, so context is required. Client builds replace the module with
|
|
85
87
|
* a one-argument {@link ClientServerFn}; UI bindings accept either shape and adapt at that boundary.
|
|
@@ -123,8 +125,6 @@ export function serverFn<Input = void, Output = unknown>(
|
|
|
123
125
|
const isServerFn = (value: unknown): value is ServerFn<unknown, unknown> =>
|
|
124
126
|
typeof value === "function" && SERVER_FN in (value as object)
|
|
125
127
|
|
|
126
|
-
/** A namespace segment: lowercase, dot/dash separated. Constrained so a mount cannot invent a path. */
|
|
127
|
-
const NAMESPACE = /^[a-z0-9]+(?:[-.][a-z0-9]+)*$/
|
|
128
128
|
/** An export name that is safe in a URL path without escaping. */
|
|
129
129
|
const EXPORT_NAME = /^[A-Za-z_$][A-Za-z0-9_$]*$/
|
|
130
130
|
|
|
@@ -156,12 +156,13 @@ export type ServerFnModule = Readonly<Record<string, unknown>>
|
|
|
156
156
|
*
|
|
157
157
|
* The namespace is explicit rather than derived from the file path: a path-derived one would put the
|
|
158
158
|
* build machine's layout in a public URL, and this keeps the route readable in logs and greppable in
|
|
159
|
-
* the codebase.
|
|
159
|
+
* the codebase. The client build's stubs call the namespace named by the module's file (`todos.fn.ts`
|
|
160
|
+
* calls `todos`), so pass that same word here.
|
|
160
161
|
*
|
|
161
162
|
* Exports that are not server functions are ignored, so `export type` and helpers can live alongside.
|
|
162
163
|
*/
|
|
163
164
|
export function serverFunctions(namespace: string, module: ServerFnModule): IdentityPlugin {
|
|
164
|
-
if (!
|
|
165
|
+
if (!SERVER_FN_NAMESPACE.test(namespace)) {
|
|
165
166
|
throw new Error(
|
|
166
167
|
`[nifra/fn] invalid server-function namespace ${JSON.stringify(namespace)} - use lowercase dot/dash segments (it becomes a URL path).`,
|
|
167
168
|
)
|
|
@@ -213,5 +214,21 @@ export function serverFunctions(namespace: string, module: ServerFnModule): Iden
|
|
|
213
214
|
}
|
|
214
215
|
return app
|
|
215
216
|
}
|
|
216
|
-
|
|
217
|
+
// A plugin name per module: the same module mounted twice stays one mount, while a second module
|
|
218
|
+
// under a taken namespace mounts too, so its functions are served, or a name both modules export
|
|
219
|
+
// fails as a duplicate route instead of the second module silently answering nothing.
|
|
220
|
+
const indexes = MODULE_INDEXES.get(module) ?? new Map<string, number>()
|
|
221
|
+
MODULE_INDEXES.set(module, indexes)
|
|
222
|
+
let index = indexes.get(namespace)
|
|
223
|
+
if (index === undefined) {
|
|
224
|
+
index = NEXT_MODULE_INDEX.get(namespace) ?? 0
|
|
225
|
+
NEXT_MODULE_INDEX.set(namespace, index + 1)
|
|
226
|
+
indexes.set(namespace, index)
|
|
227
|
+
}
|
|
228
|
+
const suffix = index === 0 ? "" : `#${index + 1}`
|
|
229
|
+
return defineIdentityPlugin(`nifra:server-fn:${namespace}${suffix}`, apply)
|
|
217
230
|
}
|
|
231
|
+
|
|
232
|
+
// Weak, so a module an app no longer uses (a dev reload, a discarded test app) is not held here.
|
|
233
|
+
const MODULE_INDEXES = new WeakMap<ServerFnModule, Map<string, number>>()
|
|
234
|
+
const NEXT_MODULE_INDEX = new Map<string, number>()
|
package/src/fs.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* (and the rest of @nifrajs/web) stays fs-free + edge-portable: this runs at build/startup
|
|
4
4
|
* only. It scans a routes dir and feeds the pure `buildManifest`.
|
|
5
5
|
*/
|
|
6
|
-
import { readdirSync } from "node:fs"
|
|
6
|
+
import { readdirSync, readFileSync } from "node:fs"
|
|
7
7
|
import { join } from "node:path"
|
|
8
8
|
import {
|
|
9
9
|
buildManifest,
|
|
10
|
+
exportsKeepAlive,
|
|
10
11
|
isMiddlewareFile,
|
|
11
12
|
isRouteBackendFile,
|
|
12
13
|
type Manifest,
|
|
@@ -45,12 +46,25 @@ export function discoverRoutes(dir: string, options: DiscoverRoutesOptions = {})
|
|
|
45
46
|
)
|
|
46
47
|
const query = options.importQuery ? `?${options.importQuery}` : ""
|
|
47
48
|
const load = options.load
|
|
48
|
-
return buildManifest(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
//
|
|
54
|
-
|
|
49
|
+
return buildManifest(
|
|
50
|
+
files,
|
|
51
|
+
(file) =>
|
|
52
|
+
load === undefined
|
|
53
|
+
? () => import(`${dir}/${file}${query}`) as Promise<RouteModule>
|
|
54
|
+
: // No `importQuery` here: an injected loader owns its own invalidation (Vite's module graph
|
|
55
|
+
// re-evaluates on change), and appending a cache-buster would defeat it by minting a new
|
|
56
|
+
// module id per request.
|
|
57
|
+
() => load(join(dir, file)) as Promise<RouteModule>,
|
|
58
|
+
{ keepAlive: files.filter((file) => keepsAlive(join(dir, file))) },
|
|
55
59
|
)
|
|
56
60
|
}
|
|
61
|
+
|
|
62
|
+
const keepsAlive = (path: string): boolean => {
|
|
63
|
+
if (isRouteBackendFile(path) || path.slice(path.lastIndexOf("/") + 1).startsWith("_"))
|
|
64
|
+
return false
|
|
65
|
+
try {
|
|
66
|
+
return exportsKeepAlive(readFileSync(path, "utf8"))
|
|
67
|
+
} catch {
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/identity.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The identity epoch: a value the server rotates whenever a response signs a visitor in or out, so a
|
|
3
|
+
* page kept mounted for one visitor is never shown to the next. Browser-safe and free of module-level
|
|
4
|
+
* state, so a client bundle that never calls it carries none of it.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** The readable cookie holding the epoch on an `https:` origin. */
|
|
8
|
+
export const EPOCH_COOKIE = "__Host-nifra-epoch"
|
|
9
|
+
/** The same cookie on local `http:` dev, where a `__Host-` cookie cannot be set. */
|
|
10
|
+
export const LOCAL_EPOCH_COOKIE = "nifra-epoch"
|
|
11
|
+
/** The channel every tab of an origin hears a sign-in or sign-out on. */
|
|
12
|
+
export const IDENTITY_CHANNEL = "nifra-identity-v1"
|
|
13
|
+
|
|
14
|
+
type Listeners = Set<() => void>
|
|
15
|
+
|
|
16
|
+
// Looked up per call: a module-level `Symbol.for` would be code every client bundle keeps.
|
|
17
|
+
const listenersOf = (): Listeners => {
|
|
18
|
+
const key = Symbol.for("nifra.identity.listeners")
|
|
19
|
+
let listeners: unknown = Reflect.get(globalThis, key)
|
|
20
|
+
if (!(listeners instanceof Set)) {
|
|
21
|
+
listeners = new Set<() => void>()
|
|
22
|
+
Reflect.set(globalThis, key, listeners)
|
|
23
|
+
}
|
|
24
|
+
// biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: only this module writes the slot, always a set of listeners
|
|
25
|
+
return listeners as Listeners
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The epoch in a `document.cookie` string, or `""` when it carries none. */
|
|
29
|
+
export function epochOf(cookie: string): string {
|
|
30
|
+
let local = ""
|
|
31
|
+
for (const part of cookie.split(";")) {
|
|
32
|
+
const at = part.indexOf("=")
|
|
33
|
+
if (at === -1) continue
|
|
34
|
+
const name = part.slice(0, at).trim()
|
|
35
|
+
if (name === EPOCH_COOKIE) return part.slice(at + 1).trim()
|
|
36
|
+
if (name === LOCAL_EPOCH_COOKIE) local = part.slice(at + 1).trim()
|
|
37
|
+
}
|
|
38
|
+
return local
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Run `listener` when this document hears that the visitor changed; returns its removal. */
|
|
42
|
+
export function onIdentityChange(listener: () => void): () => void {
|
|
43
|
+
const listeners = listenersOf()
|
|
44
|
+
listeners.add(listener)
|
|
45
|
+
return () => {
|
|
46
|
+
listeners.delete(listener)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Tell this tab and every other tab of the origin that the visitor signed in or out. Call it at login
|
|
52
|
+
* and logout when identity lives in client storage (a bearer token) rather than in a cookie, which the
|
|
53
|
+
* server's epoch cookie already covers: every page kept alive for the previous visitor is dropped.
|
|
54
|
+
*/
|
|
55
|
+
export function identityChanged(): void {
|
|
56
|
+
for (const listener of [...listenersOf()]) listener()
|
|
57
|
+
if (typeof BroadcastChannel === "undefined") return
|
|
58
|
+
const channel = new BroadcastChannel(IDENTITY_CHANNEL)
|
|
59
|
+
channel.postMessage("changed")
|
|
60
|
+
channel.close()
|
|
61
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,9 @@ export {
|
|
|
29
29
|
type PendingBoundary,
|
|
30
30
|
resolveDynamicBoundaries,
|
|
31
31
|
resolveStaticBoundaries,
|
|
32
|
+
type SharedBoundary,
|
|
33
|
+
type SharedHoleCtx,
|
|
34
|
+
type ShellCtx,
|
|
32
35
|
type StaticBoundary,
|
|
33
36
|
type StaticBoundaryCache,
|
|
34
37
|
type StaticBoundaryImportEdge,
|
|
@@ -93,8 +96,15 @@ export {
|
|
|
93
96
|
generateClientEntry,
|
|
94
97
|
generateRouteSearchTypes,
|
|
95
98
|
generateServerManifest,
|
|
99
|
+
type LiveClientEntry,
|
|
96
100
|
} from "./internal/codegen.ts"
|
|
97
101
|
export { mergeHeads, resolveChainMeta, resolveMeta } from "./internal/head-merge.ts"
|
|
102
|
+
// The server half of the identity epoch that drops kept pages on a sign-in or sign-out.
|
|
103
|
+
export {
|
|
104
|
+
type IdentityEpochContext,
|
|
105
|
+
type KeepAliveServerOptions,
|
|
106
|
+
rotateIdentityEpoch,
|
|
107
|
+
} from "./internal/identity-epoch.ts"
|
|
98
108
|
export type { PrerenderedPages } from "./internal/prerendered-pages.ts"
|
|
99
109
|
export {
|
|
100
110
|
gone,
|
|
@@ -104,6 +114,7 @@ export {
|
|
|
104
114
|
type RenderedPage,
|
|
105
115
|
type RenderPageInput,
|
|
106
116
|
type RenderPageOptions,
|
|
117
|
+
type RevalidateOptions,
|
|
107
118
|
type RevalidateResult,
|
|
108
119
|
redirect,
|
|
109
120
|
renderPage,
|
|
@@ -163,6 +174,8 @@ export {
|
|
|
163
174
|
// File-based routing manifest - pure + fs-free. `discoverRoutes` (fs) lives in `@nifrajs/web/fs`.
|
|
164
175
|
export {
|
|
165
176
|
type Action,
|
|
177
|
+
type BoundaryLoaderEntry,
|
|
178
|
+
type BoundaryLoadersOf,
|
|
166
179
|
buildManifest,
|
|
167
180
|
type ClientAction,
|
|
168
181
|
type ClientActionArgs,
|
|
@@ -176,6 +189,7 @@ export {
|
|
|
176
189
|
filePathToPatterns,
|
|
177
190
|
type GetStaticPaths,
|
|
178
191
|
type InertScriptType,
|
|
192
|
+
type KeepAliveOptions,
|
|
179
193
|
type LayoutEntry,
|
|
180
194
|
type LinkDescriptor,
|
|
181
195
|
type Loader,
|
|
@@ -210,6 +224,7 @@ export {
|
|
|
210
224
|
type BlockerLocation,
|
|
211
225
|
type BlockerState,
|
|
212
226
|
type BrowserNavigate,
|
|
227
|
+
closeBoundary,
|
|
213
228
|
getBrowserNavigate,
|
|
214
229
|
IDLE_BLOCKER,
|
|
215
230
|
type NavigateFunction,
|
|
@@ -292,11 +307,15 @@ export {
|
|
|
292
307
|
createClientRouter,
|
|
293
308
|
createMatcher,
|
|
294
309
|
DATA_HEADER,
|
|
310
|
+
type DataText,
|
|
295
311
|
type Fetcher,
|
|
296
312
|
type FetcherState,
|
|
297
313
|
type FetchRouteData,
|
|
314
|
+
type Intercepted,
|
|
315
|
+
type KeptPage,
|
|
298
316
|
type MountRouterOptions,
|
|
299
317
|
NAV_FROM_HEADER,
|
|
318
|
+
PREFETCH_HEADER,
|
|
300
319
|
REDIRECT_HEADER,
|
|
301
320
|
RETAIN_HEADER,
|
|
302
321
|
REVALIDATE_HEADER,
|
|
@@ -32,7 +32,8 @@ export interface CloudflareZoneOptions {
|
|
|
32
32
|
/**
|
|
33
33
|
* A Cloudflare zone proxying the origin. HTML is only cached by a Cache Rule that makes it eligible,
|
|
34
34
|
* and the zone's cache ignores `Vary`: the rule must also bypass the cache when the request carries
|
|
35
|
-
* `x-nifra-data` (soft navigations fetch the page URL with
|
|
35
|
+
* `x-nifra-data` or `x-nifra-swap` (soft navigations and slot swaps fetch the page URL with those
|
|
36
|
+
* headers). `nifra cdn-check` tests all three.
|
|
36
37
|
*/
|
|
37
38
|
export function cloudflareZone(options: CloudflareZoneOptions): CdnProvider {
|
|
38
39
|
if (!/^[a-f0-9]{32}$/.test(options.zoneId)) {
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* guard and the consumer check read these; `component-certification.test.ts` holds the exact pins
|
|
4
4
|
* in every manifest that runs the pipeline to them, so a range bump cannot drift past the guard.
|
|
5
5
|
*/
|
|
6
|
-
export const CERTIFIED_COMPONENT_VITE = "8.
|
|
6
|
+
export const CERTIFIED_COMPONENT_VITE = "8.3.4"
|
|
7
7
|
export const CERTIFIED_COMPONENT_REACT = "19.3.1"
|
package/src/internal/codegen.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from "../render-seam.ts"
|
|
17
17
|
import { PRERENDERED_GLOBAL } from "../router.ts"
|
|
18
18
|
import { jsStringLiteral, jsValueLiteral } from "./js-string.ts"
|
|
19
|
+
import { keepAliveTable } from "./keep-alive-table.ts"
|
|
19
20
|
|
|
20
21
|
/** The refusal for a server build given no client entry, shared by the codegen and `buildServer`. */
|
|
21
22
|
export function missingClientEntry(clientEntry: unknown): TypeError {
|
|
@@ -53,6 +54,22 @@ export interface GenerateClientEntryOptions {
|
|
|
53
54
|
/** The build moved copy tables into per-locale chunks: the handover carries the chunk URLs, and a
|
|
54
55
|
* navigation loads the copy of the URL it goes to beside the route's code. */
|
|
55
56
|
readonly copyChunks?: boolean
|
|
57
|
+
/**
|
|
58
|
+
* The server runs `createWebApp({ live })`: route loads go through its live load endpoint and the
|
|
59
|
+
* entry keeps what is on screen fresh (`@nifrajs/web/live-client`). Absent, the entry is exactly the
|
|
60
|
+
* non-live one.
|
|
61
|
+
*/
|
|
62
|
+
readonly live?: LiveClientEntry | undefined
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// The router as the entry names it: in a keep-alive app, the keep-alive layer over `router`.
|
|
66
|
+
const keepAround = (keep: unknown, router: string): string =>
|
|
67
|
+
keep === undefined ? `const router = ${router}` : `const router = __keep.attach(${router})`
|
|
68
|
+
|
|
69
|
+
/** A client entry for a live server: `{}`, or the endpoints when the runtime moves them. */
|
|
70
|
+
export interface LiveClientEntry {
|
|
71
|
+
readonly path?: string
|
|
72
|
+
readonly loadPath?: string
|
|
56
73
|
}
|
|
57
74
|
|
|
58
75
|
/**
|
|
@@ -65,11 +82,31 @@ export interface GenerateClientEntryOptions {
|
|
|
65
82
|
* Bun has no `import.meta.glob`, so file-based routing needs this. Write the result to a file and
|
|
66
83
|
* bundle it with `buildClient` / `Bun.build` (+ the adapter's transform).
|
|
67
84
|
*/
|
|
85
|
+
/** The client modules whose package has a keep-alive mount beside them, at `<package>/keep-alive`. */
|
|
86
|
+
const KEEP_ALIVE_ADAPTERS: readonly string[] = [
|
|
87
|
+
"@nifrajs/web-react/client",
|
|
88
|
+
"@nifrajs/web-svelte/client",
|
|
89
|
+
"@nifrajs/web-preact/client",
|
|
90
|
+
"@nifrajs/web-solid/client",
|
|
91
|
+
"@nifrajs/web-vue/client",
|
|
92
|
+
]
|
|
93
|
+
|
|
68
94
|
export function generateClientEntry(
|
|
69
95
|
manifest: Manifest,
|
|
70
96
|
options: GenerateClientEntryOptions,
|
|
71
97
|
): string {
|
|
72
|
-
const {
|
|
98
|
+
const { resolve } = options
|
|
99
|
+
const keep = keepAliveTable(manifest)
|
|
100
|
+
if (keep !== undefined && !KEEP_ALIVE_ADAPTERS.includes(options.clientModule)) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`[nifra/web] ${keep.routes.map((id) => `"${id}"`).join(", ")} export keepAlive, which needs the React, Preact, Solid, Svelte or Vue adapter; this app's client module is ${jsStringLiteral(options.clientModule)}. Remove the keepAlive export or switch the adapter.`,
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
// A keep-alive app mounts through the adapter's keep-alive module, which re-exports its client.
|
|
106
|
+
const clientModule =
|
|
107
|
+
keep === undefined
|
|
108
|
+
? options.clientModule
|
|
109
|
+
: options.clientModule.replace(/\/client$/, "/keep-alive")
|
|
73
110
|
|
|
74
111
|
const loaderRows: string[] = []
|
|
75
112
|
const patternRows: string[] = []
|
|
@@ -165,6 +202,13 @@ export function generateClientEntry(
|
|
|
165
202
|
)
|
|
166
203
|
}
|
|
167
204
|
|
|
205
|
+
const live = options.live
|
|
206
|
+
const liveFetch =
|
|
207
|
+
keep !== undefined
|
|
208
|
+
? ", fetchData: __keep.fetchData"
|
|
209
|
+
: live === undefined
|
|
210
|
+
? ""
|
|
211
|
+
: ", fetchData: __live.fetchData"
|
|
168
212
|
return `${[
|
|
169
213
|
// `/client`, never the root: the root's graph carries the server (renderPage, the static-file
|
|
170
214
|
// server), and Vite's dev server evaluates what it is given instead of tree-shaking it.
|
|
@@ -173,6 +217,8 @@ export function generateClientEntry(
|
|
|
173
217
|
...(options.serverComponents
|
|
174
218
|
? ['import { bindComponentRouter } from "@nifrajs/web/server-components/client"']
|
|
175
219
|
: []),
|
|
220
|
+
...(live === undefined ? [] : ['import { liveClient } from "@nifrajs/web/live-client"']),
|
|
221
|
+
...(keep === undefined ? [] : ['import { keepAliveClient } from "@nifrajs/web/keep-alive"']),
|
|
176
222
|
// Namespace import: `errorBoundary` is optional (an adapter may not export it). A namespace member
|
|
177
223
|
// access yields `undefined` if absent - unlike a named import, which would be a link error.
|
|
178
224
|
...(loadings.length > 0
|
|
@@ -235,7 +281,22 @@ export function generateClientEntry(
|
|
|
235
281
|
"const holds = {}",
|
|
236
282
|
// routeId → the ids and `handle` exports `useMatches` reports (layouts, then the page).
|
|
237
283
|
`const layoutIdsOf = ${jsValueLiteral(layoutIdsOf)}`,
|
|
284
|
+
...(live === undefined
|
|
285
|
+
? []
|
|
286
|
+
: [
|
|
287
|
+
`const __live = liveClient({ ${[
|
|
288
|
+
"layoutIdsOf",
|
|
289
|
+
...(live.path === undefined ? [] : [`path: ${jsStringLiteral(live.path)}`]),
|
|
290
|
+
...(live.loadPath === undefined ? [] : [`loadPath: ${jsStringLiteral(live.loadPath)}`]),
|
|
291
|
+
].join(", ")} })`,
|
|
292
|
+
]),
|
|
238
293
|
"const matchChains = {}",
|
|
294
|
+
...(keep === undefined
|
|
295
|
+
? []
|
|
296
|
+
: [
|
|
297
|
+
`const keepAliveTable = ${jsValueLiteral(keep)}`,
|
|
298
|
+
`const __keep = keepAliveClient({ table: keepAliveTable, routeHooks, matchChains${live === undefined ? "" : ", fetchData: __live.fetchData"} })`,
|
|
299
|
+
]),
|
|
239
300
|
`const ${options.copyChunks === true ? "loadRoute" : "loadModule"} = async (id) => {`,
|
|
240
301
|
" if (chains[id]) return",
|
|
241
302
|
" const mods = await loaders[id]()",
|
|
@@ -271,7 +332,7 @@ export function generateClientEntry(
|
|
|
271
332
|
// backend half, which no browser bundle contains.
|
|
272
333
|
" const boundaryMods = errorRouteIds.has(id) ? mods.slice(0, -1) : mods",
|
|
273
334
|
" const boundaries = boundaryMods.flatMap((m) => (m.boundaries ?? []).map((b) => ({ name: b.name, mode: b.mode, ...(b.errorId === undefined ? {} : { errorId: b.errorId }) })))",
|
|
274
|
-
|
|
335
|
+
` routeHooks[id] = { clientLoader: page.clientLoader, clientAction: page.clientAction, shareData: page.shareData, ${keep === undefined ? "" : "keepAlive: page.keepAlive, "}boundaries }`,
|
|
275
336
|
" if (page.ssr === false) holds[id] = [...chains[id].slice(0, -1), page.HydrateFallback ?? (() => null)]",
|
|
276
337
|
"}",
|
|
277
338
|
...(options.copyChunks === true
|
|
@@ -334,9 +395,18 @@ export function generateClientEntry(
|
|
|
334
395
|
...loadingLines,
|
|
335
396
|
// With `_loading` pages the store is wrapped: a slow navigation then names a loading chain (the
|
|
336
397
|
// shared layouts + the `_loading` component) for the mounted view to render in the meantime.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
398
|
+
keepAround(
|
|
399
|
+
keep,
|
|
400
|
+
loadings.length > 0
|
|
401
|
+
? `withLoading(createClientRouter({ patterns, initial, loadModule, statusRoutes${routerStatusOption}, searchClientKeys, routeHooks${liveFetch} }), { routes: loadingRoutes, modules: loadingModules, chains, searchSchemas, matchChains })`
|
|
402
|
+
: `createClientRouter({ patterns, initial, loadModule, statusRoutes${routerStatusOption}, searchClientKeys, routeHooks${liveFetch} })`,
|
|
403
|
+
),
|
|
404
|
+
// Kept pages hold the code they were rendered with: a hot update drops them.
|
|
405
|
+
...(keep === undefined
|
|
406
|
+
? []
|
|
407
|
+
: [
|
|
408
|
+
'if (import.meta.hot) for (const event of ["bun:afterUpdate", "vite:afterUpdate"]) import.meta.hot.on(event, () => router.dropKept("hot-update"))',
|
|
409
|
+
]),
|
|
340
410
|
...(options.serverComponents ? ["bindComponentRouter(router)"] : []),
|
|
341
411
|
"installHistory(router)",
|
|
342
412
|
"installForms(router)",
|
|
@@ -392,11 +462,13 @@ export function generateClientEntry(
|
|
|
392
462
|
" for (const listener of [...listeners]) listener()",
|
|
393
463
|
" }, 0)",
|
|
394
464
|
" }",
|
|
395
|
-
|
|
465
|
+
` mountRouter({ router: view, routes: chains, searchSchemas, matchChains, container: root${keep === undefined ? "" : ", keepAlive: keepAliveTable"} })`,
|
|
396
466
|
// Run the optional client loader only after the adapter has mounted the SSR tree. The initial
|
|
397
467
|
// server data is already in `window.__NIFRA_DATA__`, so `serverLoader()` reuses it and cannot
|
|
398
468
|
// duplicate the first request.
|
|
399
469
|
" router.hydrate().catch((error) => console.error('[nifra/web] clientLoader failed:', error))",
|
|
470
|
+
// Once mounted: the first live load and the socket must not race the hydration.
|
|
471
|
+
...(live === undefined ? [] : [" __live.attach(router)"]),
|
|
400
472
|
// Next frame: the adapter has committed its initial hydration, so handlers are attached. Flip the
|
|
401
473
|
// document to interactive (`data-nifra-hydrated` + `nifra:hydrated`) for apps to gate pre-hydration UI.
|
|
402
474
|
" requestAnimationFrame(signalHydrated)",
|
|
@@ -521,6 +593,13 @@ function moduleSpecifier(resolved: string): string {
|
|
|
521
593
|
// A route's namespace is not assignable to `RouteModule` under a strict `tsc` (a backend half has no
|
|
522
594
|
// `default`, a typed `meta` narrows its data), so the table holds plain objects and the cast happens at
|
|
523
595
|
// `buildManifest`'s boundary - the same cast `discoverRoutes` applies to its dynamic import.
|
|
596
|
+
// The routes the scan found exporting `keepAlive`, which a disk-less server cannot scan again.
|
|
597
|
+
const keepAliveArg = (manifest: Manifest): string => {
|
|
598
|
+
const files = [
|
|
599
|
+
...new Set(manifest.routes.filter((route) => route.keepAlive).map((route) => route.file)),
|
|
600
|
+
]
|
|
601
|
+
return files.length === 0 ? "" : `, { keepAlive: ${jsValueLiteral(files)} }`
|
|
602
|
+
}
|
|
524
603
|
const LAZY_IMPORTER = "(file) => loaders[file] as () => Promise<RouteModule>"
|
|
525
604
|
const EAGER_IMPORTER = "(file) => () => Promise.resolve(modules[file] as RouteModule)"
|
|
526
605
|
|
|
@@ -604,7 +683,7 @@ export function generateServerManifest(
|
|
|
604
683
|
cssLoadingLine,
|
|
605
684
|
...copyChunksLines,
|
|
606
685
|
...buildAssetsLines,
|
|
607
|
-
`export const manifest = buildManifest(Object.keys(loaders), ${LAZY_IMPORTER})`,
|
|
686
|
+
`export const manifest = buildManifest(Object.keys(loaders), ${LAZY_IMPORTER}${keepAliveArg(manifest)})`,
|
|
608
687
|
].join("\n")}\n`
|
|
609
688
|
}
|
|
610
689
|
// Eager: `import * as` per route (all bundled into the entry, parsed at boot). Index-based
|
|
@@ -625,6 +704,6 @@ export function generateServerManifest(
|
|
|
625
704
|
cssLoadingLine,
|
|
626
705
|
...copyChunksLines,
|
|
627
706
|
...buildAssetsLines,
|
|
628
|
-
`export const manifest = buildManifest(Object.keys(modules), ${EAGER_IMPORTER})`,
|
|
707
|
+
`export const manifest = buildManifest(Object.keys(modules), ${EAGER_IMPORTER}${keepAliveArg(manifest)})`,
|
|
629
708
|
].join("\n")}\n`
|
|
630
709
|
}
|