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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/README.md +38 -9
  2. package/package.json +241 -30
  3. package/src/adapters/README.md +6 -2
  4. package/src/adapters/abstract/application-adapter.d.ts +123 -6
  5. package/src/adapters/abstract/application-adapter.js +151 -1
  6. package/src/adapters/abstract/segment-path-matcher.d.ts +6 -0
  7. package/src/adapters/abstract/segment-path-matcher.js +149 -0
  8. package/src/adapters/abstract/server-adapter.d.ts +16 -2
  9. package/src/adapters/abstract/ws-pattern-matcher.d.ts +12 -0
  10. package/src/adapters/abstract/ws-pattern-matcher.js +30 -0
  11. package/src/adapters/bun/bun-user-websocket-lifecycle.d.ts +22 -0
  12. package/src/adapters/bun/bun-user-websocket-lifecycle.js +96 -0
  13. package/src/adapters/bun/client-bridge.d.ts +1 -0
  14. package/src/adapters/bun/client-bridge.js +3 -0
  15. package/src/adapters/bun/create-app.d.ts +9 -6
  16. package/src/adapters/bun/create-app.js +76 -45
  17. package/src/adapters/bun/hmr-manager.d.ts +1 -1
  18. package/src/adapters/bun/hmr-manager.js +1 -1
  19. package/src/adapters/bun/index.d.ts +1 -1
  20. package/src/adapters/bun/index.js +25 -2
  21. package/src/adapters/bun/runtime-host.d.ts +1 -1
  22. package/src/adapters/bun/runtime-host.js +1 -1
  23. package/src/adapters/bun/server-adapter.d.ts +92 -41
  24. package/src/adapters/bun/server-adapter.js +256 -117
  25. package/src/adapters/bun/static-preview-host.d.ts +1 -1
  26. package/src/adapters/bun/static-preview-host.js +25 -20
  27. package/src/adapters/create-app.d.ts +13 -11
  28. package/src/adapters/create-app.js +2 -51
  29. package/src/adapters/index.d.ts +2 -2
  30. package/src/adapters/index.js +26 -4
  31. package/src/adapters/node/create-app.d.ts +8 -3
  32. package/src/adapters/node/create-app.js +61 -13
  33. package/src/adapters/node/node-client-bridge.d.ts +1 -0
  34. package/src/adapters/node/node-client-bridge.js +3 -0
  35. package/src/adapters/node/node-hmr-manager.d.ts +1 -1
  36. package/src/adapters/node/node-hmr-manager.js +1 -1
  37. package/src/adapters/node/runtime-host.d.ts +1 -1
  38. package/src/adapters/node/runtime-host.js +1 -1
  39. package/src/adapters/node/server-adapter-dependencies.js +4 -0
  40. package/src/adapters/node/server-adapter.d.ts +64 -23
  41. package/src/adapters/node/server-adapter.js +169 -142
  42. package/src/adapters/node/static-content-server.d.ts +1 -0
  43. package/src/adapters/node/static-content-server.js +10 -2
  44. package/src/adapters/node/static-preview-host.d.ts +1 -1
  45. package/src/adapters/node/static-preview-host.js +27 -12
  46. package/src/adapters/shared/{hmr-entrypoint-registrar.d.ts → hmr/hmr-entrypoint-registrar.d.ts} +31 -30
  47. package/src/adapters/shared/hmr/hmr-entrypoint-registrar.js +106 -0
  48. package/src/adapters/shared/{hmr-html-response.d.ts → hmr/hmr-html-response.d.ts} +2 -2
  49. package/src/adapters/shared/{hmr-html-response.js → hmr/hmr-html-response.js} +4 -1
  50. package/src/adapters/shared/hmr/shared-hmr-manager.d.ts +101 -0
  51. package/src/adapters/shared/hmr/shared-hmr-manager.js +432 -0
  52. package/src/adapters/shared/http/api-request-pipeline.d.ts +23 -0
  53. package/src/adapters/shared/http/api-request-pipeline.js +129 -0
  54. package/src/adapters/shared/{api-response.d.ts → http/api-response.d.ts} +1 -1
  55. package/src/adapters/shared/{api-response.js → http/api-response.js} +6 -23
  56. package/src/adapters/shared/http/create-body-response.d.ts +12 -0
  57. package/src/adapters/shared/http/create-body-response.js +23 -0
  58. package/src/adapters/shared/http/define-api-handler.d.ts +90 -0
  59. package/src/adapters/shared/http/define-api-handler.js +63 -0
  60. package/src/adapters/shared/{explicit-static-render-preparation.d.ts → http/explicit-static-render-preparation.d.ts} +3 -3
  61. package/src/adapters/shared/{explicit-static-route-matcher.d.ts → http/explicit-static-route-matcher.d.ts} +3 -9
  62. package/src/adapters/shared/{explicit-static-route-matcher.js → http/explicit-static-route-matcher.js} +3 -38
  63. package/src/adapters/shared/{file-route-middleware-pipeline.d.ts → http/file-route-middleware-pipeline.d.ts} +2 -2
  64. package/src/adapters/shared/{file-route-middleware-pipeline.js → http/file-route-middleware-pipeline.js} +10 -22
  65. package/src/adapters/shared/{fs-server-response-factory.d.ts → http/fs-server-response-factory.d.ts} +7 -2
  66. package/src/adapters/shared/{fs-server-response-factory.js → http/fs-server-response-factory.js} +22 -2
  67. package/src/adapters/shared/{fs-server-response-matcher.d.ts → http/fs-server-response-matcher.d.ts} +25 -5
  68. package/src/adapters/shared/{fs-server-response-matcher.js → http/fs-server-response-matcher.js} +109 -27
  69. package/src/adapters/shared/http/run-middleware-chain.d.ts +5 -0
  70. package/src/adapters/shared/http/run-middleware-chain.js +17 -0
  71. package/src/adapters/shared/{application-adapter.d.ts → runtime/application-adapter.d.ts} +2 -2
  72. package/src/adapters/shared/{application-adapter.js → runtime/application-adapter.js} +1 -1
  73. package/src/adapters/shared/runtime/copy-runtime-public-dir.d.ts +6 -0
  74. package/src/adapters/shared/runtime/copy-runtime-public-dir.js +24 -0
  75. package/src/adapters/shared/runtime/port-manager.d.ts +116 -0
  76. package/src/adapters/shared/runtime/port-manager.js +196 -0
  77. package/src/adapters/shared/{render-context.d.ts → runtime/render-context.d.ts} +2 -2
  78. package/src/adapters/shared/{render-context.js → runtime/render-context.js} +8 -17
  79. package/src/adapters/shared/{runtime-app-bootstrap.d.ts → runtime/runtime-app-bootstrap.d.ts} +4 -3
  80. package/src/adapters/shared/{runtime-app-bootstrap.js → runtime/runtime-app-bootstrap.js} +4 -7
  81. package/src/adapters/shared/runtime/runtime-server-lifecycle.d.ts +46 -0
  82. package/src/adapters/shared/runtime/runtime-server-lifecycle.js +57 -0
  83. package/src/adapters/shared/{server-adapter.d.ts → runtime/server-adapter.d.ts} +23 -49
  84. package/src/adapters/shared/runtime/server-adapter.js +226 -0
  85. package/src/adapters/shared/{server-route-handler.d.ts → runtime/server-route-handler.d.ts} +6 -33
  86. package/src/adapters/shared/{server-route-handler.js → runtime/server-route-handler.js} +5 -43
  87. package/src/adapters/shared/{server-static-builder.d.ts → runtime/server-static-builder.d.ts} +27 -35
  88. package/src/adapters/shared/runtime/server-static-builder.js +191 -0
  89. package/src/adapters/shared/{static-preview-host.d.ts → runtime/static-preview-host.d.ts} +6 -1
  90. package/src/adapters/shared/ws/node-http-websocket-upgrades.d.ts +21 -0
  91. package/src/adapters/shared/ws/node-http-websocket-upgrades.js +100 -0
  92. package/src/adapters/shared/ws/websocket-lifecycle.d.ts +24 -0
  93. package/src/adapters/shared/ws/websocket-lifecycle.js +55 -0
  94. package/src/build/README.md +140 -31
  95. package/src/build/app-build-manifest-runtime.d.ts +39 -0
  96. package/src/build/app-build-manifest-runtime.js +124 -0
  97. package/src/build/{browser-runtime-plugin.d.ts → browser/browser-runtime-plugin.d.ts} +1 -1
  98. package/src/build/{browser-runtime-plugin.js → browser/browser-runtime-plugin.js} +1 -1
  99. package/src/build/browser/jsx-ownership-plugins.d.ts +24 -0
  100. package/src/build/browser/jsx-ownership-plugins.js +41 -0
  101. package/src/build/browser/lit-static-render-worker-context.d.ts +2 -0
  102. package/src/build/browser/lit-static-render-worker-context.js +6 -0
  103. package/src/build/build-adapter.d.ts +29 -334
  104. package/src/build/build-adapter.js +32 -133
  105. package/src/build/cache/build-input-fingerprint.d.ts +28 -0
  106. package/src/build/cache/build-input-fingerprint.js +31 -0
  107. package/src/build/cache/cache-constants.d.ts +4 -0
  108. package/src/build/cache/cache-constants.js +6 -0
  109. package/src/build/cache/cache-keys.d.ts +22 -0
  110. package/src/build/cache/cache-keys.js +63 -0
  111. package/src/build/cache/dev-browser-script-cache.d.ts +34 -0
  112. package/src/build/cache/dev-browser-script-cache.js +90 -0
  113. package/src/build/cache/pages-unified-graph-build.d.ts +31 -0
  114. package/src/build/cache/pages-unified-graph-build.js +198 -0
  115. package/src/build/cache/production-build-cache.d.ts +20 -0
  116. package/src/build/cache/production-build-cache.js +63 -0
  117. package/src/build/cache/server-entry-build-cache.d.ts +43 -0
  118. package/src/build/cache/server-entry-build-cache.js +165 -0
  119. package/src/build/contracts/build-contracts.d.ts +96 -0
  120. package/src/build/contracts/build-manifest.d.ts +90 -0
  121. package/src/build/{build-manifest.js → contracts/build-manifest.js} +2 -2
  122. package/src/build/contracts/build-types.js +0 -0
  123. package/src/build/{rolldown-adapter-helpers.d.ts → rolldown/rolldown-adapter-helpers.d.ts} +23 -9
  124. package/src/build/{rolldown-adapter-helpers.js → rolldown/rolldown-adapter-helpers.js} +99 -13
  125. package/src/build/{rolldown-build-adapter.d.ts → rolldown/rolldown-build-adapter.d.ts} +3 -7
  126. package/src/build/{rolldown-build-adapter.js → rolldown/rolldown-build-adapter.js} +3 -3
  127. package/src/build/rolldown/rolldown-build-invocation-metrics.d.ts +12 -0
  128. package/src/build/rolldown/rolldown-build-invocation-metrics.js +43 -0
  129. package/src/build/{rolldown-plugin-bridge.d.ts → rolldown/rolldown-plugin-bridge.d.ts} +16 -2
  130. package/src/build/{rolldown-plugin-bridge.js → rolldown/rolldown-plugin-bridge.js} +21 -6
  131. package/src/build/rolldown/rolldown-source-transform-pass.d.ts +15 -0
  132. package/src/build/rolldown/rolldown-source-transform-pass.js +61 -0
  133. package/src/build/rolldown/runtime-build-output-normalizer.d.ts +10 -0
  134. package/src/build/rolldown/runtime-build-output-normalizer.js +201 -0
  135. package/src/build/runtime/build-profile-options.d.ts +7 -0
  136. package/src/build/runtime/build-profile-options.js +37 -0
  137. package/src/build/runtime/build-request-identity.d.ts +17 -0
  138. package/src/build/runtime/build-request-identity.js +54 -0
  139. package/src/build/runtime/build-request-policy.d.ts +59 -0
  140. package/src/build/runtime/build-request-policy.js +46 -0
  141. package/src/build/runtime/build-runtime.d.ts +28 -0
  142. package/src/build/runtime/build-runtime.js +65 -0
  143. package/src/build/runtime/deduping-build-executor.d.ts +21 -0
  144. package/src/build/runtime/deduping-build-executor.js +34 -0
  145. package/src/build/runtime/parallel-build-executor.d.ts +21 -0
  146. package/src/build/runtime/parallel-build-executor.js +52 -0
  147. package/src/build/{serialized-build-executor.d.ts → runtime/serialized-build-executor.d.ts} +1 -1
  148. package/src/client/navigation-scripts/classification.d.ts +16 -0
  149. package/src/client/navigation-scripts/classification.js +41 -0
  150. package/src/client/navigation-scripts/index.d.ts +3 -0
  151. package/src/client/navigation-scripts/index.js +23 -0
  152. package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
  153. package/src/client/navigation-scripts/registry.d.ts +11 -0
  154. package/src/client/navigation-scripts/registry.js +12 -0
  155. package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
  156. package/src/client/navigation-scripts/rerun-queue.js +73 -0
  157. package/src/client/scroll.d.ts +17 -0
  158. package/src/client/scroll.js +25 -0
  159. package/src/client/scroll.test.browser.js +37 -0
  160. package/src/client/view-transitions.d.ts +16 -0
  161. package/src/client/view-transitions.js +63 -0
  162. package/src/config/config-builder.d.ts +25 -10
  163. package/src/config/config-builder.js +53 -11
  164. package/src/config/constants.d.ts +1 -0
  165. package/src/config/constants.js +2 -1
  166. package/src/dev/client-bridge-registry.d.ts +5 -0
  167. package/src/dev/client-bridge-registry.js +15 -0
  168. package/src/dev/dev-client-ownership.d.ts +7 -0
  169. package/src/dev/dev-client-ownership.js +6 -0
  170. package/src/dev/hmr-manager-registry.d.ts +8 -0
  171. package/src/dev/hmr-manager-registry.js +15 -0
  172. package/src/dev/host-runtime.d.ts +3 -0
  173. package/src/dev/host-runtime.js +7 -0
  174. package/src/dev/runtime-server-started-message.d.ts +2 -0
  175. package/src/dev/runtime-server-started-message.js +6 -0
  176. package/src/diagnostics/request-build-dedupe.d.ts +18 -0
  177. package/src/diagnostics/request-build-dedupe.js +33 -0
  178. package/src/diagnostics/startup-trace.d.ts +72 -0
  179. package/src/diagnostics/startup-trace.js +253 -0
  180. package/src/eco/README.md +11 -0
  181. package/src/eco/eco-declared-component.d.ts +14 -0
  182. package/src/eco/eco-declared-component.js +16 -0
  183. package/src/eco/eco.browser.js +5 -6
  184. package/src/eco/eco.js +7 -8
  185. package/src/eco/eco.types.d.ts +14 -3
  186. package/src/eco/eco.utils.d.ts +1 -1
  187. package/src/eco/eco.utils.js +1 -1
  188. package/src/eco/page-layout-normalization.d.ts +21 -0
  189. package/src/eco/page-layout-normalization.js +59 -0
  190. package/src/env.d.ts +2 -0
  191. package/src/errors/index.d.ts +1 -0
  192. package/src/errors/index.js +7 -1
  193. package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
  194. package/src/errors/undeclared-component-dependency-error.js +17 -0
  195. package/src/hmr/client/hmr-runtime.js +7 -4
  196. package/src/hmr/hmr-entrypoint-output.d.ts +49 -0
  197. package/src/hmr/hmr-entrypoint-output.js +60 -0
  198. package/src/hmr/hmr-file-change-prep.d.ts +10 -0
  199. package/src/hmr/hmr-file-change-prep.js +17 -0
  200. package/src/hmr/hmr-strategy.d.ts +15 -0
  201. package/src/hmr/hmr-strategy.js +19 -0
  202. package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -5
  203. package/src/hmr/strategies/js-hmr-strategy.js +72 -19
  204. package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
  205. package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
  206. package/src/index.d.ts +2 -1
  207. package/src/index.js +28 -2
  208. package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
  209. package/src/integrations/ghtml/ghtml-renderer.js +2 -51
  210. package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
  211. package/src/integrations/ghtml/ghtml.plugin.js +7 -14
  212. package/src/plugins/alias-resolver-cache.d.ts +6 -9
  213. package/src/plugins/alias-resolver-plugin.d.ts +3 -3
  214. package/src/plugins/alias-resolver-plugin.js +38 -51
  215. package/src/plugins/define-integration.d.ts +26 -0
  216. package/src/plugins/define-integration.js +19 -0
  217. package/src/plugins/eco-component-meta-plugin.d.ts +1 -1
  218. package/src/plugins/eco-component-meta-plugin.js +5 -8
  219. package/src/plugins/foreign-jsx-override-plugin.d.ts +1 -1
  220. package/src/plugins/foreign-jsx-override-plugin.js +4 -6
  221. package/src/plugins/integration-plugin.d.ts +43 -14
  222. package/src/plugins/integration-plugin.js +18 -5
  223. package/src/plugins/jsx-import-source.utils.d.ts +8 -0
  224. package/src/plugins/jsx-import-source.utils.js +26 -0
  225. package/src/plugins/processor.d.ts +61 -12
  226. package/src/plugins/processor.js +24 -5
  227. package/src/plugins/source-transform.d.ts +32 -1
  228. package/src/plugins/source-transform.js +23 -1
  229. package/src/plugins/tsconfig-import-resolver.d.ts +18 -0
  230. package/src/plugins/tsconfig-import-resolver.js +159 -0
  231. package/src/route-renderer/GRAPH.md +26 -32
  232. package/src/route-renderer/README.md +38 -31
  233. package/src/route-renderer/orchestration/document-shell/document-shell-render.service.d.ts +107 -0
  234. package/src/route-renderer/orchestration/document-shell/document-shell-render.service.js +148 -0
  235. package/src/route-renderer/orchestration/document-shell/layout-shell-props.service.d.ts +20 -0
  236. package/src/route-renderer/orchestration/document-shell/layout-shell-props.service.js +31 -0
  237. package/src/route-renderer/orchestration/{component-render-context.d.ts → foreign-child/component-render-context.d.ts} +8 -15
  238. package/src/route-renderer/orchestration/{component-render-context.js → foreign-child/component-render-context.js} +4 -2
  239. package/src/route-renderer/orchestration/{render-output.utils.d.ts → foreign-child/foreign-child-output.utils.d.ts} +17 -7
  240. package/src/route-renderer/orchestration/{render-output.utils.js → foreign-child/foreign-child-output.utils.js} +35 -26
  241. package/src/route-renderer/orchestration/{foreign-subtree-execution.service.d.ts → foreign-child/foreign-subtree-execution.service.d.ts} +64 -34
  242. package/src/route-renderer/orchestration/{foreign-subtree-execution.service.js → foreign-child/foreign-subtree-execution.service.js} +170 -37
  243. package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.d.ts +19 -0
  244. package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.js +35 -0
  245. package/src/route-renderer/orchestration/integration-renderer.d.ts +24 -143
  246. package/src/route-renderer/orchestration/integration-renderer.js +163 -402
  247. package/src/route-renderer/orchestration/integration-renderer.test-fixtures.d.ts +75 -0
  248. package/src/route-renderer/orchestration/integration-renderer.test-fixtures.js +177 -0
  249. package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.d.ts +10 -0
  250. package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.js +143 -0
  251. package/src/route-renderer/orchestration/ownership-graph/component-graph.d.ts +34 -0
  252. package/src/route-renderer/orchestration/ownership-graph/component-graph.js +96 -0
  253. package/src/route-renderer/orchestration/{ownership-validation.service.d.ts → ownership-graph/ownership-validation.service.d.ts} +7 -2
  254. package/src/route-renderer/orchestration/{ownership-validation.service.js → ownership-graph/ownership-validation.service.js} +30 -3
  255. package/src/route-renderer/orchestration/page-browser-graph/global-injector-assets.service.d.ts +7 -0
  256. package/src/route-renderer/orchestration/page-browser-graph/global-injector-assets.service.js +32 -0
  257. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-contribution.loader.d.ts +9 -0
  258. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-contribution.loader.js +7 -0
  259. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.d.ts +12 -0
  260. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.js +29 -0
  261. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.d.ts +106 -0
  262. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.js +436 -0
  263. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph.service.d.ts +31 -0
  264. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph.service.js +229 -0
  265. package/src/route-renderer/orchestration/{processed-asset-dedupe.d.ts → page-browser-graph/processed-asset-dedupe.d.ts} +1 -1
  266. package/src/route-renderer/orchestration/route-pipeline/integration-route-render-adapter.d.ts +31 -0
  267. package/src/route-renderer/orchestration/route-pipeline/integration-route-render-adapter.js +25 -0
  268. package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.d.ts +6 -0
  269. package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.js +27 -0
  270. package/src/route-renderer/orchestration/route-pipeline/robots-meta.contribution.d.ts +15 -0
  271. package/src/route-renderer/orchestration/route-pipeline/robots-meta.contribution.js +36 -0
  272. package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.d.ts +20 -0
  273. package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.js +24 -0
  274. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.builder.d.ts +25 -0
  275. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.builder.js +49 -0
  276. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.utils.d.ts +4 -0
  277. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.utils.js +33 -0
  278. package/src/route-renderer/orchestration/{route-render-orchestrator.d.ts → route-pipeline/route-render-orchestrator.d.ts} +13 -53
  279. package/src/route-renderer/orchestration/route-pipeline/route-render-orchestrator.js +162 -0
  280. package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
  281. package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
  282. package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
  283. package/src/route-renderer/page-loading/ecopages-virtual-imports.d.ts +6 -0
  284. package/src/route-renderer/page-loading/ecopages-virtual-imports.js +7 -2
  285. package/src/route-renderer/page-loading/module-declaration-aggregation.js +4 -0
  286. package/src/router/client/link-intent.d.ts +11 -21
  287. package/src/router/client/link-intent.js +10 -0
  288. package/src/router/client/link-intent.test.browser.js +12 -1
  289. package/src/router/client/link-navigation-policy.d.ts +45 -0
  290. package/src/router/client/link-navigation-policy.js +101 -0
  291. package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
  292. package/src/router/client/link-navigation-policy.test.browser.js +92 -0
  293. package/src/router/client/navigation-coordinator.d.ts +1 -1
  294. package/src/router/client/navigation-coordinator.js +12 -2
  295. package/src/services/assets/asset-processing-service/asset-dependency-keys.d.ts +13 -0
  296. package/src/services/assets/asset-processing-service/asset-dependency-keys.js +3 -0
  297. package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +6 -1
  298. package/src/services/assets/asset-processing-service/asset-processing.service.js +44 -5
  299. package/src/services/assets/asset-processing-service/assets.types.d.ts +1 -1
  300. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +2 -1
  301. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
  302. package/src/services/assets/asset-processing-service/browser-runtime-entry-resolution.d.ts +52 -0
  303. package/src/services/assets/asset-processing-service/browser-runtime-entry-resolution.js +78 -0
  304. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
  305. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +28 -13
  306. package/src/services/assets/asset-processing-service/finalize-processed-asset.d.ts +3 -0
  307. package/src/services/assets/asset-processing-service/finalize-processed-asset.js +7 -0
  308. package/src/services/assets/asset-processing-service/grouped-content-bundles.d.ts +2 -1
  309. package/src/services/assets/asset-processing-service/grouped-content-bundles.js +38 -12
  310. package/src/services/assets/asset-processing-service/index.d.ts +2 -0
  311. package/src/services/assets/asset-processing-service/index.js +2 -0
  312. package/src/services/assets/asset-processing-service/inline-content-script-body.d.ts +11 -0
  313. package/src/services/assets/asset-processing-service/inline-content-script-body.js +17 -0
  314. package/src/services/assets/asset-processing-service/materialize-content-script-asset.d.ts +9 -0
  315. package/src/services/assets/asset-processing-service/materialize-content-script-asset.js +18 -0
  316. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +0 -2
  317. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +2 -15
  318. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +8 -0
  319. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +73 -68
  320. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -1
  321. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +18 -15
  322. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
  323. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
  324. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
  325. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
  326. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
  327. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
  328. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
  329. package/src/services/assets/asset-processing-service/resolve-integration-plugin.d.ts +4 -0
  330. package/src/services/assets/asset-processing-service/resolve-integration-plugin.js +17 -0
  331. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.d.ts +0 -1
  332. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.js +5 -10
  333. package/src/services/assets/browser-bundle.service.d.ts +28 -30
  334. package/src/services/assets/browser-bundle.service.js +28 -19
  335. package/src/services/html/html-transformer.service.d.ts +1 -1
  336. package/src/services/html/html-transformer.service.js +5 -5
  337. package/src/services/invalidation/development-invalidation.service.d.ts +25 -2
  338. package/src/services/invalidation/development-invalidation.service.js +64 -11
  339. package/src/services/module-loading/README.md +49 -0
  340. package/src/services/module-loading/app-server-module-transpiler.service.d.ts +8 -0
  341. package/src/services/module-loading/app-server-module-transpiler.service.js +3 -21
  342. package/src/services/module-loading/page-module-import.service.d.ts +6 -2
  343. package/src/services/module-loading/page-module-import.service.js +110 -47
  344. package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
  345. package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
  346. package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
  347. package/src/services/module-loading/route-module-build-cache.js +38 -0
  348. package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
  349. package/src/services/module-loading/route-module-build-cache.store.js +207 -0
  350. package/src/services/module-loading/route-module-build-manifest.d.ts +54 -0
  351. package/src/services/module-loading/route-module-build-manifest.js +85 -0
  352. package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
  353. package/src/services/module-loading/route-module-dependency-hasher.js +122 -0
  354. package/src/services/module-loading/server-module-transpiler.service.d.ts +1 -1
  355. package/src/services/module-loading/server-module-transpiler.service.js +1 -1
  356. package/src/services/validation/schema-validation-service.d.ts +1 -4
  357. package/src/services/validation/schema-validation-service.js +12 -13
  358. package/src/services/validation/standard-schema.types.d.ts +9 -62
  359. package/src/services/validation/validate-standard-schema.d.ts +7 -0
  360. package/src/services/validation/validate-standard-schema.js +14 -0
  361. package/src/static-site-generator/README.md +41 -0
  362. package/src/static-site-generator/production-page-browser-graph-prebuild.d.ts +28 -0
  363. package/src/static-site-generator/production-page-browser-graph-prebuild.js +22 -0
  364. package/src/static-site-generator/sitemap-routes.d.ts +14 -0
  365. package/src/static-site-generator/sitemap-routes.js +31 -0
  366. package/src/static-site-generator/sitemap.d.ts +15 -0
  367. package/src/static-site-generator/sitemap.js +33 -0
  368. package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
  369. package/src/static-site-generator/static-build-invalidation.js +59 -0
  370. package/src/static-site-generator/static-export-context.d.ts +30 -0
  371. package/src/static-site-generator/static-export-context.js +0 -0
  372. package/src/static-site-generator/static-site-generator.d.ts +43 -25
  373. package/src/static-site-generator/static-site-generator.js +381 -106
  374. package/src/types/internal-types.d.ts +39 -13
  375. package/src/types/public-types.d.ts +289 -52
  376. package/src/utils/ecopages-route-info.d.ts +26 -0
  377. package/src/utils/ecopages-route-info.js +26 -0
  378. package/src/utils/html-escaping.d.ts +7 -0
  379. package/src/utils/html-escaping.js +5 -1
  380. package/src/utils/parse-cli-args.d.ts +2 -0
  381. package/src/utils/parse-cli-args.js +6 -0
  382. package/src/utils/path-pattern.d.ts +23 -0
  383. package/src/utils/path-pattern.js +27 -0
  384. package/src/utils/server-utils.module.d.ts +3 -2
  385. package/src/utils/server-utils.module.js +5 -6
  386. package/src/utils/static-file-extensions.d.ts +12 -0
  387. package/src/utils/static-file-extensions.js +48 -0
  388. package/src/watchers/project-watcher-ignore.d.ts +11 -0
  389. package/src/watchers/project-watcher-ignore.js +16 -0
  390. package/src/watchers/project-watcher.d.ts +29 -6
  391. package/src/watchers/project-watcher.js +146 -34
  392. package/src/watchers/project-watcher.test-helpers.js +5 -5
  393. package/src/adapters/shared/define-api-handler.d.ts +0 -25
  394. package/src/adapters/shared/define-api-handler.js +0 -15
  395. package/src/adapters/shared/hmr-entrypoint-registrar.js +0 -87
  396. package/src/adapters/shared/server-adapter.js +0 -436
  397. package/src/adapters/shared/server-static-builder.js +0 -162
  398. package/src/adapters/shared/shared-hmr-manager.d.ts +0 -59
  399. package/src/adapters/shared/shared-hmr-manager.js +0 -241
  400. package/src/build/build-manifest.d.ts +0 -33
  401. package/src/build/rolldown-dev-build-adapter.d.ts +0 -82
  402. package/src/build/rolldown-dev-build-adapter.js +0 -166
  403. package/src/build/runtime-build-executor.d.ts +0 -21
  404. package/src/build/runtime-build-executor.js +0 -19
  405. package/src/build/runtime-build-output-normalizer.d.ts +0 -3
  406. package/src/build/runtime-build-output-normalizer.js +0 -111
  407. package/src/hmr/hmr.postcss.test.e2e.js +0 -31
  408. package/src/hmr/hmr.test.e2e.js +0 -43
  409. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +0 -18
  410. package/src/route-renderer/orchestration/declared-ownership-graph.js +0 -34
  411. package/src/route-renderer/orchestration/ownership-planning.service.d.ts +0 -24
  412. package/src/route-renderer/orchestration/ownership-planning.service.js +0 -63
  413. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +0 -91
  414. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +0 -170
  415. package/src/route-renderer/orchestration/route-render-orchestrator.js +0 -577
  416. package/src/route-renderer/orchestration/template-serialization.d.ts +0 -38
  417. package/src/route-renderer/orchestration/template-serialization.js +0 -45
  418. /package/src/adapters/shared/{explicit-static-render-preparation.js → http/explicit-static-render-preparation.js} +0 -0
  419. /package/src/adapters/shared/{runtime-host.d.ts → runtime/runtime-host.d.ts} +0 -0
  420. /package/src/adapters/shared/{runtime-host.js → runtime/runtime-host.js} +0 -0
  421. /package/src/adapters/shared/{static-preview-host.js → runtime/static-preview-host.js} +0 -0
  422. /package/src/build/{browser-runtime-manifest.d.ts → browser/browser-runtime-manifest.d.ts} +0 -0
  423. /package/src/build/{browser-runtime-manifest.js → browser/browser-runtime-manifest.js} +0 -0
  424. /package/src/build/{browser-runtime-plugin-helpers.d.ts → browser/browser-runtime-plugin-helpers.d.ts} +0 -0
  425. /package/src/build/{browser-runtime-plugin-helpers.js → browser/browser-runtime-plugin-helpers.js} +0 -0
  426. /package/src/build/{build-types.js → contracts/build-contracts.js} +0 -0
  427. /package/src/build/{build-types.d.ts → contracts/build-types.d.ts} +0 -0
  428. /package/src/build/{server-side-css-shim-plugin.d.ts → rolldown/server-side-css-shim-plugin.d.ts} +0 -0
  429. /package/src/build/{server-side-css-shim-plugin.js → rolldown/server-side-css-shim-plugin.js} +0 -0
  430. /package/src/build/{serialized-build-executor.js → runtime/serialized-build-executor.js} +0 -0
  431. /package/src/{hmr/hmr.postcss.test.e2e.d.ts → client/navigation-scripts/navigation-scripts.test.browser.d.ts} +0 -0
  432. /package/src/{hmr/hmr.test.e2e.d.ts → client/scroll.test.browser.d.ts} +0 -0
  433. /package/src/route-renderer/orchestration/{processed-asset-dedupe.js → page-browser-graph/processed-asset-dedupe.js} +0 -0
