@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
@@ -2,11 +2,14 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
5
- import { getAppBuildExecutor } from "../../build/build-adapter.js";
5
+ import { resolveHmrEntrypointOutputPaths } from "../../hmr/hmr-entrypoint-output.js";
6
+ import { requireBuildRuntime } from "../../build/build-runtime.js";
6
7
  import { fileSystem } from "@ecopages/file-system";
7
8
  import { HmrStrategyType } from "../../hmr/hmr-strategy.js";
8
9
  import { DefaultHmrStrategy } from "../../hmr/strategies/default-hmr-strategy.js";
9
10
  import { JsHmrStrategy } from "../../hmr/strategies/js-hmr-strategy.js";
11
+ import { ServerRenderedTemplateHmrStrategy } from "../../hmr/strategies/server-rendered-template-hmr-strategy.js";
12
+ import { DevelopmentInvalidationService } from "../../services/invalidation/development-invalidation.service.js";
10
13
  import { appLogger } from "../../global/app-logger.js";
11
14
  import { HmrEntrypointRegistrar } from "./hmr-entrypoint-registrar.js";
12
15
  import { BrowserBundleService } from "../../services/assets/browser-bundle.service.js";
@@ -16,6 +19,24 @@ import {
16
19
  setAppEntrypointDependencyGraph
17
20
  } from "../../services/runtime-state/entrypoint-dependency-graph.service.js";
18
21
  import { resolveInternalExecutionDir, resolveInternalWorkDir } from "../../utils/resolve-work-dir.js";
