@ecopages/core 0.2.0-beta.3 → 0.2.0-beta.30

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 (433) hide show
  1. package/README.md +38 -9
  2. package/package.json +241 -30
  3. package/src/adapters/README.md +6 -2
  4. package/src/adapters/abstract/application-adapter.d.ts +123 -6
  5. package/src/adapters/abstract/application-adapter.js +151 -1
  6. package/src/adapters/abstract/segment-path-matcher.d.ts +6 -0
  7. package/src/adapters/abstract/segment-path-matcher.js +149 -0
  8. package/src/adapters/abstract/server-adapter.d.ts +16 -2
  9. package/src/adapters/abstract/ws-pattern-matcher.d.ts +12 -0
  10. package/src/adapters/abstract/ws-pattern-matcher.js +30 -0
  11. package/src/adapters/bun/bun-user-websocket-lifecycle.d.ts +22 -0
  12. package/src/adapters/bun/bun-user-websocket-lifecycle.js +96 -0
  13. package/src/adapters/bun/client-bridge.d.ts +1 -0
  14. package/src/adapters/bun/client-bridge.js +3 -0
  15. package/src/adapters/bun/create-app.d.ts +9 -6
  16. package/src/adapters/bun/create-app.js +76 -45
  17. package/src/adapters/bun/hmr-manager.d.ts +1 -1
  18. package/src/adapters/bun/hmr-manager.js +1 -1
  19. package/src/adapters/bun/index.d.ts +1 -1
  20. package/src/adapters/bun/index.js +25 -2
  21. package/src/adapters/bun/runtime-host.d.ts +1 -1
  22. package/src/adapters/bun/runtime-host.js +1 -1
  23. package/src/adapters/bun/server-adapter.d.ts +92 -41
  24. package/src/adapters/bun/server-adapter.js +256 -117
  25. package/src/adapters/bun/static-preview-host.d.ts +1 -1
  26. package/src/adapters/bun/static-preview-host.js +25 -20
  27. package/src/adapters/create-app.d.ts +13 -11
  28. package/src/adapters/create-app.js +2 -51
  29. package/src/adapters/index.d.ts +2 -2
  30. package/src/adapters/index.js +26 -4
  31. package/src/adapters/node/create-app.d.ts +8 -3
  32. package/src/adapters/node/create-app.js +61 -13
  33. package/src/adapters/node/node-client-bridge.d.ts +1 -0
  34. package/src/adapters/node/node-client-bridge.js +3 -0
  35. package/src/adapters/node/node-hmr-manager.d.ts +1 -1
  36. package/src/adapters/node/node-hmr-manager.js +1 -1
  37. package/src/adapters/node/runtime-host.d.ts +1 -1
  38. package/src/adapters/node/runtime-host.js +1 -1
  39. package/src/adapters/node/server-adapter-dependencies.js +4 -0
  40. package/src/adapters/node/server-adapter.d.ts +64 -23
  41. package/src/adapters/node/server-adapter.js +169 -142
  42. package/src/adapters/node/static-content-server.d.ts +1 -0
  43. package/src/adapters/node/static-content-server.js +10 -2
  44. package/src/adapters/node/static-preview-host.d.ts +1 -1
  45. package/src/adapters/node/static-preview-host.js +27 -12
  46. package/src/adapters/shared/{hmr-entrypoint-registrar.d.ts → hmr/hmr-entrypoint-registrar.d.ts} +31 -30
  47. package/src/adapters/shared/hmr/hmr-entrypoint-registrar.js +106 -0
  48. package/src/adapters/shared/{hmr-html-response.d.ts → hmr/hmr-html-response.d.ts} +2 -2
  49. package/src/adapters/shared/{hmr-html-response.js → hmr/hmr-html-response.js} +4 -1
  50. package/src/adapters/shared/hmr/shared-hmr-manager.d.ts +101 -0
  51. package/src/adapters/shared/hmr/shared-hmr-manager.js +432 -0
  52. package/src/adapters/shared/http/api-request-pipeline.d.ts +23 -0
  53. package/src/adapters/shared/http/api-request-pipeline.js +129 -0
  54. package/src/adapters/shared/{api-response.d.ts → http/api-response.d.ts} +1 -1
  55. package/src/adapters/shared/{api-response.js → http/api-response.js} +6 -23
  56. package/src/adapters/shared/http/create-body-response.d.ts +12 -0
  57. package/src/adapters/shared/http/create-body-response.js +23 -0
  58. package/src/adapters/shared/http/define-api-handler.d.ts +90 -0
  59. package/src/adapters/shared/http/define-api-handler.js +63 -0
  60. package/src/adapters/shared/{explicit-static-render-preparation.d.ts → http/explicit-static-render-preparation.d.ts} +3 -3
  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/{explicit-static-route-matcher.js → http/explicit-static-route-matcher.js} +3 -38
  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/{file-route-middleware-pipeline.js → http/file-route-middleware-pipeline.js} +10 -22
  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/{fs-server-response-factory.js → http/fs-server-response-factory.js} +22 -2
  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/{fs-server-response-matcher.js → http/fs-server-response-matcher.js} +109 -27
  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/{application-adapter.js → runtime/application-adapter.js} +1 -1
  73. package/src/adapters/shared/runtime/copy-runtime-public-dir.d.ts +6 -0
  74. package/src/adapters/shared/runtime/copy-runtime-public-dir.js +24 -0
  75. package/src/adapters/shared/runtime/port-manager.d.ts +116 -0
  76. package/src/adapters/shared/runtime/port-manager.js +196 -0
  77. package/src/adapters/shared/{render-context.d.ts → runtime/render-context.d.ts} +2 -2
  78. package/src/adapters/shared/{render-context.js → runtime/render-context.js} +8 -17
  79. package/src/adapters/shared/{runtime-app-bootstrap.d.ts → runtime/runtime-app-bootstrap.d.ts} +4 -3
  80. package/src/adapters/shared/{runtime-app-bootstrap.js → runtime/runtime-app-bootstrap.js} +4 -7
  81. package/src/adapters/shared/runtime/runtime-server-lifecycle.d.ts +46 -0
  82. package/src/adapters/shared/runtime/runtime-server-lifecycle.js +57 -0
  83. package/src/adapters/shared/{server-adapter.d.ts → runtime/server-adapter.d.ts} +23 -49
  84. package/src/adapters/shared/runtime/server-adapter.js +226 -0
  85. package/src/adapters/shared/{server-route-handler.d.ts → runtime/server-route-handler.d.ts} +6 -33
  86. package/src/adapters/shared/{server-route-handler.js → runtime/server-route-handler.js} +5 -43
  87. package/src/adapters/shared/{server-static-builder.d.ts → runtime/server-static-builder.d.ts} +27 -35
  88. package/src/adapters/shared/runtime/server-static-builder.js +191 -0
  89. package/src/adapters/shared/{static-preview-host.d.ts → runtime/static-preview-host.d.ts} +6 -1
  90. package/src/adapters/shared/ws/node-http-websocket-upgrades.d.ts +21 -0
  91. package/src/adapters/shared/ws/node-http-websocket-upgrades.js +100 -0
  92. package/src/adapters/shared/ws/websocket-lifecycle.d.ts +24 -0
  93. package/src/adapters/shared/ws/websocket-lifecycle.js +55 -0
  94. package/src/build/README.md +140 -31
  95. package/src/build/app-build-manifest-runtime.d.ts +39 -0
  96. package/src/build/app-build-manifest-runtime.js +124 -0
  97. package/src/build/{browser-runtime-plugin.d.ts → browser/browser-runtime-plugin.d.ts} +1 -1
  98. package/src/build/{browser-runtime-plugin.js → browser/browser-runtime-plugin.js} +1 -1
  99. package/src/build/browser/jsx-ownership-plugins.d.ts +24 -0
  100. package/src/build/browser/jsx-ownership-plugins.js +41 -0
  101. package/src/build/browser/lit-static-render-worker-context.d.ts +2 -0
  102. package/src/build/browser/lit-static-render-worker-context.js +6 -0
  103. package/src/build/build-adapter.d.ts +29 -334
  104. package/src/build/build-adapter.js +32 -133
  105. package/src/build/cache/build-input-fingerprint.d.ts +28 -0
  106. package/src/build/cache/build-input-fingerprint.js +31 -0
  107. package/src/build/cache/cache-constants.d.ts +4 -0
  108. package/src/build/cache/cache-constants.js +6 -0
  109. package/src/build/cache/cache-keys.d.ts +22 -0
  110. package/src/build/cache/cache-keys.js +63 -0
  111. package/src/build/cache/dev-browser-script-cache.d.ts +34 -0
  112. package/src/build/cache/dev-browser-script-cache.js +90 -0
  113. package/src/build/cache/pages-unified-graph-build.d.ts +31 -0
  114. package/src/build/cache/pages-unified-graph-build.js +198 -0
  115. package/src/build/cache/production-build-cache.d.ts +20 -0
  116. package/src/build/cache/production-build-cache.js +63 -0
  117. package/src/build/cache/server-entry-build-cache.d.ts +43 -0
  118. package/src/build/cache/server-entry-build-cache.js +165 -0
  119. package/src/build/contracts/build-contracts.d.ts +96 -0
  120. package/src/build/contracts/build-manifest.d.ts +90 -0
  121. package/src/build/{build-manifest.js → contracts/build-manifest.js} +2 -2
  122. package/src/build/contracts/build-types.js +0 -0
  123. package/src/build/{rolldown-adapter-helpers.d.ts → rolldown/rolldown-adapter-helpers.d.ts} +23 -9
  124. package/src/build/{rolldown-adapter-helpers.js → rolldown/rolldown-adapter-helpers.js} +99 -13
  125. package/src/build/{rolldown-build-adapter.d.ts → rolldown/rolldown-build-adapter.d.ts} +3 -7
  126. package/src/build/{rolldown-build-adapter.js → rolldown/rolldown-build-adapter.js} +3 -3
  127. package/src/build/rolldown/rolldown-build-invocation-metrics.d.ts +12 -0
  128. package/src/build/rolldown/rolldown-build-invocation-metrics.js +43 -0
  129. package/src/build/{rolldown-plugin-bridge.d.ts → rolldown/rolldown-plugin-bridge.d.ts} +16 -2
  130. package/src/build/{rolldown-plugin-bridge.js → rolldown/rolldown-plugin-bridge.js} +21 -6
  131. package/src/build/rolldown/rolldown-source-transform-pass.d.ts +15 -0
  132. package/src/build/rolldown/rolldown-source-transform-pass.js +61 -0
  133. package/src/build/rolldown/runtime-build-output-normalizer.d.ts +10 -0
  134. package/src/build/rolldown/runtime-build-output-normalizer.js +201 -0
  135. package/src/build/runtime/build-profile-options.d.ts +7 -0
  136. package/src/build/runtime/build-profile-options.js +37 -0
  137. package/src/build/runtime/build-request-identity.d.ts +17 -0
  138. package/src/build/runtime/build-request-identity.js +54 -0
  139. package/src/build/runtime/build-request-policy.d.ts +59 -0
  140. package/src/build/runtime/build-request-policy.js +46 -0
  141. package/src/build/runtime/build-runtime.d.ts +28 -0
  142. package/src/build/runtime/build-runtime.js +65 -0
  143. package/src/build/runtime/deduping-build-executor.d.ts +21 -0
  144. package/src/build/runtime/deduping-build-executor.js +34 -0
  145. package/src/build/runtime/parallel-build-executor.d.ts +21 -0
  146. package/src/build/runtime/parallel-build-executor.js +52 -0
  147. package/src/build/{serialized-build-executor.d.ts → runtime/serialized-build-executor.d.ts} +1 -1
  148. package/src/client/navigation-scripts/classification.d.ts +16 -0
  149. package/src/client/navigation-scripts/classification.js +41 -0
  150. package/src/client/navigation-scripts/index.d.ts +3 -0
  151. package/src/client/navigation-scripts/index.js +23 -0
  152. package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
  153. package/src/client/navigation-scripts/registry.d.ts +11 -0
  154. package/src/client/navigation-scripts/registry.js +12 -0
  155. package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
  156. package/src/client/navigation-scripts/rerun-queue.js +73 -0
  157. package/src/client/scroll.d.ts +17 -0
  158. package/src/client/scroll.js +25 -0
  159. package/src/client/scroll.test.browser.js +37 -0
  160. package/src/client/view-transitions.d.ts +16 -0
  161. package/src/client/view-transitions.js +63 -0
  162. package/src/config/config-builder.d.ts +25 -10
  163. package/src/config/config-builder.js +53 -11
  164. package/src/config/constants.d.ts +1 -0
  165. package/src/config/constants.js +2 -1
  166. package/src/dev/client-bridge-registry.d.ts +5 -0
  167. package/src/dev/client-bridge-registry.js +15 -0
  168. package/src/dev/dev-client-ownership.d.ts +7 -0
  169. package/src/dev/dev-client-ownership.js +6 -0
  170. package/src/dev/hmr-manager-registry.d.ts +8 -0
  171. package/src/dev/hmr-manager-registry.js +15 -0
  172. package/src/dev/host-runtime.d.ts +3 -0
  173. package/src/dev/host-runtime.js +7 -0
  174. package/src/dev/runtime-server-started-message.d.ts +2 -0
  175. package/src/dev/runtime-server-started-message.js +6 -0
  176. package/src/diagnostics/request-build-dedupe.d.ts +18 -0
  177. package/src/diagnostics/request-build-dedupe.js +33 -0
  178. package/src/diagnostics/startup-trace.d.ts +72 -0
  179. package/src/diagnostics/startup-trace.js +253 -0
  180. package/src/eco/README.md +11 -0
  181. package/src/eco/eco-declared-component.d.ts +14 -0
  182. package/src/eco/eco-declared-component.js +16 -0
  183. package/src/eco/eco.browser.js +5 -6
  184. package/src/eco/eco.js +7 -8
  185. package/src/eco/eco.types.d.ts +14 -3
  186. package/src/eco/eco.utils.d.ts +1 -1
  187. package/src/eco/eco.utils.js +1 -1
  188. package/src/eco/page-layout-normalization.d.ts +21 -0
  189. package/src/eco/page-layout-normalization.js +59 -0
  190. package/src/env.d.ts +2 -0
  191. package/src/errors/index.d.ts +1 -0
  192. package/src/errors/index.js +7 -1
  193. package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
  194. package/src/errors/undeclared-component-dependency-error.js +17 -0
  195. package/src/hmr/client/hmr-runtime.js +7 -4
  196. package/src/hmr/hmr-entrypoint-output.d.ts +49 -0
  197. package/src/hmr/hmr-entrypoint-output.js +60 -0
  198. package/src/hmr/hmr-file-change-prep.d.ts +10 -0
  199. package/src/hmr/hmr-file-change-prep.js +17 -0
  200. package/src/hmr/hmr-strategy.d.ts +15 -0
  201. package/src/hmr/hmr-strategy.js +19 -0
  202. package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -5
  203. package/src/hmr/strategies/js-hmr-strategy.js +72 -19
  204. package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
  205. package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
  206. package/src/index.d.ts +2 -1
  207. package/src/index.js +28 -2
  208. package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
  209. package/src/integrations/ghtml/ghtml-renderer.js +2 -51
  210. package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
  211. package/src/integrations/ghtml/ghtml.plugin.js +7 -14
  212. package/src/plugins/alias-resolver-cache.d.ts +6 -9
  213. package/src/plugins/alias-resolver-plugin.d.ts +3 -3
  214. package/src/plugins/alias-resolver-plugin.js +38 -51
  215. package/src/plugins/define-integration.d.ts +26 -0
  216. package/src/plugins/define-integration.js +19 -0
  217. package/src/plugins/eco-component-meta-plugin.d.ts +1 -1
  218. package/src/plugins/eco-component-meta-plugin.js +5 -8
  219. package/src/plugins/foreign-jsx-override-plugin.d.ts +1 -1
  220. package/src/plugins/foreign-jsx-override-plugin.js +4 -6
  221. package/src/plugins/integration-plugin.d.ts +43 -14
  222. package/src/plugins/integration-plugin.js +18 -5
  223. package/src/plugins/jsx-import-source.utils.d.ts +8 -0
  224. package/src/plugins/jsx-import-source.utils.js +26 -0
  225. package/src/plugins/processor.d.ts +61 -12
  226. package/src/plugins/processor.js +24 -5
  227. package/src/plugins/source-transform.d.ts +32 -1
  228. package/src/plugins/source-transform.js +23 -1
  229. package/src/plugins/tsconfig-import-resolver.d.ts +18 -0
  230. package/src/plugins/tsconfig-import-resolver.js +159 -0
  231. package/src/route-renderer/GRAPH.md +26 -32
  232. package/src/route-renderer/README.md +38 -31
  233. package/src/route-renderer/orchestration/document-shell/document-shell-render.service.d.ts +107 -0
  234. package/src/route-renderer/orchestration/document-shell/document-shell-render.service.js +148 -0
  235. package/src/route-renderer/orchestration/document-shell/layout-shell-props.service.d.ts +20 -0
  236. package/src/route-renderer/orchestration/document-shell/layout-shell-props.service.js +31 -0
  237. package/src/route-renderer/orchestration/{component-render-context.d.ts → foreign-child/component-render-context.d.ts} +8 -15
  238. package/src/route-renderer/orchestration/{component-render-context.js → foreign-child/component-render-context.js} +4 -2
  239. package/src/route-renderer/orchestration/{render-output.utils.d.ts → foreign-child/foreign-child-output.utils.d.ts} +17 -7
  240. package/src/route-renderer/orchestration/{render-output.utils.js → foreign-child/foreign-child-output.utils.js} +35 -26
  241. package/src/route-renderer/orchestration/{foreign-subtree-execution.service.d.ts → foreign-child/foreign-subtree-execution.service.d.ts} +64 -34
  242. package/src/route-renderer/orchestration/{foreign-subtree-execution.service.js → foreign-child/foreign-subtree-execution.service.js} +170 -37
  243. package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.d.ts +19 -0
  244. package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.js +35 -0
  245. package/src/route-renderer/orchestration/integration-renderer.d.ts +24 -143
  246. package/src/route-renderer/orchestration/integration-renderer.js +163 -402
  247. package/src/route-renderer/orchestration/integration-renderer.test-fixtures.d.ts +75 -0
  248. package/src/route-renderer/orchestration/integration-renderer.test-fixtures.js +177 -0
  249. package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.d.ts +10 -0
  250. package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.js +143 -0
  251. package/src/route-renderer/orchestration/ownership-graph/component-graph.d.ts +34 -0
  252. package/src/route-renderer/orchestration/ownership-graph/component-graph.js +96 -0
  253. package/src/route-renderer/orchestration/{ownership-validation.service.d.ts → ownership-graph/ownership-validation.service.d.ts} +7 -2
  254. package/src/route-renderer/orchestration/{ownership-validation.service.js → ownership-graph/ownership-validation.service.js} +30 -3
  255. package/src/route-renderer/orchestration/page-browser-graph/global-injector-assets.service.d.ts +7 -0
  256. package/src/route-renderer/orchestration/page-browser-graph/global-injector-assets.service.js +32 -0
  257. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-contribution.loader.d.ts +9 -0
  258. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-contribution.loader.js +7 -0
  259. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.d.ts +12 -0
  260. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.js +29 -0
  261. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.d.ts +106 -0
  262. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.js +436 -0
  263. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph.service.d.ts +31 -0
  264. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph.service.js +229 -0
  265. package/src/route-renderer/orchestration/{processed-asset-dedupe.d.ts → page-browser-graph/processed-asset-dedupe.d.ts} +1 -1
  266. package/src/route-renderer/orchestration/route-pipeline/integration-route-render-adapter.d.ts +31 -0
  267. package/src/route-renderer/orchestration/route-pipeline/integration-route-render-adapter.js +25 -0
  268. package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.d.ts +6 -0
  269. package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.js +27 -0
  270. package/src/route-renderer/orchestration/route-pipeline/robots-meta.contribution.d.ts +15 -0
  271. package/src/route-renderer/orchestration/route-pipeline/robots-meta.contribution.js +36 -0
  272. package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.d.ts +20 -0
  273. package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.js +24 -0
  274. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.builder.d.ts +25 -0
  275. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.builder.js +49 -0
  276. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.utils.d.ts +4 -0
  277. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.utils.js +33 -0
  278. package/src/route-renderer/orchestration/{route-render-orchestrator.d.ts → route-pipeline/route-render-orchestrator.d.ts} +13 -53
  279. package/src/route-renderer/orchestration/route-pipeline/route-render-orchestrator.js +162 -0
  280. package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
  281. package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
  282. package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
  283. package/src/route-renderer/page-loading/ecopages-virtual-imports.d.ts +6 -0
  284. package/src/route-renderer/page-loading/ecopages-virtual-imports.js +7 -2
  285. package/src/route-renderer/page-loading/module-declaration-aggregation.js +4 -0
  286. package/src/router/client/link-intent.d.ts +11 -21
  287. package/src/router/client/link-intent.js +10 -0
  288. package/src/router/client/link-intent.test.browser.js +12 -1
  289. package/src/router/client/link-navigation-policy.d.ts +45 -0
  290. package/src/router/client/link-navigation-policy.js +101 -0
  291. package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
  292. package/src/router/client/link-navigation-policy.test.browser.js +92 -0
  293. package/src/router/client/navigation-coordinator.d.ts +1 -1
  294. package/src/router/client/navigation-coordinator.js +12 -2
  295. package/src/services/assets/asset-processing-service/asset-dependency-keys.d.ts +13 -0
  296. package/src/services/assets/asset-processing-service/asset-dependency-keys.js +3 -0
  297. package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +6 -1
  298. package/src/services/assets/asset-processing-service/asset-processing.service.js +44 -5
  299. package/src/services/assets/asset-processing-service/assets.types.d.ts +1 -1
  300. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +2 -1
  301. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
  302. package/src/services/assets/asset-processing-service/browser-runtime-entry-resolution.d.ts +52 -0
  303. package/src/services/assets/asset-processing-service/browser-runtime-entry-resolution.js +78 -0
  304. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
  305. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +28 -13
  306. package/src/services/assets/asset-processing-service/finalize-processed-asset.d.ts +3 -0
  307. package/src/services/assets/asset-processing-service/finalize-processed-asset.js +7 -0
  308. package/src/services/assets/asset-processing-service/grouped-content-bundles.d.ts +2 -1
  309. package/src/services/assets/asset-processing-service/grouped-content-bundles.js +38 -12
  310. package/src/services/assets/asset-processing-service/index.d.ts +2 -0
  311. package/src/services/assets/asset-processing-service/index.js +2 -0
  312. package/src/services/assets/asset-processing-service/inline-content-script-body.d.ts +11 -0
  313. package/src/services/assets/asset-processing-service/inline-content-script-body.js +17 -0
  314. package/src/services/assets/asset-processing-service/materialize-content-script-asset.d.ts +9 -0
  315. package/src/services/assets/asset-processing-service/materialize-content-script-asset.js +18 -0
  316. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +0 -2
  317. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +2 -15
  318. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +8 -0
  319. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +73 -68
  320. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -1
  321. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +18 -15
  322. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
  323. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
  324. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
  325. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
  326. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
  327. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
  328. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
  329. package/src/services/assets/asset-processing-service/resolve-integration-plugin.d.ts +4 -0
  330. package/src/services/assets/asset-processing-service/resolve-integration-plugin.js +17 -0
  331. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.d.ts +0 -1
  332. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.js +5 -10
  333. package/src/services/assets/browser-bundle.service.d.ts +28 -30
  334. package/src/services/assets/browser-bundle.service.js +28 -19
  335. package/src/services/html/html-transformer.service.d.ts +1 -1
  336. package/src/services/html/html-transformer.service.js +5 -5
  337. package/src/services/invalidation/development-invalidation.service.d.ts +25 -2
  338. package/src/services/invalidation/development-invalidation.service.js +64 -11
  339. package/src/services/module-loading/README.md +49 -0
  340. package/src/services/module-loading/app-server-module-transpiler.service.d.ts +8 -0
  341. package/src/services/module-loading/app-server-module-transpiler.service.js +3 -21
  342. package/src/services/module-loading/page-module-import.service.d.ts +6 -2
  343. package/src/services/module-loading/page-module-import.service.js +110 -47
  344. package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
  345. package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
  346. package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
  347. package/src/services/module-loading/route-module-build-cache.js +38 -0
  348. package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
  349. package/src/services/module-loading/route-module-build-cache.store.js +207 -0
  350. package/src/services/module-loading/route-module-build-manifest.d.ts +54 -0
  351. package/src/services/module-loading/route-module-build-manifest.js +85 -0
  352. package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
  353. package/src/services/module-loading/route-module-dependency-hasher.js +122 -0
  354. package/src/services/module-loading/server-module-transpiler.service.d.ts +1 -1
  355. package/src/services/module-loading/server-module-transpiler.service.js +1 -1
  356. package/src/services/validation/schema-validation-service.d.ts +1 -4
  357. package/src/services/validation/schema-validation-service.js +12 -13
  358. package/src/services/validation/standard-schema.types.d.ts +9 -62
  359. package/src/services/validation/validate-standard-schema.d.ts +7 -0
  360. package/src/services/validation/validate-standard-schema.js +14 -0
  361. package/src/static-site-generator/README.md +41 -0
  362. package/src/static-site-generator/production-page-browser-graph-prebuild.d.ts +28 -0
  363. package/src/static-site-generator/production-page-browser-graph-prebuild.js +22 -0
  364. package/src/static-site-generator/sitemap-routes.d.ts +14 -0
  365. package/src/static-site-generator/sitemap-routes.js +31 -0
  366. package/src/static-site-generator/sitemap.d.ts +15 -0
  367. package/src/static-site-generator/sitemap.js +33 -0
  368. package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
  369. package/src/static-site-generator/static-build-invalidation.js +59 -0
  370. package/src/static-site-generator/static-export-context.d.ts +30 -0
  371. package/src/static-site-generator/static-export-context.js +0 -0
  372. package/src/static-site-generator/static-site-generator.d.ts +43 -25
  373. package/src/static-site-generator/static-site-generator.js +381 -106
  374. package/src/types/internal-types.d.ts +39 -13
  375. package/src/types/public-types.d.ts +289 -52
  376. package/src/utils/ecopages-route-info.d.ts +26 -0
  377. package/src/utils/ecopages-route-info.js +26 -0
  378. package/src/utils/html-escaping.d.ts +7 -0
  379. package/src/utils/html-escaping.js +5 -1
  380. package/src/utils/parse-cli-args.d.ts +2 -0
  381. package/src/utils/parse-cli-args.js +6 -0
  382. package/src/utils/path-pattern.d.ts +23 -0
  383. package/src/utils/path-pattern.js +27 -0
  384. package/src/utils/server-utils.module.d.ts +3 -2
  385. package/src/utils/server-utils.module.js +5 -6
  386. package/src/utils/static-file-extensions.d.ts +12 -0
  387. package/src/utils/static-file-extensions.js +48 -0
  388. package/src/watchers/project-watcher-ignore.d.ts +11 -0
  389. package/src/watchers/project-watcher-ignore.js +16 -0
  390. package/src/watchers/project-watcher.d.ts +29 -6
  391. package/src/watchers/project-watcher.js +146 -34
  392. package/src/watchers/project-watcher.test-helpers.js +5 -5
  393. package/src/adapters/shared/define-api-handler.d.ts +0 -25
  394. package/src/adapters/shared/define-api-handler.js +0 -15
  395. package/src/adapters/shared/hmr-entrypoint-registrar.js +0 -87
  396. package/src/adapters/shared/server-adapter.js +0 -436
  397. package/src/adapters/shared/server-static-builder.js +0 -162
  398. package/src/adapters/shared/shared-hmr-manager.d.ts +0 -59
  399. package/src/adapters/shared/shared-hmr-manager.js +0 -241
  400. package/src/build/build-manifest.d.ts +0 -33
  401. package/src/build/rolldown-dev-build-adapter.d.ts +0 -82
  402. package/src/build/rolldown-dev-build-adapter.js +0 -166
  403. package/src/build/runtime-build-executor.d.ts +0 -21
  404. package/src/build/runtime-build-executor.js +0 -19
  405. package/src/build/runtime-build-output-normalizer.d.ts +0 -3
  406. package/src/build/runtime-build-output-normalizer.js +0 -111
  407. package/src/hmr/hmr.postcss.test.e2e.js +0 -31
  408. package/src/hmr/hmr.test.e2e.js +0 -43
  409. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +0 -18
  410. package/src/route-renderer/orchestration/declared-ownership-graph.js +0 -34
  411. package/src/route-renderer/orchestration/ownership-planning.service.d.ts +0 -24
  412. package/src/route-renderer/orchestration/ownership-planning.service.js +0 -63
  413. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +0 -91
  414. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +0 -170
  415. package/src/route-renderer/orchestration/route-render-orchestrator.js +0 -577
  416. package/src/route-renderer/orchestration/template-serialization.d.ts +0 -38
  417. package/src/route-renderer/orchestration/template-serialization.js +0 -45
  418. /package/src/adapters/shared/{explicit-static-render-preparation.js → http/explicit-static-render-preparation.js} +0 -0
  419. /package/src/adapters/shared/{runtime-host.d.ts → runtime/runtime-host.d.ts} +0 -0
  420. /package/src/adapters/shared/{runtime-host.js → runtime/runtime-host.js} +0 -0
  421. /package/src/adapters/shared/{static-preview-host.js → runtime/static-preview-host.js} +0 -0
  422. /package/src/build/{browser-runtime-manifest.d.ts → browser/browser-runtime-manifest.d.ts} +0 -0
  423. /package/src/build/{browser-runtime-manifest.js → browser/browser-runtime-manifest.js} +0 -0
  424. /package/src/build/{browser-runtime-plugin-helpers.d.ts → browser/browser-runtime-plugin-helpers.d.ts} +0 -0
  425. /package/src/build/{browser-runtime-plugin-helpers.js → browser/browser-runtime-plugin-helpers.js} +0 -0
  426. /package/src/build/{build-types.js → contracts/build-contracts.js} +0 -0
  427. /package/src/build/{build-types.d.ts → contracts/build-types.d.ts} +0 -0
  428. /package/src/build/{server-side-css-shim-plugin.d.ts → rolldown/server-side-css-shim-plugin.d.ts} +0 -0
  429. /package/src/build/{server-side-css-shim-plugin.js → rolldown/server-side-css-shim-plugin.js} +0 -0
  430. /package/src/build/{serialized-build-executor.js → runtime/serialized-build-executor.js} +0 -0
  431. /package/src/{hmr/hmr.postcss.test.e2e.d.ts → client/navigation-scripts/navigation-scripts.test.browser.d.ts} +0 -0
  432. /package/src/{hmr/hmr.test.e2e.d.ts → client/scroll.test.browser.d.ts} +0 -0
  433. /package/src/route-renderer/orchestration/{processed-asset-dedupe.js → page-browser-graph/processed-asset-dedupe.js} +0 -0
