@ecopages/core 0.2.0-beta.3 → 0.2.0-beta.31
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/README.md +38 -9
- package/package.json +241 -30
- package/src/adapters/README.md +6 -2
- package/src/adapters/abstract/application-adapter.d.ts +123 -6
- package/src/adapters/abstract/application-adapter.js +151 -1
- package/src/adapters/abstract/segment-path-matcher.d.ts +6 -0
- package/src/adapters/abstract/segment-path-matcher.js +149 -0
- package/src/adapters/abstract/server-adapter.d.ts +16 -2
- package/src/adapters/abstract/ws-pattern-matcher.d.ts +12 -0
- package/src/adapters/abstract/ws-pattern-matcher.js +30 -0
- package/src/adapters/bun/bun-user-websocket-lifecycle.d.ts +22 -0
- package/src/adapters/bun/bun-user-websocket-lifecycle.js +96 -0
- package/src/adapters/bun/client-bridge.d.ts +1 -0
- package/src/adapters/bun/client-bridge.js +3 -0
- package/src/adapters/bun/create-app.d.ts +9 -6
- package/src/adapters/bun/create-app.js +76 -45
- package/src/adapters/bun/hmr-manager.d.ts +1 -1
- package/src/adapters/bun/hmr-manager.js +1 -1
- package/src/adapters/bun/index.d.ts +1 -1
- package/src/adapters/bun/index.js +25 -2
- package/src/adapters/bun/runtime-host.d.ts +1 -1
- package/src/adapters/bun/runtime-host.js +1 -1
- package/src/adapters/bun/server-adapter.d.ts +92 -41
- package/src/adapters/bun/server-adapter.js +256 -117
- package/src/adapters/bun/static-preview-host.d.ts +1 -1
- package/src/adapters/bun/static-preview-host.js +25 -20
- package/src/adapters/create-app.d.ts +13 -11
- package/src/adapters/create-app.js +2 -51
- package/src/adapters/index.d.ts +2 -2
- package/src/adapters/index.js +26 -4
- package/src/adapters/node/create-app.d.ts +8 -3
- package/src/adapters/node/create-app.js +61 -13
- package/src/adapters/node/node-client-bridge.d.ts +1 -0
- package/src/adapters/node/node-client-bridge.js +3 -0
- package/src/adapters/node/node-hmr-manager.d.ts +1 -1
- package/src/adapters/node/node-hmr-manager.js +1 -1
- package/src/adapters/node/runtime-host.d.ts +1 -1
- package/src/adapters/node/runtime-host.js +1 -1
- package/src/adapters/node/server-adapter-dependencies.js +4 -0
- package/src/adapters/node/server-adapter.d.ts +64 -23
- package/src/adapters/node/server-adapter.js +169 -142
- package/src/adapters/node/static-content-server.d.ts +1 -0
- package/src/adapters/node/static-content-server.js +10 -2
- package/src/adapters/node/static-preview-host.d.ts +1 -1
- package/src/adapters/node/static-preview-host.js +27 -12
- package/src/adapters/shared/{hmr-entrypoint-registrar.d.ts → hmr/hmr-entrypoint-registrar.d.ts} +31 -30
- package/src/adapters/shared/hmr/hmr-entrypoint-registrar.js +106 -0
- package/src/adapters/shared/{hmr-html-response.d.ts → hmr/hmr-html-response.d.ts} +2 -2
- package/src/adapters/shared/{hmr-html-response.js → hmr/hmr-html-response.js} +4 -1
- package/src/adapters/shared/hmr/shared-hmr-manager.d.ts +101 -0
- package/src/adapters/shared/hmr/shared-hmr-manager.js +432 -0
- package/src/adapters/shared/http/api-request-pipeline.d.ts +23 -0
- package/src/adapters/shared/http/api-request-pipeline.js +129 -0
- package/src/adapters/shared/{api-response.d.ts → http/api-response.d.ts} +1 -1
- package/src/adapters/shared/{api-response.js → http/api-response.js} +6 -23
- package/src/adapters/shared/http/create-body-response.d.ts +12 -0
- package/src/adapters/shared/http/create-body-response.js +23 -0
- package/src/adapters/shared/http/define-api-handler.d.ts +90 -0
- package/src/adapters/shared/http/define-api-handler.js +63 -0
- package/src/adapters/shared/{explicit-static-render-preparation.d.ts → http/explicit-static-render-preparation.d.ts} +3 -3
- package/src/adapters/shared/{explicit-static-route-matcher.d.ts → http/explicit-static-route-matcher.d.ts} +3 -9
- package/src/adapters/shared/{explicit-static-route-matcher.js → http/explicit-static-route-matcher.js} +3 -38
- package/src/adapters/shared/{file-route-middleware-pipeline.d.ts → http/file-route-middleware-pipeline.d.ts} +2 -2
- package/src/adapters/shared/{file-route-middleware-pipeline.js → http/file-route-middleware-pipeline.js} +10 -22
- package/src/adapters/shared/{fs-server-response-factory.d.ts → http/fs-server-response-factory.d.ts} +7 -2
- package/src/adapters/shared/{fs-server-response-factory.js → http/fs-server-response-factory.js} +22 -2
- package/src/adapters/shared/{fs-server-response-matcher.d.ts → http/fs-server-response-matcher.d.ts} +25 -5
- package/src/adapters/shared/{fs-server-response-matcher.js → http/fs-server-response-matcher.js} +109 -27
- package/src/adapters/shared/http/run-middleware-chain.d.ts +5 -0
- package/src/adapters/shared/http/run-middleware-chain.js +17 -0
- package/src/adapters/shared/{application-adapter.d.ts → runtime/application-adapter.d.ts} +2 -2
- package/src/adapters/shared/{application-adapter.js → runtime/application-adapter.js} +1 -1
- package/src/adapters/shared/runtime/copy-runtime-public-dir.d.ts +6 -0
- package/src/adapters/shared/runtime/copy-runtime-public-dir.js +24 -0
- package/src/adapters/shared/runtime/port-manager.d.ts +116 -0
- package/src/adapters/shared/runtime/port-manager.js +196 -0
- package/src/adapters/shared/{render-context.d.ts → runtime/render-context.d.ts} +2 -2
- package/src/adapters/shared/{render-context.js → runtime/render-context.js} +8 -17
- package/src/adapters/shared/{runtime-app-bootstrap.d.ts → runtime/runtime-app-bootstrap.d.ts} +4 -3
- package/src/adapters/shared/{runtime-app-bootstrap.js → runtime/runtime-app-bootstrap.js} +4 -7
- package/src/adapters/shared/runtime/runtime-server-lifecycle.d.ts +46 -0
- package/src/adapters/shared/runtime/runtime-server-lifecycle.js +57 -0
- package/src/adapters/shared/{server-adapter.d.ts → runtime/server-adapter.d.ts} +23 -49
- package/src/adapters/shared/runtime/server-adapter.js +226 -0
- package/src/adapters/shared/{server-route-handler.d.ts → runtime/server-route-handler.d.ts} +6 -33
- package/src/adapters/shared/{server-route-handler.js → runtime/server-route-handler.js} +5 -43
- package/src/adapters/shared/{server-static-builder.d.ts → runtime/server-static-builder.d.ts} +27 -35
- package/src/adapters/shared/runtime/server-static-builder.js +191 -0
- package/src/adapters/shared/{static-preview-host.d.ts → runtime/static-preview-host.d.ts} +6 -1
- package/src/adapters/shared/ws/node-http-websocket-upgrades.d.ts +21 -0
- package/src/adapters/shared/ws/node-http-websocket-upgrades.js +100 -0
- package/src/adapters/shared/ws/websocket-lifecycle.d.ts +24 -0
- package/src/adapters/shared/ws/websocket-lifecycle.js +55 -0
- package/src/build/README.md +140 -31
- package/src/build/app-build-manifest-runtime.d.ts +39 -0
- package/src/build/app-build-manifest-runtime.js +124 -0
- package/src/build/{browser-runtime-plugin.d.ts → browser/browser-runtime-plugin.d.ts} +1 -1
- package/src/build/{browser-runtime-plugin.js → browser/browser-runtime-plugin.js} +1 -1
- package/src/build/browser/jsx-ownership-plugins.d.ts +24 -0
- package/src/build/browser/jsx-ownership-plugins.js +41 -0
- package/src/build/browser/lit-static-render-worker-context.d.ts +2 -0
- package/src/build/browser/lit-static-render-worker-context.js +6 -0
- package/src/build/build-adapter.d.ts +29 -334
- package/src/build/build-adapter.js +32 -133
- package/src/build/cache/build-input-fingerprint.d.ts +28 -0
- package/src/build/cache/build-input-fingerprint.js +31 -0
- package/src/build/cache/cache-constants.d.ts +4 -0
- package/src/build/cache/cache-constants.js +6 -0
- package/src/build/cache/cache-keys.d.ts +22 -0
- package/src/build/cache/cache-keys.js +63 -0
- package/src/build/cache/dev-browser-script-cache.d.ts +34 -0
- package/src/build/cache/dev-browser-script-cache.js +90 -0
- package/src/build/cache/pages-unified-graph-build.d.ts +31 -0
- package/src/build/cache/pages-unified-graph-build.js +198 -0
- package/src/build/cache/production-build-cache.d.ts +20 -0
- package/src/build/cache/production-build-cache.js +63 -0
- package/src/build/cache/server-entry-build-cache.d.ts +43 -0
- package/src/build/cache/server-entry-build-cache.js +165 -0
- package/src/build/contracts/build-contracts.d.ts +96 -0
- package/src/build/contracts/build-manifest.d.ts +90 -0
- package/src/build/{build-manifest.js → contracts/build-manifest.js} +2 -2
- package/src/build/contracts/build-types.js +0 -0
- package/src/build/{rolldown-adapter-helpers.d.ts → rolldown/rolldown-adapter-helpers.d.ts} +23 -9
- package/src/build/{rolldown-adapter-helpers.js → rolldown/rolldown-adapter-helpers.js} +99 -13
- package/src/build/{rolldown-build-adapter.d.ts → rolldown/rolldown-build-adapter.d.ts} +3 -7
- package/src/build/{rolldown-build-adapter.js → rolldown/rolldown-build-adapter.js} +3 -3
- package/src/build/rolldown/rolldown-build-invocation-metrics.d.ts +12 -0
- package/src/build/rolldown/rolldown-build-invocation-metrics.js +43 -0
- package/src/build/{rolldown-plugin-bridge.d.ts → rolldown/rolldown-plugin-bridge.d.ts} +16 -2
- package/src/build/{rolldown-plugin-bridge.js → rolldown/rolldown-plugin-bridge.js} +21 -6
- package/src/build/rolldown/rolldown-source-transform-pass.d.ts +15 -0
- package/src/build/rolldown/rolldown-source-transform-pass.js +61 -0
- package/src/build/rolldown/runtime-build-output-normalizer.d.ts +10 -0
- package/src/build/rolldown/runtime-build-output-normalizer.js +201 -0
- package/src/build/runtime/build-profile-options.d.ts +7 -0
- package/src/build/runtime/build-profile-options.js +37 -0
- package/src/build/runtime/build-request-identity.d.ts +17 -0
- package/src/build/runtime/build-request-identity.js +54 -0
- package/src/build/runtime/build-request-policy.d.ts +59 -0
- package/src/build/runtime/build-request-policy.js +46 -0
- package/src/build/runtime/build-runtime.d.ts +28 -0
- package/src/build/runtime/build-runtime.js +65 -0
- package/src/build/runtime/deduping-build-executor.d.ts +21 -0
- package/src/build/runtime/deduping-build-executor.js +34 -0
- package/src/build/runtime/parallel-build-executor.d.ts +21 -0
- package/src/build/runtime/parallel-build-executor.js +52 -0
- package/src/build/{serialized-build-executor.d.ts → runtime/serialized-build-executor.d.ts} +1 -1
- package/src/client/navigation-scripts/classification.d.ts +16 -0
- package/src/client/navigation-scripts/classification.js +41 -0
- package/src/client/navigation-scripts/index.d.ts +3 -0
- package/src/client/navigation-scripts/index.js +23 -0
- package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
- package/src/client/navigation-scripts/registry.d.ts +11 -0
- package/src/client/navigation-scripts/registry.js +12 -0
- package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
- package/src/client/navigation-scripts/rerun-queue.js +73 -0
- package/src/client/scroll.d.ts +17 -0
- package/src/client/scroll.js +25 -0
- package/src/client/scroll.test.browser.js +37 -0
- package/src/client/view-transitions.d.ts +16 -0
- package/src/client/view-transitions.js +63 -0
- package/src/config/config-builder.d.ts +25 -10
- package/src/config/config-builder.js +53 -11
- package/src/config/constants.d.ts +1 -0
- package/src/config/constants.js +2 -1
- package/src/dev/client-bridge-registry.d.ts +5 -0
- package/src/dev/client-bridge-registry.js +15 -0
- package/src/dev/dev-client-ownership.d.ts +7 -0
- package/src/dev/dev-client-ownership.js +6 -0
- package/src/dev/hmr-manager-registry.d.ts +8 -0
- package/src/dev/hmr-manager-registry.js +15 -0
- package/src/dev/host-runtime.d.ts +3 -0
- package/src/dev/host-runtime.js +7 -0
- package/src/dev/runtime-server-started-message.d.ts +2 -0
- package/src/dev/runtime-server-started-message.js +6 -0
- package/src/diagnostics/request-build-dedupe.d.ts +18 -0
- package/src/diagnostics/request-build-dedupe.js +33 -0
- package/src/diagnostics/startup-trace.d.ts +72 -0
- package/src/diagnostics/startup-trace.js +253 -0
- package/src/eco/README.md +11 -0
- package/src/eco/eco-declared-component.d.ts +14 -0
- package/src/eco/eco-declared-component.js +16 -0
- package/src/eco/eco.browser.js +5 -6
- package/src/eco/eco.js +7 -8
- package/src/eco/eco.types.d.ts +14 -3
- package/src/eco/eco.utils.d.ts +1 -1
- package/src/eco/eco.utils.js +1 -1
- package/src/eco/page-layout-normalization.d.ts +21 -0
- package/src/eco/page-layout-normalization.js +59 -0
- package/src/env.d.ts +2 -0
- package/src/errors/index.d.ts +1 -0
- package/src/errors/index.js +7 -1
- package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
- package/src/errors/undeclared-component-dependency-error.js +17 -0
- package/src/hmr/client/hmr-runtime.js +7 -4
- package/src/hmr/hmr-entrypoint-output.d.ts +49 -0
- package/src/hmr/hmr-entrypoint-output.js +60 -0
- package/src/hmr/hmr-file-change-prep.d.ts +10 -0
- package/src/hmr/hmr-file-change-prep.js +17 -0
- package/src/hmr/hmr-strategy.d.ts +15 -0
- package/src/hmr/hmr-strategy.js +19 -0
- package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -5
- package/src/hmr/strategies/js-hmr-strategy.js +72 -19
- package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
- package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
- package/src/index.d.ts +2 -1
- package/src/index.js +28 -2
- package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
- package/src/integrations/ghtml/ghtml-renderer.js +2 -51
- package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
- package/src/integrations/ghtml/ghtml.plugin.js +7 -14
- package/src/plugins/alias-resolver-cache.d.ts +6 -9
- package/src/plugins/alias-resolver-plugin.d.ts +3 -3
- package/src/plugins/alias-resolver-plugin.js +38 -51
- package/src/plugins/define-integration.d.ts +26 -0
- package/src/plugins/define-integration.js +19 -0
- package/src/plugins/eco-component-meta-plugin.d.ts +1 -1
- package/src/plugins/eco-component-meta-plugin.js +5 -8
- package/src/plugins/foreign-jsx-override-plugin.d.ts +1 -1
- package/src/plugins/foreign-jsx-override-plugin.js +4 -6
- package/src/plugins/integration-plugin.d.ts +43 -14
- package/src/plugins/integration-plugin.js +18 -5
- package/src/plugins/jsx-import-source.utils.d.ts +8 -0
- package/src/plugins/jsx-import-source.utils.js +26 -0
- package/src/plugins/processor.d.ts +61 -12
- package/src/plugins/processor.js +24 -5
- package/src/plugins/source-transform.d.ts +32 -1
- package/src/plugins/source-transform.js +23 -1
- package/src/plugins/tsconfig-import-resolver.d.ts +18 -0
- package/src/plugins/tsconfig-import-resolver.js +159 -0
- package/src/route-renderer/GRAPH.md +26 -32
- package/src/route-renderer/README.md +38 -31
- package/src/route-renderer/orchestration/document-shell/document-shell-render.service.d.ts +107 -0
- package/src/route-renderer/orchestration/document-shell/document-shell-render.service.js +148 -0
- package/src/route-renderer/orchestration/document-shell/layout-shell-props.service.d.ts +20 -0
- package/src/route-renderer/orchestration/document-shell/layout-shell-props.service.js +31 -0
- package/src/route-renderer/orchestration/{component-render-context.d.ts → foreign-child/component-render-context.d.ts} +8 -15
- package/src/route-renderer/orchestration/{component-render-context.js → foreign-child/component-render-context.js} +4 -2
- package/src/route-renderer/orchestration/{render-output.utils.d.ts → foreign-child/foreign-child-output.utils.d.ts} +17 -7
- package/src/route-renderer/orchestration/{render-output.utils.js → foreign-child/foreign-child-output.utils.js} +35 -26
- package/src/route-renderer/orchestration/{foreign-subtree-execution.service.d.ts → foreign-child/foreign-subtree-execution.service.d.ts} +64 -34
- package/src/route-renderer/orchestration/{foreign-subtree-execution.service.js → foreign-child/foreign-subtree-execution.service.js} +170 -37
- package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.d.ts +19 -0
- package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.js +35 -0
- package/src/route-renderer/orchestration/integration-renderer.d.ts +24 -143
- package/src/route-renderer/orchestration/integration-renderer.js +163 -402
- package/src/route-renderer/orchestration/integration-renderer.test-fixtures.d.ts +75 -0
- package/src/route-renderer/orchestration/integration-renderer.test-fixtures.js +177 -0
- package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.d.ts +10 -0
- package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.js +143 -0
- package/src/route-renderer/orchestration/ownership-graph/component-graph.d.ts +34 -0
- package/src/route-renderer/orchestration/ownership-graph/component-graph.js +96 -0
- package/src/route-renderer/orchestration/{ownership-validation.service.d.ts → ownership-graph/ownership-validation.service.d.ts} +7 -2
- package/src/route-renderer/orchestration/{ownership-validation.service.js → ownership-graph/ownership-validation.service.js} +30 -3
- package/src/route-renderer/orchestration/page-browser-graph/global-injector-assets.service.d.ts +7 -0
- package/src/route-renderer/orchestration/page-browser-graph/global-injector-assets.service.js +32 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-contribution.loader.d.ts +9 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-contribution.loader.js +7 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.d.ts +12 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.js +29 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.d.ts +106 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.js +436 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph.service.d.ts +31 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph.service.js +229 -0
- package/src/route-renderer/orchestration/{processed-asset-dedupe.d.ts → page-browser-graph/processed-asset-dedupe.d.ts} +1 -1
- package/src/route-renderer/orchestration/route-pipeline/integration-route-render-adapter.d.ts +31 -0
- package/src/route-renderer/orchestration/route-pipeline/integration-route-render-adapter.js +25 -0
- package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.d.ts +6 -0
- package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.js +27 -0
- package/src/route-renderer/orchestration/route-pipeline/robots-meta.contribution.d.ts +15 -0
- package/src/route-renderer/orchestration/route-pipeline/robots-meta.contribution.js +36 -0
- package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.d.ts +20 -0
- package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.js +24 -0
- package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.builder.d.ts +25 -0
- package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.builder.js +49 -0
- package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.utils.d.ts +4 -0
- package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.utils.js +33 -0
- package/src/route-renderer/orchestration/{route-render-orchestrator.d.ts → route-pipeline/route-render-orchestrator.d.ts} +13 -53
- package/src/route-renderer/orchestration/route-pipeline/route-render-orchestrator.js +162 -0
- package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
- package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
- package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
- package/src/route-renderer/page-loading/ecopages-virtual-imports.d.ts +6 -0
- package/src/route-renderer/page-loading/ecopages-virtual-imports.js +7 -2
- package/src/route-renderer/page-loading/module-declaration-aggregation.js +4 -0
- package/src/router/client/link-intent.d.ts +11 -21
- package/src/router/client/link-intent.js +10 -0
- package/src/router/client/link-intent.test.browser.js +12 -1
- package/src/router/client/link-navigation-policy.d.ts +45 -0
- package/src/router/client/link-navigation-policy.js +101 -0
- package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
- package/src/router/client/link-navigation-policy.test.browser.js +92 -0
- package/src/router/client/navigation-coordinator.d.ts +1 -1
- package/src/router/client/navigation-coordinator.js +12 -2
- package/src/services/assets/asset-processing-service/asset-dependency-keys.d.ts +13 -0
- package/src/services/assets/asset-processing-service/asset-dependency-keys.js +3 -0
- package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +6 -1
- package/src/services/assets/asset-processing-service/asset-processing.service.js +44 -5
- package/src/services/assets/asset-processing-service/assets.types.d.ts +1 -1
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +2 -1
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry-resolution.d.ts +52 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry-resolution.js +78 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +28 -13
- package/src/services/assets/asset-processing-service/finalize-processed-asset.d.ts +3 -0
- package/src/services/assets/asset-processing-service/finalize-processed-asset.js +7 -0
- package/src/services/assets/asset-processing-service/grouped-content-bundles.d.ts +2 -1
- package/src/services/assets/asset-processing-service/grouped-content-bundles.js +38 -12
- package/src/services/assets/asset-processing-service/index.d.ts +2 -0
- package/src/services/assets/asset-processing-service/index.js +2 -0
- package/src/services/assets/asset-processing-service/inline-content-script-body.d.ts +11 -0
- package/src/services/assets/asset-processing-service/inline-content-script-body.js +17 -0
- package/src/services/assets/asset-processing-service/materialize-content-script-asset.d.ts +9 -0
- package/src/services/assets/asset-processing-service/materialize-content-script-asset.js +18 -0
- package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +0 -2
- package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +2 -15
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +8 -0
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +73 -68
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -1
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +18 -15
- package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
- package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
- package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
- package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
- package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
- package/src/services/assets/asset-processing-service/resolve-integration-plugin.d.ts +4 -0
- package/src/services/assets/asset-processing-service/resolve-integration-plugin.js +17 -0
- package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.d.ts +0 -1
- package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.js +5 -10
- package/src/services/assets/browser-bundle.service.d.ts +28 -30
- package/src/services/assets/browser-bundle.service.js +28 -19
- package/src/services/html/html-transformer.service.d.ts +1 -1
- package/src/services/html/html-transformer.service.js +5 -5
- package/src/services/invalidation/development-invalidation.service.d.ts +25 -2
- package/src/services/invalidation/development-invalidation.service.js +64 -11
- package/src/services/module-loading/README.md +49 -0
- package/src/services/module-loading/app-server-module-transpiler.service.d.ts +8 -0
- package/src/services/module-loading/app-server-module-transpiler.service.js +3 -21
- package/src/services/module-loading/page-module-import.service.d.ts +6 -2
- package/src/services/module-loading/page-module-import.service.js +110 -47
- package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
- package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
- package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
- package/src/services/module-loading/route-module-build-cache.js +38 -0
- package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
- package/src/services/module-loading/route-module-build-cache.store.js +207 -0
- package/src/services/module-loading/route-module-build-manifest.d.ts +54 -0
- package/src/services/module-loading/route-module-build-manifest.js +85 -0
- package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
- package/src/services/module-loading/route-module-dependency-hasher.js +122 -0
- package/src/services/module-loading/server-module-transpiler.service.d.ts +1 -1
- package/src/services/module-loading/server-module-transpiler.service.js +1 -1
- package/src/services/validation/schema-validation-service.d.ts +1 -4
- package/src/services/validation/schema-validation-service.js +12 -13
- package/src/services/validation/standard-schema.types.d.ts +9 -62
- package/src/services/validation/validate-standard-schema.d.ts +7 -0
- package/src/services/validation/validate-standard-schema.js +14 -0
- package/src/static-site-generator/README.md +41 -0
- package/src/static-site-generator/production-page-browser-graph-prebuild.d.ts +28 -0
- package/src/static-site-generator/production-page-browser-graph-prebuild.js +22 -0
- package/src/static-site-generator/sitemap-routes.d.ts +14 -0
- package/src/static-site-generator/sitemap-routes.js +31 -0
- package/src/static-site-generator/sitemap.d.ts +15 -0
- package/src/static-site-generator/sitemap.js +33 -0
- package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
- package/src/static-site-generator/static-build-invalidation.js +59 -0
- package/src/static-site-generator/static-export-context.d.ts +30 -0
- package/src/static-site-generator/static-export-context.js +0 -0
- package/src/static-site-generator/static-site-generator.d.ts +43 -25
- package/src/static-site-generator/static-site-generator.js +381 -106
- package/src/types/internal-types.d.ts +39 -13
- package/src/types/public-types.d.ts +289 -52
- package/src/utils/ecopages-route-info.d.ts +26 -0
- package/src/utils/ecopages-route-info.js +26 -0
- package/src/utils/html-escaping.d.ts +7 -0
- package/src/utils/html-escaping.js +5 -1
- package/src/utils/parse-cli-args.d.ts +2 -0
- package/src/utils/parse-cli-args.js +6 -0
- package/src/utils/path-pattern.d.ts +23 -0
- package/src/utils/path-pattern.js +27 -0
- package/src/utils/server-utils.module.d.ts +3 -2
- package/src/utils/server-utils.module.js +5 -6
- package/src/utils/static-file-extensions.d.ts +12 -0
- package/src/utils/static-file-extensions.js +48 -0
- package/src/watchers/project-watcher-ignore.d.ts +11 -0
- package/src/watchers/project-watcher-ignore.js +16 -0
- package/src/watchers/project-watcher.d.ts +29 -6
- package/src/watchers/project-watcher.js +146 -34
- package/src/watchers/project-watcher.test-helpers.js +5 -5
- package/src/adapters/shared/define-api-handler.d.ts +0 -25
- package/src/adapters/shared/define-api-handler.js +0 -15
- package/src/adapters/shared/hmr-entrypoint-registrar.js +0 -87
- package/src/adapters/shared/server-adapter.js +0 -436
- package/src/adapters/shared/server-static-builder.js +0 -162
- package/src/adapters/shared/shared-hmr-manager.d.ts +0 -59
- package/src/adapters/shared/shared-hmr-manager.js +0 -241
- package/src/build/build-manifest.d.ts +0 -33
- package/src/build/rolldown-dev-build-adapter.d.ts +0 -82
- package/src/build/rolldown-dev-build-adapter.js +0 -166
- package/src/build/runtime-build-executor.d.ts +0 -21
- package/src/build/runtime-build-executor.js +0 -19
- package/src/build/runtime-build-output-normalizer.d.ts +0 -3
- package/src/build/runtime-build-output-normalizer.js +0 -111
- package/src/hmr/hmr.postcss.test.e2e.js +0 -31
- package/src/hmr/hmr.test.e2e.js +0 -43
- package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +0 -18
- package/src/route-renderer/orchestration/declared-ownership-graph.js +0 -34
- package/src/route-renderer/orchestration/ownership-planning.service.d.ts +0 -24
- package/src/route-renderer/orchestration/ownership-planning.service.js +0 -63
- package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +0 -91
- package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +0 -170
- package/src/route-renderer/orchestration/route-render-orchestrator.js +0 -577
- package/src/route-renderer/orchestration/template-serialization.d.ts +0 -38
- package/src/route-renderer/orchestration/template-serialization.js +0 -45
- /package/src/adapters/shared/{explicit-static-render-preparation.js → http/explicit-static-render-preparation.js} +0 -0
- /package/src/adapters/shared/{runtime-host.d.ts → runtime/runtime-host.d.ts} +0 -0
- /package/src/adapters/shared/{runtime-host.js → runtime/runtime-host.js} +0 -0
- /package/src/adapters/shared/{static-preview-host.js → runtime/static-preview-host.js} +0 -0
- /package/src/build/{browser-runtime-manifest.d.ts → browser/browser-runtime-manifest.d.ts} +0 -0
- /package/src/build/{browser-runtime-manifest.js → browser/browser-runtime-manifest.js} +0 -0
- /package/src/build/{browser-runtime-plugin-helpers.d.ts → browser/browser-runtime-plugin-helpers.d.ts} +0 -0
- /package/src/build/{browser-runtime-plugin-helpers.js → browser/browser-runtime-plugin-helpers.js} +0 -0
- /package/src/build/{build-types.js → contracts/build-contracts.js} +0 -0
- /package/src/build/{build-types.d.ts → contracts/build-types.d.ts} +0 -0
- /package/src/build/{server-side-css-shim-plugin.d.ts → rolldown/server-side-css-shim-plugin.d.ts} +0 -0
- /package/src/build/{server-side-css-shim-plugin.js → rolldown/server-side-css-shim-plugin.js} +0 -0
- /package/src/build/{serialized-build-executor.js → runtime/serialized-build-executor.js} +0 -0
- /package/src/{hmr/hmr.postcss.test.e2e.d.ts → client/navigation-scripts/navigation-scripts.test.browser.d.ts} +0 -0
- /package/src/{hmr/hmr.test.e2e.d.ts → client/scroll.test.browser.d.ts} +0 -0
- /package/src/route-renderer/orchestration/{processed-asset-dedupe.js → page-browser-graph/processed-asset-dedupe.js} +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { inspectUnresolvedMarkerArtifactHtml } from "./marker-artifact.utils.js";
|
|
2
|
+
import {
|
|
3
|
+
OwnershipValidationService,
|
|
4
|
+
throwIfOwnershipInvalid
|
|
5
|
+
} from "../ownership-graph/ownership-validation.service.js";
|
|
6
|
+
import {
|
|
7
|
+
buildEagerSsrLazyAssetsFromGraph,
|
|
8
|
+
collectResolvedLazyTriggersFromGraph,
|
|
9
|
+
collectUsedIntegrationDependenciesFromGraph
|
|
10
|
+
} from "../ownership-graph/component-graph-collectors.js";
|
|
11
|
+
import { buildGlobalInjectorAssets } from "../page-browser-graph/global-injector-assets.service.js";
|
|
12
|
+
import { PageBrowserGraphService } from "../page-browser-graph/page-browser-graph.service.js";
|
|
13
|
+
import { buildPreparedRenderOptions } from "./route-prepared-options.builder.js";
|
|
14
|
+
class RouteRenderOrchestrator {
|
|
15
|
+
appConfig;
|
|
16
|
+
assetProcessingService;
|
|
17
|
+
ownershipValidationService;
|
|
18
|
+
pageBrowserGraphService;
|
|
19
|
+
constructor(appConfig, assetProcessingService, dependencies = {}) {
|
|
20
|
+
this.appConfig = appConfig;
|
|
21
|
+
this.assetProcessingService = assetProcessingService;
|
|
22
|
+
this.ownershipValidationService = dependencies.ownershipValidationService ?? new OwnershipValidationService(appConfig);
|
|
23
|
+
this.pageBrowserGraphService = dependencies.pageBrowserGraphService ?? new PageBrowserGraphService(appConfig, assetProcessingService);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Builds normalized route render options before the integration render runs.
|
|
27
|
+
*
|
|
28
|
+
* This preparation step validates route-root ownership, resolves page data,
|
|
29
|
+
* collects processed assets, and produces the page package consumed by downstream
|
|
30
|
+
* HTML transformation.
|
|
31
|
+
*/
|
|
32
|
+
async prepareRenderOptions(routeOptions, adapter) {
|
|
33
|
+
const resolvedInputs = await adapter.resolveRouteRenderInputs(routeOptions);
|
|
34
|
+
const { Page, HtmlTemplate, Layouts } = resolvedInputs;
|
|
35
|
+
const validationErrors = this.ownershipValidationService.validate({
|
|
36
|
+
currentIntegrationName: adapter.name,
|
|
37
|
+
roots: [
|
|
38
|
+
{ component: HtmlTemplate, source: "html-template" },
|
|
39
|
+
...Layouts.map((layout) => ({ component: layout, source: "layout" })),
|
|
40
|
+
{ component: Page, source: "page" }
|
|
41
|
+
]
|
|
42
|
+
});
|
|
43
|
+
throwIfOwnershipInvalid(validationErrors);
|
|
44
|
+
const componentsToResolve = [HtmlTemplate, ...Layouts, Page];
|
|
45
|
+
const [{ resolvedDependencies }, pageBrowserGraph] = await Promise.all([
|
|
46
|
+
adapter.resolveRouteDependencies({
|
|
47
|
+
components: componentsToResolve
|
|
48
|
+
}),
|
|
49
|
+
this.pageBrowserGraphService.resolvePageBrowserGraph({
|
|
50
|
+
routeFile: routeOptions.file,
|
|
51
|
+
integrationName: adapter.name,
|
|
52
|
+
collectContribution: async (routeFile) => await adapter.collectPageBrowserGraphContribution(routeFile)
|
|
53
|
+
})
|
|
54
|
+
]);
|
|
55
|
+
const allDependencies = [
|
|
56
|
+
...resolvedDependencies,
|
|
57
|
+
...collectUsedIntegrationDependenciesFromGraph(this.appConfig, componentsToResolve, adapter.name)
|
|
58
|
+
];
|
|
59
|
+
const triggers = collectResolvedLazyTriggersFromGraph(componentsToResolve, adapter.name);
|
|
60
|
+
const [globalAssets, eagerSsrLazyAssets] = await Promise.all([
|
|
61
|
+
triggers.length > 0 ? buildGlobalInjectorAssets(this.appConfig, this.assetProcessingService, triggers, adapter.name) : Promise.resolve([]),
|
|
62
|
+
buildEagerSsrLazyAssetsFromGraph(this.assetProcessingService, componentsToResolve, adapter.name)
|
|
63
|
+
]);
|
|
64
|
+
allDependencies.push(...globalAssets, ...eagerSsrLazyAssets);
|
|
65
|
+
return buildPreparedRenderOptions({
|
|
66
|
+
routeOptions,
|
|
67
|
+
resolvedInputs,
|
|
68
|
+
resolvedDependencies,
|
|
69
|
+
allDependencies,
|
|
70
|
+
pageBrowserGraph,
|
|
71
|
+
appConfig: this.appConfig
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async resolveDeclaredPageBrowserGraph(input) {
|
|
75
|
+
return await this.pageBrowserGraphService.resolvePageBrowserGraph(input);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Captures one route render body as HTML while preserving a replayable body value.
|
|
79
|
+
*/
|
|
80
|
+
async captureHtmlRender(render) {
|
|
81
|
+
const renderedBody = await render();
|
|
82
|
+
const capturedRender = await this.captureRenderedBody(renderedBody);
|
|
83
|
+
return {
|
|
84
|
+
body: capturedRender.body,
|
|
85
|
+
html: capturedRender.html
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Executes the full route-render flow and returns the final body plus cache strategy.
|
|
90
|
+
*/
|
|
91
|
+
async execute(options, adapter) {
|
|
92
|
+
const renderOptions = await this.prepareRenderOptions(options, adapter);
|
|
93
|
+
return this.executePrepared(renderOptions, adapter);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Executes the route-render finalization path for already prepared render options.
|
|
97
|
+
*/
|
|
98
|
+
async executePrepared(renderOptions, adapter) {
|
|
99
|
+
const renderExecution = await this.captureHtmlRender(async () => adapter.renderRouteBody(renderOptions));
|
|
100
|
+
const unresolvedArtifactInspection = inspectUnresolvedMarkerArtifactHtml(renderExecution.html);
|
|
101
|
+
const htmlFinalization = adapter.getRouteHtmlFinalization(renderOptions);
|
|
102
|
+
const hasUnresolvedMarkerHtml = unresolvedArtifactInspection.hasUnresolvedMarkerArtifacts;
|
|
103
|
+
if (hasUnresolvedMarkerHtml) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
"[ecopages] Route render returned unresolved eco-marker artifact HTML. Full-route unresolved-marker fallback has been removed; resolve mixed foreign children inside renderComponentWithForeignChildren()."
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
const canReuseCapturedBody = !hasUnresolvedMarkerHtml && htmlFinalization.finalizeHtml === void 0;
|
|
109
|
+
if (canReuseCapturedBody) {
|
|
110
|
+
const body2 = await adapter.transformRouteResponse(
|
|
111
|
+
new Response(renderExecution.body, {
|
|
112
|
+
headers: {
|
|
113
|
+
"Content-Type": "text/html"
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
htmlFinalization.htmlContributions,
|
|
117
|
+
renderOptions.pagePackage
|
|
118
|
+
);
|
|
119
|
+
return {
|
|
120
|
+
body: body2,
|
|
121
|
+
cacheStrategy: renderOptions.cacheStrategy
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const finalization = htmlFinalization.finalizeHtml ? htmlFinalization.finalizeHtml(unresolvedArtifactInspection.normalizedHtml) : unresolvedArtifactInspection.normalizedHtml;
|
|
125
|
+
const body = await adapter.transformRouteResponse(
|
|
126
|
+
new Response(finalization, {
|
|
127
|
+
headers: {
|
|
128
|
+
"Content-Type": "text/html"
|
|
129
|
+
}
|
|
130
|
+
}),
|
|
131
|
+
htmlFinalization.htmlContributions,
|
|
132
|
+
renderOptions.pagePackage
|
|
133
|
+
);
|
|
134
|
+
return {
|
|
135
|
+
body,
|
|
136
|
+
cacheStrategy: renderOptions.cacheStrategy
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
async captureRenderedBody(body) {
|
|
140
|
+
const response = new Response(body);
|
|
141
|
+
if (typeof body === "string") {
|
|
142
|
+
return {
|
|
143
|
+
body,
|
|
144
|
+
html: await response.text()
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (!response.body) {
|
|
148
|
+
return {
|
|
149
|
+
body,
|
|
150
|
+
html: await response.text()
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const [capturedBody, replayBody] = response.body.tee();
|
|
154
|
+
return {
|
|
155
|
+
body: replayBody,
|
|
156
|
+
html: await new Response(capturedBody).text()
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export {
|
|
161
|
+
RouteRenderOrchestrator
|
|
162
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ComponentRenderInput, ComponentRenderResult, EcoComponent, EcoPagesElement, IntegrationRendererRenderOptions, RouteRendererBody } from '../../types/public-types.js';
|
|
2
|
+
import { IntegrationRenderer, type RenderToResponseContext } from './integration-renderer.js';
|
|
3
|
+
/**
|
|
4
|
+
* Base renderer for integrations whose page output is string HTML markup.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Ghtml, KitaJS, and MDX share the same document-shell rendering path. Subclasses
|
|
8
|
+
* only need to set `name` and override hooks for integration-specific behavior.
|
|
9
|
+
*/
|
|
10
|
+
export declare abstract class StringMarkupRenderer extends IntegrationRenderer<EcoPagesElement> {
|
|
11
|
+
renderComponent(input: ComponentRenderInput): Promise<ComponentRenderResult>;
|
|
12
|
+
render({ params, query, props, locals, pageLocals, metadata, Page, Layout, HtmlTemplate, pageProps, }: IntegrationRendererRenderOptions): Promise<RouteRendererBody>;
|
|
13
|
+
renderToResponse<P = Record<string, unknown>>(view: EcoComponent<P>, props: P, ctx: RenderToResponseContext): Promise<Response>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { IntegrationRenderer } from "./integration-renderer.js";
|
|
2
|
+
import { resolveInnermostPageLayout } from "./document-shell/layout-shell-props.service.js";
|
|
3
|
+
class StringMarkupRenderer extends IntegrationRenderer {
|
|
4
|
+
async renderComponent(input) {
|
|
5
|
+
if (typeof input.component !== "function") {
|
|
6
|
+
throw new TypeError(`${this.name} renderer expected a callable component.`);
|
|
7
|
+
}
|
|
8
|
+
return this.renderStringComponentWithQueuedForeignSubtrees(input, input.component);
|
|
9
|
+
}
|
|
10
|
+
async render({
|
|
11
|
+
params,
|
|
12
|
+
query,
|
|
13
|
+
props,
|
|
14
|
+
locals,
|
|
15
|
+
pageLocals,
|
|
16
|
+
metadata,
|
|
17
|
+
Page,
|
|
18
|
+
Layout,
|
|
19
|
+
HtmlTemplate,
|
|
20
|
+
pageProps
|
|
21
|
+
}) {
|
|
22
|
+
try {
|
|
23
|
+
return await this.renderPageWithDocumentShell({
|
|
24
|
+
page: {
|
|
25
|
+
component: Page,
|
|
26
|
+
props: { params, query, ...props, locals: pageLocals }
|
|
27
|
+
},
|
|
28
|
+
layout: Layout ? {
|
|
29
|
+
component: Layout,
|
|
30
|
+
props: locals ? { locals } : {}
|
|
31
|
+
} : void 0,
|
|
32
|
+
htmlTemplate: HtmlTemplate,
|
|
33
|
+
metadata,
|
|
34
|
+
pageProps: pageProps ?? props ?? {}
|
|
35
|
+
});
|
|
36
|
+
} catch (error) {
|
|
37
|
+
throw this.createRenderError("Error rendering page", error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async renderToResponse(view, props, ctx) {
|
|
41
|
+
try {
|
|
42
|
+
return await this.renderViewWithDocumentShell({
|
|
43
|
+
view,
|
|
44
|
+
props,
|
|
45
|
+
ctx,
|
|
46
|
+
layout: resolveInnermostPageLayout(view.config?.layouts)
|
|
47
|
+
});
|
|
48
|
+
} catch (error) {
|
|
49
|
+
throw this.createRenderError("Error rendering view", error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
StringMarkupRenderer
|
|
55
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import { assertEcoDeclaredComponent } from "../../eco/eco-declared-component.js";
|
|
2
3
|
import { AssetFactory } from "../../services/assets/asset-processing-service/index.js";
|
|
3
4
|
import { extractEcopagesVirtualImports } from "./ecopages-virtual-imports.js";
|
|
4
5
|
import { collectDeclaredAssetEntries } from "./declared-asset-collection.js";
|
|
@@ -103,9 +104,11 @@ function collectComponentDependencies(options) {
|
|
|
103
104
|
});
|
|
104
105
|
if (dependenciesConfig?.components) {
|
|
105
106
|
for (const nestedComponent of dependenciesConfig.components) {
|
|
106
|
-
if (nestedComponent
|
|
107
|
-
|
|
107
|
+
if (!nestedComponent) {
|
|
108
|
+
continue;
|
|
108
109
|
}
|
|
110
|
+
assertEcoDeclaredComponent(nestedComponent, { parentComponentFile: file });
|
|
111
|
+
collect(nestedComponent.config);
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
};
|
|
@@ -2,6 +2,12 @@ export type EcopagesVirtualImport = {
|
|
|
2
2
|
from: string;
|
|
3
3
|
imports: string[] | undefined;
|
|
4
4
|
};
|
|
5
|
+
/**
|
|
6
|
+
* @remarks
|
|
7
|
+
* Content server modules static-import every MDX entry. They must never become
|
|
8
|
+
* browser module-script dependencies discovered from page or component sources.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isBrowserEcopagesVirtualImport(specifier: string): boolean;
|
|
5
11
|
/**
|
|
6
12
|
* Extracts runtime `ecopages:` virtual-module imports from a component source file.
|
|
7
13
|
*
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { parseSync } from "oxc-parser";
|
|
3
|
+
const CONTENT_SERVER_VIRTUAL_MODULE_PATTERN = /^ecopages:content\/[a-z][a-z0-9-]+\/server$/;
|
|
4
|
+
function isBrowserEcopagesVirtualImport(specifier) {
|
|
5
|
+
return specifier.startsWith("ecopages:") && !CONTENT_SERVER_VIRTUAL_MODULE_PATTERN.test(specifier);
|
|
6
|
+
}
|
|
3
7
|
function extractEcopagesVirtualImports(file) {
|
|
4
8
|
let source;
|
|
5
9
|
try {
|
|
@@ -18,7 +22,7 @@ function extractEcopagesVirtualImports(file) {
|
|
|
18
22
|
if (node.type !== "ImportDeclaration") continue;
|
|
19
23
|
if (node.importKind === "type") continue;
|
|
20
24
|
const specifier = node.source?.value ?? "";
|
|
21
|
-
if (!specifier
|
|
25
|
+
if (!isBrowserEcopagesVirtualImport(specifier)) continue;
|
|
22
26
|
if (found.get(specifier) === null) {
|
|
23
27
|
continue;
|
|
24
28
|
}
|
|
@@ -53,5 +57,6 @@ function extractEcopagesVirtualImports(file) {
|
|
|
53
57
|
}));
|
|
54
58
|
}
|
|
55
59
|
export {
|
|
56
|
-
extractEcopagesVirtualImports
|
|
60
|
+
extractEcopagesVirtualImports,
|
|
61
|
+
isBrowserEcopagesVirtualImport
|
|
57
62
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeModuleDeclarations } from "../../eco/module-dependencies.js";
|
|
2
|
+
import { isBrowserEcopagesVirtualImport } from "./ecopages-virtual-imports.js";
|
|
2
3
|
function getDeclaredModules(value) {
|
|
3
4
|
if (!Array.isArray(value)) {
|
|
4
5
|
return void 0;
|
|
@@ -22,6 +23,9 @@ function mergeModuleDeclaration(modulesMap, declaration) {
|
|
|
22
23
|
}
|
|
23
24
|
function collectModuleDeclarations(modulesMap, declaredModules, autoVirtualImports) {
|
|
24
25
|
for (const declaration of normalizeModuleDeclarations(getDeclaredModules(declaredModules))) {
|
|
26
|
+
if (declaration.from.startsWith("ecopages:") && !isBrowserEcopagesVirtualImport(declaration.from)) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
25
29
|
mergeModuleDeclaration(modulesMap, declaration);
|
|
26
30
|
}
|
|
27
31
|
for (const declaration of autoVirtualImports) {
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* Timestamped navigation intent captured from pointer or hover activity.
|
|
16
16
|
*/
|
|
17
17
|
export type EcoPendingNavigationIntent = {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
href: string;
|
|
19
|
+
timestamp: number;
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
22
22
|
* Finds the nearest matching anchor within an event's composed path.
|
|
@@ -28,26 +28,16 @@ export type EcoPendingNavigationIntent = {
|
|
|
28
28
|
* @param linkSelector - Selector that identifies navigable anchors.
|
|
29
29
|
* @returns The matched anchor element, or `null` when no matching anchor exists.
|
|
30
30
|
*/
|
|
31
|
-
export declare function getAnchorFromNavigationEvent(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
export declare function getAnchorFromNavigationEvent(event: MouseEvent | PointerEvent, linkSelector: string): HTMLAnchorElement | null;
|
|
32
|
+
/**
|
|
33
|
+
* Returns whether an href targets a static asset that should use a full document load.
|
|
34
|
+
*/
|
|
35
|
+
export declare function isStaticAssetHref(href: string): boolean;
|
|
35
36
|
/**
|
|
36
37
|
* Resolves a previously captured intent while a navigation is still in flight.
|
|
37
38
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* @param intent - Previously captured pointer or hover intent.
|
|
43
|
-
* @param hasInFlightNavigation - Whether a router navigation is still active.
|
|
44
|
-
* @param now - Current monotonic timestamp, usually from `performance.now()`.
|
|
45
|
-
* @param maxAgeMs - Maximum allowed age for the recovered intent.
|
|
46
|
-
* @returns The intended href when still valid, otherwise `null`.
|
|
39
|
+
* @remarks
|
|
40
|
+
* Pending intents expire quickly because they bridge pointer or hover capture
|
|
41
|
+
* and the later click when the DOM changes during a rapid navigation sequence.
|
|
47
42
|
*/
|
|
48
|
-
export declare function recoverPendingNavigationHref(
|
|
49
|
-
intent: EcoPendingNavigationIntent | null,
|
|
50
|
-
hasInFlightNavigation: boolean,
|
|
51
|
-
now: number,
|
|
52
|
-
maxAgeMs?: number,
|
|
53
|
-
): string | null;
|
|
43
|
+
export declare function recoverPendingNavigationHref(intent: EcoPendingNavigationIntent | null, hasInFlightNavigation: boolean, now: number, maxAgeMs?: number): string | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hasKnownStaticExtension } from "../../utils/static-file-extensions.js";
|
|
1
2
|
function getAnchorFromNavigationEvent(event, linkSelector) {
|
|
2
3
|
const eventTarget = event.target;
|
|
3
4
|
if (eventTarget instanceof HTMLAnchorElement && eventTarget.matches(linkSelector)) {
|
|
@@ -19,6 +20,14 @@ function getAnchorFromNavigationEvent(event, linkSelector) {
|
|
|
19
20
|
(target) => target instanceof HTMLAnchorElement && target.matches(linkSelector)
|
|
20
21
|
);
|
|
21
22
|
}
|
|
23
|
+
function isStaticAssetHref(href) {
|
|
24
|
+
try {
|
|
25
|
+
const url = new URL(href, "http://localhost");
|
|
26
|
+
return hasKnownStaticExtension(url.pathname);
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
22
31
|
function recoverPendingNavigationHref(intent, hasInFlightNavigation, now, maxAgeMs = 1e3) {
|
|
23
32
|
if (!intent || !hasInFlightNavigation) {
|
|
24
33
|
return null;
|
|
@@ -30,5 +39,6 @@ function recoverPendingNavigationHref(intent, hasInFlightNavigation, now, maxAge
|
|
|
30
39
|
}
|
|
31
40
|
export {
|
|
32
41
|
getAnchorFromNavigationEvent,
|
|
42
|
+
isStaticAssetHref,
|
|
33
43
|
recoverPendingNavigationHref
|
|
34
44
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getAnchorFromNavigationEvent, recoverPendingNavigationHref } from "./link-intent.js";
|
|
2
|
+
import { getAnchorFromNavigationEvent, isStaticAssetHref, recoverPendingNavigationHref } from "./link-intent.js";
|
|
3
3
|
describe("getAnchorFromNavigationEvent", () => {
|
|
4
4
|
it("returns the anchor when the event target is a text node inside it", () => {
|
|
5
5
|
const anchor = document.createElement("a");
|
|
@@ -31,6 +31,17 @@ describe("getAnchorFromNavigationEvent", () => {
|
|
|
31
31
|
expect(getAnchorFromNavigationEvent(event, "a[data-eco-link]")).toBe(anchor);
|
|
32
32
|
});
|
|
33
33
|
});
|
|
34
|
+
describe("isStaticAssetHref", () => {
|
|
35
|
+
it("returns true for known static asset paths", () => {
|
|
36
|
+
expect(isStaticAssetHref("/skill.txt")).toBe(true);
|
|
37
|
+
expect(isStaticAssetHref("/skill/reference/full-stack.md")).toBe(true);
|
|
38
|
+
expect(isStaticAssetHref("/assets/logo.png")).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it("returns false for application routes", () => {
|
|
41
|
+
expect(isStaticAssetHref("/docs/getting-started/introduction")).toBe(false);
|
|
42
|
+
expect(isStaticAssetHref("/")).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
34
45
|
describe("recoverPendingNavigationHref", () => {
|
|
35
46
|
it("returns null for stale or missing pending intent state", () => {
|
|
36
47
|
expect(recoverPendingNavigationHref(null, true, 10)).toBeNull();
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical link interception, prefetch eligibility, and HTML fetch guards.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
export type LinkNavigationPolicyOptions = {
|
|
6
|
+
/** Attribute that forces a full document reload instead of SPA navigation. */
|
|
7
|
+
reloadAttribute?: string;
|
|
8
|
+
/** Attribute that opts a link out of prefetch. */
|
|
9
|
+
noPrefetchAttribute?: string;
|
|
10
|
+
};
|
|
11
|
+
export type LinkNavigationDecision = {
|
|
12
|
+
shouldIntercept: true;
|
|
13
|
+
href: string;
|
|
14
|
+
} | {
|
|
15
|
+
shouldIntercept: false;
|
|
16
|
+
reason: 'modified-click' | 'non-left-click' | 'external-target' | 'explicit-reload' | 'download' | 'no-prefetch' | 'invalid-href' | 'cross-origin' | 'static-asset' | 'same-page-hash';
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Returns whether an href only adds a hash fragment on the current page.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isSamePageHashNavigationHref(href: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Decides whether a pointer or click on an anchor should be handled as SPA navigation.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getLinkNavigationDecision(event: MouseEvent | PointerEvent, link: HTMLAnchorElement, options: LinkNavigationPolicyOptions): LinkNavigationDecision;
|
|
26
|
+
/**
|
|
27
|
+
* Returns the href when SPA navigation should intercept the click, otherwise `null`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getNavigableHrefFromClick(event: MouseEvent | PointerEvent, link: HTMLAnchorElement, options: LinkNavigationPolicyOptions): string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Returns whether a link is eligible for hover or viewport prefetch.
|
|
32
|
+
*/
|
|
33
|
+
export declare function shouldPrefetchLink(link: HTMLAnchorElement, options: LinkNavigationPolicyOptions): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* @remarks
|
|
36
|
+
* Prefetch and SPA fetches request HTML. Only explicit `text/html` and
|
|
37
|
+
* `application/xhtml+xml` responses are accepted; missing or asset types are rejected.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isHtmlPageResponse(response: Response): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* @remarks
|
|
42
|
+
* Servers should send `text/html`. When the type is missing or the runtime
|
|
43
|
+
* defaults to `text/plain` (common in tests), a document-shaped body is accepted.
|
|
44
|
+
*/
|
|
45
|
+
export declare function assertHtmlPageResponse(response: Response): Promise<void>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { isStaticAssetHref } from "./link-intent.js";
|
|
2
|
+
function getLinkIneligibilityReason(link, options) {
|
|
3
|
+
if (options.noPrefetchAttribute && link.hasAttribute(options.noPrefetchAttribute)) {
|
|
4
|
+
return "no-prefetch";
|
|
5
|
+
}
|
|
6
|
+
if (options.reloadAttribute && link.hasAttribute(options.reloadAttribute)) {
|
|
7
|
+
return "explicit-reload";
|
|
8
|
+
}
|
|
9
|
+
if (link.hasAttribute("download")) {
|
|
10
|
+
return "download";
|
|
11
|
+
}
|
|
12
|
+
const href = link.getAttribute("href");
|
|
13
|
+
if (!href || href.startsWith("#") || href.startsWith("javascript:")) {
|
|
14
|
+
return "invalid-href";
|
|
15
|
+
}
|
|
16
|
+
const url = new URL(href, window.location.origin);
|
|
17
|
+
if (url.origin !== window.location.origin) {
|
|
18
|
+
return "cross-origin";
|
|
19
|
+
}
|
|
20
|
+
if (isStaticAssetHref(href)) {
|
|
21
|
+
return "static-asset";
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
function isSamePageHashNavigationHref(href) {
|
|
26
|
+
if (!href) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const currentUrl = new URL(window.location.href);
|
|
30
|
+
const targetUrl = new URL(href, currentUrl);
|
|
31
|
+
return targetUrl.origin === currentUrl.origin && targetUrl.hash.length > 0 && targetUrl.pathname === currentUrl.pathname && targetUrl.search === currentUrl.search;
|
|
32
|
+
}
|
|
33
|
+
function getLinkNavigationDecision(event, link, options) {
|
|
34
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
35
|
+
return { shouldIntercept: false, reason: "modified-click" };
|
|
36
|
+
}
|
|
37
|
+
if (event.button !== 0) {
|
|
38
|
+
return { shouldIntercept: false, reason: "non-left-click" };
|
|
39
|
+
}
|
|
40
|
+
const target = link.getAttribute("target");
|
|
41
|
+
if (target && target !== "_self") {
|
|
42
|
+
return { shouldIntercept: false, reason: "external-target" };
|
|
43
|
+
}
|
|
44
|
+
const ineligibility = getLinkIneligibilityReason(link, options);
|
|
45
|
+
if (ineligibility) {
|
|
46
|
+
return { shouldIntercept: false, reason: ineligibility };
|
|
47
|
+
}
|
|
48
|
+
const href = link.getAttribute("href");
|
|
49
|
+
if (isSamePageHashNavigationHref(href)) {
|
|
50
|
+
return { shouldIntercept: false, reason: "same-page-hash" };
|
|
51
|
+
}
|
|
52
|
+
return { shouldIntercept: true, href };
|
|
53
|
+
}
|
|
54
|
+
function getNavigableHrefFromClick(event, link, options) {
|
|
55
|
+
const decision = getLinkNavigationDecision(event, link, options);
|
|
56
|
+
return decision.shouldIntercept ? decision.href : null;
|
|
57
|
+
}
|
|
58
|
+
function shouldPrefetchLink(link, options) {
|
|
59
|
+
if (getLinkIneligibilityReason(link, options)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const href = link.getAttribute("href");
|
|
63
|
+
try {
|
|
64
|
+
const url = new URL(href, window.location.origin);
|
|
65
|
+
const currentPath = window.location.pathname + window.location.search;
|
|
66
|
+
const targetPath = url.pathname + url.search;
|
|
67
|
+
return currentPath !== targetPath;
|
|
68
|
+
} catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function isHtmlPageResponse(response) {
|
|
73
|
+
const contentType = response.headers.get("Content-Type");
|
|
74
|
+
if (!contentType) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const normalized = contentType.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
78
|
+
return normalized === "text/html" || normalized === "application/xhtml+xml";
|
|
79
|
+
}
|
|
80
|
+
async function assertHtmlPageResponse(response) {
|
|
81
|
+
if (isHtmlPageResponse(response)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const contentType = response.headers.get("Content-Type");
|
|
85
|
+
const normalized = contentType?.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
86
|
+
if (normalized === "text/plain" || normalized === "") {
|
|
87
|
+
const sample = (await response.clone().text()).trimStart();
|
|
88
|
+
if (sample.startsWith("<")) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
throw new Error(`Expected HTML page response, received ${contentType ?? "unknown content type"}`);
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
assertHtmlPageResponse,
|
|
96
|
+
getLinkNavigationDecision,
|
|
97
|
+
getNavigableHrefFromClick,
|
|
98
|
+
isHtmlPageResponse,
|
|
99
|
+
isSamePageHashNavigationHref,
|
|
100
|
+
shouldPrefetchLink
|
|
101
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
getLinkNavigationDecision,
|
|
4
|
+
getNavigableHrefFromClick,
|
|
5
|
+
isHtmlPageResponse,
|
|
6
|
+
isSamePageHashNavigationHref,
|
|
7
|
+
shouldPrefetchLink
|
|
8
|
+
} from "./link-navigation-policy.js";
|
|
9
|
+
function createLink(href, attributes = {}) {
|
|
10
|
+
const link = document.createElement("a");
|
|
11
|
+
link.href = href;
|
|
12
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
13
|
+
link.setAttribute(key, value);
|
|
14
|
+
}
|
|
15
|
+
document.body.append(link);
|
|
16
|
+
return link;
|
|
17
|
+
}
|
|
18
|
+
function createMouseEvent(button = 0, modifiers = {}) {
|
|
19
|
+
return new MouseEvent("click", { bubbles: true, cancelable: true, button, ...modifiers });
|
|
20
|
+
}
|
|
21
|
+
const policy = { reloadAttribute: "data-eco-reload", noPrefetchAttribute: "data-eco-no-prefetch" };
|
|
22
|
+
describe("isSamePageHashNavigationHref", () => {
|
|
23
|
+
it("returns true for same pathname with a new hash", () => {
|
|
24
|
+
history.replaceState({}, "", "/docs/page");
|
|
25
|
+
expect(isSamePageHashNavigationHref("/docs/page#section")).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe("getLinkNavigationDecision", () => {
|
|
29
|
+
it("allows same-origin page links", () => {
|
|
30
|
+
const link = createLink("/page");
|
|
31
|
+
const decision = getLinkNavigationDecision(createMouseEvent(), link, policy);
|
|
32
|
+
expect(decision).toEqual({ shouldIntercept: true, href: "/page" });
|
|
33
|
+
});
|
|
34
|
+
it("rejects static asset links", () => {
|
|
35
|
+
const link = createLink("/skill.txt");
|
|
36
|
+
expect(getLinkNavigationDecision(createMouseEvent(), link, policy)).toEqual({
|
|
37
|
+
shouldIntercept: false,
|
|
38
|
+
reason: "static-asset"
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
it("rejects explicit reload links", () => {
|
|
42
|
+
const link = createLink("/logout", { "data-eco-reload": "" });
|
|
43
|
+
expect(getLinkNavigationDecision(createMouseEvent(), link, policy)).toEqual({
|
|
44
|
+
shouldIntercept: false,
|
|
45
|
+
reason: "explicit-reload"
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe("getNavigableHrefFromClick", () => {
|
|
50
|
+
it("returns href when navigation should be intercepted", () => {
|
|
51
|
+
const link = createLink("/page");
|
|
52
|
+
expect(getNavigableHrefFromClick(createMouseEvent(), link, policy)).toBe("/page");
|
|
53
|
+
});
|
|
54
|
+
it("returns null for static assets", () => {
|
|
55
|
+
const link = createLink("/llms.txt");
|
|
56
|
+
expect(getNavigableHrefFromClick(createMouseEvent(), link, policy)).toBeNull();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe("shouldPrefetchLink", () => {
|
|
60
|
+
it("prefetches internal page links", () => {
|
|
61
|
+
history.replaceState({}, "", "/");
|
|
62
|
+
const link = createLink("/docs/intro");
|
|
63
|
+
expect(shouldPrefetchLink(link, policy)).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
it("skips static assets and opt-outs", () => {
|
|
66
|
+
history.replaceState({}, "", "/");
|
|
67
|
+
expect(shouldPrefetchLink(createLink("/skill.txt"), policy)).toBe(false);
|
|
68
|
+
expect(shouldPrefetchLink(createLink("/page", { "data-eco-no-prefetch": "" }), policy)).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe("isHtmlPageResponse", () => {
|
|
72
|
+
it("accepts html content types", () => {
|
|
73
|
+
expect(isHtmlPageResponse(new Response("", { headers: { "Content-Type": "text/html; charset=utf-8" } }))).toBe(
|
|
74
|
+
true
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
it("rejects plain text responses", () => {
|
|
78
|
+
expect(isHtmlPageResponse(new Response("", { headers: { "Content-Type": "text/plain" } }))).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("isHtmlPageResponse", () => {
|
|
82
|
+
it("accepts html and xhtml content types", () => {
|
|
83
|
+
expect(isHtmlPageResponse(new Response("", { headers: { "Content-Type": "text/html" } }))).toBe(true);
|
|
84
|
+
expect(isHtmlPageResponse(new Response("", { headers: { "Content-Type": "application/xhtml+xml" } }))).toBe(
|
|
85
|
+
true
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
it("rejects plain text and markdown responses", () => {
|
|
89
|
+
expect(isHtmlPageResponse(new Response("text", { headers: { "Content-Type": "text/plain" } }))).toBe(false);
|
|
90
|
+
expect(isHtmlPageResponse(new Response("# doc", { headers: { "Content-Type": "text/markdown" } }))).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -96,7 +96,7 @@ export type EcoNavigationRuntimeRegistration = {
|
|
|
96
96
|
* Implementations may honor `request.moduleUrl` to force a specific page entry
|
|
97
97
|
* and `request.clearCache` to discard persisted runtime state before reloading.
|
|
98
98
|
*/
|
|
99
|
-
reloadCurrentPage?: (request?: EcoReloadRequest) => Promise<void>;
|
|
99
|
+
reloadCurrentPage?: (request?: EcoReloadRequest) => Promise<boolean | void>;
|
|
100
100
|
/**
|
|
101
101
|
* Releases runtime-owned client state before another runtime commits a new
|
|
102
102
|
* document.
|