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

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/hmr-manager.d.ts +2 -1
  13. package/src/adapters/bun/hmr-manager.js +2 -2
  14. package/src/adapters/bun/server-adapter.d.ts +90 -22
  15. package/src/adapters/bun/server-adapter.js +265 -84
  16. package/src/adapters/bun/static-preview-host.js +25 -20
  17. package/src/adapters/create-app.d.ts +13 -11
  18. package/src/adapters/create-app.js +2 -51
  19. package/src/adapters/index.d.ts +1 -1
  20. package/src/adapters/index.js +1 -2
  21. package/src/adapters/node/create-app.d.ts +5 -1
  22. package/src/adapters/node/create-app.js +51 -12
  23. package/src/adapters/node/node-client-bridge.d.ts +1 -0
  24. package/src/adapters/node/node-client-bridge.js +3 -0
  25. package/src/adapters/node/node-hmr-manager.d.ts +2 -1
  26. package/src/adapters/node/node-hmr-manager.js +2 -2
  27. package/src/adapters/node/server-adapter-dependencies.js +4 -0
  28. package/src/adapters/node/server-adapter.d.ts +62 -20
  29. package/src/adapters/node/server-adapter.js +161 -131
  30. package/src/adapters/node/static-content-server.d.ts +1 -0
  31. package/src/adapters/node/static-content-server.js +10 -2
  32. package/src/adapters/node/static-preview-host.js +27 -12
  33. package/src/adapters/shared/bun-user-websocket-lifecycle.d.ts +22 -0
  34. package/src/adapters/shared/bun-user-websocket-lifecycle.js +96 -0
  35. package/src/adapters/shared/copy-runtime-public-dir.d.ts +6 -0
  36. package/src/adapters/shared/copy-runtime-public-dir.js +24 -0
  37. package/src/adapters/shared/fs-server-response-matcher.d.ts +2 -0
  38. package/src/adapters/shared/fs-server-response-matcher.js +40 -18
  39. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +0 -2
  40. package/src/adapters/shared/hmr-entrypoint-registrar.js +3 -26
  41. package/src/adapters/shared/hmr-html-response.d.ts +1 -1
  42. package/src/adapters/shared/hmr-html-response.js +4 -1
  43. package/src/adapters/shared/node-http-websocket-upgrades.d.ts +21 -0
  44. package/src/adapters/shared/node-http-websocket-upgrades.js +100 -0
  45. package/src/adapters/shared/port-manager.d.ts +116 -0
  46. package/src/adapters/shared/port-manager.js +196 -0
  47. package/src/adapters/shared/runtime-app-bootstrap.d.ts +2 -1
  48. package/src/adapters/shared/runtime-app-bootstrap.js +3 -6
  49. package/src/adapters/shared/runtime-server-lifecycle.d.ts +38 -0
  50. package/src/adapters/shared/runtime-server-lifecycle.js +43 -0
  51. package/src/adapters/shared/server-adapter.d.ts +2 -1
  52. package/src/adapters/shared/server-adapter.js +13 -6
  53. package/src/adapters/shared/server-route-handler.d.ts +4 -1
  54. package/src/adapters/shared/server-route-handler.js +5 -2
  55. package/src/adapters/shared/server-static-builder.d.ts +23 -32
  56. package/src/adapters/shared/server-static-builder.js +97 -73
  57. package/src/adapters/shared/shared-hmr-manager.d.ts +28 -0
  58. package/src/adapters/shared/shared-hmr-manager.js +119 -9
  59. package/src/adapters/shared/static-preview-host.d.ts +5 -0
  60. package/src/adapters/shared/websocket-lifecycle.d.ts +24 -0
  61. package/src/adapters/shared/websocket-lifecycle.js +55 -0
  62. package/src/build/README.md +77 -14
  63. package/src/build/app-build-manifest-runtime.d.ts +10 -0
  64. package/src/build/app-build-manifest-runtime.js +90 -0
  65. package/src/build/build-adapter.d.ts +17 -319
  66. package/src/build/build-adapter.js +28 -94
  67. package/src/build/build-contracts.d.ts +97 -0
  68. package/src/build/build-contracts.js +0 -0
  69. package/src/build/build-input-fingerprint.d.ts +28 -0
  70. package/src/build/build-input-fingerprint.js +31 -0
  71. package/src/build/build-profile-options.d.ts +7 -0
  72. package/src/build/build-profile-options.js +37 -0
  73. package/src/build/build-runtime.d.ts +24 -0
  74. package/src/build/build-runtime.js +65 -0
  75. package/src/build/deduping-build-executor.d.ts +28 -0
  76. package/src/build/deduping-build-executor.js +56 -0
  77. package/src/build/jsx-ownership-plugins.d.ts +24 -0
  78. package/src/build/jsx-ownership-plugins.js +41 -0
  79. package/src/build/pages-unified-graph-build.d.ts +31 -0
  80. package/src/build/pages-unified-graph-build.js +206 -0
  81. package/src/build/parallel-build-executor.d.ts +21 -0
  82. package/src/build/parallel-build-executor.js +52 -0
  83. package/src/build/production-build-cache.d.ts +20 -0
  84. package/src/build/production-build-cache.js +63 -0
  85. package/src/build/rolldown-adapter-helpers.d.ts +3 -6
  86. package/src/build/rolldown-adapter-helpers.js +71 -6
  87. package/src/build/rolldown-build-adapter.d.ts +2 -6
  88. package/src/build/rolldown-build-adapter.js +3 -3
  89. package/src/build/rolldown-build-invocation-metrics.d.ts +12 -0
  90. package/src/build/rolldown-build-invocation-metrics.js +43 -0
  91. package/src/build/rolldown-plugin-bridge.d.ts +15 -1
  92. package/src/build/rolldown-plugin-bridge.js +20 -5
  93. package/src/build/rolldown-source-transform-pass.d.ts +15 -0
  94. package/src/build/rolldown-source-transform-pass.js +58 -0
  95. package/src/build/runtime-build-executor.d.ts +8 -15
  96. package/src/build/runtime-build-executor.js +12 -15
  97. package/src/build/runtime-build-output-normalizer.d.ts +7 -0
  98. package/src/build/runtime-build-output-normalizer.js +94 -2
  99. package/src/build/server-entry-build-cache.d.ts +44 -0
  100. package/src/build/server-entry-build-cache.js +161 -0
  101. package/src/client/navigation-scripts/classification.d.ts +16 -0
  102. package/src/client/navigation-scripts/classification.js +41 -0
  103. package/src/client/navigation-scripts/index.d.ts +3 -0
  104. package/src/client/navigation-scripts/index.js +23 -0
  105. package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
  106. package/src/client/navigation-scripts/registry.d.ts +11 -0
  107. package/src/client/navigation-scripts/registry.js +12 -0
  108. package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
  109. package/src/client/navigation-scripts/rerun-queue.js +73 -0
  110. package/src/client/scroll.d.ts +17 -0
  111. package/src/client/scroll.js +25 -0
  112. package/src/client/scroll.test.browser.js +37 -0
  113. package/src/client/view-transitions.d.ts +16 -0
  114. package/src/client/view-transitions.js +63 -0
  115. package/src/config/config-builder.d.ts +12 -7
  116. package/src/config/config-builder.js +12 -9
  117. package/src/dev/client-bridge-registry.d.ts +5 -0
  118. package/src/dev/client-bridge-registry.js +15 -0
  119. package/src/dev/dev-client-ownership.d.ts +7 -0
  120. package/src/dev/dev-client-ownership.js +6 -0
  121. package/src/dev/hmr-manager-registry.d.ts +8 -0
  122. package/src/dev/hmr-manager-registry.js +15 -0
  123. package/src/dev/host-runtime.d.ts +3 -0
  124. package/src/dev/host-runtime.js +7 -0
  125. package/src/dev/runtime-server-started-message.d.ts +2 -0
  126. package/src/dev/runtime-server-started-message.js +6 -0
  127. package/src/eco/README.md +11 -0
  128. package/src/eco/eco-declared-component.d.ts +14 -0
  129. package/src/eco/eco-declared-component.js +16 -0
  130. package/src/eco/eco.browser.js +5 -6
  131. package/src/eco/eco.js +5 -6
  132. package/src/eco/eco.types.d.ts +2 -2
  133. package/src/eco/page-layout-normalization.d.ts +21 -0
  134. package/src/eco/page-layout-normalization.js +59 -0
  135. package/src/errors/index.d.ts +1 -0
  136. package/src/errors/index.js +7 -1
  137. package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
  138. package/src/errors/undeclared-component-dependency-error.js +17 -0
  139. package/src/hmr/client/hmr-runtime.js +5 -2
  140. package/src/hmr/hmr-entrypoint-output.d.ts +28 -0
  141. package/src/hmr/hmr-entrypoint-output.js +58 -0
  142. package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -0
  143. package/src/hmr/strategies/js-hmr-strategy.js +68 -18
  144. package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
  145. package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
  146. package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
  147. package/src/integrations/ghtml/ghtml-renderer.js +2 -51
  148. package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
  149. package/src/integrations/ghtml/ghtml.plugin.js +7 -14
  150. package/src/plugins/define-integration.d.ts +26 -0
  151. package/src/plugins/define-integration.js +19 -0
  152. package/src/plugins/eco-component-meta-plugin.js +5 -8
  153. package/src/plugins/foreign-jsx-override-plugin.js +4 -6
  154. package/src/plugins/integration-plugin.d.ts +19 -9
  155. package/src/plugins/integration-plugin.js +7 -4
  156. package/src/plugins/jsx-import-source.utils.d.ts +8 -0
  157. package/src/plugins/jsx-import-source.utils.js +26 -0
  158. package/src/plugins/processor.d.ts +19 -4
  159. package/src/plugins/processor.js +22 -4
  160. package/src/plugins/source-transform.d.ts +31 -0
  161. package/src/plugins/source-transform.js +23 -1
  162. package/src/route-renderer/GRAPH.md +8 -8
  163. package/src/route-renderer/README.md +30 -28
  164. package/src/route-renderer/orchestration/component-graph-collectors.d.ts +10 -0
  165. package/src/route-renderer/orchestration/component-graph-collectors.js +143 -0
  166. package/src/route-renderer/orchestration/component-graph.d.ts +36 -0
  167. package/src/route-renderer/orchestration/component-graph.js +98 -0
  168. package/src/route-renderer/orchestration/component-render-context.d.ts +3 -10
  169. package/src/route-renderer/orchestration/component-render-context.js +3 -1
  170. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +1 -18
  171. package/src/route-renderer/orchestration/declared-ownership-graph.js +5 -31
  172. package/src/route-renderer/orchestration/document-shell-render.service.d.ts +90 -0
  173. package/src/route-renderer/orchestration/document-shell-render.service.js +120 -0
  174. package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +59 -29
  175. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +164 -35
  176. package/src/route-renderer/orchestration/global-injector-assets.service.d.ts +7 -0
  177. package/src/route-renderer/orchestration/global-injector-assets.service.js +32 -0
  178. package/src/route-renderer/orchestration/integration-renderer.d.ts +18 -54
  179. package/src/route-renderer/orchestration/integration-renderer.js +113 -195
  180. package/src/route-renderer/orchestration/integration-route-render-adapter.d.ts +38 -0
  181. package/src/route-renderer/orchestration/integration-route-render-adapter.js +27 -0
  182. package/src/route-renderer/orchestration/layout-shell-props.service.d.ts +20 -0
  183. package/src/route-renderer/orchestration/layout-shell-props.service.js +31 -0
  184. package/src/route-renderer/orchestration/ownership-validation.service.d.ts +5 -0
  185. package/src/route-renderer/orchestration/ownership-validation.service.js +29 -1
  186. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.d.ts +9 -0
  187. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.js +7 -0
  188. package/src/route-renderer/orchestration/page-browser-graph.service.d.ts +25 -0
  189. package/src/route-renderer/orchestration/page-browser-graph.service.js +174 -0
  190. package/src/route-renderer/orchestration/render-output.utils.d.ts +2 -0
  191. package/src/route-renderer/orchestration/render-output.utils.js +4 -0
  192. package/src/route-renderer/orchestration/route-html-finalization.service.d.ts +17 -0
  193. package/src/route-renderer/orchestration/route-html-finalization.service.js +26 -0
  194. package/src/route-renderer/orchestration/route-prepared-options.builder.d.ts +26 -0
  195. package/src/route-renderer/orchestration/route-prepared-options.builder.js +54 -0
  196. package/src/route-renderer/orchestration/route-prepared-options.utils.d.ts +4 -0
  197. package/src/route-renderer/orchestration/route-prepared-options.utils.js +33 -0
  198. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +8 -39
  199. package/src/route-renderer/orchestration/route-render-orchestrator.js +53 -461
  200. package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
  201. package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
  202. package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
  203. package/src/router/client/link-intent.d.ts +11 -21
  204. package/src/router/client/link-intent.js +10 -0
  205. package/src/router/client/link-intent.test.browser.js +12 -1
  206. package/src/router/client/link-navigation-policy.d.ts +45 -0
  207. package/src/router/client/link-navigation-policy.js +101 -0
  208. package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
  209. package/src/router/client/link-navigation-policy.test.browser.js +92 -0
  210. package/src/router/client/navigation-coordinator.d.ts +1 -1
  211. package/src/router/client/navigation-coordinator.js +12 -2
  212. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -0
  213. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
  214. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
  215. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +27 -7
  216. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +36 -14
  217. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
  218. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
  219. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
  220. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
  221. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
  222. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
  223. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
  224. package/src/services/assets/browser-bundle.service.d.ts +3 -1
  225. package/src/services/assets/browser-bundle.service.js +17 -5
  226. package/src/services/html/html-transformer.service.d.ts +1 -1
  227. package/src/services/html/html-transformer.service.js +4 -4
  228. package/src/services/invalidation/development-invalidation.service.d.ts +20 -2
  229. package/src/services/invalidation/development-invalidation.service.js +56 -2
  230. package/src/services/module-loading/README.md +49 -0
  231. package/src/services/module-loading/app-server-module-transpiler.service.js +5 -17
  232. package/src/services/module-loading/page-module-import.service.d.ts +5 -1
  233. package/src/services/module-loading/page-module-import.service.js +97 -45
  234. package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
  235. package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
  236. package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
  237. package/src/services/module-loading/route-module-build-cache.js +38 -0
  238. package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
  239. package/src/services/module-loading/route-module-build-cache.store.js +207 -0
  240. package/src/services/module-loading/route-module-build-manifest.d.ts +61 -0
  241. package/src/services/module-loading/route-module-build-manifest.js +116 -0
  242. package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
  243. package/src/services/module-loading/route-module-dependency-hasher.js +121 -0
  244. package/src/services/module-loading/server-module-transpiler.service.js +1 -1
  245. package/src/static-site-generator/README.md +33 -0
  246. package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
  247. package/src/static-site-generator/static-build-invalidation.js +59 -0
  248. package/src/static-site-generator/static-export-context.d.ts +22 -0
  249. package/src/static-site-generator/static-export-context.js +0 -0
  250. package/src/static-site-generator/static-site-generator.d.ts +17 -20
  251. package/src/static-site-generator/static-site-generator.js +188 -85
  252. package/src/types/internal-types.d.ts +16 -9
  253. package/src/types/public-types.d.ts +138 -26
  254. package/src/utils/parse-cli-args.d.ts +2 -0
  255. package/src/utils/parse-cli-args.js +6 -0
  256. package/src/utils/server-utils.module.d.ts +3 -2
  257. package/src/utils/server-utils.module.js +5 -6
  258. package/src/utils/static-file-extensions.d.ts +12 -0
  259. package/src/utils/static-file-extensions.js +48 -0
  260. package/src/watchers/project-watcher-ignore.d.ts +11 -0
  261. package/src/watchers/project-watcher-ignore.js +16 -0
  262. package/src/watchers/project-watcher.d.ts +25 -2
  263. package/src/watchers/project-watcher.js +130 -23
  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
