@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,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The declarative binding walker - attaches signal-driven behavior to SERVER-RENDERED markup.
|
|
3
|
+
* No VDOM, no hydration re-render: the HTML the server sent (e.g. via `@nifrajs/web-vanilla`) is
|
|
4
|
+
* already the initial state; bindings update it surgically when signals change. `bindIsland` runs it.
|
|
5
|
+
*
|
|
6
|
+
* The attribute set is CLOSED and documented - six bindings, no expression language. Values are
|
|
7
|
+
* signal/handler NAMES looked up in the island's scope, never evaluated code, so markup can't
|
|
8
|
+
* inject behavior:
|
|
9
|
+
*
|
|
10
|
+
* data-bind-text="count" textContent ← String(signal())
|
|
11
|
+
* data-bind-show="isOpen" hidden ← !signal()
|
|
12
|
+
* data-bind-class="active:isOpen,b:sigB" classList.toggle per pair
|
|
13
|
+
* data-bind-attr="aria-expanded:isOpen" setAttribute / removeAttribute (false/null remove);
|
|
14
|
+
* never an `on*` handler or `srcdoc`, and a URL attribute
|
|
15
|
+
* takes only an http(s)/mailto/tel or relative URL
|
|
16
|
+
* data-bind-value="query" two-way <input>/<select>/<textarea> (input and change)
|
|
17
|
+
* data-bind-on="click:inc,submit:save" addEventListener per pair
|
|
18
|
+
*
|
|
19
|
+
* Nothing inside a `data-island-ignore` element binds or mounts: render user HTML there, so its
|
|
20
|
+
* markup cannot reach the island's handlers or signals.
|
|
21
|
+
*
|
|
22
|
+
* A binding belongs to its nearest island: an island never binds inside a nested island's host. The
|
|
23
|
+
* nested host element itself is still the outer island's markup, so the outer island may bind it.
|
|
24
|
+
*/
|
|
25
|
+
import { watch } from "./island-signals.js";
|
|
26
|
+
const warned = new Set();
|
|
27
|
+
/** Unknown names warn once (loud in dev, resilient in prod - progressive enhancement must not
|
|
28
|
+
* throw over a typo'd attribute) and the binding is skipped. */
|
|
29
|
+
function warnOnce(kind, name) {
|
|
30
|
+
const key = `${kind}:${name}`;
|
|
31
|
+
if (warned.has(key))
|
|
32
|
+
return;
|
|
33
|
+
warned.add(key);
|
|
34
|
+
console.warn(`[nifra/islands] unknown ${kind} ${JSON.stringify(name)} - binding skipped`);
|
|
35
|
+
}
|
|
36
|
+
// Own keys only: a name such as `constructor` must not resolve to what a plain object inherits.
|
|
37
|
+
function named(kind, record, name) {
|
|
38
|
+
if (Object.hasOwn(record, name))
|
|
39
|
+
return record[name];
|
|
40
|
+
warnOnce(kind, name);
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
/** Parse a `"key:name,key2:name2"` pair list (whitespace-tolerant). Malformed entries skip. */
|
|
44
|
+
function pairs(spec) {
|
|
45
|
+
const out = [];
|
|
46
|
+
for (const part of spec.split(",")) {
|
|
47
|
+
const sep = part.indexOf(":");
|
|
48
|
+
if (sep <= 0)
|
|
49
|
+
continue;
|
|
50
|
+
const key = part.slice(0, sep).trim();
|
|
51
|
+
const name = part.slice(sep + 1).trim();
|
|
52
|
+
if (key && name)
|
|
53
|
+
out.push([key, name]);
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
// A bound value is data (often from island state the markup carries), so an attribute that would run
|
|
58
|
+
// it as code, or navigate to it as a script URL, is refused.
|
|
59
|
+
const CODE_ATTRIBUTE = /^(?:on|srcdoc$)/i;
|
|
60
|
+
const URL_ATTRIBUTE = /^(?:href|src|action|formaction|xlink:href|poster|data|background|cite|ping)$/i;
|
|
61
|
+
const SAFE_URL = /^(?:(?:https?|mailto|tel):|[^:/?#]*(?:[/?#]|$))/i;
|
|
62
|
+
/** Walk `root` and attach every `data-bind-*` binding against `scope`. Each binding's disposer
|
|
63
|
+
* (reactive effect or event listener) goes onto `stops` as it attaches, so a binding that throws
|
|
64
|
+
* midway leaves the earlier ones disposable; `stops` is returned. */
|
|
65
|
+
export function bindScope(root, scope, stops = []) {
|
|
66
|
+
// Each element carrying `data-bind-<kind>` outside any ignored subtree and any nested island, with
|
|
67
|
+
// that attribute's value.
|
|
68
|
+
const each = (kind) => {
|
|
69
|
+
const attribute = `data-bind-${kind}`;
|
|
70
|
+
return [
|
|
71
|
+
...root.querySelectorAll(`[${attribute}]:not([data-island-ignore],[data-island-ignore] *,:scope [data-island] *)`),
|
|
72
|
+
].map((el) => [el, el.getAttribute(attribute) ?? ""]);
|
|
73
|
+
};
|
|
74
|
+
for (const [el, name] of each("text")) {
|
|
75
|
+
const s = named("signal", scope.signals, name);
|
|
76
|
+
if (s) {
|
|
77
|
+
stops.push(watch(s, (v) => {
|
|
78
|
+
el.textContent = String(v);
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
for (const [el, name] of each("show")) {
|
|
83
|
+
const s = named("signal", scope.signals, name);
|
|
84
|
+
if (s) {
|
|
85
|
+
stops.push(watch(s, (v) => {
|
|
86
|
+
el.hidden = !v;
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const [el, spec] of each("class")) {
|
|
91
|
+
for (const [className, name] of pairs(spec)) {
|
|
92
|
+
const s = named("signal", scope.signals, name);
|
|
93
|
+
if (s) {
|
|
94
|
+
stops.push(watch(s, (v) => {
|
|
95
|
+
el.classList.toggle(className, !!v);
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
for (const [el, spec] of each("attr")) {
|
|
101
|
+
for (const [attr, name] of pairs(spec)) {
|
|
102
|
+
if (CODE_ATTRIBUTE.test(attr)) {
|
|
103
|
+
warnOnce("attribute", attr);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const s = named("signal", scope.signals, name);
|
|
107
|
+
if (s) {
|
|
108
|
+
const isUrl = URL_ATTRIBUTE.test(attr);
|
|
109
|
+
stops.push(watch(s, (v) => {
|
|
110
|
+
if (v === false || v == null || (isUrl && !SAFE_URL.test(String(v).trim())))
|
|
111
|
+
el.removeAttribute(attr);
|
|
112
|
+
else
|
|
113
|
+
el.setAttribute(attr, String(v));
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
for (const [el, name] of each("value")) {
|
|
119
|
+
const s = named("signal", scope.signals, name);
|
|
120
|
+
if (s) {
|
|
121
|
+
stops.push(watch(s, (v) => {
|
|
122
|
+
const next = String(v);
|
|
123
|
+
// Skip same-value writes: resetting an input's value mid-typing moves the caret.
|
|
124
|
+
if (el.value !== next)
|
|
125
|
+
el.value = next;
|
|
126
|
+
}));
|
|
127
|
+
const input = () => s.set(el.value ?? "");
|
|
128
|
+
// A <select> commits on `change`, and browsers disagree on whether `input` comes first. The
|
|
129
|
+
// second event of a pair writes the same value, which the signal skips.
|
|
130
|
+
for (const type of ["input", "change"]) {
|
|
131
|
+
el.addEventListener(type, input);
|
|
132
|
+
stops.push(() => el.removeEventListener(type, input));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const [el, spec] of each("on")) {
|
|
137
|
+
for (const [event, name] of pairs(spec)) {
|
|
138
|
+
const handler = named("handler", scope.handlers, name);
|
|
139
|
+
if (handler === undefined)
|
|
140
|
+
continue;
|
|
141
|
+
el.addEventListener(event, handler);
|
|
142
|
+
stops.push(() => el.removeEventListener(event, handler));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return stops;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=island-bindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-bindings.js","sourceRoot":"","sources":["../../src/internal/island-bindings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** The node surface `bindList` uses; an `Element` has it. */
|
|
2
|
+
export interface ListNode {
|
|
3
|
+
remove(): void;
|
|
4
|
+
}
|
|
5
|
+
/** The container surface `bindList` uses; an `Element` has it. */
|
|
6
|
+
export interface ListContainer<E extends ListNode> {
|
|
7
|
+
replaceChildren(...nodes: E[]): void;
|
|
8
|
+
insertBefore(node: E, before: E | null): unknown;
|
|
9
|
+
}
|
|
10
|
+
/** How `bindList` turns items into keyed DOM. */
|
|
11
|
+
export interface BindListOptions<T, E extends ListNode = HTMLElement> {
|
|
12
|
+
/** Stable and unique per item - never the array index, or a removal reuses the wrong node. */
|
|
13
|
+
key(item: T): string | number;
|
|
14
|
+
create(item: T): E;
|
|
15
|
+
/** Brings a node in line with its item: runs after `create` and on every later change. */
|
|
16
|
+
update?(el: E, item: T): void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Render a list signal (or any getter) into `container` with keyed reconciliation. A surviving item
|
|
20
|
+
* keeps its node, so focus, selection and input state survive a reorder. A render with no earlier
|
|
21
|
+
* nodes replaces the container's children; later renders move only the nodes outside the longest
|
|
22
|
+
* run already in order. `key`, `create` and `update` run untracked: a signal they read does not
|
|
23
|
+
* re-render the list. Returns the disposer; inside an island the binding also stops on unmount.
|
|
24
|
+
*/
|
|
25
|
+
export declare function bindList<T, E extends ListNode = HTMLElement>(source: () => readonly T[], container: ListContainer<NoInfer<E>>, options: BindListOptions<T, E>): () => void;
|
|
26
|
+
//# sourceMappingURL=island-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-list.d.ts","sourceRoot":"","sources":["../../src/internal/island-list.ts"],"names":[],"mappings":"AAEA,6DAA6D;AAC7D,MAAM,WAAW,QAAQ;IACvB,MAAM,IAAI,IAAI,CAAA;CACf;AAED,kEAAkE;AAClE,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,QAAQ;IAC/C,eAAe,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,CAAA;IACpC,YAAY,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAA;CACjD;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,WAAW;IAClE,8FAA8F;IAC9F,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,GAAG,MAAM,CAAA;IAC7B,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;IAClB,0FAA0F;IAC1F,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,WAAW,EAC1D,MAAM,EAAE,MAAM,SAAS,CAAC,EAAE,EAE1B,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EACpC,OAAO,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAC7B,MAAM,IAAI,CAkCZ"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { effect, untrack } from "./island-signals.js";
|
|
2
|
+
/**
|
|
3
|
+
* Render a list signal (or any getter) into `container` with keyed reconciliation. A surviving item
|
|
4
|
+
* keeps its node, so focus, selection and input state survive a reorder. A render with no earlier
|
|
5
|
+
* nodes replaces the container's children; later renders move only the nodes outside the longest
|
|
6
|
+
* run already in order. `key`, `create` and `update` run untracked: a signal they read does not
|
|
7
|
+
* re-render the list. Returns the disposer; inside an island the binding also stops on unmount.
|
|
8
|
+
*/
|
|
9
|
+
export function bindList(source,
|
|
10
|
+
// A DOM container's generic methods would drive E to `ListNode`; the row type comes from `create`.
|
|
11
|
+
container, options) {
|
|
12
|
+
let nodes = new Map();
|
|
13
|
+
// Each node's position in the last render; empty until a render leaves nodes to keep.
|
|
14
|
+
let at = new Map();
|
|
15
|
+
return effect(() => {
|
|
16
|
+
const items = source();
|
|
17
|
+
untrack(() => {
|
|
18
|
+
const next = new Map();
|
|
19
|
+
for (const item of items) {
|
|
20
|
+
const key = options.key(item);
|
|
21
|
+
if (next.has(key))
|
|
22
|
+
console.warn("[nifra/islands] bindList: duplicate key skipped", key);
|
|
23
|
+
else {
|
|
24
|
+
const el = nodes.get(key) ?? options.create(item);
|
|
25
|
+
options.update?.(el, item);
|
|
26
|
+
next.set(key, el);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const els = [...next.values()];
|
|
30
|
+
if (at.size === 0)
|
|
31
|
+
container.replaceChildren(...els);
|
|
32
|
+
else {
|
|
33
|
+
for (const [key, el] of nodes)
|
|
34
|
+
if (!next.has(key))
|
|
35
|
+
el.remove();
|
|
36
|
+
const stays = inOrder(els.map((el) => at.get(el) ?? -1));
|
|
37
|
+
let anchor = null;
|
|
38
|
+
for (let i = els.length - 1; i >= 0; i--) {
|
|
39
|
+
const el = els[i];
|
|
40
|
+
if (el === undefined)
|
|
41
|
+
continue;
|
|
42
|
+
if (!stays.has(i))
|
|
43
|
+
container.insertBefore(el, anchor);
|
|
44
|
+
anchor = el;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
at = new Map(els.map((el, i) => [el, i]));
|
|
48
|
+
nodes = next;
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// The indexes of `old` (each node's previous position, -1 for a new node) on a longest increasing
|
|
53
|
+
// run: those nodes already sit in order, and every other node is moved.
|
|
54
|
+
function inOrder(old) {
|
|
55
|
+
// tails[n] is the index ending the best run of length n + 1; back links each run.
|
|
56
|
+
const tails = [];
|
|
57
|
+
const back = [];
|
|
58
|
+
old.forEach((o, i) => {
|
|
59
|
+
if (o < 0)
|
|
60
|
+
return;
|
|
61
|
+
let lo = 0;
|
|
62
|
+
let hi = tails.length;
|
|
63
|
+
while (lo < hi) {
|
|
64
|
+
const mid = (lo + hi) >> 1;
|
|
65
|
+
if ((old[tails[mid] ?? 0] ?? 0) < o)
|
|
66
|
+
lo = mid + 1;
|
|
67
|
+
else
|
|
68
|
+
hi = mid;
|
|
69
|
+
}
|
|
70
|
+
back[i] = tails[lo - 1] ?? -1;
|
|
71
|
+
tails[lo] = i;
|
|
72
|
+
});
|
|
73
|
+
const stays = new Set();
|
|
74
|
+
for (let i = tails.at(-1) ?? -1; i >= 0; i = back[i] ?? -1)
|
|
75
|
+
stays.add(i);
|
|
76
|
+
return stays;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=island-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-list.js","sourceRoot":"","sources":["../../src/internal/island-list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IslandCleanup, IslandEnhancer } from "../islands.js";
|
|
2
|
+
/** Own one host so removing a subtree can stop its islands without disturbing retained siblings. */
|
|
3
|
+
export declare function mountIsland(el: HTMLElement, enhancers: Readonly<Record<string, IslandEnhancer<never>>>): IslandCleanup | undefined;
|
|
4
|
+
//# sourceMappingURL=island-mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-mount.d.ts","sourceRoot":"","sources":["../../src/internal/island-mount.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAalE,oGAAoG;AACpG,wBAAgB,WAAW,CACzB,EAAE,EAAE,WAAW,EACf,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,GACzD,aAAa,GAAG,SAAS,CA6C3B"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { MAX_MEDIA_QUERY_LENGTH, scheduleTrigger, } from "@nifrajs/island-trigger";
|
|
2
|
+
import { owned } from "./island-owner.js";
|
|
3
|
+
function readProps(el) {
|
|
4
|
+
const raw = el.dataset.islandProps;
|
|
5
|
+
if (raw === undefined || raw === "")
|
|
6
|
+
return undefined;
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(raw);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** Own one host so removing a subtree can stop its islands without disturbing retained siblings. */
|
|
15
|
+
export function mountIsland(el, enhancers) {
|
|
16
|
+
const id = el.dataset.island;
|
|
17
|
+
if (id === undefined || el.dataset.islandMounted !== undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
const enhancer = Object.hasOwn(enhancers, id) ? enhancers[id] : undefined;
|
|
20
|
+
if (enhancer === undefined)
|
|
21
|
+
return undefined;
|
|
22
|
+
const strategyAttr = el.dataset.islandStrategy;
|
|
23
|
+
const media = el.dataset.islandMedia;
|
|
24
|
+
const strategy = strategyAttr === "idle" || strategyAttr === "visible" || strategyAttr === "load"
|
|
25
|
+
? strategyAttr
|
|
26
|
+
: strategyAttr === "media" &&
|
|
27
|
+
media !== undefined &&
|
|
28
|
+
media.length > 0 &&
|
|
29
|
+
media.length <= MAX_MEDIA_QUERY_LENGTH
|
|
30
|
+
? { media }
|
|
31
|
+
: strategyAttr === undefined
|
|
32
|
+
? "load"
|
|
33
|
+
: undefined;
|
|
34
|
+
// Invalid markers must stay inert, including untrusted oversized media queries.
|
|
35
|
+
if (strategy === undefined)
|
|
36
|
+
return undefined;
|
|
37
|
+
const disposers = [];
|
|
38
|
+
el.dataset.islandMounted = "";
|
|
39
|
+
disposers.push(() => {
|
|
40
|
+
delete el.dataset.islandMounted;
|
|
41
|
+
});
|
|
42
|
+
const props = readProps(el);
|
|
43
|
+
const run = () => {
|
|
44
|
+
try {
|
|
45
|
+
// biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: enhancer props are the authored SSR contract, as in defineIsland
|
|
46
|
+
const cleanup = owned(disposers, () => enhancer(el, props));
|
|
47
|
+
if (typeof cleanup === "function")
|
|
48
|
+
disposers.push(cleanup);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
console.error(`[nifra/islands] enhancer "${id}" failed:`, err);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
disposers.push(scheduleTrigger(strategy, run, { target: el }));
|
|
55
|
+
return () => {
|
|
56
|
+
for (const dispose of disposers.splice(0)) {
|
|
57
|
+
try {
|
|
58
|
+
dispose();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Best-effort teardown: one failing cleanup must not block the rest.
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=island-mount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-mount.js","sourceRoot":"","sources":["../../src/internal/island-mount.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Run `fn` with every disposer it registers pushed onto `kids`. */
|
|
2
|
+
export declare function owned<T>(kids: Array<() => void>, fn: () => T): T;
|
|
3
|
+
/** Register `stop` with the running island, if any. Outside an enhancer it stays the caller's. */
|
|
4
|
+
export declare function adopt(stop: () => void): void;
|
|
5
|
+
//# sourceMappingURL=island-owner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-owner.d.ts","sourceRoot":"","sources":["../../src/internal/island-owner.ts"],"names":[],"mappings":"AAKA,oEAAoE;AACpE,wBAAgB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAQhE;AAED,kGAAkG;AAClG,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI,CAE5C"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// The disposer list of the island whose enhancer is running, so every effect, computed, list binding
|
|
2
|
+
// and resource it creates stops when the island unmounts. A separate module so an imperative-only
|
|
3
|
+
// island bundle carries no signal code.
|
|
4
|
+
let owner;
|
|
5
|
+
/** Run `fn` with every disposer it registers pushed onto `kids`. */
|
|
6
|
+
export function owned(kids, fn) {
|
|
7
|
+
const prev = owner;
|
|
8
|
+
owner = kids;
|
|
9
|
+
try {
|
|
10
|
+
return fn();
|
|
11
|
+
}
|
|
12
|
+
finally {
|
|
13
|
+
owner = prev;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Register `stop` with the running island, if any. Outside an enhancer it stays the caller's. */
|
|
17
|
+
export function adopt(stop) {
|
|
18
|
+
owner?.push(stop);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=island-owner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-owner.js","sourceRoot":"","sources":["../../src/internal/island-owner.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,kGAAkG;AAClG,wCAAwC;AACxC,IAAI,KAAoC,CAAA;AAExC,oEAAoE;AACpE,MAAM,UAAU,KAAK,CAAI,IAAuB,EAAE,EAAW;IAC3D,MAAM,IAAI,GAAG,KAAK,CAAA;IAClB,KAAK,GAAG,IAAI,CAAA;IACZ,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAA;IACb,CAAC;YAAS,CAAC;QACT,KAAK,GAAG,IAAI,CAAA;IACd,CAAC;AACH,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,KAAK,CAAC,IAAgB;IACpC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;AACnB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** An async value's state. `status` narrows `value` and `error`, so no branch can be skipped. */
|
|
2
|
+
export type ResourceState<T> = {
|
|
3
|
+
readonly status: "pending";
|
|
4
|
+
readonly value: undefined;
|
|
5
|
+
readonly error: undefined;
|
|
6
|
+
} | {
|
|
7
|
+
readonly status: "ready";
|
|
8
|
+
readonly value: T;
|
|
9
|
+
readonly error: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
readonly status: "error";
|
|
12
|
+
readonly value: undefined;
|
|
13
|
+
readonly error: unknown;
|
|
14
|
+
};
|
|
15
|
+
/** Call it to read the current state (tracking, like a signal). */
|
|
16
|
+
export type Resource<T> = {
|
|
17
|
+
(): ResourceState<T>;
|
|
18
|
+
/** Fetch the current key again; once disposed, nothing. */
|
|
19
|
+
refetch(): void;
|
|
20
|
+
/** Stop refetching and abort the request in flight; its result is dropped. */
|
|
21
|
+
dispose(): void;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* An async value keyed by `source`. `source` runs tracked, so a write to any signal it reads starts a
|
|
25
|
+
* new fetch; `fetcher` runs untracked with that key, so nothing it reads (before or after an `await`)
|
|
26
|
+
* is a dependency. A newer fetch aborts the older one and only the newest result lands. Inside an
|
|
27
|
+
* island, unmounting disposes it: the request in flight is aborted and its late result dropped.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resource<K, T>(source: () => K, fetcher: (key: K, abort: AbortSignal) => Promise<T>): Resource<T>;
|
|
30
|
+
//# sourceMappingURL=island-resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-resource.d.ts","sourceRoot":"","sources":["../../src/internal/island-resource.ts"],"names":[],"mappings":"AAGA,iGAAiG;AACjG,MAAM,MAAM,aAAa,CAAC,CAAC,IACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GACpF;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAEpF,mEAAmE;AACnE,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACxB,IAAI,aAAa,CAAC,CAAC,CAAC,CAAA;IACpB,2DAA2D;IAC3D,OAAO,IAAI,IAAI,CAAA;IACf,8EAA8E;IAC9E,OAAO,IAAI,IAAI,CAAA;CAChB,CAAA;AAID;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAC3B,MAAM,EAAE,MAAM,CAAC,EACf,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAClD,QAAQ,CAAC,CAAC,CAAC,CA8Cb"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { adopt } from "./island-owner.js";
|
|
2
|
+
import { effect, signal, untrack } from "./island-signals.js";
|
|
3
|
+
const PENDING = { status: "pending", value: undefined, error: undefined };
|
|
4
|
+
/**
|
|
5
|
+
* An async value keyed by `source`. `source` runs tracked, so a write to any signal it reads starts a
|
|
6
|
+
* new fetch; `fetcher` runs untracked with that key, so nothing it reads (before or after an `await`)
|
|
7
|
+
* is a dependency. A newer fetch aborts the older one and only the newest result lands. Inside an
|
|
8
|
+
* island, unmounting disposes it: the request in flight is aborted and its late result dropped.
|
|
9
|
+
*/
|
|
10
|
+
export function resource(source, fetcher) {
|
|
11
|
+
const state = signal(PENDING);
|
|
12
|
+
let generation = 0;
|
|
13
|
+
let live = true;
|
|
14
|
+
let controller;
|
|
15
|
+
let key;
|
|
16
|
+
const run = () => {
|
|
17
|
+
const mine = ++generation;
|
|
18
|
+
controller?.abort();
|
|
19
|
+
const active = new AbortController();
|
|
20
|
+
controller = active;
|
|
21
|
+
state.set(PENDING);
|
|
22
|
+
let pending;
|
|
23
|
+
try {
|
|
24
|
+
pending = fetcher(key, active.signal);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
pending = Promise.reject(error);
|
|
28
|
+
}
|
|
29
|
+
pending.then((value) => {
|
|
30
|
+
if (mine === generation)
|
|
31
|
+
state.set({ status: "ready", value, error: undefined });
|
|
32
|
+
}, (error) => {
|
|
33
|
+
// A superseded or aborted fetch is not an error the reader should see.
|
|
34
|
+
if (mine === generation && !active.signal.aborted)
|
|
35
|
+
state.set({ status: "error", value: undefined, error });
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const stop = effect(() => {
|
|
39
|
+
key = source();
|
|
40
|
+
untrack(run);
|
|
41
|
+
});
|
|
42
|
+
// biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: `refetch` and `dispose` are assigned below
|
|
43
|
+
const read = (() => state());
|
|
44
|
+
read.refetch = () => {
|
|
45
|
+
if (live)
|
|
46
|
+
untrack(run);
|
|
47
|
+
};
|
|
48
|
+
read.dispose = () => {
|
|
49
|
+
live = false;
|
|
50
|
+
stop();
|
|
51
|
+
generation++;
|
|
52
|
+
controller?.abort();
|
|
53
|
+
};
|
|
54
|
+
adopt(read.dispose);
|
|
55
|
+
return read;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=island-resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-resource.js","sourceRoot":"","sources":["../../src/internal/island-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAiB7D,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAW,CAAA;AAElF;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAe,EACf,OAAmD;IAEnD,MAAM,KAAK,GAAG,MAAM,CAAmB,OAAO,CAAC,CAAA;IAC/C,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,IAAI,GAAG,IAAI,CAAA;IACf,IAAI,UAAuC,CAAA;IAC3C,IAAI,GAAM,CAAA;IACV,MAAM,GAAG,GAAG,GAAS,EAAE;QACrB,MAAM,IAAI,GAAG,EAAE,UAAU,CAAA;QACzB,UAAU,EAAE,KAAK,EAAE,CAAA;QACnB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAA;QACpC,UAAU,GAAG,MAAM,CAAA;QACnB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAClB,IAAI,OAAmB,CAAA;QACvB,IAAI,CAAC;YACH,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACjC,CAAC;QACD,OAAO,CAAC,IAAI,CACV,CAAC,KAAK,EAAE,EAAE;YACR,IAAI,IAAI,KAAK,UAAU;gBAAE,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;QAClF,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;YACR,uEAAuE;YACvE,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO;gBAC/C,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAA;QAC3D,CAAC,CACF,CAAA;IACH,CAAC,CAAA;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE;QACvB,GAAG,GAAG,MAAM,EAAE,CAAA;QACd,OAAO,CAAC,GAAG,CAAC,CAAA;IACd,CAAC,CAAC,CAAA;IACF,4GAA4G;IAC5G,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,CAAgB,CAAA;IAC3C,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE;QAClB,IAAI,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IACxB,CAAC,CAAA;IACD,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE;QAClB,IAAI,GAAG,KAAK,CAAA;QACZ,IAAI,EAAE,CAAA;QACN,UAAU,EAAE,CAAA;QACZ,UAAU,EAAE,KAAK,EAAE,CAAA;IACrB,CAAC,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACnB,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fine-grained signals - the reactive core of `@nifrajs/web/islands`. Pull-based auto-tracking with
|
|
3
|
+
* per-run re-tracking (a branch switch drops the stale branch's subscriptions), `Object.is`
|
|
4
|
+
* equality skips, and an explicit synchronous {@link batch} that coalesces effect re-runs.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately tiny and synchronous: a write recomputes the computeds it feeds at once and runs its
|
|
7
|
+
* effects before `set` returns, each once, after every computed has settled - predictable for
|
|
8
|
+
* island-scale code (a counter, a filter drawer), and the whole core stays well under a kilobyte.
|
|
9
|
+
* This is NOT a general app framework - just island-scale reactivity.
|
|
10
|
+
*/
|
|
11
|
+
/** Run `fn` without subscribing the running effect or computed to the signals it reads. */
|
|
12
|
+
export declare function untrack<T>(fn: () => T): T;
|
|
13
|
+
/** A readable/writable reactive value: call it to read (tracking), `.set` to write. */
|
|
14
|
+
export type Signal<T> = {
|
|
15
|
+
(): T;
|
|
16
|
+
set(next: T | ((prev: T) => T)): void;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Batch writes: effects triggered inside `fn` run ONCE after it returns, deduplicated - so
|
|
20
|
+
* `setA(); setB()` updates the DOM once, not twice. Re-entrant; an effect re-queued during the
|
|
21
|
+
* flush runs in the same flush.
|
|
22
|
+
*/
|
|
23
|
+
export declare function batch<T>(fn: () => T): T;
|
|
24
|
+
/** Create a signal. Reads inside an {@link effect} (or {@link computed}) subscribe automatically. */
|
|
25
|
+
export declare function signal<T>(initial: T): Signal<T>;
|
|
26
|
+
/**
|
|
27
|
+
* Call `fn` with `source`'s value now and after each change, queued and batched like an effect but
|
|
28
|
+
* subscribed once instead of tracking reads. Any other getter (a computed, a derived function) is
|
|
29
|
+
* tracked as an effect. Either way `fn` runs untracked. Internal to the binding walker, whose bindings each read one named signal,
|
|
30
|
+
* and to `bindList`; not exported from `@nifrajs/web/islands`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function watch<T>(source: () => T, fn: (value: T) => void): () => void;
|
|
33
|
+
/** A derived value: call it to read (tracking), `.dispose()` to stop recomputing it. */
|
|
34
|
+
export type Computed<T> = {
|
|
35
|
+
(): T;
|
|
36
|
+
dispose(): void;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Derived value, cached into a signal and computed on first read. While an effect (or another
|
|
40
|
+
* computed) reads it, it recomputes when its tracked inputs change. Once nothing reads it, the next
|
|
41
|
+
* input change stops it instead of recomputing, so a dropped computed costs nothing; reading it
|
|
42
|
+
* again starts it afresh. `dispose()` stops it at once.
|
|
43
|
+
*/
|
|
44
|
+
export declare function computed<T>(fn: () => T): Computed<T>;
|
|
45
|
+
/**
|
|
46
|
+
* Run `fn` now and again whenever any signal it read changes. Returns a disposer. Dependencies
|
|
47
|
+
* re-track on every run, so conditional reads subscribe to exactly the live branch. Every run,
|
|
48
|
+
* the first included, finishes before the effects its writes trigger run, itself among them.
|
|
49
|
+
*/
|
|
50
|
+
export declare function effect(fn: () => void): () => void;
|
|
51
|
+
//# sourceMappingURL=island-signals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"island-signals.d.ts","sourceRoot":"","sources":["../../src/internal/island-signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqBH,2FAA2F;AAC3F,wBAAgB,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAQzC;AAKD,uFAAuF;AACvF,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;IACtB,IAAI,CAAC,CAAA;IACL,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;CACtC,CAAA;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAOvC;AAyBD,qGAAqG;AACrG,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAK/C;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CA6B5E;AA0CD,wFAAwF;AACxF,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACxB,IAAI,CAAC,CAAA;IACL,OAAO,IAAI,IAAI,CAAA;CAChB,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAmBpD;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA"}
|