@@ -0,0 +1,253 @@
1
+ import { mkdirSync, statSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { availableParallelism } from "node:os";
4
+ import { fileSystem } from "@ecopages/file-system";
5
+ const LOG_PREFIX = "[ecopages:startup-trace]";
6
+ function isStartupTraceEnabled() {
7
+ return process.env.ECOPAGES_STARTUP_TRACE === "true" || process.env.ECOPAGES_LOGGER_DEBUG === "true";
8
+ }
9
+ function wallMsSinceProcessStart() {
10
+ return Math.round(process.uptime() * 1e3);
11
+ }
12
+ function resolveTraceBuildParallelism() {
13
+ const fromEnv = process.env.ECOPAGES_DEV_BUILD_PARALLELISM ?? process.env.ECOPAGES_DEV_HMR_PARALLELISM;
14
+ if (fromEnv) {
15
+ return fromEnv;
16
+ }
17
+ return String(Math.max(1, availableParallelism()));
18
+ }
19
+ function writeTraceLine(message) {
20
+ process.stderr.write(`${LOG_PREFIX} ${message}
21
+ `);
22
+ }
23
+ function resolveStartupTraceJsonPath() {
24
+ const configured = process.env.ECOPAGES_STARTUP_TRACE_JSON?.trim();
25
+ return configured && configured.length > 0 ? configured : void 0;
26
+ }
27
+ class StartupTrace {
28
+ phaseNesting = /* @__PURE__ */ new Map();
29
+ phases = /* @__PURE__ */ new Map();
30
+ firstRequestPending = true;
31
+ firstRequestPath;
32
+ firstRequestBundleCount = 0;
33
+ firstRequestClientBytes = 0;
34
+ firstRequestGraphBuildCount = 0;
35
+ summaryEmitted = false;
36
+ firstPageBrowserGraphEmitted = false;
37
+ clientRequestCount = 0;
38
+ clientTransferredBytes = 0;
39
+ hmrConnected = false;
40
+ hydrationReadyMs = null;
41
+ isEnabled() {
42
+ return isStartupTraceEnabled();
43
+ }
44
+ markPhaseStart(phase) {
45
+ if (!isStartupTraceEnabled() || this.phases.has(phase)) {
46
+ return;
47
+ }
48
+ const nesting = this.phaseNesting.get(phase);
49
+ if (!nesting) {
50
+ this.phaseNesting.set(phase, { outerStart: performance.now(), depth: 1 });
51
+ return;
52
+ }
53
+ nesting.depth += 1;
54
+ }
55
+ markPhaseEnd(phase) {
56
+ if (!isStartupTraceEnabled() || this.phases.has(phase)) {
57
+ return;
58
+ }
59
+ const nesting = this.phaseNesting.get(phase);
60
+ if (!nesting) {
61
+ return;
62
+ }
63
+ nesting.depth -= 1;
64
+ if (nesting.depth > 0) {
65
+ return;
66
+ }
67
+ const durationMs = Math.round(performance.now() - nesting.outerStart);
68
+ const record = {
69
+ durationMs,
70
+ wallMs: wallMsSinceProcessStart()
71
+ };
72
+ this.phases.set(phase, record);
73
+ this.phaseNesting.delete(phase);
74
+ writeTraceLine(`phase=${phase} durationMs=${durationMs} wallMs=${record.wallMs}`);
75
+ this.writeJsonReport();
76
+ }
77
+ markConfigReady() {
78
+ if (!isStartupTraceEnabled() || this.phases.has("config-ready")) {
79
+ return;
80
+ }
81
+ const record = {
82
+ durationMs: 0,
83
+ wallMs: wallMsSinceProcessStart()
84
+ };
85
+ this.phases.set("config-ready", record);
86
+ writeTraceLine(`phase=config-ready wallMs=${record.wallMs} buildParallelism=${resolveTraceBuildParallelism()}`);
87
+ this.writeJsonReport();
88
+ }
89
+ markServerListening() {
90
+ this.markPhaseEnd("server-listen");
91
+ }
92
+ beginServerListen() {
93
+ this.markPhaseStart("server-listen");
94
+ }
95
+ markFirstByte() {
96
+ if (!isStartupTraceEnabled() || this.phases.has("first-byte")) {
97
+ return;
98
+ }
99
+ this.markPhaseEnd("first-byte");
100
+ }
101
+ beginFirstByte() {
102
+ this.markPhaseStart("first-byte");
103
+ }
104
+ markFirstPageBrowserGraphReady(graphBuildCount) {
105
+ if (!isStartupTraceEnabled() || this.firstPageBrowserGraphEmitted) {
106
+ return;
107
+ }
108
+ if (typeof graphBuildCount === "number") {
109
+ this.firstRequestGraphBuildCount = graphBuildCount;
110
+ }
111
+ this.firstPageBrowserGraphEmitted = true;
112
+ this.markPhaseEnd("first-page-browser-graph");
113
+ }
114
+ recordBrowserBundle(outputs) {
115
+ if (!isStartupTraceEnabled() || !this.firstRequestPending) {
116
+ return;
117
+ }
118
+ this.firstRequestBundleCount += 1;
119
+ for (const output of outputs) {
120
+ try {
121
+ if (fileSystem.exists(output.path)) {
122
+ this.firstRequestClientBytes += statSync(output.path).size;
123
+ }
124
+ } catch {
125
+ }
126
+ }
127
+ }
128
+ recordClientTransfer(requestCount, transferredBytes) {
129
+ if (!isStartupTraceEnabled()) {
130
+ return;
131
+ }
132
+ this.clientRequestCount = requestCount;
133
+ this.clientTransferredBytes = transferredBytes;
134
+ this.markPhaseEnd("client-transfer");
135
+ }
136
+ beginClientTransfer() {
137
+ this.markPhaseStart("client-transfer");
138
+ }
139
+ recordClientHydration(durationMs) {
140
+ if (!isStartupTraceEnabled()) {
141
+ return;
142
+ }
143
+ this.hydrationReadyMs = durationMs;
144
+ this.markPhaseEnd("client-hydration");
145
+ }
146
+ beginClientHydration() {
147
+ this.markPhaseStart("client-hydration");
148
+ }
149
+ recordHmrConnected() {
150
+ if (!isStartupTraceEnabled()) {
151
+ return;
152
+ }
153
+ this.hmrConnected = true;
154
+ }
155
+ async traceFirstRequest(request, handler) {
156
+ if (!isStartupTraceEnabled() || !this.firstRequestPending) {
157
+ return handler();
158
+ }
159
+ this.firstRequestPath = new URL(request.url).pathname;
160
+ this.markPhaseStart("first-page-browser-graph");
161
+ this.markPhaseStart("first-request-ssr");
162
+ try {
163
+ return await handler();
164
+ } finally {
165
+ this.markPhaseEnd("first-request-ssr");
166
+ this.emitFirstRequestSummary();
167
+ this.firstRequestPending = false;
168
+ this.writeJsonReport();
169
+ }
170
+ }
171
+ emitFirstRequestSummary() {
172
+ if (!isStartupTraceEnabled() || this.summaryEmitted) {
173
+ return;
174
+ }
175
+ this.summaryEmitted = true;
176
+ writeTraceLine(
177
+ [
178
+ "summary",
179
+ `path=${this.firstRequestPath ?? "unknown"}`,
180
+ `bundleCount=${this.firstRequestBundleCount}`,
181
+ `clientBundleBytes=${this.firstRequestClientBytes}`,
182
+ `graphBuildCount=${this.firstRequestGraphBuildCount}`,
183
+ `wallMs=${wallMsSinceProcessStart()}`
184
+ ].join(" ")
185
+ );
186
+ }
187
+ writeJsonReport() {
188
+ const outputPath = resolveStartupTraceJsonPath();
189
+ if (!outputPath) {
190
+ return;
191
+ }
192
+ const report = this.createReport();
193
+ mkdirSync(path.dirname(outputPath), { recursive: true });
194
+ writeFileSync(outputPath, JSON.stringify(report, null, 2), "utf-8");
195
+ }
196
+ createReport() {
197
+ const phases = {};
198
+ for (const [phase, record] of this.phases) {
199
+ phases[phase] = record;
200
+ }
201
+ return {
202
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
203
+ runtime: typeof Bun !== "undefined" ? `bun ${Bun.version}` : `node ${process.version}`,
204
+ platform: process.platform,
205
+ phases,
206
+ firstRequest: this.firstRequestPath ? {
207
+ path: this.firstRequestPath,
208
+ bundleCount: this.firstRequestBundleCount,
209
+ clientBundleBytes: this.firstRequestClientBytes,
210
+ graphBuildCount: this.firstRequestGraphBuildCount,
211
+ wallMs: wallMsSinceProcessStart()
212
+ } : void 0,
213
+ client: this.clientRequestCount > 0 || this.hydrationReadyMs !== null ? {
214
+ requestCount: this.clientRequestCount,
215
+ transferredBytes: this.clientTransferredBytes,
216
+ hmrConnected: this.hmrConnected,
217
+ hydrationReadyMs: this.hydrationReadyMs
218
+ } : void 0
219
+ };
220
+ }
221
+ /** Resets mutable trace state for unit tests. */
222
+ resetForTests() {
223
+ this.phaseNesting.clear();
224
+ this.phases.clear();
225
+ this.firstRequestPending = true;
226
+ this.firstRequestPath = void 0;
227
+ this.firstRequestBundleCount = 0;
228
+ this.firstRequestClientBytes = 0;
229
+ this.firstRequestGraphBuildCount = 0;
230
+ this.summaryEmitted = false;
231
+ this.firstPageBrowserGraphEmitted = false;
232
+ this.clientRequestCount = 0;
233
+ this.clientTransferredBytes = 0;
234
+ this.hmrConnected = false;
235
+ this.hydrationReadyMs = null;
236
+ }
237
+ /**
238
+ * Resets only the first-request bundle counters.
239
+ *
240
+ * @remarks
241
+ * Used by tests that need to re-measure first-request browser bundle work
242
+ * without clearing earlier startup phase records.
243
+ */
244
+ resetFirstRequestCounters() {
245
+ this.firstRequestBundleCount = 0;
246
+ this.firstRequestClientBytes = 0;
247
+ this.firstRequestGraphBuildCount = 0;
248
+ }
249
+ }
250
+ const startupTrace = new StartupTrace();
251
+ export {
252
+ startupTrace
253
+ };
package/src/eco/README.md CHANGED
@@ -279,6 +279,17 @@ export default eco.page({
279
279
  });
280
280
  ```
281
281
 
282
+ **Nested layouts (outer → inner):**
283
+
284
+ ```tsx
285
+ export default eco.page({
286
+ layout: [MarketingShell, DocsShell],
287
+ render: () => <h1>Hello</h1>,
288
+ });
289
+ ```
290
+
291
+ A single layout remains equivalent to a one-element array. Normalization stores the stack on `config.layouts` and `config.layoutEntries` at factory time.
292
+
282
293
  ### `eco.component()`
283
294
 
284
295
  Define a reusable component with dependencies.
@@ -0,0 +1,14 @@
1
+ import type { EcoDeclaredComponent } from '../types/public-types.js';
2
+ export { getUndeclaredComponentDependencyMessage } from '../errors/undeclared-component-dependency-error.js';
3
+ /**
4
+ * @remarks
5
+ * Declared components are produced by `eco.component()`, `eco.layout()`, and
6
+ * `eco.html()` after the component-meta plugin injects `config.__eco`.
7
+ */
8
+ export declare function isEcoDeclaredComponent(component: unknown): component is EcoDeclaredComponent;
9
+ /**
10
+ * @throws {UndeclaredComponentDependencyError} When the value lacks `config.__eco`.
11
+ */
12
+ export declare function assertEcoDeclaredComponent(component: unknown, context?: {
13
+ parentComponentFile?: string;
14
+ }): asserts component is EcoDeclaredComponent;
@@ -0,0 +1,16 @@
1
+ import { UndeclaredComponentDependencyError } from "../errors/undeclared-component-dependency-error.js";
2
+ import { getUndeclaredComponentDependencyMessage } from "../errors/undeclared-component-dependency-error.js";
3
+ function isEcoDeclaredComponent(component) {
4
+ return typeof component === "function" && typeof component.config?.__eco?.file === "string" && typeof component.config?.__eco?.integration === "string";
5
+ }
6
+ function assertEcoDeclaredComponent(component, context = {}) {
7
+ if (isEcoDeclaredComponent(component)) {
8
+ return;
9
+ }
10
+ throw new UndeclaredComponentDependencyError(context.parentComponentFile);
11
+ }
12
+ export {
13
+ assertEcoDeclaredComponent,
14
+ getUndeclaredComponentDependencyMessage,
15
+ isEcoDeclaredComponent
16
+ };
@@ -1,3 +1,4 @@
1
+ import { applyPageLayoutConfig, mergeLayoutDependencies, normalizePageLayouts } from "./page-layout-normalization.js";
1
2
  function createComponentFactory(options) {
2
3
  const component2 = ((props) => options.render(props));
3
4
  component2.config = {
@@ -32,17 +33,15 @@ function page(options) {
32
33
  requires,
33
34
  middleware
34
35
  } = options;
36
+ const layoutEntries = normalizePageLayouts(pageLayout);
35
37
  const pageComponent = createComponentFactory({
36
38
  __eco: options.__eco,
37
39
  integration: options.integration,
38
- dependencies: pageLayout ? {
39
- ...dependencies,
40
- components: [...dependencies?.components ?? [], pageLayout]
41
- } : dependencies,
40
+ dependencies: mergeLayoutDependencies(dependencies, layoutEntries),
42
41
  render
43
42
  });
44
- if (pageLayout && pageComponent.config) {
45
- pageComponent.config.layout = pageLayout;
43
+ if (pageComponent.config) {
44
+ applyPageLayoutConfig(pageComponent.config, layoutEntries);
46
45
  }
47
46
  if (staticPaths2) {
48
47
  pageComponent.staticPaths = staticPaths2;
package/src/eco/eco.js CHANGED
@@ -2,8 +2,9 @@ import {
2
2
  finalizeComponentRender,
3
3
  getComponentRenderContext,
4
4
  interceptForeignChild
5
- } from "../route-renderer/orchestration/component-render-context.js";
6
- import { isThenable } from "../route-renderer/orchestration/render-output.utils.js";
5
+ } from "../route-renderer/orchestration/foreign-child/component-render-context.js";
6
+ import { isThenable } from "../route-renderer/orchestration/foreign-child/foreign-child-output.utils.js";
7
+ import { applyPageLayoutConfig, mergeLayoutDependencies, normalizePageLayouts } from "./page-layout-normalization.js";
7
8
  function createComponentFactory(options) {
8
9
  const integrationName = options.integration ?? options.__eco?.integration;
9
10
  const comp = ((props) => {
@@ -74,18 +75,16 @@ function layout(options) {
74
75
  }
75
76
  function page(options) {
76
77
  const { layout: layout2, dependencies, render, staticPaths: staticPaths2, staticProps: staticProps2, metadata: metadata2, cache, requires, middleware } = options;
78
+ const layoutEntries = normalizePageLayouts(layout2);
77
79
  const componentOptions = {
78
80
  __eco: options.__eco,
79
81
  integration: options.integration,
80
- dependencies: layout2 ? {
81
- ...dependencies,
82
- components: [...dependencies?.components || [], layout2]
83
- } : dependencies,
82
+ dependencies: mergeLayoutDependencies(dependencies, layoutEntries),
84
83
  render
85
84
  };
86
85
  const pageComponent = createComponentFactory(componentOptions);
87
- if (layout2 && pageComponent.config) {
88
- pageComponent.config.layout = layout2;
86
+ if (pageComponent.config) {
87
+ applyPageLayoutConfig(pageComponent.config, layoutEntries);
89
88
  }
90
89
  if (staticPaths2) pageComponent.staticPaths = staticPaths2;
91
90
  if (staticProps2) pageComponent.staticProps = staticProps2;
@@ -2,7 +2,7 @@
2
2
  * Type definitions for the eco namespace API
3
3
  * @module
4
4
  */
5
- import type { DependencyLazyTrigger, EcoComponent, EcoComponentDependencies, EcoHtmlComponent, EcoInjectedMeta, EcoLayoutComponent, EcoPageLayoutComponent, EcoPagesElement, FileRouteMiddleware, GetMetadata, GetStaticPaths, GetStaticProps, HtmlTemplateProps, LayoutProps, RequestLocals, RequestPageContext } from '../types/public-types.js';
5
+ import type { DependencyLazyTrigger, EcoComponent, EcoComponentDependencies, EcoHtmlComponent, EcoInjectedMeta, EcoLayoutComponent, EcoPageLayouts, EcoPagesElement, FileRouteMiddleware, GetMetadata, GetStaticPaths, GetStaticProps, HtmlTemplateProps, LayoutProps, RequestLocals, RequestPageContext } from '../types/public-types.js';
6
6
  import type { CacheStrategy } from '../services/cache/cache.types.js';
7
7
  /**
8
8
  * Extracts the props type from one eco component.
@@ -72,7 +72,18 @@ export interface ComponentOptions<P, E = EcoPagesElement> {
72
72
  render: (props: P) => E | Promise<E>;
73
73
  }
74
74
  export type HtmlOptions<E = EcoPagesElement> = ComponentOptions<HtmlTemplateProps, E>;
75
- export type LayoutOptions<E = EcoPagesElement> = ComponentOptions<LayoutProps<E>, E>;
75
+ export type LayoutOptions<E = EcoPagesElement> = ComponentOptions<LayoutProps<E>, E> & {
76
+ /**
77
+ * Marks this layout as mounting shared client runtime state such as React context
78
+ * providers or query clients.
79
+ *
80
+ * @remarks
81
+ * When any layout in the app sets this flag, only flagged layouts participate in
82
+ * React auto-vendoring discovery. This keeps shell-only layouts out of provider
83
+ * scans while persisted SPA navigation stays on one shared vendor instance.
84
+ */
85
+ runtimeProvider?: boolean;
86
+ };
76
87
  /**
77
88
  * Base options shared by all page variants
78
89
  */
@@ -81,7 +92,7 @@ export interface PageOptionsBase<T, E = EcoPagesElement> {
81
92
  __eco?: EcoInjectedMeta;
82
93
  integration?: string;
83
94
  dependencies?: EcoComponentDependencies;
84
- layout?: EcoPageLayoutComponent<E>;
95
+ layout?: EcoPageLayouts<E>;
85
96
  /**
86
97
  * Define static paths for dynamic routes (e.g., [slug].tsx).
87
98
  * Returns all possible paths that should be pre-rendered at build time.
@@ -1 +1 @@
1
- export { addTriggerAttribute, isThenable, wrapWithScriptsInjector, } from '../route-renderer/orchestration/render-output.utils.js';
1
+ export { addTriggerAttribute, isThenable, wrapWithScriptsInjector, } from '../route-renderer/orchestration/foreign-child/foreign-child-output.utils.js';
@@ -2,7 +2,7 @@ import {
2
2
  addTriggerAttribute,
3
3
  isThenable,
4
4
  wrapWithScriptsInjector
5
- } from "../route-renderer/orchestration/render-output.utils.js";
5
+ } from "../route-renderer/orchestration/foreign-child/foreign-child-output.utils.js";
6
6
  export {
7
7
  addTriggerAttribute,
8
8
  isThenable,
@@ -0,0 +1,21 @@
1
+ import type { EcoComponentConfig, EcoComponentDependencies, EcoPageLayoutEntry, EcoPageLayouts } from '../types/public-types.js';
2
+ /**
3
+ * Normalizes `layout` page options to an outer→inner stack of layout entries.
4
+ */
5
+ export declare function normalizePageLayouts<E>(layout?: EcoPageLayouts<E>): EcoPageLayoutEntry<E>[];
6
+ /**
7
+ * Merges layout components into `dependencies.components` without duplicates.
8
+ */
9
+ export declare function mergeLayoutDependencies(dependencies: EcoComponentDependencies | undefined, layoutEntries: EcoPageLayoutEntry[]): EcoComponentDependencies | undefined;
10
+ /**
11
+ * Writes normalized layout metadata onto a page `config`.
12
+ */
13
+ export declare function applyPageLayoutConfig(pageConfig: EcoComponentConfig, layoutEntries: EcoPageLayoutEntry[]): void;
14
+ /**
15
+ * Migrates MDX-exported `config.layout` values onto normalized layout metadata.
16
+ *
17
+ * @remarks
18
+ * `eco.page({ layout })` already normalizes at factory time. MDX modules that
19
+ * export `config.layout` directly still need this import-time migration.
20
+ */
21
+ export declare function ensurePageConfigLayouts(config: EcoComponentConfig | undefined): EcoComponentConfig | undefined;
@@ -0,0 +1,59 @@
1
+ function isLayoutSpecObject(spec) {
2
+ return typeof spec === "object" && spec !== null && "component" in spec;
3
+ }
4
+ function normalizePageLayouts(layout) {
5
+ if (!layout) {
6
+ return [];
7
+ }
8
+ const specs = Array.isArray(layout) ? layout : [layout];
9
+ return specs.map((spec) => {
10
+ if (isLayoutSpecObject(spec)) {
11
+ return {
12
+ component: spec.component,
13
+ props: spec.props
14
+ };
15
+ }
16
+ return {
17
+ component: spec
18
+ };
19
+ });
20
+ }
21
+ function mergeLayoutDependencies(dependencies, layoutEntries) {
22
+ if (layoutEntries.length === 0) {
23
+ return dependencies;
24
+ }
25
+ const mergedComponents = [...dependencies?.components ?? []];
26
+ for (const entry of layoutEntries) {
27
+ if (!mergedComponents.includes(entry.component)) {
28
+ mergedComponents.push(entry.component);
29
+ }
30
+ }
31
+ return {
32
+ ...dependencies,
33
+ components: mergedComponents
34
+ };
35
+ }
36
+ function applyPageLayoutConfig(pageConfig, layoutEntries) {
37
+ if (layoutEntries.length === 0) {
38
+ return;
39
+ }
40
+ pageConfig.layouts = layoutEntries.map((entry) => entry.component);
41
+ pageConfig.layoutEntries = layoutEntries;
42
+ }
43
+ function ensurePageConfigLayouts(config) {
44
+ if (!config || config.layouts && config.layouts.length > 0) {
45
+ return config;
46
+ }
47
+ const legacyLayout = config.layout;
48
+ if (!legacyLayout) {
49
+ return config;
50
+ }
51
+ applyPageLayoutConfig(config, normalizePageLayouts(legacyLayout));
52
+ return config;
53
+ }
54
+ export {
55
+ applyPageLayoutConfig,
56
+ ensurePageConfigLayouts,
57
+ mergeLayoutDependencies,
58
+ normalizePageLayouts
59
+ };
package/src/env.d.ts CHANGED
@@ -3,6 +3,8 @@ interface EcopagesEnv {
3
3
  ECOPAGES_HOSTNAME: string;
4
4
  ECOPAGES_PORT: string;
5
5
  ECOPAGES_LOGGER_DEBUG: 'true' | 'false';
6
+ /** When `true`, emits startup phase timings to stderr. Also enabled when `ECOPAGES_LOGGER_DEBUG=true`. */
7
+ ECOPAGES_STARTUP_TRACE?: 'true' | 'false';
6
8
  }
7
9
 
8
10
  declare global {
@@ -1,3 +1,4 @@
1
1
  export { HttpError } from './http-error.js';
2
2
  export type { HttpErrorDetails, HttpErrorJson } from './http-error.js';
3
3
  export { LocalsAccessError } from './locals-access-error.js';
4
+ export { UndeclaredComponentDependencyError, getUndeclaredComponentDependencyMessage, } from './undeclared-component-dependency-error.js';
@@ -1,6 +1,12 @@
1
1
  import { HttpError } from "./http-error.js";
2
2
  import { LocalsAccessError } from "./locals-access-error.js";
3
+ import {
4
+ UndeclaredComponentDependencyError,
5
+ getUndeclaredComponentDependencyMessage
6
+ } from "./undeclared-component-dependency-error.js";
3
7
  export {
4
8
  HttpError,
5
- LocalsAccessError
9
+ LocalsAccessError,
10
+ UndeclaredComponentDependencyError,
11
+ getUndeclaredComponentDependencyMessage
6
12
  };
@@ -0,0 +1,11 @@
1
+ export declare function getUndeclaredComponentDependencyMessage(parentComponentFile?: string): string;
2
+ /**
3
+ * Thrown when `dependencies.components` contains a plain function or component
4
+ * without plugin-injected `config.__eco` metadata.
5
+ */
6
+ export declare class UndeclaredComponentDependencyError extends Error {
7
+ name: string;
8
+ /** Parent component file path when the invalid entry was declared. */
9
+ readonly parentComponentFile?: string;
10
+ constructor(parentComponentFile?: string);
11
+ }
@@ -0,0 +1,17 @@
1
+ function getUndeclaredComponentDependencyMessage(parentComponentFile) {
2
+ const parentHint = parentComponentFile ? ` (declared by ${parentComponentFile})` : "";
3
+ return `[ecopages] dependencies.components entries must be eco.component(), eco.layout(), or eco.html() components with __eco metadata${parentHint}. Plain functions and untyped components are not valid dependency entries.`;
4
+ }
5
+ class UndeclaredComponentDependencyError extends Error {
6
+ name = "UndeclaredComponentDependencyError";
7
+ /** Parent component file path when the invalid entry was declared. */
8
+ parentComponentFile;
9
+ constructor(parentComponentFile) {
10
+ super(getUndeclaredComponentDependencyMessage(parentComponentFile));
11
+ this.parentComponentFile = parentComponentFile;
12
+ }
13
+ }
14
+ export {
15
+ UndeclaredComponentDependencyError,
16
+ getUndeclaredComponentDependencyMessage
17
+ };
@@ -12,7 +12,7 @@ import { getEcoNavigationRuntime } from "../../router/client/navigation-coordina
12
12
  socket.addEventListener("message", async (event) => {
13
13
  try {
14
14
  const payload = JSON.parse(event.data);
15
- handleMessage(payload);
15
+ await handleMessage(payload);
16
16
  } catch (e) {
17
17
  console.error("[ecopages] Invalid HMR message:", e);
18
18
  }
@@ -29,12 +29,15 @@ import { getEcoNavigationRuntime } from "../../router/client/navigation-coordina
29
29
  switch (payload.type) {
30
30
  case "reload":
31
31
  await waitForNavigationToSettle(navigationRuntime);
32
+ if (window.__ECOPAGES_HOST_OWNS_RELOAD__) {
33
+ break;
34
+ }
32
35
  location.reload();
33
36
  break;
34
37
  case "layout-update": {
35
38
  await waitForNavigationToSettle(navigationRuntime);
36
39
  if (await navigationRuntime.reloadCurrentPage({ clearCache: true, moduleUrl: getActiveHmrModuleUrl() })) {
37
- } else {
40
+ } else if (!window.__ECOPAGES_HOST_OWNS_RELOAD__) {
38
41
  location.reload();
39
42
  }
40
43
  break;
@@ -65,7 +68,7 @@ import { getEcoNavigationRuntime } from "../../router/client/navigation-coordina
65
68
  return;
66
69
  }
67
70
  await import(url);
68
- if (await navigationRuntime.reloadCurrentPage({ clearCache: false })) {
71
+ if (await navigationRuntime.reloadCurrentPage({ clearCache: false, moduleUrl: url })) {
69
72
  }
70
73
  } catch (e) {
71
74
  console.error("[ecopages] Failed to apply HMR update:", e);
@@ -85,7 +88,7 @@ import { getEcoNavigationRuntime } from "../../router/client/navigation-coordina
85
88
  }
86
89
  await new Promise((resolve) => {
87
90
  const startedAt = performance.now();
88
- const timeoutMs = 2e3;
91
+ const timeoutMs = 5e3;
89
92
  const poll = () => {
90
93
  if (!navigationRuntime.hasPendingNavigationTransaction()) {
91
94
  resolve();
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Verified HMR entrypoint artifact produced by registration.
3
+ */
4
+ export interface ResolvedHmrEntrypoint {
5
+ sourcePath: string;
6
+ outputPath: string;
7
+ outputUrl: string;
8
+ }
9
+ /**
10
+ * Returns whether a source path is a registered client script HMR entrypoint.
11
+ */
12
+ export declare function isRegisteredScriptEntrypoint(registered: ReadonlyMap<string, unknown>, filePath: string): boolean;
13
+ /**
14
+ * Returns whether a registered script entrypoint is browser-only and must not be
15
+ * server-imported during HMR invalidation.
16
+ *
17
+ * @remarks
18
+ * Declared `*.script.ts` modules run only in the browser bundle. Re-importing them
19
+ * on the server during `prepareRegisteredScriptChange()` executes DOM globals and
20
+ * aborts the watcher before the client artifact rebuilds. Radiant `*.script.tsx`
21
+ * entrypoints are server-rendered and remain on the invalidation path.
22
+ */
23
+ export declare function isBrowserOnlyRegisteredScriptEntrypoint(filePath: string): boolean;
24
+ export declare function encodeHmrDynamicSegments(filepath: string): string;
25
+ /**
26
+ * Resolves the on-disk and browser URL targets for one HMR script entrypoint.
27
+ */
28
+ export declare function resolveHmrEntrypointOutputPaths(srcDir: string, distDir: string, entrypointPath: string): {
29
+ outputPath: string;
30
+ outputUrl: string;
31
+ };
32
+ /**
33
+ * @remarks
34
+ * Rebuilds must delete the previous artifact so browser-hmr does not reuse a
35
+ * stale bundle when the source file changed.
36
+ */
37
+ export declare function removeStaleHmrEntrypointOutput(outputPath: string, scope: string): void;
38
+ /**
39
+ * @remarks
40
+ * Guards against broadcasting reload/update before the bundler has flushed a
41
+ * fresher artifact than the edited source file.
42
+ */
43
+ export declare function isHmrOutputFresh(outputPath: string, sourcePath: string): boolean;
44
+ /**
45
+ * @remarks
46
+ * Missing output is treated as a benign rebuild race. This helper isolates the
47
+ * post-build case where a bundle exists but is still older than its source.
48
+ */
49
+ export declare function isHmrOutputOlderThanSource(outputPath: string, sourcePath: string): boolean;