@@ -0,0 +1,38 @@
1
+ import type { EcoPagesAppConfig } from '../../types/internal-types.js';
2
+ import type { IHmrManager } from '../../types/public-types.js';
3
+ import type { ProjectWatcher } from '../../watchers/project-watcher.js';
4
+ /**
5
+ * Copies source `public/` into dist and ensures the resolved assets directory exists.
6
+ */
7
+ export declare function prepareRuntimePublicDir(appConfig: EcoPagesAppConfig): void;
8
+ /**
9
+ * Propagates browser build plugins and the shared HMR manager into integrations.
10
+ */
11
+ export declare function wireIntegrationHmrManagers(appConfig: EcoPagesAppConfig, hmrManager: IHmrManager): void;
12
+ /**
13
+ * Injects the dev HMR runtime into adapter-level HTML responses when watch mode is active.
14
+ */
15
+ export declare function maybeInjectAdapterHmrHtmlResponse(response: Response, options: {
16
+ watch: boolean;
17
+ hmrManager?: Pick<IHmrManager, 'isEnabled'>;
18
+ hostOwnsDevClient: boolean;
19
+ }): Promise<Response>;
20
+ /**
21
+ * Releases shared dev resources in a consistent order across server adapters.
22
+ *
23
+ * @remarks
24
+ * Bun calls `buildRuntime()` during `initialize()` when watch is enabled; Node defers
25
+ * runtime creation to `completeInitialization()`. Transport-specific setup stays in
26
+ * each adapter — only shared teardown lives here.
27
+ */
28
+ export declare function disposeDevResources(options: {
29
+ projectWatcher: ProjectWatcher | null | undefined;
30
+ appConfig: EcoPagesAppConfig;
31
+ hmrManager: IHmrManager | null | undefined;
32
+ bridge: {
33
+ destroy(): void;
34
+ } | null | undefined;
35
+ previewHost: {
36
+ stop(): Promise<void>;
37
+ };
38
+ }): Promise<void>;
@@ -0,0 +1,43 @@
1
+ import path from "node:path";
2
+ import { fileSystem } from "@ecopages/file-system";
3
+ import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
4
+ import { disposeAppBuildRuntime } from "../../build/build-runtime.js";
5
+ import { getAppBrowserBuildPlugins } from "../../build/build-adapter.js";
6
+ import { copyRuntimePublicDirIfChanged } from "./copy-runtime-public-dir.js";
7
+ import { clearAppDevClientBridge } from "../../dev/client-bridge-registry.js";
8
+ import { clearAppHmrManager } from "../../dev/hmr-manager-registry.js";
9
+ import { injectHmrRuntimeIntoHtmlResponse, isHtmlResponse, shouldInjectHmrHtmlResponse } from "./hmr-html-response.js";
10
+ function prepareRuntimePublicDir(appConfig) {
11
+ const srcPublicDir = path.join(appConfig.rootDir, appConfig.srcDir, appConfig.publicDir);
12
+ if (fileSystem.exists(srcPublicDir)) {
13
+ copyRuntimePublicDirIfChanged(srcPublicDir, path.join(appConfig.rootDir, appConfig.distDir));
14
+ }
15
+ fileSystem.ensureDir(path.join(appConfig.absolutePaths.distDir, RESOLVED_ASSETS_DIR));
16
+ }
17
+ function wireIntegrationHmrManagers(appConfig, hmrManager) {
18
+ hmrManager.setPlugins(getAppBrowserBuildPlugins(appConfig));
19
+ for (const integration of appConfig.integrations) {
20
+ integration.setHmrManager(hmrManager);
21
+ }
22
+ }
23
+ async function maybeInjectAdapterHmrHtmlResponse(response, options) {
24
+ if (shouldInjectHmrHtmlResponse(options.watch, options.hmrManager, options.hostOwnsDevClient) && isHtmlResponse(response)) {
25
+ return injectHmrRuntimeIntoHtmlResponse(response);
26
+ }
27
+ return response;
28
+ }
29
+ async function disposeDevResources(options) {
30
+ await options.projectWatcher?.close();
31
+ await disposeAppBuildRuntime(options.appConfig);
32
+ options.hmrManager?.stop();
33
+ options.bridge?.destroy();
34
+ clearAppDevClientBridge(options.appConfig);
35
+ clearAppHmrManager(options.appConfig);
36
+ await options.previewHost.stop();
37
+ }
38
+ export {
39
+ disposeDevResources,
40
+ maybeInjectAdapterHmrHtmlResponse,
41
+ prepareRuntimePublicDir,
42
+ wireIntegrationHmrManagers
43
+ };
@@ -21,7 +21,8 @@ export declare abstract class SharedServerAdapter<TOptions extends ServerAdapter
21
21
  protected routeHandler: ServerRouteHandler;
