@ecopages/core 0.2.0-beta.2 → 0.2.0-beta.21

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 (273) hide show
  1. package/README.md +1 -1
  2. package/package.json +163 -3
  3. package/src/adapters/abstract/application-adapter.d.ts +104 -5
  4. package/src/adapters/abstract/application-adapter.js +125 -1
  5. package/src/adapters/abstract/server-adapter.d.ts +6 -2
  6. package/src/adapters/abstract/ws-pattern-matcher.d.ts +60 -0
  7. package/src/adapters/abstract/ws-pattern-matcher.js +61 -0
  8. package/src/adapters/bun/client-bridge.d.ts +1 -0
  9. package/src/adapters/bun/client-bridge.js +3 -0
  10. package/src/adapters/bun/create-app.d.ts +6 -4
  11. package/src/adapters/bun/create-app.js +65 -43
  12. package/src/adapters/bun/server-adapter.d.ts +90 -22
  13. package/src/adapters/bun/server-adapter.js +266 -84
  14. package/src/adapters/bun/static-preview-host.js +25 -20
  15. package/src/adapters/create-app.d.ts +13 -11
  16. package/src/adapters/create-app.js +2 -51
  17. package/src/adapters/index.d.ts +1 -1
  18. package/src/adapters/index.js +1 -2
  19. package/src/adapters/node/create-app.d.ts +5 -1
  20. package/src/adapters/node/create-app.js +51 -12
  21. package/src/adapters/node/node-client-bridge.d.ts +1 -0
  22. package/src/adapters/node/node-client-bridge.js +3 -0
  23. package/src/adapters/node/server-adapter-dependencies.js +4 -0
  24. package/src/adapters/node/server-adapter.d.ts +62 -20
  25. package/src/adapters/node/server-adapter.js +160 -131
  26. package/src/adapters/node/static-content-server.d.ts +1 -0
  27. package/src/adapters/node/static-content-server.js +10 -2
  28. package/src/adapters/node/static-preview-host.js +27 -12
  29. package/src/adapters/shared/bun-user-websocket-lifecycle.d.ts +22 -0
  30. package/src/adapters/shared/bun-user-websocket-lifecycle.js +96 -0
  31. package/src/adapters/shared/copy-runtime-public-dir.d.ts +6 -0
  32. package/src/adapters/shared/copy-runtime-public-dir.js +24 -0
  33. package/src/adapters/shared/fs-server-response-matcher.d.ts +2 -0
  34. package/src/adapters/shared/fs-server-response-matcher.js +40 -18
  35. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +21 -30
  36. package/src/adapters/shared/hmr-entrypoint-registrar.js +49 -54
  37. package/src/adapters/shared/hmr-html-response.d.ts +1 -1
  38. package/src/adapters/shared/hmr-html-response.js +4 -1
  39. package/src/adapters/shared/node-http-websocket-upgrades.d.ts +21 -0
  40. package/src/adapters/shared/node-http-websocket-upgrades.js +100 -0
  41. package/src/adapters/shared/port-manager.d.ts +116 -0
  42. package/src/adapters/shared/port-manager.js +196 -0
  43. package/src/adapters/shared/runtime-app-bootstrap.d.ts +2 -1
  44. package/src/adapters/shared/runtime-app-bootstrap.js +3 -6
  45. package/src/adapters/shared/runtime-server-lifecycle.d.ts +46 -0
  46. package/src/adapters/shared/runtime-server-lifecycle.js +50 -0
  47. package/src/adapters/shared/server-adapter.d.ts +2 -1
  48. package/src/adapters/shared/server-adapter.js +13 -6
  49. package/src/adapters/shared/server-route-handler.d.ts +4 -1
  50. package/src/adapters/shared/server-route-handler.js +5 -2
  51. package/src/adapters/shared/server-static-builder.d.ts +23 -32
  52. package/src/adapters/shared/server-static-builder.js +100 -73
  53. package/src/adapters/shared/shared-hmr-manager.d.ts +45 -11
  54. package/src/adapters/shared/shared-hmr-manager.js +204 -58
  55. package/src/adapters/shared/static-preview-host.d.ts +5 -0
  56. package/src/adapters/shared/websocket-lifecycle.d.ts +24 -0
  57. package/src/adapters/shared/websocket-lifecycle.js +55 -0
  58. package/src/build/README.md +77 -14
  59. package/src/build/app-build-manifest-runtime.d.ts +9 -0
  60. package/src/build/app-build-manifest-runtime.js +87 -0
  61. package/src/build/build-adapter.d.ts +17 -319
  62. package/src/build/build-adapter.js +28 -94
  63. package/src/build/build-contracts.d.ts +97 -0
  64. package/src/build/build-contracts.js +0 -0
  65. package/src/build/build-input-fingerprint.d.ts +28 -0
  66. package/src/build/build-input-fingerprint.js +31 -0
  67. package/src/build/build-profile-options.d.ts +7 -0
  68. package/src/build/build-profile-options.js +37 -0
  69. package/src/build/build-runtime.d.ts +24 -0
  70. package/src/build/build-runtime.js +65 -0
  71. package/src/build/deduping-build-executor.d.ts +28 -0
  72. package/src/build/deduping-build-executor.js +56 -0
  73. package/src/build/jsx-ownership-plugins.d.ts +24 -0
  74. package/src/build/jsx-ownership-plugins.js +41 -0
  75. package/src/build/pages-unified-graph-build.d.ts +31 -0
  76. package/src/build/pages-unified-graph-build.js +206 -0
  77. package/src/build/parallel-build-executor.d.ts +21 -0
  78. package/src/build/parallel-build-executor.js +52 -0
  79. package/src/build/production-build-cache.d.ts +20 -0
  80. package/src/build/production-build-cache.js +63 -0
  81. package/src/build/rolldown-adapter-helpers.d.ts +3 -6
  82. package/src/build/rolldown-adapter-helpers.js +71 -6
  83. package/src/build/rolldown-build-adapter.d.ts +2 -6
  84. package/src/build/rolldown-build-adapter.js +3 -3
  85. package/src/build/rolldown-build-invocation-metrics.d.ts +12 -0
  86. package/src/build/rolldown-build-invocation-metrics.js +43 -0
  87. package/src/build/rolldown-plugin-bridge.d.ts +15 -1
  88. package/src/build/rolldown-plugin-bridge.js +20 -5
  89. package/src/build/rolldown-source-transform-pass.d.ts +15 -0
  90. package/src/build/rolldown-source-transform-pass.js +58 -0
  91. package/src/build/runtime-build-executor.d.ts +8 -15
  92. package/src/build/runtime-build-executor.js +12 -15
  93. package/src/build/runtime-build-output-normalizer.d.ts +7 -0
  94. package/src/build/runtime-build-output-normalizer.js +94 -2
  95. package/src/build/server-entry-build-cache.d.ts +44 -0
  96. package/src/build/server-entry-build-cache.js +161 -0
  97. package/src/client/navigation-scripts/classification.d.ts +16 -0
  98. package/src/client/navigation-scripts/classification.js +41 -0
  99. package/src/client/navigation-scripts/index.d.ts +3 -0
  100. package/src/client/navigation-scripts/index.js +23 -0
  101. package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
  102. package/src/client/navigation-scripts/registry.d.ts +11 -0
  103. package/src/client/navigation-scripts/registry.js +12 -0
  104. package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
  105. package/src/client/navigation-scripts/rerun-queue.js +73 -0
  106. package/src/client/scroll.d.ts +17 -0
  107. package/src/client/scroll.js +25 -0
  108. package/src/client/scroll.test.browser.js +37 -0
  109. package/src/client/view-transitions.d.ts +16 -0
  110. package/src/client/view-transitions.js +63 -0
  111. package/src/config/config-builder.d.ts +12 -7
  112. package/src/config/config-builder.js +12 -9
  113. package/src/dev/client-bridge-registry.d.ts +5 -0
  114. package/src/dev/client-bridge-registry.js +15 -0
  115. package/src/dev/dev-client-ownership.d.ts +7 -0
  116. package/src/dev/dev-client-ownership.js +6 -0
  117. package/src/dev/hmr-manager-registry.d.ts +8 -0
  118. package/src/dev/hmr-manager-registry.js +15 -0
  119. package/src/dev/host-runtime.d.ts +3 -0
  120. package/src/dev/host-runtime.js +7 -0
  121. package/src/dev/runtime-server-started-message.d.ts +2 -0
  122. package/src/dev/runtime-server-started-message.js +6 -0
  123. package/src/eco/README.md +11 -0
  124. package/src/eco/eco-declared-component.d.ts +14 -0
  125. package/src/eco/eco-declared-component.js +16 -0
  126. package/src/eco/eco.browser.js +5 -6
  127. package/src/eco/eco.js +5 -6
  128. package/src/eco/eco.types.d.ts +2 -2
  129. package/src/eco/page-layout-normalization.d.ts +21 -0
  130. package/src/eco/page-layout-normalization.js +59 -0
  131. package/src/errors/index.d.ts +1 -0
  132. package/src/errors/index.js +7 -1
  133. package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
  134. package/src/errors/undeclared-component-dependency-error.js +17 -0
  135. package/src/hmr/client/hmr-runtime.js +5 -2
  136. package/src/hmr/hmr-entrypoint-output.d.ts +43 -0
  137. package/src/hmr/hmr-entrypoint-output.js +53 -0
  138. package/src/hmr/hmr-strategy.d.ts +15 -0
  139. package/src/hmr/hmr-strategy.js +19 -0
  140. package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -5
  141. package/src/hmr/strategies/js-hmr-strategy.js +67 -19
  142. package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
  143. package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
  144. package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
  145. package/src/integrations/ghtml/ghtml-renderer.js +2 -51
  146. package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
  147. package/src/integrations/ghtml/ghtml.plugin.js +7 -14
  148. package/src/plugins/define-integration.d.ts +26 -0
  149. package/src/plugins/define-integration.js +19 -0
  150. package/src/plugins/eco-component-meta-plugin.js +5 -8
  151. package/src/plugins/foreign-jsx-override-plugin.js +4 -6
  152. package/src/plugins/integration-plugin.d.ts +19 -9
  153. package/src/plugins/integration-plugin.js +7 -4
  154. package/src/plugins/jsx-import-source.utils.d.ts +8 -0
  155. package/src/plugins/jsx-import-source.utils.js +26 -0
  156. package/src/plugins/processor.d.ts +19 -4
  157. package/src/plugins/processor.js +22 -4
  158. package/src/plugins/source-transform.d.ts +31 -0
  159. package/src/plugins/source-transform.js +23 -1
  160. package/src/route-renderer/GRAPH.md +8 -8
  161. package/src/route-renderer/README.md +30 -28
  162. package/src/route-renderer/orchestration/component-graph-collectors.d.ts +10 -0
  163. package/src/route-renderer/orchestration/component-graph-collectors.js +143 -0
  164. package/src/route-renderer/orchestration/component-graph.d.ts +36 -0
  165. package/src/route-renderer/orchestration/component-graph.js +98 -0
  166. package/src/route-renderer/orchestration/component-render-context.d.ts +3 -10
  167. package/src/route-renderer/orchestration/component-render-context.js +3 -1
  168. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +1 -18
  169. package/src/route-renderer/orchestration/declared-ownership-graph.js +5 -31
  170. package/src/route-renderer/orchestration/document-shell-render.service.d.ts +90 -0
  171. package/src/route-renderer/orchestration/document-shell-render.service.js +120 -0
  172. package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +59 -29
  173. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +164 -35
  174. package/src/route-renderer/orchestration/global-injector-assets.service.d.ts +7 -0
  175. package/src/route-renderer/orchestration/global-injector-assets.service.js +32 -0
  176. package/src/route-renderer/orchestration/integration-renderer.d.ts +18 -54
  177. package/src/route-renderer/orchestration/integration-renderer.js +113 -195
  178. package/src/route-renderer/orchestration/integration-route-render-adapter.d.ts +38 -0
  179. package/src/route-renderer/orchestration/integration-route-render-adapter.js +27 -0
  180. package/src/route-renderer/orchestration/layout-shell-props.service.d.ts +20 -0
  181. package/src/route-renderer/orchestration/layout-shell-props.service.js +31 -0
  182. package/src/route-renderer/orchestration/ownership-validation.service.d.ts +5 -0
  183. package/src/route-renderer/orchestration/ownership-validation.service.js +29 -1
  184. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.d.ts +9 -0
  185. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.js +7 -0
  186. package/src/route-renderer/orchestration/page-browser-graph.service.d.ts +25 -0
  187. package/src/route-renderer/orchestration/page-browser-graph.service.js +174 -0
  188. package/src/route-renderer/orchestration/render-output.utils.d.ts +2 -0
  189. package/src/route-renderer/orchestration/render-output.utils.js +4 -0
  190. package/src/route-renderer/orchestration/route-html-finalization.service.d.ts +17 -0
  191. package/src/route-renderer/orchestration/route-html-finalization.service.js +26 -0
  192. package/src/route-renderer/orchestration/route-prepared-options.builder.d.ts +26 -0
  193. package/src/route-renderer/orchestration/route-prepared-options.builder.js +54 -0
  194. package/src/route-renderer/orchestration/route-prepared-options.utils.d.ts +4 -0
  195. package/src/route-renderer/orchestration/route-prepared-options.utils.js +33 -0
  196. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +8 -39
  197. package/src/route-renderer/orchestration/route-render-orchestrator.js +53 -461
  198. package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
  199. package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
  200. package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
  201. package/src/router/client/link-intent.d.ts +11 -21
  202. package/src/router/client/link-intent.js +10 -0
  203. package/src/router/client/link-intent.test.browser.js +12 -1
  204. package/src/router/client/link-navigation-policy.d.ts +45 -0
  205. package/src/router/client/link-navigation-policy.js +101 -0
  206. package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
  207. package/src/router/client/link-navigation-policy.test.browser.js +92 -0
  208. package/src/router/client/navigation-coordinator.d.ts +1 -1
  209. package/src/router/client/navigation-coordinator.js +12 -2
  210. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -0
  211. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
  212. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
  213. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +27 -7
  214. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -1
  215. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +18 -15
  216. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
  217. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
  218. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
  219. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
  220. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
  221. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
  222. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
  223. package/src/services/assets/browser-bundle.service.d.ts +3 -1
  224. package/src/services/assets/browser-bundle.service.js +17 -5
  225. package/src/services/html/html-transformer.service.d.ts +1 -1
  226. package/src/services/html/html-transformer.service.js +4 -4
  227. package/src/services/invalidation/development-invalidation.service.d.ts +20 -2
  228. package/src/services/invalidation/development-invalidation.service.js +56 -2
  229. package/src/services/module-loading/README.md +49 -0
  230. package/src/services/module-loading/app-server-module-transpiler.service.js +5 -17
  231. package/src/services/module-loading/page-module-import.service.d.ts +5 -1
  232. package/src/services/module-loading/page-module-import.service.js +96 -45
  233. package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
  234. package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
  235. package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
  236. package/src/services/module-loading/route-module-build-cache.js +38 -0
  237. package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
  238. package/src/services/module-loading/route-module-build-cache.store.js +207 -0
  239. package/src/services/module-loading/route-module-build-manifest.d.ts +61 -0
  240. package/src/services/module-loading/route-module-build-manifest.js +116 -0
  241. package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
  242. package/src/services/module-loading/route-module-dependency-hasher.js +122 -0
  243. package/src/services/module-loading/server-module-transpiler.service.js +1 -1
  244. package/src/static-site-generator/README.md +33 -0
  245. package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
  246. package/src/static-site-generator/static-build-invalidation.js +59 -0
  247. package/src/static-site-generator/static-export-context.d.ts +22 -0
  248. package/src/static-site-generator/static-export-context.js +0 -0
  249. package/src/static-site-generator/static-site-generator.d.ts +17 -20
  250. package/src/static-site-generator/static-site-generator.js +188 -85
  251. package/src/types/internal-types.d.ts +16 -9
  252. package/src/types/public-types.d.ts +144 -40
  253. package/src/utils/parse-cli-args.d.ts +2 -0
  254. package/src/utils/parse-cli-args.js +6 -0
  255. package/src/utils/server-utils.module.d.ts +3 -2
  256. package/src/utils/server-utils.module.js +5 -6
  257. package/src/utils/static-file-extensions.d.ts +12 -0
  258. package/src/utils/static-file-extensions.js +48 -0
  259. package/src/watchers/project-watcher-ignore.d.ts +11 -0
  260. package/src/watchers/project-watcher-ignore.js +16 -0
  261. package/src/watchers/project-watcher.d.ts +26 -3
  262. package/src/watchers/project-watcher.js +132 -30
  263. package/src/watchers/project-watcher.test-helpers.js +5 -5
  264. package/src/build/rolldown-dev-build-adapter.d.ts +0 -82
  265. package/src/build/rolldown-dev-build-adapter.js +0 -166
  266. package/src/hmr/hmr.postcss.test.e2e.js +0 -31
  267. package/src/hmr/hmr.test.e2e.js +0 -43
  268. package/src/route-renderer/orchestration/ownership-planning.service.d.ts +0 -24
  269. package/src/route-renderer/orchestration/ownership-planning.service.js +0 -63
  270. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +0 -91
  271. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +0 -170
  272. /package/src/{hmr/hmr.postcss.test.e2e.d.ts → client/navigation-scripts/navigation-scripts.test.browser.d.ts} +0 -0
  273. /package/src/{hmr/hmr.test.e2e.d.ts → client/scroll.test.browser.d.ts} +0 -0
