@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,183 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ DefaultHtmlRewriterProvider,
4
+ type HtmlRewriterElement,
5
+ type HtmlRewriterLogger,
6
+ type HtmlRewriterRuntime,
7
+ } from './html-rewriter-provider.service';
8
+
9
+ type HtmlRewriterHandler = {
10
+ element: (element: HtmlRewriterElement) => void;
11
+ };
12
+
13
+ class TestHtmlRewriter implements HtmlRewriterRuntime {
14
+ private handlers = new Map<'head' | 'body', HtmlRewriterHandler>();
15
+
16
+ on(selector: 'head' | 'body', handler: HtmlRewriterHandler): TestHtmlRewriter {
17
+ this.handlers.set(selector, handler);
18
+ return this;
19
+ }
20
+
21
+ transform(response: Response): Response {
22
+ return response;
23
+ }
24
+ }
25
+
26
+ class TestLogger implements HtmlRewriterLogger {
27
+ public warnings: string[] = [];
28
+
29
+ warn(message: string) {
30
+ this.warnings.push(message);
31
+ }
32
+ }
33
+
34
+ describe('DefaultHtmlRewriterProvider', () => {
35
+ it('should prefer the native html rewriter in auto mode', async () => {
36
+ let workerToolsLoads = 0;
37
+
38
+ const provider = new DefaultHtmlRewriterProvider({
39
+ getNativeHtmlRewriter: () => TestHtmlRewriter,
40
+ loadWorkerToolsHtmlRewriter: async () => {
41
+ workerToolsLoads += 1;
42
+ return TestHtmlRewriter;
43
+ },
44
+ });
45
+
46
+ const htmlRewriter = await provider.createHtmlRewriter();
47
+
48
+ expect(htmlRewriter).toBeInstanceOf(TestHtmlRewriter);
49
+ expect(workerToolsLoads).toBe(0);
50
+ });
51
+
52
+ it('should load worker-tools when auto mode has no native runtime', async () => {
53
+ let workerToolsLoads = 0;
54
+
55
+ const provider = new DefaultHtmlRewriterProvider({
56
+ getNativeHtmlRewriter: () => undefined,
57
+ loadWorkerToolsHtmlRewriter: async () => {
58
+ workerToolsLoads += 1;
59
+ return TestHtmlRewriter;
60
+ },
61
+ });
62
+
63
+ const htmlRewriter = await provider.createHtmlRewriter();
64
+
65
+ expect(htmlRewriter).toBeInstanceOf(TestHtmlRewriter);
66
+ expect(workerToolsLoads).toBe(1);
67
+ });
68
+
69
+ it('should allow forcing worker-tools mode even when native is available', async () => {
70
+ let workerToolsLoads = 0;
71
+
72
+ const provider = new DefaultHtmlRewriterProvider({
73
+ mode: 'worker-tools',
74
+ getNativeHtmlRewriter: () => TestHtmlRewriter,
75
+ loadWorkerToolsHtmlRewriter: async () => {
76
+ workerToolsLoads += 1;
77
+ return TestHtmlRewriter;
78
+ },
79
+ });
80
+
81
+ const htmlRewriter = await provider.createHtmlRewriter();
82
+
83
+ expect(htmlRewriter).toBeInstanceOf(TestHtmlRewriter);
84
+ expect(workerToolsLoads).toBe(1);
85
+ });
86
+
87
+ it('should allow forcing fallback mode', async () => {
88
+ let workerToolsLoads = 0;
89
+
90
+ const provider = new DefaultHtmlRewriterProvider({
91
+ mode: 'fallback',
92
+ getNativeHtmlRewriter: () => TestHtmlRewriter,
93
+ loadWorkerToolsHtmlRewriter: async () => {
94
+ workerToolsLoads += 1;
95
+ return TestHtmlRewriter;
96
+ },
97
+ });
98
+
99
+ const htmlRewriter = await provider.createHtmlRewriter();
100
+
101
+ expect(htmlRewriter).toBeNull();
102
+ expect(workerToolsLoads).toBe(0);
103
+ });
104
+
105
+ it('should warn and fall back when native mode is forced without a runtime implementation', async () => {
106
+ const logger = new TestLogger();
107
+
108
+ const provider = new DefaultHtmlRewriterProvider({
109
+ mode: 'native',
110
+ logger,
111
+ getNativeHtmlRewriter: () => undefined,
112
+ });
113
+
114
+ const htmlRewriter = await provider.createHtmlRewriter();
115
+
116
+ expect(htmlRewriter).toBeNull();
117
+ expect(logger.warnings).toEqual([
118
+ '[HtmlTransformerService] Native HTMLRewriter was forced but is unavailable, falling back to string injection.',
119
+ ]);
120
+ });
121
+
122
+ it('should reset the cached constructor when the mode changes', async () => {
123
+ let workerToolsLoads = 0;
124
+
125
+ const provider = new DefaultHtmlRewriterProvider({
126
+ getNativeHtmlRewriter: () => undefined,
127
+ loadWorkerToolsHtmlRewriter: async () => {
128
+ workerToolsLoads += 1;
129
+ return TestHtmlRewriter;
130
+ },
131
+ });
132
+
133
+ await provider.createHtmlRewriter();
134
+ await provider.createHtmlRewriter();
135
+ provider.setMode('fallback');
136
+ const fallbackHtmlRewriter = await provider.createHtmlRewriter();
137
+
138
+ expect(workerToolsLoads).toBe(1);
139
+ expect(fallbackHtmlRewriter).toBeNull();
140
+ });
141
+
142
+ it('should allow switching back to worker-tools after fallback mode', async () => {
143
+ let workerToolsLoads = 0;
144
+
145
+ const provider = new DefaultHtmlRewriterProvider({
146
+ mode: 'fallback',
147
+ getNativeHtmlRewriter: () => undefined,
148
+ loadWorkerToolsHtmlRewriter: async () => {
149
+ workerToolsLoads += 1;
150
+ return TestHtmlRewriter;
151
+ },
152
+ });
153
+
154
+ await provider.createHtmlRewriter();
155
+ provider.setMode('worker-tools');
156
+ const htmlRewriter = await provider.createHtmlRewriter();
157
+
158
+ expect(htmlRewriter).toBeInstanceOf(TestHtmlRewriter);
159
+ expect(workerToolsLoads).toBe(1);
160
+ });
161
+
162
+ it('should return null when worker-tools loading fails', async () => {
163
+ const logger = new TestLogger();
164
+
165
+ const provider = new DefaultHtmlRewriterProvider({
166
+ logger,
167
+ getNativeHtmlRewriter: () => undefined,
168
+ loadWorkerToolsHtmlRewriter: async () => {
169
+ logger.warn(
170
+ '[HtmlTransformerService] Failed to load @worker-tools/html-rewriter/base64, falling back to string injection: test failure',
171
+ );
172
+ return null;
173
+ },
174
+ });
175
+
176
+ const htmlRewriter = await provider.createHtmlRewriter();
177
+
178
+ expect(htmlRewriter).toBeNull();
179
+ expect(logger.warnings).toEqual([
180
+ '[HtmlTransformerService] Failed to load @worker-tools/html-rewriter/base64, falling back to string injection: test failure',
181
+ ]);
182
+ });
183
+ });
@@ -0,0 +1,103 @@
1
+ import { appLogger } from '../../global/app-logger.js';
2
+
3
+ export type HtmlRewriterElement = {
4
+ append(content: string, options?: { html?: boolean }): void;
5
+ };
6
+
7
+ export type HtmlRewriterRuntime = {
8
+ on(selector: 'head' | 'body', handler: { element: (element: HtmlRewriterElement) => void }): HtmlRewriterRuntime;
9
+ transform(response: Response): Response;
10
+ };
11
+
12
+ export type HtmlRewriterConstructor = new () => HtmlRewriterRuntime;
13
+
14
+ export type HtmlRewriterMode = 'auto' | 'native' | 'worker-tools' | 'fallback';
15
+
16
+ export interface HtmlRewriterProvider {
17
+ createHtmlRewriter(): Promise<HtmlRewriterRuntime | null>;
18
+ setMode(mode: HtmlRewriterMode): void;
19
+ }
20
+
21
+ export interface HtmlRewriterLogger {
22
+ warn(message: string): void;
23
+ }
24
+
25
+ export interface DefaultHtmlRewriterProviderOptions {
26
+ mode?: HtmlRewriterMode;
27
+ logger?: HtmlRewriterLogger;
28
+ getNativeHtmlRewriter?: () => HtmlRewriterConstructor | undefined;
29
+ loadWorkerToolsHtmlRewriter?: () => Promise<HtmlRewriterConstructor | null>;
30
+ }
31
+
32
+ export class DefaultHtmlRewriterProvider implements HtmlRewriterProvider {
33
+ private htmlRewriterConstructorPromise?: Promise<HtmlRewriterConstructor | null>;
34
+ private htmlRewriterMode: HtmlRewriterMode;
35
+ private logger: HtmlRewriterLogger;
36
+ private getNativeHtmlRewriter: () => HtmlRewriterConstructor | undefined;
37
+ private loadWorkerToolsHtmlRewriter: () => Promise<HtmlRewriterConstructor | null>;
38
+
39
+ constructor(options: DefaultHtmlRewriterProviderOptions = {}) {
40
+ this.htmlRewriterMode = options.mode ?? 'auto';
41
+ this.logger = options.logger ?? appLogger;
42
+ this.getNativeHtmlRewriter =
43
+ options.getNativeHtmlRewriter ??
44
+ (() => (globalThis as { HTMLRewriter?: HtmlRewriterConstructor }).HTMLRewriter);
45
+ this.loadWorkerToolsHtmlRewriter = options.loadWorkerToolsHtmlRewriter ?? loadWorkerToolsHtmlRewriter;
46
+ }
47
+
48
+ setMode(mode: HtmlRewriterMode) {
49
+ this.htmlRewriterMode = mode;
50
+ this.htmlRewriterConstructorPromise = undefined;
51
+ }
52
+
53
+ async createHtmlRewriter(): Promise<HtmlRewriterRuntime | null> {
54
+ const RuntimeHtmlRewriter = await this.resolveHtmlRewriterConstructor();
55
+ return RuntimeHtmlRewriter ? new RuntimeHtmlRewriter() : null;
56
+ }
57
+
58
+ private async resolveHtmlRewriterConstructor(): Promise<HtmlRewriterConstructor | null> {
59
+ if (!this.htmlRewriterConstructorPromise) {
60
+ const mode = this.htmlRewriterMode;
61
+ const RuntimeHtmlRewriter = this.getNativeHtmlRewriter();
62
+
63
+ if (mode === 'fallback') {
64
+ this.htmlRewriterConstructorPromise = Promise.resolve(null);
65
+ } else if (mode === 'native') {
66
+ if (RuntimeHtmlRewriter) {
67
+ this.htmlRewriterConstructorPromise = Promise.resolve(RuntimeHtmlRewriter);
68
+ } else {
69
+ this.logger.warn(
70
+ '[HtmlTransformerService] Native HTMLRewriter was forced but is unavailable, falling back to string injection.',
71
+ );
72
+ this.htmlRewriterConstructorPromise = Promise.resolve(null);
73
+ }
74
+ } else if (mode === 'auto' && RuntimeHtmlRewriter) {
75
+ this.htmlRewriterConstructorPromise = Promise.resolve(RuntimeHtmlRewriter);
76
+ } else {
77
+ this.htmlRewriterConstructorPromise = this.loadWorkerToolsHtmlRewriter();
78
+ }
79
+ }
80
+
81
+ return this.htmlRewriterConstructorPromise;
82
+ }
83
+ }
84
+
85
+ async function loadWorkerToolsHtmlRewriter(): Promise<HtmlRewriterConstructor | null> {
86
+ try {
87
+ const module = await import('@worker-tools/html-rewriter/base64');
88
+ return module.HTMLRewriter as HtmlRewriterConstructor;
89
+ } catch (primaryError) {
90
+ try {
91
+ const runtimeLocalModule = await import(
92
+ new URL('../node_modules/@worker-tools/html-rewriter/base64.js', import.meta.url).href
93
+ );
94
+ return runtimeLocalModule.HTMLRewriter as HtmlRewriterConstructor;
95
+ } catch {
96
+ const message = primaryError instanceof Error ? primaryError.message : String(primaryError);
97
+ appLogger.warn(
98
+ `[HtmlTransformerService] Failed to load @worker-tools/html-rewriter/base64, falling back to string injection: ${message}`,
99
+ );
100
+ return null;
101
+ }
102
+ }
103
+ }
@@ -0,0 +1,378 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { ProcessedAsset } from '../assets/asset-processing-service/index.js';
3
+ import { HtmlTransformerService } from './html-transformer.service.ts';
4
+ import type {
5
+ HtmlRewriterElement,
6
+ HtmlRewriterMode,
7
+ HtmlRewriterProvider,
8
+ HtmlRewriterRuntime,
9
+ } from './html-rewriter-provider.service.ts';
10
+
11
+ type HtmlRewriterHandler = {
12
+ element: (element: HtmlRewriterElement) => void;
13
+ };
14
+
15
+ class TestHtmlRewriter {
16
+ private handlers = new Map<'head' | 'body', HtmlRewriterHandler>();
17
+
18
+ on(selector: 'head' | 'body', handler: HtmlRewriterHandler): TestHtmlRewriter {
19
+ this.handlers.set(selector, handler);
20
+ return this;
21
+ }
22
+
23
+ transform(response: Response): Response {
24
+ const body = new ReadableStream<Uint8Array>({
25
+ start: async (controller) => {
26
+ const html = await response.text();
27
+ let result = html;
28
+
29
+ for (const selector of ['head', 'body'] as const) {
30
+ const handler = this.handlers.get(selector);
31
+ if (!handler) {
32
+ continue;
33
+ }
34
+
35
+ const chunks: string[] = [];
36
+ handler.element({
37
+ append: (content: string) => {
38
+ chunks.push(content);
39
+ },
40
+ });
41
+
42
+ const closingTag = `</${selector}>`;
43
+ result = result.replace(closingTag, `${chunks.join('')}${closingTag}`);
44
+ }
45
+
46
+ controller.enqueue(new TextEncoder().encode(result));
47
+ controller.close();
48
+ },
49
+ });
50
+
51
+ return new Response(body, {
52
+ headers: response.headers,
53
+ status: response.status,
54
+ statusText: response.statusText,
55
+ });
56
+ }
57
+ }
58
+
59
+ class TestHtmlRewriterProvider implements HtmlRewriterProvider {
60
+ public mode: HtmlRewriterMode = 'auto';
61
+
62
+ setMode(mode: HtmlRewriterMode) {
63
+ this.mode = mode;
64
+ }
65
+
66
+ async createHtmlRewriter(): Promise<HtmlRewriterRuntime | null> {
67
+ return this.mode === 'fallback' ? null : new TestHtmlRewriter();
68
+ }
69
+ }
70
+
71
+ type HtmlRewriterModeScenario = {
72
+ label: string;
73
+ html: string;
74
+ dependencies: ProcessedAsset[];
75
+ expectedFragments: string[];
76
+ unexpectedFragments?: string[];
77
+ };
78
+
79
+ type HtmlRewriterModeCase = {
80
+ label: string;
81
+ mode: 'auto' | 'native' | 'worker-tools' | 'fallback';
82
+ };
83
+
84
+ describe('HtmlTransformerService', () => {
85
+ const createMockResponse = (html: string) => {
86
+ return new Response(html, {
87
+ headers: { 'Content-Type': 'text/html' },
88
+ });
89
+ };
90
+
91
+ const createTransformer = (mode: HtmlRewriterMode = 'auto') => {
92
+ const htmlRewriterProvider = new TestHtmlRewriterProvider();
93
+ const transformer = new HtmlTransformerService({ htmlRewriterMode: mode, htmlRewriterProvider });
94
+ return { transformer, htmlRewriterProvider };
95
+ };
96
+
97
+ const htmlRewriterModeCases: HtmlRewriterModeCase[] = [
98
+ { label: 'auto', mode: 'auto' },
99
+ { label: 'native', mode: 'native' },
100
+ { label: 'worker-tools', mode: 'worker-tools' },
101
+ { label: 'fallback', mode: 'fallback' },
102
+ ];
103
+
104
+ const htmlRewriterScenarios: HtmlRewriterModeScenario[] = [
105
+ {
106
+ label: 'injects mixed head and body dependencies while preserving document content',
107
+ html: '<html><head><title>Matrix</title></head><body><main>Page content</main></body></html>',
108
+ dependencies: [
109
+ {
110
+ kind: 'stylesheet',
111
+ inline: false,
112
+ position: 'head',
113
+ srcUrl: '/matrix.css',
114
+ attributes: { media: 'screen' },
115
+ },
116
+ {
117
+ kind: 'script',
118
+ inline: true,
119
+ content: 'window.matrix = true;',
120
+ position: 'head',
121
+ srcUrl: '/matrix-inline.js',
122
+ attributes: { id: 'matrix-inline' },
123
+ },
124
+ {
125
+ kind: 'script',
126
+ inline: false,
127
+ position: 'body',
128
+ srcUrl: '/matrix-body.js',
129
+ attributes: { defer: 'true' },
130
+ },
131
+ ],
132
+ expectedFragments: [
133
+ '<title>Matrix</title>',
134
+ '<main>Page content</main>',
135
+ '<link rel="stylesheet" href="/matrix.css" media="screen">',
136
+ '<script id="matrix-inline">window.matrix = true;</script>',
137
+ '<script src="/matrix-body.js" defer="true"></script>',
138
+ ],
139
+ },
140
+ {
141
+ label: 'skips excluded scripts while still injecting remaining dependencies',
142
+ html: '<html><head></head><body><section>Visible</section></body></html>',
143
+ dependencies: [
144
+ {
145
+ kind: 'script',
146
+ inline: false,
147
+ position: 'body',
148
+ srcUrl: '/excluded.js',
149
+ excludeFromHtml: true,
150
+ },
151
+ {
152
+ kind: 'script',
153
+ inline: false,
154
+ position: 'body',
155
+ srcUrl: '/included.js',
156
+ },
157
+ ],
158
+ expectedFragments: ['<section>Visible</section>', '<script src="/included.js"></script>'],
159
+ unexpectedFragments: ['<script src="/excluded.js"></script>'],
160
+ },
161
+ {
162
+ label: 'injects inline styles and preserves nested body markup',
163
+ html: '<html><head></head><body><div><span>Nested</span></div></body></html>',
164
+ dependencies: [
165
+ {
166
+ kind: 'stylesheet',
167
+ inline: true,
168
+ position: 'head',
169
+ content: '.nested{color:red;}',
170
+ srcUrl: '/nested.css',
171
+ attributes: { 'data-test': 'inline-style' },
172
+ },
173
+ ],
174
+ expectedFragments: [
175
+ '<div><span>Nested</span></div>',
176
+ '<style data-test="inline-style">.nested{color:red;}</style>',
177
+ ],
178
+ },
179
+ ];
180
+
181
+ it('should inject script dependencies correctly', async () => {
182
+ const dependencies: ProcessedAsset[] = [
183
+ {
184
+ kind: 'script',
185
+ inline: true,
186
+ content: "console.log('test')",
187
+ position: 'body',
188
+ srcUrl: '/test.js',
189
+ attributes: { id: 'test-script' },
190
+ },
191
+ ];
192
+
193
+ const { transformer } = createTransformer();
194
+ transformer.setProcessedDependencies(dependencies);
195
+ const Response = createMockResponse('<html><head></head><body></body></html>');
196
+ const result = await transformer.transform(Response);
197
+ const html = await result.text();
198
+
199
+ expect(html).toContain('<script id="test-script">console.log(\'test\')</script>');
200
+ });
201
+
202
+ it('should inject stylesheet dependencies correctly', async () => {
203
+ const dependencies: ProcessedAsset[] = [
204
+ {
205
+ kind: 'stylesheet',
206
+ inline: false,
207
+ position: 'head',
208
+ srcUrl: '/test.css',
209
+ attributes: { media: 'screen' },
210
+ },
211
+ ];
212
+
213
+ const { transformer } = createTransformer();
214
+ transformer.setProcessedDependencies(dependencies);
215
+ const Response = createMockResponse('<html><head></head><body></body></html>');
216
+ const result = await transformer.transform(Response);
217
+ const html = await result.text();
218
+
219
+ expect(html).toContain('<link rel="stylesheet" href="/test.css" media="screen">');
220
+ });
221
+
222
+ it('should handle both inline and src dependencies', async () => {
223
+ const dependencies: ProcessedAsset[] = [
224
+ {
225
+ kind: 'script',
226
+ inline: true,
227
+ content: 'const x = 1;',
228
+ position: 'head',
229
+ srcUrl: '/inline.js',
230
+ },
231
+ {
232
+ kind: 'script',
233
+ inline: false,
234
+ position: 'body',
235
+ srcUrl: '/external.js',
236
+ },
237
+ ];
238
+
239
+ const { transformer } = createTransformer();
240
+ transformer.setProcessedDependencies(dependencies);
241
+ const Response = createMockResponse('<html><head></head><body></body></html>');
242
+ const result = await transformer.transform(Response);
243
+ const html = await result.text();
244
+
245
+ expect(html).toContain('<script>const x = 1;</script>');
246
+ expect(html).toContain('<script src="/external.js"></script>');
247
+ });
248
+
249
+ it('should preserve existing HTML content', async () => {
250
+ const dependencies: ProcessedAsset[] = [
251
+ {
252
+ kind: 'script',
253
+ inline: true,
254
+ content: "console.log('test')",
255
+ position: 'body',
256
+ srcUrl: '/test.js',
257
+ },
258
+ ];
259
+
260
+ const originalHtml = '<html><head><title>Test</title></head><body><div>Content</div></body></html>';
261
+ const { transformer } = createTransformer();
262
+ transformer.setProcessedDependencies(dependencies);
263
+ const Response = createMockResponse(originalHtml);
264
+ const result = await transformer.transform(Response);
265
+ const html = await result.text();
266
+
267
+ expect(html).toContain('<title>Test</title>');
268
+ expect(html).toContain('<div>Content</div>');
269
+ expect(html).toContain("console.log('test')");
270
+ });
271
+
272
+ it('should use the injected html rewriter provider when available', async () => {
273
+ const dependencies: ProcessedAsset[] = [
274
+ {
275
+ kind: 'script',
276
+ inline: false,
277
+ position: 'body',
278
+ srcUrl: '/native.js',
279
+ },
280
+ ];
281
+
282
+ const { transformer } = createTransformer();
283
+ transformer.setProcessedDependencies(dependencies);
284
+ const result = await transformer.transform(createMockResponse('<html><head></head><body></body></html>'));
285
+ const html = await result.text();
286
+
287
+ expect(html).toContain('<script src="/native.js"></script>');
288
+ });
289
+
290
+ it('should fall back to string injection when the provider returns no rewriter', async () => {
291
+ const dependencies: ProcessedAsset[] = [
292
+ {
293
+ kind: 'stylesheet',
294
+ inline: false,
295
+ position: 'head',
296
+ srcUrl: '/worker-tools.css',
297
+ },
298
+ ];
299
+
300
+ const { transformer } = createTransformer('fallback');
301
+ transformer.setProcessedDependencies(dependencies);
302
+ const result = await transformer.transform(createMockResponse('<html><head></head><body></body></html>'));
303
+ const html = await result.text();
304
+
305
+ expect(html).toContain('<link rel="stylesheet" href="/worker-tools.css">');
306
+ });
307
+
308
+ it('should delegate html rewriter mode changes to the injected provider', () => {
309
+ const { transformer, htmlRewriterProvider } = createTransformer();
310
+
311
+ transformer.setHtmlRewriterMode('worker-tools');
312
+ expect(htmlRewriterProvider.mode).toBe('worker-tools');
313
+
314
+ transformer.setHtmlRewriterMode('fallback');
315
+ expect(htmlRewriterProvider.mode).toBe('fallback');
316
+ });
317
+
318
+ it('should support the same transformation scenarios across all html rewriter modes', async () => {
319
+ for (const modeCase of htmlRewriterModeCases) {
320
+ const { transformer } = createTransformer(modeCase.mode);
321
+
322
+ for (const scenario of htmlRewriterScenarios) {
323
+ transformer.setProcessedDependencies(scenario.dependencies);
324
+
325
+ const result = await transformer.transform(createMockResponse(scenario.html));
326
+ const html = await result.text();
327
+
328
+ for (const expectedFragment of scenario.expectedFragments) {
329
+ expect(html, `${modeCase.label}: ${scenario.label}`).toContain(expectedFragment);
330
+ }
331
+
332
+ for (const unexpectedFragment of scenario.unexpectedFragments ?? []) {
333
+ expect(html, `${modeCase.label}: ${scenario.label}`).not.toContain(unexpectedFragment);
334
+ }
335
+ }
336
+ }
337
+ });
338
+
339
+ it('should apply attributes to the html element', () => {
340
+ const { transformer } = createTransformer();
341
+ const result = transformer.applyAttributesToHtmlElement(
342
+ '<!DOCTYPE html><html lang="en"><body>Hello</body></html>',
343
+ {
344
+ 'data-eco-document-owner': 'react-router',
345
+ },
346
+ );
347
+
348
+ expect(result).toContain('<html lang="en" data-eco-document-owner="react-router">');
349
+ });
350
+
351
+ it('should apply attributes to the first body child', () => {
352
+ const { transformer } = createTransformer();
353
+ const result = transformer.applyAttributesToFirstBodyElement(
354
+ '<html><body><main>Hello</main><footer>Footer</footer></body></html>',
355
+ { 'data-eco-component-id': 'root-1', role: 'main' },
356
+ );
357
+
358
+ expect(result).toContain('<main data-eco-component-id="root-1" role="main">Hello</main>');
359
+ });
360
+
361
+ it('should apply attributes to the first fragment element', () => {
362
+ const { transformer } = createTransformer();
363
+ const result = transformer.applyAttributesToFirstElement(' <aside>Content</aside><div>Other</div>', {
364
+ 'aria-live': 'polite',
365
+ });
366
+
367
+ expect(result).toContain('<aside aria-live="polite">Content</aside>');
368
+ });
369
+
370
+ it('should deduplicate processed assets while preserving order', () => {
371
+ const { transformer } = createTransformer();
372
+ const first = { kind: 'script', srcUrl: '/assets/app.js', position: 'head' } as ProcessedAsset;
373
+ const duplicate = { kind: 'script', srcUrl: '/assets/app.js', position: 'head' } as ProcessedAsset;
374
+ const second = { kind: 'stylesheet', srcUrl: '/assets/app.css', position: 'head' } as ProcessedAsset;
375
+
376
+ expect(transformer.dedupeProcessedAssets([first, duplicate, second])).toEqual([first, second]);
377
+ });
378
+ });