@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,214 @@
1
+ import { describe, expect, test, vi } from 'vitest';
2
+ import { FIXTURE_APP_PROJECT_DIR } from '../../../__fixtures__/constants.js';
3
+ import { ConfigBuilder } from '../../config/config-builder.js';
4
+ import type { Route, Routes } from '../../internal-types.js';
5
+ import { FSRouter } from './fs-router.ts';
6
+ import { FSRouterScanner } from './fs-router-scanner.ts';
7
+
8
+ const {
9
+ templatesExt,
10
+ absolutePaths: { pagesDir, distDir },
11
+ } = await new ConfigBuilder().setRootDir(FIXTURE_APP_PROJECT_DIR).build();
12
+
13
+ const scanner = new FSRouterScanner({
14
+ dir: pagesDir,
15
+ appConfig: {
16
+ absolutePaths: {
17
+ distDir,
18
+ },
19
+ } as any,
20
+ origin: 'http://localhost:3000',
21
+ templatesExt,
22
+ options: {
23
+ buildMode: false,
24
+ },
25
+ });
26
+
27
+ const router = new FSRouter({
28
+ origin: 'http://localhost:3000',
29
+ assetPrefix: distDir,
30
+ scanner,
31
+ });
32
+
33
+ await router.init();
34
+
35
+ describe('FSRouter', async () => {
36
+ describe('init', async () => {
37
+ test('should scan and return routes', async () => {
38
+ expect(Object.keys(router.routes).sort()).toEqual([
39
+ 'http://localhost:3000/',
40
+ 'http://localhost:3000/404',
41
+ 'http://localhost:3000/catch-all/[...path]',
42
+ 'http://localhost:3000/dynamic/another-blog-post',
43
+ 'http://localhost:3000/dynamic/blog-post',
44
+ 'http://localhost:3000/postcss-hmr',
45
+ ]);
46
+ });
47
+ });
48
+
49
+ describe('getDynamicParams', async () => {
50
+ test.each([
51
+ ['/products/[id]', '/products/123', { id: '123' }],
52
+ ['/products/[id]', '/products/123/456', { id: '123' }],
53
+ ['/products/[id]', '/products/123/456/789', { id: '123' }],
54
+ ])(
55
+ 'dynamic route %p with URL %p should have dynamic params %p',
56
+ async (dynamicPathname, pathname, expected) => {
57
+ const route: Route = {
58
+ filePath: '',
59
+ kind: 'dynamic',
60
+ pathname: dynamicPathname,
61
+ };
62
+ const params = router.getDynamicParams(route, pathname);
63
+
64
+ expect(params).toEqual(expected);
65
+ },
66
+ );
67
+
68
+ test.each([
69
+ ['/products/[...id]', '/products/123/456/789', { id: ['123', '456', '789'] }],
70
+ ['/products/[...id]', '/products/123', { id: ['123'] }],
71
+ ['/products/[...id]', '/products', { id: [] }],
72
+ ])(
73
+ 'catch-all route %p with URL %p should have dynamic params %p',
74
+ async (catchAllRoute, pathname, expected) => {
75
+ const route: Route = {
76
+ filePath: '',
77
+ kind: 'dynamic',
78
+ pathname: catchAllRoute,
79
+ };
80
+ const params = router.getDynamicParams(route, pathname);
81
+
82
+ expect(params).toEqual(expected);
83
+ },
84
+ );
85
+ });
86
+
87
+ describe('getSearchParams', () => {
88
+ test('should extract query parameters from URL', () => {
89
+ const url = new URL('http://localhost:3000/page?foo=bar&baz=qux');
90
+ const params = router.getSearchParams(url);
91
+
92
+ expect(params).toEqual({ foo: 'bar', baz: 'qux' });
93
+ });
94
+
95
+ test('should return empty object for URL without query params', () => {
96
+ const url = new URL('http://localhost:3000/page');
97
+ const params = router.getSearchParams(url);
98
+
99
+ expect(params).toEqual({});
100
+ });
101
+ });
102
+
103
+ describe('match', () => {
104
+ const createRouterWithRoutes = (routes: Routes) => {
105
+ const Scanner = { scan: async () => routes } as unknown as FSRouterScanner;
106
+ const testRouter = new FSRouter({
107
+ origin: 'http://localhost:3000',
108
+ assetPrefix: '/dist',
109
+ scanner: Scanner,
110
+ });
111
+ testRouter.routes = routes;
112
+ return testRouter;
113
+ };
114
+
115
+ test('should match exact route', () => {
116
+ const testRouter = createRouterWithRoutes({
117
+ '/about': { filePath: '/pages/about.ts', kind: 'exact', pathname: '/about' },
118
+ });
119
+
120
+ const result = testRouter.match('http://localhost:3000/about');
121
+
122
+ expect(result).not.toBeNull();
123
+ expect(result?.kind).toBe('exact');
124
+ expect(result?.pathname).toBe('/about');
125
+ });
126
+
127
+ test('should match exact route with trailing slash', () => {
128
+ const testRouter = createRouterWithRoutes({
129
+ '/about': { filePath: '/pages/about.ts', kind: 'exact', pathname: '/about' },
130
+ });
131
+
132
+ const result = testRouter.match('http://localhost:3000/about/');
133
+
134
+ expect(result).not.toBeNull();
135
+ expect(result?.kind).toBe('exact');
136
+ });
137
+
138
+ test('should match dynamic route', () => {
139
+ const testRouter = createRouterWithRoutes({
140
+ '/dynamic/[id]': { filePath: '/pages/dynamic/[id].ts', kind: 'dynamic', pathname: '/dynamic/[id]' },
141
+ });
142
+
143
+ const result = testRouter.match('http://localhost:3000/dynamic/123');
144
+
145
+ expect(result).not.toBeNull();
146
+ expect(result?.kind).toBe('dynamic');
147
+ expect(result?.params).toEqual({ id: '123' });
148
+ });
149
+
150
+ test('should match catch-all route', () => {
151
+ const testRouter = createRouterWithRoutes({
152
+ '/catch-all/[...slug]': {
153
+ filePath: '/pages/catch-all/[...slug].ts',
154
+ kind: 'catch-all',
155
+ pathname: '/catch-all/[...slug]',
156
+ },
157
+ });
158
+
159
+ const result = testRouter.match('http://localhost:3000/catch-all/a/b/c');
160
+
161
+ expect(result).not.toBeNull();
162
+ expect(result?.kind).toBe('catch-all');
163
+ expect(result?.params).toEqual({ slug: ['a', 'b', 'c'] });
164
+ });
165
+
166
+ test('should include query params in match result', () => {
167
+ const testRouter = createRouterWithRoutes({
168
+ '/page': { filePath: '/pages/page.ts', kind: 'exact', pathname: '/page' },
169
+ });
170
+
171
+ const result = testRouter.match('http://localhost:3000/page?sort=asc&page=2');
172
+
173
+ expect(result?.query).toEqual({ sort: 'asc', page: '2' });
174
+ });
175
+
176
+ test('should return null for non-matching route', () => {
177
+ const testRouter = createRouterWithRoutes({
178
+ '/about': { filePath: '/pages/about.ts', kind: 'exact', pathname: '/about' },
179
+ });
180
+
181
+ const result = testRouter.match('http://localhost:3000/contact');
182
+
183
+ expect(result).toBeNull();
184
+ });
185
+
186
+ test('should prefer exact match over dynamic', () => {
187
+ const testRouter = createRouterWithRoutes({
188
+ '/blog/latest': { filePath: '/pages/blog/latest.ts', kind: 'exact', pathname: '/blog/latest' },
189
+ '/blog/[slug]': { filePath: '/pages/blog/[slug].ts', kind: 'dynamic', pathname: '/blog/[slug]' },
190
+ });
191
+
192
+ const result = testRouter.match('http://localhost:3000/blog/latest');
193
+
194
+ expect(result?.kind).toBe('exact');
195
+ });
196
+ });
197
+
198
+ describe('setOnReload and reload', () => {
199
+ test('should set and call onReload callback', async () => {
200
+ const Scanner = { scan: async () => ({}) } as unknown as FSRouterScanner;
201
+ const testRouter = new FSRouter({
202
+ origin: 'http://localhost:3000',
203
+ assetPrefix: '/dist',
204
+ scanner: Scanner,
205
+ });
206
+
207
+ const callback = vi.fn(() => {});
208
+ testRouter.setOnReload(callback);
209
+ testRouter.reload();
210
+
211
+ expect(callback).toHaveBeenCalledTimes(1);
212
+ });
213
+ });
214
+ });
@@ -1,5 +1,5 @@
1
- import { appLogger } from '../global/app-logger.ts';
2
- import type { MatchResult, Route, Routes } from '../internal-types.ts';
1
+ import { appLogger } from '../../global/app-logger.js';
2
+ import type { MatchResult, Route, Routes } from '../../internal-types.js';
3
3
  import type { FSRouterScanner } from './fs-router-scanner.ts';
