@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,225 @@
1
+ /**
2
+ * Unit tests for MemoryCacheStore
3
+ */
4
+
5
+ import { describe, expect, test, beforeEach } from 'vitest';
6
+ import { MemoryCacheStore } from './memory-cache-store.js';
7
+ import type { CacheEntry } from './cache.types.js';
8
+
9
+ function createEntry(overrides: Partial<CacheEntry> = {}): CacheEntry {
10
+ return {
11
+ html: '<html>test</html>',
12
+ createdAt: Date.now(),
13
+ revalidateAfter: null,
14
+ tags: [],
15
+ strategy: 'static',
16
+ ...overrides,
17
+ };
18
+ }
19
+
20
+ describe('MemoryCacheStore', () => {
21
+ let store: MemoryCacheStore;
22
+
23
+ beforeEach(() => {
24
+ store = new MemoryCacheStore();
25
+ });
26
+
27
+ describe('get/set', () => {
28
+ test('should return null for cache miss', async () => {
29
+ const result = await store.get('/nonexistent');
30
+ expect(result).toBeNull();
31
+ });
32
+
33
+ test('should store and retrieve an entry', async () => {
34
+ const entry = createEntry({ html: '<html>hello</html>' });
35
+ await store.set('/page', entry);
36
+ const result = await store.get('/page');
37
+ expect(result?.html).toBe('<html>hello</html>');
38
+ });
39
+
40
+ test('should update existing entry', async () => {
41
+ await store.set('/page', createEntry({ html: '<html>v1</html>' }));
42
+ await store.set('/page', createEntry({ html: '<html>v2</html>' }));
43
+ const result = await store.get('/page');
44
+ expect(result?.html).toBe('<html>v2</html>');
45
+ });
46
+ });
47
+
48
+ describe('LRU eviction', () => {
49
+ test('should evict oldest entry when maxEntries reached', async () => {
50
+ const smallStore = new MemoryCacheStore({ maxEntries: 3 });
51
+
52
+ await smallStore.set('/page1', createEntry());
53
+ await smallStore.set('/page2', createEntry());
54
+ await smallStore.set('/page3', createEntry());
55
+
56
+ await smallStore.set('/page4', createEntry());
57
+
58
+ expect(await smallStore.get('/page1')).toBeNull();
59
+ expect(await smallStore.get('/page2')).not.toBeNull();
60
+ expect(await smallStore.get('/page3')).not.toBeNull();
61
+ expect(await smallStore.get('/page4')).not.toBeNull();
62
+ });
63
+
64
+ test('should refresh entry position on access', async () => {
65
+ const smallStore = new MemoryCacheStore({ maxEntries: 3 });
66
+
67
+ await smallStore.set('/page1', createEntry());
68
+ await smallStore.set('/page2', createEntry());
69
+ await smallStore.set('/page3', createEntry());
70
+
71
+ await smallStore.get('/page1');
72
+
73
+ await smallStore.set('/page4', createEntry());
74
+
75
+ expect(await smallStore.get('/page1')).not.toBeNull();
76
+ expect(await smallStore.get('/page2')).toBeNull();
77
+ expect(await smallStore.get('/page3')).not.toBeNull();
78
+ expect(await smallStore.get('/page4')).not.toBeNull();
79
+ });
80
+
81
+ test('should not evict when updating existing key', async () => {
82
+ const smallStore = new MemoryCacheStore({ maxEntries: 3 });
83
+
84
+ await smallStore.set('/page1', createEntry());
85
+ await smallStore.set('/page2', createEntry());
86
+ await smallStore.set('/page3', createEntry());
87
+
88
+ await smallStore.set('/page1', createEntry({ html: '<html>updated</html>' }));
89
+
90
+ const stats = await smallStore.stats();
91
+ expect(stats.entries).toBe(3);
92
+ expect((await smallStore.get('/page1'))?.html).toBe('<html>updated</html>');
93
+ });
94
+
95
+ test('should refresh entry position on update (move to most recent)', async () => {
96
+ const smallStore = new MemoryCacheStore({ maxEntries: 3 });
97
+
98
+ await smallStore.set('/page1', createEntry({ html: '<html>v1</html>' }));
99
+ await smallStore.set('/page2', createEntry());
100
+ await smallStore.set('/page3', createEntry());
101
+
102
+ await smallStore.set('/page1', createEntry({ html: '<html>v2</html>' }));
103
+
104
+ await smallStore.set('/page4', createEntry());
105
+
106
+ expect(await smallStore.get('/page1')).not.toBeNull();
107
+ expect(await smallStore.get('/page2')).toBeNull();
108
+ expect(await smallStore.get('/page3')).not.toBeNull();
109
+ expect(await smallStore.get('/page4')).not.toBeNull();
110
+ });
111
+ });
112
+
113
+ describe('delete', () => {
114
+ test('should delete an entry', async () => {
115
+ await store.set('/page', createEntry());
116
+ const deleted = await store.delete('/page');
117
+ expect(deleted).toBe(true);
118
+ expect(await store.get('/page')).toBeNull();
119
+ });
120
+
121
+ test('should return false for non-existent entry', async () => {
122
+ const deleted = await store.delete('/nonexistent');
123
+ expect(deleted).toBe(false);
124
+ });
125
+ });
126
+
127
+ describe('invalidateByTags', () => {
128
+ test('should invalidate all entries with matching tag', async () => {
129
+ await store.set('/blog/1', createEntry({ tags: ['blog'] }));
130
+ await store.set('/blog/2', createEntry({ tags: ['blog'] }));
131
+ await store.set('/about', createEntry({ tags: ['static'] }));
132
+
133
+ const count = await store.invalidateByTags(['blog']);
134
+ expect(count).toBe(2);
135
+ expect(await store.get('/blog/1')).toBeNull();
136
+ expect(await store.get('/blog/2')).toBeNull();
137
+ expect(await store.get('/about')).not.toBeNull();
138
+ });
139
+
140
+ test('should handle multiple tags', async () => {
141
+ await store.set('/blog/1', createEntry({ tags: ['blog', 'featured'] }));
142
+ await store.set('/product/1', createEntry({ tags: ['product'] }));
143
+
144
+ const count = await store.invalidateByTags(['blog', 'product']);
145
+ expect(count).toBe(2);
146
+ });
147
+
148
+ test('should return 0 for non-matching tags', async () => {
149
+ await store.set('/page', createEntry({ tags: ['blog'] }));
150
+ const count = await store.invalidateByTags(['nonexistent']);
151
+ expect(count).toBe(0);
152
+ });
153
+
154
+ test('should clean up all tag references when entry has multiple tags', async () => {
155
+ await store.set('/blog/featured', createEntry({ tags: ['blog', 'featured', 'homepage'] }));
156
+ await store.set('/blog/regular', createEntry({ tags: ['blog'] }));
157
+ await store.set('/featured-product', createEntry({ tags: ['featured', 'product'] }));
158
+
159
+ const count = await store.invalidateByTags(['blog']);
160
+ expect(count).toBe(2);
161
+
162
+ expect(await store.get('/blog/featured')).toBeNull();
163
+ expect(await store.get('/blog/regular')).toBeNull();
164
+ expect(await store.get('/featured-product')).not.toBeNull();
165
+
166
+ const countFeatured = await store.invalidateByTags(['featured']);
167
+ expect(countFeatured).toBe(1);
168
+ expect(await store.get('/featured-product')).toBeNull();
169
+ });
170
+
171
+ test('should not leave orphaned tag references after invalidation', async () => {
172
+ await store.set('/page1', createEntry({ tags: ['tagA', 'tagB'] }));
173
+
174
+ await store.invalidateByTags(['tagA']);
175
+
176
+ expect(await store.get('/page1')).toBeNull();
177
+
178
+ await store.set('/page2', createEntry({ tags: ['tagB'] }));
179
+ const count = await store.invalidateByTags(['tagB']);
180
+ expect(count).toBe(1);
181
+ });
182
+ });
183
+
184
+ describe('invalidateByPaths', () => {
185
+ test('should invalidate specific paths', async () => {
186
+ await store.set('/blog/1', createEntry());
187
+ await store.set('/blog/2', createEntry());
188
+
189
+ const count = await store.invalidateByPaths(['/blog/1']);
190
+ expect(count).toBe(1);
191
+ expect(await store.get('/blog/1')).toBeNull();
192
+ expect(await store.get('/blog/2')).not.toBeNull();
193
+ });
194
+
195
+ test('should handle multiple paths', async () => {
196
+ await store.set('/blog/1', createEntry());
197
+ await store.set('/blog/2', createEntry());
198
+ await store.set('/about', createEntry());
199
+
200
+ const count = await store.invalidateByPaths(['/blog/1', '/about']);
201
+ expect(count).toBe(2);
202
+ });
203
+ });
204
+
205
+ describe('clear', () => {
206
+ test('should remove all entries', async () => {
207
+ await store.set('/page1', createEntry());
208
+ await store.set('/page2', createEntry());
209
+ await store.clear();
210
+
211
+ const stats = await store.stats();
212
+ expect(stats.entries).toBe(0);
213
+ });
214
+ });
215
+
216
+ describe('stats', () => {
217
+ test('should return entry count', async () => {
218
+ await store.set('/page1', createEntry());
219
+ await store.set('/page2', createEntry());
220
+
221
+ const stats = await store.stats();
222
+ expect(stats.entries).toBe(2);
223
+ });
224
+ });
225
+ });
@@ -4,7 +4,7 @@
4
4
  * @module