package/src/eco/eco.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  interceptForeignChild
5
5
  } from "../route-renderer/orchestration/component-render-context.js";
6
6
  import { isThenable } from "../route-renderer/orchestration/render-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.
@@ -81,7 +81,7 @@ export interface PageOptionsBase<T, E = EcoPagesElement> {
81
81
  __eco?: EcoInjectedMeta;
82
82
  integration?: string;
83
83
  dependencies?: EcoComponentDependencies;
84
- layout?: EcoPageLayoutComponent<E>;
84
+ layout?: EcoPageLayouts<E>;
85
85
  /**
86
86
  * Define static paths for dynamic routes (e.g., [slug].tsx).
87
87
  * Returns all possible paths that should be pre-rendered at build time.
@@ -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
+ };
@@ -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;
@@ -0,0 +1,43 @@
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;
@@ -0,0 +1,53 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileSystem } from "@ecopages/file-system";
4
+ import { RESOLVED_ASSETS_DIR } from "../config/constants.js";
5
+ import { appLogger } from "../global/app-logger.js";
6
+ function isRegisteredScriptEntrypoint(registered, filePath) {
7
+ return registered.has(path.resolve(filePath));
8
+ }
9
+ function isBrowserOnlyRegisteredScriptEntrypoint(filePath) {
10
+ return /\.script\.ts$/u.test(path.resolve(filePath));
11
+ }
12
+ function encodeHmrDynamicSegments(filepath) {
13
+ return filepath.replace(/\[([^\]]+)\]/g, "_$1_");
14
+ }
15
+ function resolveHmrEntrypointOutputPaths(srcDir, distDir, entrypointPath) {
16
+ const normalizedEntrypoint = path.resolve(entrypointPath);
17
+ const relativePath = path.relative(srcDir, normalizedEntrypoint);
18
+ const relativePathJs = relativePath.replace(/\.(tsx?|jsx?|mdx?)$/, ".js");
19
+ const encodedPathJs = encodeHmrDynamicSegments(relativePathJs);
20
+ const urlPath = encodedPathJs.split(path.sep).join("/");
21
+ return {
22
+ outputUrl: `/${path.join(RESOLVED_ASSETS_DIR, "_hmr", urlPath).split(path.sep).join("/")}`,
23
+ outputPath: path.join(distDir, urlPath)
24
+ };
25
+ }
26
+ function removeStaleHmrEntrypointOutput(outputPath, scope) {
27
+ if (!fileSystem.exists(outputPath)) {
28
+ return;
29
+ }
30
+ try {
31
+ fileSystem.remove(outputPath);
32
+ } catch (error) {
33
+ appLogger.warn(
34
+ `[${scope}] Failed to remove stale entrypoint output ${outputPath}: ${error instanceof Error ? error.message : String(error)}`
35
+ );
36
+ }
37
+ }
38
+ function isHmrOutputFresh(outputPath, sourcePath) {
39
+ if (!fileSystem.exists(outputPath) || !fileSystem.exists(sourcePath)) {
40
+ return false;
41
+ }
42
+ const outputMtimeMs = fs.statSync(outputPath).mtimeMs;
43
+ const sourceMtimeMs = fs.statSync(sourcePath).mtimeMs;
44
+ return outputMtimeMs >= sourceMtimeMs;
45
+ }
46
+ export {
47
+ encodeHmrDynamicSegments,
48
+ isBrowserOnlyRegisteredScriptEntrypoint,
49
+ isHmrOutputFresh,
50
+ isRegisteredScriptEntrypoint,
51
+ removeStaleHmrEntrypointOutput,
52
+ resolveHmrEntrypointOutputPaths
53
+ };
@@ -133,6 +133,21 @@ export declare abstract class HmrStrategy {
133
133
  * ```
134
134
  */
135
135
  abstract matches(filePath: string): boolean;
136
+ /**
137
+ * Returns whether this strategy owns cold registration for the entrypoint.
138
+ *
139
+ * @remarks
140
+ * Registration dispatch uses only integration strategies that claim the
141
+ * entrypoint. File-change dispatch continues to use {@link matches}.
142
+ */
143
+ canEmitEntrypoint(_entrypointPath: string): boolean;
144
+ /**
145
+ * Materializes one integration-owned HMR entrypoint during registration.
146
+ *
147
+ * @remarks
148
+ * Must write the canonical output path and must not broadcast client events.
149
+ */
150
+ emitEntrypoint(_entrypointPath: string, _outputPath: string): Promise<void>;
136
151
  /**
137
152
  * Processes a file change and returns the action to take.
138
153
  *
@@ -37,6 +37,25 @@ class HmrStrategy {
37
37
  get priority() {
38
38
  return this.type + this.priorityOffset;
39
39
  }
40
+ /**
41
+ * Returns whether this strategy owns cold registration for the entrypoint.
42
+ *
43
+ * @remarks
44
+ * Registration dispatch uses only integration strategies that claim the
45
+ * entrypoint. File-change dispatch continues to use {@link matches}.
46
+ */
47
+ canEmitEntrypoint(_entrypointPath) {
48
+ return false;
49
+ }
50
+ /**
51
+ * Materializes one integration-owned HMR entrypoint during registration.
52
+ *
53
+ * @remarks
54
+ * Must write the canonical output path and must not broadcast client events.
55
+ */
56
+ async emitEntrypoint(_entrypointPath, _outputPath) {
57
+ return;
58
+ }
40
59
  }