4
4
 
5
5
  /**
@@ -0,0 +1,29 @@
1
+ # Core Services
2
+
3
+ This directory contains the app-owned service layer used by runtime startup, rendering, asset processing, browser bundling, and development invalidation.
4
+
5
+ ## Purpose
6
+
7
+ Services in this directory exist to keep cross-cutting framework logic out of adapters, integrations, and processors.
8
+
9
+ Typical responsibilities include:
10
+
11
+ - server-module loading and transpilation
12
+ - browser bundle coordination
13
+ - asset processing and runtime asset declaration helpers
14
+ - runtime specifier registry management
15
+ - server invalidation state and entrypoint dependency graphs
16
+ - HTML finalization and dependency injection
17
+
18
+ ## Main Areas
19
+
20
+ - `module-loading/`: framework-owned config/app bootstrap loading and server-side source loading
21
+ - `assets/`: shared browser build coordination and processed asset pipelines
22
+ - `invalidation/`: file-change classification and invalidation policy
23
+ - `runtime-state/`: app-owned invalidation state, dependency graphs, and runtime specifier registry
24
+ - `runtime-manifest/`: node runtime manifest derivation and persistence
25
+ - `html/`: final HTML dependency injection and rewriter selection
26
+
27
+ ## Design Rule
28
+
29
+ If a concern affects more than one integration or more than one runtime adapter, it usually belongs here instead of in a package-specific implementation.
@@ -0,0 +1,385 @@
1
+ import { afterEach, beforeEach, expect, test, vi } from 'vitest';
2
+ import { fileSystem } from '@ecopages/file-system';
3
+ import { AssetProcessingService } from './asset-processing.service';
4
+ import type { AssetDefinition } from './assets.types';
5
+
6
+ const Config = {
7
+ absolutePaths: {
8
+ distDir: '/test/dist',
9
+ },
10
+ } as any;
11
+
12
+ const Processor = {
13
+ process: async () => ({
14
+ filepath: '/test/dist/assets/test.js',
15
+ kind: 'script',
16
+ inline: false,
17
+ }),
18
+ };
19
+
20
+ const originalEnsureDirectoryExists = fileSystem.ensureDir;
21
+ const originalGzipDir = fileSystem.gzipDir;
22
+ const originalWrite = fileSystem.write;
23
+ const originalReadFileSync = fileSystem.readFileSync;
24
+ const originalRemove = fileSystem.remove;
25
+ const originalExists = fileSystem.exists;
26
+
27
+ beforeEach(() => {
28
+ fileSystem.ensureDir = vi.fn(() => {});
29
+ fileSystem.gzipDir = vi.fn(() => {});
30
+ fileSystem.write = vi.fn(() => {});
31
+ fileSystem.readFileSync = vi.fn(() => Buffer.from('') as any);
32
+ fileSystem.remove = vi.fn(() => {});
33
+ fileSystem.exists = vi.fn(() => false);
34
+ });
35
+
36
+ afterEach(() => {
37
+ fileSystem.ensureDir = originalEnsureDirectoryExists;
38
+ fileSystem.gzipDir = originalGzipDir;
39
+ fileSystem.write = originalWrite;
40
+ fileSystem.readFileSync = originalReadFileSync;
41
+ fileSystem.remove = originalRemove;
42
+ fileSystem.exists = originalExists;
43
+ vi.restoreAllMocks();
44
+ });
45
+
46
+ test('AssetProcessingService - registerProcessor', () => {
47
+ const service = new AssetProcessingService(Config);
48
+ service.registerProcessor('script', 'file', Processor);
49
+ expect(service.getRegistry().getProcessor('script', 'file')).toBeDefined();
50
+ });
51
+
52
+ test('AssetProcessingService - processDependencies', async () => {
53
+ const service = AssetProcessingService.createWithDefaultProcessors(Config);
54
+ const results = await service.processDependencies(
55
+ [
56
+ {
57
+ kind: 'script',
58
+ source: 'content',
59
+ content: 'console.log("test")',
60
+ bundle: false,
61
+ } as AssetDefinition,
62
+ ],
63
+ 'test-key',
64
+ );
65
+
66
+ expect(results.length).toBe(1);
67
+ expect((results[0] as any).key).toBe('test-key');
68
+ });
69
+
70
+ test('AssetProcessingService - createWithDefaultProcessors', () => {
71
+ const service = AssetProcessingService.createWithDefaultProcessors(Config);
72
+ expect([...service.getRegistry().getAllProcessors().values()].length).toBeGreaterThan(0);
73
+ });
74
+
75
+ test('AssetProcessingService - processDependencies - success', async () => {
76
+ const ensureDirMock = vi.fn(() => {});
77
+ const gzipDirMock = vi.fn(() => {});
78
+ fileSystem.ensureDir = ensureDirMock;
79
+ fileSystem.gzipDir = gzipDirMock;
80
+ fileSystem.exists = vi.fn(() => true);
81
+
82
+ const service = new AssetProcessingService(Config);
83
+ const Processor1 = {
84
+ process: vi.fn(async () => ({
85
+ filepath: '/test/dist/assets/script.js',
86
+ kind: 'script',
87
+ inline: false,
88
+ })),
89
+ };
90
+ const Processor2 = {
91
+ process: vi.fn(async () => ({
92
+ filepath: '/test/dist/assets/style.css',
93
+ kind: 'stylesheet',
94
+ inline: false,
95
+ })),
96
+ };
97
+ service.registerProcessor('script', 'file', Processor1);
98
+ service.registerProcessor('stylesheet', 'file', Processor2);
99
+
100
+ const dependencies: AssetDefinition[] = [
101
+ { kind: 'script', source: 'file', filepath: 'path/to/script.js' },
102
+ { kind: 'stylesheet', source: 'file', filepath: 'path/to/style.css' },
103
+ ];
104
+ const key = 'test-page';
105
+
106
+ const results = await service.processDependencies(dependencies, key);
107
+
108
+ expect(ensureDirMock).toHaveBeenCalledWith('/test/dist/assets');
109
+ expect(Processor1.process).toHaveBeenCalledTimes(1);
110
+ expect(Processor2.process).toHaveBeenCalledTimes(1);
111
+ expect(results.length).toBe(2);
112
+
113
+ expect(results[0]).toEqual(
114
+ expect.objectContaining({
115
+ filepath: '/test/dist/assets/script.js',
116
+ kind: 'script',
117
+ inline: false,
118
+ srcUrl: '/assets/script.js',
119
+ }),
120
+ );
121
+ expect(results[1]).toEqual(
122
+ expect.objectContaining({
123
+ filepath: '/test/dist/assets/style.css',
124
+ kind: 'stylesheet',
125
+ inline: false,
126
+ srcUrl: '/assets/style.css',
127
+ }),
128
+ );
129
+
130
+ expect(gzipDirMock).not.toHaveBeenCalled();
131
+ });
132
+
133
+ test('AssetProcessingService - processDependencies - processor not found', async () => {
134
+ const ensureDirMock = vi.fn(() => {});
135
+ const gzipDirMock = vi.fn(() => {});
136
+
137
+ fileSystem.ensureDir = ensureDirMock;
138
+ fileSystem.gzipDir = gzipDirMock;
139
+
140
+ const service = new AssetProcessingService(Config);
141
+
142
+ const dependencies: AssetDefinition[] = [{ kind: 'script', source: 'content', content: 'alert(1)' }];
143
+ const key = 'test-key-missing';
144
+
145
+ const results = await service.processDependencies(dependencies, key);
146
+
147
+ expect(ensureDirMock).toHaveBeenCalledWith('/test/dist/assets');
148
+ expect(results.length).toBe(0);
149
+ expect(gzipDirMock).not.toHaveBeenCalled();
150
+ });
151
+
152
+ test('AssetProcessingService - processDependencies - error during processing', async () => {
153
+ const ensureDirMock = vi.fn(() => {});
154
+ const gzipDirMock = vi.fn(() => {});
155
+ fileSystem.ensureDir = ensureDirMock;
156
+ fileSystem.gzipDir = gzipDirMock;
157
+ fileSystem.exists = vi.fn(() => true);
158
+
159
+ const service = new AssetProcessingService(Config);
160
+ const erroringProcessor = {
161
+ process: vi.fn(async () => {
162
+ throw new Error('Processing failed!');
163
+ }),
164
+ };
165
+ service.registerProcessor('script', 'file', erroringProcessor);
166
+
167
+ const dependency: AssetDefinition = {
168
+ kind: 'script',
169
+ source: 'file',
170
+ filepath: 'path/to/failing.js',
171
+ };
172
+ const key = 'test-key-error';
173
+
174
+ const results = await service.processDependencies([dependency], key);
175
+
176
+ expect(ensureDirMock).toHaveBeenCalledWith('/test/dist/assets');
177
+ expect(erroringProcessor.process).toHaveBeenCalledTimes(1);
178
+ expect(results.length).toBe(0);
179
+ expect(gzipDirMock).not.toHaveBeenCalled();
180
+ });
181
+
182
+ test('AssetProcessingService - processDependencies - handles undefined filepath for srcUrl', async () => {
183
+ const ensureDirMock = vi.fn(() => {});
184
+ const gzipDirMock = vi.fn(() => {});
185
+ fileSystem.ensureDir = ensureDirMock;
186
+ fileSystem.gzipDir = gzipDirMock;
187
+
188
+ const service = new AssetProcessingService(Config);
189
+ const ProcessorInline = {
190
+ process: vi.fn(async () => ({
191
+ kind: 'script',
192
+ inline: true,
193
+ content: 'console.log("inline");',
194
+ })),
195
+ };
196
+ service.registerProcessor('script', 'content', ProcessorInline);
197
+
198
+ const dependencies: AssetDefinition[] = [
199
+ { kind: 'script', source: 'content', content: 'console.log("inline");', inline: true },
200
+ ];
201
+ const key = 'test-inline';
202
+
203
+ const results = await service.processDependencies(dependencies, key);
204
+
205
+ expect(ensureDirMock).toHaveBeenCalledWith('/test/dist/assets');
206
+ expect(ProcessorInline.process).toHaveBeenCalledTimes(1);
207
+ expect(results.length).toBe(1);
208
+
209
+ expect(results[0]).toEqual(
210
+ expect.objectContaining({
211
+ kind: 'script',
212
+ inline: true,
213
+ content: 'console.log("inline");',
214
+ srcUrl: undefined,
215
+ }),
216
+ );
217
+
218
+ expect(gzipDirMock).not.toHaveBeenCalled();
219
+ });
220
+
221
+ test('AssetProcessingService - processDependencies - normalizes absolute srcUrl to public assets path', async () => {
222
+ fileSystem.ensureDir = vi.fn(() => {});
223
+ fileSystem.gzipDir = vi.fn(() => {});
224
+ fileSystem.exists = vi.fn(() => true);
225
+
226
+ const service = new AssetProcessingService(Config);
227
+ const processor = {
228
+ process: vi.fn(async () => ({
229
+ srcUrl: '/test/dist/assets/scripts/module--tanstack-react-table.js',
230
+ kind: 'script',
231
+ inline: false,
232
+ })),
233
+ };
234
+ service.registerProcessor('script', 'file', processor);
235
+
236
+ const dependency: AssetDefinition = { kind: 'script', source: 'file', filepath: 'path/to/module.js' };
237
+
238
+ const results = await service.processDependencies([dependency], 'normalize-src-url-key');
239
+
240
+ expect(processor.process).toHaveBeenCalledTimes(1);
241
+ expect(results.length).toBe(1);
242
+ expect(results[0].srcUrl).toBe('/assets/scripts/module--tanstack-react-table.js');
243
+ });
244
+
245
+ test('AssetProcessingService - caching returns cached asset without reprocessing', async () => {
246
+ fileSystem.ensureDir = vi.fn(() => {});
247
+ fileSystem.gzipDir = vi.fn(() => {});
248
+ fileSystem.exists = vi.fn(() => true);
249
+
250
+ const service = new AssetProcessingService(Config);
251
+ const processMock = vi.fn(async () => ({
252
+ filepath: '/test/dist/assets/cached.js',
253
+ kind: 'script',
254
+ inline: false,
255
+ }));
256
+ service.registerProcessor('script', 'file', { process: processMock });
257
+
258
+ const dependency: AssetDefinition = { kind: 'script', source: 'file', filepath: 'path/to/cached.js' };
259
+
260
+ const results1 = await service.processDependencies([dependency], 'key1');
261
+ const results2 = await service.processDependencies([dependency], 'key2');
262
+
263
+ expect(processMock).toHaveBeenCalledTimes(1);
264
+ expect(results1.length).toBe(1);
265
+ expect(results2.length).toBe(1);
266
+ expect(results1[0].srcUrl).toBe('/assets/cached.js');
267
+ expect(results2[0].srcUrl).toBe('/assets/cached.js');
268
+ });
269
+
270
+ test('AssetProcessingService - stale cached emitted files are rebuilt when output is missing', async () => {
271
+ fileSystem.ensureDir = vi.fn(() => {});
272
+ fileSystem.gzipDir = vi.fn(() => {});
273
+ const existsMock = vi
274
+ .fn()
275
+ .mockImplementationOnce(() => true)
276
+ .mockImplementationOnce(() => false)
277
+ .mockImplementation(() => true);
278
+ fileSystem.exists = existsMock;
279
+
280
+ const service = new AssetProcessingService(Config);
281
+ const processMock = vi.fn(async () => ({
282
+ filepath: '/test/dist/assets/stale.js',
283
+ kind: 'script',
284
+ inline: false,
285
+ }));
286
+ service.registerProcessor('script', 'file', { process: processMock });
287
+
288
+ const dependency: AssetDefinition = { kind: 'script', source: 'file', filepath: 'path/to/stale.js' };
289
+
290
+ await service.processDependencies([dependency], 'key1');
291
+ await service.processDependencies([dependency], 'key2');
292
+
293
+ expect(processMock).toHaveBeenCalledTimes(2);
294
+ });
295
+
296
+ test('AssetProcessingService - deduplication processes duplicate deps only once', async () => {
297
+ fileSystem.ensureDir = vi.fn(() => {});
298
+ fileSystem.gzipDir = vi.fn(() => {});
299
+ fileSystem.exists = vi.fn(() => true);
300
+
301
+ const service = new AssetProcessingService(Config);
302
+ const processMock = vi.fn(async () => ({
303
+ filepath: '/test/dist/assets/dedup.js',
304
+ kind: 'script',
305
+ inline: false,
306
+ }));
307
+ service.registerProcessor('script', 'file', { process: processMock });
308
+
309
+ const dependency: AssetDefinition = { kind: 'script', source: 'file', filepath: 'path/to/dedup.js' };
310
+ const duplicateDeps = [dependency, dependency, dependency];
311
+
312
+ const results = await service.processDependencies(duplicateDeps, 'dedup-key');
313
+
314
+ expect(processMock).toHaveBeenCalledTimes(1);
315
+ expect(results.length).toBe(1);
316
+ });
317
+
318
+ test('AssetProcessingService - clearCache clears all cached assets', async () => {
319
+ fileSystem.ensureDir = vi.fn(() => {});
320
+ fileSystem.gzipDir = vi.fn(() => {});
321
+ fileSystem.exists = vi.fn(() => true);
322
+
323
+ const service = new AssetProcessingService(Config);
324
+ const processMock = vi.fn(async () => ({
325
+ filepath: '/test/dist/assets/clear.js',
326
+ kind: 'script',
327
+ inline: false,
328
+ }));
329
+ service.registerProcessor('script', 'file', { process: processMock });
330
+
331
+ const dependency: AssetDefinition = { kind: 'script', source: 'file', filepath: 'path/to/clear.js' };
332
+
333
+ await service.processDependencies([dependency], 'key1');
334
+ expect(processMock).toHaveBeenCalledTimes(1);
335
+
336
+ service.clearCache();
337
+
338
+ await service.processDependencies([dependency], 'key2');
339
+ expect(processMock).toHaveBeenCalledTimes(2);
340
+ });
341
+
342
+ test('AssetProcessingService - invalidateCacheForFile removes specific file from cache', async () => {
343
+ fileSystem.ensureDir = vi.fn(() => {});
344
+ fileSystem.gzipDir = vi.fn(() => {});
345
+ fileSystem.exists = vi.fn(() => true);
346
+
347
+ const service = new AssetProcessingService(Config);
348
+ const processMock = vi.fn(async () => ({
349
+ filepath: '/test/dist/assets/invalidate.js',
350
+ kind: 'script',
351
+ inline: false,
352
+ }));
353
+ service.registerProcessor('script', 'file', { process: processMock });
354
+
355
+ const dependency: AssetDefinition = { kind: 'script', source: 'file', filepath: 'path/to/invalidate.js' };
356
+
357
+ await service.processDependencies([dependency], 'key1');
358
+ expect(processMock).toHaveBeenCalledTimes(1);
359
+
360
+ service.invalidateCacheForFile('/test/dist/assets/invalidate.js');
361
+
362
+ await service.processDependencies([dependency], 'key2');
363
+ expect(processMock).toHaveBeenCalledTimes(2);
364
+ });
365
+
366
+ test('AssetProcessingService - skips missing file dependencies', async () => {
367
+ fileSystem.ensureDir = vi.fn(() => {});
368
+ fileSystem.gzipDir = vi.fn(() => {});
369
+ fileSystem.exists = vi.fn(() => false);
370
+
371
+ const service = new AssetProcessingService(Config);
372
+ const processMock = vi.fn(async () => ({
373
+ filepath: '/test/dist/assets/missing.js',
374
+ kind: 'script',
375
+ inline: false,
376
+ }));
377
+ service.registerProcessor('script', 'file', { process: processMock });
378
+
379
+ const dependency: AssetDefinition = { kind: 'script', source: 'file', filepath: 'path/to/missing.js' };
380
+
381
+ const results = await service.processDependencies([dependency], 'missing-key');
382
+
383
+ expect(processMock).not.toHaveBeenCalled();
384
+ expect(results.length).toBe(0);
385
+ });