5
5
  */
6
6
 
7
- import type { CacheEntry, CacheStats, CacheStore } from './cache.types.ts';
7
+ import type { CacheEntry, CacheStats, CacheStore } from './cache.types.js';
8
8
 
9
9
  export interface MemoryCacheStoreOptions {
10
10
  /** Maximum number of entries before LRU eviction. @default 1000 */
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Unit tests for PageCacheService
3
+ */
4
+
5
+ import { describe, expect, test, beforeEach, vi } from 'vitest';
6
+ import { PageCacheService, getCacheControlHeader } from './page-cache-service.js';
7
+ import { MemoryCacheStore } from './memory-cache-store.js';
8
+
9
+ describe('PageCacheService', () => {
10
+ let service: PageCacheService;
11
+ let store: MemoryCacheStore;
12
+
13
+ beforeEach(() => {
14
+ store = new MemoryCacheStore();
15
+ service = new PageCacheService({ store });
16
+ });
17
+
18
+ describe('generateCacheKey', () => {
19
+ test('should use full URL as key', () => {
20
+ expect(service.generateCacheKey('/blog/post-1')).toBe('/blog/post-1');
21
+ expect(service.generateCacheKey('/search?q=test')).toBe('/search?q=test');
22
+ });
23
+ });
24
+
25
+ describe('getOrCreate', () => {
26
+ test('should return miss and render on cache miss', async () => {
27
+ const renderFn = vi.fn().mockResolvedValue({ html: '<html>hello</html>', strategy: 'static' as const });
28
+
29
+ const result = await service.getOrCreate('/page', 'static', renderFn);
30
+
31
+ expect(result.status).toBe('miss');
32
+ expect(result.html).toBe('<html>hello</html>');
33
+ expect(result.strategy).toBe('static');
34
+ expect(renderFn).toHaveBeenCalledTimes(1);
35
+ });
36
+
37
+ test('should return hit on cache hit', async () => {
38
+ const renderFn = vi.fn().mockResolvedValue({ html: '<html>hello</html>', strategy: 'static' as const });
39
+
40
+ await service.getOrCreate('/page', 'static', renderFn);
41
+
42
+ renderFn.mockClear();
43
+ const result = await service.getOrCreate('/page', 'static', renderFn);
44
+
45
+ expect(result.status).toBe('hit');
46
+ expect(result.html).toBe('<html>hello</html>');
47
+ expect(result.strategy).toBe('static');
48
+ expect(renderFn).not.toHaveBeenCalled();
49
+ });
50
+
51
+ test('should bypass cache for dynamic strategy', async () => {
52
+ const renderFn = vi.fn().mockResolvedValue({ html: '<html>hello</html>', strategy: 'dynamic' as const });
53
+
54
+ const result1 = await service.getOrCreate('/page', 'dynamic', renderFn);
55
+ const result2 = await service.getOrCreate('/page', 'dynamic', renderFn);
56
+
57
+ expect(result1.status).toBe('miss');
58
+ expect(result2.status).toBe('miss');
59
+ expect(renderFn).toHaveBeenCalledTimes(2);
60
+ });
61
+
62
+ test('should return stale when entry is past revalidation time', async () => {
63
+ const revalidateStrategy = { revalidate: 60 };
64
+ const renderFn = vi.fn().mockResolvedValue({ html: '<html>v1</html>', strategy: revalidateStrategy });
65
+
66
+ const staleEntry = {
67
+ html: '<html>stale</html>',
68
+ createdAt: Date.now() - 120000,
69
+ revalidateAfter: Date.now() - 60000,
70
+ tags: [],
71
+ strategy: revalidateStrategy,
72
+ };
73
+ await store.set('/stale-page', staleEntry);
74
+
75
+ const result = await service.getOrCreate('/stale-page', { revalidate: 60 }, renderFn);
76
+ expect(result.status).toBe('stale');
77
+ expect(result.html).toBe('<html>stale</html>');
78
+ });
79
+
80
+ test('should deduplicate concurrent regeneration requests', async () => {
81
+ let callCount = 0;
82
+ const renderFn = vi.fn().mockImplementation(async () => {
83
+ callCount++;
84
+ await new Promise((resolve) => setTimeout(resolve, 10));
85
+ return { html: `<html>v${callCount}</html>`, strategy: { revalidate: 60 } };
86
+ });
87
+
88
+ const staleEntry = {
89
+ html: '<html>stale</html>',
90
+ createdAt: Date.now() - 120000,
91
+ revalidateAfter: Date.now() - 60000,
92
+ tags: [],
93
+ strategy: { revalidate: 60 },
94
+ };
95
+ await store.set('/dedup-page', staleEntry);
96
+
97
+ const results = await Promise.all([
98
+ service.getOrCreate('/dedup-page', { revalidate: 60 }, renderFn),
99
+ service.getOrCreate('/dedup-page', { revalidate: 60 }, renderFn),
100
+ service.getOrCreate('/dedup-page', { revalidate: 60 }, renderFn),
101
+ ]);
102
+
103
+ for (const result of results) {
104
+ expect(result.status).toBe('stale');
105
+ expect(result.html).toBe('<html>stale</html>');
106
+ }
107
+
108
+ await new Promise((resolve) => setTimeout(resolve, 50));
109
+
110
+ expect(renderFn).toHaveBeenCalledTimes(1);
111
+ });
112
+ });
113
+
114
+ describe('invalidation', () => {
115
+ test('should invalidate by tags', async () => {
116
+ const strategy = { revalidate: 3600, tags: ['blog'] };
117
+ const renderFn = vi.fn().mockResolvedValue({ html: '<html>hello</html>', strategy });
118
+
119
+ await service.getOrCreate('/blog/1', strategy, renderFn);
120
+ await service.getOrCreate('/blog/2', strategy, renderFn);
121
+
122
+ const count = await service.invalidateByTags(['blog']);
123
+ expect(count).toBe(2);
124
+
125
+ renderFn.mockClear();
126
+ const result = await service.getOrCreate('/blog/1', 'static', renderFn);
127
+ expect(result.status).toBe('miss');
128
+ });
129
+
130
+ test('should invalidate by paths', async () => {
131
+ const renderFn = vi.fn().mockResolvedValue({ html: '<html>hello</html>', strategy: 'static' as const });
132
+
133
+ await service.getOrCreate('/blog/1', 'static', renderFn);
134
+
135
+ const count = await service.invalidateByPaths(['/blog/1']);
136
+ expect(count).toBe(1);
137
+
138
+ renderFn.mockClear();
139
+ const result = await service.getOrCreate('/blog/1', 'static', renderFn);
140
+ expect(result.status).toBe('miss');
141
+ });
142
+ });
143
+
144
+ describe('disabled cache', () => {
145
+ test('should bypass cache when disabled', async () => {
146
+ const disabledService = new PageCacheService({ store, enabled: false });
147
+ const renderFn = vi.fn().mockResolvedValue({ html: '<html>hello</html>', strategy: 'static' as const });
148
+
149
+ const result1 = await disabledService.getOrCreate('/page', 'static', renderFn);
150
+ const result2 = await disabledService.getOrCreate('/page', 'static', renderFn);
151
+
152
+ expect(result1.status).toBe('miss');
153
+ expect(result2.status).toBe('miss');
154
+ expect(renderFn).toHaveBeenCalledTimes(2);
155
+ });
156
+ });
157
+ });
158
+
159
+ describe('getCacheControlHeader', () => {
160
+ test('should return immutable for static strategy', () => {
161
+ expect(getCacheControlHeader('static')).toBe('public, max-age=31536000, immutable');
162
+ });
163
+
164
+ test('should return no-store for dynamic strategy', () => {
165
+ expect(getCacheControlHeader('dynamic')).toBe('no-store, must-revalidate');
166
+ });
167
+
168
+ test('should return max-age and stale-while-revalidate for object strategy', () => {
169
+ expect(getCacheControlHeader({ revalidate: 3600 })).toBe('public, max-age=3600, stale-while-revalidate=7200');
170
+ });
171
+
172
+ test('should return no-store when disabled', () => {
173
+ expect(getCacheControlHeader('disabled')).toBe('no-store, must-revalidate');
174
+ });
175
+ });
@@ -4,9 +4,9 @@
4
4
  * @module
5
5
  */
6
6
 
7
- import { appLogger } from '../../global/app-logger.ts';
8
- import type { CacheEntry, CacheResult, CacheStore, CacheStrategy, RenderResult } from './cache.types.ts';
9
- import { MemoryCacheStore } from './memory-cache-store.ts';
7
+ import { appLogger } from '../../global/app-logger.js';
8
+ import type { CacheEntry, CacheResult, CacheStore, CacheStrategy, RenderResult } from './cache.types.js';
9
+ import { MemoryCacheStore } from './memory-cache-store.js';
10
10
 
11
11
  export interface PageCacheServiceOptions {
12
12
  store?: CacheStore;
@@ -0,0 +1,79 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { PageRequestCacheCoordinator } from './page-request-cache-coordinator.service.ts';
3
+ import type { PageCacheService } from './page-cache-service.js';
4
+
5
+ describe('PageRequestCacheCoordinator', () => {
6
+ it('should build cache keys with query parameters', () => {
7
+ const service = new PageRequestCacheCoordinator(null, 'static');
8
+
9
+ expect(service.buildCacheKey({ pathname: '/blog' })).toBe('/blog');
10
+ expect(service.buildCacheKey({ pathname: '/blog', query: { page: '2', tag: 'eco' } })).toBe(
11
+ '/blog?page=2&tag=eco',
12
+ );
13
+ });
14
+
15
+ it('should bypass the cache service for dynamic pages', async () => {
16
+ const cacheService = {
17
+ getOrCreate: vi.fn(),
18
+ } as unknown as PageCacheService;
19
+ const renderFn = vi.fn(async () => ({
20
+ html: '<html><body>dynamic</body></html>',
21
+ strategy: 'dynamic' as const,
22
+ }));
23
+ const service = new PageRequestCacheCoordinator(cacheService, 'static');
24
+
25
+ const response = await service.render({
26
+ cacheKey: '/dynamic',
27
+ pageCacheStrategy: 'dynamic',
28
+ renderFn,
29
+ });
30
+
31
+ expect(await response.text()).toBe('<html><body>dynamic</body></html>');
32
+ expect(response.headers.get('X-Cache')).toBe('DISABLED');
33
+ expect(cacheService.getOrCreate).not.toHaveBeenCalled();
34
+ expect(renderFn).toHaveBeenCalledTimes(1);
35
+ });
36
+
37
+ it('should delegate cached rendering to the cache service', async () => {
38
+ const cacheService = {
39
+ getOrCreate: vi.fn(async () => ({
40
+ html: '<html><body>cached</body></html>',
41
+ strategy: { revalidate: 60 },
42
+ status: 'hit',
43
+ })),
44
+ } as unknown as PageCacheService;
45
+ const service = new PageRequestCacheCoordinator(cacheService, 'static');
46
+
47
+ const response = await service.render({
48
+ cacheKey: '/cached',
49
+ pageCacheStrategy: { revalidate: 60 },
50
+ renderFn: async () => ({
51
+ html: '<html><body>fresh</body></html>',
52
+ strategy: { revalidate: 60 },
53
+ }),
54
+ });
55
+
56
+ expect(await response.text()).toBe('<html><body>cached</body></html>');
57
+ expect(response.headers.get('X-Cache')).toBe('HIT');
58
+ expect(response.headers.get('Cache-Control')).toContain('max-age=60');
59
+ expect(cacheService.getOrCreate).toHaveBeenCalledWith('/cached', { revalidate: 60 }, expect.any(Function));
60
+ });
61
+
62
+ it('should normalize supported body types to strings', async () => {
63
+ const service = new PageRequestCacheCoordinator(null, 'static');
64
+
65
+ expect(await service.bodyToString('plain')).toBe('plain');
66
+ expect(await service.bodyToString(Buffer.from('buffered'))).toBe('buffered');
67
+ expect(await service.bodyToString(new Uint8Array([104, 101, 108, 108, 111]))).toBe('hello');
68
+ expect(
69
+ await service.bodyToString(
70
+ new ReadableStream({
71
+ start: (controller) => {
72
+ controller.enqueue(new TextEncoder().encode('streamed'));
73
+ controller.close();
74
+ },
75
+ }),
76
+ ),
77
+ ).toBe('streamed');
78
+ });
79
+ });
@@ -1,5 +1,5 @@
1
- import { getCacheControlHeader, type PageCacheService } from './cache/page-cache-service.ts';
2
- import type { CacheStrategy, RenderResult } from './cache/cache.types.ts';
1
+ import { getCacheControlHeader, type PageCacheService } from './page-cache-service.js';
2
+ import type { CacheStrategy, RenderResult } from './cache.types.js';
3
3
 
4
4
  type CacheStatus = 'hit' | 'miss' | 'stale' | 'expired' | 'disabled';
5
5
 
@@ -11,10 +11,13 @@ type CacheStatus = 'hit' | 'miss' | 'stale' | 'expired' | 'disabled';
11
11
  * body normalization for cache storage, and final cache header generation.
12
12
  */
13
13
  export class PageRequestCacheCoordinator {
14
- constructor(
15
- private cacheService: PageCacheService | null,
16
- private defaultCacheStrategy: CacheStrategy,
17
- ) {}
14
+ private cacheService: PageCacheService | null;
15
+ private defaultCacheStrategy: CacheStrategy;
16
+
17
+ constructor(cacheService: PageCacheService | null, defaultCacheStrategy: CacheStrategy) {
18
+ this.cacheService = cacheService;
19
+ this.defaultCacheStrategy = defaultCacheStrategy;
20
+ }
18
21
 
19
22
  /**
20
23
  * Builds the cache key used for page lookups.