@ecopages/core 0.2.0-alpha.8 → 0.2.1
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 +18 -11
- package/README.md +23 -26
- package/package.json +76 -58
- package/src/adapters/README.md +2 -2
- package/src/adapters/abstract/application-adapter.d.ts +28 -2
- package/src/adapters/abstract/application-adapter.js +14 -2
- package/src/adapters/abstract/router-adapter.d.ts +1 -1
- package/src/adapters/abstract/server-adapter.d.ts +2 -2
- package/src/adapters/bun/client-bridge.d.ts +1 -1
- package/src/adapters/bun/create-app.d.ts +4 -12
- package/src/adapters/bun/create-app.js +4 -5
- package/src/adapters/bun/hmr-manager.d.ts +4 -4
- package/src/adapters/bun/hmr-manager.js +8 -8
- package/src/adapters/bun/index.d.ts +1 -1
- package/src/adapters/bun/index.js +2 -2
- package/src/adapters/bun/server-adapter.d.ts +5 -5
- package/src/adapters/bun/server-adapter.js +6 -5
- package/src/adapters/bun/server-lifecycle.d.ts +4 -4
- package/src/adapters/bun/server-lifecycle.js +2 -2
- package/src/{create-app.d.ts → adapters/create-app.d.ts} +9 -6
- package/src/{create-app.js → adapters/create-app.js} +4 -4
- package/src/adapters/index.d.ts +1 -5
- package/src/adapters/index.js +1 -7
- package/src/adapters/node/create-app.d.ts +6 -9
- package/src/adapters/node/create-app.js +12 -6
- package/src/adapters/node/node-client-bridge.d.ts +1 -1
- package/src/adapters/node/node-hmr-manager.d.ts +2 -2
- package/src/adapters/node/node-hmr-manager.js +3 -3
- package/src/adapters/node/server-adapter.d.ts +4 -4
- package/src/adapters/node/server-adapter.js +13 -12
- package/src/adapters/node/static-content-server.d.ts +1 -1
- package/src/adapters/node/static-content-server.js +1 -1
- package/src/adapters/shared/application-adapter.d.ts +1 -1
- package/src/adapters/shared/define-api-handler.d.ts +1 -1
- package/src/adapters/shared/explicit-static-route-matcher.d.ts +2 -2
- package/src/adapters/shared/file-route-middleware-pipeline.d.ts +1 -1
- package/src/adapters/shared/fs-server-response-factory.d.ts +2 -2
- package/src/adapters/shared/fs-server-response-factory.js +1 -1
- package/src/adapters/shared/fs-server-response-matcher.d.ts +1 -1
- package/src/adapters/shared/hmr-entrypoint-registrar.js +1 -1
- package/src/adapters/shared/hmr-html-response.d.ts +1 -1
- package/src/adapters/shared/render-context.d.ts +2 -1
- package/src/adapters/shared/render-context.js +3 -1
- package/src/adapters/shared/runtime-bootstrap.d.ts +1 -1
- package/src/adapters/shared/runtime-bootstrap.js +1 -1
- package/src/adapters/shared/server-adapter.d.ts +1 -1
- package/src/adapters/shared/server-adapter.js +5 -1
- package/src/adapters/shared/server-route-handler.d.ts +4 -4
- package/src/adapters/shared/server-route-handler.js +3 -3
- package/src/adapters/shared/server-static-builder.d.ts +5 -5
- package/src/adapters/shared/server-static-builder.js +5 -4
- package/src/build/README.md +19 -13
- package/src/build/build-adapter.d.ts +67 -20
- package/src/build/build-adapter.js +420 -19
- package/src/build/dev-build-coordinator.d.ts +10 -12
- package/src/build/dev-build-coordinator.js +8 -15
- package/src/build/esbuild-build-adapter.d.ts +6 -0
- package/src/build/esbuild-build-adapter.js +94 -11
- package/src/build/runtime-build-executor.d.ts +5 -4
- package/src/build/runtime-build-executor.js +5 -3
- package/src/build/runtime-specifier-alias-plugin.js +19 -15
- package/src/build/runtime-specifier-aliases.d.ts +5 -0
- package/src/build/runtime-specifier-aliases.js +95 -0
- package/src/config/README.md +5 -2
- package/src/config/config-builder.d.ts +25 -2
- package/src/config/config-builder.js +44 -7
- package/src/declarations.d.ts +1 -1
- package/src/dev/sc-server.d.ts +1 -1
- package/src/dev/sc-server.js +1 -1
- package/src/eco/eco.browser.d.ts +2 -0
- package/src/eco/eco.browser.js +83 -0
- package/src/eco/eco.js +19 -48
- package/src/eco/eco.types.d.ts +1 -1
- package/src/eco/eco.utils.d.ts +1 -40
- package/src/eco/eco.utils.js +5 -35
- package/src/eco/global-injector-map.d.ts +1 -1
- package/src/eco/lazy-injector-map.d.ts +1 -1
- package/src/hmr/hmr-strategy.d.ts +16 -13
- package/src/hmr/hmr-strategy.js +22 -7
- package/src/hmr/strategies/default-hmr-strategy.d.ts +2 -2
- package/src/hmr/strategies/default-hmr-strategy.js +1 -1
- package/src/hmr/strategies/js-hmr-strategy.d.ts +2 -2
- package/src/hmr/strategies/js-hmr-strategy.js +2 -2
- package/src/index.browser.d.ts +2 -2
- package/src/index.browser.js +1 -1
- package/src/index.d.ts +3 -2
- package/src/index.js +15 -4
- package/src/integrations/ghtml/ghtml-renderer.d.ts +6 -1
- package/src/integrations/ghtml/ghtml-renderer.js +29 -28
- package/src/integrations/ghtml/ghtml.plugin.d.ts +2 -2
- package/src/integrations/ghtml/ghtml.plugin.js +2 -2
- package/src/plugins/README.md +1 -0
- package/src/plugins/eco-component-meta-plugin.d.ts +12 -1
- package/src/plugins/eco-component-meta-plugin.js +26 -20
- package/src/plugins/foreign-jsx-override-plugin.d.ts +31 -0
- package/src/plugins/foreign-jsx-override-plugin.js +35 -0
- package/src/plugins/integration-plugin.d.ts +99 -33
- package/src/plugins/integration-plugin.js +68 -21
- package/src/plugins/processor.d.ts +2 -2
- package/src/plugins/processor.js +2 -2
- package/src/plugins/source-transform.d.ts +46 -0
- package/src/plugins/source-transform.js +71 -0
- package/src/route-renderer/GRAPH.md +54 -84
- package/src/route-renderer/README.md +14 -20
- package/src/route-renderer/orchestration/component-render-context.d.ts +83 -0
- package/src/route-renderer/orchestration/component-render-context.js +147 -0
- package/src/route-renderer/orchestration/integration-renderer.d.ts +233 -76
- package/src/route-renderer/orchestration/integration-renderer.js +500 -143
- package/src/route-renderer/orchestration/queued-boundary-runtime.service.d.ts +93 -0
- package/src/route-renderer/orchestration/queued-boundary-runtime.service.js +155 -0
- package/src/route-renderer/orchestration/render-execution.service.d.ts +11 -71
- package/src/route-renderer/orchestration/render-execution.service.js +65 -80
- package/src/{eco/eco.utils.ts → route-renderer/orchestration/render-output.utils.d.ts} +10 -53
- package/src/route-renderer/orchestration/render-output.utils.js +65 -0
- package/src/route-renderer/orchestration/render-preparation.service.d.ts +2 -8
- package/src/route-renderer/orchestration/render-preparation.service.js +10 -17
- package/src/route-renderer/orchestration/template-serialization.d.ts +38 -0
- package/src/route-renderer/orchestration/template-serialization.js +45 -0
- package/src/route-renderer/page-loading/dependency-resolver.d.ts +2 -2
- package/src/route-renderer/page-loading/dependency-resolver.js +10 -8
- package/src/route-renderer/page-loading/page-module-loader.d.ts +6 -4
- package/src/route-renderer/page-loading/page-module-loader.js +7 -5
- package/src/route-renderer/route-renderer.d.ts +5 -3
- package/src/route-renderer/route-renderer.js +13 -3
- package/src/router/README.md +79 -8
- package/src/router/client/navigation-coordinator.js +2 -2
- package/src/router/server/fs-router-scanner.d.ts +1 -1
- package/src/router/server/fs-router-scanner.js +6 -1
- package/src/router/server/fs-router.d.ts +1 -1
- package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +3 -3
- package/src/services/assets/asset-processing-service/asset-processing.service.js +6 -6
- package/src/services/assets/asset-processing-service/asset.factory.d.ts +1 -1
- package/src/services/assets/asset-processing-service/asset.factory.js +2 -2
- package/src/services/assets/asset-processing-service/index.d.ts +5 -5
- package/src/services/assets/asset-processing-service/index.js +5 -5
- package/src/services/assets/asset-processing-service/processor.interface.d.ts +2 -2
- package/src/services/assets/asset-processing-service/processor.registry.d.ts +2 -2
- package/src/services/assets/asset-processing-service/processors/base/base-processor.d.ts +1 -1
- package/src/services/assets/asset-processing-service/processors/base/base-processor.js +1 -1
- package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +3 -3
- package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +2 -2
- package/src/services/assets/asset-processing-service/processors/index.d.ts +5 -5
- package/src/services/assets/asset-processing-service/processors/index.js +5 -5
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +2 -2
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +1 -1
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +4 -3
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +15 -3
- package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.d.ts +3 -3
- package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +1 -1
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +2 -2
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +1 -1
- package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +2 -2
- package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +1 -1
- package/src/services/assets/browser-bundle.service.d.ts +1 -1
- package/src/services/assets/browser-bundle.service.js +2 -2
- package/src/services/html/html-rewriter-provider.service.js +4 -1
- package/src/services/html/html-transformer.service.d.ts +2 -2
- package/src/services/html/html-transformer.service.js +4 -10
- package/src/services/invalidation/development-invalidation.service.d.ts +1 -1
- package/src/services/invalidation/development-invalidation.service.js +1 -0
- package/src/services/module-loading/app-module-loader.service.d.ts +25 -0
- package/src/services/module-loading/app-module-loader.service.js +31 -0
- package/src/services/module-loading/app-server-module-transpiler.service.d.ts +9 -1
- package/src/services/module-loading/app-server-module-transpiler.service.js +77 -2
- package/src/services/module-loading/host-module-loader-registry.d.ts +4 -0
- package/src/services/module-loading/host-module-loader-registry.js +15 -0
- package/src/services/module-loading/module-loading-types.d.ts +2 -0
- package/src/{adapters/node/bootstrap-dependency-resolver.d.ts → services/module-loading/node-bootstrap-plugin.d.ts} +2 -24
- package/src/{adapters/node/bootstrap-dependency-resolver.js → services/module-loading/node-bootstrap-plugin.js} +42 -22
- package/src/services/module-loading/page-module-import.service.d.ts +4 -0
- package/src/services/module-loading/page-module-import.service.js +38 -9
- package/src/services/module-loading/server-module-transpiler.service.d.ts +3 -0
- package/src/services/module-loading/server-module-transpiler.service.js +4 -1
- package/src/services/runtime-state/dev-graph.service.d.ts +6 -6
- package/src/services/runtime-state/dev-graph.service.js +10 -10
- package/src/services/runtime-state/entrypoint-dependency-graph.service.d.ts +1 -1
- package/src/services/runtime-state/runtime-specifier-registry.service.d.ts +1 -1
- package/src/services/runtime-state/server-invalidation-state.service.d.ts +1 -1
- package/src/static-site-generator/static-site-generator.d.ts +2 -2
- package/src/static-site-generator/static-site-generator.js +1 -1
- package/src/{internal-types.d.ts → types/internal-types.d.ts} +24 -14
- package/src/{public-types.d.ts → types/public-types.d.ts} +30 -14
- package/src/types/public-types.js +0 -0
- package/src/utils/html-escaping.d.ts +7 -0
- package/src/utils/html-escaping.js +6 -0
- package/src/utils/locals-utils.d.ts +1 -1
- package/src/utils/parse-cli-args.d.ts +4 -1
- package/src/utils/parse-cli-args.js +16 -1
- package/src/utils/resolve-work-dir.js +1 -1
- package/src/watchers/project-watcher.d.ts +4 -4
- package/src/watchers/project-watcher.js +4 -10
- package/src/watchers/project-watcher.test-helpers.d.ts +2 -2
- package/src/adapters/abstract/application-adapter.ts +0 -337
- package/src/adapters/abstract/router-adapter.ts +0 -30
- package/src/adapters/abstract/server-adapter.ts +0 -79
- package/src/adapters/bun/client-bridge.ts +0 -62
- package/src/adapters/bun/create-app.ts +0 -189
- package/src/adapters/bun/hmr-manager.ts +0 -409
- package/src/adapters/bun/index.ts +0 -2
- package/src/adapters/bun/server-adapter.ts +0 -499
- package/src/adapters/bun/server-lifecycle.ts +0 -124
- package/src/adapters/index.ts +0 -6
- package/src/adapters/node/bootstrap-dependency-resolver.ts +0 -301
- package/src/adapters/node/create-app.ts +0 -179
- package/src/adapters/node/index.d.ts +0 -6
- package/src/adapters/node/index.js +0 -11
- package/src/adapters/node/index.ts +0 -16
- package/src/adapters/node/node-client-bridge.ts +0 -79
- package/src/adapters/node/node-hmr-manager.ts +0 -381
- package/src/adapters/node/runtime-adapter.d.ts +0 -46
- package/src/adapters/node/runtime-adapter.js +0 -306
- package/src/adapters/node/runtime-adapter.ts +0 -439
- package/src/adapters/node/server-adapter.ts +0 -488
- package/src/adapters/node/static-content-server.ts +0 -239
- package/src/adapters/node/write-runtime-manifest.d.ts +0 -26
- package/src/adapters/node/write-runtime-manifest.js +0 -12
- package/src/adapters/node/write-runtime-manifest.ts +0 -38
- package/src/adapters/shared/api-response.ts +0 -104
- package/src/adapters/shared/application-adapter.ts +0 -199
- package/src/adapters/shared/define-api-handler.ts +0 -66
- package/src/adapters/shared/explicit-static-route-matcher.ts +0 -140
- package/src/adapters/shared/file-route-middleware-pipeline.ts +0 -127
- package/src/adapters/shared/fs-server-response-factory.ts +0 -118
- package/src/adapters/shared/fs-server-response-matcher.ts +0 -205
- package/src/adapters/shared/hmr-entrypoint-registrar.ts +0 -149
- package/src/adapters/shared/hmr-html-response.ts +0 -52
- package/src/adapters/shared/render-context.ts +0 -120
- package/src/adapters/shared/runtime-bootstrap.ts +0 -79
- package/src/adapters/shared/server-adapter.ts +0 -489
- package/src/adapters/shared/server-route-handler.ts +0 -153
- package/src/adapters/shared/server-static-builder.ts +0 -166
- package/src/build/build-adapter.ts +0 -361
- package/src/build/build-manifest.ts +0 -54
- package/src/build/build-types.ts +0 -83
- package/src/build/dev-build-coordinator.ts +0 -221
- package/src/build/esbuild-build-adapter.ts +0 -559
- package/src/build/runtime-build-executor.ts +0 -34
- package/src/build/runtime-specifier-alias-plugin.ts +0 -58
- package/src/config/config-builder.ts +0 -706
- package/src/constants.ts +0 -54
- package/src/create-app.ts +0 -87
- package/src/dev/sc-server.ts +0 -143
- package/src/eco/component-render-context.d.ts +0 -105
- package/src/eco/component-render-context.js +0 -87
- package/src/eco/component-render-context.ts +0 -224
- package/src/eco/eco.ts +0 -242
- package/src/eco/eco.types.ts +0 -221
- package/src/eco/global-injector-map.ts +0 -112
- package/src/eco/lazy-injector-map.ts +0 -120
- package/src/eco/module-dependencies.ts +0 -75
- package/src/errors/http-error.ts +0 -72
- package/src/errors/index.ts +0 -2
- package/src/errors/locals-access-error.ts +0 -7
- package/src/global/app-logger.ts +0 -4
- package/src/hmr/client/hmr-runtime.ts +0 -152
- package/src/hmr/hmr-strategy.ts +0 -172
- package/src/hmr/hmr.postcss.test.e2e.ts +0 -41
- package/src/hmr/hmr.test.e2e.ts +0 -66
- package/src/hmr/strategies/default-hmr-strategy.ts +0 -60
- package/src/hmr/strategies/js-hmr-strategy.ts +0 -320
- package/src/index.browser.ts +0 -3
- package/src/index.ts +0 -5
- package/src/integrations/ghtml/ghtml-renderer.ts +0 -96
- package/src/integrations/ghtml/ghtml.plugin.ts +0 -32
- package/src/internal-types.ts +0 -232
- package/src/plugins/alias-resolver-plugin.ts +0 -63
- package/src/plugins/eco-component-meta-plugin.ts +0 -481
- package/src/plugins/integration-plugin.ts +0 -226
- package/src/plugins/processor.ts +0 -240
- package/src/plugins/runtime-capability.ts +0 -14
- package/src/public-types.ts +0 -1317
- package/src/route-renderer/component-graph/component-graph-executor.d.ts +0 -32
- package/src/route-renderer/component-graph/component-graph-executor.js +0 -31
- package/src/route-renderer/component-graph/component-graph-executor.ts +0 -84
- package/src/route-renderer/component-graph/component-graph.d.ts +0 -42
- package/src/route-renderer/component-graph/component-graph.js +0 -72
- package/src/route-renderer/component-graph/component-graph.ts +0 -159
- package/src/route-renderer/component-graph/component-marker.d.ts +0 -52
- package/src/route-renderer/component-graph/component-marker.js +0 -46
- package/src/route-renderer/component-graph/component-marker.ts +0 -117
- package/src/route-renderer/component-graph/component-reference.d.ts +0 -10
- package/src/route-renderer/component-graph/component-reference.js +0 -19
- package/src/route-renderer/component-graph/component-reference.ts +0 -29
- package/src/route-renderer/component-graph/marker-graph-resolver.d.ts +0 -77
- package/src/route-renderer/component-graph/marker-graph-resolver.js +0 -95
- package/src/route-renderer/component-graph/marker-graph-resolver.ts +0 -155
- package/src/route-renderer/orchestration/integration-renderer.ts +0 -790
- package/src/route-renderer/orchestration/render-execution.service.ts +0 -230
- package/src/route-renderer/orchestration/render-preparation.service.ts +0 -476
- package/src/route-renderer/page-loading/dependency-resolver.ts +0 -612
- package/src/route-renderer/page-loading/page-module-loader.ts +0 -181
- package/src/route-renderer/route-renderer.ts +0 -115
- package/src/router/client/link-intent.test.browser.ts +0 -51
- package/src/router/client/link-intent.ts +0 -92
- package/src/router/client/navigation-coordinator.ts +0 -433
- package/src/router/server/fs-router-scanner.ts +0 -219
- package/src/router/server/fs-router.ts +0 -122
- package/src/services/assets/asset-processing-service/asset-processing.service.ts +0 -401
- package/src/services/assets/asset-processing-service/asset.factory.ts +0 -105
- package/src/services/assets/asset-processing-service/assets.types.ts +0 -113
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.ts +0 -95
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.ts +0 -78
- package/src/services/assets/asset-processing-service/index.ts +0 -5
- package/src/services/assets/asset-processing-service/processor.interface.ts +0 -27
- package/src/services/assets/asset-processing-service/processor.registry.ts +0 -18
- package/src/services/assets/asset-processing-service/processors/base/base-processor.ts +0 -82
- package/src/services/assets/asset-processing-service/processors/base/base-script-processor.ts +0 -95
- package/src/services/assets/asset-processing-service/processors/index.ts +0 -5
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.ts +0 -66
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.ts +0 -88
- package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.ts +0 -85
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +0 -27
- package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +0 -80
- package/src/services/assets/browser-bundle.service.ts +0 -53
- package/src/services/cache/cache.types.ts +0 -126
- package/src/services/cache/index.ts +0 -18
- package/src/services/cache/memory-cache-store.ts +0 -130
- package/src/services/cache/page-cache-service.ts +0 -202
- package/src/services/cache/page-request-cache-coordinator.service.ts +0 -131
- package/src/services/html/html-rewriter-provider.service.ts +0 -103
- package/src/services/html/html-transformer.service.ts +0 -279
- package/src/services/invalidation/development-invalidation.service.ts +0 -261
- package/src/services/module-loading/app-server-module-transpiler.service.ts +0 -52
- package/src/services/module-loading/page-module-import.service.ts +0 -200
- package/src/services/module-loading/server-loader.service.d.ts +0 -96
- package/src/services/module-loading/server-loader.service.js +0 -32
- package/src/services/module-loading/server-loader.service.ts +0 -130
- package/src/services/module-loading/server-module-transpiler.service.ts +0 -105
- package/src/services/runtime-manifest/node-runtime-manifest.service.d.ts +0 -35
- package/src/services/runtime-manifest/node-runtime-manifest.service.js +0 -60
- package/src/services/runtime-manifest/node-runtime-manifest.service.ts +0 -101
- package/src/services/runtime-state/dev-graph.service.ts +0 -217
- package/src/services/runtime-state/entrypoint-dependency-graph.service.ts +0 -136
- package/src/services/runtime-state/runtime-specifier-registry.service.ts +0 -96
- package/src/services/runtime-state/server-invalidation-state.service.ts +0 -68
- package/src/services/validation/schema-validation-service.ts +0 -204
- package/src/services/validation/standard-schema.types.ts +0 -68
- package/src/static-site-generator/static-site-generator.ts +0 -462
- package/src/utils/css.d.ts +0 -1
- package/src/utils/css.js +0 -7
- package/src/utils/css.ts +0 -5
- package/src/utils/deep-merge.ts +0 -47
- package/src/utils/hash.ts +0 -5
- package/src/utils/html.ts +0 -1
- package/src/utils/invariant.ts +0 -15
- package/src/utils/locals-utils.ts +0 -37
- package/src/utils/parse-cli-args.ts +0 -83
- package/src/utils/path-utils.module.ts +0 -14
- package/src/utils/resolve-work-dir.ts +0 -45
- package/src/utils/runtime.ts +0 -44
- package/src/utils/server-utils.module.ts +0 -67
- package/src/watchers/project-watcher.test-helpers.ts +0 -41
- package/src/watchers/project-watcher.ts +0 -363
- /package/src/{constants.d.ts → config/constants.d.ts} +0 -0
- /package/src/{constants.js → config/constants.js} +0 -0
- /package/src/{internal-types.js → services/module-loading/module-loading-types.js} +0 -0
- /package/src/{public-types.js → types/internal-types.js} +0 -0
|
@@ -6,9 +6,13 @@ import { HttpError } from "../../errors/http-error.js";
|
|
|
6
6
|
import { LocalsAccessError } from "../../errors/locals-access-error.js";
|
|
7
7
|
import { DependencyResolverService } from "../page-loading/dependency-resolver.js";
|
|
8
8
|
import { PageModuleLoaderService } from "../page-loading/page-module-loader.js";
|
|
9
|
-
import { MarkerGraphResolver } from "../component-graph/marker-graph-resolver.js";
|
|
10
9
|
import { RenderExecutionService } from "./render-execution.service.js";
|
|
11
10
|
import { RenderPreparationService } from "./render-preparation.service.js";
|
|
11
|
+
import { normalizeBoundaryArtifactHtml } from "./render-output.utils.js";
|
|
12
|
+
import { getComponentRenderContext, runWithComponentRenderContext } from "./component-render-context.js";
|
|
13
|
+
import {
|
|
14
|
+
QueuedBoundaryRuntimeService
|
|
15
|
+
} from "./queued-boundary-runtime.service.js";
|
|
12
16
|
function createLocalsProxy(filePath) {
|
|
13
17
|
const errorMessage = `[ecopages] Request locals are only available during request-time rendering with cache: 'dynamic'. Page: ${filePath}. If you meant to use locals here, set cache: 'dynamic' and provide locals from route middleware/handlers.`;
|
|
14
18
|
return new Proxy(
|
|
@@ -44,13 +48,91 @@ class IntegrationRenderer {
|
|
|
44
48
|
htmlTransformer;
|
|
45
49
|
hmrManager;
|
|
46
50
|
resolvedIntegrationDependencies = [];
|
|
51
|
+
rendererModules;
|
|
47
52
|
runtimeOrigin;
|
|
48
53
|
dependencyResolverService;
|
|
49
54
|
pageModuleLoaderService;
|
|
50
|
-
markerGraphResolver;
|
|
51
55
|
renderPreparationService;
|
|
52
56
|
renderExecutionService;
|
|
57
|
+
queuedBoundaryRuntimeService = new QueuedBoundaryRuntimeService();
|
|
53
58
|
DOC_TYPE = "<!DOCTYPE html>";
|
|
59
|
+
/**
|
|
60
|
+
* Reads the execution-scoped foreign renderer cache from one boundary input.
|
|
61
|
+
*
|
|
62
|
+
* Shared page/layout/document shell helpers pass one cache through
|
|
63
|
+
* `integrationContext` so repeated delegation to the same foreign integration
|
|
64
|
+
* can reuse a single initialized renderer instance during one render flow.
|
|
65
|
+
* The cache is deliberately scoped to the current render execution rather than
|
|
66
|
+
* stored on the renderer, which avoids leaking mutable integration state across
|
|
67
|
+
* requests while still preventing redundant renderer initialization.
|
|
68
|
+
*
|
|
69
|
+
* @param integrationContext - Optional boundary context carried with one render input.
|
|
70
|
+
* @returns The current execution cache when present.
|
|
71
|
+
*/
|
|
72
|
+
getBoundaryRendererCache(integrationContext) {
|
|
73
|
+
if (typeof integrationContext === "object" && integrationContext !== null && "rendererCache" in integrationContext && integrationContext.rendererCache instanceof Map) {
|
|
74
|
+
return integrationContext.rendererCache;
|
|
75
|
+
}
|
|
76
|
+
return void 0;
|
|
77
|
+
}
|
|
78
|
+
getRegisteredBoundaryOwner(component) {
|
|
79
|
+
const integrationName = component.config?.integration ?? component.config?.__eco?.integration;
|
|
80
|
+
if (!integrationName || integrationName === this.name) {
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
83
|
+
return this.appConfig.integrations.some((integration) => integration.name === integrationName) ? integrationName : void 0;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Attaches an execution-scoped foreign renderer cache to one boundary input.
|
|
87
|
+
*
|
|
88
|
+
* Foreign-owned page, layout, or document shells may delegate several times in
|
|
89
|
+
* the same render flow. Threading the cache through `integrationContext`
|
|
90
|
+
* preserves renderer reuse without changing the public boundary input contract.
|
|
91
|
+
* Existing integration-specific context is preserved and augmented.
|
|
92
|
+
*
|
|
93
|
+
* @param input - Original boundary render input.
|
|
94
|
+
* @param rendererCache - Execution-scoped renderer cache to propagate.
|
|
95
|
+
* @returns Boundary input augmented with the shared renderer cache.
|
|
96
|
+
*/
|
|
97
|
+
withBoundaryRendererCache(input, rendererCache) {
|
|
98
|
+
const integrationContext = input.integrationContext;
|
|
99
|
+
return {
|
|
100
|
+
...input,
|
|
101
|
+
integrationContext: typeof integrationContext === "object" && integrationContext !== null ? { ...integrationContext, rendererCache } : { rendererCache }
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
getRendererModuleValue(key) {
|
|
105
|
+
if (!this.rendererModules || typeof this.rendererModules !== "object") {
|
|
106
|
+
return void 0;
|
|
107
|
+
}
|
|
108
|
+
return this.rendererModules[key];
|
|
109
|
+
}
|
|
110
|
+
getRendererModuleString(key) {
|
|
111
|
+
const value = this.getRendererModuleValue(key);
|
|
112
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
113
|
+
}
|
|
114
|
+
getRendererBootstrapDependencies(partial = false) {
|
|
115
|
+
if (partial) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
const islandClientModuleId = this.getRendererModuleString("islandClientModuleId");
|
|
119
|
+
if (!islandClientModuleId) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
return [
|
|
123
|
+
{
|
|
124
|
+
attributes: {
|
|
125
|
+
crossorigin: "anonymous",
|
|
126
|
+
"data-ecopages-runtime": "islands",
|
|
127
|
+
type: "module"
|
|
128
|
+
},
|
|
129
|
+
content: `import ${JSON.stringify(islandClientModuleId)};`,
|
|
130
|
+
inline: true,
|
|
131
|
+
kind: "script",
|
|
132
|
+
position: "body"
|
|
133
|
+
}
|
|
134
|
+
];
|
|
135
|
+
}
|
|
54
136
|
setHmrManager(hmrManager) {
|
|
55
137
|
this.hmrManager = hmrManager;
|
|
56
138
|
if (this.assetProcessingService) {
|
|
@@ -109,20 +191,280 @@ class IntegrationRenderer {
|
|
|
109
191
|
this.htmlTransformer.setProcessedDependencies(resolvedDependencies);
|
|
110
192
|
return resolvedDependencies;
|
|
111
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Merges component-scoped assets into the active HTML transformer state.
|
|
196
|
+
*
|
|
197
|
+
* Explicit page, layout, and document shell composition can produce assets at
|
|
198
|
+
* each boundary. This helper deduplicates those groups and folds them back into
|
|
199
|
+
* the transformer so downstream HTML finalization sees one canonical asset set.
|
|
200
|
+
*
|
|
201
|
+
* @param assetGroups - Optional groups of processed assets to merge.
|
|
202
|
+
* @returns The deduplicated asset subset contributed by this merge operation.
|
|
203
|
+
*/
|
|
204
|
+
appendProcessedDependencies(...assetGroups) {
|
|
205
|
+
const nextDependencies = this.htmlTransformer.dedupeProcessedAssets(
|
|
206
|
+
assetGroups.flatMap((assets) => assets ?? [])
|
|
207
|
+
);
|
|
208
|
+
if (nextDependencies.length === 0) {
|
|
209
|
+
return nextDependencies;
|
|
210
|
+
}
|
|
211
|
+
this.htmlTransformer.setProcessedDependencies(
|
|
212
|
+
this.htmlTransformer.dedupeProcessedAssets([
|
|
213
|
+
...this.htmlTransformer.getProcessedDependencies(),
|
|
214
|
+
...nextDependencies
|
|
215
|
+
])
|
|
216
|
+
);
|
|
217
|
+
return nextDependencies;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Resolves metadata for explicit view rendering.
|
|
221
|
+
*
|
|
222
|
+
* When a view declares a `metadata()` function, that contract owns the final
|
|
223
|
+
* metadata for the explicit render. Otherwise the app-level default metadata is
|
|
224
|
+
* reused so explicit routes and page-module routes share the same fallback.
|
|
225
|
+
*
|
|
226
|
+
* @param view - View component being rendered.
|
|
227
|
+
* @param props - Props passed to the view.
|
|
228
|
+
* @returns Resolved metadata for the final document shell.
|
|
229
|
+
*/
|
|
230
|
+
async resolveViewMetadata(view, props) {
|
|
231
|
+
return view.metadata ? await view.metadata({
|
|
232
|
+
params: {},
|
|
233
|
+
query: {},
|
|
234
|
+
props,
|
|
235
|
+
appConfig: this.appConfig
|
|
236
|
+
}) : this.appConfig.defaultMetadata;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Renders one explicit view response in partial mode.
|
|
240
|
+
*
|
|
241
|
+
* Same-integration views can optionally stream or render inline via the caller's
|
|
242
|
+
* `renderInline()` hook. Once a view may cross integration boundaries, this
|
|
243
|
+
* helper routes the render through `renderComponentBoundary()` instead so mixed
|
|
244
|
+
* shells can reuse the execution-scoped renderer cache and resolve nested
|
|
245
|
+
* foreign ownership before the partial response is returned.
|
|
246
|
+
*
|
|
247
|
+
* @param input - View render options for the partial response.
|
|
248
|
+
* @returns HTML response for the partial render.
|
|
249
|
+
*/
|
|
250
|
+
async renderPartialViewResponse(input) {
|
|
251
|
+
if (input.renderInline && !this.hasForeignBoundaryDescendants(input.view)) {
|
|
252
|
+
return this.createHtmlResponse(await input.renderInline(), input.ctx);
|
|
253
|
+
}
|
|
254
|
+
const rendererCache = /* @__PURE__ */ new Map();
|
|
255
|
+
const viewRender = await this.renderComponentBoundary({
|
|
256
|
+
component: input.view,
|
|
257
|
+
props: input.props ?? {},
|
|
258
|
+
integrationContext: { rendererCache }
|
|
259
|
+
});
|
|
260
|
+
const html = input.transformHtml ? input.transformHtml(viewRender.html) : viewRender.html;
|
|
261
|
+
return this.createHtmlResponse(html, input.ctx);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Renders an explicit view through optional layout and document shells.
|
|
265
|
+
*
|
|
266
|
+
* This helper is the shared explicit-route path for string-oriented and mixed
|
|
267
|
+
* integrations. It prepares view dependencies, resolves metadata, and composes
|
|
268
|
+
* view, layout, and html template boundaries with one execution-scoped renderer
|
|
269
|
+
* cache so repeated foreign shell delegation can reuse initialized renderers
|
|
270
|
+
* during the same render flow.
|
|
271
|
+
*
|
|
272
|
+
* @param input - View, props, and optional layout metadata for the render.
|
|
273
|
+
* @returns HTML response for the explicit view render.
|
|
274
|
+
*/
|
|
275
|
+
async renderViewWithDocumentShell(input) {
|
|
276
|
+
const normalizedProps = input.props ?? {};
|
|
277
|
+
if (input.ctx.partial) {
|
|
278
|
+
return this.renderPartialViewResponse({
|
|
279
|
+
view: input.view,
|
|
280
|
+
props: input.props,
|
|
281
|
+
ctx: input.ctx
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
await this.prepareViewDependencies(input.view, input.layout);
|
|
285
|
+
const HtmlTemplate = await this.getHtmlTemplate();
|
|
286
|
+
const metadata = await this.resolveViewMetadata(input.view, input.props);
|
|
287
|
+
const rendererCache = /* @__PURE__ */ new Map();
|
|
288
|
+
const viewRender = await this.renderComponentBoundary({
|
|
289
|
+
component: input.view,
|
|
290
|
+
props: normalizedProps,
|
|
291
|
+
integrationContext: { rendererCache }
|
|
292
|
+
});
|
|
293
|
+
const layoutRender = input.layout ? await this.renderComponentBoundary({
|
|
294
|
+
component: input.layout,
|
|
295
|
+
props: {},
|
|
296
|
+
children: viewRender.html,
|
|
297
|
+
integrationContext: { rendererCache }
|
|
298
|
+
}) : void 0;
|
|
299
|
+
const documentRender = await this.renderComponentBoundary({
|
|
300
|
+
component: HtmlTemplate,
|
|
301
|
+
props: {
|
|
302
|
+
metadata,
|
|
303
|
+
pageProps: normalizedProps
|
|
304
|
+
},
|
|
305
|
+
children: layoutRender?.html ?? viewRender.html,
|
|
306
|
+
integrationContext: { rendererCache }
|
|
307
|
+
});
|
|
308
|
+
this.appendProcessedDependencies(viewRender.assets, layoutRender?.assets, documentRender.assets);
|
|
309
|
+
const html = await this.finalizeResolvedHtml({
|
|
310
|
+
html: `${this.DOC_TYPE}${documentRender.html}`,
|
|
311
|
+
partial: false
|
|
312
|
+
});
|
|
313
|
+
return this.createHtmlResponse(html, input.ctx);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Renders a route page through optional layout and document shells.
|
|
317
|
+
*
|
|
318
|
+
* Route rendering and explicit view rendering now share the same boundary-owned
|
|
319
|
+
* shell composition model. This helper composes page, layout, and html template
|
|
320
|
+
* boundaries while threading one execution-scoped renderer cache through every
|
|
321
|
+
* delegated boundary so foreign shell ownership remains stable and renderer
|
|
322
|
+
* initialization is reused inside the current request.
|
|
323
|
+
*
|
|
324
|
+
* @param input - Page, layout, document, and metadata inputs for the route render.
|
|
325
|
+
* @returns Final serialized document HTML including the doctype prefix.
|
|
326
|
+
*/
|
|
327
|
+
async renderPageWithDocumentShell(input) {
|
|
328
|
+
const rendererCache = /* @__PURE__ */ new Map();
|
|
329
|
+
const pageRender = await this.renderComponentBoundary({
|
|
330
|
+
component: input.page.component,
|
|
331
|
+
props: input.page.props,
|
|
332
|
+
integrationContext: { rendererCache }
|
|
333
|
+
});
|
|
334
|
+
const layoutRender = input.layout ? await this.renderComponentBoundary({
|
|
335
|
+
component: input.layout.component,
|
|
336
|
+
props: input.layout.props ?? {},
|
|
337
|
+
children: pageRender.html,
|
|
338
|
+
integrationContext: { rendererCache }
|
|
339
|
+
}) : void 0;
|
|
340
|
+
const documentRender = await this.renderComponentBoundary({
|
|
341
|
+
component: input.htmlTemplate,
|
|
342
|
+
props: {
|
|
343
|
+
metadata: input.metadata,
|
|
344
|
+
pageProps: input.pageProps,
|
|
345
|
+
...input.documentProps ?? {}
|
|
346
|
+
},
|
|
347
|
+
children: layoutRender?.html ?? pageRender.html,
|
|
348
|
+
integrationContext: { rendererCache }
|
|
349
|
+
});
|
|
350
|
+
this.appendProcessedDependencies(pageRender.assets, layoutRender?.assets, documentRender.assets);
|
|
351
|
+
const documentHtml = input.transformDocumentHtml ? input.transformDocumentHtml(documentRender.html) : documentRender.html;
|
|
352
|
+
return `${this.DOC_TYPE}${documentHtml}`;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Renders one string-first component boundary and collects its assets.
|
|
356
|
+
*
|
|
357
|
+
* String-oriented integrations frequently share the same boundary contract:
|
|
358
|
+
* pass serialized children through props, coerce the render result to HTML, and
|
|
359
|
+
* attach any component-scoped dependencies. This helper centralizes that flow
|
|
360
|
+
* so integrations can opt into shared orchestration without repeating the same
|
|
361
|
+
* boundary boilerplate.
|
|
362
|
+
*
|
|
363
|
+
* @param input - Boundary render input.
|
|
364
|
+
* @param component - String-oriented component implementation to execute.
|
|
365
|
+
* @returns Structured component render result for orchestration paths.
|
|
366
|
+
*/
|
|
367
|
+
async renderStringComponentBoundary(input, component) {
|
|
368
|
+
const props = input.children === void 0 ? input.props : { ...input.props, children: input.children };
|
|
369
|
+
const content = await component(props);
|
|
370
|
+
const html = String(content);
|
|
371
|
+
const assets = input.component.config?.dependencies && typeof this.assetProcessingService?.processDependencies === "function" ? await this.processComponentDependencies([input.component]) : void 0;
|
|
372
|
+
return {
|
|
373
|
+
html,
|
|
374
|
+
canAttachAttributes: true,
|
|
375
|
+
rootTag: this.getRootTagName(html),
|
|
376
|
+
integrationName: this.name,
|
|
377
|
+
assets
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
getBoundaryTokenPrefix() {
|
|
381
|
+
return `__${this.name}_boundary__`;
|
|
382
|
+
}
|
|
383
|
+
getBoundaryRuntimeContextKey() {
|
|
384
|
+
return `__${this.name}_boundary_runtime__`;
|
|
385
|
+
}
|
|
386
|
+
getQueuedBoundaryRuntime(input, runtimeContextKey = this.getBoundaryRuntimeContextKey()) {
|
|
387
|
+
return this.queuedBoundaryRuntimeService.getRuntimeContext(input, runtimeContextKey);
|
|
388
|
+
}
|
|
389
|
+
async resolveQueuedBoundaryTokens(html, queuedResolutionsByToken, resolveToken) {
|
|
390
|
+
let resolvedHtml = html;
|
|
391
|
+
for (const token of queuedResolutionsByToken.keys()) {
|
|
392
|
+
if (!resolvedHtml.includes(token)) {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
resolvedHtml = resolvedHtml.split(token).join(await resolveToken(token));
|
|
396
|
+
}
|
|
397
|
+
return resolvedHtml;
|
|
398
|
+
}
|
|
399
|
+
createQueuedBoundaryRuntime(options) {
|
|
400
|
+
return this.queuedBoundaryRuntimeService.createRuntime({
|
|
401
|
+
boundaryInput: options.boundaryInput,
|
|
402
|
+
rendererCache: options.rendererCache,
|
|
403
|
+
runtimeContextKey: options.runtimeContextKey ?? this.getBoundaryRuntimeContextKey(),
|
|
404
|
+
tokenPrefix: options.tokenPrefix ?? this.getBoundaryTokenPrefix(),
|
|
405
|
+
shouldQueueBoundary: (input) => this.shouldResolveBoundaryInOwningRenderer(input),
|
|
406
|
+
createRuntimeContext: options.createRuntimeContext
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
async resolveRendererOwnedQueuedBoundaryHtml(options) {
|
|
410
|
+
return this.queuedBoundaryRuntimeService.resolveQueuedHtml({
|
|
411
|
+
html: options.html,
|
|
412
|
+
runtimeContext: options.runtimeContext,
|
|
413
|
+
queueLabel: options.queueLabel,
|
|
414
|
+
renderQueuedChildren: options.renderQueuedChildren,
|
|
415
|
+
resolveBoundary: (input, rendererCache) => this.resolveBoundaryInOwningRenderer(input, rendererCache),
|
|
416
|
+
applyAttributesToFirstElement: (html, attributes) => this.htmlTransformer.applyAttributesToFirstElement(html, attributes),
|
|
417
|
+
dedupeProcessedAssets: (assets) => this.htmlTransformer.dedupeProcessedAssets(assets)
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Renders a string-first component, then resolves any queued foreign
|
|
422
|
+
* boundaries before returning final component HTML.
|
|
423
|
+
*/
|
|
424
|
+
async renderStringComponentBoundaryWithQueuedForeignBoundaries(input, component) {
|
|
425
|
+
const componentRender = await this.renderStringComponentBoundary(input, component);
|
|
426
|
+
const queuedBoundaryResolution = await this.resolveRendererOwnedQueuedBoundaryHtml({
|
|
427
|
+
html: componentRender.html,
|
|
428
|
+
runtimeContext: this.getQueuedBoundaryRuntime(input),
|
|
429
|
+
queueLabel: "String",
|
|
430
|
+
renderQueuedChildren: async (children, _runtimeContext, queuedResolutionsByToken, resolveToken) => {
|
|
431
|
+
if (children === void 0) {
|
|
432
|
+
return { assets: [], html: void 0 };
|
|
433
|
+
}
|
|
434
|
+
const html = await this.resolveQueuedBoundaryTokens(
|
|
435
|
+
typeof children === "string" ? children : String(children ?? ""),
|
|
436
|
+
queuedResolutionsByToken,
|
|
437
|
+
resolveToken
|
|
438
|
+
);
|
|
439
|
+
return { assets: [], html };
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
const mergedAssets = this.htmlTransformer.dedupeProcessedAssets([
|
|
443
|
+
...componentRender.assets ?? [],
|
|
444
|
+
...queuedBoundaryResolution.assets
|
|
445
|
+
]);
|
|
446
|
+
return {
|
|
447
|
+
...componentRender,
|
|
448
|
+
html: queuedBoundaryResolution.html,
|
|
449
|
+
rootTag: this.getRootTagName(queuedBoundaryResolution.html),
|
|
450
|
+
assets: mergedAssets.length > 0 ? mergedAssets : void 0
|
|
451
|
+
};
|
|
452
|
+
}
|
|
112
453
|
constructor({
|
|
113
454
|
appConfig,
|
|
114
455
|
assetProcessingService,
|
|
115
456
|
resolvedIntegrationDependencies,
|
|
457
|
+
rendererModules,
|
|
116
458
|
runtimeOrigin
|
|
117
459
|
}) {
|
|
118
460
|
this.appConfig = appConfig;
|
|
119
461
|
this.assetProcessingService = assetProcessingService;
|
|
120
462
|
this.htmlTransformer = new HtmlTransformerService();
|
|
121
463
|
this.resolvedIntegrationDependencies = resolvedIntegrationDependencies || [];
|
|
464
|
+
this.rendererModules = rendererModules ?? appConfig.runtime?.rendererModuleContext;
|
|
122
465
|
this.runtimeOrigin = runtimeOrigin;
|
|
123
466
|
this.dependencyResolverService = new DependencyResolverService(appConfig, assetProcessingService);
|
|
124
467
|
this.pageModuleLoaderService = new PageModuleLoaderService(appConfig, runtimeOrigin);
|
|
125
|
-
this.markerGraphResolver = new MarkerGraphResolver();
|
|
126
468
|
this.renderPreparationService = new RenderPreparationService(appConfig, assetProcessingService);
|
|
127
469
|
this.renderExecutionService = new RenderExecutionService();
|
|
128
470
|
}
|
|
@@ -150,9 +492,9 @@ class IntegrationRenderer {
|
|
|
150
492
|
* @returns The HTML template component.
|
|
151
493
|
*/
|
|
152
494
|
async getHtmlTemplate() {
|
|
153
|
-
const
|
|
495
|
+
const htmlTemplatePath = this.getRendererModuleString("htmlTemplateModulePath") ?? this.appConfig.absolutePaths.htmlTemplatePath;
|
|
154
496
|
try {
|
|
155
|
-
const { default: HtmlTemplate } = await this.importPageFile(
|
|
497
|
+
const { default: HtmlTemplate } = await this.importPageFile(htmlTemplatePath);
|
|
156
498
|
return HtmlTemplate;
|
|
157
499
|
} catch (error) {
|
|
158
500
|
invariant(false, `Error importing HtmlTemplate: ${error}`);
|
|
@@ -186,6 +528,15 @@ class IntegrationRenderer {
|
|
|
186
528
|
context: { props, params, query }
|
|
187
529
|
});
|
|
188
530
|
}
|
|
531
|
+
usesIntegrationPageImporter(_file) {
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
async importIntegrationPageFile(_file) {
|
|
535
|
+
invariant(false, "Integration page importer must be implemented when enabled");
|
|
536
|
+
}
|
|
537
|
+
normalizeImportedPageFile(_file, pageModule) {
|
|
538
|
+
return pageModule;
|
|
539
|
+
}
|
|
189
540
|
/**
|
|
190
541
|
* Imports the page file from the specified path.
|
|
191
542
|
* It uses dynamic import to load the file and returns the imported module.
|
|
@@ -194,7 +545,9 @@ class IntegrationRenderer {
|
|
|
194
545
|
* @returns The imported module.
|
|
195
546
|
*/
|
|
196
547
|
async importPageFile(file) {
|
|
197
|
-
|
|
548
|
+
const bypassCache = typeof Bun !== "undefined" && process.env.NODE_ENV === "development";
|
|
549
|
+
const pageModule = this.usesIntegrationPageImporter(file) ? await this.importIntegrationPageFile(file) : await this.pageModuleLoaderService.importPageFile(file, { bypassCache });
|
|
550
|
+
return this.normalizeImportedPageFile(file, pageModule);
|
|
198
551
|
}
|
|
199
552
|
/**
|
|
200
553
|
* Resolves the dependency path based on the component directory.
|
|
@@ -281,14 +634,13 @@ class IntegrationRenderer {
|
|
|
281
634
|
resolveDependencies: (components) => this.resolveDependencies(components),
|
|
282
635
|
buildRouteRenderAssets: (file) => this.buildRouteRenderAssets(file),
|
|
283
636
|
shouldRenderPageComponent: (input) => this.shouldRenderPageComponent(input),
|
|
284
|
-
renderPageComponent: ({ component, props }) => this.
|
|
637
|
+
renderPageComponent: ({ component, props }) => this.renderComponentBoundary({
|
|
285
638
|
component,
|
|
286
639
|
props,
|
|
287
640
|
integrationContext: {
|
|
288
641
|
componentInstanceId: "eco-page-root"
|
|
289
642
|
}
|
|
290
643
|
}),
|
|
291
|
-
getComponentRenderBoundaryContext: () => this.getComponentRenderBoundaryContext(),
|
|
292
644
|
setProcessedDependencies: (dependencies) => this.htmlTransformer.setProcessedDependencies(dependencies),
|
|
293
645
|
dedupeProcessedAssets: (assets) => this.htmlTransformer.dedupeProcessedAssets(assets),
|
|
294
646
|
createPageLocalsProxy: (filePath) => createLocalsProxy(filePath)
|
|
@@ -328,11 +680,10 @@ class IntegrationRenderer {
|
|
|
328
680
|
*
|
|
329
681
|
* Execution flow:
|
|
330
682
|
* 1. Build normalized render options (`prepareRenderOptions`).
|
|
331
|
-
* 2. Render
|
|
332
|
-
* 3.
|
|
333
|
-
* 4.
|
|
334
|
-
* 5.
|
|
335
|
-
* 6. Run HTML transformer with final dependency set.
|
|
683
|
+
* 2. Render the route body once.
|
|
684
|
+
* 3. Reject unresolved route-level boundary artifacts.
|
|
685
|
+
* 4. Optionally apply root attributes for page/component root boundaries.
|
|
686
|
+
* 5. Run HTML transformer with final dependency set.
|
|
336
687
|
*
|
|
337
688
|
* Stream-safety note: the first render result is normalized to a string once,
|
|
338
689
|
* then the pipeline continues with that immutable HTML value to avoid disturbed
|
|
@@ -342,82 +693,41 @@ class IntegrationRenderer {
|
|
|
342
693
|
* @returns Rendered route body plus effective cache strategy.
|
|
343
694
|
*/
|
|
344
695
|
async execute(options) {
|
|
345
|
-
return this.renderExecutionService.execute(options,
|
|
696
|
+
return this.renderExecutionService.execute(options, {
|
|
346
697
|
prepareRenderOptions: (routeOptions) => this.prepareRenderOptions(routeOptions),
|
|
347
698
|
render: (renderOptions) => this.render(renderOptions),
|
|
348
|
-
getComponentRenderBoundaryContext: () => this.getComponentRenderBoundaryContext(),
|
|
349
|
-
resolveMarkerGraphHtml: (input) => this.resolveMarkerGraphHtml({
|
|
350
|
-
html: input.html,
|
|
351
|
-
componentsToResolve: input.componentsToResolve,
|
|
352
|
-
graphContext: input.graphContext
|
|
353
|
-
}),
|
|
354
699
|
getDocumentAttributes: (renderOptions) => this.getDocumentAttributes(renderOptions),
|
|
355
|
-
dedupeProcessedAssets: (assets) => this.htmlTransformer.dedupeProcessedAssets(assets),
|
|
356
|
-
getProcessedDependencies: () => this.htmlTransformer.getProcessedDependencies(),
|
|
357
|
-
setProcessedDependencies: (dependencies) => this.htmlTransformer.setProcessedDependencies(dependencies),
|
|
358
700
|
applyAttributesToHtmlElement: (html, attributes) => this.htmlTransformer.applyAttributesToHtmlElement(html, attributes),
|
|
359
701
|
applyAttributesToFirstBodyElement: (html, attributes) => this.htmlTransformer.applyAttributesToFirstBodyElement(html, attributes),
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
headers: {
|
|
364
|
-
"Content-Type": "text/html"
|
|
365
|
-
}
|
|
366
|
-
})
|
|
367
|
-
);
|
|
368
|
-
return response.body;
|
|
702
|
+
transformResponse: async (response) => {
|
|
703
|
+
const transformedResponse = await this.htmlTransformer.transform(response);
|
|
704
|
+
return transformedResponse.body ?? await transformedResponse.text();
|
|
369
705
|
}
|
|
370
706
|
});
|
|
371
707
|
}
|
|
372
708
|
/**
|
|
373
|
-
*
|
|
374
|
-
* for deferred marker resolution.
|
|
709
|
+
* Finalizes already-resolved HTML for explicit renderer-owned paths.
|
|
375
710
|
*
|
|
376
|
-
* This
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*/
|
|
380
|
-
async captureHtmlRender(render) {
|
|
381
|
-
return this.renderExecutionService.captureHtmlRender(
|
|
382
|
-
this.name,
|
|
383
|
-
this.getComponentRenderBoundaryContext(),
|
|
384
|
-
render
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* Finalizes previously captured HTML by resolving deferred markers, merging
|
|
389
|
-
* any emitted assets, stamping optional attributes, and optionally running the
|
|
390
|
-
* HTML transformer for full-document flows.
|
|
711
|
+
* This keeps document and root-attribute stamping plus HTML transformation
|
|
712
|
+
* available after a renderer has completed nested boundary resolution without
|
|
713
|
+
* routing back through shared route execution.
|
|
391
714
|
*/
|
|
392
|
-
async
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
{
|
|
403
|
-
resolveMarkerGraphHtml: (input) => this.resolveMarkerGraphHtml({
|
|
404
|
-
html: input.html,
|
|
405
|
-
componentsToResolve: input.componentsToResolve,
|
|
406
|
-
graphContext: input.graphContext
|
|
407
|
-
}),
|
|
408
|
-
dedupeProcessedAssets: (assets) => this.htmlTransformer.dedupeProcessedAssets(assets),
|
|
409
|
-
getProcessedDependencies: () => this.htmlTransformer.getProcessedDependencies(),
|
|
410
|
-
setProcessedDependencies: (dependencies) => this.htmlTransformer.setProcessedDependencies(dependencies),
|
|
411
|
-
applyAttributesToHtmlElement: (html, attributes) => this.htmlTransformer.applyAttributesToHtmlElement(html, attributes),
|
|
412
|
-
applyAttributesToFirstBodyElement: (html, attributes) => this.htmlTransformer.applyAttributesToFirstBodyElement(html, attributes)
|
|
413
|
-
}
|
|
414
|
-
);
|
|
715
|
+
async finalizeResolvedHtml(options) {
|
|
716
|
+
const rendererBootstrapDependencies = this.getRendererBootstrapDependencies(options.partial);
|
|
717
|
+
this.appendProcessedDependencies(rendererBootstrapDependencies);
|
|
718
|
+
let html = options.html;
|
|
719
|
+
if (options.componentRootAttributes && Object.keys(options.componentRootAttributes).length > 0) {
|
|
720
|
+
html = this.htmlTransformer.applyAttributesToFirstBodyElement(html, options.componentRootAttributes);
|
|
721
|
+
}
|
|
722
|
+
if (options.documentAttributes && Object.keys(options.documentAttributes).length > 0) {
|
|
723
|
+
html = this.htmlTransformer.applyAttributesToHtmlElement(html, options.documentAttributes);
|
|
724
|
+
}
|
|
415
725
|
const shouldTransform = options.transformHtml ?? !options.partial;
|
|
416
726
|
if (!shouldTransform) {
|
|
417
|
-
return
|
|
727
|
+
return html;
|
|
418
728
|
}
|
|
419
729
|
const transformedResponse = await this.htmlTransformer.transform(
|
|
420
|
-
new Response(
|
|
730
|
+
new Response(html, {
|
|
421
731
|
headers: { "Content-Type": "text/html" }
|
|
422
732
|
})
|
|
423
733
|
);
|
|
@@ -432,39 +742,6 @@ class IntegrationRenderer {
|
|
|
432
742
|
getDocumentAttributes(_renderOptions) {
|
|
433
743
|
return void 0;
|
|
434
744
|
}
|
|
435
|
-
/**
|
|
436
|
-
* Resolves all `eco-marker` placeholders in rendered HTML using integration
|
|
437
|
-
* dispatch and bottom-up graph execution.
|
|
438
|
-
*
|
|
439
|
-
* Responsibility split:
|
|
440
|
-
* - core decodes markers into component refs, props, slot children, and target
|
|
441
|
-
* integration dispatch
|
|
442
|
-
* - the selected integration renderer performs the actual component render via
|
|
443
|
-
* `renderComponent()`
|
|
444
|
-
*
|
|
445
|
-
* Resolver callback behavior per marker:
|
|
446
|
-
* - resolve component definition by `componentRef`
|
|
447
|
-
* - resolve serialized props by `propsRef`
|
|
448
|
-
* - stitch resolved child HTML when `slotRef` is present
|
|
449
|
-
* - dispatch to target integration `renderComponent`
|
|
450
|
-
* - collect produced assets and apply root attributes when attachable
|
|
451
|
-
*
|
|
452
|
-
* @param options.html HTML that may still contain marker tokens.
|
|
453
|
-
* @param options.componentsToResolve Component set used to build component ref registry.
|
|
454
|
-
* @param options.graphContext Props/slot linkage captured during render.
|
|
455
|
-
* @returns Resolved HTML plus any component-scoped assets produced while resolving nodes.
|
|
456
|
-
* @throws Error when marker component refs or props refs cannot be resolved.
|
|
457
|
-
*/
|
|
458
|
-
async resolveMarkerGraphHtml(options) {
|
|
459
|
-
const integrationRendererCache = /* @__PURE__ */ new Map();
|
|
460
|
-
return this.markerGraphResolver.resolve({
|
|
461
|
-
html: options.html,
|
|
462
|
-
componentsToResolve: options.componentsToResolve,
|
|
463
|
-
graphContext: options.graphContext,
|
|
464
|
-
resolveRenderer: (integrationName) => this.getIntegrationRendererForName(integrationName, integrationRendererCache),
|
|
465
|
-
applyAttributesToFirstElement: (html, attributes) => this.htmlTransformer.applyAttributesToFirstElement(html, attributes)
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
745
|
/**
|
|
469
746
|
* Returns a renderer instance for a given integration name.
|
|
470
747
|
*
|
|
@@ -486,18 +763,103 @@ class IntegrationRenderer {
|
|
|
486
763
|
const integrationPlugin = this.appConfig.integrations.find(
|
|
487
764
|
(integration) => integration.name === integrationName
|
|
488
765
|
);
|
|
489
|
-
invariant(!!integrationPlugin, `[ecopages] Integration not found for
|
|
490
|
-
const renderer = integrationPlugin.initializeRenderer(
|
|
766
|
+
invariant(!!integrationPlugin, `[ecopages] Integration not found for boundary owner: ${integrationName}`);
|
|
767
|
+
const renderer = integrationPlugin.initializeRenderer({
|
|
768
|
+
rendererModules: this.appConfig.runtime?.rendererModuleContext
|
|
769
|
+
});
|
|
491
770
|
cache.set(integrationName, renderer);
|
|
492
771
|
return renderer;
|
|
493
772
|
}
|
|
773
|
+
async resolveBoundaryInOwningRenderer(input, rendererCache) {
|
|
774
|
+
const boundaryOwner = this.getRegisteredBoundaryOwner(input.component);
|
|
775
|
+
if (!boundaryOwner) {
|
|
776
|
+
return void 0;
|
|
777
|
+
}
|
|
778
|
+
return await this.getIntegrationRendererForName(boundaryOwner, rendererCache).renderComponentBoundary(
|
|
779
|
+
this.withBoundaryRendererCache(input, rendererCache)
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Renders one component under this integration's boundary runtime and resolves
|
|
784
|
+
* any nested foreign boundaries captured during that render.
|
|
785
|
+
*
|
|
786
|
+
* Without this wrapper, a component tree with foreign-owned descendants would
|
|
787
|
+
* render them with no active boundary runtime, which bypasses the owning
|
|
788
|
+
* renderer's nested-boundary handoff.
|
|
789
|
+
*/
|
|
790
|
+
async renderComponentBoundary(input) {
|
|
791
|
+
const rendererCache = this.getBoundaryRendererCache(input.integrationContext) ?? /* @__PURE__ */ new Map();
|
|
792
|
+
const delegatedBoundaryRender = await this.resolveBoundaryInOwningRenderer(input, rendererCache);
|
|
793
|
+
if (delegatedBoundaryRender) {
|
|
794
|
+
return delegatedBoundaryRender;
|
|
795
|
+
}
|
|
796
|
+
const hasForeignBoundaries = this.hasForeignBoundaryDescendants(input.component);
|
|
797
|
+
const activeRenderContext = getComponentRenderContext();
|
|
798
|
+
if (!hasForeignBoundaries) {
|
|
799
|
+
if (!activeRenderContext || activeRenderContext.currentIntegration === this.name) {
|
|
800
|
+
return this.normalizeComponentBoundaryRender(await this.renderComponent(input));
|
|
801
|
+
}
|
|
802
|
+
const sameIntegrationExecution = await runWithComponentRenderContext(
|
|
803
|
+
{
|
|
804
|
+
currentIntegration: this.name
|
|
805
|
+
},
|
|
806
|
+
async () => this.renderComponent(input)
|
|
807
|
+
);
|
|
808
|
+
return this.normalizeComponentBoundaryRender(sameIntegrationExecution.value);
|
|
809
|
+
}
|
|
810
|
+
const execution = await runWithComponentRenderContext(
|
|
811
|
+
{
|
|
812
|
+
currentIntegration: this.name,
|
|
813
|
+
boundaryRuntime: this.createComponentBoundaryRuntime({
|
|
814
|
+
boundaryInput: input,
|
|
815
|
+
rendererCache
|
|
816
|
+
})
|
|
817
|
+
},
|
|
818
|
+
async () => this.renderComponent(input)
|
|
819
|
+
);
|
|
820
|
+
return this.normalizeComponentBoundaryRender(execution.value);
|
|
821
|
+
}
|
|
822
|
+
normalizeComponentBoundaryRender(result) {
|
|
823
|
+
const normalizedHtml = this.normalizeBoundaryArtifactHtml(result.html);
|
|
824
|
+
return normalizedHtml === result.html ? result : {
|
|
825
|
+
...result,
|
|
826
|
+
html: normalizedHtml
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
normalizeBoundaryArtifactHtml(html) {
|
|
830
|
+
return normalizeBoundaryArtifactHtml(html);
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Returns whether the component dependency tree crosses into another
|
|
834
|
+
* integration.
|
|
835
|
+
*
|
|
836
|
+
* This keeps boundary-runtime setup narrow: same-integration trees can render
|
|
837
|
+
* directly without paying the queue orchestration cost.
|
|
838
|
+
*/
|
|
839
|
+
hasForeignBoundaryDescendants(component) {
|
|
840
|
+
const stack = [component];
|
|
841
|
+
const seen = /* @__PURE__ */ new Set();
|
|
842
|
+
while (stack.length > 0) {
|
|
843
|
+
const current = stack.pop();
|
|
844
|
+
if (!current || seen.has(current)) {
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
847
|
+
seen.add(current);
|
|
848
|
+
const integrationName = current.config?.integration ?? current.config?.__eco?.integration;
|
|
849
|
+
if (integrationName && integrationName !== this.name) {
|
|
850
|
+
return true;
|
|
851
|
+
}
|
|
852
|
+
stack.push(...current.config?.dependencies?.components ?? []);
|
|
853
|
+
}
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
494
856
|
/**
|
|
495
857
|
* Render a single component and return structured output for orchestration paths.
|
|
496
858
|
*
|
|
497
859
|
* Default behavior delegates to `renderToResponse` in partial mode and wraps
|
|
498
860
|
* the resulting HTML into the `ComponentRenderResult` contract.
|
|
499
861
|
*
|
|
500
|
-
* In
|
|
862
|
+
* In boundary resolution, this method is the integration-owned step that turns an
|
|
501
863
|
* already-resolved deferred boundary into concrete HTML, assets, and optional
|
|
502
864
|
* root attributes.
|
|
503
865
|
*
|
|
@@ -505,7 +867,7 @@ class IntegrationRenderer {
|
|
|
505
867
|
* root attributes, integration-specific hydration metadata).
|
|
506
868
|
*
|
|
507
869
|
* @param input Component render request.
|
|
508
|
-
* @returns Structured render result used by
|
|
870
|
+
* @returns Structured render result used by component/page orchestration.
|
|
509
871
|
*/
|
|
510
872
|
async renderComponent(input) {
|
|
511
873
|
const response = await this.renderToResponse(
|
|
@@ -528,7 +890,7 @@ class IntegrationRenderer {
|
|
|
528
890
|
* @returns Root tag name when present; otherwise `undefined`.
|
|
529
891
|
*/
|
|
530
892
|
getRootTagName(html) {
|
|
531
|
-
const rootTag = html.match(
|
|
893
|
+
const rootTag = html.match(/^(?:\s|<!--[\s\S]*?-->)*<([a-zA-Z][a-zA-Z0-9:-]*)\b/);
|
|
532
894
|
return rootTag?.[1];
|
|
533
895
|
}
|
|
534
896
|
/**
|
|
@@ -542,46 +904,41 @@ class IntegrationRenderer {
|
|
|
542
904
|
return void 0;
|
|
543
905
|
}
|
|
544
906
|
/**
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
* `eco.component()` consumes this facade without knowing about integration
|
|
549
|
-
* registries or plugin instances.
|
|
907
|
+
* Creates the per-render boundary runtime adopted by the shared component
|
|
908
|
+
* render context.
|
|
550
909
|
*
|
|
551
|
-
*
|
|
910
|
+
* Real mixed-integration renderers should override this and keep foreign
|
|
911
|
+
* boundary resolution inside their own renderer-owned queue. The base runtime
|
|
912
|
+
* fails fast when a renderer crosses into a foreign owner without providing its
|
|
913
|
+
* own handoff mechanism.
|
|
552
914
|
*/
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
915
|
+
createComponentBoundaryRuntime(_options) {
|
|
916
|
+
const decideBoundaryInterception = (input) => {
|
|
917
|
+
if (!this.shouldResolveBoundaryInOwningRenderer(input)) {
|
|
918
|
+
return { kind: "inline" };
|
|
919
|
+
}
|
|
920
|
+
throw new Error(
|
|
921
|
+
`[ecopages] ${this.name} renderer crossed into ${input.targetIntegration} without a renderer-owned boundary runtime. Override createComponentBoundaryRuntime() to resolve foreign boundaries inside the owning renderer.`
|
|
922
|
+
);
|
|
923
|
+
};
|
|
924
|
+
const runtime = {
|
|
925
|
+
interceptBoundary: decideBoundaryInterception,
|
|
926
|
+
interceptBoundarySync: decideBoundaryInterception
|
|
556
927
|
};
|
|
928
|
+
return runtime;
|
|
557
929
|
}
|
|
558
930
|
/**
|
|
559
|
-
* Resolves whether a
|
|
560
|
-
*
|
|
931
|
+
* Resolves whether a boundary should leave the current render pass and be
|
|
932
|
+
* resolved by its owning renderer.
|
|
561
933
|
*
|
|
562
|
-
* Boundaries
|
|
563
|
-
*
|
|
564
|
-
* `shouldDeferComponentBoundary()` policy.
|
|
934
|
+
* Boundaries owned by the current integration always render inline. Foreign-
|
|
935
|
+
* owned boundaries must be handed off by a renderer-owned runtime.
|
|
565
936
|
*
|
|
566
937
|
* @param input Boundary metadata for the active render pass.
|
|
567
|
-
* @returns `true` when the boundary should
|
|
938
|
+
* @returns `true` when the boundary should leave the current pass; otherwise `false`.
|
|
568
939
|
*/
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
return false;
|
|
572
|
-
}
|
|
573
|
-
const targetIntegration = this.appConfig.integrations.find(
|
|
574
|
-
(integration) => integration.name === input.targetIntegration
|
|
575
|
-
);
|
|
576
|
-
invariant(
|
|
577
|
-
!!targetIntegration,
|
|
578
|
-
`[ecopages] Integration not found for component boundary: ${input.targetIntegration}`
|
|
579
|
-
);
|
|
580
|
-
return targetIntegration.shouldDeferComponentBoundary({
|
|
581
|
-
currentIntegration: input.currentIntegration,
|
|
582
|
-
targetIntegration: input.targetIntegration,
|
|
583
|
-
component: input.component
|
|
584
|
-
});
|
|
940
|
+
shouldResolveBoundaryInOwningRenderer(input) {
|
|
941
|
+
return !!input.targetIntegration && input.targetIntegration !== input.currentIntegration;
|
|
585
942
|
}
|
|
586
943
|
}
|
|
587
944
|
export {
|