@ecopages/core 0.2.0-alpha.4 → 0.2.0-alpha.6

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 (418) hide show
  1. package/README.md +213 -12
  2. package/package.json +100 -188
  3. package/src/adapters/README.md +39 -0
  4. package/src/adapters/bun/hmr-manager.test.ts +267 -0
  5. package/src/adapters/bun/hmr-manager.ts +181 -68
  6. package/src/adapters/bun/index.ts +1 -2
  7. package/src/adapters/bun/server-adapter.ts +41 -34
  8. package/src/adapters/bun/server-lifecycle.ts +40 -70
  9. package/src/adapters/index.ts +1 -1
  10. package/src/adapters/node/bootstrap-dependency-resolver.test.ts +282 -0
  11. package/src/adapters/node/bootstrap-dependency-resolver.ts +301 -0
  12. package/src/adapters/node/index.ts +7 -0
  13. package/src/adapters/node/node-client-bridge.test.ts +198 -0
  14. package/src/adapters/node/node-hmr-manager.test.ts +322 -0
  15. package/src/adapters/node/node-hmr-manager.ts +208 -116
  16. package/src/adapters/node/runtime-adapter.test.ts +868 -0
  17. package/src/adapters/node/runtime-adapter.ts +439 -0
  18. package/src/adapters/node/server-adapter.ts +31 -104
  19. package/src/adapters/node/static-content-server.test.ts +60 -0
  20. package/src/adapters/node/static-content-server.ts +36 -0
  21. package/src/adapters/node/write-runtime-manifest.ts +38 -0
  22. package/src/adapters/shared/api-response.test.ts +97 -0
  23. package/src/{define-api-handler.ts → adapters/shared/define-api-handler.ts} +1 -1
  24. package/src/adapters/shared/explicit-static-route-matcher.test.ts +381 -0
  25. package/src/adapters/shared/explicit-static-route-matcher.ts +7 -1
  26. package/src/adapters/shared/file-route-middleware-pipeline.test.ts +90 -0
  27. package/src/adapters/shared/file-route-middleware-pipeline.ts +6 -2
  28. package/src/adapters/shared/fs-server-response-factory.test.ts +187 -0
  29. package/src/adapters/shared/fs-server-response-matcher.test.ts +286 -0
  30. package/src/adapters/shared/fs-server-response-matcher.ts +17 -10
  31. package/src/adapters/shared/hmr-entrypoint-registrar.ts +149 -0
  32. package/src/adapters/shared/hmr-html-response.ts +52 -0
  33. package/src/adapters/shared/hmr-manager.contract.test.ts +196 -0
  34. package/src/adapters/shared/hmr-manager.dispatch.test.ts +220 -0
  35. package/src/adapters/shared/render-context.test.ts +146 -0
  36. package/src/adapters/shared/render-context.ts +21 -6
  37. package/src/adapters/shared/runtime-bootstrap.ts +79 -0
  38. package/src/adapters/shared/server-adapter.test.ts +77 -0
  39. package/src/adapters/shared/server-adapter.ts +51 -4
  40. package/src/adapters/shared/server-route-handler.test.ts +110 -0
  41. package/src/adapters/shared/server-route-handler.ts +5 -18
  42. package/src/adapters/shared/server-static-builder.test.ts +316 -0
  43. package/src/adapters/shared/server-static-builder.ts +92 -8
  44. package/src/build/README.md +101 -0
  45. package/src/build/build-adapter-serialization.test.ts +268 -0
  46. package/src/build/build-adapter.test.ts +815 -0
  47. package/src/build/build-adapter.ts +235 -6
  48. package/src/build/build-manifest.ts +54 -0
  49. package/src/build/dev-build-coordinator.ts +221 -0
  50. package/src/build/esbuild-build-adapter.ts +132 -83
  51. package/src/build/runtime-build-executor.ts +34 -0
  52. package/src/build/runtime-specifier-alias-plugin.test.ts +43 -0
  53. package/src/build/runtime-specifier-alias-plugin.ts +58 -0
  54. package/src/config/README.md +33 -0
  55. package/src/config/config-builder.test.ts +410 -0
  56. package/src/config/config-builder.ts +281 -49
  57. package/src/constants.ts +15 -0
  58. package/src/declarations.d.ts +18 -13
  59. package/src/eco/README.md +70 -16
  60. package/src/eco/component-render-context.ts +39 -17
  61. package/src/eco/eco.test.ts +678 -0
  62. package/src/eco/eco.ts +29 -8
  63. package/src/eco/eco.types.ts +20 -1
  64. package/src/eco/eco.utils.test.ts +124 -0
  65. package/src/eco/global-injector-map.test.ts +42 -0
  66. package/src/eco/lazy-injector-map.test.ts +66 -0
  67. package/src/eco/module-dependencies.test.ts +30 -0
  68. package/src/errors/http-error.test.ts +134 -0
  69. package/src/global/utils.test.ts +12 -0
  70. package/src/hmr/README.md +26 -0
  71. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-have-HMR-script-injected-in-page-1.png +0 -0
  72. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-load-fixture-app-page-1.png +0 -0
  73. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-WebSocket-Connection-should-connect-to-correct-HMR-endpoint-1.png +0 -0
  74. package/src/hmr/client/hmr-runtime.ts +38 -7
  75. package/src/hmr/hmr-strategy.test.ts +124 -0
  76. package/src/hmr/hmr.postcss.test.e2e.ts +41 -0
  77. package/src/hmr/hmr.test.e2e.ts +29 -38
  78. package/src/hmr/strategies/js-hmr-strategy.test.ts +335 -0
  79. package/src/hmr/strategies/js-hmr-strategy.ts +115 -115
  80. package/src/index.ts +1 -1
  81. package/src/integrations/ghtml/ghtml-renderer.test.ts +63 -0
  82. package/src/integrations/ghtml/ghtml-renderer.ts +4 -1
  83. package/src/internal-types.ts +39 -19
  84. package/src/plugins/README.md +34 -0
  85. package/src/plugins/alias-resolver-plugin.test.ts +41 -0
  86. package/src/plugins/alias-resolver-plugin.ts +21 -3
  87. package/src/plugins/eco-component-meta-plugin.test.ts +380 -0
  88. package/src/plugins/eco-component-meta-plugin.ts +10 -3
  89. package/src/plugins/integration-plugin.test.ts +111 -0
  90. package/src/plugins/integration-plugin.ts +45 -3
  91. package/src/plugins/processor.test.ts +148 -0
  92. package/src/plugins/processor.ts +22 -2
  93. package/src/plugins/runtime-capability.ts +14 -0
  94. package/src/public-types.ts +73 -16
  95. package/src/route-renderer/GRAPH.md +16 -20
  96. package/src/route-renderer/README.md +8 -21
  97. package/src/route-renderer/component-graph/component-graph-executor.test.ts +41 -0
  98. package/src/route-renderer/component-graph/component-graph.test.ts +63 -0
  99. package/src/route-renderer/component-graph/component-marker.test.ts +73 -0
  100. package/src/route-renderer/component-graph/component-reference.ts +29 -0
  101. package/src/route-renderer/component-graph/marker-graph-resolver.test.ts +135 -0
  102. package/src/route-renderer/{marker-graph-resolver.ts → component-graph/marker-graph-resolver.ts} +11 -9
  103. package/src/route-renderer/orchestration/integration-renderer.test.ts +936 -0
  104. package/src/route-renderer/{integration-renderer.ts → orchestration/integration-renderer.ts} +113 -19
  105. package/src/route-renderer/orchestration/render-execution.service.test.ts +97 -0
  106. package/src/route-renderer/{render-execution.service.ts → orchestration/render-execution.service.ts} +109 -37
  107. package/src/route-renderer/orchestration/render-preparation.service.test.ts +235 -0
  108. package/src/route-renderer/{render-preparation.service.ts → orchestration/render-preparation.service.ts} +127 -9
  109. package/src/route-renderer/page-loading/dependency-resolver.test.ts +345 -0
  110. package/src/route-renderer/{dependency-resolver.ts → page-loading/dependency-resolver.ts} +28 -12
  111. package/src/route-renderer/page-loading/page-module-loader.test.ts +96 -0
  112. package/src/route-renderer/{page-module-loader.ts → page-loading/page-module-loader.ts} +49 -21
  113. package/src/route-renderer/route-renderer.ts +36 -1
  114. package/src/router/README.md +26 -0
  115. package/src/router/client/link-intent.d.ts +53 -0
  116. package/src/router/client/link-intent.test.browser.ts +51 -0
  117. package/src/router/client/link-intent.ts +92 -0
  118. package/src/router/client/navigation-coordinator.test.ts +237 -0
  119. package/src/router/client/navigation-coordinator.ts +433 -0
  120. package/src/router/server/fs-router-scanner.test.ts +83 -0
  121. package/src/router/{fs-router-scanner.ts → server/fs-router-scanner.ts} +12 -10
  122. package/src/router/server/fs-router.test.ts +214 -0
  123. package/src/router/{fs-router.ts → server/fs-router.ts} +2 -2
  124. package/src/services/README.md +29 -0
  125. package/src/services/assets/asset-processing-service/asset-processing.service.test.ts +385 -0
  126. package/src/services/{asset-processing-service → assets/asset-processing-service}/asset-processing.service.ts +101 -6
  127. package/src/services/assets/asset-processing-service/asset.factory.test.ts +63 -0
  128. package/src/services/{asset-processing-service → assets/asset-processing-service}/asset.factory.ts +2 -2
  129. package/src/services/{asset-processing-service → assets/asset-processing-service}/assets.types.ts +2 -1
  130. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.test.ts +72 -0
  131. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.ts +95 -0
  132. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.test.ts +67 -0
  133. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.ts +78 -0
  134. package/src/services/{asset-processing-service → assets/asset-processing-service}/index.ts +2 -0
  135. package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.interface.ts +1 -1
  136. package/src/services/assets/asset-processing-service/processors/base/base-processor.test.ts +59 -0
  137. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-processor.ts +11 -5
  138. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-script-processor.ts +17 -27
  139. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.test.ts +286 -0
  140. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/file-script.processor.ts +3 -3
  141. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.test.ts +227 -0
  142. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/node-module-script.processor.ts +5 -4
  143. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.test.ts +199 -0
  144. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/file-stylesheet.processor.ts +4 -1
  145. package/src/services/assets/browser-bundle.service.test.ts +36 -0
  146. package/src/services/assets/browser-bundle.service.ts +53 -0
  147. package/src/services/cache/index.ts +3 -3
  148. package/src/services/cache/memory-cache-store.test.ts +225 -0
  149. package/src/services/cache/memory-cache-store.ts +1 -1
  150. package/src/services/cache/page-cache-service.test.ts +175 -0
  151. package/src/services/cache/page-cache-service.ts +3 -3
  152. package/src/services/cache/page-request-cache-coordinator.service.test.ts +79 -0
  153. package/src/services/{page-request-cache-coordinator.service.ts → cache/page-request-cache-coordinator.service.ts} +9 -6
  154. package/src/services/html/html-rewriter-provider.service.test.ts +183 -0
  155. package/src/services/html/html-rewriter-provider.service.ts +103 -0
  156. package/src/services/html/html-transformer.service.test.ts +378 -0
  157. package/src/services/html/html-transformer.service.ts +279 -0
  158. package/src/services/invalidation/development-invalidation.service.test.ts +77 -0
  159. package/src/services/invalidation/development-invalidation.service.ts +261 -0
  160. package/src/services/module-loading/app-server-module-transpiler.service.ts +52 -0
  161. package/src/services/module-loading/page-module-import.service.test.ts +253 -0
  162. package/src/services/module-loading/page-module-import.service.ts +200 -0
  163. package/src/services/module-loading/server-loader.service.test.ts +161 -0
  164. package/src/services/module-loading/server-loader.service.ts +130 -0
  165. package/src/services/module-loading/server-module-transpiler.service.test.ts +115 -0
  166. package/src/services/module-loading/server-module-transpiler.service.ts +105 -0
  167. package/src/services/runtime-manifest/node-runtime-manifest.service.test.ts +95 -0
  168. package/src/services/runtime-manifest/node-runtime-manifest.service.ts +101 -0
  169. package/src/services/runtime-state/dev-graph.service.ts +217 -0
  170. package/src/services/runtime-state/entrypoint-dependency-graph.service.ts +136 -0
  171. package/src/services/runtime-state/runtime-specifier-registry.service.ts +96 -0
  172. package/src/services/runtime-state/server-invalidation-state.service.ts +68 -0
  173. package/src/services/validation/schema-validation-service.test.ts +223 -0
  174. package/src/services/{schema-validation-service.ts → validation/schema-validation-service.ts} +1 -1
  175. package/src/static-site-generator/README.md +26 -0
  176. package/src/static-site-generator/static-site-generator.test.ts +307 -0
  177. package/src/static-site-generator/static-site-generator.ts +109 -6
  178. package/src/utils/deep-merge.test.ts +114 -0
  179. package/src/utils/invariant.test.ts +22 -0
  180. package/src/utils/path-utils.test.ts +15 -0
  181. package/src/utils/resolve-work-dir.ts +45 -0
  182. package/src/utils/server-utils.test.ts +38 -0
  183. package/src/watchers/project-watcher.integration.test.ts +337 -0
  184. package/src/watchers/project-watcher.test-helpers.ts +1 -1
  185. package/src/watchers/project-watcher.test.ts +678 -0
  186. package/src/watchers/project-watcher.ts +130 -111
  187. package/CHANGELOG.md +0 -91
  188. package/src/adapters/abstract/application-adapter.d.ts +0 -168
  189. package/src/adapters/abstract/application-adapter.js +0 -109
  190. package/src/adapters/abstract/router-adapter.d.ts +0 -26
  191. package/src/adapters/abstract/router-adapter.js +0 -5
  192. package/src/adapters/abstract/server-adapter.d.ts +0 -69
  193. package/src/adapters/abstract/server-adapter.js +0 -15
  194. package/src/adapters/bun/client-bridge.d.ts +0 -34
  195. package/src/adapters/bun/client-bridge.js +0 -48
  196. package/src/adapters/bun/create-app.d.ts +0 -60
  197. package/src/adapters/bun/create-app.js +0 -117
  198. package/src/adapters/bun/define-api-handler.d.ts +0 -61
  199. package/src/adapters/bun/define-api-handler.js +0 -15
  200. package/src/adapters/bun/define-api-handler.ts +0 -114
  201. package/src/adapters/bun/hmr-manager.d.ts +0 -85
  202. package/src/adapters/bun/hmr-manager.js +0 -240
  203. package/src/adapters/bun/index.d.ts +0 -3
  204. package/src/adapters/bun/index.js +0 -8
  205. package/src/adapters/bun/server-adapter.d.ts +0 -155
  206. package/src/adapters/bun/server-adapter.js +0 -368
  207. package/src/adapters/bun/server-lifecycle.d.ts +0 -52
  208. package/src/adapters/bun/server-lifecycle.js +0 -120
  209. package/src/adapters/index.d.ts +0 -6
  210. package/src/adapters/index.js +0 -14
  211. package/src/adapters/node/create-app.d.ts +0 -21
  212. package/src/adapters/node/create-app.js +0 -143
  213. package/src/adapters/node/index.d.ts +0 -4
  214. package/src/adapters/node/index.js +0 -8
  215. package/src/adapters/node/node-client-bridge.d.ts +0 -26
  216. package/src/adapters/node/node-client-bridge.js +0 -66
  217. package/src/adapters/node/node-hmr-manager.d.ts +0 -63
  218. package/src/adapters/node/node-hmr-manager.js +0 -237
  219. package/src/adapters/node/server-adapter.d.ts +0 -190
  220. package/src/adapters/node/server-adapter.js +0 -420
  221. package/src/adapters/node/static-content-server.d.ts +0 -24
  222. package/src/adapters/node/static-content-server.js +0 -166
  223. package/src/adapters/shared/api-response.d.ts +0 -52
  224. package/src/adapters/shared/api-response.js +0 -96
  225. package/src/adapters/shared/application-adapter.d.ts +0 -18
  226. package/src/adapters/shared/application-adapter.js +0 -90
  227. package/src/adapters/shared/explicit-static-route-matcher.d.ts +0 -38
  228. package/src/adapters/shared/explicit-static-route-matcher.js +0 -100
  229. package/src/adapters/shared/file-route-middleware-pipeline.d.ts +0 -65
  230. package/src/adapters/shared/file-route-middleware-pipeline.js +0 -98
  231. package/src/adapters/shared/fs-server-response-factory.d.ts +0 -19
  232. package/src/adapters/shared/fs-server-response-factory.js +0 -97
  233. package/src/adapters/shared/fs-server-response-matcher.d.ts +0 -71
  234. package/src/adapters/shared/fs-server-response-matcher.js +0 -155
  235. package/src/adapters/shared/render-context.d.ts +0 -14
  236. package/src/adapters/shared/render-context.js +0 -69
  237. package/src/adapters/shared/server-adapter.d.ts +0 -87
  238. package/src/adapters/shared/server-adapter.js +0 -353
  239. package/src/adapters/shared/server-route-handler.d.ts +0 -89
  240. package/src/adapters/shared/server-route-handler.js +0 -120
  241. package/src/adapters/shared/server-static-builder.d.ts +0 -38
  242. package/src/adapters/shared/server-static-builder.js +0 -46
  243. package/src/build/build-adapter.d.ts +0 -74
  244. package/src/build/build-adapter.js +0 -54
  245. package/src/build/build-types.d.ts +0 -57
  246. package/src/build/build-types.js +0 -0
  247. package/src/build/esbuild-build-adapter.d.ts +0 -69
  248. package/src/build/esbuild-build-adapter.js +0 -390
  249. package/src/config/config-builder.d.ts +0 -227
  250. package/src/config/config-builder.js +0 -392
  251. package/src/constants.d.ts +0 -32
  252. package/src/constants.js +0 -21
  253. package/src/create-app.d.ts +0 -17
  254. package/src/create-app.js +0 -66
  255. package/src/define-api-handler.d.ts +0 -25
  256. package/src/define-api-handler.js +0 -15
  257. package/src/dev/sc-server.d.ts +0 -30
  258. package/src/dev/sc-server.js +0 -111
  259. package/src/eco/component-render-context.d.ts +0 -105
  260. package/src/eco/component-render-context.js +0 -77
  261. package/src/eco/eco.d.ts +0 -9
  262. package/src/eco/eco.js +0 -110
  263. package/src/eco/eco.types.d.ts +0 -170
  264. package/src/eco/eco.types.js +0 -0
  265. package/src/eco/eco.utils.d.ts +0 -40
  266. package/src/eco/eco.utils.js +0 -40
  267. package/src/eco/global-injector-map.d.ts +0 -16
  268. package/src/eco/global-injector-map.js +0 -80
  269. package/src/eco/lazy-injector-map.d.ts +0 -8
  270. package/src/eco/lazy-injector-map.js +0 -70
  271. package/src/eco/module-dependencies.d.ts +0 -18
  272. package/src/eco/module-dependencies.js +0 -49
  273. package/src/errors/http-error.d.ts +0 -31
  274. package/src/errors/http-error.js +0 -50
  275. package/src/errors/index.d.ts +0 -2
  276. package/src/errors/index.js +0 -4
  277. package/src/errors/locals-access-error.d.ts +0 -4
  278. package/src/errors/locals-access-error.js +0 -9
  279. package/src/global/app-logger.d.ts +0 -2
  280. package/src/global/app-logger.js +0 -6
  281. package/src/hmr/client/hmr-runtime.d.ts +0 -10
  282. package/src/hmr/client/hmr-runtime.js +0 -86
  283. package/src/hmr/hmr-strategy.d.ts +0 -159
  284. package/src/hmr/hmr-strategy.js +0 -29
  285. package/src/hmr/hmr.test.e2e.d.ts +0 -1
  286. package/src/hmr/hmr.test.e2e.js +0 -50
  287. package/src/hmr/strategies/default-hmr-strategy.d.ts +0 -43
  288. package/src/hmr/strategies/default-hmr-strategy.js +0 -34
  289. package/src/hmr/strategies/js-hmr-strategy.d.ts +0 -136
  290. package/src/hmr/strategies/js-hmr-strategy.js +0 -188
  291. package/src/index.browser.d.ts +0 -3
  292. package/src/index.browser.js +0 -4
  293. package/src/index.d.ts +0 -5
  294. package/src/index.js +0 -10
  295. package/src/integrations/ghtml/ghtml-renderer.d.ts +0 -15
  296. package/src/integrations/ghtml/ghtml-renderer.js +0 -60
  297. package/src/integrations/ghtml/ghtml.plugin.d.ts +0 -20
  298. package/src/integrations/ghtml/ghtml.plugin.js +0 -21
  299. package/src/internal-types.d.ts +0 -200
  300. package/src/internal-types.js +0 -0
  301. package/src/plugins/alias-resolver-plugin.d.ts +0 -2
  302. package/src/plugins/alias-resolver-plugin.js +0 -39
  303. package/src/plugins/eco-component-meta-plugin.d.ts +0 -95
  304. package/src/plugins/eco-component-meta-plugin.js +0 -157
  305. package/src/plugins/integration-plugin.d.ts +0 -102
  306. package/src/plugins/integration-plugin.js +0 -100
  307. package/src/plugins/processor.d.ts +0 -82
  308. package/src/plugins/processor.js +0 -122
  309. package/src/public-types.d.ts +0 -1098
  310. package/src/public-types.js +0 -0
  311. package/src/route-renderer/component-graph-executor.d.ts +0 -32
  312. package/src/route-renderer/component-graph-executor.js +0 -31
  313. package/src/route-renderer/component-graph.d.ts +0 -42
  314. package/src/route-renderer/component-graph.js +0 -72
  315. package/src/route-renderer/component-marker.d.ts +0 -52
  316. package/src/route-renderer/component-marker.js +0 -46
  317. package/src/route-renderer/dependency-resolver.d.ts +0 -24
  318. package/src/route-renderer/dependency-resolver.js +0 -428
  319. package/src/route-renderer/html-post-processing.service.d.ts +0 -40
  320. package/src/route-renderer/html-post-processing.service.js +0 -86
  321. package/src/route-renderer/html-post-processing.service.ts +0 -103
  322. package/src/route-renderer/integration-renderer.d.ts +0 -339
  323. package/src/route-renderer/integration-renderer.js +0 -526
  324. package/src/route-renderer/marker-graph-resolver.d.ts +0 -76
  325. package/src/route-renderer/marker-graph-resolver.js +0 -93
  326. package/src/route-renderer/page-module-loader.d.ts +0 -61
  327. package/src/route-renderer/page-module-loader.js +0 -102
  328. package/src/route-renderer/render-execution.service.d.ts +0 -69
  329. package/src/route-renderer/render-execution.service.js +0 -91
  330. package/src/route-renderer/render-preparation.service.d.ts +0 -112
  331. package/src/route-renderer/render-preparation.service.js +0 -243
  332. package/src/route-renderer/route-renderer.d.ts +0 -26
  333. package/src/route-renderer/route-renderer.js +0 -68
  334. package/src/router/fs-router-scanner.d.ts +0 -41
  335. package/src/router/fs-router-scanner.js +0 -155
  336. package/src/router/fs-router.d.ts +0 -26
  337. package/src/router/fs-router.js +0 -100
  338. package/src/services/asset-processing-service/asset-processing.service.d.ts +0 -41
  339. package/src/services/asset-processing-service/asset-processing.service.js +0 -250
  340. package/src/services/asset-processing-service/asset.factory.d.ts +0 -17
  341. package/src/services/asset-processing-service/asset.factory.js +0 -82
  342. package/src/services/asset-processing-service/assets.types.d.ts +0 -88
  343. package/src/services/asset-processing-service/assets.types.js +0 -0
  344. package/src/services/asset-processing-service/index.d.ts +0 -3
  345. package/src/services/asset-processing-service/index.js +0 -3
  346. package/src/services/asset-processing-service/processor.interface.d.ts +0 -22
  347. package/src/services/asset-processing-service/processor.interface.js +0 -6
  348. package/src/services/asset-processing-service/processor.registry.d.ts +0 -8
  349. package/src/services/asset-processing-service/processor.registry.js +0 -15
  350. package/src/services/asset-processing-service/processors/base/base-processor.d.ts +0 -24
  351. package/src/services/asset-processing-service/processors/base/base-processor.js +0 -59
  352. package/src/services/asset-processing-service/processors/base/base-script-processor.d.ts +0 -16
  353. package/src/services/asset-processing-service/processors/base/base-script-processor.js +0 -80
  354. package/src/services/asset-processing-service/processors/index.d.ts +0 -5
  355. package/src/services/asset-processing-service/processors/index.js +0 -5
  356. package/src/services/asset-processing-service/processors/script/content-script.processor.d.ts +0 -5
  357. package/src/services/asset-processing-service/processors/script/content-script.processor.js +0 -57
  358. package/src/services/asset-processing-service/processors/script/file-script.processor.d.ts +0 -8
  359. package/src/services/asset-processing-service/processors/script/file-script.processor.js +0 -76
  360. package/src/services/asset-processing-service/processors/script/node-module-script.processor.d.ts +0 -7
  361. package/src/services/asset-processing-service/processors/script/node-module-script.processor.js +0 -74
  362. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -5
  363. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +0 -25
  364. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -9
  365. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +0 -63
  366. package/src/services/cache/cache.types.d.ts +0 -107
  367. package/src/services/cache/cache.types.js +0 -0
  368. package/src/services/cache/index.d.ts +0 -7
  369. package/src/services/cache/index.js +0 -7
  370. package/src/services/cache/memory-cache-store.d.ts +0 -42
  371. package/src/services/cache/memory-cache-store.js +0 -98
  372. package/src/services/cache/page-cache-service.d.ts +0 -70
  373. package/src/services/cache/page-cache-service.js +0 -152
  374. package/src/services/html-transformer.service.d.ts +0 -50
  375. package/src/services/html-transformer.service.js +0 -163
  376. package/src/services/html-transformer.service.ts +0 -217
  377. package/src/services/page-module-import.service.d.ts +0 -37
  378. package/src/services/page-module-import.service.js +0 -88
  379. package/src/services/page-module-import.service.ts +0 -129
  380. package/src/services/page-request-cache-coordinator.service.d.ts +0 -75
  381. package/src/services/page-request-cache-coordinator.service.js +0 -107
  382. package/src/services/schema-validation-service.d.ts +0 -122
  383. package/src/services/schema-validation-service.js +0 -101
  384. package/src/services/validation/standard-schema.types.d.ts +0 -65
  385. package/src/services/validation/standard-schema.types.js +0 -0
  386. package/src/static-site-generator/static-site-generator.d.ts +0 -57
  387. package/src/static-site-generator/static-site-generator.js +0 -272
  388. package/src/utils/css.d.ts +0 -1
  389. package/src/utils/css.js +0 -7
  390. package/src/utils/deep-merge.d.ts +0 -14
  391. package/src/utils/deep-merge.js +0 -32
  392. package/src/utils/hash.d.ts +0 -1
  393. package/src/utils/hash.js +0 -7
  394. package/src/utils/html.d.ts +0 -1
  395. package/src/utils/html.js +0 -4
  396. package/src/utils/invariant.d.ts +0 -5
  397. package/src/utils/invariant.js +0 -11
  398. package/src/utils/locals-utils.d.ts +0 -15
  399. package/src/utils/locals-utils.js +0 -24
  400. package/src/utils/parse-cli-args.d.ts +0 -24
  401. package/src/utils/parse-cli-args.js +0 -47
  402. package/src/utils/path-utils.module.d.ts +0 -5
  403. package/src/utils/path-utils.module.js +0 -14
  404. package/src/utils/runtime.d.ts +0 -11
  405. package/src/utils/runtime.js +0 -40
  406. package/src/utils/server-utils.module.d.ts +0 -19
  407. package/src/utils/server-utils.module.js +0 -56
  408. package/src/watchers/project-watcher.d.ts +0 -125
  409. package/src/watchers/project-watcher.js +0 -265
  410. package/src/watchers/project-watcher.test-helpers.d.ts +0 -4
  411. package/src/watchers/project-watcher.test-helpers.js +0 -52
  412. /package/src/route-renderer/{component-graph-executor.ts → component-graph/component-graph-executor.ts} +0 -0
  413. /package/src/route-renderer/{component-graph.ts → component-graph/component-graph.ts} +0 -0
  414. /package/src/route-renderer/{component-marker.ts → component-graph/component-marker.ts} +0 -0
  415. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.registry.ts +0 -0
  416. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/index.ts +0 -0
  417. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/content-script.processor.ts +0 -0
  418. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/content-stylesheet.processor.ts +0 -0
