@ecopages/core 0.2.0-alpha.9 → 0.2.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (471) hide show
  1. package/README.md +79 -28
  2. package/package.json +94 -116
  3. package/src/adapters/README.md +2 -2
  4. package/src/adapters/abstract/application-adapter.d.ts +28 -2
  5. package/src/adapters/abstract/application-adapter.js +14 -2
  6. package/src/adapters/abstract/router-adapter.d.ts +1 -1
  7. package/src/adapters/abstract/server-adapter.d.ts +2 -2
  8. package/src/adapters/bun/client-bridge.d.ts +1 -1
  9. package/src/adapters/bun/create-app.d.ts +12 -12
  10. package/src/adapters/bun/create-app.js +64 -41
  11. package/src/adapters/bun/hmr-manager.d.ts +19 -115
  12. package/src/adapters/bun/hmr-manager.js +25 -301
  13. package/src/adapters/bun/index.d.ts +1 -1
  14. package/src/adapters/bun/index.js +2 -2
  15. package/src/adapters/bun/runtime-host.d.ts +52 -0
  16. package/src/adapters/bun/runtime-host.js +56 -0
  17. package/src/adapters/bun/server-adapter.d.ts +100 -32
  18. package/src/adapters/bun/server-adapter.js +142 -65
  19. package/src/adapters/bun/static-preview-host.d.ts +28 -0
  20. package/src/adapters/bun/static-preview-host.js +45 -0
  21. package/src/{create-app.d.ts → adapters/create-app.d.ts} +9 -6
  22. package/src/{create-app.js → adapters/create-app.js} +4 -4
  23. package/src/adapters/index.d.ts +1 -5
  24. package/src/adapters/index.js +1 -7
  25. package/src/adapters/node/create-app.d.ts +15 -12
  26. package/src/adapters/node/create-app.js +34 -85
  27. package/src/adapters/node/http-request-bridge.d.ts +57 -0
  28. package/src/adapters/node/http-request-bridge.js +118 -0
  29. package/src/adapters/node/node-client-bridge.d.ts +1 -1
  30. package/src/adapters/node/node-hmr-manager.d.ts +22 -103
  31. package/src/adapters/node/node-hmr-manager.js +26 -289
  32. package/src/adapters/node/runtime-host.d.ts +57 -0
  33. package/src/adapters/node/runtime-host.js +92 -0
  34. package/src/adapters/node/server-adapter-dependencies.d.ts +19 -0
  35. package/src/adapters/node/server-adapter-dependencies.js +18 -0
  36. package/src/adapters/node/server-adapter.d.ts +19 -42
  37. package/src/adapters/node/server-adapter.js +94 -139
  38. package/src/adapters/node/static-content-server.d.ts +1 -1
  39. package/src/adapters/node/static-content-server.js +1 -1
  40. package/src/adapters/node/static-preview-host.d.ts +55 -0
  41. package/src/adapters/node/static-preview-host.js +68 -0
  42. package/src/adapters/shared/application-adapter.d.ts +1 -1
  43. package/src/adapters/shared/define-api-handler.d.ts +1 -1
  44. package/src/adapters/shared/explicit-static-render-preparation.d.ts +25 -0
  45. package/src/adapters/shared/explicit-static-render-preparation.js +26 -0
  46. package/src/adapters/shared/explicit-static-route-matcher.d.ts +7 -4
  47. package/src/adapters/shared/explicit-static-route-matcher.js +14 -16
  48. package/src/adapters/shared/file-route-middleware-pipeline.d.ts +7 -10
  49. package/src/adapters/shared/file-route-middleware-pipeline.js +2 -11
  50. package/src/adapters/shared/fs-server-response-factory.d.ts +14 -10
  51. package/src/adapters/shared/fs-server-response-factory.js +11 -27
  52. package/src/adapters/shared/fs-server-response-matcher.d.ts +18 -18
  53. package/src/adapters/shared/fs-server-response-matcher.js +72 -46
  54. package/src/adapters/shared/hmr-entrypoint-registrar.js +1 -1
  55. package/src/adapters/shared/hmr-html-response.d.ts +1 -1
  56. package/src/adapters/shared/hmr-html-response.js +4 -3
  57. package/src/adapters/shared/render-context.d.ts +5 -3
  58. package/src/adapters/shared/render-context.js +24 -1
  59. package/src/adapters/shared/runtime-app-bootstrap.d.ts +26 -0
  60. package/src/adapters/shared/runtime-app-bootstrap.js +46 -0
  61. package/src/adapters/shared/runtime-host.d.ts +12 -0
  62. package/src/adapters/shared/server-adapter.d.ts +22 -11
  63. package/src/adapters/shared/server-adapter.js +183 -133
  64. package/src/adapters/shared/server-route-handler.d.ts +5 -5
  65. package/src/adapters/shared/server-route-handler.js +4 -4
  66. package/src/adapters/shared/server-static-builder.d.ts +8 -7
  67. package/src/adapters/shared/server-static-builder.js +6 -5
  68. package/src/adapters/shared/shared-hmr-manager.d.ts +59 -0
  69. package/src/adapters/shared/shared-hmr-manager.js +241 -0
  70. package/src/adapters/shared/static-preview-host.d.ts +10 -0
  71. package/src/build/README.md +57 -67
  72. package/src/build/browser-runtime-manifest.d.ts +31 -0
  73. package/src/build/browser-runtime-manifest.js +61 -0
  74. package/src/build/browser-runtime-plugin-helpers.d.ts +26 -0
  75. package/src/build/browser-runtime-plugin-helpers.js +14 -0
  76. package/src/build/browser-runtime-plugin.d.ts +78 -0
  77. package/src/build/browser-runtime-plugin.js +173 -0
  78. package/src/build/build-adapter.d.ts +384 -63
  79. package/src/build/build-adapter.js +129 -54
  80. package/src/build/build-manifest.d.ts +6 -0
  81. package/src/build/build-manifest.js +21 -2
  82. package/src/build/build-types.d.ts +2 -2
  83. package/src/build/rolldown-adapter-helpers.d.ts +58 -0
  84. package/src/build/rolldown-adapter-helpers.js +265 -0
  85. package/src/build/rolldown-build-adapter.d.ts +28 -0
  86. package/src/build/rolldown-build-adapter.js +65 -0
  87. package/src/build/rolldown-dev-build-adapter.d.ts +82 -0
  88. package/src/build/rolldown-dev-build-adapter.js +166 -0
  89. package/src/build/rolldown-plugin-bridge.d.ts +59 -0
  90. package/src/build/rolldown-plugin-bridge.js +199 -0
  91. package/src/build/runtime-build-executor.d.ts +15 -7
  92. package/src/build/runtime-build-executor.js +8 -9
  93. package/src/build/runtime-build-output-normalizer.d.ts +3 -0
  94. package/src/build/runtime-build-output-normalizer.js +111 -0
  95. package/src/build/serialized-build-executor.d.ts +64 -0
  96. package/src/build/serialized-build-executor.js +63 -0
  97. package/src/build/server-side-css-shim-plugin.d.ts +41 -0
  98. package/src/build/server-side-css-shim-plugin.js +35 -0
  99. package/src/cache/index.d.ts +6 -0
  100. package/src/cache/index.js +6 -0
  101. package/src/cache/module-parse-cache.d.ts +65 -0
  102. package/src/cache/module-parse-cache.js +75 -0
  103. package/src/config/README.md +5 -2
  104. package/src/config/config-builder.d.ts +41 -13
  105. package/src/config/config-builder.js +62 -24
  106. package/src/declarations.d.ts +1 -1
  107. package/src/dev/host-runtime.d.ts +10 -0
  108. package/src/dev/host-runtime.js +24 -0
  109. package/src/dev/sc-server.d.ts +1 -1
  110. package/src/dev/sc-server.js +1 -1
  111. package/src/eco/eco.browser.d.ts +2 -0
  112. package/src/eco/eco.browser.js +88 -0
  113. package/src/eco/eco.js +50 -45
  114. package/src/eco/eco.types.d.ts +60 -8
  115. package/src/eco/eco.utils.d.ts +1 -40
  116. package/src/eco/eco.utils.js +5 -35
  117. package/src/eco/global-injector-map.d.ts +3 -3
  118. package/src/eco/global-injector-map.js +2 -2
  119. package/src/eco/lazy-injector-map.d.ts +2 -2
  120. package/src/errors/index.d.ts +1 -0
  121. package/src/errors/index.js +3 -1
  122. package/src/hmr/client/hmr-runtime.js +9 -1
  123. package/src/hmr/hmr-strategy.d.ts +16 -13
  124. package/src/hmr/hmr-strategy.js +22 -7
  125. package/src/hmr/strategies/default-hmr-strategy.d.ts +2 -2
  126. package/src/hmr/strategies/default-hmr-strategy.js +1 -1
  127. package/src/hmr/strategies/js-hmr-strategy.d.ts +4 -9
  128. package/src/hmr/strategies/js-hmr-strategy.js +5 -10
  129. package/src/index.browser.d.ts +2 -2
  130. package/src/index.browser.js +1 -1
  131. package/src/index.d.ts +3 -2
  132. package/src/index.js +15 -4
  133. package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -1
  134. package/src/integrations/ghtml/ghtml-renderer.js +24 -29
  135. package/src/integrations/ghtml/ghtml.constants.d.ts +1 -0
  136. package/src/integrations/ghtml/ghtml.constants.js +4 -0
  137. package/src/integrations/ghtml/ghtml.plugin.d.ts +2 -6
  138. package/src/integrations/ghtml/ghtml.plugin.js +3 -4
  139. package/src/plugins/README.md +1 -0
  140. package/src/plugins/alias-resolver-cache.d.ts +68 -0
  141. package/src/plugins/alias-resolver-cache.js +106 -0
  142. package/src/plugins/alias-resolver-plugin.d.ts +5 -1
  143. package/src/plugins/alias-resolver-plugin.js +19 -7
  144. package/src/plugins/eco-component-meta-plugin.d.ts +12 -1
  145. package/src/plugins/eco-component-meta-plugin.js +43 -25
  146. package/src/plugins/foreign-jsx-override-plugin.d.ts +33 -0
  147. package/src/plugins/foreign-jsx-override-plugin.js +41 -0
  148. package/src/plugins/integration-plugin.d.ts +136 -42
  149. package/src/plugins/integration-plugin.js +99 -31
  150. package/src/plugins/processor.d.ts +4 -2
  151. package/src/plugins/processor.js +8 -3
  152. package/src/plugins/source-transform.d.ts +46 -0
  153. package/src/plugins/source-transform.js +71 -0
  154. package/src/route-renderer/GRAPH.md +80 -318
  155. package/src/route-renderer/README.md +74 -78
  156. package/src/route-renderer/orchestration/component-render-context.d.ts +97 -0
  157. package/src/route-renderer/orchestration/component-render-context.js +147 -0
  158. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +18 -0
  159. package/src/route-renderer/orchestration/declared-ownership-graph.js +34 -0
  160. package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +110 -0
  161. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +233 -0
  162. package/src/route-renderer/orchestration/integration-renderer.d.ts +290 -128
  163. package/src/route-renderer/orchestration/integration-renderer.js +660 -258
  164. package/src/route-renderer/orchestration/ownership-planning.service.d.ts +24 -0
  165. package/src/route-renderer/orchestration/ownership-planning.service.js +63 -0
  166. package/src/route-renderer/orchestration/ownership-validation.service.d.ts +29 -0
  167. package/src/route-renderer/orchestration/ownership-validation.service.js +53 -0
  168. package/src/route-renderer/orchestration/processed-asset-dedupe.d.ts +3 -0
  169. package/src/route-renderer/orchestration/processed-asset-dedupe.js +27 -0
  170. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +91 -0
  171. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +170 -0
  172. package/src/route-renderer/orchestration/render-output.utils.d.ts +66 -0
  173. package/src/route-renderer/orchestration/render-output.utils.js +171 -0
  174. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +156 -0
  175. package/src/route-renderer/orchestration/route-render-orchestrator.js +577 -0
  176. package/src/route-renderer/orchestration/template-serialization.d.ts +38 -0
  177. package/src/route-renderer/orchestration/template-serialization.js +45 -0
  178. package/src/route-renderer/page-loading/component-dependency-collection.d.ts +37 -0
  179. package/src/route-renderer/page-loading/component-dependency-collection.js +132 -0
  180. package/src/route-renderer/page-loading/declared-asset-collection.d.ts +24 -0
  181. package/src/route-renderer/page-loading/declared-asset-collection.js +106 -0
  182. package/src/route-renderer/page-loading/dependency-resolver.d.ts +2 -2
  183. package/src/route-renderer/page-loading/dependency-resolver.js +27 -354
  184. package/src/route-renderer/page-loading/ecopages-virtual-imports.d.ts +11 -0
  185. package/src/route-renderer/page-loading/ecopages-virtual-imports.js +57 -0
  186. package/src/route-renderer/page-loading/lazy-entry-collection.d.ts +45 -0
  187. package/src/route-renderer/page-loading/lazy-entry-collection.js +105 -0
  188. package/src/route-renderer/page-loading/lazy-trigger-planning.d.ts +19 -0
  189. package/src/route-renderer/page-loading/lazy-trigger-planning.js +40 -0
  190. package/src/route-renderer/page-loading/module-declaration-aggregation.d.ts +5 -0
  191. package/src/route-renderer/page-loading/module-declaration-aggregation.js +33 -0
  192. package/src/route-renderer/page-loading/module-declaration-scripts.d.ts +3 -0
  193. package/src/route-renderer/page-loading/module-declaration-scripts.js +18 -0
  194. package/src/route-renderer/page-loading/page-dependency-bundling.d.ts +13 -0
  195. package/src/route-renderer/page-loading/page-dependency-bundling.js +137 -0
  196. package/src/route-renderer/page-loading/page-module-loader.d.ts +7 -4
  197. package/src/route-renderer/page-loading/page-module-loader.js +8 -5
  198. package/src/route-renderer/route-renderer.d.ts +31 -23
  199. package/src/route-renderer/route-renderer.js +17 -24
  200. package/src/router/README.md +76 -8
  201. package/src/router/client/navigation-coordinator.d.ts +20 -0
  202. package/src/router/client/navigation-coordinator.js +2 -2
  203. package/src/router/server/route-registry.d.ts +78 -0
  204. package/src/router/server/route-registry.js +262 -0
  205. package/src/services/README.md +1 -2
  206. package/src/services/assets/asset-processing-service/asset-dependency-keys.d.ts +3 -0
  207. package/src/services/assets/asset-processing-service/asset-dependency-keys.js +56 -0
  208. package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +3 -20
  209. package/src/services/assets/asset-processing-service/asset-processing.service.js +52 -98
  210. package/src/services/assets/asset-processing-service/asset.factory.d.ts +1 -1
  211. package/src/services/assets/asset-processing-service/asset.factory.js +2 -2
  212. package/src/services/assets/asset-processing-service/assets.types.d.ts +14 -0
  213. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +2 -0
  214. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
  215. package/src/services/assets/asset-processing-service/grouped-content-bundles.d.ts +30 -0
  216. package/src/services/assets/asset-processing-service/grouped-content-bundles.js +65 -0
  217. package/src/services/assets/asset-processing-service/index.d.ts +6 -5
  218. package/src/services/assets/asset-processing-service/index.js +6 -5
  219. package/src/services/assets/asset-processing-service/page-package.d.ts +6 -0
  220. package/src/services/assets/asset-processing-service/page-package.js +80 -0
  221. package/src/services/assets/asset-processing-service/processor.interface.d.ts +2 -2
  222. package/src/services/assets/asset-processing-service/processor.registry.d.ts +2 -2
  223. package/src/services/assets/asset-processing-service/processors/base/base-processor.d.ts +1 -1
  224. package/src/services/assets/asset-processing-service/processors/base/base-processor.js +3 -2
  225. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +10 -5
  226. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +69 -5
  227. package/src/services/assets/asset-processing-service/processors/index.d.ts +5 -5
  228. package/src/services/assets/asset-processing-service/processors/index.js +5 -5
  229. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +3 -2
  230. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +66 -3
  231. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +4 -3
  232. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +27 -6
  233. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.d.ts +38 -3
  234. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +57 -6
  235. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +5 -2
  236. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +39 -5
  237. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +2 -2
  238. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +5 -2
  239. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.d.ts +18 -0
  240. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.js +45 -0
  241. package/src/services/assets/browser-bundle.service.d.ts +44 -3
  242. package/src/services/assets/browser-bundle.service.js +15 -7
  243. package/src/services/html/html-rewriter-provider.service.d.ts +3 -0
  244. package/src/services/html/html-rewriter-provider.service.js +4 -1
  245. package/src/services/html/html-transformer.service.d.ts +22 -3
  246. package/src/services/html/html-transformer.service.js +101 -35
  247. package/src/services/invalidation/development-invalidation.service.d.ts +1 -1
  248. package/src/services/invalidation/development-invalidation.service.js +1 -0
  249. package/src/services/module-loading/app-module-loader.service.d.ts +7 -0
  250. package/src/services/module-loading/app-module-loader.service.js +0 -0
  251. package/src/services/module-loading/app-server-module-transpiler.service.d.ts +9 -1
  252. package/src/services/module-loading/app-server-module-transpiler.service.js +102 -6
  253. package/src/services/module-loading/host-module-loader-registry.d.ts +4 -0
  254. package/src/services/module-loading/host-module-loader-registry.js +15 -0
  255. package/src/services/module-loading/module-loading-types.d.ts +2 -0
  256. package/src/services/module-loading/module-loading-types.js +0 -0
  257. package/src/services/module-loading/page-module-import.service.d.ts +32 -8
  258. package/src/services/module-loading/page-module-import.service.js +83 -22
  259. package/src/services/module-loading/server-module-transpiler.service.d.ts +8 -14
  260. package/src/services/module-loading/server-module-transpiler.service.js +5 -2
  261. package/src/services/module-loading/source-module-support.d.ts +5 -0
  262. package/src/services/module-loading/source-module-support.js +8 -0
  263. package/src/services/runtime-state/dev-graph.service.d.ts +6 -6
  264. package/src/services/runtime-state/dev-graph.service.js +10 -10
  265. package/src/services/runtime-state/entrypoint-dependency-graph.service.d.ts +1 -1
  266. package/src/services/runtime-state/server-invalidation-state.service.d.ts +1 -1
  267. package/src/static-site-generator/static-site-generator.d.ts +23 -28
  268. package/src/static-site-generator/static-site-generator.js +119 -156
  269. package/src/{internal-types.d.ts → types/internal-types.d.ts} +34 -23
  270. package/src/types/internal-types.js +0 -0
  271. package/src/{public-types.d.ts → types/public-types.d.ts} +195 -37
  272. package/src/types/public-types.js +0 -0
  273. package/src/utils/html-escaping.d.ts +7 -0
  274. package/src/utils/html-escaping.js +6 -0
  275. package/src/utils/locals-utils.d.ts +1 -1
  276. package/src/utils/parse-cli-args.d.ts +4 -1
  277. package/src/utils/parse-cli-args.js +16 -1
  278. package/src/utils/resolve-work-dir.js +1 -1
  279. package/src/watchers/project-watcher.d.ts +4 -4
  280. package/src/watchers/project-watcher.js +35 -41
  281. package/src/watchers/project-watcher.test-helpers.d.ts +2 -2
  282. package/src/watchers/project-watcher.test-helpers.js +5 -5
  283. package/CHANGELOG.md +0 -31
  284. package/src/adapters/abstract/application-adapter.ts +0 -337
  285. package/src/adapters/abstract/router-adapter.ts +0 -30
  286. package/src/adapters/abstract/server-adapter.ts +0 -79
  287. package/src/adapters/bun/client-bridge.ts +0 -62
  288. package/src/adapters/bun/create-app.ts +0 -189
  289. package/src/adapters/bun/hmr-manager.ts +0 -409
  290. package/src/adapters/bun/index.ts +0 -2
  291. package/src/adapters/bun/server-adapter.ts +0 -499
  292. package/src/adapters/bun/server-lifecycle.d.ts +0 -63
  293. package/src/adapters/bun/server-lifecycle.js +0 -92
  294. package/src/adapters/bun/server-lifecycle.ts +0 -124
  295. package/src/adapters/index.ts +0 -6
  296. package/src/adapters/node/bootstrap-dependency-resolver.d.ts +0 -44
  297. package/src/adapters/node/bootstrap-dependency-resolver.js +0 -172
  298. package/src/adapters/node/bootstrap-dependency-resolver.ts +0 -301
  299. package/src/adapters/node/create-app.ts +0 -179
  300. package/src/adapters/node/index.d.ts +0 -6
  301. package/src/adapters/node/index.js +0 -11
  302. package/src/adapters/node/index.ts +0 -16
  303. package/src/adapters/node/node-client-bridge.ts +0 -79
  304. package/src/adapters/node/node-hmr-manager.ts +0 -381
  305. package/src/adapters/node/runtime-adapter.d.ts +0 -46
  306. package/src/adapters/node/runtime-adapter.js +0 -306
  307. package/src/adapters/node/runtime-adapter.ts +0 -439
  308. package/src/adapters/node/server-adapter.ts +0 -488
  309. package/src/adapters/node/static-content-server.ts +0 -239
  310. package/src/adapters/node/write-runtime-manifest.d.ts +0 -26
  311. package/src/adapters/node/write-runtime-manifest.js +0 -12
  312. package/src/adapters/node/write-runtime-manifest.ts +0 -38
  313. package/src/adapters/shared/api-response.ts +0 -104
  314. package/src/adapters/shared/application-adapter.ts +0 -199
  315. package/src/adapters/shared/define-api-handler.ts +0 -66
  316. package/src/adapters/shared/explicit-static-route-matcher.ts +0 -140
  317. package/src/adapters/shared/file-route-middleware-pipeline.ts +0 -127
  318. package/src/adapters/shared/fs-server-response-factory.ts +0 -118
  319. package/src/adapters/shared/fs-server-response-matcher.ts +0 -205
  320. package/src/adapters/shared/hmr-entrypoint-registrar.ts +0 -149
  321. package/src/adapters/shared/hmr-html-response.ts +0 -52
  322. package/src/adapters/shared/render-context.ts +0 -120
  323. package/src/adapters/shared/runtime-bootstrap.d.ts +0 -38
  324. package/src/adapters/shared/runtime-bootstrap.js +0 -43
  325. package/src/adapters/shared/runtime-bootstrap.ts +0 -79
  326. package/src/adapters/shared/server-adapter.ts +0 -489
  327. package/src/adapters/shared/server-route-handler.ts +0 -153
  328. package/src/adapters/shared/server-static-builder.ts +0 -166
  329. package/src/build/build-adapter.ts +0 -361
  330. package/src/build/build-manifest.ts +0 -54
  331. package/src/build/build-types.ts +0 -83
  332. package/src/build/dev-build-coordinator.d.ts +0 -74
  333. package/src/build/dev-build-coordinator.js +0 -161
  334. package/src/build/dev-build-coordinator.ts +0 -221
  335. package/src/build/esbuild-build-adapter.d.ts +0 -72
  336. package/src/build/esbuild-build-adapter.js +0 -422
  337. package/src/build/esbuild-build-adapter.ts +0 -559
  338. package/src/build/runtime-build-executor.ts +0 -34
  339. package/src/build/runtime-specifier-alias-plugin.d.ts +0 -15
  340. package/src/build/runtime-specifier-alias-plugin.js +0 -31
  341. package/src/build/runtime-specifier-alias-plugin.ts +0 -58
  342. package/src/config/config-builder.ts +0 -706
  343. package/src/constants.ts +0 -54
  344. package/src/create-app.ts +0 -87
  345. package/src/dev/sc-server.ts +0 -143
  346. package/src/eco/component-render-context.d.ts +0 -105
  347. package/src/eco/component-render-context.js +0 -87
  348. package/src/eco/component-render-context.ts +0 -224
  349. package/src/eco/eco.ts +0 -242
  350. package/src/eco/eco.types.ts +0 -221
  351. package/src/eco/eco.utils.ts +0 -89
  352. package/src/eco/global-injector-map.ts +0 -112
  353. package/src/eco/lazy-injector-map.ts +0 -120
  354. package/src/eco/module-dependencies.ts +0 -75
  355. package/src/errors/http-error.ts +0 -72
  356. package/src/errors/index.ts +0 -2
  357. package/src/errors/locals-access-error.ts +0 -7
  358. package/src/global/app-logger.ts +0 -4
  359. package/src/hmr/client/hmr-runtime.ts +0 -152
  360. package/src/hmr/hmr-strategy.ts +0 -172
  361. package/src/hmr/hmr.postcss.test.e2e.ts +0 -41
  362. package/src/hmr/hmr.test.e2e.ts +0 -66
  363. package/src/hmr/strategies/default-hmr-strategy.ts +0 -60
  364. package/src/hmr/strategies/js-hmr-strategy.ts +0 -320
  365. package/src/index.browser.ts +0 -3
  366. package/src/index.ts +0 -5
  367. package/src/integrations/ghtml/ghtml-renderer.ts +0 -96
  368. package/src/integrations/ghtml/ghtml.plugin.ts +0 -32
  369. package/src/internal-types.ts +0 -232
  370. package/src/plugins/alias-resolver-plugin.ts +0 -63
  371. package/src/plugins/eco-component-meta-plugin.ts +0 -481
  372. package/src/plugins/integration-plugin.ts +0 -226
  373. package/src/plugins/processor.ts +0 -240
  374. package/src/plugins/runtime-capability.ts +0 -14
  375. package/src/public-types.ts +0 -1317
  376. package/src/route-renderer/component-graph/component-graph-executor.d.ts +0 -32
  377. package/src/route-renderer/component-graph/component-graph-executor.js +0 -31
  378. package/src/route-renderer/component-graph/component-graph-executor.ts +0 -84
  379. package/src/route-renderer/component-graph/component-graph.d.ts +0 -42
  380. package/src/route-renderer/component-graph/component-graph.js +0 -72
  381. package/src/route-renderer/component-graph/component-graph.ts +0 -159
  382. package/src/route-renderer/component-graph/component-marker.d.ts +0 -52
  383. package/src/route-renderer/component-graph/component-marker.js +0 -46
  384. package/src/route-renderer/component-graph/component-marker.ts +0 -117
  385. package/src/route-renderer/component-graph/component-reference.d.ts +0 -10
  386. package/src/route-renderer/component-graph/component-reference.js +0 -19
  387. package/src/route-renderer/component-graph/component-reference.ts +0 -29
  388. package/src/route-renderer/component-graph/marker-graph-resolver.d.ts +0 -77
  389. package/src/route-renderer/component-graph/marker-graph-resolver.js +0 -95
  390. package/src/route-renderer/component-graph/marker-graph-resolver.ts +0 -155
  391. package/src/route-renderer/orchestration/integration-renderer.ts +0 -790
  392. package/src/route-renderer/orchestration/render-execution.service.d.ts +0 -103
  393. package/src/route-renderer/orchestration/render-execution.service.js +0 -121
  394. package/src/route-renderer/orchestration/render-execution.service.ts +0 -230
  395. package/src/route-renderer/orchestration/render-preparation.service.d.ts +0 -121
  396. package/src/route-renderer/orchestration/render-preparation.service.js +0 -332
  397. package/src/route-renderer/orchestration/render-preparation.service.ts +0 -476
  398. package/src/route-renderer/page-loading/dependency-resolver.ts +0 -612
  399. package/src/route-renderer/page-loading/page-module-loader.ts +0 -181
  400. package/src/route-renderer/route-renderer.ts +0 -115
  401. package/src/router/client/link-intent.test.browser.ts +0 -51
  402. package/src/router/client/link-intent.ts +0 -92
  403. package/src/router/client/navigation-coordinator.ts +0 -433
  404. package/src/router/server/fs-router-scanner.d.ts +0 -41
  405. package/src/router/server/fs-router-scanner.js +0 -156
  406. package/src/router/server/fs-router-scanner.ts +0 -219
  407. package/src/router/server/fs-router.d.ts +0 -26
  408. package/src/router/server/fs-router.js +0 -100
  409. package/src/router/server/fs-router.ts +0 -122
  410. package/src/services/assets/asset-processing-service/asset-processing.service.ts +0 -401
  411. package/src/services/assets/asset-processing-service/asset.factory.ts +0 -105
  412. package/src/services/assets/asset-processing-service/assets.types.ts +0 -113
  413. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.ts +0 -95
  414. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.ts +0 -78
  415. package/src/services/assets/asset-processing-service/index.ts +0 -5
  416. package/src/services/assets/asset-processing-service/processor.interface.ts +0 -27
  417. package/src/services/assets/asset-processing-service/processor.registry.ts +0 -18
  418. package/src/services/assets/asset-processing-service/processors/base/base-processor.ts +0 -82
  419. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.ts +0 -95
  420. package/src/services/assets/asset-processing-service/processors/index.ts +0 -5
  421. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.ts +0 -66
  422. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.ts +0 -88
  423. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.ts +0 -85
  424. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +0 -27
  425. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +0 -80
  426. package/src/services/assets/browser-bundle.service.ts +0 -53
  427. package/src/services/cache/cache.types.ts +0 -126
  428. package/src/services/cache/index.ts +0 -18
  429. package/src/services/cache/memory-cache-store.ts +0 -130
  430. package/src/services/cache/page-cache-service.ts +0 -202
  431. package/src/services/cache/page-request-cache-coordinator.service.ts +0 -131
  432. package/src/services/html/html-rewriter-provider.service.ts +0 -103
  433. package/src/services/html/html-transformer.service.ts +0 -279
  434. package/src/services/invalidation/development-invalidation.service.ts +0 -261
  435. package/src/services/module-loading/app-server-module-transpiler.service.ts +0 -52
  436. package/src/services/module-loading/page-module-import.service.ts +0 -200
  437. package/src/services/module-loading/server-loader.service.d.ts +0 -96
  438. package/src/services/module-loading/server-loader.service.js +0 -32
  439. package/src/services/module-loading/server-loader.service.ts +0 -130
  440. package/src/services/module-loading/server-module-transpiler.service.ts +0 -105
  441. package/src/services/runtime-manifest/node-runtime-manifest.service.d.ts +0 -35
  442. package/src/services/runtime-manifest/node-runtime-manifest.service.js +0 -60
  443. package/src/services/runtime-manifest/node-runtime-manifest.service.ts +0 -101
  444. package/src/services/runtime-state/dev-graph.service.ts +0 -217
  445. package/src/services/runtime-state/entrypoint-dependency-graph.service.ts +0 -136
  446. package/src/services/runtime-state/runtime-specifier-registry.service.d.ts +0 -69
  447. package/src/services/runtime-state/runtime-specifier-registry.service.js +0 -37
  448. package/src/services/runtime-state/runtime-specifier-registry.service.ts +0 -96
  449. package/src/services/runtime-state/server-invalidation-state.service.ts +0 -68
  450. package/src/services/validation/schema-validation-service.ts +0 -204
  451. package/src/services/validation/standard-schema.types.ts +0 -68
  452. package/src/static-site-generator/static-site-generator.ts +0 -462
  453. package/src/utils/css.d.ts +0 -1
  454. package/src/utils/css.js +0 -7
  455. package/src/utils/css.ts +0 -5
  456. package/src/utils/deep-merge.ts +0 -47
  457. package/src/utils/hash.ts +0 -5
  458. package/src/utils/html.ts +0 -1
  459. package/src/utils/invariant.ts +0 -15
  460. package/src/utils/locals-utils.ts +0 -37
  461. package/src/utils/parse-cli-args.ts +0 -83
  462. package/src/utils/path-utils.module.ts +0 -14
  463. package/src/utils/resolve-work-dir.ts +0 -45
  464. package/src/utils/runtime.ts +0 -44
  465. package/src/utils/server-utils.module.ts +0 -67
  466. package/src/watchers/project-watcher.test-helpers.ts +0 -41
  467. package/src/watchers/project-watcher.ts +0 -363
  468. /package/src/{internal-types.js → adapters/shared/runtime-host.js} +0 -0
  469. /package/src/{public-types.js → adapters/shared/static-preview-host.js} +0 -0
  470. /package/src/{constants.d.ts → config/constants.d.ts} +0 -0
  471. /package/src/{constants.js → config/constants.js} +0 -0
