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