@@ -0,0 +1,124 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { HmrStrategy, HmrStrategyType, type HmrAction } from './hmr-strategy';
3
+
4
+ /**
5
+ * Mock strategy for testing the base class behavior
6
+ */
7
+ class MockStrategy extends HmrStrategy {
8
+ readonly type: HmrStrategyType;
9
+ override readonly priorityOffset: number;
10
+ private matchPattern: string;
11
+
12
+ constructor(options: { type: HmrStrategyType; priorityOffset?: number; matchPattern?: string }) {
13
+ super();
14
+ this.type = options.type;
15
+ this.priorityOffset = options.priorityOffset ?? 0;
16
+ this.matchPattern = options.matchPattern ?? '.';
17
+ }
18
+
19
+ matches(filePath: string): boolean {
20
+ return filePath.endsWith(this.matchPattern);
21
+ }
22
+
23
+ async process(filePath: string): Promise<HmrAction> {
24
+ return {
25
+ type: 'broadcast',
26
+ events: [{ type: 'update', path: filePath, timestamp: Date.now() }],
27
+ };
28
+ }
29
+ }
30
+
31
+ describe('HmrStrategyType', () => {
32
+ it('INTEGRATION has value 100', () => {
33
+ expect(HmrStrategyType.INTEGRATION).toBe(100);
34
+ });
35
+
36
+ it('ASSET has value 50', () => {
37
+ expect(HmrStrategyType.ASSET).toBe(50);
38
+ });
39
+
40
+ it('SCRIPT has value 25', () => {
41
+ expect(HmrStrategyType.SCRIPT).toBe(25);
42
+ });
43
+
44
+ it('FALLBACK has value 0', () => {
45
+ expect(HmrStrategyType.FALLBACK).toBe(0);
46
+ });
47
+
48
+ it('maintains priority order: INTEGRATION > ASSET > SCRIPT > FALLBACK', () => {
49
+ expect(HmrStrategyType.INTEGRATION).toBeGreaterThan(HmrStrategyType.ASSET);
50
+ expect(HmrStrategyType.ASSET).toBeGreaterThan(HmrStrategyType.SCRIPT);
51
+ expect(HmrStrategyType.SCRIPT).toBeGreaterThan(HmrStrategyType.FALLBACK);
52
+ });
53
+ });
54
+
55
+ describe('HmrStrategy', () => {
56
+ describe('priority', () => {
57
+ it('returns type value when priorityOffset is 0', () => {
58
+ const strategy = new MockStrategy({ type: HmrStrategyType.INTEGRATION });
59
+ expect(strategy.priority).toBe(100);
60
+ });
61
+
62
+ it('returns type + priorityOffset', () => {
63
+ const strategy = new MockStrategy({ type: HmrStrategyType.INTEGRATION, priorityOffset: 5 });
64
+ expect(strategy.priority).toBe(105);
65
+ });
66
+
67
+ it('allows negative priorityOffset', () => {
68
+ const strategy = new MockStrategy({ type: HmrStrategyType.ASSET, priorityOffset: -10 });
69
+ expect(strategy.priority).toBe(40);
70
+ });
71
+ });
72
+
73
+ describe('strategy selection by priority', () => {
74
+ it('higher priority strategies are selected first', () => {
75
+ const strategies = [
76
+ new MockStrategy({ type: HmrStrategyType.FALLBACK, matchPattern: '.test' }),
77
+ new MockStrategy({ type: HmrStrategyType.INTEGRATION, matchPattern: '.test' }),
78
+ new MockStrategy({ type: HmrStrategyType.SCRIPT, matchPattern: '.test' }),
79
+ new MockStrategy({ type: HmrStrategyType.ASSET, matchPattern: '.test' }),
80
+ ];
81
+
82
+ const sorted = [...strategies].sort((a, b) => b.priority - a.priority);
83
+
84
+ expect(sorted[0].type).toBe(HmrStrategyType.INTEGRATION);
85
+ expect(sorted[1].type).toBe(HmrStrategyType.ASSET);
86
+ expect(sorted[2].type).toBe(HmrStrategyType.SCRIPT);
87
+ expect(sorted[3].type).toBe(HmrStrategyType.FALLBACK);
88
+ });
89
+
90
+ it('priorityOffset can override default ordering', () => {
91
+ const assetWithHighOffset = new MockStrategy({
92
+ type: HmrStrategyType.ASSET,
93
+ priorityOffset: 60,
94
+ matchPattern: '.test',
95
+ });
96
+ const integration = new MockStrategy({
97
+ type: HmrStrategyType.INTEGRATION,
98
+ matchPattern: '.test',
99
+ });
100
+
101
+ expect(assetWithHighOffset.priority).toBeGreaterThan(integration.priority);
102
+ });
103
+ });
104
+
105
+ describe('matches', () => {
106
+ it('should be implemented by subclasses', () => {
107
+ const strategy = new MockStrategy({ type: HmrStrategyType.ASSET, matchPattern: '.css' });
108
+ expect(strategy.matches('styles.css')).toBe(true);
109
+ expect(strategy.matches('script.js')).toBe(false);
110
+ });
111
+ });
112
+
113
+ describe('process', () => {
114
+ it('should return an HmrAction', async () => {
115
+ const strategy = new MockStrategy({ type: HmrStrategyType.ASSET });
116
+ const action = await strategy.process('/path/to/file.');
117
+
118
+ expect(action.type).toBe('broadcast');
119
+ expect(action.events).toBeDefined();
120
+ expect(action.events?.[0].type).toBe('update');
121
+ expect(action.events?.[0].path).toBe('/path/to/file.');
122
+ });
123
+ });
124
+ });
@@ -0,0 +1,41 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import { readFileSync } from 'node:fs';
3
+ import { writeFile } from 'node:fs/promises';
4
+ import { resolve } from 'node:path';
5
+
6
+ const FIXTURE_DIR = resolve(process.cwd(), 'packages/core/__fixtures__/app');
7
+ const TEST_CSS_FILE = resolve(FIXTURE_DIR, 'src/pages/postcss-hmr.css');
8
+
9
+ test.describe('HMR E2E PostCSS', () => {
10
+ test('should hot-update processor-owned CSS without a full page reload', async ({ page }) => {
11
+ const originalCss = readFileSync(TEST_CSS_FILE, 'utf-8');
12
+ const title = page.locator('.postcss-title').first();
13
+
14
+ try {
15
+ await page.goto('/postcss-hmr', { waitUntil: 'networkidle' });
16
+ await expect(title).toBeVisible();
17
+
18
+ const initialColor = await title.evaluate((el) => getComputedStyle(el).color);
19
+ expect(initialColor).toBeTruthy();
20
+ await page.evaluate(() => {
21
+ (window as typeof window & { __postcssReloadProbe?: string }).__postcssReloadProbe = 'before-change';
22
+ });
23
+
24
+ const modifiedCss = originalCss.replace('.postcss-title {', '.postcss-title {\n\tcolor: rgb(255, 0, 0);');
25
+
26
+ await writeFile(TEST_CSS_FILE, modifiedCss, { flush: true });
27
+
28
+ await expect
29
+ .poll(async () => title.evaluate((el) => getComputedStyle(el).color), { timeout: 10000 })
30
+ .toBe('rgb(255, 0, 0)');
31
+
32
+ await expect(
33
+ page.evaluate(
34
+ () => (window as typeof window & { __postcssReloadProbe?: string }).__postcssReloadProbe ?? null,
35
+ ),
36
+ ).resolves.toBe('before-change');
37
+ } finally {
38
+ await writeFile(TEST_CSS_FILE, originalCss, { flush: true });
39
+ }
40
+ });
41
+ });
@@ -14,62 +14,53 @@ import { resolve } from 'node:path';
14
14
 