@@ -1,42 +1,23 @@
1
1
  import {
2
+ createPagePackage
2
3
  } from "../../services/assets/asset-processing-service/index.js";
3
4
  import { HtmlTransformerService } from "../../services/html/html-transformer.service.js";
4
5
  import { invariant } from "../../utils/invariant.js";
5
6
  import { HttpError } from "../../errors/http-error.js";
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
- import { RenderExecutionService } from "./render-execution.service.js";
11
- import { RenderPreparationService } from "./render-preparation.service.js";
12
- function createLocalsProxy(filePath) {
13
- 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
- return new Proxy(
15
- {},
16
- {
17
- get: () => {
18
- throw new LocalsAccessError(errorMessage);
19
- },
20
- set: () => {
21
- throw new LocalsAccessError(errorMessage);
22
- },
23
- has: () => {
24
- throw new LocalsAccessError(errorMessage);
25
- },
26
- ownKeys: () => {
27
- throw new LocalsAccessError(errorMessage);
28
- },
29
- deleteProperty: () => {
30
- throw new LocalsAccessError(errorMessage);
31
- },
32
- defineProperty: () => {
33
- throw new LocalsAccessError(errorMessage);
34
- },
35
- getOwnPropertyDescriptor: () => {
36
- throw new LocalsAccessError(errorMessage);
37
- }
38
- }
39
- );
9
+ import { OwnershipValidationService } from "./ownership-validation.service.js";
10
+ import {
11
+ RouteRenderOrchestrator
12
+ } from "./route-render-orchestrator.js";
13
+ import { normalizeUnresolvedMarkerArtifactHtml } from "./render-output.utils.js";
14
+ import {
15
+ ForeignSubtreeExecutionService
16
+ } from "./foreign-subtree-execution.service.js";
17
+ import {} from "./queued-foreign-subtree-resolution.service.js";
18
+ import { buildProcessedAssetDedupeKey } from "./processed-asset-dedupe.js";
19
+ function isMarkupNodeLike(value) {
20
+ return typeof value === "object" && value !== null && "nodeType" in value && typeof value.nodeType === "number" && "outerHTML" in value && typeof value.outerHTML === "string";
40
21
  }
41
22
  class IntegrationRenderer {
42
23
  appConfig;
@@ -44,13 +25,103 @@ class IntegrationRenderer {
44
25
  htmlTransformer;
45
26
  hmrManager;
46
27
  resolvedIntegrationDependencies = [];
28
+ rendererModules;
47
29
  runtimeOrigin;
48
30
  dependencyResolverService;
49
31
  pageModuleLoaderService;
50
- markerGraphResolver;
51
- renderPreparationService;
52
- renderExecutionService;
32
+ routeRenderOrchestrator;
33
+ foreignSubtreeExecutionService = new ForeignSubtreeExecutionService();
53
34
  DOC_TYPE = "<!DOCTYPE html>";
35
+ /**
36
+ * Loads one route module through the owning renderer's import path.
37
+ *
38
+ * Request-time infrastructure may need page metadata such as cache strategy or
39
+ * middleware before full rendering starts. Exposing this narrow entrypoint lets
40
+ * those callers reuse integration-specific import setup instead of bypassing it
41
+ * with raw transpiler access.
42
+ */
43
+ async loadPageModule(file, options) {
44
+ return this.importPageFile(file, options);
45
+ }
46
+ /**
47
+ * Reads the execution-scoped owning-renderer cache from one render input.
48
+ *
49
+ * Shared page/layout/document shell helpers pass one cache through
50
+ * `integrationContext` so repeated delegation to the same foreign integration
51
+ * can reuse a single initialized renderer instance during one render flow.
52
+ * The cache is deliberately scoped to the current render execution rather than
53
+ * stored on the renderer, which avoids leaking mutable integration state across
54
+ * requests while still preventing redundant renderer initialization.
55
+ *
56
+ * @param integrationContext - Optional render context carried with one render input.
57
+ * @returns The current execution cache when present.
58
+ */
59
+ getOwningRendererCache(integrationContext) {
60
+ if (integrationContext?.rendererCache instanceof Map) {
61
+ return integrationContext.rendererCache;
62
+ }
63
+ return void 0;
64
+ }
65
+ getForeignOwnerIntegrationName(component) {
66
+ const integrationName = component.config?.integration ?? component.config?.__eco?.integration;
67
+ if (!integrationName || integrationName === this.name) {
68
+ return void 0;
69
+ }
70
+ return this.appConfig.integrations.some((integration) => integration.name === integrationName) ? integrationName : void 0;
71
+ }
72
+ /**
73
+ * Attaches an execution-scoped owning-renderer cache to one render input.
74
+ *
75
+ * Foreign-owned page, layout, or document shells may delegate several times in
76
+ * the same render flow. Threading the cache through `integrationContext`
77
+ * preserves renderer reuse without changing the public render input contract.
78
+ * Existing integration-specific context is preserved and augmented.
79
+ *
80
+ * @param input - Original render input.
81
+ * @param rendererCache - Execution-scoped renderer cache to propagate.
82
+ * @returns Render input augmented with the shared renderer cache.
83
+ */
84
+ withOwningRendererCache(input, rendererCache) {
85
+ const integrationContext = input.integrationContext;
86
+ const sharedRendererCache = rendererCache;
87
+ return {
88
+ ...input,
89
+ integrationContext: integrationContext ? { ...integrationContext, rendererCache: sharedRendererCache } : { rendererCache: sharedRendererCache }
90
+ };
91
+ }
92
+ getRendererModuleValue(key) {
93
+ if (!this.rendererModules || typeof this.rendererModules !== "object") {
94
+ return void 0;
95
+ }
96
+ return this.rendererModules[key];
97
+ }
98
+ getRendererModuleString(key) {
99
+ const value = this.getRendererModuleValue(key);
100
+ return typeof value === "string" && value.length > 0 ? value : void 0;
101
+ }
102
+ getRendererBootstrapDependencies(partial = false) {
103
+ if (partial) {
104
+ return [];
105
+ }
106
+ const islandClientModuleId = this.getRendererModuleString("islandClientModuleId");
107
+ if (!islandClientModuleId) {
108
+ return [];
109
+ }
110
+ return [
111
+ {
112
+ attributes: {
113
+ crossorigin: "anonymous",
114
+ "data-ecopages-runtime": "islands",
115
+ type: "module"
116
+ },
117
+ content: `import ${JSON.stringify(islandClientModuleId)};`,
118
+ inline: true,
119
+ kind: "script",
120
+ packageRole: "keep-separate",
121
+ position: "body"
122
+ }
123
+ ];
124
+ }
54
125
  setHmrManager(hmrManager) {
55
126
  this.hmrManager = hmrManager;
56
127
  if (this.assetProcessingService) {
@@ -106,25 +177,312 @@ class IntegrationRenderer {
106
177
  const resolvedDependencies = this.htmlTransformer.dedupeProcessedAssets(
107
178
  await this.resolveDependencies(componentsToResolve)
108
179
  );
109
- this.htmlTransformer.setProcessedDependencies(resolvedDependencies);
180
+ this.htmlTransformer.setPagePackage(createPagePackage(resolvedDependencies));
110
181
  return resolvedDependencies;
111
182
  }
183
+ async resolvePageBrowserGraphForFile(filePath) {
184
+ return await this.routeRenderOrchestrator.resolveDeclaredPageBrowserGraph({
185
+ routeFile: filePath,
186
+ integrationName: this.name,
187
+ collectContribution: async (routeFile) => {
188
+ const pageModule = await this.importPageFile(routeFile);
189
+ return await this.collectPageBrowserGraphContribution({ file: routeFile, pageModule });
190
+ }
191
+ });
192
+ }
193
+ mergePageBrowserGraphIntoPagePackage(pageBrowserGraph) {
194
+ if (!pageBrowserGraph) {
195
+ return void 0;
196
+ }
197
+ const currentPagePackage = this.htmlTransformer.getPagePackage();
198
+ const mergedPageBrowserGraph = currentPagePackage?.pageBrowserGraph ? {
199
+ entryAssets: this.htmlTransformer.dedupeProcessedAssets([
200
+ ...currentPagePackage.pageBrowserGraph.entryAssets,
201
+ ...pageBrowserGraph.entryAssets
202
+ ]),
203
+ chunkAssets: this.htmlTransformer.dedupeProcessedAssets([
204
+ ...currentPagePackage.pageBrowserGraph.chunkAssets,
205
+ ...pageBrowserGraph.chunkAssets
206
+ ])
207
+ } : pageBrowserGraph;
208
+ const pageBrowserGraphAssetKeys = new Set(
209
+ [...mergedPageBrowserGraph.entryAssets, ...mergedPageBrowserGraph.chunkAssets].map(
210
+ (asset) => buildProcessedAssetDedupeKey(asset)
211
+ )
212
+ );
213
+ const baseAssets = currentPagePackage ? currentPagePackage.assets.filter(
214
+ (asset) => !pageBrowserGraphAssetKeys.has(buildProcessedAssetDedupeKey(asset))
215
+ ) : this.htmlTransformer.getProcessedDependencies();
216
+ this.htmlTransformer.setPagePackage(
217
+ createPagePackage(this.htmlTransformer.dedupeProcessedAssets(baseAssets), {
218
+ pageBrowserGraph: mergedPageBrowserGraph
219
+ })
220
+ );
221
+ return mergedPageBrowserGraph;
222
+ }
223
+ /**
224
+ * Merges component-scoped assets into the active HTML transformer state.
225
+ *
226
+ * Explicit page, layout, and document shell composition can produce assets at
227
+ * each foreign subtree. This helper deduplicates those groups and folds them back into
228
+ * the transformer so downstream HTML finalization sees one canonical asset set.
229
+ *
230
+ * @param assetGroups - Optional groups of processed assets to merge.
231
+ * @returns The deduplicated asset subset contributed by this merge operation.
232
+ */
233
+ appendProcessedDependencies(...assetGroups) {
234
+ const nextDependencies = this.htmlTransformer.dedupeProcessedAssets(
235
+ assetGroups.flatMap((assets) => assets ?? [])
236
+ );
237
+ if (nextDependencies.length === 0) {
238
+ return nextDependencies;
239
+ }
240
+ const mergedDependencies = this.htmlTransformer.dedupeProcessedAssets([
241
+ ...this.htmlTransformer.getProcessedDependencies(),
242
+ ...nextDependencies
243
+ ]);
244
+ const currentPageBrowserGraph = this.htmlTransformer.getPagePackage()?.pageBrowserGraph;
245
+ this.htmlTransformer.setPagePackage(
246
+ createPagePackage(mergedDependencies, {
247
+ pageBrowserGraph: currentPageBrowserGraph
248
+ })
249
+ );
250
+ return nextDependencies;
251
+ }
252
+ /**
253
+ * Resolves metadata for explicit view rendering.
254
+ *
255
+ * When a view declares a `metadata()` function, that contract owns the final
256
+ * metadata for the explicit render. Otherwise the app-level default metadata is
257
+ * reused so explicit routes and page-module routes share the same fallback.
258
+ *
259
+ * @param view - View component being rendered.
260
+ * @param props - Props passed to the view.
261
+ * @returns Resolved metadata for the final document shell.
262
+ */
263
+ async resolveViewMetadata(view, props) {
264
+ return view.metadata ? await view.metadata({
265
+ params: {},
266
+ query: {},
267
+ props,
268
+ appConfig: this.appConfig
269
+ }) : this.appConfig.defaultMetadata;
270
+ }
271
+ /**
272
+ * Renders one explicit view response in partial mode.
273
+ *
274
+ * Same-integration views can optionally stream or render inline via the caller's
275
+ * `renderInline()` hook. Once a view may cross integration boundaries, this
276
+ * helper routes the render through `renderComponentWithForeignChildren()` instead so mixed
277
+ * shells can reuse the execution-scoped renderer cache and resolve nested
278
+ * foreign ownership before the partial response is returned.
279
+ *
280
+ * @param input - View render options for the partial response.
281
+ * @returns HTML response for the partial render.
282
+ */
283
+ async renderPartialViewResponse(input) {
284
+ if (input.renderInline && !this.hasForeignChildDescendants(input.view)) {
285
+ return this.createHtmlResponse(await input.renderInline(), input.ctx);
286
+ }
287
+ const rendererCache = /* @__PURE__ */ new Map();
288
+ const viewRender = await this.renderComponentWithForeignChildren({
289
+ component: input.view,
290
+ props: input.props ?? {},
291
+ integrationContext: { rendererCache }
292
+ });
293
+ const html = input.transformHtml ? input.transformHtml(viewRender.html) : viewRender.html;
294
+ return this.createHtmlResponse(html, input.ctx);
295
+ }
296
+ /**
297
+ * Renders an explicit view through optional layout and document shells.
298
+ *
299
+ * This helper is the shared explicit-route path for string-oriented and mixed
300
+ * integrations. It prepares view dependencies, resolves metadata, and composes
301
+ * view, layout, and html template boundaries with one execution-scoped renderer
302
+ * cache so repeated foreign shell delegation can reuse initialized renderers
303
+ * during the same render flow.
304
+ *
305
+ * @param input - View, props, and optional layout metadata for the render.
306
+ * @returns HTML response for the explicit view render.
307
+ */
308
+ async renderViewWithDocumentShell(input) {
309
+ const normalizedProps = input.props ?? {};
310
+ if (input.ctx.partial) {
311
+ return this.renderPartialViewResponse(input);
312
+ }
313
+ await this.prepareViewDependencies(input.view, input.layout);
314
+ const HtmlTemplate = await this.getHtmlTemplate();
315
+ const metadata = await this.resolveViewMetadata(input.view, input.props);
316
+ const { documentHtml } = await this.composeDocumentShell({
317
+ primaryComponent: input.view,
318
+ primaryProps: normalizedProps,
319
+ layout: input.layout ? {
320
+ component: input.layout,
321
+ props: {}
322
+ } : void 0,
323
+ htmlTemplate: HtmlTemplate,
324
+ documentProps: {
325
+ metadata,
326
+ pageProps: normalizedProps
327
+ }
328
+ });
329
+ const html = await this.finalizeResolvedHtml({
330
+ html: `${this.DOC_TYPE}${documentHtml}`,
331
+ partial: false
332
+ });
333
+ return this.createHtmlResponse(html, input.ctx);
334
+ }
335
+ /**
336
+ * Renders a route page through optional layout and document shells.
337
+ *
338
+ * Route rendering and explicit view rendering now share the same renderer-owned
339
+ * shell composition model. This helper composes page, layout, and html template
340
+ * renders while threading one execution-scoped renderer cache through every
341
+ * delegated foreign subtree so foreign shell ownership remains stable and renderer
342
+ * initialization is reused inside the current request.
343
+ *
344
+ * @param input - Page, layout, document, and metadata inputs for the route render.
345
+ * @returns Final serialized document HTML including the doctype prefix.
346
+ */
347
+ async renderPageWithDocumentShell(input) {
348
+ const { documentHtml: composedDocumentHtml } = await this.composeDocumentShell({
349
+ primaryComponent: input.page.component,
350
+ primaryProps: input.page.props,
351
+ layout: input.layout,
352
+ htmlTemplate: input.htmlTemplate,
353
+ documentProps: {
354
+ metadata: input.metadata,
355
+ pageProps: input.pageProps,
356
+ ...input.documentProps ?? {}
357
+ }
358
+ });
359
+ const documentHtml = input.transformDocumentHtml ? input.transformDocumentHtml(composedDocumentHtml) : composedDocumentHtml;
360
+ return `${this.DOC_TYPE}${documentHtml}`;
361
+ }
362
+ async composeDocumentShell(input) {
363
+ const rendererCache = /* @__PURE__ */ new Map();
364
+ const primaryRender = await this.renderComponentWithForeignChildren({
365
+ component: input.primaryComponent,
366
+ props: input.primaryProps,
367
+ integrationContext: { rendererCache }
368
+ });
369
+ const layoutRender = input.layout ? await this.renderComponentWithForeignChildren({
370
+ component: input.layout.component,
371
+ props: input.layout.props ?? {},
372
+ children: primaryRender.html,
373
+ integrationContext: { rendererCache }
374
+ }) : void 0;
375
+ const documentRender = await this.renderComponentWithForeignChildren({
376
+ component: input.htmlTemplate,
377
+ props: input.documentProps,
378
+ children: layoutRender?.html ?? primaryRender.html,
379
+ integrationContext: { rendererCache }
380
+ });
381
+ this.appendProcessedDependencies(primaryRender.assets, layoutRender?.assets, documentRender.assets);
382
+ return {
383
+ documentHtml: documentRender.html
384
+ };
385
+ }
386
+ /**
387
+ * Renders one string-first component with serialized children and collects its assets.
388
+ *
389
+ * String-oriented integrations frequently share the same component contract:
390
+ * pass serialized children through props, coerce the render result to HTML, and
391
+ * attach any component-scoped dependencies. This helper centralizes that flow
392
+ * so integrations can opt into shared orchestration without repeating the same
393
+ * string-render boilerplate.
394
+ *
395
+ * @param input - Component render input.
396
+ * @param component - String-oriented component implementation to execute.
397
+ * @returns Structured component render result for orchestration paths.
398
+ */
399
+ async renderStringComponentWithSerializedChildren(input, component) {
400
+ const serializedChildren = input.children === void 0 ? void 0 : typeof input.children === "string" ? input.children : isMarkupNodeLike(input.children) ? input.children.outerHTML : void 0;
401
+ if (input.children !== void 0 && serializedChildren === void 0) {
402
+ const componentFile = input.component.config?.__eco?.file ?? "unknown component";
403
+ const childTag = Object.prototype.toString.call(input.children);
404
+ throw new TypeError(
405
+ `[ecopages] ${this.name} renderer expected serialized children for ${componentFile}, received ${childTag}.`
406
+ );
407
+ }
408
+ const props = serializedChildren === void 0 ? input.props : { ...input.props, children: serializedChildren };
409
+ const content = await component(props);
410
+ const html = String(content);
411
+ const assets = input.component.config?.dependencies && typeof this.assetProcessingService?.processDependencies === "function" ? await this.processComponentDependencies([input.component]) : void 0;
412
+ return {
413
+ html,
414
+ canAttachAttributes: true,
415
+ rootTag: this.getRootTagName(html),
416
+ integrationName: this.name,
417
+ assets
418
+ };
419
+ }
420
+ getForeignSubtreeTokenPrefix() {
421
+ return `__${this.name}_foreign_subtree__`;
422
+ }
423
+ getForeignSubtreeResolutionContextKey() {
424
+ return `__${this.name}_foreign_subtree_runtime__`;
425
+ }
426
+ createQueuedForeignSubtreeExecutionRuntime(options) {
427
+ return this.foreignSubtreeExecutionService.createQueuedRuntime({
428
+ renderInput: options.renderInput,
429
+ rendererCache: options.rendererCache,
430
+ runtimeContextKey: options.runtimeContextKey ?? this.getForeignSubtreeResolutionContextKey(),
431
+ tokenPrefix: options.tokenPrefix ?? this.getForeignSubtreeTokenPrefix(),
432
+ createRuntimeContext: options.createRuntimeContext
433
+ });
434
+ }
435
+ getQueuedForeignSubtreeResolutionContext(input) {
436
+ return this.foreignSubtreeExecutionService.getQueuedRuntimeContext(
437
+ input,
438
+ this.getForeignSubtreeResolutionContextKey()
439
+ );
440
+ }
441
+ /**
442
+ * Renders a string-first component, then resolves any queued foreign
443
+ * boundaries before returning final component HTML.
444
+ */
445
+ async renderStringComponentWithQueuedForeignSubtrees(input, component) {
446
+ const componentRender = await this.renderStringComponentWithSerializedChildren(input, component);
447
+ const queuedForeignSubtreeResolution = await this.foreignSubtreeExecutionService.resolveStringQueuedHtml({
448
+ currentIntegrationName: this.name,
449
+ renderInput: input,
450
+ html: componentRender.html,
451
+ runtimeContextKey: this.getForeignSubtreeResolutionContextKey(),
452
+ queueLabel: "String",
453
+ getOwningRenderer: (integrationName, rendererCache) => this.getIntegrationRendererForName(integrationName, rendererCache),
454
+ applyAttributesToFirstElement: (html, attributes) => this.htmlTransformer.applyAttributesToFirstElement(html, attributes),
455
+ dedupeProcessedAssets: (assets) => this.htmlTransformer.dedupeProcessedAssets(assets)
456
+ });
457
+ const mergedAssets = this.htmlTransformer.dedupeProcessedAssets([
458
+ ...componentRender.assets ?? [],
459
+ ...queuedForeignSubtreeResolution.assets
460
+ ]);
461
+ return {
462
+ ...componentRender,
463
+ html: queuedForeignSubtreeResolution.html,
464
+ rootTag: this.getRootTagName(queuedForeignSubtreeResolution.html),
465
+ assets: mergedAssets.length > 0 ? mergedAssets : void 0
466
+ };
467
+ }
112
468
  constructor({
113
469
  appConfig,
114
470
  assetProcessingService,
115
471
  resolvedIntegrationDependencies,
472
+ rendererModules,
116
473
  runtimeOrigin
117
474
  }) {
118
475
  this.appConfig = appConfig;
119
476
  this.assetProcessingService = assetProcessingService;
120
477
  this.htmlTransformer = new HtmlTransformerService();
121
478
  this.resolvedIntegrationDependencies = resolvedIntegrationDependencies || [];
479
+ this.rendererModules = rendererModules ?? appConfig.runtime?.rendererModuleContext;
122
480
  this.runtimeOrigin = runtimeOrigin;
123
481
  this.dependencyResolverService = new DependencyResolverService(appConfig, assetProcessingService);
124
482
  this.pageModuleLoaderService = new PageModuleLoaderService(appConfig, runtimeOrigin);
125
- this.markerGraphResolver = new MarkerGraphResolver();
126
- this.renderPreparationService = new RenderPreparationService(appConfig, assetProcessingService);
127
- this.renderExecutionService = new RenderExecutionService();
483
+ this.routeRenderOrchestrator = new RouteRenderOrchestrator(appConfig, assetProcessingService, {
484
+ ownershipValidationService: new OwnershipValidationService(appConfig)
485
+ });
128
486
  }
129
487
  /**
130
488
  * Returns the HTML path from the provided file path.
@@ -150,41 +508,22 @@ class IntegrationRenderer {
150
508
  * @returns The HTML template component.
151
509
  */
152
510
  async getHtmlTemplate() {
153
- const { absolutePaths } = this.appConfig;
511
+ const htmlTemplatePath = this.getRendererModuleString("htmlTemplateModulePath") ?? this.appConfig.absolutePaths.htmlTemplatePath;
154
512
  try {
155
- const { default: HtmlTemplate } = await this.importPageFile(absolutePaths.htmlTemplatePath);
513
+ const { default: HtmlTemplate } = await this.importPageFile(htmlTemplatePath);
156
514
  return HtmlTemplate;
157
515
  } catch (error) {
158
516
  invariant(false, `Error importing HtmlTemplate: ${error}`);
159
517
  }
160
518
  }
161
- /**
162
- * Returns the static props for the page.
163
- * It calls the provided getStaticProps function with the given options.
164
- *
165
- * @param getStaticProps - The function to get static props.
166
- * @param options - The options to pass to the getStaticProps function.
167
- * @returns The static props and metadata.
168
- */
169
- async getStaticProps(getStaticProps, options) {
170
- return this.pageModuleLoaderService.getStaticPropsForPage({
171
- getStaticProps,
172
- params: options?.params
173
- });
519
+ usesIntegrationPageImporter(_file) {
520
+ return false;
174
521
  }
175
- /**
176
- * Returns the metadata properties for the page.
177
- * It calls the provided getMetadata function with the given context.
178
- *
179
- * @param getMetadata - The function to get metadata.
180
- * @param context - The context to pass to the getMetadata function.
181
- * @returns The metadata properties.
182
- */
183
- async getMetadataProps(getMetadata, { props, params, query }) {
184
- return this.pageModuleLoaderService.getMetadataPropsForPage({
185
- getMetadata,
186
- context: { props, params, query }
187
- });
522
+ async importIntegrationPageFile(_file, _options) {
523
+ invariant(false, "Integration page importer must be implemented when enabled");
524
+ }
525
+ normalizeImportedPageFile(_file, pageModule) {
526
+ return pageModule;
188
527
  }
189
528
  /**
190
529
  * Imports the page file from the specified path.
@@ -193,8 +532,16 @@ class IntegrationRenderer {
193
532
  * @param file - The file path to import.
194
533
  * @returns The imported module.
195
534
  */
196
- async importPageFile(file) {
197
- return this.pageModuleLoaderService.importPageFile(file);
535
+ async importPageFile(file, options) {
536
+ const bypassCache = options?.bypassCache ?? (typeof Bun !== "undefined" && process.env.NODE_ENV === "development");
537
+ const pageModule = this.usesIntegrationPageImporter(file) ? await this.importIntegrationPageFile(file, {
538
+ bypassCache,
539
+ cacheScope: options?.cacheScope
540
+ }) : await this.pageModuleLoaderService.importPageFile(file, {
541
+ bypassCache,
542
+ cacheScope: options?.cacheScope
543
+ });
544
+ return this.normalizeImportedPageFile(file, pageModule);
198
545
  }
199
546
  /**
200
547
  * Resolves the dependency path based on the component directory.
@@ -266,6 +613,103 @@ class IntegrationRenderer {
266
613
  async processComponentDependencies(components) {
267
614
  return this.dependencyResolverService.processComponentDependencies(components, this.name);
268
615
  }
616
+ /**
617
+ * Builds the internal route-render adapter consumed by `RouteRenderOrchestrator`.
618
+ *
619
+ * The route orchestrator needs a narrow orchestration contract, but those hooks should
620
+ * not become public API on the renderer base class. Keeping the adapter object
621
+ * local to the execution path lets the orchestrator depend on one explicit seam while
622
+ * subclasses continue to override protected renderer behavior directly.
623
+ */
624
+ createRouteRenderOrchestratorAdapter() {
625
+ return {
626
+ name: this.name,
627
+ resolveRouteRenderInputs: (routeOptions) => this.resolveRouteRenderInputs(routeOptions),
628
+ resolveRouteDependencies: (input) => this.resolveRouteDependencies(input),
629
+ collectPageBrowserGraphContribution: async (routeFile) => {
630
+ const pageModule = await this.importPageFile(routeFile);
631
+ return await this.collectPageBrowserGraphContribution({ file: routeFile, pageModule });
632
+ },
633
+ resolveRoutePageComponentRender: (input) => this.resolveRoutePageComponentRender(input),
634
+ renderRouteBody: (renderOptions) => this.renderRouteBody(renderOptions),
635
+ getRouteHtmlFinalization: (renderOptions) => this.getRouteHtmlFinalization(renderOptions),
636
+ transformRouteResponse: (response, htmlContributions) => this.transformRouteResponse(response, htmlContributions)
637
+ };
638
+ }
639
+ async resolveRouteRenderInputs(routeOptions) {
640
+ const pageModule = await this.pageModuleLoaderService.resolvePageModule({
641
+ file: routeOptions.file,
642
+ importPageFileFn: (targetFile) => this.importPageFile(targetFile)
643
+ });
644
+ const { Page, integrationSpecificProps } = pageModule;
645
+ const HtmlTemplate = await this.getHtmlTemplate();
646
+ const Layout = Page.config?.layout;
647
+ const { props, metadata } = await this.pageModuleLoaderService.resolvePageData({
648
+ pageModule,
649
+ routeOptions
650
+ });
651
+ return {
652
+ Page,
653
+ HtmlTemplate,
654
+ Layout,
655
+ props,
656
+ metadata,
657
+ integrationSpecificProps
658
+ };
659
+ }
660
+ async resolveRouteDependencies(input) {
661
+ return {
662
+ resolvedDependencies: await this.resolveDependencies(input.components)
663
+ };
664
+ }
665
+ async resolveRoutePageComponentRender(input) {
666
+ if (!this.shouldRenderPageComponent({ Page: input.Page, Layout: input.Layout, options: input.routeOptions })) {
667
+ return void 0;
668
+ }
669
+ return this.renderComponentWithForeignChildren({
670
+ component: input.Page,
671
+ props: {
672
+ ...input.props,
673
+ params: input.routeOptions.params || {},
674
+ query: input.routeOptions.query || {}
675
+ },
676
+ integrationContext: {
677
+ componentInstanceId: "eco-page-root"
678
+ }
679
+ });
680
+ }
681
+ async renderRouteBody(renderOptions) {
682
+ return this.render(renderOptions);
683
+ }
684
+ getRouteHtmlFinalization(renderOptions) {
685
+ const componentRootAttributes = renderOptions.componentRender?.canAttachAttributes && renderOptions.componentRender.rootAttributes && Object.keys(renderOptions.componentRender.rootAttributes).length > 0 ? renderOptions.componentRender.rootAttributes : void 0;
686
+ const documentAttributes = this.getDocumentAttributes(renderOptions);
687
+ const htmlContributions = this.getHtmlDocumentContributions({ renderOptions, partial: false });
688
+ const hasStructuralFinalization = componentRootAttributes && Object.keys(componentRootAttributes).length > 0 || documentAttributes && Object.keys(documentAttributes).length > 0;
689
+ if (!hasStructuralFinalization && (!htmlContributions || htmlContributions.length === 0)) {
690
+ return {};
691
+ }
692
+ return {
693
+ htmlContributions,
694
+ finalizeHtml: (html) => {
695
+ let renderedHtml = html;
696
+ if (componentRootAttributes) {
697
+ renderedHtml = this.htmlTransformer.applyAttributesToFirstBodyElement(
698
+ renderedHtml,
699
+ componentRootAttributes
700
+ );
701
+ }
702
+ if (documentAttributes) {
703
+ renderedHtml = this.htmlTransformer.applyAttributesToHtmlElement(renderedHtml, documentAttributes);
704
+ }
705
+ return renderedHtml;
706
+ }
707
+ };
708
+ }
709
+ async transformRouteResponse(response, htmlContributions) {
710
+ const transformedResponse = await this.htmlTransformer.transform(response, htmlContributions);
711
+ return transformedResponse.body ?? await transformedResponse.text();
712
+ }
269
713
  /**
270
714
  * Prepares the render options for the integration renderer.
271
715
  * It imports the page file, collects dependencies, and prepares the render options.
@@ -273,26 +717,11 @@ class IntegrationRenderer {
273
717
  * @param options - The route renderer options.
274
718
  * @returns The prepared render options.
275
719
  */
276
- async prepareRenderOptions(options) {
277
- return this.renderPreparationService.prepare(options, this.name, {
278
- resolvePageModule: (file) => this.resolvePageModule(file),
279
- getHtmlTemplate: () => this.getHtmlTemplate(),
280
- resolvePageData: (pageModule, routeOptions) => this.resolvePageData(pageModule, routeOptions),
281
- resolveDependencies: (components) => this.resolveDependencies(components),
282
- buildRouteRenderAssets: (file) => this.buildRouteRenderAssets(file),
283
- shouldRenderPageComponent: (input) => this.shouldRenderPageComponent(input),
284
- renderPageComponent: ({ component, props }) => this.renderComponent({
285
- component,
286
- props,
287
- integrationContext: {
288
- componentInstanceId: "eco-page-root"
289
- }
290
- }),
291
- getComponentRenderBoundaryContext: () => this.getComponentRenderBoundaryContext(),
292
- setProcessedDependencies: (dependencies) => this.htmlTransformer.setProcessedDependencies(dependencies),
293
- dedupeProcessedAssets: (assets) => this.htmlTransformer.dedupeProcessedAssets(assets),
294
- createPageLocalsProxy: (filePath) => createLocalsProxy(filePath)
295
- });
720
+ async prepareRenderOptions(options, adapter = this.createRouteRenderOrchestratorAdapter()) {
721
+ const renderOptions = await this.routeRenderOrchestrator.prepareRenderOptions(options, adapter);
722
+ invariant(renderOptions.pagePackage !== void 0, "Expected render preparation to produce a page package");
723
+ this.htmlTransformer.setPagePackage(renderOptions.pagePackage);
724
+ return renderOptions;
296
725
  }
297
726
  /**
298
727
  * Controls whether the page root should be rendered through `renderComponent()`
@@ -305,34 +734,15 @@ class IntegrationRenderer {
305
734
  shouldRenderPageComponent(_input) {
306
735
  return true;
307
736
  }
308
- /**
309
- * Resolves the page module and normalizes exports.
310
- */
311
- async resolvePageModule(file) {
312
- return this.pageModuleLoaderService.resolvePageModule({
313
- file,
314
- importPageFileFn: (targetFile) => this.importPageFile(targetFile)
315
- });
316
- }
317
- /**
318
- * Resolves static props and metadata for the page.
319
- */
320
- async resolvePageData(pageModule, options) {
321
- return this.pageModuleLoaderService.resolvePageData({
322
- pageModule,
323
- routeOptions: options
324
- });
325
- }
326
737
  /**
327
738
  * Executes the integration renderer with the provided options.
328
739
  *
329
740
  * Execution flow:
330
741
  * 1. Build normalized render options (`prepareRenderOptions`).
331
- * 2. Render once inside component render context to capture marker graph refs.
332
- * 3. Merge captured refs with optional explicit page-module graph context.
333
- * 4. Resolve any `eco-marker` graph bottom-up and merge produced assets.
334
- * 5. Optionally apply root attributes for page/component root boundaries.
335
- * 6. Run HTML transformer with final dependency set.
742
+ * 2. Render the route body once.
743
+ * 3. Reject unresolved route-level eco-marker artifacts.
744
+ * 4. Optionally apply root attributes for page/component root boundaries.
745
+ * 5. Run HTML transformer with final dependency set.
336
746
  *
337
747
  * Stream-safety note: the first render result is normalized to a string once,
338
748
  * then the pipeline continues with that immutable HTML value to avoid disturbed
@@ -342,84 +752,39 @@ class IntegrationRenderer {
342
752
  * @returns Rendered route body plus effective cache strategy.
343
753
  */
344
754
  async execute(options) {
345
- return this.renderExecutionService.execute(options, this.name, {
346
- prepareRenderOptions: (routeOptions) => this.prepareRenderOptions(routeOptions),
347
- 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
- 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
- applyAttributesToHtmlElement: (html, attributes) => this.htmlTransformer.applyAttributesToHtmlElement(html, attributes),
359
- applyAttributesToFirstBodyElement: (html, attributes) => this.htmlTransformer.applyAttributesToFirstBodyElement(html, attributes),
360
- transformHtml: async (html) => {
361
- const response = await this.htmlTransformer.transform(
362
- new Response(html, {
363
- headers: {
364
- "Content-Type": "text/html"
365
- }
366
- })
367
- );
368
- return response.body;
369
- }
370
- });
755
+ const adapter = this.createRouteRenderOrchestratorAdapter();
756
+ const renderOptions = await this.prepareRenderOptions(options, adapter);
757
+ return this.routeRenderOrchestrator.executePrepared(renderOptions, adapter);
371
758
  }
372
759
  /**
373
- * Captures a render pass as immutable HTML along with the graph context needed
374
- * for deferred marker resolution.
760
+ * Finalizes already-resolved HTML for explicit renderer-owned paths.
375
761
  *
376
- * This is the shared entry point for direct `renderToResponse()` flows that
377
- * need the same component graph capture semantics as route execution without
378
- * going through `prepareRenderOptions()`.
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.
762
+ * This keeps document and root-attribute stamping plus HTML transformation
763
+ * available after a renderer has completed nested foreign-subtree resolution without
764
+ * routing back through shared route execution.
391
765
  */
392
- async finalizeCapturedHtmlRender(options) {
393
- const finalization = await this.renderExecutionService.finalizeHtmlRender(
394
- {
395
- html: options.html,
396
- graphContext: options.graphContext,
397
- componentsToResolve: options.componentsToResolve,
398
- componentRootAttributes: options.componentRootAttributes,
399
- documentAttributes: options.documentAttributes,
400
- mergeAssets: options.mergeAssets ?? !options.partial
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
- );
766
+ async finalizeResolvedHtml(options) {
767
+ const rendererBootstrapDependencies = this.getRendererBootstrapDependencies(options.partial);
768
+ this.appendProcessedDependencies(rendererBootstrapDependencies);
769
+ let html = options.html;
770
+ if (options.componentRootAttributes && Object.keys(options.componentRootAttributes).length > 0) {
771
+ html = this.htmlTransformer.applyAttributesToFirstBodyElement(html, options.componentRootAttributes);
772
+ }
773
+ if (options.documentAttributes && Object.keys(options.documentAttributes).length > 0) {
774
+ html = this.htmlTransformer.applyAttributesToHtmlElement(html, options.documentAttributes);
775
+ }
415
776
  const shouldTransform = options.transformHtml ?? !options.partial;
416
777
  if (!shouldTransform) {
417
- return finalization.html;
778
+ return html;
418
779
  }
780
+ const htmlContributions = options.htmlContributions ?? this.getHtmlDocumentContributions({
781
+ partial: options.partial
782
+ });
419
783
  const transformedResponse = await this.htmlTransformer.transform(
420
- new Response(finalization.html, {
784
+ new Response(html, {
421
785
  headers: { "Content-Type": "text/html" }
422
- })
786
+ }),
787
+ htmlContributions
423
788
  );
424
789
  return await transformedResponse.text();
425
790
  }
@@ -433,37 +798,16 @@ class IntegrationRenderer {
433
798
  return void 0;
434
799
  }
435
800
  /**
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
- });
801
+ * Returns declarative HTML fragments that core should inject into the final document.
802
+ *
803
+ * @remarks
804
+ * Integrations may contribute document markup here, but core retains ownership
805
+ * of the final HTML rewrite pipeline and placement semantics. This is the
806
+ * supported document-markup extension point for integrations instead of custom
807
+ * response finalization logic.
808
+ */
809
+ getHtmlDocumentContributions(_options) {
810
+ return void 0;
467
811
  }
468
812
  /**
469
813
  * Returns a renderer instance for a given integration name.
@@ -486,26 +830,100 @@ class IntegrationRenderer {
486
830
  const integrationPlugin = this.appConfig.integrations.find(
487
831
  (integration) => integration.name === integrationName
488
832
  );
489
- invariant(!!integrationPlugin, `[ecopages] Integration not found for marker: ${integrationName}`);
490
- const renderer = integrationPlugin.initializeRenderer();
833
+ invariant(!!integrationPlugin, `[ecopages] Integration not found for foreign owner: ${integrationName}`);
834
+ const renderer = integrationPlugin.initializeRenderer({
835
+ rendererModules: this.appConfig.runtime?.rendererModuleContext
836
+ });
491
837
  cache.set(integrationName, renderer);
492
838
  return renderer;
493
839
  }
840
+ /**
841
+ * Renders one component under this integration's foreign-child runtime and resolves
842
+ * any nested foreign children captured during that render.
843
+ *
844
+ * Without this wrapper, a component tree with foreign-owned descendants would
845
+ * render them with no active foreign-child runtime, which bypasses the owning
846
+ * renderer's nested foreign-child handoff.
847
+ */
848
+ async renderComponentWithForeignChildren(input) {
849
+ return await this.foreignSubtreeExecutionService.executeComponentRender({
850
+ currentIntegrationName: this.name,
851
+ input,
852
+ renderComponent: (renderInput) => this.renderComponent(renderInput),
853
+ normalizeComponentRenderOutput: (result) => this.normalizeComponentRenderOutput(result),
854
+ hasForeignChildDescendants: (component) => this.hasForeignChildDescendants(component),
855
+ createForeignChildRuntime: ({ renderInput, rendererCache }) => this.createForeignChildRuntime({
856
+ renderInput,
857
+ rendererCache
858
+ }),
859
+ getOwningRenderer: (integrationName, rendererCache) => this.getIntegrationRendererForName(integrationName, rendererCache)
860
+ });
861
+ }
862
+ /**
863
+ * Compatibility foreign-subtree contract that exposes a narrower payload shape for
864
+ * future route-composition work while preserving the current
865
+ * `renderComponentWithForeignChildren()` runtime semantics.
866
+ */
867
+ async renderForeignSubtree(input) {
868
+ const result = await this.renderComponentWithForeignChildren(input);
869
+ return {
870
+ html: result.html,
871
+ assets: result.assets ?? [],
872
+ rootTag: result.rootTag,
873
+ rootAttributes: result.rootAttributes,
874
+ attachmentPolicy: result.canAttachAttributes ? { kind: "first-element" } : { kind: "none" },
875
+ integrationName: result.integrationName
876
+ };
877
+ }
878
+ normalizeComponentRenderOutput(result) {
879
+ const normalizedHtml = this.normalizeUnresolvedMarkerArtifactHtml(result.html);
880
+ return normalizedHtml === result.html ? result : {
881
+ ...result,
882
+ html: normalizedHtml
883
+ };
884
+ }
885
+ normalizeUnresolvedMarkerArtifactHtml(html) {
886
+ return normalizeUnresolvedMarkerArtifactHtml(html);
887
+ }
888
+ /**
889
+ * Returns whether the component dependency tree crosses into another
890
+ * integration.
891
+ *
892
+ * This keeps foreign-child runtime setup narrow: same-integration trees can render
893
+ * directly without paying the queue orchestration cost.
894
+ */
895
+ hasForeignChildDescendants(component) {
896
+ const stack = [component];
897
+ const seen = /* @__PURE__ */ new Set();
898
+ while (stack.length > 0) {
899
+ const current = stack.pop();
900
+ if (!current || seen.has(current)) {
901
+ continue;
902
+ }
903
+ seen.add(current);
904
+ const integrationName = current.config?.integration ?? current.config?.__eco?.integration;
905
+ if (integrationName && integrationName !== this.name) {
906
+ return true;
907
+ }
908
+ stack.push(...current.config?.dependencies?.components ?? []);
909
+ }
910
+ return false;
911
+ }
494
912
  /**
495
913
  * Render a single component and return structured output for orchestration paths.
496
914
  *
497
915
  * Default behavior delegates to `renderToResponse` in partial mode and wraps
498
916
  * the resulting HTML into the `ComponentRenderResult` contract.
499
917
  *
500
- * In marker resolution, this method is the integration-owned step that turns an
501
- * already-resolved deferred boundary into concrete HTML, assets, and optional
918
+ * In foreign-subtree resolution, this method is the integration-owned step that turns an
919
+ * already-resolved deferred foreign subtree into concrete HTML, assets, and optional
502
920
  * root attributes.
503
921
  *
504
922
  * Integrations can override this for richer behavior (asset emission,
505
923
  * root attributes, integration-specific hydration metadata).
506
924
  *
507
925
  * @param input Component render request.
508
- * @returns Structured render result used by marker/page orchestration.
926
+ * @returns Structured render result used by component/page orchestration.
509
927
  */
510
928
  async renderComponent(input) {
511
929
  const response = await this.renderToResponse(
@@ -528,60 +946,44 @@ class IntegrationRenderer {
528
946
  * @returns Root tag name when present; otherwise `undefined`.
529
947
  */
530
948
  getRootTagName(html) {
531
- const rootTag = html.match(/^\s*<([a-zA-Z][a-zA-Z0-9:-]*)\b/);
949
+ const rootTag = html.match(/^(?:\s|<!--[\s\S]*?-->)*<([a-zA-Z][a-zA-Z0-9:-]*)\b/);
532
950
  return rootTag?.[1];
533
951
  }
534
952
  /**
535
- * Method to build route render assets.
536
- * This method can be optionally overridden by the specific integration renderer.
953
+ * Collects declarative Page Browser Graph contributions for one Page.
954
+ *
955
+ * @remarks
956
+ * Integrations may describe page-scoped browser requirements here, while core
957
+ * retains ownership of dependency processing and final graph assembly. This is
958
+ * the supported page-browser extension point for integrations.
537
959
  *
538
- * @param file - The file path to build assets for.
539
- * @returns The processed assets or undefined.
960
+ * @param context - The route file path and already imported page module.
961
+ * @returns Declarative dependencies or pre-resolved assets for the Page.
540
962
  */
541
- buildRouteRenderAssets(_file) {
963
+ async collectPageBrowserGraphContribution(_context) {
542
964
  return void 0;
543
965
  }
544
966
  /**
545
- * Builds the narrow boundary policy facade injected into component render
546
- * context for this render pass.
967
+ * Creates the per-render foreign-child runtime adopted by the shared component
968
+ * render context.
547
969
  *
548
- * `eco.component()` consumes this facade without knowing about integration
549
- * registries or plugin instances.
550
- *
551
- * @returns Boundary policy context for the active integration renderer.
970
+ * The default runtime queues delegated foreign subtrees inside the owning
971
+ * renderer so string and markup renderers do not need to re-declare the same
972
+ * handoff boilerplate. Override only when a renderer needs custom runtime
973
+ * context or a different foreign-child execution strategy.
552
974
  */
553
- getComponentRenderBoundaryContext() {
554
- return {
555
- decideBoundaryRender: (input) => this.shouldDeferComponentBoundary(input) ? "defer" : "inline"
556
- };
975
+ createForeignChildRuntime(options) {
976
+ return this.createQueuedForeignSubtreeExecutionRuntime({
977
+ renderInput: options.renderInput,
978
+ rendererCache: options.rendererCache
979
+ });
557
980
  }
558
981
  /**
559
- * Resolves whether a component boundary should be deferred by consulting the
560
- * target integration plugin.
561
- *
562
- * Boundaries targeting the current integration always render inline. Cross-
563
- * integration boundaries delegate the decision to the target integration's
564
- * `shouldDeferComponentBoundary()` policy.
565
- *
566
- * @param input Boundary metadata for the active render pass.
567
- * @returns `true` when the boundary should emit a marker; otherwise `false`.
982
+ * Creates an explicit fail-fast runtime for tests or renderers that do not
983
+ * support cross-integration foreign-child execution.
568
984
  */
569
- shouldDeferComponentBoundary(input) {
570
- if (!input.targetIntegration || input.targetIntegration === input.currentIntegration) {
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
- });
985
+ createFailFastForeignChildRuntime() {
986
+ return this.foreignSubtreeExecutionService.createFailFastRuntime(this.name);
585
987
  }
586
988
  }
587
989
  export {