22
22
  protected staticSiteGenerator: StaticSiteGenerator;
23
23
  protected staticBuilder: ServerStaticBuilder;
24
- protected readonly schemaValidator: SchemaValidationService;
24
+ protected schemaValidator: SchemaValidationService;
25
+ protected hostOwnsDevClient: boolean;
25
26
  protected initializeSharedRouteHandling(options: {
26
27
  staticRoutes: StaticRoute[];
27
28
  hmrManager?: any;
@@ -27,6 +27,7 @@ class SharedServerAdapter extends AbstractServerAdapter {
27
27
  staticSiteGenerator;
28
28
  staticBuilder;
29
29
  schemaValidator = new SchemaValidationService();
30
+ hostOwnsDevClient = false;
30
31
  async initializeSharedRouteHandling(options) {
31
32
  await this.initSharedRouter();
32
33
  this.configureSharedResponseHandlers(options.staticRoutes, options.hmrManager);
@@ -76,7 +77,7 @@ class SharedServerAdapter extends AbstractServerAdapter {
76
77
  const module = await serverModuleTranspiler.importModule({
77
78
  filePath,
78
79
  outdir: path.join(resolveInternalExecutionDir(this.appConfig), ".server-route-modules"),
79
- externalPackages: false,
80
+ externalPackages: true,
80
81
  transpileErrorMessage: (details) => `Error transpiling route module: ${details}`,
81
82
  noOutputMessage: (targetFilePath) => `No transpiled output generated for route module: ${targetFilePath}`
82
83
  });
@@ -115,7 +116,8 @@ class SharedServerAdapter extends AbstractServerAdapter {
115
116
  fileSystemResponseMatcher: this.fileSystemResponseMatcher,
116
117
  explicitStaticRouteMatcher,
117
118
  watch: !!this.options?.watch,
118
- hmrManager
119
+ hmrManager,
120
+ hostOwnsDevClient: this.hostOwnsDevClient
119
121
  });
120
122
  }
121
123
  createSharedResponseHandlerDependencies(staticRoutes) {
@@ -164,8 +166,7 @@ class SharedServerAdapter extends AbstractServerAdapter {
164
166
  importServerModule: async (filePath) => await serverModuleTranspiler.importModule({
165
167
  filePath,
166
168
  outdir: path.join(resolveInternalExecutionDir(this.appConfig), ".server-modules"),
167
- externalPackages: true,
168
- bypassCache: this.options?.watch === true
169
+ externalPackages: true
169
170
  })
170
171
  });
171
172
  }
@@ -380,7 +381,10 @@ class SharedServerAdapter extends AbstractServerAdapter {
380
381
  const runtimePath = context.hmrManager.getRuntimePath();
381
382
  if (fileSystem.exists(runtimePath)) {
382
383
  return new Response(fileSystem.readFileAsBuffer(runtimePath), {
383
- headers: { "Content-Type": "application/javascript" }
384
+ headers: {
385
+ "Content-Type": "application/javascript",
386
+ "Cache-Control": "no-store, must-revalidate"
387
+ }
384
388
  });
385
389
  }
386
390
  }
@@ -389,7 +393,10 @@ class SharedServerAdapter extends AbstractServerAdapter {
389
393
  const assetPath = path.join(context.hmrManager.getDistDir(), relativePath);
390
394
  if (fileSystem.exists(assetPath)) {
391
395
  return new Response(fileSystem.readFileAsBuffer(assetPath), {
392
- headers: { "Content-Type": "application/javascript" }
396
+ headers: {
397
+ "Content-Type": "application/javascript",
398
+ "Cache-Control": "no-store, must-revalidate"
399
+ }
393
400
  });
394
401
  }
395
402
  }
@@ -16,6 +16,8 @@ export interface ServerRouteHandlerParams {
16
16
  watch?: boolean;
17
17
  /** HMR manager for broadcasting hot module reload events in development. */
18
18
  hmrManager?: IHmrManager;
19
+ /** When true, the host dev server owns browser dev-client bootstrap. */
20
+ hostOwnsDevClient?: boolean;
19
21
  }
20
22
  /**
21
23
  * Handles HTTP requests and routing for the server.
@@ -33,12 +35,13 @@ export declare class ServerRouteHandler {
33
35
  private readonly explicitStaticRouteMatcher?;
34
36
  private readonly watch;
35
37
  private readonly hmrManager?;
38
+ private readonly hostOwnsDevClient;
36
39
  /**
37
40
  * Creates a new ServerRouteHandler instance.
38
41
  *
39
42
  * @param params - Configuration parameters
40
43
  */
41
- constructor({ router, fileSystemResponseMatcher, explicitStaticRouteMatcher, watch, hmrManager, }: ServerRouteHandlerParams);
44
+ constructor({ router, fileSystemResponseMatcher, explicitStaticRouteMatcher, watch, hmrManager, hostOwnsDevClient, }: ServerRouteHandlerParams);
42
45
  /**
43
46
  * Determines if HMR script should be injected.
44
47
  *
@@ -7,6 +7,7 @@ class ServerRouteHandler {
7
7
  explicitStaticRouteMatcher;
8
8
  watch;
9
9
  hmrManager;
10
+ hostOwnsDevClient;
10
11
  /**
11
12
  * Creates a new ServerRouteHandler instance.
12
13
  *
@@ -17,13 +18,15 @@ class ServerRouteHandler {
17
18
  fileSystemResponseMatcher,
18
19
  explicitStaticRouteMatcher,
19
20
  watch = false,
20
- hmrManager
21
+ hmrManager,
22
+ hostOwnsDevClient = false
21
23
  }) {
22
24
  this.router = router;
23
25
  this.fileSystemResponseMatcher = fileSystemResponseMatcher;
24
26
  this.explicitStaticRouteMatcher = explicitStaticRouteMatcher;
25
27
  this.watch = watch;
26
28
  this.hmrManager = hmrManager;
29
+ this.hostOwnsDevClient = hostOwnsDevClient;
27
30
  }
28
31
  /**
29
32
  * Determines if HMR script should be injected.
@@ -31,7 +34,7 @@ class ServerRouteHandler {
31
34
  * @returns true if in watch mode and HMR manager is enabled
32
35
  */
33
36
  shouldInjectHmrScript() {
34
- return shouldInjectHmrHtmlResponse(this.watch, this.hmrManager);
37
+ return shouldInjectHmrHtmlResponse(this.watch, this.hmrManager, this.hostOwnsDevClient);
35
38
  }
36
39
  /**
37
40
  * Checks if a response contains HTML content.
@@ -1,11 +1,12 @@
1
- import type { EcoPagesAppConfig } from '../../types/internal-types.js';
2
- import type { ApiHandler, StaticRoute } from '../../types/public-types.js';
1
+ import type { EcoPagesAppConfig, IHmrManager } from '../../types/internal-types.js';
2
+ import type { EcoBuildPlugin } from '../../build/build-types.js';
3
+ import type { StaticRoute } from '../../types/public-types.js';
3
4
  import type { RouteRegistry } from '../../router/server/route-registry.js';
4
5
  import type { StaticSiteGenerator } from '../../static-site-generator/static-site-generator.js';
5
6
  import type { StaticGenerationRendererResolver } from '../../route-renderer/route-renderer.js';
6
7
  export interface StaticBuildOptions {
7
- preview?: boolean;
8
8
  baseUrl?: string;
9
+ force?: boolean;
9
10
  }
10
11
  export interface ServeOptions {
11
12
  hostname?: string;
@@ -15,10 +16,17 @@ export interface ServerStaticBuilderParams {
15
16
  appConfig: EcoPagesAppConfig;
16
17
  staticSiteGenerator: StaticSiteGenerator;
17
18
  serveOptions: ServeOptions;
18
- apiHandlers?: ApiHandler[];
19
+ runtimeOrigin: string;
20
+ /**
21
+ * Whether the app requires a server entry bundle for production use.
22
+ * When `true`, the build step bundles the server entry file for `ecopages start`.
23
+ * Defaults to `false` (static-only build, no server needed).
24
+ */
25
+ needsServerBundle?: boolean;
19
26
  logger?: ServerStaticBuilderLogger;
20
- previewServerFactory?: ServerStaticPreviewServerFactory;
21
27
  entryFile?: string;
28
+ hmrManager?: IHmrManager;
29
+ onRuntimePlugin?: (plugin: EcoBuildPlugin) => void;
22
30
  }
23
31
  /**
24
32
  * Minimal logger dependency used by the static builder.
@@ -29,50 +37,34 @@ export interface ServerStaticBuilderLogger {
29
37
  error(message: string): unknown;
30
38
  }
31
39
  /**
32
- * Preview server factory dependency used when static preview mode is enabled.
33
- */
34
- export interface ServerStaticPreviewServerFactory {
35
- createServer(args: {
36
- appConfig: EcoPagesAppConfig;
37
- options: {
38
- port: number;
39
- };
40
- }): {
41
- server?: {
42
- port?: number;
43
- } | null;
44
- };
45
- }
46
- /**
47
- * Handles static site generation and previews.
40
+ * Handles static site generation.
48
41
  */
49
42
  export declare class ServerStaticBuilder {
50
43
  private readonly appConfig;
51
44
  private readonly staticSiteGenerator;
52
45
  private readonly serveOptions;
53
- private readonly apiHandlers;
46
+ private readonly runtimeOrigin;
47
+ private readonly needsServerBundle;
54
48
  private readonly logger;
55
- private readonly previewServerFactory;
56
49
  private readonly entryFile;
57
- constructor({ appConfig, staticSiteGenerator, serveOptions, apiHandlers, logger, previewServerFactory, entryFile, }: ServerStaticBuilderParams);
58
- private warnApiHandlersUnavailableInStaticMode;
50
+ private readonly hmrManager?;
51
+ private readonly onRuntimePlugin?;
52
+ constructor({ appConfig, staticSiteGenerator, serveOptions, runtimeOrigin, needsServerBundle, logger, entryFile, hmrManager, onRuntimePlugin, }: ServerStaticBuilderParams);
59
53
  private prepareExportDirectory;
60
54
  private refreshRuntimeAssets;
61
55
  /**
62
56
  * Bundles the server entry file for production use.
63
57
  *
64
58
  * @remarks
65
- * When the project has API endpoints, the entry file must be bundled
66
- * into a single JS file so the production server can start without
67
- * on-the-fly TypeScript transpilation. The bundle is output to
68
- * `dist/{SERVER_BUNDLE_DIR}/{SERVER_BUNDLE_FILENAME}` and used by
69
- * `ecopages start` in production.
59
+ * Only invoked when the app requires a runtime server (API handlers,
60
+ * websocket handlers, etc.). Static-only apps skip this step entirely.
61
+ * Incremental builds may skip Rolldown when the `.eco/.server-entry`
62
+ * cache is still valid.
70
63
  *
71
64
  * Package imports remain external so native addons and runtime-owned
72
65
  * dependencies continue to load through the app's installed
73
66
  * `node_modules` tree. Only the app entry graph is bundled.
74
67
  *
75
- * Skips silently when no API endpoints are registered (static-only site).
76
68
  * Throws if the build adapter is unavailable, is owned by a host
77
69
  * runtime, or bundling fails.
78
70
  *
@@ -81,7 +73,6 @@ export declare class ServerStaticBuilder {
81
73
  private bundleServerEntry;
82
74
  /**
83
75
  * Generates a static build of the site for deployment.
84
- * @param options.preview - If true, starts a preview server after build
85
76
  * @param dependencies.router - The initialized router
86
77
  * @param dependencies.routeRendererFactory - The route renderer factory
87
78
  * @param dependencies.staticRoutes - Explicit static routes registered via app.static()
@@ -1,53 +1,65 @@
1
1
  import path from "node:path";
2
2
  import { fileSystem } from "@ecopages/file-system";
3
3
  import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT } from "../../config/constants.js";
4
- import { StaticContentServer } from "../../dev/sc-server.js";
5
4
  import { appLogger } from "../../global/app-logger.js";
6
- import { getAppBuildAdapter } from "../../build/build-adapter.js";
7
- import { resolveEntryFile, SERVER_BUNDLE_DIR, SERVER_BUNDLE_FILENAME } from "../../utils/resolve-entry-file.js";
5
+ import { build, getAppBuildAdapter, setupAppRuntimePlugins } from "../../build/build-adapter.js";
6
+ import { resolveBuildProfileOptions } from "../../build/build-profile-options.js";
7
+ import {
8
+ getServerBundleOutputPaths,
9
+ lookupServerEntryBuildCache,
10
+ recordServerEntryBuildCache,
11
+ writeServerBundleDeployManifest
12
+ } from "../../build/server-entry-build-cache.js";
13
+ import { getInstalledServerEntryBuildExecutor } from "../../build/runtime-build-executor.js";
14
+ import {
15
+ clearProductionBuildCaches,
16
+ shouldResetStaticExportDirectory
17
+ } from "../../static-site-generator/static-build-invalidation.js";
18
+ import { resolveEntryFile, SERVER_BUNDLE_FILENAME } from "../../utils/resolve-entry-file.js";
8
19
  class ServerStaticBuilder {
9
20
  appConfig;
10
21
  staticSiteGenerator;
11
22
  serveOptions;
12
- apiHandlers;
23
+ runtimeOrigin;
24
+ needsServerBundle;
13
25
  logger;
14
- previewServerFactory;
15
26
  entryFile;
27
+ hmrManager;
28
+ onRuntimePlugin;
16
29
  constructor({
17
30
  appConfig,
18
31
  staticSiteGenerator,
19
32
  serveOptions,
20
- apiHandlers,
33
+ runtimeOrigin,
34
+ needsServerBundle,
21
35
  logger,
22
- previewServerFactory,
23
- entryFile
36
+ entryFile,
37
+ hmrManager,
38
+ onRuntimePlugin
24
39
  }) {
25
40
  this.appConfig = appConfig;
26
41
  this.staticSiteGenerator = staticSiteGenerator;
27
42
  this.serveOptions = serveOptions;
28
- this.apiHandlers = apiHandlers ?? [];
43
+ this.runtimeOrigin = runtimeOrigin;
44
+ this.needsServerBundle = needsServerBundle ?? false;
29
45
  this.logger = logger ?? appLogger;
30
- this.previewServerFactory = previewServerFactory ?? StaticContentServer;
31
46
  this.entryFile = resolveEntryFile({ entryFile });
47
+ this.hmrManager = hmrManager;
48
+ this.onRuntimePlugin = onRuntimePlugin;
32
49
  }
33
- warnApiHandlersUnavailableInStaticMode() {
34
- if (this.apiHandlers.length === 0) {
35
- return;
50
+ prepareExportDirectory(force) {
51
+ if (force) {
52
+ clearProductionBuildCaches(this.appConfig);
36
53
  }
37
- const uniqueHandlers = Array.from(
38
- new Set(this.apiHandlers.map((handler) => `${handler.method} ${handler.path}`))
39
- );
40
- const visibleHandlers = uniqueHandlers.slice(0, 5).join(", ");
41
- const remainingCount = uniqueHandlers.length - Math.min(uniqueHandlers.length, 5);
42
- const summary = remainingCount > 0 ? `${visibleHandlers}, +${remainingCount} more` : visibleHandlers;
43
- this.logger.warn(
44
- "Registered API endpoints are not available in static build or preview modes because no server runtime is started. They are excluded from the generated output.\n",
45
- `\u27A4 ${summary}`
46
- );
47
- }
48
- prepareExportDirectory() {
49
54
  const exportDir = this.appConfig.absolutePaths?.distDir ?? path.join(this.appConfig.rootDir, this.appConfig.distDir);
50
- fileSystem.ensureDir(exportDir, true);
55
+ const shouldCleanDist = shouldResetStaticExportDirectory(this.appConfig, force);
56
+ fileSystem.ensureDir(exportDir, shouldCleanDist);
57
+ if (shouldCleanDist) {
58
+ this.appConfig.runtime = {
59
+ ...this.appConfig.runtime ?? {},
60
+ runtimeAssetsPrepared: false
61
+ };
62
+ }
51
63
  const srcPublicDir = path.join(
52
64
  this.appConfig.rootDir,
53
65
  this.appConfig.srcDir ?? "src",
@@ -56,39 +68,40 @@ class ServerStaticBuilder {
56
68
  if (fileSystem.exists(srcPublicDir)) {
57
69
  fileSystem.copyDir(srcPublicDir, exportDir);
58
70
  }
71
+ return !shouldCleanDist;
59
72
  }
60
73
  async refreshRuntimeAssets() {
61
- for (const processor of this.appConfig.processors.values()) {
62
- await processor.setup();
63
- }
64
- for (const integration of this.appConfig.integrations) {
65
- await integration.setup();
74
+ appLogger.debugTime("refreshRuntimeAssets");
75
+ try {
76
+ await setupAppRuntimePlugins({
77
+ appConfig: this.appConfig,
78
+ runtimeOrigin: this.runtimeOrigin,
79
+ hmrManager: this.hmrManager,
80
+ onRuntimePlugin: this.onRuntimePlugin
81
+ });
82
+ } finally {
83
+ appLogger.debugTimeEnd("refreshRuntimeAssets");
66
84
  }
67
85
  }
68
86
  /**
69
87
  * Bundles the server entry file for production use.
70
88
  *
71
89
  * @remarks
72
- * When the project has API endpoints, the entry file must be bundled
73
- * into a single JS file so the production server can start without
74
- * on-the-fly TypeScript transpilation. The bundle is output to
75
- * `dist/{SERVER_BUNDLE_DIR}/{SERVER_BUNDLE_FILENAME}` and used by
76
- * `ecopages start` in production.
90
+ * Only invoked when the app requires a runtime server (API handlers,
91
+ * websocket handlers, etc.). Static-only apps skip this step entirely.
92
+ * Incremental builds may skip Rolldown when the `.eco/.server-entry`
93
+ * cache is still valid.
77
94
  *
78
95
  * Package imports remain external so native addons and runtime-owned
79
96
  * dependencies continue to load through the app's installed
80
97
  * `node_modules` tree. Only the app entry graph is bundled.
81
98
  *
82
- * Skips silently when no API endpoints are registered (static-only site).
83
99
  * Throws if the build adapter is unavailable, is owned by a host
84
100
  * runtime, or bundling fails.
85
101
  *
86
102
  * @throws If the build adapter is unavailable, is host-owned, or bundling fails.
87
103
  */
88
- async bundleServerEntry() {
89
- if (this.apiHandlers.length === 0) {
90
- return;
91
- }
104
+ async bundleServerEntry(options) {
92
105
  const buildAdapter = getAppBuildAdapter(this.appConfig);
93
106
  if (buildAdapter.ownership === "vite-host") {
94
107
  throw new Error(
@@ -101,60 +114,71 @@ class ServerStaticBuilder {
101
114
  `Cannot bundle server entry: file "${this.entryFile}" not found in "${this.appConfig.rootDir}".`
102
115
  );
103
116
  }
104
- const distDir = this.appConfig.absolutePaths?.distDir ?? path.join(this.appConfig.rootDir, this.appConfig.distDir);
105
- const serverOutdir = path.join(distDir, SERVER_BUNDLE_DIR);
106
- this.logger.info("Bundling server entry file...");
107
- const result = await buildAdapter.build({
108
- entrypoints: [entryPath],
109
- outdir: serverOutdir,
110
- naming: SERVER_BUNDLE_FILENAME,
111
- target: "node",
112
- format: "esm",
113
- sourcemap: "hidden",
114
- externalPackages: true,
115
- root: this.appConfig.rootDir
117
+ const { serverOutdir, serverEntryPath } = getServerBundleOutputPaths(this.appConfig);
118
+ const cached = lookupServerEntryBuildCache({
119
+ appConfig: this.appConfig,
120
+ entryPath,
121
+ force: options?.force
116
122
  });
123
+ if (cached) {
124
+ const hasBundle = cached.outputPaths.some(
125
+ (outputPath) => path.resolve(outputPath) === path.resolve(serverEntryPath) && fileSystem.exists(outputPath)
126
+ );
127
+ if (hasBundle) {
128
+ this.logger.info("Reusing cached server entry bundle");
129
+ writeServerBundleDeployManifest(this.appConfig, serverEntryPath);
130
+ return;
131
+ }
132
+ }
133
+ this.logger.info("Bundling server entry file...");
134
+ const buildOptions = {
135
+ ...resolveBuildProfileOptions("server-entry", this.appConfig, {
136
+ entrypoints: [entryPath],
137
+ outdir: serverOutdir,
138
+ naming: SERVER_BUNDLE_FILENAME,
139
+ sourcemap: "hidden"
140
+ }),
141
+ entrypoints: [entryPath]
142
+ };
143
+ const result = await build(buildOptions, getInstalledServerEntryBuildExecutor(this.appConfig));
117
144
  if (!result.success) {
118
145
  const errorMessages = result.logs.map((log) => log.message).join("\n");
119
146
  throw new Error(`Failed to bundle server entry file:
120
147
  ${errorMessages}`);
121
148
  }
149
+ const outputPaths = result.outputs.length > 0 ? result.outputs.map((output) => output.path) : fileSystem.exists(serverEntryPath) ? [serverEntryPath] : [];
150
+ recordServerEntryBuildCache({
151
+ appConfig: this.appConfig,
152
+ entryPath,
153
+ buildResult: result,
154
+ outputPaths
155
+ });
156
+ writeServerBundleDeployManifest(this.appConfig, serverEntryPath);
122
157
  this.logger.info("Server entry file bundled successfully");
123
158
  }
124
159
  /**
125
160
  * Generates a static build of the site for deployment.
126
- * @param options.preview - If true, starts a preview server after build
127
161
  * @param dependencies.router - The initialized router
128
162
  * @param dependencies.routeRendererFactory - The route renderer factory
129
163
  * @param dependencies.staticRoutes - Explicit static routes registered via app.static()
130
164
  */
131
165
  async build(options, dependencies) {
132
- const { preview = false, baseUrl: explicitBaseUrl } = options ?? {};
166
+ const { baseUrl: explicitBaseUrl, force = false } = options ?? {};
133
167
  const baseUrl = explicitBaseUrl ?? `http://${this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME}:${this.serveOptions.port || DEFAULT_ECOPAGES_PORT}`;
134
- this.warnApiHandlersUnavailableInStaticMode();
135
- this.prepareExportDirectory();
168
+ const preserveExportDirectory = this.prepareExportDirectory(force);
136
169
  await this.refreshRuntimeAssets();
137
- await this.bundleServerEntry();
170
+ if (this.needsServerBundle) {
171
+ await this.bundleServerEntry({ force });
172
+ }
138
173
  await this.staticSiteGenerator.run({
139
174
  router: dependencies.router,
140
175
  baseUrl,
141
176
  routeRendererFactory: dependencies.routeRendererFactory,
142
- staticRoutes: dependencies.staticRoutes
177
+ staticRoutes: dependencies.staticRoutes,
178
+ force,
179
+ preserveExportDirectory
143
180
  });
144
- if (!preview) {
145
- this.logger.info("Build completed");
146
- return;
147
- }
148
- const previewPort = this.serveOptions.port || DEFAULT_ECOPAGES_PORT;
149
- const { server } = this.previewServerFactory.createServer({
150
- appConfig: this.appConfig,
151
- options: { port: Number(previewPort) }
152
- });
153
- if (server?.port) {
154
- this.logger.info(`Preview running at http://localhost:${server.port}`);
155
- } else {
156
- this.logger.error("Failed to start preview server");
157
- }
181
+ this.logger.info("Build completed");
158
182
  }
159
183
  }
160
184
  export {
@@ -10,6 +10,7 @@ import type { ServerModuleTranspiler } from '../../services/module-loading/serve
10
10
  type HandleFileChangeOptions = {
11
11
  broadcast?: boolean;
12
12
  };
13
+ export declare function resolveHmrRegistrationTimeoutMs(explicitTimeoutMs?: number): number;
13
14
  type SharedHmrManagerParams = {
14
15
  appConfig: EcoPagesAppConfig;
15
16
  bridge: IClientBridge;
@@ -29,6 +30,7 @@ export declare abstract class SharedHmrManager implements IHmrManager {
29
30
  protected readonly browserBundleService: BrowserBundleService;
30
31
  protected readonly entrypointDependencyGraph: EntrypointDependencyGraph;
31
32
  protected readonly serverModuleTranspiler: ServerModuleTranspiler;
33
+ private runtimeBuildPromise;
32
34
  constructor({ appConfig, bridge, registrationTimeoutMs }: SharedHmrManagerParams);
33
35
  protected abstract createEntrypointDependencyGraph(existingEntrypointDependencyGraph: EntrypointDependencyGraph): EntrypointDependencyGraph;
34
36
  protected shouldSkipMissingFileChange(_filePath: string): boolean;
@@ -40,11 +42,36 @@ export declare abstract class SharedHmrManager implements IHmrManager {
40
42
  setPlugins(plugins: EcoBuildPlugin[]): void;
41
43
  setEnabled(enabled: boolean): void;
42
44
  isEnabled(): boolean;
45
+ isRuntimeReady(): boolean;
46
+ /**
47
+ * Builds the browser HMR runtime once and reuses the in-flight build for concurrent callers.
48
+ */
49
+ ensureRuntimeReady(): Promise<boolean>;
43
50
  buildRuntime(): Promise<void>;
44
51
  getRuntimePath(): string;
52
+ private buildRuntimeInternal;
53
+ /**
54
+ * @remarks
55
+ * Rolldown may emit the runtime bundle under a derived filename when the
56
+ * entrypoint lives outside the app root. The dev server always serves
57
+ * `/_hmr_runtime.js` from a stable path under `.eco/assets/_hmr/`.
58
+ */
59
+ private syncRuntimeOutput;
45
60
  broadcast(event: ClientBridgeEvent): void;
46
61
  handleFileChange(filePath: string, options?: HandleFileChangeOptions): Promise<void>;
47
62
  getOutputUrl(entrypointPath: string): string | undefined;
63
+ /**
64
+ * Returns the emitted HMR script output when the entrypoint is already registered
65
+ * and its browser bundle exists on disk.
66
+ *
67
+ * @remarks
68
+ * Disk artifacts alone are not enough: a fresh dev session must still register
69
+ * the entrypoint so file watchers can rebuild it on change.
70
+ */
71
+ getResolvedScriptOutput(entrypointPath: string): {
72
+ outputUrl: string;
73
+ outputPath: string;
74
+ } | undefined;
48
75
  getWatchedFiles(): Map<string, string>;
49
76
  getDistDir(): string;
50
77
  getPlugins(): EcoBuildPlugin[];
@@ -55,5 +82,6 @@ export declare abstract class SharedHmrManager implements IHmrManager {
55
82
  protected emitStrictEntrypoint(entrypointPath: string): Promise<void>;
56
83
  protected emitScriptEntrypoint(entrypointPath: string, outputPath: string): Promise<void>;
57
84
  stop(): void;
85
+ [Symbol.dispose](): void;
58
86
  }
59
87
  export {};