41
60
  export {
42
61
  HmrStrategy,
@@ -8,7 +8,6 @@
8
8
  * @module
9
9
  */
10
10
  import { HmrStrategy, type HmrAction } from '../hmr-strategy.js';
11
- import type { EcoBuildPlugin } from '../../build/build-types.js';
12
11
  import type { BrowserBundleExecutor } from '../../services/assets/browser-bundle.service.js';
13
12
  import type { EntrypointDependencyGraph } from '../../services/runtime-state/entrypoint-dependency-graph.service.js';
14
13
  /**
@@ -25,10 +24,6 @@ export interface JsHmrContext {
25
24
  * Directory where HMR bundles are written.
26
25
  */
27
26
  getDistDir(): string;
28
- /**
29
- * Build plugins to use during bundling.
30
- */
31
- getPlugins(): EcoBuildPlugin[];
32
27
  /**
33
28
  * Absolute path to the source directory.
34
29
  */
@@ -98,6 +93,7 @@ export declare class JsHmrStrategy extends HmrStrategy {
98
93
  * Matches if:
99
94
  * 1. There are registered entrypoints to rebuild
100
95
  * 2. The changed file is a JS/TS file in the src directory
96
+ * 3. Registered entrypoints always match, even when they share an integration template extension
101
97
  *
102
98
  * @param filePath - Absolute path to the changed file
103
99
  * @returns True if this file should trigger entrypoint rebuilds
@@ -116,6 +112,8 @@ export declare class JsHmrStrategy extends HmrStrategy {
116
112
  * @returns Action to broadcast update events
117
113
  */
118
114
  process(filePath: string): Promise<HmrAction>;
115
+ private resolveEntrypointOutputPath;
116
+ private removeStaleEntrypointOutput;
119
117
  /**
120
118
  * Bundles one or more entrypoints in a single build invocation.
121
119
  * Uses the source directory as the output base so that the directory structure
@@ -2,6 +2,12 @@ import path from "node:path";
2
2
  import { fileSystem } from "@ecopages/file-system";
3
3
  import { HmrStrategy, HmrStrategyType } from "../hmr-strategy.js";
4
4
  import { appLogger } from "../../global/app-logger.js";
5
+ import {
6
+ removeStaleHmrEntrypointOutput,
7
+ resolveHmrEntrypointOutputPaths,
8
+ isRegisteredScriptEntrypoint,
9
+ isHmrOutputFresh
10
+ } from "../hmr-entrypoint-output.js";
5
11
  class JsHmrStrategy extends HmrStrategy {
6
12
  type = HmrStrategyType.SCRIPT;
7
13
  context;
@@ -15,27 +21,30 @@ class JsHmrStrategy extends HmrStrategy {
15
21
  * Matches if:
16
22
  * 1. There are registered entrypoints to rebuild
17
23
  * 2. The changed file is a JS/TS file in the src directory
24
+ * 3. Registered entrypoints always match, even when they share an integration template extension
18
25
  *
19
26
  * @param filePath - Absolute path to the changed file
20
27
  * @returns True if this file should trigger entrypoint rebuilds
21
28
  */
22
29
  matches(filePath) {
23
30
  const watchedFiles = this.context.getWatchedFiles();
24
- const isJsTs = /\.(ts|tsx|js|jsx)$/.test(filePath);
25
- const isInSrc = filePath.startsWith(this.context.getSrcDir());
26
- const isIntegrationTemplate = this.context.getTemplateExtensions().some((extension) => filePath.endsWith(extension));
31
+ const resolvedPath = path.resolve(filePath);
32
+ const isJsTs = /\.(ts|tsx|js|jsx)$/.test(resolvedPath);
33
+ const srcDir = path.resolve(this.context.getSrcDir());
34
+ const isInSrc = resolvedPath.startsWith(`${srcDir}${path.sep}`) || resolvedPath === srcDir;
35
+ const isIntegrationTemplate = this.context.getTemplateExtensions().some((extension) => resolvedPath.endsWith(extension));
27
36
  if (watchedFiles.size === 0) {
28
37
  return false;
29
38
  }
30
39
  if (!isJsTs || !isInSrc) {
31
40
  return false;
32
41
  }
42
+ if (watchedFiles.has(resolvedPath)) {
43
+ return true;
44
+ }
33
45
  if (isIntegrationTemplate) {
34
46
  return false;
35
47
  }
36
- if (watchedFiles.has(filePath)) {
37
- return true;
38
- }
39
48
  return true;
40
49
  }
41
50
  /**
@@ -53,22 +62,27 @@ class JsHmrStrategy extends HmrStrategy {
53
62
  async process(filePath) {
54
63
  appLogger.debug(`[JsHmrStrategy] Processing ${filePath}`);
55
64
  const watchedFiles = this.context.getWatchedFiles();
65
+ const resolvedChanged = path.resolve(filePath);
66
+ const isRegisteredEntrypointEdit = isRegisteredScriptEntrypoint(watchedFiles, resolvedChanged);
56
67
  if (watchedFiles.size === 0) {
57
68
  appLogger.debug(`[JsHmrStrategy] No watched files to rebuild`);
58
69
  return { type: "none" };
59
70
  }
60
71
  const dependencyHits = this.context.getEntrypointDependencyGraph().getDependencyEntrypoints(filePath);
61
72
  const hasDependencyHit = dependencyHits.size > 0;
62
- const impactedEntrypoints = hasDependencyHit ? Array.from(dependencyHits).filter((entrypoint) => watchedFiles.has(entrypoint)) : Array.from(watchedFiles.keys());
73
+ const impactedEntrypoints = isRegisteredEntrypointEdit ? [resolvedChanged] : hasDependencyHit ? Array.from(dependencyHits).filter((entrypoint) => watchedFiles.has(path.resolve(entrypoint))) : Array.from(watchedFiles.keys());
63
74
  const buildableEntrypoints = impactedEntrypoints.filter(
64
75
  (entrypoint) => this.context.shouldProcessEntrypoint?.(entrypoint) ?? true
65
76
  );
66
- if (!hasDependencyHit) {
77
+ if (!hasDependencyHit && !isRegisteredEntrypointEdit) {
67
78
  appLogger.debug("[JsHmrStrategy] Dependency graph miss, rebuilding all watched entrypoints");
68
79
  }
69
80
  if (buildableEntrypoints.length === 0) {
70
81
  return { type: "none" };
71
82
  }
83
+ for (const entrypoint of buildableEntrypoints) {
84
+ this.removeStaleEntrypointOutput(this.resolveEntrypointOutputPath(entrypoint));
85
+ }
72
86
  const buildResult = await this.bundleEntrypoints(buildableEntrypoints);
73
87
  if (!buildResult.success) {
74
88
  return { type: "none" };
@@ -76,17 +90,19 @@ class JsHmrStrategy extends HmrStrategy {
76
90
  const updates = [];
77
91
  let reloadRequired = false;
78
92
  for (const entrypoint of buildableEntrypoints) {
79
- const outputUrl = watchedFiles.get(entrypoint);
80
- if (!outputUrl) continue;
93
+ const resolvedEntrypoint = path.resolve(entrypoint);
94
+ const derivedOutput = resolveHmrEntrypointOutputPaths(
95
+ this.context.getSrcDir(),
96
+ this.context.getDistDir(),
97
+ resolvedEntrypoint
98
+ );
99
+ const outputUrl = watchedFiles.get(resolvedEntrypoint) ?? derivedOutput.outputUrl;
100
+ const outputPath = this.resolveEntrypointOutputPath(resolvedEntrypoint);
81
101
  if (buildResult.dependencies) {
82
- const entrypointDeps = buildResult.dependencies.get(path.resolve(entrypoint)) ?? [];
83
- this.context.getEntrypointDependencyGraph().setEntrypointDependencies(entrypoint, entrypointDeps);
102
+ const entrypointDeps = buildResult.dependencies.get(resolvedEntrypoint) ?? [];
103
+ this.context.getEntrypointDependencyGraph().setEntrypointDependencies(resolvedEntrypoint, entrypointDeps);
84
104
  }
85
- const srcDir = this.context.getSrcDir();
86
- const relativePath = path.relative(srcDir, entrypoint);
87
- const relativePathJs = relativePath.replace(/\.(tsx?|jsx?|mdx?)$/, ".js");
88
- const outputPath = path.join(this.context.getDistDir(), relativePathJs);
89
- const result = await this.processOutput(outputPath, outputUrl);
105
+ const result = await this.processOutput(outputPath, outputUrl, resolvedEntrypoint);
90
106
  if (result.success) {
91
107
  updates.push(outputUrl);
92
108
  if (result.requiresReload) {
@@ -113,6 +129,12 @@ class JsHmrStrategy extends HmrStrategy {
113
129
  }
114
130
  return { type: "none" };
115
131
  }
132
+ resolveEntrypointOutputPath(entrypointPath) {
133
+ return resolveHmrEntrypointOutputPaths(this.context.getSrcDir(), this.context.getDistDir(), entrypointPath).outputPath;
134
+ }
135
+ removeStaleEntrypointOutput(outputPath) {
136
+ removeStaleHmrEntrypointOutput(outputPath, "JsHmrStrategy");
137
+ }
116
138
  /**
117
139
  * Bundles one or more entrypoints in a single build invocation.
118
140
  * Uses the source directory as the output base so that the directory structure
@@ -120,13 +142,35 @@ class JsHmrStrategy extends HmrStrategy {
120
142
  */
121
143
  async bundleEntrypoints(entrypoints) {
122
144
  try {
145
+ if (entrypoints.length === 1) {
146
+ const entrypoint = entrypoints[0];
147
+ const outputPath = this.resolveEntrypointOutputPath(entrypoint);
148
+ const naming = path.relative(this.context.getDistDir(), outputPath).split(path.sep).join("/");
149
+ const result2 = await this.context.getBrowserBundleService().bundle({
150
+ profile: "hmr-entrypoint",
151
+ entrypoints: [entrypoint],
152
+ outdir: this.context.getDistDir(),
153
+ naming,
154
+ minify: false
155
+ });
156
+ if (!result2.success) {
157
+ appLogger.error("[JsHmrStrategy] Entrypoint build failed:", result2.logs);
158
+ return { success: false };
159
+ }
160
+ const dependencies2 = /* @__PURE__ */ new Map();
161
+ if (result2.dependencyGraph?.entrypoints) {
162
+ for (const [resolvedEntrypoint, deps] of Object.entries(result2.dependencyGraph.entrypoints)) {
163
+ dependencies2.set(path.resolve(resolvedEntrypoint), deps);
164
+ }
165
+ }
166
+ return { success: true, dependencies: dependencies2 };
167
+ }
123
168
  const result = await this.context.getBrowserBundleService().bundle({
124
169
  profile: "hmr-entrypoint",
125
170
  entrypoints,
126
171
  outdir: this.context.getDistDir(),
127
172
  outbase: this.context.getSrcDir(),
128
173
  naming: "[dir]/[name]",
129
- plugins: this.context.getPlugins(),
130
174
  minify: false
131
175
  });
132
176
  if (!result.success) {
@@ -153,8 +197,12 @@ class JsHmrStrategy extends HmrStrategy {
153
197
  * @param url - URL path for the bundled file
154
198
  * @returns True if processing was successful and update should be broadcast
155
199
  */
156
- async processOutput(filepath, url) {
200
+ async processOutput(filepath, url, sourcePath) {
157
201
  try {
202
+ if (sourcePath && !isHmrOutputFresh(filepath, sourcePath)) {
203
+ appLogger.warn(`[JsHmrStrategy] Skipping broadcast for stale HMR output ${url}`);
204
+ return { success: false, requiresReload: false };
205
+ }
158
206
  const code = await fileSystem.readFile(filepath);
159
207
  if (code.includes("/* [ecopages] hmr */")) {
160
208
  return { success: true, requiresReload: !code.includes("import.meta.hot.accept") };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * HMR strategy for server-rendered include templates and explicit server views.
3
+ *
4
+ * These files affect SSR output (head, layout shell, explicit views) but are not
5
+ * client HMR entrypoints. Broadcast a layout-update so the active navigation
6
+ * runtime can refresh the current page without a full document reload.
7
+ */
8
+ import { HmrStrategy, type HmrAction } from '../hmr-strategy.js';
9
+ import type { DevelopmentInvalidationService } from '../../services/invalidation/development-invalidation.service.js';
10
+ export declare class ServerRenderedTemplateHmrStrategy extends HmrStrategy {
11
+ private readonly invalidationService;
12
+ readonly type: 100;
13
+ readonly priorityOffset = 50;
14
+ constructor(invalidationService: DevelopmentInvalidationService);
15
+ matches(filePath: string): boolean;
16
+ process(filePath: string): Promise<HmrAction>;
17
+ }
@@ -0,0 +1,29 @@
1
+ import { HmrStrategy, HmrStrategyType } from "../hmr-strategy.js";
2
+ const SERVER_RENDERED_TEMPLATE_PRIORITY_OFFSET = 50;
3
+ class ServerRenderedTemplateHmrStrategy extends HmrStrategy {
4
+ constructor(invalidationService) {
5
+ super();
6
+ this.invalidationService = invalidationService;
7
+ }
8
+ invalidationService;
9
+ type = HmrStrategyType.INTEGRATION;
10
+ priorityOffset = SERVER_RENDERED_TEMPLATE_PRIORITY_OFFSET;
11
+ matches(filePath) {
12
+ return this.invalidationService.isIncludeSourceFile(filePath) || this.invalidationService.isExplicitServerViewFile(filePath);
13
+ }
14
+ async process(filePath) {
15
+ return {
16
+ type: "broadcast",
17
+ events: [
18
+ {
19
+ type: "layout-update",
20
+ path: filePath,
21
+ timestamp: Date.now()
22
+ }
23
+ ]
24
+ };
25
+ }
26
+ }
27
+ export {
28
+ ServerRenderedTemplateHmrStrategy
29
+ };
@@ -2,15 +2,11 @@
2
2
  * This module contains the ghtml renderer
3
3
  * @module
4
4
  */
5
- import type { ComponentRenderInput, ComponentRenderResult, EcoComponent, EcoPagesElement, IntegrationRendererRenderOptions, RouteRendererBody } from '../../types/public-types.js';
6
- import { IntegrationRenderer, type RenderToResponseContext } from '../../route-renderer/orchestration/integration-renderer.js';
5
+ import { StringMarkupRenderer } from '../../route-renderer/orchestration/string-markup-renderer.js';
7
6
  /**
8
7
  * A renderer for the ghtml integration.
9
8
  * It renders a page using the HtmlTemplate and Page components.
10
9
  */
11
- export declare class GhtmlRenderer extends IntegrationRenderer<EcoPagesElement> {
10
+ export declare class GhtmlRenderer extends StringMarkupRenderer {
12
11
  name: string;
13
- renderComponent(input: ComponentRenderInput): Promise<ComponentRenderResult>;
14
- render({ params, query, props, locals, pageLocals, metadata, Page, Layout, HtmlTemplate, }: IntegrationRendererRenderOptions): Promise<RouteRendererBody>;
15
- renderToResponse<P = Record<string, unknown>>(view: EcoComponent<P>, props: P, ctx: RenderToResponseContext): Promise<Response>;
16
12
  }