22
+ const DEFAULT_HMR_REGISTRATION_TIMEOUT_MS = 4e3;
23
+ const DEVELOPMENT_HMR_REGISTRATION_TIMEOUT_MS = 15e3;
24
+ function resolveHmrRegistrationTimeoutMs(explicitTimeoutMs) {
25
+ if (explicitTimeoutMs !== void 0) {
26
+ return explicitTimeoutMs;
27
+ }
28
+ const envTimeoutMs = process.env.ECOPAGES_HMR_REGISTRATION_TIMEOUT_MS;
29
+ if (envTimeoutMs !== void 0 && envTimeoutMs !== "") {
30
+ const parsedTimeoutMs = Number(envTimeoutMs);
31
+ if (Number.isFinite(parsedTimeoutMs) && parsedTimeoutMs > 0) {
32
+ return parsedTimeoutMs;
33
+ }
34
+ }
35
+ if (process.env.NODE_ENV === "development") {
36
+ return DEVELOPMENT_HMR_REGISTRATION_TIMEOUT_MS;
37
+ }
38
+ return DEFAULT_HMR_REGISTRATION_TIMEOUT_MS;
39
+ }
19
40
  class SharedHmrManager {
20
41
  appConfig;
21
42
  bridge;
@@ -24,13 +45,14 @@ class SharedHmrManager {
24
45
  entrypointRegistrations = /* @__PURE__ */ new Map();
25
46
  distDir;
26
47
  plugins = [];
27
- enabled = true;
48
+ enabled = false;
28
49
  strategies = [];
29
50
  entrypointRegistrar;
30
51
  browserBundleService;
31
52
  entrypointDependencyGraph;
32
53
  serverModuleTranspiler;
33
- constructor({ appConfig, bridge, registrationTimeoutMs = 4e3 }) {
54
+ runtimeBuildPromise = null;
55
+ constructor({ appConfig, bridge, registrationTimeoutMs }) {
34
56
  this.appConfig = appConfig;
35
57
  this.bridge = bridge;
36
58
  this.distDir = path.join(resolveInternalWorkDir(this.appConfig), RESOLVED_ASSETS_DIR, "_hmr");
@@ -40,7 +62,7 @@ class SharedHmrManager {
40
62
  entrypointRegistrations: this.entrypointRegistrations,
41
63
  watchedFiles: this.watchedFiles,
42
64
  clearFailedRegistration: (entrypointPath) => this.clearFailedEntrypointRegistration(entrypointPath),
43
- registrationTimeoutMs
65
+ registrationTimeoutMs: resolveHmrRegistrationTimeoutMs(registrationTimeoutMs)
44
66
  });
45
67
  this.browserBundleService = new BrowserBundleService(appConfig);
46
68
  this.entrypointDependencyGraph = this.createEntrypointDependencyGraph(
@@ -86,7 +108,12 @@ class SharedHmrManager {
86
108
  getEntrypointDependencyGraph: () => this.entrypointDependencyGraph,
87
109
  shouldProcessEntrypoint: (entrypointPath) => this.shouldJsStrategyProcessEntrypoint(entrypointPath)
88
110
  };
89
- this.strategies = [new JsHmrStrategy(jsContext), new DefaultHmrStrategy()];
111
+ const invalidationService = new DevelopmentInvalidationService(this.appConfig);
112
+ this.strategies = [
113
+ new JsHmrStrategy(jsContext),
114
+ new ServerRenderedTemplateHmrStrategy(invalidationService),
115
+ new DefaultHmrStrategy()
116
+ ];
90
117
  }
91
118
  registerStrategy(strategy) {
92
119
  this.strategies.push(strategy);
@@ -100,7 +127,33 @@ class SharedHmrManager {
100
127
  isEnabled() {
101
128
  return this.enabled;
102
129
  }
130
+ isRuntimeReady() {
131
+ return fileSystem.exists(this.getRuntimePath());
132
+ }
133
+ /**
134
+ * Builds the browser HMR runtime once and reuses the in-flight build for concurrent callers.
135
+ */
136
+ async ensureRuntimeReady() {
137
+ if (this.isRuntimeReady()) {
138
+ return true;
139
+ }
140
+ if (this.runtimeBuildPromise) {
141
+ return this.runtimeBuildPromise;
142
+ }
143
+ this.runtimeBuildPromise = this.buildRuntimeInternal();
144
+ try {
145
+ return await this.runtimeBuildPromise;
146
+ } finally {
147
+ this.runtimeBuildPromise = null;
148
+ }
149
+ }
103
150
  async buildRuntime() {
151
+ await this.ensureRuntimeReady();
152
+ }
153
+ getRuntimePath() {
154
+ return path.join(this.distDir, "_hmr_runtime.js");
155
+ }
156
+ async buildRuntimeInternal() {
104
157
  const runtimeSource = fileURLToPath(import.meta.resolve("@ecopages/core/hmr/client/hmr-runtime"));
105
158
  try {
106
159
  const result = await this.browserBundleService.bundle({
@@ -113,13 +166,32 @@ class SharedHmrManager {
113
166
  });
114
167
  if (!result.success) {
115
168
  this.onRuntimeBundleFailure(result.logs);
169
+ return false;
116
170
  }
171
+ this.syncRuntimeOutput(result);
172
+ return this.isRuntimeReady();
117
173
  } catch (error) {
118
174
  this.onRuntimeBundleFailure(error);
175
+ return false;
119
176
  }
120
177
  }
121
- getRuntimePath() {
122
- return path.join(this.distDir, "_hmr_runtime.js");
178
+ /**
179
+ * @remarks
180
+ * Rolldown may emit the runtime bundle under a derived filename when the
181
+ * entrypoint lives outside the app root. The dev server always serves
182
+ * `/_hmr_runtime.js` from a stable path under `.eco/assets/_hmr/`.
183
+ */
184
+ syncRuntimeOutput(result) {
185
+ const runtimePath = this.getRuntimePath();
186
+ if (fileSystem.exists(runtimePath)) {
187
+ return;
188
+ }
189
+ const emittedRuntime = result.outputs.find((output) => output.path.endsWith(".js"));
190
+ if (!emittedRuntime || emittedRuntime.path === runtimePath) {
191
+ return;
192
+ }
193
+ fileSystem.ensureDir(path.dirname(runtimePath));
194
+ fileSystem.copyFile(emittedRuntime.path, runtimePath);
123
195
  }
124
196
  broadcast(event) {
125
197
  appLogger.debug(
@@ -158,6 +230,30 @@ class SharedHmrManager {
158
230
  getOutputUrl(entrypointPath) {
159
231
  return this.watchedFiles.get(entrypointPath);
160
232
  }
233
+ /**
234
+ * Returns the emitted HMR script output when the entrypoint is already registered
235
+ * and its browser bundle exists on disk.
236
+ *
237
+ * @remarks
238
+ * Disk artifacts alone are not enough: a fresh dev session must still register
239
+ * the entrypoint so file watchers can rebuild it on change.
240
+ */
241
+ getResolvedScriptOutput(entrypointPath) {
242
+ const normalizedEntrypoint = path.resolve(entrypointPath);
243
+ if (!this.watchedFiles.has(normalizedEntrypoint)) {
244
+ return void 0;
245
+ }
246
+ const { outputPath, outputUrl: derivedOutputUrl } = resolveHmrEntrypointOutputPaths(
247
+ this.appConfig.absolutePaths.srcDir,
248
+ this.distDir,
249
+ normalizedEntrypoint
250
+ );
251
+ if (!fileSystem.exists(outputPath)) {
252
+ return void 0;
253
+ }
254
+ const outputUrl = this.watchedFiles.get(normalizedEntrypoint) ?? derivedOutputUrl;
255
+ return { outputUrl, outputPath };
256
+ }
161
257
  getWatchedFiles() {
162
258
  return this.watchedFiles;
163
259
  }
@@ -175,7 +271,7 @@ class SharedHmrManager {
175
271
  getSrcDir: () => this.appConfig.absolutePaths.srcDir,
176
272
  getLayoutsDir: () => this.appConfig.absolutePaths.layoutsDir,
177
273
  getPagesDir: () => this.appConfig.absolutePaths.pagesDir,
178
- getBuildExecutor: () => getAppBuildExecutor(this.appConfig),
274
+ getBuildExecutor: () => requireBuildRuntime(this.appConfig).getProfile("browser-hmr"),
179
275
  getBrowserBundleService: () => this.browserBundleService,
180
276
  getEntrypointDependencyGraph: () => this.entrypointDependencyGraph,
181
277
  importServerModule: async (filePath) => await this.serverModuleTranspiler.importModule({
@@ -220,6 +316,16 @@ class SharedHmrManager {
220
316
  appLogger.error(`[HMR] Generic script entrypoint build failed for ${entrypointPath}:`, buildResult.logs);
221
317
  return;
222
318
  }
319
+ if (!fileSystem.exists(outputPath) && buildResult.outputs.length > 0) {
320
+ const resolvedOutputPath = path.resolve(outputPath);
321
+ const emittedOutput = buildResult.outputs.find((output) => path.resolve(output.path) === resolvedOutputPath)?.path ?? buildResult.outputs.find((output) => path.basename(output.path) === path.basename(outputPath))?.path;
322
+ if (emittedOutput && fileSystem.exists(emittedOutput)) {
323
+ fileSystem.ensureDir(path.dirname(outputPath));
324
+ if (path.resolve(emittedOutput) !== resolvedOutputPath) {
325
+ fileSystem.copyFile(emittedOutput, outputPath);
326
+ }
327
+ }
328
+ }
223
329
  const entrypointDependencies = buildResult.dependencyGraph?.entrypoints?.[entrypointPath];
224
330
  if (entrypointDependencies) {
225
331
  this.entrypointDependencyGraph.setEntrypointDependencies(entrypointPath, entrypointDependencies);
@@ -235,7 +341,11 @@ class SharedHmrManager {
235
341
  this.entrypointDependencyGraph.reset();
236
342
  this.plugins = [];
237
343
  }
344
+ [Symbol.dispose]() {
345
+ this.stop();
346
+ }
238
347
  }
239
348
  export {
240
- SharedHmrManager
349
+ SharedHmrManager,
350
+ resolveHmrRegistrationTimeoutMs
241
351
  };
@@ -7,4 +7,9 @@ export interface StaticPreviewHostStartOptions {
7
7
  appConfig: EcoPagesAppConfig;
8
8
  hostname: string;
9
9
  port: number;
10
+ /**
11
+ * When true, bind to the next available port if the preferred one is busy.
12
+ * Should remain false when the port was explicitly configured.
13
+ */
14
+ allowPortFallback?: boolean;
10
15
  }
@@ -0,0 +1,24 @@
1
+ import type { EcopagesSocket, WebSocketCloseInfo } from '../../types/public-types.js';
2
+ /**
3
+ * @remarks
4
+ * Bun and Node expose different raw socket types but share the same
5
+ * {@link OutgoingWebSocketMessage} contract. Adapters supply only `send`/`close`;
6
+ * {@link createEcopagesSocket} owns message normalization and stream forwarding.
7
+ */
8
+ export interface WebSocketSendTransport {
9
+ send(data: string | Uint8Array): void;
10
+ close(code?: number, reason?: string): void;
11
+ }
12
+ /**
13
+ * @remarks
14
+ * Bun and Node adapters previously duplicated outgoing-message dispatch and
15
+ * stream forwarding; this is the shared implementation both transports delegate to.
16
+ */
17
+ export declare function createEcopagesSocket<TContext, TParams extends Record<string, string>>(transport: WebSocketSendTransport, meta: {
18
+ kind: string;
19
+ params: TParams;
20
+ search: Record<string, string>;
21
+ context: TContext;
22
+ }): EcopagesSocket<TContext, TParams>;
23
+ export declare function toWebSocketCloseInfo(code: number, reason: string): WebSocketCloseInfo;
24
+ export declare function invokeWebSocketHandlerHook(kind: string, hookName: string, result: void | Promise<void>): void;
@@ -0,0 +1,55 @@
1
+ import { appLogger } from "../../global/app-logger.js";
2
+ function sendOutgoingMessage(transport, message) {
3
+ if (typeof message === "string") {
4
+ transport.send(message);
5
+ } else if (message instanceof Blob) {
6
+ void message.arrayBuffer().then((buffer) => transport.send(new Uint8Array(buffer)));
7
+ } else if (message instanceof ArrayBuffer) {
8
+ transport.send(new Uint8Array(message));
9
+ } else if (ArrayBuffer.isView(message)) {
10
+ transport.send(new Uint8Array(message.buffer, message.byteOffset, message.byteLength));
11
+ } else {
12
+ transport.send(message);
13
+ }
14
+ }
15
+ function createEcopagesSocket(transport, meta) {
16
+ return {
17
+ kind: meta.kind,
18
+ params: meta.params,
19
+ search: meta.search,
20
+ context: meta.context,
21
+ send: (message) => sendOutgoingMessage(transport, message),
22
+ sendStream: async (stream) => {
23
+ const reader = stream.getReader();
24
+ try {
25
+ while (true) {
26
+ const { value, done } = await reader.read();
27
+ if (done) break;
28
+ if (value) transport.send(value);
29
+ }
30
+ } finally {
31
+ reader.releaseLock();
32
+ }
33
+ },
34
+ close: (code, reason) => transport.close(code, reason)
35
+ };
36
+ }
37
+ function toWebSocketCloseInfo(code, reason) {
38
+ return {
39
+ code,
40
+ reason,
41
+ wasClean: code === 1e3 || code === 1001
42
+ };
43
+ }
44
+ function invokeWebSocketHandlerHook(kind, hookName, result) {
45
+ if (result instanceof Promise) {
46
+ result.catch((error) => {
47
+ appLogger.error(`[WS:${kind}] ${hookName} failed:`, error);
48
+ });
49
+ }
50
+ }
51
+ export {
52
+ createEcopagesSocket,
53
+ invokeWebSocketHandlerHook,
54
+ toWebSocketCloseInfo
55
+ };
@@ -4,13 +4,15 @@ The build layer is the bundler contract for Ecopages. One bundled adapter is the
4
4
 
5
5
  ## Mental Model
6
6
 
7
- Three concentric shapes, plus a serializer and a plugin injector:
7
+ Three concentric shapes, plus profile executors and a plugin injector:
8
8
 
9
9
  | Shape | Lives in | Purpose |
10
10
  | -------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
11
11
  | `BuildAdapter` | `build-adapter.ts` | Low-level backend. Two implementations: the bundled adapter (the real bundler) and `ViteHostBuildAdapter` (a host-owned boundary marker that throws on direct use). |
12
- | `BuildExecutor` | `build-adapter.ts` | Narrower runtime facade. Only `build` is exposed. Stored on `appConfig.runtime.buildExecutor`. |
13
- | `SerializedBuildExecutor` | `serialized-build-executor.ts` | FIFO queue around any `BuildExecutor`. Used by the dev watch pipeline. |
12
+ | `BuildRuntime` | `build-runtime.ts` | Profile-based executor registry. Single entry point on `appConfig.runtime.buildRuntime`. |
13
+ | `BuildExecutor` | `build-contracts.ts` | Narrower runtime facade. Only `build` is exposed. Retrieved via `buildRuntime.getProfile(...)`. |
14
+ | `SerializedBuildExecutor` | `serialized-build-executor.ts` | FIFO queue around any `BuildExecutor`. Used for server-entry single-flight ordering. |
15
+ | `ParallelBuildExecutor` | `parallel-build-executor.ts` | Concurrency-limited wrapper for independent route-module and HMR browser builds. |
14
16
  | `withBuildExecutorPlugins` | `build-adapter.ts` | Merges app-owned plugins into every `build` call. The single point of plugin injection. |
15
17
 
16
18
  Plus one translation bridge:
@@ -20,29 +22,31 @@ Plus one translation bridge:
20
22
  ## Files
21
23
 
22
24
  - `build-adapter.ts`: types, factories, app-owned helpers, `withBuildExecutorPlugins`.
25
+ - `build-runtime.ts`: profile-based executor installation (`server-entry`, `route-module`, `browser-hmr`).
23
26
  - `build-types.ts`: the `EcoBuildPlugin` contract used by integrations and processors.
24
27
  - `rolldown-build-adapter.ts`: the production `BuildAdapter`. Wraps the bundler and exposes a normalized `BuildResult` (outputs, dependency graph, logs).
25
28
  - `rolldown-plugin-bridge.ts`: `EcoBuildPlugin[]` → bundler-plugin translation.
26
29
  - `serialized-build-executor.ts`: FIFO queue primitive.
27
- - `runtime-build-executor.ts`: dev-watch entrypoint that wraps the app-owned adapter in a `SerializedBuildExecutor + withBuildExecutorPlugins` chain.
30
+ - `runtime-build-executor.ts`: server-adapter entrypoint that installs `BuildRuntime` via `installAppRuntimeBuildExecutor()`.
31
+ - `server-entry-build-cache.ts`: production server-entry bundle cache (`.eco/.server-entry/.build-cache.json` + `dist/.server/manifest.json`).
28
32
  - `*.test.ts`: regression coverage.
29
33
 
30
34
  ## Default Flow
31
35
 
32
- `ConfigBuilder.build()` creates one app-owned adapter, manifest, executor, dev graph, and runtime registry. The executor it stores is the raw `BuildAdapter`; the plugin-wrap step lives in the runtime path.
33
-
34
- When a server adapter initializes, it calls `installAppRuntimeBuildExecutor(appConfig)`. That function reads the existing executor (or falls back to the app-owned adapter) and stores a fresh wrapper:
36
+ `ConfigBuilder.build()` creates one app-owned adapter and manifest. When a server adapter initializes, it calls `installAppRuntimeBuildExecutor(appConfig)`, which installs `BuildRuntime`:
35
37
 
36
38
  ```
37
- BuildExecutor
38
- └─ SerializedBuildExecutor // FIFO queue
39
- └─ withBuildExecutorPlugins // injects app plugins
40
- └─ BuildAdapter (bundled adapter or Vite-host)
39
+ BuildRuntime.getProfile(...)
40
+ ├─ server-entry → SerializedBuildExecutor withBuildExecutorPlugins → RolldownBuildAdapter
41
+ ├─ route-module → ParallelBuildExecutor → withBuildExecutorPlugins RolldownBuildAdapter
42
+ └─ browser-hmr → ParallelBuildExecutor → withBuildExecutorPlugins RolldownBuildAdapter
41
43
  ```
42
44
 
43
- Every dev-watch caller reads `appConfig.runtime.buildExecutor` and gets the merged plugin set without further ceremony.
45
+ All profiles use one-shot Rolldown in both dev and production. Route-module and browser-HMR builds run in parallel; server-entry stays serialized single-flight.
46
+
47
+ Runtime code should call `requireBuildRuntime(appConfig).getProfile('route-module' | 'browser-hmr' | 'server-entry')` instead of reading legacy executor slots.
44
48
 
45
- The exported `defaultBuildAdapter` and the top-level `build()` / `getTranspileOptions()` helpers are non-app-aware escape hatches. New runtime code should prefer `getAppBuildAdapter()`, `getAppBuildExecutor()`, and `getAppTranspileOptions()`.
49
+ The exported `defaultBuildAdapter` and the top-level `build()` / `getTranspileOptions()` helpers are non-app-aware escape hatches. New runtime code should prefer `getAppBuildAdapter()`, `requireBuildRuntime()`, and `getAppTranspileOptions()`.
46
50
 
47
51
  ## Vite-Host Boundary
48
52
 
@@ -81,11 +85,70 @@ Plugin ordering: the bundler's `resolveId` and `load` are "first" hooks. The bri
81
85
 
82
86
  These fields are kept in the type so existing call-sites compile. The proper fix is a more focused `BuildOptions` schema in a follow-up.
83
87
 
88
+ ## Dev / watch path
89
+
90
+ `installBuildRuntime` (via `installAppRuntimeBuildExecutor`) installs profile-based executors:
91
+
92
+ | Profile | Backend | Concurrency |
93
+ | -------------- | ----------------- | -------------------- |
94
+ | `server-entry` | Rolldown one-shot | Serialized |
95
+ | `route-module` | Rolldown one-shot | Parallel |
96
+ | `browser-hmr` | Rolldown one-shot | Parallel (limit ≤ 3) |
97
+
98
+ `hmr-entrypoint` rebuilds use the `browser-hmr` profile. Other browser builds (`browser-script`, `hmr-runtime`) use `route-module`.
99
+
100
+ `ProjectWatcher` deduplicates watch roots, ignores `.eco/` and `dist/`, and coalesces duplicate chokidar events within 150ms.
101
+
102
+ ## Metrics
103
+
104
+ Set `ECOPAGES_ROLLDOWN_BUILD_METRICS=1` to log Rolldown invocation counts during dev and production builds. Compare kitchen-sink dev navigation and `static-build-bench` before/after runtime changes.
105
+
106
+ ## Production build caches
107
+
108
+ Two persisted cache layers accelerate production builds. Both use `.build-cache.json` manifests keyed by dependency hashes and a build-inputs fingerprint.
109
+
110
+ | Cache | On-disk location | Module |
111
+ | -------------------------------------- | --------------------------------------------------- | ----------------------------------- |
112
+ | Server-entry bundle | `.eco/.server-entry/.build-cache.json` | `server-entry-build-cache.ts` |
113
+ | Route-module transpile + static render | `<server-outdir>/.server-modules/.build-cache.json` | `route-module-build-cache.store.ts` |
114
+
115
+ `getInstalledServerEntryBuildExecutor()` returns the `server-entry` profile from `BuildRuntime`. `clearProductionBuildCaches()` wipes both manifest trees, resets in-memory route-module state, and clears `buildRuntime`.
116
+
117
+ The route-module registry (`route-module-build-cache-registry.ts`) shares one `RouteModuleBuildCache` per `(app, outdir)` pair. Legacy `.server-route-modules` outdirs are still read for migration but new writes go to `.server-modules`.
118
+
119
+ ## Unified pages graph
120
+
121
+ Production static exports compile all template pages in one Rolldown invocation when `shouldBuildPagesUnifiedGraph()` is true (default in production; opt out with `ECOPAGES_UNIFIED_PAGES_GRAPH=0`).
122
+
123
+ | Artifact | Location |
124
+ | -------------- | ----------------------------------------------------- |
125
+ | Graph manifest | `.eco/.server-pages-graph/.build-cache.json` |
126
+ | Chunk outputs | `.eco/.server-modules/` (shared with per-route cache) |
127
+
128
+ `StaticSiteGenerator` calls `ensurePagesUnifiedGraphBuilt()` before the export loop. `PageModuleImportService` imports prebuilt chunks via `importPagesUnifiedGraphModule()` and falls back to per-page Rolldown on miss.
129
+
130
+ `ECOPAGES_ROLLDOWN_BUILD_METRICS=1` enables `rolldown-build-invocation-metrics.ts` counters used by bench and parity tests.
131
+
132
+ Build-input fingerprinting lives in `build-input-fingerprint.ts` and is shared with server-entry cache, unified pages graph, and static-render invalidation.
133
+
134
+ ## JSX Ownership Plugins
135
+
136
+ Mixed-integration apps need explicit `@jsxImportSource` handling in two different shapes:
137
+
138
+ | Helper | Use when | Behavior |
139
+ | ------------------------------------ | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
140
+ | `getJsxOwnershipPlugins()` | App-wide server/transpile builds | Each JSX integration extension gets its **own** `jsxImportSource` so native files keep their owning runtime. |
141
+ | `getHostScopedJsxOwnershipPlugins()` | One integration's **client** bundle graph | Foreign `.tsx`/`.jsx` files compile with the **host** integration JSX runtime (for example React bundling `.kita.tsx`). |
142
+ | `eco-component-meta-plugin` | Component metadata injection | Prepends the **owning** integration pragma only when injecting `__eco` metadata into native files. |
143
+
144
+ `foreign-jsx-override-plugin.ts` is the shared implementation. Prefer the helpers above instead of calling it directly from integrations.
145
+
84
146
  ## Testing Strategy
85
147
 
86
148
  - `rolldown-build-adapter.test.ts` covers the adapter's `build`, `resolve`, `getTranspileOptions`, and dependency-graph extraction end-to-end.
87
149
  - `rolldown-plugin-bridge.test.ts` covers the `EcoBuildPlugin[]` → plugin translation in isolation.
88
150
  - `build-adapter.test.ts` covers the app-owned helpers, the `BuildOwnership` routing, the `withBuildExecutorPlugins` injection, and the default-fallback behaviour.
89
- - `runtime-build-executor.test.ts` covers the dev-watch wrapper: serialization, plugin injection, and the Vite-host rejection path.
151
+ - `build-runtime.test.ts` covers profile executor installation and parallelism.
152
+ - `runtime-build-executor.test.ts` covers the runtime wrapper: plugin injection and the Vite-host rejection path.
90
153
 
91
154
  If you change option mapping or plugin-bridge semantics, update the adapter and bridge tests first. If you change the app-owned helper contracts, update `build-adapter.test.ts` first.
@@ -0,0 +1,10 @@
1
+ import type { EcoBuildPlugin } from './build-types.js';
2
+ import type { AppBuildManifest } from './build-manifest.js';
3
+ import type { EcoPagesAppConfig, IHmrManager } from '../types/internal-types.js';
4
+ export declare function collectConfiguredAppBuildManifestContributions(appConfig: EcoPagesAppConfig): Promise<Pick<AppBuildManifest, 'runtimePlugins' | 'browserBundlePlugins' | 'browserRuntimeManifest'>>;
5
+ export declare function setupAppRuntimePlugins(options: {
6
+ appConfig: EcoPagesAppConfig;
7
+ runtimeOrigin: string;
8
+ hmrManager?: IHmrManager;
9
+ onRuntimePlugin?: (plugin: EcoBuildPlugin) => void;
10
+ }): Promise<void>;
@@ -0,0 +1,90 @@
1
+ import { mergeBrowserRuntimeManifests } from "./browser-runtime-manifest.js";
2
+ import { appLogger } from "../global/app-logger.js";
3
+ function patchAppRuntime(appConfig, patch) {
4
+ appConfig.runtime = {
5
+ ...appConfig.runtime ?? {},
6
+ ...patch
7
+ };
8
+ }
9
+ function registerRuntimePlugins(appConfig, onRuntimePlugin) {
10
+ for (const loader of appConfig.loaders.values()) {
11
+ onRuntimePlugin?.(loader);
12
+ }
13
+ for (const processor of appConfig.processors.values()) {
14
+ if (processor.plugins) {
15
+ for (const plugin of processor.plugins) {
16
+ onRuntimePlugin?.(plugin);
17
+ }
18
+ }
19
+ }
20
+ for (const integration of appConfig.integrations) {
21
+ for (const plugin of integration.plugins) {
22
+ onRuntimePlugin?.(plugin);
23
+ }
24
+ }
25
+ }
26
+ async function collectConfiguredAppBuildManifestContributions(appConfig) {
27
+ const runtimePlugins = [];
28
+ const browserBundlePlugins = [];
29
+ const browserRuntimeManifests = [];
30
+ for (const processor of appConfig.processors.values()) {
31
+ await processor.prepareBuildContributions();
32
+ if (processor.plugins) {
33
+ runtimePlugins.push(...processor.plugins);
34
+ }
35
+ if (processor.buildPlugins) {
36
+ browserBundlePlugins.push(...processor.buildPlugins);
37
+ }
38
+ }
39
+ for (const integration of appConfig.integrations) {
40
+ integration.setConfig(appConfig);
41
+ await integration.prepareBuildContributions();
42
+ runtimePlugins.push(...integration.plugins ?? []);
43
+ browserBundlePlugins.push(...integration.browserBuildPlugins ?? []);
44
+ browserRuntimeManifests.push(integration.browserRuntimeManifest);
45
+ }
46
+ return {
47
+ runtimePlugins,
48
+ browserBundlePlugins,
49
+ browserRuntimeManifest: mergeBrowserRuntimeManifests(...browserRuntimeManifests)
50
+ };
51
+ }
52
+ async function setupAppRuntimePlugins(options) {
53
+ if (options.appConfig.runtime?.runtimeAssetsPrepared) {
54
+ appLogger.debug("Skipped setupAppRuntimePlugins: runtime assets already prepared");
55
+ registerRuntimePlugins(options.appConfig, options.onRuntimePlugin);
56
+ return;
57
+ }
58
+ appLogger.debugTime("setupAppRuntimePlugins");
59
+ try {
60
+ for (const loader of options.appConfig.loaders.values()) {
61
+ options.onRuntimePlugin?.(loader);
62
+ }
63
+ for (const processor of options.appConfig.processors.values()) {
64
+ await processor.setup();
65
+ if (processor.plugins) {
66
+ for (const plugin of processor.plugins) {
67
+ options.onRuntimePlugin?.(plugin);
68
+ }
69
+ }
70
+ }
71
+ for (const integration of options.appConfig.integrations) {
72
+ integration.setConfig(options.appConfig);
73
+ integration.setRuntimeOrigin(options.runtimeOrigin);
74
+ if (options.hmrManager) {
75
+ integration.setHmrManager(options.hmrManager);
76
+ }
77
+ await integration.setup();
78
+ for (const plugin of integration.plugins) {
79
+ options.onRuntimePlugin?.(plugin);
80
+ }
81
+ }
82
+ patchAppRuntime(options.appConfig, { runtimeAssetsPrepared: true });
83
+ } finally {
84
+ appLogger.debugTimeEnd("setupAppRuntimePlugins");
85
+ }
86
+ }
87
+ export {
88
+ collectConfiguredAppBuildManifestContributions,
89
+ setupAppRuntimePlugins
90
+ };