15
15
  const FIXTURE_DIR = resolve(process.cwd(), 'packages/core/__fixtures__/app');
16
16
  const TEST_CSS_FILE = resolve(FIXTURE_DIR, 'src/pages/index.css');
17
- const BUILT_CSS_FILE = resolve(FIXTURE_DIR, '.eco/assets/pages/index.css');
18
- const TEST_URL = 'http://localhost:3002';
19
17
 
20
18
  test.describe('HMR E2E', () => {
21
19
  test('should load page with .main-title element', async ({ page }) => {
22
- await page.goto(TEST_URL, { waitUntil: 'networkidle' });
20
+ await page.goto('/', { waitUntil: 'networkidle' });
23
21
  const title = page.locator('.main-title').first();
24
22
  await expect(title).toBeVisible();
25
23
  });
26
24
 
27
25
  test('should connect to HMR WebSocket', async ({ page }) => {
28
- await page.goto(TEST_URL);
29
-
30
- const connected = await page.evaluate(async () => {
31
- return new Promise<boolean>((resolve) => {
32
- const ws = new WebSocket('ws://localhost:3002/_hmr');
33
- ws.onopen = () => {
34
- ws.close();
35
- resolve(true);
36
- };
37
- ws.onerror = () => resolve(false);
38
- setTimeout(() => resolve(false), 5000);
39
- });
26
+ const socketPromise = page.waitForEvent('websocket', {
27
+ predicate: (socket) => socket.url().endsWith('/_hmr'),
28
+ timeout: 10000,
40
29
  });
41
30
 
42
- expect(connected).toBe(true);
31
+ await page.goto('/', { waitUntil: 'networkidle' });
32
+ const socket = await socketPromise;
33
+
34
+ expect(socket.url()).toMatch(/\/_hmr$/);
43
35
  });
44
36
 
45
- test('should reload page when CSS file changes', async ({ page }) => {
37
+ test('should fall back to a full page reload when raw CSS file changes', async ({ page }) => {
46
38
  const originalCss = readFileSync(TEST_CSS_FILE, 'utf-8');
39
+ const title = page.locator('.main-title').first();
47
40
 
48
- await page.goto(TEST_URL, { waitUntil: 'networkidle' });
49
-
50
- const initialColor = await page.evaluate(() => {
51
- const el = document.querySelector('.main-title');
52
- return el ? getComputedStyle(el).color : null;
53
- });
54
-
55
- expect(initialColor).toBeTruthy();
56
-
57
- const modifiedCss = originalCss.replace('.main-title {', '.main-title {\n\tcolor: rgb(255, 0, 0);');
58
-
59
- const loadPromise = page.waitForEvent('load', { timeout: 10000 });
41
+ try {
42
+ await page.goto('/', { waitUntil: 'networkidle' });
43
+ await expect(title).toBeVisible();
60
44
 
61
- await writeFile(TEST_CSS_FILE, modifiedCss, { flush: true });
62
- await writeFile(BUILT_CSS_FILE, modifiedCss, { flush: true });
45
+ const initialColor = await title.evaluate((el) => getComputedStyle(el).color);
46
+ expect(initialColor).toBeTruthy();
63
47
 
64
- await loadPromise;
48
+ const modifiedCss = originalCss.replace('.main-title {', '.main-title {\n\tcolor: rgb(255, 0, 0);');
49
+ const reloadPromise = page.waitForEvent('framenavigated', {
50
+ predicate: (frame) => frame === page.mainFrame(),
51
+ timeout: 10000,
52
+ });
65
53
 
66
- const updatedColor = await page.evaluate(() => {
67
- const el = document.querySelector('.main-title');
68
- return el ? getComputedStyle(el).color : null;
69
- });
54
+ await writeFile(TEST_CSS_FILE, modifiedCss, { flush: true });
70
55
 
71
- expect(updatedColor).toBe('rgb(255, 0, 0)');
56
+ await reloadPromise;
57
+ await page.waitForLoadState('networkidle');
72
58
 
73
- await writeFile(TEST_CSS_FILE, originalCss, { flush: true });
59
+ await expect
60
+ .poll(async () => title.evaluate((el) => getComputedStyle(el).color), { timeout: 10000 })
61
+ .toBe('rgb(255, 0, 0)');
62
+ } finally {
63
+ await writeFile(TEST_CSS_FILE, originalCss, { flush: true });
64
+ }
74
65
  });
75
66
  });
@@ -0,0 +1,335 @@
1
+ import { describe, expect, it, beforeAll, afterAll } from 'vitest';
2
+ import { JsHmrStrategy, type JsHmrContext } from './js-hmr-strategy';
3
+ import { HmrStrategyType } from '../hmr-strategy';
4
+ import { InMemoryDevGraphService, NoopDevGraphService } from '../../services/runtime-state/dev-graph.service.ts';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import os from 'node:os';
8
+
9
+ const TMP_DIR = path.join(os.tmpdir(), 'js-hmr-strategy-test');
10
+ const SRC_DIR = path.join(TMP_DIR, 'src');
11
+
12
+ function createMockContext(overrides: Partial<JsHmrContext> = {}): JsHmrContext {
13
+ return {
14
+ getWatchedFiles: () => new Map(),
15
+ getSpecifierMap: () => new Map(),
16
+ getEntrypointDependencyGraph: () => new NoopDevGraphService(),
17
+ getDistDir: () => TMP_DIR,
18
+ getPlugins: () => [],
19
+ getSrcDir: () => SRC_DIR,
20
+ getPagesDir: () => path.join(SRC_DIR, 'pages'),
21
+ getLayoutsDir: () => path.join(SRC_DIR, 'layouts'),
22
+ getTemplateExtensions: () => ['.tsx'],
23
+ getBrowserBundleService: () => ({
24
+ bundle: async () => ({ success: true, logs: [], outputs: [] }),
25
+ }),
26
+ ...overrides,
27
+ };
28
+ }
29
+
30
+ describe('JsHmrStrategy', () => {
31
+ beforeAll(() => {
32
+ fs.mkdirSync(SRC_DIR, { recursive: true });
33
+ });
34
+
35
+ afterAll(() => {
36
+ fs.rmSync(TMP_DIR, { recursive: true, force: true });
37
+ });
38
+
39
+ describe('type', () => {
40
+ it('has SCRIPT type', () => {
41
+ const context = createMockContext();
42
+ const strategy = new JsHmrStrategy(context);
43
+ expect(strategy.type).toBe(HmrStrategyType.SCRIPT);
44
+ });
45
+
46
+ it('has default priority of 25', () => {
47
+ const context = createMockContext();
48
+ const strategy = new JsHmrStrategy(context);
49
+ expect(strategy.priority).toBe(25);
50
+ });
51
+ });
52
+
53
+ describe('matches', () => {
54
+ it('returns false when no watched files are registered', () => {
55
+ const context = createMockContext({
56
+ getWatchedFiles: () => new Map(),
57
+ });
58
+ const strategy = new JsHmrStrategy(context);
59
+
60
+ expect(strategy.matches(path.join(SRC_DIR, 'app.ts'))).toBe(false);
61
+ });
62
+
63
+ it('returns false for unrelated .ts files when dependency graph support is available', () => {
64
+ const devGraphService = new InMemoryDevGraphService();
65
+ const context = createMockContext({
66
+ getWatchedFiles: () => new Map([[path.join(SRC_DIR, 'entry.ts'), '/output.js']]),
67
+ getEntrypointDependencyGraph: () => devGraphService,
68
+ });
69
+ const strategy = new JsHmrStrategy(context);
70
+
71
+ expect(strategy.matches(path.join(SRC_DIR, 'component.ts'))).toBe(false);
72
+ });
73
+
74
+ it('returns true for dependency-connected .tsx files in src directory', () => {
75
+ const changedFile = path.join(SRC_DIR, 'component.tsx');
76
+ const devGraphService = new InMemoryDevGraphService();
77
+ devGraphService.setEntrypointDependencies(path.join(SRC_DIR, 'entry.ts'), [changedFile]);
78
+ const context = createMockContext({
79
+ getWatchedFiles: () => new Map([[path.join(SRC_DIR, 'entry.ts'), '/output.js']]),
80
+ getEntrypointDependencyGraph: () => devGraphService,
81
+ });
82
+ const strategy = new JsHmrStrategy(context);
83
+
84
+ expect(strategy.matches(changedFile)).toBe(true);
85
+ });
86
+
87
+ it('returns true for registered entrypoints even without dependency graph hits', () => {
88
+ const entrypoint = path.join(SRC_DIR, 'entry.tsx');
89
+ const devGraphService = new InMemoryDevGraphService();
90
+ const context = createMockContext({
91
+ getWatchedFiles: () => new Map([[entrypoint, '/output.js']]),
92
+ getEntrypointDependencyGraph: () => devGraphService,
93
+ });
94
+ const strategy = new JsHmrStrategy(context);
95
+
96
+ expect(strategy.matches(entrypoint)).toBe(true);
97
+ });
98
+
99
+ it('returns true for .js files in src directory', () => {
100
+ const context = createMockContext({
101
+ getWatchedFiles: () => new Map([[path.join(SRC_DIR, 'entry.ts'), '/output.js']]),
102
+ });
103
+ const strategy = new JsHmrStrategy(context);
104
+
105
+ expect(strategy.matches(path.join(SRC_DIR, 'utils.js'))).toBe(true);
106
+ });
107
+
108
+ it('returns true for .jsx files in src directory', () => {
109
+ const context = createMockContext({
110
+ getWatchedFiles: () => new Map([[path.join(SRC_DIR, 'entry.ts'), '/output.js']]),
111
+ });
112
+ const strategy = new JsHmrStrategy(context);
113
+
114
+ expect(strategy.matches(path.join(SRC_DIR, 'component.jsx'))).toBe(true);
115
+ });
116
+
117
+ it('returns false for .css files', () => {
118
+ const context = createMockContext({
119
+ getWatchedFiles: () => new Map([[path.join(SRC_DIR, 'entry.ts'), '/output.js']]),
120
+ });
121
+ const strategy = new JsHmrStrategy(context);
122
+
123
+ expect(strategy.matches(path.join(SRC_DIR, 'styles.css'))).toBe(false);
124
+ });
125
+
126
+ it('returns false for files outside src directory', () => {
127
+ const context = createMockContext({
128
+ getWatchedFiles: () => new Map([[path.join(SRC_DIR, 'entry.ts'), '/output.js']]),
129
+ });
130
+ const strategy = new JsHmrStrategy(context);
131
+
132
+ expect(strategy.matches('/other/path/file.ts')).toBe(false);
133
+ });
134
+
135
+ it('returns false for integration-owned route template files', () => {
136
+ const pagesDir = path.join(SRC_DIR, 'pages');
137
+ const context = createMockContext({
138
+ getWatchedFiles: () => new Map([[path.join(SRC_DIR, 'entry.ts'), '/output.js']]),
139
+ getPagesDir: () => pagesDir,
140
+ getTemplateExtensions: () => ['.kita.tsx', '.react.tsx'],
141
+ });
142
+ const strategy = new JsHmrStrategy(context);
143
+
144
+ expect(strategy.matches(path.join(pagesDir, 'index.kita.tsx'))).toBe(false);
145
+ expect(strategy.matches(path.join(pagesDir, 'home.react.tsx'))).toBe(false);
146
+ });
147
+
148
+ it('returns false for non-extension matches', () => {
149
+ const context = createMockContext({
150
+ getWatchedFiles: () => new Map([[path.join(SRC_DIR, 'entry.ts'), '/output.js']]),
151
+ });
152
+ const strategy = new JsHmrStrategy(context);
153
+
154
+ expect(strategy.matches(path.join(SRC_DIR, 'data.json'))).toBe(false);
155
+ expect(strategy.matches(path.join(SRC_DIR, 'readme.md'))).toBe(false);
156
+ });
157
+ });
158
+
159
+ describe('process', () => {
160
+ it('returns none when no watched files are registered', async () => {
161
+ const context = createMockContext({
162
+ getWatchedFiles: () => new Map(),
163
+ });
164
+ const strategy = new JsHmrStrategy(context);
165
+
166
+ const action = await strategy.process(path.join(SRC_DIR, 'app.ts'));
167
+
168
+ expect(action.type).toBe('none');
169
+ });
170
+
171
+ it('rebuilds only dependency-connected entrypoints when graph hit exists', async () => {
172
+ const entryA = path.join(SRC_DIR, 'entry-a.ts');
173
+ const entryB = path.join(SRC_DIR, 'entry-b.ts');
174
+ const depA = path.join(SRC_DIR, 'shared-a.ts');
175
+ const setEntrypointDependenciesCalls: Array<{ entrypointPath: string; dependencies: string[] }> = [];
176
+ let batchedEntrypoints: string[] = [];
177
+ const devGraphService = new InMemoryDevGraphService();
178
+ devGraphService.setEntrypointDependencies(entryA, [depA]);
179
+ devGraphService.setEntrypointDependencies(entryB, [entryB]);
180
+
181
+ const context = createMockContext({
182
+ getWatchedFiles: () =>
183
+ new Map([
184
+ [entryA, '/_hmr/entry-a.js'],
185
+ [entryB, '/_hmr/entry-b.js'],
186
+ ]),
187
+ getEntrypointDependencyGraph: () => ({
188
+ supportsSelectiveInvalidation: () => devGraphService.supportsSelectiveInvalidation(),
189
+ getDependencyEntrypoints: (filePath: string) => devGraphService.getDependencyEntrypoints(filePath),
190
+ setEntrypointDependencies: (entrypointPath: string, dependencies: string[]) => {
191
+ setEntrypointDependenciesCalls.push({ entrypointPath, dependencies });
192
+ devGraphService.setEntrypointDependencies(entrypointPath, dependencies);
193
+ },
194
+ clearEntrypointDependencies: (entrypointPath: string) =>
195
+ devGraphService.clearEntrypointDependencies(entrypointPath),
196
+ reset: () => devGraphService.reset(),
197
+ }),
198
+ });
199
+
200
+ const strategy = new JsHmrStrategy(context) as unknown as {
201
+ process: (filePath: string) => Promise<{ type: string; events?: unknown[] }>;
202
+ [key: string]: unknown;
203
+ };
204
+
205
+ strategy.bundleEntrypoints = async (entrypoints: string[]) => {
206
+ batchedEntrypoints = entrypoints;
207
+ const dependencies = new Map<string, string[]>();
208
+ for (const ep of entrypoints) {
209
+ dependencies.set(path.resolve(ep), [ep, depA]);
210
+ }
211
+ return { success: true, dependencies };
212
+ };
213
+
214
+ strategy.processOutput = async () => {
215
+ return { success: true, requiresReload: false };
216
+ };
217
+
218
+ const action = await strategy.process(depA);
219
+
220
+ expect(batchedEntrypoints).toEqual([entryA]);
221
+ expect(setEntrypointDependenciesCalls).toEqual([{ entrypointPath: entryA, dependencies: [entryA, depA] }]);
222
+ expect(action).toEqual({
223
+ type: 'broadcast',
224
+ events: [
225
+ {
226
+ type: 'update',
227
+ path: '/_hmr/entry-a.js',
228
+ timestamp: expect.any(Number),
229
+ },
230
+ ],
231
+ });
232
+ });
233
+
234
+ it('falls back to rebuilding all watched entrypoints when graph has no hit', async () => {
235
+ const entryA = path.join(SRC_DIR, 'entry-a.ts');
236
+ const entryB = path.join(SRC_DIR, 'entry-b.ts');
237
+ const changedFile = path.join(SRC_DIR, 'new-shared.ts');
238
+ let batchedEntrypoints: string[] = [];
239
+
240
+ const context = createMockContext({
241
+ getWatchedFiles: () =>
242
+ new Map([
243
+ [entryA, '/_hmr/entry-a.js'],
244
+ [entryB, '/_hmr/entry-b.js'],
245
+ ]),
246
+ getEntrypointDependencyGraph: () => new NoopDevGraphService(),
247
+ });
248
+
249
+ const strategy = new JsHmrStrategy(context) as unknown as {
250
+ process: (filePath: string) => Promise<{ type: string; events?: unknown[] }>;
251
+ [key: string]: unknown;
252
+ };
253
+
254
+ strategy.bundleEntrypoints = async (entrypoints: string[]) => {
255
+ batchedEntrypoints = entrypoints;
256
+ const dependencies = new Map<string, string[]>();
257
+ for (const ep of entrypoints) {
258
+ dependencies.set(path.resolve(ep), [ep]);
259
+ }
260
+ return { success: true, dependencies };
261
+ };
262
+
263
+ strategy.processOutput = async () => {
264
+ return { success: true, requiresReload: false };
265
+ };
266
+
267
+ const action = await strategy.process(changedFile);
268
+
269
+ expect(batchedEntrypoints).toEqual([entryA, entryB]);
270
+ expect(action).toEqual({
271
+ type: 'broadcast',
272
+ events: [
273
+ {
274
+ type: 'update',
275
+ path: '/_hmr/entry-a.js',
276
+ timestamp: expect.any(Number),
277
+ },
278
+ {
279
+ type: 'update',
280
+ path: '/_hmr/entry-b.js',
281
+ timestamp: expect.any(Number),
282
+ },
283
+ ],
284
+ });
285
+ });
286
+
287
+ it('skips watched entrypoints owned by higher-priority integration strategies', async () => {
288
+ const reactEntrypoint = path.join(SRC_DIR, 'react-page.tsx');
289
+ const scriptEntrypoint = path.join(SRC_DIR, 'widget.script.ts');
290
+ const changedFile = path.join(SRC_DIR, 'shared.ts');
291
+ let batchedEntrypoints: string[] = [];
292
+ const devGraphService = new InMemoryDevGraphService();
293
+ devGraphService.setEntrypointDependencies(reactEntrypoint, [changedFile]);
294
+ devGraphService.setEntrypointDependencies(scriptEntrypoint, [changedFile]);
295
+
296
+ const context = createMockContext({
297
+ getWatchedFiles: () =>
298
+ new Map([
299
+ [reactEntrypoint, '/_hmr/react-page.js'],
300
+ [scriptEntrypoint, '/_hmr/widget.script.js'],
301
+ ]),
302
+ getEntrypointDependencyGraph: () => devGraphService,
303
+ shouldProcessEntrypoint: (entrypointPath: string) => entrypointPath !== reactEntrypoint,
304
+ });
305
+
306
+ const strategy = new JsHmrStrategy(context) as unknown as {
307
+ process: (filePath: string) => Promise<{ type: string; events?: unknown[] }>;
308
+ [key: string]: unknown;
309
+ };
310
+
311
+ strategy.bundleEntrypoints = async (entrypoints: string[]) => {
312
+ batchedEntrypoints = entrypoints;
313
+ return { success: true, dependencies: new Map([[path.resolve(scriptEntrypoint), [scriptEntrypoint]]]) };
314
+ };
315
+
316
+ strategy.processOutput = async () => {
317
+ return { success: true, requiresReload: false };
318
+ };
319
+
320
+ const action = await strategy.process(changedFile);
321
+
322
+ expect(batchedEntrypoints).toEqual([scriptEntrypoint]);
323
+ expect(action).toEqual({
324
+ type: 'broadcast',
325
+ events: [
326
+ {
327
+ type: 'update',
328
+ path: '/_hmr/widget.script.js',
329
+ timestamp: expect.any(Number),
330
+ },
331
+ ],
332
+ });
333
+ });
334
+ });
335
+ });