@@ -13,6 +13,8 @@ export type ReturnParseCliArgs = {
13
13
  build: boolean;
14
14
  start: boolean;
15
15
  dev: boolean;
16
+ force: boolean;
17
+ serveOnly: boolean;
16
18
  port?: number;
17
19
  hostname?: string;
18
20
  reactFastRefresh?: boolean;
@@ -7,6 +7,8 @@ function getEmbeddedRuntimeCommandOptions() {
7
7
  build: false,
8
8
  start: !isDevelopment,
9
9
  dev: isDevelopment,
10
+ force: false,
11
+ serveOnly: false,
10
12
  port: void 0,
11
13
  hostname: void 0,
12
14
  reactFastRefresh: void 0
@@ -25,6 +27,8 @@ function parseCliArgs(options = {}) {
25
27
  dev: { type: "boolean" },
26
28
  preview: { type: "boolean" },
27
29
  build: { type: "boolean" },
30
+ force: { type: "boolean" },
31
+ "serve-only": { type: "boolean" },
28
32
  port: { type: "string" },
29
33
  hostname: { type: "string" },
30
34
  "react-fast-refresh": { type: "boolean" }
@@ -48,6 +52,8 @@ function parseCliArgs(options = {}) {
48
52
  build: isBuildCommand,
49
53
  start: isStartCommand,
50
54
  dev: isDevCommand,
55
+ force: !!values.force,
56
+ serveOnly: !!values["serve-only"] || process.env.ECOPAGES_PREVIEW_SERVE_ONLY === "true",
51
57
  port: values.port ? Number(values.port) : void 0,
52
58
  hostname: values.hostname,
53
59
  reactFastRefresh: values["react-fast-refresh"]
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Normalizes a URL pathname for matching and sitemap location building.
3
+ *
4
+ * @remarks
5
+ * Ensures a leading slash and strips trailing slashes except for `/`.
6
+ */
7
+ export declare function normalizePathname(pathname: string): string;
8
+ /**
9
+ * Matches a pathname against a small set of supported patterns.
10
+ *
11
+ * @remarks
12
+ * Supported forms:
13
+ * - exact: `/admin`
14
+ * - prefix wildcard: `/admin/**` (matches `/admin` and descendants)
15
+ * - trailing `**` only as a full segment after `/`
16
+ *
17
+ * This is not a full glob engine. Unsupported patterns are treated as exact matches.
18
+ */
19
+ export declare function matchPathPattern(pathname: string, pattern: string): boolean;
20
+ /**
21
+ * Returns true when the pathname matches any of the patterns.
22
+ */
23
+ export declare function matchesAnyPathPattern(pathname: string, patterns: readonly string[]): boolean;
@@ -0,0 +1,27 @@
1
+ function normalizePathname(pathname) {
2
+ if (!pathname || pathname === "/") {
3
+ return "/";
4
+ }
5
+ const withLeadingSlash = pathname.startsWith("/") ? pathname : `/${pathname}`;
6
+ return withLeadingSlash.replace(/\/+$/, "") || "/";
7
+ }
8
+ function matchPathPattern(pathname, pattern) {
9
+ const normalizedPath = normalizePathname(pathname);
10
+ const normalizedPattern = pattern.trim();
11
+ if (normalizedPattern.endsWith("/**")) {
12
+ const prefix = normalizePathname(normalizedPattern.slice(0, -3));
13
+ if (prefix === "/") {
14
+ return true;
15
+ }
16
+ return normalizedPath === prefix || normalizedPath.startsWith(`${prefix}/`);
17
+ }
18
+ return normalizedPath === normalizePathname(normalizedPattern);
19
+ }
20
+ function matchesAnyPathPattern(pathname, patterns) {
21
+ return patterns.some((pattern) => matchPathPattern(pathname, pattern));
22
+ }
23
+ export {
24
+ matchPathPattern,
25
+ matchesAnyPathPattern,
26
+ normalizePathname
27
+ };
@@ -1,3 +1,4 @@
1
+ import { hasKnownStaticExtension } from './static-file-extensions.js';
1
2
  /**
2
3
  * Get the content type of a file based on its extension.
3
4
  * @param file - The file name.
@@ -9,11 +10,11 @@ export declare const getContentType: (file: string) => string;
9
10
  * @param file - The file name or path.
10
11
  * @returns true if the extension is recognized.
11
12
  */
12
- export declare const hasKnownExtension: (file: string) => boolean;
13
+ export { hasKnownStaticExtension } from './static-file-extensions.js';
13
14
  /**
14
15
  * A module for server utilities.
15
16
  */
16
17
  export declare const ServerUtils: {
17
18
  getContentType: (file: string) => string;
18
- hasKnownExtension: (file: string) => boolean;
19
+ hasKnownStaticExtension: typeof hasKnownStaticExtension;
19
20
  };
@@ -1,3 +1,4 @@
1
+ import { hasKnownStaticExtension } from "./static-file-extensions.js";
1
2
  const ContentTypeMap = /* @__PURE__ */ new Map([
2
3
  ["jpg", "image/jpeg"],
3
4
  ["jpeg", "image/jpeg"],
@@ -17,6 +18,7 @@ const ContentTypeMap = /* @__PURE__ */ new Map([
17
18
  ["ogv", "video/ogg"],
18
19
  ["mov", "video/quicktime"],
19
20
  ["txt", "text/plain"],
21
+ ["md", "text/markdown"],
20
22
  ["html", "text/html"],
21
23
  ["css", "text/css"],
22
24
  ["js", "text/javascript"],
@@ -41,16 +43,13 @@ const getContentType = (file) => {
41
43
  const extension = file.split(".").pop() || "txt";
42
44
  return ContentTypeMap.get(extension) || "text/plain";
43
45
  };
44
- const hasKnownExtension = (file) => {
45
- const extension = file.split(".").pop();
46
- return extension !== void 0 && ContentTypeMap.has(extension);
47
- };
46
+ import { hasKnownStaticExtension as hasKnownStaticExtension2 } from "./static-file-extensions.js";
48
47
  const ServerUtils = {
49
48
  getContentType,
50
- hasKnownExtension
49
+ hasKnownStaticExtension
51
50
  };
52
51
  export {
53
52
  ServerUtils,
54
53
  getContentType,
55
- hasKnownExtension
54
+ hasKnownStaticExtension2 as hasKnownStaticExtension
56
55
  };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Known static asset extensions served directly from disk.
3
+ *
4
+ * @remarks
5
+ * Keep this list aligned with server static-file handling and client routers
6
+ * that must bypass SPA navigation for same-origin asset links.
7
+ */
8
+ export declare const STATIC_FILE_EXTENSIONS: Set<string>;
9
+ /**
10
+ * Returns whether a path or filename ends with a known static asset extension.
11
+ */
12
+ export declare function hasKnownStaticExtension(fileOrPath: string): boolean;
@@ -0,0 +1,48 @@
1
+ const STATIC_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
2
+ "jpg",
3
+ "jpeg",
4
+ "png",
5
+ "gif",
6
+ "bmp",
7
+ "svg",
8
+ "tiff",
9
+ "webp",
10
+ "avif",
11
+ "ico",
12
+ "mp3",
13
+ "ogg",
14
+ "wav",
15
+ "mp4",
16
+ "webm",
17
+ "ogv",
18
+ "mov",
19
+ "txt",
20
+ "md",
21
+ "html",
22
+ "css",
23
+ "js",
24
+ "mjs",
25
+ "json",
26
+ "map",
27
+ "xml",
28
+ "webmanifest",
29
+ "wasm",
30
+ "csv",
31
+ "ttf",
32
+ "woff",
33
+ "woff2",
34
+ "otf",
35
+ "eot",
36
+ "gz",
37
+ "zip",
38
+ "pdf",
39
+ "doc"
40
+ ]);
41
+ function hasKnownStaticExtension(fileOrPath) {
42
+ const extension = fileOrPath.split(".").pop();
43
+ return extension !== void 0 && STATIC_FILE_EXTENSIONS.has(extension);
44
+ }
45
+ export {
46
+ STATIC_FILE_EXTENSIONS,
47
+ hasKnownStaticExtension
48
+ };
@@ -0,0 +1,11 @@
1
+ export type ProjectWatcherIgnorePaths = {
2
+ workDir: string;
3
+ distDir: string;
4
+ };
5
+ /**
6
+ * @remarks
7
+ * chokidar v4+ no longer treats glob strings in `ignored` as patterns. A path
8
+ * predicate keeps node_modules, VCS metadata, and scoped artifact dirs out of
9
+ * the watch tree without descending into symlinked monorepo node_modules.
10
+ */
11
+ export declare function createProjectWatcherIgnorePredicate(absolutePaths: ProjectWatcherIgnorePaths): (watchedPath: string) => boolean;
@@ -0,0 +1,16 @@
1
+ import path from "node:path";
2
+ function createProjectWatcherIgnorePredicate(absolutePaths) {
3
+ const ignoredPrefixes = [absolutePaths.workDir, absolutePaths.distDir];
4
+ return (watchedPath) => {
5
+ const segments = watchedPath.split(path.sep);
6
+ if (segments.includes("node_modules") || segments.includes(".git")) {
7
+ return true;
8
+ }
9
+ return ignoredPrefixes.some(
10
+ (prefix) => watchedPath === prefix || watchedPath.startsWith(`${prefix}${path.sep}`)
11
+ );
12
+ };
13
+ }
14
+ export {
15
+ createProjectWatcherIgnorePredicate
16
+ };
@@ -13,6 +13,10 @@ export interface ProjectWatcherConfig {
13
13
  refreshRouterRoutesCallback: () => Promise<void>;
14
14
  hmrManager: IHmrManager;
15
15
  bridge: IClientBridge;
16
+ /** When true, the host dev server owns browser dev-client bootstrap. */
17
+ hostOwnsDevClient?: boolean;
18
+ /** Delay before a change event is processed; 0 disables debouncing. */
19
+ changeDebounceMs?: number;
16
20
  }
17
21
  /**
18
22
  * ProjectWatcher handles file system changes for hot module replacement (HMR).
@@ -42,11 +46,14 @@ export declare class ProjectWatcher {
42
46
  private refreshRouterRoutesCallback;
43
47
  private hmrManager;
44
48
  private bridge;
49
+ private readonly hostOwnsDevClient;
45
50
  private readonly invalidationService;
51
+ private readonly changeDebounceMs;
46
52
  private watcher;
47
- private lastHandledChange;
53
+ private closed;
54
+ private pendingChangeEvents;
48
55
  private changeQueue;
49
- constructor({ config, refreshRouterRoutesCallback, hmrManager, bridge }: ProjectWatcherConfig);
56
+ constructor({ config, refreshRouterRoutesCallback, hmrManager, bridge, hostOwnsDevClient, changeDebounceMs, }: ProjectWatcherConfig);
50
57
  /**
51
58
  * Uncaches modules in the source directory to ensure fresh imports.
52
59
  * This is necessary for hot module replacement to work correctly.
@@ -55,6 +62,7 @@ export declare class ProjectWatcher {
55
62
  private uncacheModules;
56
63
  private isRouteSourceFile;
57
64
  private isIncludeSourceFile;
65
+ private requestBrowserReload;
58
66
  /**
59
67
  * Handles public directory file changes by copying only the changed file.
60
68
  * @param filePath - Absolute path of the changed file
@@ -70,7 +78,7 @@ export declare class ProjectWatcher {
70
78
  * Follows 5-rule priority:
71
79
  * 0. Public directory match? -> copy file and reload
72
80
  * 1. additionalWatchPaths match? -> reload
73
- * 2. Include template source? -> reload after processor notifications
81
+ * 2. Include template source? -> current-page refresh via HMR after processor notifications are deferred
74
82
  * 3. Processor-owned asset? -> processor already handled it via notification, skip HMR
75
83
  * 4. Otherwise -> HMR strategies
76
84
  *
@@ -84,6 +92,13 @@ export declare class ProjectWatcher {
84
92
  * @param event - The type of file system event
85
93
  */
86
94
  private handleFileChange;
95
+ private processFileChange;
96
+ /**
97
+ * Re-imports server modules before HMR broadcast so reload/refetch does not
98
+ * race stale in-memory imports or custom-element registry state.
99
+ */
100
+ private prewarmBeforeHmr;
101
+ private prewarmServerModuleImports;
87
102
  /**
88
103
  * Notifies all processors whose watch config matches the given file extension.
89
104
  * This is called before checking processor ownership so that dependency-only
@@ -101,9 +116,9 @@ export declare class ProjectWatcher {
101
116
  */
102
117
  private matchesAdditionalWatchPaths;
103
118
  /**
104
- * Checks if a file is handled by a processor.
105
- * Processors that declare asset capabilities own those file types.
106
- * Processors without capabilities fall back to checking watch extensions.
119
+ * Checks if a file is owned by a processor as an asset input.
120
+ * Ownership requires declared asset capabilities; watch config only drives
121
+ * {@link notifyProcessors} notifications.
107
122
  */
108
123
  private isHandledByProcessor;
109
124
  /**
@@ -133,4 +148,12 @@ export declare class ProjectWatcher {
133
148
  * rapid file changes efficiently.
134
149
  */
135
150
  createWatcherSubscription(): Promise<FSWatcher>;
151
+ /**
152
+ * Closes the active filesystem watcher subscription.
153
+ *
154
+ * @remarks
155
+ * Safe to call multiple times. Used when tearing down dev servers in tests
156
+ * and other short-lived Ecopages runtimes.
157
+ */
158
+ close(): Promise<void>;
136
159
  }
@@ -2,7 +2,14 @@ import path from "node:path";
2
2
  import chokidar, {} from "chokidar";
3
3
  import { fileSystem } from "@ecopages/file-system";
4
4
  import { appLogger } from "../global/app-logger.js";
5
- import { DevelopmentInvalidationService } from "../services/invalidation/development-invalidation.service.js";
5
+ import {
6
+ DevelopmentInvalidationService
7
+ } from "../services/invalidation/development-invalidation.service.js";
8
+ import { prepareHmrFileChange } from "../hmr/hmr-file-change-prep.js";
9
+ import { getAppPageBrowserGraphSession } from "../route-renderer/orchestration/page-browser-graph/page-browser-graph-session.js";
10
+ import { isRegisteredScriptEntrypoint } from "../hmr/hmr-entrypoint-output.js";
11
+ import { resolveInternalExecutionDir } from "../utils/resolve-work-dir.js";
12
+ import { createProjectWatcherIgnorePredicate } from "./project-watcher-ignore.js";
6
13
  class ProjectWatcher {
7
14
  /**
8
15
  * Duplicate identical watcher events within this window are ignored.
@@ -16,19 +23,33 @@ class ProjectWatcher {
16
23
  refreshRouterRoutesCallback;
17
24
  hmrManager;
18
25
  bridge;
26
+ hostOwnsDevClient;
19
27
  invalidationService;
28
+ changeDebounceMs;
20
29
  watcher = null;
21
- lastHandledChange = /* @__PURE__ */ new Map();
30
+ closed = false;
31
+ pendingChangeEvents = /* @__PURE__ */ new Map();
22
32
  changeQueue = Promise.resolve();
23
- constructor({ config, refreshRouterRoutesCallback, hmrManager, bridge }) {
33
+ constructor({
34
+ config,
35
+ refreshRouterRoutesCallback,
36
+ hmrManager,
37
+ bridge,
38
+ hostOwnsDevClient,
39
+ changeDebounceMs
40
+ }) {
24
41
  this.appConfig = config;
25
42
  this.refreshRouterRoutesCallback = refreshRouterRoutesCallback;
26
43
  this.hmrManager = hmrManager;
27
44
  this.bridge = bridge;
45
+ this.hostOwnsDevClient = hostOwnsDevClient === true;
46
+ const envDebounceMs = process.env.ECOPAGES_WATCH_CHANGE_DEBOUNCE_MS;
47
+ this.changeDebounceMs = changeDebounceMs ?? (envDebounceMs !== void 0 && envDebounceMs !== "" ? Number(envDebounceMs) : void 0) ?? ProjectWatcher.duplicateChangeWindowMs;
28
48
  this.invalidationService = new DevelopmentInvalidationService(config);
29
49
  this.triggerRouterRefresh = this.triggerRouterRefresh.bind(this);
30
50
  this.handleError = this.handleError.bind(this);
31
51
  this.handleFileChange = this.handleFileChange.bind(this);
52
+ this.processFileChange = this.processFileChange.bind(this);
32
53
  }
33
54
  /**
34
55
  * Uncaches modules in the source directory to ensure fresh imports.
@@ -51,6 +72,12 @@ class ProjectWatcher {
51
72
  isIncludeSourceFile(filePath) {
52
73
  return this.invalidationService.isIncludeSourceFile(filePath);
53
74
  }
75
+ requestBrowserReload() {
76
+ if (this.hostOwnsDevClient) {
77
+ return;
78
+ }
79
+ this.bridge.reload();
80
+ }
54
81
  /**
55
82
  * Handles public directory file changes by copying only the changed file.
56
83
  * @param filePath - Absolute path of the changed file
@@ -64,10 +91,10 @@ class ProjectWatcher {
64
91
  fileSystem.ensureDir(destDir);
65
92
  await fileSystem.copyFileAsync(filePath, destPath);
66
93
  }
67
- this.bridge.reload();
94
+ this.requestBrowserReload();
68
95
  } catch (error) {
69
96
  appLogger.error(`Failed to copy public file: ${error instanceof Error ? error.message : String(error)}`);
70
- this.bridge.reload();
97
+ this.requestBrowserReload();
71
98
  }
72
99
  }
73
100
  /**
@@ -77,13 +104,14 @@ class ProjectWatcher {
77
104
  enqueueChange(task) {
78
105
  const queuedTask = this.changeQueue.then(task, task);
79
106
  this.changeQueue = queuedTask.catch(() => void 0);
107
+ return queuedTask;
80
108
  }
81
109
  /**
82
110
  * Handles file changes by uncaching modules, refreshing routes, and delegating appropriately.
83
111
  * Follows 5-rule priority:
84
112
  * 0. Public directory match? -> copy file and reload
85
113
  * 1. additionalWatchPaths match? -> reload
86
- * 2. Include template source? -> reload after processor notifications
114
+ * 2. Include template source? -> current-page refresh via HMR after processor notifications are deferred
87
115
  * 3. Processor-owned asset? -> processor already handled it via notification, skip HMR
88
116
  * 4. Otherwise -> HMR strategies
89
117
  *
@@ -96,14 +124,26 @@ class ProjectWatcher {
96
124
  * @param rawPath - Path of the changed file
97
125
  * @param event - The type of file system event
98
126
  */
99
- async handleFileChange(rawPath, event = "change") {
127
+ handleFileChange(rawPath, event = "change") {
128
+ if (this.closed) {
129
+ return Promise.resolve();
130
+ }
100
131
  const filePath = path.resolve(rawPath);
101
- const now = Date.now();
102
- const lastHandledAt = this.lastHandledChange.get(filePath);
103
- if (lastHandledAt !== void 0 && now - lastHandledAt < ProjectWatcher.duplicateChangeWindowMs) {
104
- return;
132
+ if (this.changeDebounceMs === 0) {
133
+ return this.enqueueChange(() => this.processFileChange(filePath, event));
134
+ }
135
+ const existing = this.pendingChangeEvents.get(filePath);
136
+ if (existing) {
137
+ clearTimeout(existing.timer);
105
138
  }
106
- this.lastHandledChange.set(filePath, now);
139
+ const timer = setTimeout(() => {
140
+ this.pendingChangeEvents.delete(filePath);
141
+ void this.enqueueChange(() => this.processFileChange(filePath, event));
142
+ }, this.changeDebounceMs);
143
+ this.pendingChangeEvents.set(filePath, { event, timer });
144
+ return Promise.resolve();
145
+ }
146
+ async processFileChange(filePath, event) {
107
147
  try {
108
148
  const plan = this.invalidationService.planFileChange(filePath);
109
149
  if (plan.category === "public-asset") {
@@ -111,26 +151,42 @@ class ProjectWatcher {
111
151
  return;
112
152
  }
113
153
  this.uncacheModules();
114
- if (plan.invalidateServerModules) {
154
+ const resolvedFilePath = path.resolve(filePath);
155
+ const graphPreparation = this.hmrManager.isEnabled() ? prepareHmrFileChange(this.appConfig, resolvedFilePath) : void 0;
156
+ if (plan.refreshRoutes && (event === "unlink" || event === "add")) {
157
+ getAppPageBrowserGraphSession(this.appConfig).invalidateByRouteFile(resolvedFilePath);
158
+ }
159
+ const isRegisteredScriptEdit = isRegisteredScriptEntrypoint(
160
+ this.hmrManager.getWatchedFiles(),
161
+ resolvedFilePath
162
+ );
163
+ if (plan.invalidateServerModules && !isRegisteredScriptEdit) {
115
164
  this.invalidationService.invalidateServerModules([filePath]);
116
165
  }
117
166
  if (plan.refreshRoutes) {
118
167
  await this.refreshRouterRoutesCallback();
119
168
  }
120
- if (plan.category === "additional-watch") {
121
- this.bridge.reload();
169
+ if (plan.reloadBrowser) {
170
+ this.requestBrowserReload();
122
171
  return;
123
172
  }
124
- await this.notifyProcessors(filePath, event);
125
- if (plan.category === "include-source") {
126
- this.bridge.reload();
173
+ const deferProcessorNotifications = plan.category === "include-source" || plan.category === "explicit-server-view" || isRegisteredScriptEdit;
174
+ if (deferProcessorNotifications && plan.delegateToHmr) {
175
+ await this.prewarmBeforeHmr(resolvedFilePath, plan);
176
+ await this.hmrManager.handleFileChange(filePath, {
177
+ graphIdentities: graphPreparation?.affectedGraphIdentities
178
+ });
179
+ await this.notifyProcessors(filePath, event);
127
180
  return;
128
181
  }
182
+ await this.notifyProcessors(filePath, event);
129
183
  if (plan.processorHandledAsset) {
130
184
  return;
131
185
  }
132
186
  if (plan.delegateToHmr) {
133
- await this.hmrManager.handleFileChange(filePath);
187
+ await this.hmrManager.handleFileChange(filePath, {
188
+ graphIdentities: graphPreparation?.affectedGraphIdentities
189
+ });
134
190
  }
135
191
  } catch (error) {
136
192
  if (error instanceof Error) {
@@ -139,6 +195,42 @@ class ProjectWatcher {
139
195
  }
140
196
  }
141
197
  }
198
+ /**
199
+ * Re-imports server modules before HMR broadcast so reload/refetch does not
200
+ * race stale in-memory imports or custom-element registry state.
201
+ */
202
+ async prewarmBeforeHmr(filePath, plan) {
203
+ if (plan.category !== "include-source" && plan.category !== "explicit-server-view") {
204
+ return;
205
+ }
206
+ const modulePaths = plan.category === "include-source" ? [this.appConfig.absolutePaths.htmlTemplatePath] : [path.resolve(filePath)];
207
+ await this.prewarmServerModuleImports(modulePaths, { scope: "server template" });
208
+ }
209
+ async prewarmServerModuleImports(modulePaths, options) {
210
+ const appModuleLoader = this.appConfig.runtime?.appModuleLoader;
211
+ if (!appModuleLoader) {
212
+ return;
213
+ }
214
+ const outdir = path.join(resolveInternalExecutionDir(this.appConfig), ".server-modules");
215
+ for (const modulePath of modulePaths) {
216
+ if (!modulePath) {
217
+ continue;
218
+ }
219
+ try {
220
+ await appModuleLoader.importModule({
221
+ filePath: modulePath,
222
+ rootDir: this.appConfig.rootDir,
223
+ outdir,
224
+ externalPackages: true,
225
+ bypassCache: options.bypassCache
226
+ });
227
+ } catch (error) {
228
+ appLogger.error(
229
+ `Failed to prewarm ${options.scope} ${modulePath}: ${error instanceof Error ? error.message : String(error)}`
230
+ );
231
+ }
232
+ }
233
+ }
142
234
  /**
143
235
  * Notifies all processors whose watch config matches the given file extension.
144
236
  * This is called before checking processor ownership so that dependency-only
@@ -183,9 +275,9 @@ class ProjectWatcher {
183
275
  return this.invalidationService.matchesAdditionalWatchPaths(filePath);
184
276
  }
185
277
  /**
186
- * Checks if a file is handled by a processor.
187
- * Processors that declare asset capabilities own those file types.
188
- * Processors without capabilities fall back to checking watch extensions.
278
+ * Checks if a file is owned by a processor as an asset input.
279
+ * Ownership requires declared asset capabilities; watch config only drives
280
+ * {@link notifyProcessors} notifications.
189
281
  */
190
282
  isHandledByProcessor(filePath) {
191
283
  return this.invalidationService.isProcessorOwnedAsset(filePath);
@@ -231,36 +323,37 @@ class ProjectWatcher {
231
323
  if (this.watcher) {
232
324
  return this.watcher;
233
325
  }
234
- const processorPaths = [];
326
+ const processorPaths = /* @__PURE__ */ new Set();
235
327
  for (const processor of this.appConfig.processors.values()) {
236
328
  const watchConfig = processor.getWatchConfig();
237
329
  if (!watchConfig) continue;
238
- processorPaths.push(...watchConfig.paths);
330
+ for (const watchPath of watchConfig.paths) {
331
+ processorPaths.add(watchPath);
332
+ }
239
333
  }
240
334
  if (fileSystem.exists(this.appConfig.absolutePaths.includesDir)) {
241
- processorPaths.push(this.appConfig.absolutePaths.includesDir);
335
+ processorPaths.add(this.appConfig.absolutePaths.includesDir);
242
336
  }
243
337
  if (fileSystem.exists(this.appConfig.absolutePaths.srcDir)) {
244
- processorPaths.push(this.appConfig.absolutePaths.srcDir);
245
- }
246
- if (fileSystem.exists(this.appConfig.absolutePaths.pagesDir)) {
247
- processorPaths.push(this.appConfig.absolutePaths.pagesDir);
338
+ processorPaths.add(this.appConfig.absolutePaths.srcDir);
248
339
  }
249
340
  if (fileSystem.exists(this.appConfig.absolutePaths.publicDir)) {
250
- processorPaths.push(this.appConfig.absolutePaths.publicDir);
341
+ processorPaths.add(this.appConfig.absolutePaths.publicDir);
251
342
  }
252
- if (this.appConfig.additionalWatchPaths.length) {
253
- processorPaths.push(...this.appConfig.additionalWatchPaths);
343
+ for (const watchPath of this.appConfig.additionalWatchPaths) {
344
+ processorPaths.add(watchPath);
254
345
  }
255
- this.watcher = chokidar.watch(processorPaths, {
346
+ const ignored = createProjectWatcherIgnorePredicate(this.appConfig.absolutePaths);
347
+ this.watcher = chokidar.watch(Array.from(processorPaths), {
256
348
  ignoreInitial: true,
257
349
  ignorePermissionErrors: true,
350
+ ignored,
258
351
  awaitWriteFinish: {
259
352
  stabilityThreshold: 50,
260
353
  pollInterval: 50
261
354
  }
262
355
  });
263
- this.watcher.on("change", (p) => this.enqueueChange(() => this.handleFileChange(p, "change"))).on("add", (p) => this.enqueueChange(() => this.handleFileChange(p, "add"))).on("addDir", (p) => this.enqueueChange(() => this.triggerRouterRefresh(p))).on("unlink", (p) => this.enqueueChange(() => this.handleFileChange(p, "unlink"))).on("unlinkDir", (p) => this.enqueueChange(() => this.triggerRouterRefresh(p))).on("error", (error) => this.handleError(error));
356
+ this.watcher.on("change", (p) => this.handleFileChange(p, "change")).on("add", (p) => this.handleFileChange(p, "add")).on("addDir", (p) => this.enqueueChange(() => this.triggerRouterRefresh(p))).on("unlink", (p) => this.handleFileChange(p, "unlink")).on("unlinkDir", (p) => this.enqueueChange(() => this.triggerRouterRefresh(p))).on("error", (error) => this.handleError(error));
264
357
  for (const processor of this.appConfig.processors.values()) {
265
358
  const watchConfig = processor.getWatchConfig();
266
359
  if (watchConfig?.onError) {
@@ -269,6 +362,25 @@ class ProjectWatcher {
269
362
  }
270
363
  return this.watcher;
271
364
  }
365
+ /**
366
+ * Closes the active filesystem watcher subscription.
367
+ *
368
+ * @remarks
369
+ * Safe to call multiple times. Used when tearing down dev servers in tests
370
+ * and other short-lived Ecopages runtimes.
371
+ */
372
+ async close() {
373
+ this.closed = true;
374
+ for (const pending of this.pendingChangeEvents.values()) {
375
+ clearTimeout(pending.timer);
376
+ }
377
+ this.pendingChangeEvents.clear();
378
+ if (this.watcher) {
379
+ await this.watcher.close();
380
+ this.watcher = null;
381
+ }
382
+ await this.changeQueue.catch(() => void 0);
383
+ }
272
384
  }
273
385
  export {
274
386
  ProjectWatcher
@@ -6,21 +6,21 @@ const createMockHmrManager = () => ({
6
6
  }),
7
7
  setEnabled: vi.fn(() => {
8
8
  }),
9
- setPlugins: vi.fn(() => {
10
- }),
11
9
  registerEntrypoint: vi.fn(async () => ""),
12
- registerScriptEntrypoint: vi.fn(async () => ""),
10
+ registerScriptEntrypoint: vi.fn(async () => ({
11
+ sourcePath: "",
12
+ outputPath: "",
13
+ outputUrl: ""
14
+ })),
13
15
  registerStrategy: vi.fn(() => {
14
16
  }),
15
17
  isEnabled: vi.fn(() => true),
16
18
  getOutputUrl: vi.fn(() => void 0),
17
19
  getWatchedFiles: vi.fn(() => /* @__PURE__ */ new Map()),
18
20
  getDistDir: vi.fn(() => ""),
19
- getPlugins: vi.fn(() => []),
20
21
  getDefaultContext: vi.fn(() => ({
21
22
  getWatchedFiles: () => /* @__PURE__ */ new Map(),
22
23
  getDistDir: () => "",
23
- getPlugins: () => [],
24
24
  getSrcDir: () => "",
25
25
  getLayoutsDir: () => "",
26
26
  getPagesDir: () => "",