@ecopages/core 0.2.0-alpha.53 → 0.2.0-alpha.54

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 (590) hide show
  1. package/README.md +2 -3
  2. package/package.json +97 -182
  3. package/src/adapters/abstract/application-adapter.test.ts +218 -0
  4. package/src/adapters/abstract/application-adapter.ts +379 -0
  5. package/src/adapters/abstract/router-adapter.ts +30 -0
  6. package/src/adapters/abstract/server-adapter.ts +79 -0
  7. package/src/adapters/bun/client-bridge.ts +62 -0
  8. package/src/adapters/bun/create-app.ts +214 -0
  9. package/src/adapters/bun/hmr-manager.test.ts +265 -0
  10. package/src/adapters/bun/hmr-manager.ts +88 -0
  11. package/src/adapters/bun/index.ts +2 -0
  12. package/src/adapters/bun/runtime-host.ts +76 -0
  13. package/src/adapters/bun/server-adapter.ts +605 -0
  14. package/src/adapters/bun/static-preview-host.ts +70 -0
  15. package/src/adapters/create-app.test.ts +10 -0
  16. package/src/adapters/create-app.ts +91 -0
  17. package/src/adapters/index.ts +2 -0
  18. package/src/adapters/node/create-app.test.ts +76 -0
  19. package/src/adapters/node/create-app.ts +116 -0
  20. package/src/adapters/node/http-request-bridge.test.ts +146 -0
  21. package/src/adapters/node/http-request-bridge.ts +176 -0
  22. package/src/adapters/node/node-client-bridge.test.ts +198 -0
  23. package/src/adapters/node/node-client-bridge.ts +79 -0
  24. package/src/adapters/node/node-hmr-manager.test.ts +374 -0
  25. package/src/adapters/node/node-hmr-manager.ts +72 -0
  26. package/src/adapters/node/runtime-host.test.ts +49 -0
  27. package/src/adapters/node/runtime-host.ts +113 -0
  28. package/src/adapters/node/server-adapter-dependencies.ts +28 -0
  29. package/src/adapters/node/server-adapter.test.ts +84 -0
  30. package/src/adapters/node/server-adapter.ts +423 -0
  31. package/src/adapters/node/static-content-server.test.ts +60 -0
  32. package/src/adapters/node/static-content-server.ts +239 -0
  33. package/src/adapters/node/static-preview-host.test.ts +89 -0
  34. package/src/adapters/node/static-preview-host.ts +101 -0
  35. package/src/adapters/shared/api-response.test.ts +97 -0
  36. package/src/adapters/shared/api-response.ts +104 -0
  37. package/src/adapters/shared/application-adapter.ts +199 -0
  38. package/src/adapters/shared/define-api-handler.ts +66 -0
  39. package/src/adapters/shared/explicit-static-render-preparation.ts +58 -0
  40. package/src/adapters/shared/explicit-static-route-matcher.test.ts +381 -0
  41. package/src/adapters/shared/explicit-static-route-matcher.ts +131 -0
  42. package/src/adapters/shared/file-route-middleware-pipeline.test.ts +85 -0
  43. package/src/adapters/shared/file-route-middleware-pipeline.ts +118 -0
  44. package/src/adapters/shared/fs-server-response-factory.test.ts +176 -0
  45. package/src/adapters/shared/fs-server-response-factory.ts +96 -0
  46. package/src/adapters/shared/fs-server-response-matcher.test.ts +311 -0
  47. package/src/adapters/shared/fs-server-response-matcher.ts +240 -0
  48. package/src/adapters/shared/hmr-entrypoint-registrar.ts +149 -0
  49. package/src/adapters/shared/hmr-html-response.ts +54 -0
  50. package/src/adapters/shared/hmr-manager.contract.test.ts +228 -0
  51. package/src/adapters/shared/hmr-manager.dispatch.test.ts +229 -0
  52. package/src/adapters/shared/render-context.test.ts +244 -0
  53. package/src/adapters/shared/render-context.ts +161 -0
  54. package/src/adapters/shared/runtime-app-bootstrap.test.ts +96 -0
  55. package/src/adapters/shared/runtime-app-bootstrap.ts +72 -0
  56. package/src/adapters/shared/runtime-host.ts +11 -0
  57. package/src/adapters/shared/server-adapter.test.ts +130 -0
  58. package/src/adapters/shared/server-adapter.ts +571 -0
  59. package/src/adapters/shared/server-route-handler.test.ts +112 -0
  60. package/src/adapters/shared/server-route-handler.ts +153 -0
  61. package/src/adapters/shared/server-static-builder.test.ts +338 -0
  62. package/src/adapters/shared/server-static-builder.ts +170 -0
  63. package/src/adapters/shared/shared-hmr-manager.ts +298 -0
  64. package/src/adapters/shared/static-preview-host.ts +12 -0
  65. package/src/build/README.md +57 -73
  66. package/src/build/browser-runtime-manifest.test.ts +121 -0
  67. package/src/build/browser-runtime-manifest.ts +105 -0
  68. package/src/build/browser-runtime-plugin-helpers.test.ts +49 -0
  69. package/src/build/browser-runtime-plugin-helpers.ts +37 -0
  70. package/src/build/browser-runtime-plugin.test.ts +256 -0
  71. package/src/build/browser-runtime-plugin.ts +306 -0
  72. package/src/build/build-adapter.test.ts +463 -0
  73. package/src/build/build-adapter.ts +788 -0
  74. package/src/build/build-manifest.ts +79 -0
  75. package/src/build/build-types.ts +83 -0
  76. package/src/build/rolldown-build-adapter.test.ts +352 -0
  77. package/src/build/rolldown-build-adapter.ts +363 -0
  78. package/src/build/rolldown-plugin-bridge.test.ts +256 -0
  79. package/src/build/rolldown-plugin-bridge.ts +309 -0
  80. package/src/build/runtime-build-executor.test.ts +130 -0
  81. package/src/build/runtime-build-executor.ts +37 -0
  82. package/src/build/runtime-build-output-normalizer.ts +137 -0
  83. package/src/build/serialized-build-executor.test.ts +96 -0
  84. package/src/build/serialized-build-executor.ts +90 -0
  85. package/src/build/server-side-css-shim-plugin.ts +77 -0
  86. package/src/cache/index.ts +6 -0
  87. package/src/cache/module-parse-cache.test.ts +73 -0
  88. package/src/cache/module-parse-cache.ts +137 -0
  89. package/src/config/README.md +1 -1
  90. package/src/config/config-builder.test.ts +456 -0
  91. package/src/config/config-builder.ts +728 -0
  92. package/src/config/config-builder.typecheck.test.ts +96 -0
  93. package/src/config/{constants.d.ts → constants.ts} +22 -13
  94. package/src/dev/host-runtime.ts +34 -0
  95. package/src/dev/sc-server.ts +143 -0
  96. package/src/eco/eco.browser.test.ts +43 -0
  97. package/src/eco/eco.browser.ts +137 -0
  98. package/src/eco/eco.test.ts +781 -0
  99. package/src/eco/eco.ts +262 -0
  100. package/src/eco/eco.types.ts +293 -0
  101. package/src/eco/eco.utils.test.ts +219 -0
  102. package/src/eco/eco.utils.ts +5 -0
  103. package/src/eco/global-injector-map.test.ts +42 -0
  104. package/src/eco/global-injector-map.ts +112 -0
  105. package/src/eco/lazy-injector-map.test.ts +66 -0
  106. package/src/eco/lazy-injector-map.ts +120 -0
  107. package/src/eco/module-dependencies.test.ts +30 -0
  108. package/src/eco/module-dependencies.ts +75 -0
  109. package/src/errors/http-error.test.ts +134 -0
  110. package/src/errors/http-error.ts +72 -0
  111. package/src/errors/index.ts +3 -0
  112. package/src/errors/locals-access-error.ts +7 -0
  113. package/src/global/app-logger.ts +4 -0
  114. package/src/global/utils.test.ts +12 -0
  115. 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
  116. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-load-fixture-app-page-1.png +0 -0
  117. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-WebSocket-Connection-should-connect-to-correct-HMR-endpoint-1.png +0 -0
  118. package/src/hmr/client/hmr-runtime.ts +162 -0
  119. package/src/hmr/hmr-strategy.test.ts +124 -0
  120. package/src/hmr/hmr-strategy.ts +177 -0
  121. package/src/hmr/hmr.postcss.test.e2e.ts +41 -0
  122. package/src/hmr/hmr.test.e2e.ts +66 -0
  123. package/src/hmr/strategies/default-hmr-strategy.ts +60 -0
  124. package/src/hmr/strategies/js-hmr-strategy.test.ts +344 -0
  125. package/src/hmr/strategies/js-hmr-strategy.ts +307 -0
  126. package/src/index.browser.ts +3 -0
  127. package/src/index.ts +15 -0
  128. package/src/integrations/ghtml/ghtml-renderer.test.ts +253 -0
  129. package/src/integrations/ghtml/ghtml-renderer.ts +87 -0
  130. package/src/integrations/ghtml/ghtml.constants.ts +1 -0
  131. package/src/integrations/ghtml/ghtml.plugin.ts +28 -0
  132. package/src/plugins/alias-resolver-cache.test.ts +110 -0
  133. package/src/plugins/alias-resolver-cache.ts +145 -0
  134. package/src/plugins/alias-resolver-plugin.test.ts +41 -0
  135. package/src/plugins/alias-resolver-plugin.ts +75 -0
  136. package/src/plugins/eco-component-meta-plugin.test.ts +421 -0
  137. package/src/plugins/eco-component-meta-plugin.ts +518 -0
  138. package/src/plugins/foreign-jsx-override-plugin.test.ts +65 -0
  139. package/src/plugins/foreign-jsx-override-plugin.ts +76 -0
  140. package/src/plugins/integration-plugin.test.ts +151 -0
  141. package/src/plugins/integration-plugin.ts +344 -0
  142. package/src/plugins/processor.test.ts +148 -0
  143. package/src/plugins/processor.ts +257 -0
  144. package/src/plugins/{runtime-capability.d.ts → runtime-capability.ts} +8 -3
  145. package/src/plugins/source-transform.test.ts +82 -0
  146. package/src/plugins/source-transform.ts +123 -0
  147. package/src/route-renderer/orchestration/component-render-context.ts +338 -0
  148. package/src/route-renderer/orchestration/declared-ownership-graph.ts +62 -0
  149. package/src/route-renderer/orchestration/foreign-subtree-execution.service.ts +431 -0
  150. package/src/route-renderer/orchestration/integration-renderer.test.ts +2251 -0
  151. package/src/route-renderer/orchestration/integration-renderer.ts +1384 -0
  152. package/src/route-renderer/orchestration/ownership-planning.service.ts +97 -0
  153. package/src/route-renderer/orchestration/ownership-validation.service.ts +76 -0
  154. package/src/route-renderer/orchestration/processed-asset-dedupe.ts +29 -0
  155. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.test.ts +435 -0
  156. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.ts +310 -0
  157. package/src/route-renderer/orchestration/render-output.utils.ts +310 -0
  158. package/src/route-renderer/orchestration/route-render-orchestrator.prepare-render-options.test.ts +1365 -0
  159. package/src/route-renderer/orchestration/route-render-orchestrator.test.ts +267 -0
  160. package/src/route-renderer/orchestration/route-render-orchestrator.ts +879 -0
  161. package/src/route-renderer/orchestration/template-serialization.test.ts +110 -0
  162. package/src/route-renderer/orchestration/template-serialization.ts +117 -0
  163. package/src/route-renderer/page-loading/component-dependency-collection.ts +202 -0
  164. package/src/route-renderer/page-loading/declared-asset-collection.ts +153 -0
  165. package/src/route-renderer/page-loading/dependency-resolver.test.ts +761 -0
  166. package/src/route-renderer/page-loading/dependency-resolver.ts +144 -0
  167. package/src/route-renderer/page-loading/ecopages-virtual-imports.ts +75 -0
  168. package/src/route-renderer/page-loading/lazy-entry-collection.ts +167 -0
  169. package/src/route-renderer/page-loading/lazy-trigger-planning.ts +74 -0
  170. package/src/route-renderer/page-loading/module-declaration-aggregation.ts +60 -0
  171. package/src/route-renderer/page-loading/module-declaration-scripts.ts +16 -0
  172. package/src/route-renderer/page-loading/page-dependency-bundling.ts +244 -0
  173. package/src/route-renderer/page-loading/page-module-loader.test.ts +183 -0
  174. package/src/route-renderer/page-loading/page-module-loader.ts +184 -0
  175. package/src/route-renderer/route-renderer.ts +133 -0
  176. package/src/router/client/link-intent.test.browser.ts +51 -0
  177. package/src/router/client/link-intent.ts +92 -0
  178. package/src/router/client/navigation-coordinator.test.ts +237 -0
  179. package/src/router/client/navigation-coordinator.ts +453 -0
  180. package/src/router/server/route-registry.test.ts +176 -0
  181. package/src/router/server/route-registry.ts +382 -0
  182. package/src/services/assets/asset-processing-service/asset-dependency-keys.ts +66 -0
  183. package/src/services/assets/asset-processing-service/asset-processing.service.test.ts +473 -0
  184. package/src/services/assets/asset-processing-service/asset-processing.service.ts +344 -0
  185. package/src/services/assets/asset-processing-service/asset.factory.test.ts +63 -0
  186. package/src/services/assets/asset-processing-service/asset.factory.ts +105 -0
  187. package/src/services/assets/asset-processing-service/assets.types.ts +128 -0
  188. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.test.ts +74 -0
  189. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.ts +98 -0
  190. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.test.ts +67 -0
  191. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.ts +78 -0
  192. package/src/services/assets/asset-processing-service/grouped-content-bundles.ts +104 -0
  193. package/src/services/assets/asset-processing-service/index.ts +6 -0
  194. package/src/services/assets/asset-processing-service/page-package.test.ts +135 -0
  195. package/src/services/assets/asset-processing-service/page-package.ts +103 -0
  196. package/src/services/assets/asset-processing-service/{processor.interface.d.ts → processor.interface.ts} +10 -5
  197. package/src/services/assets/asset-processing-service/processor.registry.ts +18 -0
  198. package/src/services/assets/asset-processing-service/processors/base/base-processor.test.ts +59 -0
  199. package/src/services/assets/asset-processing-service/processors/base/base-processor.ts +83 -0
  200. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.ts +173 -0
  201. package/src/services/assets/asset-processing-service/processors/index.ts +5 -0
  202. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.test.ts +188 -0
  203. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.ts +138 -0
  204. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.test.ts +326 -0
  205. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.ts +116 -0
  206. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.test.ts +270 -0
  207. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.ts +145 -0
  208. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.test.ts +261 -0
  209. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +72 -0
  210. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +83 -0
  211. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.ts +65 -0
  212. package/src/services/assets/browser-bundle.service.test.ts +66 -0
  213. package/src/services/assets/browser-bundle.service.ts +109 -0
  214. package/src/services/cache/cache.types.ts +126 -0
  215. package/src/services/cache/index.ts +18 -0
  216. package/src/services/cache/memory-cache-store.test.ts +225 -0
  217. package/src/services/cache/memory-cache-store.ts +130 -0
  218. package/src/services/cache/page-cache-service.test.ts +175 -0
  219. package/src/services/cache/page-cache-service.ts +202 -0
  220. package/src/services/cache/page-request-cache-coordinator.service.test.ts +79 -0
  221. package/src/services/cache/page-request-cache-coordinator.service.ts +131 -0
  222. package/src/services/html/html-rewriter-provider.service.test.ts +183 -0
  223. package/src/services/html/html-rewriter-provider.service.ts +105 -0
  224. package/src/services/html/html-transformer.service.test.ts +544 -0
  225. package/src/services/html/html-transformer.service.ts +369 -0
  226. package/src/services/invalidation/development-invalidation.service.test.ts +87 -0
  227. package/src/services/invalidation/development-invalidation.service.ts +262 -0
  228. package/src/services/module-loading/app-module-loader.service.ts +9 -0
  229. package/src/services/module-loading/app-server-module-transpiler.service.test.ts +297 -0
  230. package/src/services/module-loading/app-server-module-transpiler.service.ts +168 -0
  231. package/src/services/module-loading/host-module-loader-registry.ts +15 -0
  232. package/src/services/module-loading/{module-loading-types.d.ts → module-loading-types.ts} +1 -0
  233. package/src/services/module-loading/page-module-import.service.test.ts +652 -0
  234. package/src/services/module-loading/page-module-import.service.ts +302 -0
  235. package/src/services/module-loading/server-module-transpiler.service.test.ts +242 -0
  236. package/src/services/module-loading/server-module-transpiler.service.ts +104 -0
  237. package/src/services/module-loading/source-module-support.ts +19 -0
  238. package/src/services/runtime-state/dev-graph.service.ts +217 -0
  239. package/src/services/runtime-state/entrypoint-dependency-graph.service.ts +136 -0
  240. package/src/services/runtime-state/server-invalidation-state.service.ts +68 -0
  241. package/src/services/validation/schema-validation-service.test.ts +223 -0
  242. package/src/services/validation/schema-validation-service.ts +204 -0
  243. package/src/services/validation/{standard-schema.types.d.ts → standard-schema.types.ts} +20 -17
  244. package/src/static-site-generator/static-site-generator.test.ts +408 -0
  245. package/src/static-site-generator/static-site-generator.ts +445 -0
  246. package/src/types/internal-types.ts +243 -0
  247. package/src/types/public-types.ts +1508 -0
  248. package/src/utils/deep-merge.test.ts +114 -0
  249. package/src/utils/deep-merge.ts +47 -0
  250. package/src/utils/hash.ts +5 -0
  251. package/src/utils/html-escaping.ts +9 -0
  252. package/src/utils/invariant.test.ts +22 -0
  253. package/src/utils/invariant.ts +15 -0
  254. package/src/utils/locals-utils.ts +37 -0
  255. package/src/utils/parse-cli-args.test.ts +69 -0
  256. package/src/utils/parse-cli-args.ts +105 -0
  257. package/src/utils/path-utils.module.ts +14 -0
  258. package/src/utils/path-utils.test.ts +15 -0
  259. package/src/utils/resolve-work-dir.ts +45 -0
  260. package/src/utils/runtime.ts +44 -0
  261. package/src/utils/server-utils.module.ts +67 -0
  262. package/src/utils/server-utils.test.ts +38 -0
  263. package/src/watchers/project-watcher.integration.test.ts +337 -0
  264. package/src/watchers/project-watcher.test-helpers.ts +42 -0
  265. package/src/watchers/project-watcher.test.ts +768 -0
  266. package/src/watchers/project-watcher.ts +357 -0
  267. package/src/adapters/abstract/application-adapter.d.ts +0 -194
  268. package/src/adapters/abstract/application-adapter.js +0 -121
  269. package/src/adapters/abstract/router-adapter.d.ts +0 -26
  270. package/src/adapters/abstract/router-adapter.js +0 -5
  271. package/src/adapters/abstract/server-adapter.d.ts +0 -69
  272. package/src/adapters/abstract/server-adapter.js +0 -15
  273. package/src/adapters/bun/client-bridge.d.ts +0 -34
  274. package/src/adapters/bun/client-bridge.js +0 -48
  275. package/src/adapters/bun/create-app.d.ts +0 -60
  276. package/src/adapters/bun/create-app.js +0 -140
  277. package/src/adapters/bun/hmr-manager.d.ts +0 -47
  278. package/src/adapters/bun/hmr-manager.js +0 -58
  279. package/src/adapters/bun/index.d.ts +0 -2
  280. package/src/adapters/bun/index.js +0 -8
  281. package/src/adapters/bun/runtime-host.d.ts +0 -52
  282. package/src/adapters/bun/runtime-host.js +0 -56
  283. package/src/adapters/bun/server-adapter.d.ts +0 -216
  284. package/src/adapters/bun/server-adapter.js +0 -445
  285. package/src/adapters/bun/static-preview-host.d.ts +0 -28
  286. package/src/adapters/bun/static-preview-host.js +0 -45
  287. package/src/adapters/create-app.d.ts +0 -20
  288. package/src/adapters/create-app.js +0 -66
  289. package/src/adapters/index.d.ts +0 -2
  290. package/src/adapters/index.js +0 -8
  291. package/src/adapters/node/create-app.d.ts +0 -24
  292. package/src/adapters/node/create-app.js +0 -92
  293. package/src/adapters/node/http-request-bridge.d.ts +0 -57
  294. package/src/adapters/node/http-request-bridge.js +0 -118
  295. package/src/adapters/node/node-client-bridge.d.ts +0 -26
  296. package/src/adapters/node/node-client-bridge.js +0 -66
  297. package/src/adapters/node/node-hmr-manager.d.ts +0 -52
  298. package/src/adapters/node/node-hmr-manager.js +0 -49
  299. package/src/adapters/node/runtime-host.d.ts +0 -57
  300. package/src/adapters/node/runtime-host.js +0 -92
  301. package/src/adapters/node/server-adapter-dependencies.d.ts +0 -19
  302. package/src/adapters/node/server-adapter-dependencies.js +0 -18
  303. package/src/adapters/node/server-adapter.d.ts +0 -138
  304. package/src/adapters/node/server-adapter.js +0 -315
  305. package/src/adapters/node/static-content-server.d.ts +0 -60
  306. package/src/adapters/node/static-content-server.js +0 -194
  307. package/src/adapters/node/static-preview-host.d.ts +0 -55
  308. package/src/adapters/node/static-preview-host.js +0 -68
  309. package/src/adapters/shared/api-response.d.ts +0 -52
  310. package/src/adapters/shared/api-response.js +0 -96
  311. package/src/adapters/shared/application-adapter.d.ts +0 -18
  312. package/src/adapters/shared/application-adapter.js +0 -90
  313. package/src/adapters/shared/define-api-handler.d.ts +0 -25
  314. package/src/adapters/shared/define-api-handler.js +0 -15
  315. package/src/adapters/shared/explicit-static-render-preparation.d.ts +0 -25
  316. package/src/adapters/shared/explicit-static-render-preparation.js +0 -26
  317. package/src/adapters/shared/explicit-static-route-matcher.d.ts +0 -41
  318. package/src/adapters/shared/explicit-static-route-matcher.js +0 -101
  319. package/src/adapters/shared/file-route-middleware-pipeline.d.ts +0 -62
  320. package/src/adapters/shared/file-route-middleware-pipeline.js +0 -90
  321. package/src/adapters/shared/fs-server-response-factory.d.ts +0 -23
  322. package/src/adapters/shared/fs-server-response-factory.js +0 -81
  323. package/src/adapters/shared/fs-server-response-matcher.d.ts +0 -75
  324. package/src/adapters/shared/fs-server-response-matcher.js +0 -186
  325. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +0 -55
  326. package/src/adapters/shared/hmr-entrypoint-registrar.js +0 -87
  327. package/src/adapters/shared/hmr-html-response.d.ts +0 -22
  328. package/src/adapters/shared/hmr-html-response.js +0 -33
  329. package/src/adapters/shared/render-context.d.ts +0 -16
  330. package/src/adapters/shared/render-context.js +0 -93
  331. package/src/adapters/shared/runtime-app-bootstrap.d.ts +0 -26
  332. package/src/adapters/shared/runtime-app-bootstrap.js +0 -46
  333. package/src/adapters/shared/runtime-host.d.ts +0 -12
  334. package/src/adapters/shared/runtime-host.js +0 -0
  335. package/src/adapters/shared/server-adapter.d.ts +0 -108
  336. package/src/adapters/shared/server-adapter.js +0 -436
  337. package/src/adapters/shared/server-route-handler.d.ts +0 -89
  338. package/src/adapters/shared/server-route-handler.js +0 -111
  339. package/src/adapters/shared/server-static-builder.d.ts +0 -71
  340. package/src/adapters/shared/server-static-builder.js +0 -100
  341. package/src/adapters/shared/shared-hmr-manager.d.ts +0 -59
  342. package/src/adapters/shared/shared-hmr-manager.js +0 -241
  343. package/src/adapters/shared/static-preview-host.d.ts +0 -10
  344. package/src/adapters/shared/static-preview-host.js +0 -0
  345. package/src/build/browser-runtime-import-rewrite-plugin.d.ts +0 -26
  346. package/src/build/browser-runtime-import-rewrite-plugin.js +0 -165
  347. package/src/build/browser-runtime-manifest.d.ts +0 -31
  348. package/src/build/browser-runtime-manifest.js +0 -61
  349. package/src/build/build-adapter.d.ts +0 -247
  350. package/src/build/build-adapter.js +0 -671
  351. package/src/build/build-manifest.d.ts +0 -33
  352. package/src/build/build-manifest.js +0 -52
  353. package/src/build/build-types.d.ts +0 -57
  354. package/src/build/build-types.js +0 -0
  355. package/src/build/dev-build-coordinator.d.ts +0 -72
  356. package/src/build/dev-build-coordinator.js +0 -154
  357. package/src/build/esbuild-build-adapter.d.ts +0 -79
  358. package/src/build/esbuild-build-adapter.js +0 -521
  359. package/src/build/runtime-build-executor.d.ts +0 -14
  360. package/src/build/runtime-build-executor.js +0 -22
  361. package/src/build/runtime-specifier-alias-plugin.d.ts +0 -15
  362. package/src/build/runtime-specifier-alias-plugin.js +0 -31
  363. package/src/config/config-builder.d.ts +0 -252
  364. package/src/config/config-builder.js +0 -598
  365. package/src/config/constants.js +0 -25
  366. package/src/dev/host-runtime.d.ts +0 -10
  367. package/src/dev/host-runtime.js +0 -24
  368. package/src/dev/sc-server.d.ts +0 -30
  369. package/src/dev/sc-server.js +0 -111
  370. package/src/eco/eco.browser.d.ts +0 -2
  371. package/src/eco/eco.browser.js +0 -88
  372. package/src/eco/eco.d.ts +0 -9
  373. package/src/eco/eco.js +0 -119
  374. package/src/eco/eco.types.d.ts +0 -233
  375. package/src/eco/eco.types.js +0 -0
  376. package/src/eco/eco.utils.d.ts +0 -1
  377. package/src/eco/eco.utils.js +0 -10
  378. package/src/eco/global-injector-map.d.ts +0 -16
  379. package/src/eco/global-injector-map.js +0 -80
  380. package/src/eco/lazy-injector-map.d.ts +0 -8
  381. package/src/eco/lazy-injector-map.js +0 -70
  382. package/src/eco/module-dependencies.d.ts +0 -18
  383. package/src/eco/module-dependencies.js +0 -49
  384. package/src/errors/http-error.d.ts +0 -31
  385. package/src/errors/http-error.js +0 -50
  386. package/src/errors/index.d.ts +0 -3
  387. package/src/errors/index.js +0 -6
  388. package/src/errors/locals-access-error.d.ts +0 -4
  389. package/src/errors/locals-access-error.js +0 -9
  390. package/src/global/app-logger.d.ts +0 -2
  391. package/src/global/app-logger.js +0 -6
  392. package/src/hmr/client/hmr-runtime.d.ts +0 -5
  393. package/src/hmr/client/hmr-runtime.js +0 -117
  394. package/src/hmr/hmr-strategy.d.ts +0 -162
  395. package/src/hmr/hmr-strategy.js +0 -44
  396. package/src/hmr/hmr.postcss.test.e2e.d.ts +0 -1
  397. package/src/hmr/hmr.postcss.test.e2e.js +0 -31
  398. package/src/hmr/hmr.test.e2e.d.ts +0 -1
  399. package/src/hmr/hmr.test.e2e.js +0 -43
  400. package/src/hmr/strategies/default-hmr-strategy.d.ts +0 -43
  401. package/src/hmr/strategies/default-hmr-strategy.js +0 -34
  402. package/src/hmr/strategies/js-hmr-strategy.d.ts +0 -134
  403. package/src/hmr/strategies/js-hmr-strategy.js +0 -173
  404. package/src/index.browser.d.ts +0 -3
  405. package/src/index.browser.js +0 -4
  406. package/src/index.d.ts +0 -6
  407. package/src/index.js +0 -21
  408. package/src/integrations/ghtml/ghtml-renderer.d.ts +0 -16
  409. package/src/integrations/ghtml/ghtml-renderer.js +0 -57
  410. package/src/integrations/ghtml/ghtml.constants.d.ts +0 -1
  411. package/src/integrations/ghtml/ghtml.constants.js +0 -4
  412. package/src/integrations/ghtml/ghtml.plugin.d.ts +0 -16
  413. package/src/integrations/ghtml/ghtml.plugin.js +0 -20
  414. package/src/plugins/alias-resolver-plugin.d.ts +0 -3
  415. package/src/plugins/alias-resolver-plugin.js +0 -61
  416. package/src/plugins/eco-component-meta-plugin.d.ts +0 -108
  417. package/src/plugins/eco-component-meta-plugin.js +0 -175
  418. package/src/plugins/foreign-jsx-override-plugin.d.ts +0 -33
  419. package/src/plugins/foreign-jsx-override-plugin.js +0 -41
  420. package/src/plugins/integration-plugin.d.ts +0 -230
  421. package/src/plugins/integration-plugin.js +0 -201
  422. package/src/plugins/processor.d.ts +0 -97
  423. package/src/plugins/processor.js +0 -141
  424. package/src/plugins/runtime-capability.js +0 -0
  425. package/src/plugins/source-transform.d.ts +0 -46
  426. package/src/plugins/source-transform.js +0 -71
  427. package/src/route-renderer/orchestration/component-render-context.d.ts +0 -97
  428. package/src/route-renderer/orchestration/component-render-context.js +0 -147
  429. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +0 -18
  430. package/src/route-renderer/orchestration/declared-ownership-graph.js +0 -34
  431. package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +0 -110
  432. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +0 -233
  433. package/src/route-renderer/orchestration/integration-renderer.d.ts +0 -534
  434. package/src/route-renderer/orchestration/integration-renderer.js +0 -991
  435. package/src/route-renderer/orchestration/ownership-planning.service.d.ts +0 -24
  436. package/src/route-renderer/orchestration/ownership-planning.service.js +0 -63
  437. package/src/route-renderer/orchestration/ownership-validation.service.d.ts +0 -29
  438. package/src/route-renderer/orchestration/ownership-validation.service.js +0 -53
  439. package/src/route-renderer/orchestration/processed-asset-dedupe.d.ts +0 -3
  440. package/src/route-renderer/orchestration/processed-asset-dedupe.js +0 -27
  441. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +0 -91
  442. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +0 -170
  443. package/src/route-renderer/orchestration/render-output.utils.d.ts +0 -66
  444. package/src/route-renderer/orchestration/render-output.utils.js +0 -171
  445. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +0 -156
  446. package/src/route-renderer/orchestration/route-render-orchestrator.js +0 -577
  447. package/src/route-renderer/orchestration/template-serialization.d.ts +0 -38
  448. package/src/route-renderer/orchestration/template-serialization.js +0 -45
  449. package/src/route-renderer/page-loading/component-dependency-collection.d.ts +0 -37
  450. package/src/route-renderer/page-loading/component-dependency-collection.js +0 -132
  451. package/src/route-renderer/page-loading/declared-asset-collection.d.ts +0 -24
  452. package/src/route-renderer/page-loading/declared-asset-collection.js +0 -106
  453. package/src/route-renderer/page-loading/dependency-resolver.d.ts +0 -35
  454. package/src/route-renderer/page-loading/dependency-resolver.js +0 -115
  455. package/src/route-renderer/page-loading/ecopages-virtual-imports.d.ts +0 -11
  456. package/src/route-renderer/page-loading/ecopages-virtual-imports.js +0 -57
  457. package/src/route-renderer/page-loading/lazy-entry-collection.d.ts +0 -45
  458. package/src/route-renderer/page-loading/lazy-entry-collection.js +0 -105
  459. package/src/route-renderer/page-loading/lazy-trigger-planning.d.ts +0 -19
  460. package/src/route-renderer/page-loading/lazy-trigger-planning.js +0 -40
  461. package/src/route-renderer/page-loading/module-declaration-aggregation.d.ts +0 -5
  462. package/src/route-renderer/page-loading/module-declaration-aggregation.js +0 -33
  463. package/src/route-renderer/page-loading/module-declaration-scripts.d.ts +0 -3
  464. package/src/route-renderer/page-loading/module-declaration-scripts.js +0 -18
  465. package/src/route-renderer/page-loading/page-dependency-bundling.d.ts +0 -13
  466. package/src/route-renderer/page-loading/page-dependency-bundling.js +0 -137
  467. package/src/route-renderer/page-loading/page-module-loader.d.ts +0 -90
  468. package/src/route-renderer/page-loading/page-module-loader.js +0 -127
  469. package/src/route-renderer/route-renderer.d.ts +0 -69
  470. package/src/route-renderer/route-renderer.js +0 -80
  471. package/src/router/client/link-intent.js +0 -34
  472. package/src/router/client/link-intent.test.browser.d.ts +0 -1
  473. package/src/router/client/link-intent.test.browser.js +0 -43
  474. package/src/router/client/navigation-coordinator.d.ts +0 -169
  475. package/src/router/client/navigation-coordinator.js +0 -215
  476. package/src/router/server/route-registry.d.ts +0 -78
  477. package/src/router/server/route-registry.js +0 -262
  478. package/src/services/assets/asset-processing-service/asset-dependency-keys.d.ts +0 -3
  479. package/src/services/assets/asset-processing-service/asset-dependency-keys.js +0 -56
  480. package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +0 -103
  481. package/src/services/assets/asset-processing-service/asset-processing.service.js +0 -285
  482. package/src/services/assets/asset-processing-service/asset.factory.d.ts +0 -17
  483. package/src/services/assets/asset-processing-service/asset.factory.js +0 -82
  484. package/src/services/assets/asset-processing-service/assets.types.d.ts +0 -103
  485. package/src/services/assets/asset-processing-service/assets.types.js +0 -0
  486. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +0 -57
  487. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +0 -49
  488. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +0 -20
  489. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +0 -41
  490. package/src/services/assets/asset-processing-service/grouped-content-bundles.d.ts +0 -30
  491. package/src/services/assets/asset-processing-service/grouped-content-bundles.js +0 -65
  492. package/src/services/assets/asset-processing-service/index.d.ts +0 -6
  493. package/src/services/assets/asset-processing-service/index.js +0 -6
  494. package/src/services/assets/asset-processing-service/page-package.d.ts +0 -6
  495. package/src/services/assets/asset-processing-service/page-package.js +0 -80
  496. package/src/services/assets/asset-processing-service/processor.interface.js +0 -6
  497. package/src/services/assets/asset-processing-service/processor.registry.d.ts +0 -8
  498. package/src/services/assets/asset-processing-service/processor.registry.js +0 -15
  499. package/src/services/assets/asset-processing-service/processors/base/base-processor.d.ts +0 -24
  500. package/src/services/assets/asset-processing-service/processors/base/base-processor.js +0 -65
  501. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +0 -22
  502. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +0 -136
  503. package/src/services/assets/asset-processing-service/processors/index.d.ts +0 -5
  504. package/src/services/assets/asset-processing-service/processors/index.js +0 -5
  505. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +0 -6
  506. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +0 -120
  507. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -9
  508. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +0 -97
  509. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.d.ts +0 -42
  510. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +0 -126
  511. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -8
  512. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +0 -59
  513. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -9
  514. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +0 -69
  515. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.d.ts +0 -18
  516. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.js +0 -45
  517. package/src/services/assets/browser-bundle.service.d.ts +0 -73
  518. package/src/services/assets/browser-bundle.service.js +0 -41
  519. package/src/services/cache/cache.types.d.ts +0 -107
  520. package/src/services/cache/cache.types.js +0 -0
  521. package/src/services/cache/index.d.ts +0 -7
  522. package/src/services/cache/index.js +0 -7
  523. package/src/services/cache/memory-cache-store.d.ts +0 -42
  524. package/src/services/cache/memory-cache-store.js +0 -98
  525. package/src/services/cache/page-cache-service.d.ts +0 -70
  526. package/src/services/cache/page-cache-service.js +0 -152
  527. package/src/services/cache/page-request-cache-coordinator.service.d.ts +0 -75
  528. package/src/services/cache/page-request-cache-coordinator.service.js +0 -109
  529. package/src/services/html/html-rewriter-provider.service.d.ts +0 -40
  530. package/src/services/html/html-rewriter-provider.service.js +0 -68
  531. package/src/services/html/html-transformer.service.d.ts +0 -96
  532. package/src/services/html/html-transformer.service.js +0 -287
  533. package/src/services/invalidation/development-invalidation.service.d.ts +0 -74
  534. package/src/services/invalidation/development-invalidation.service.js +0 -190
  535. package/src/services/module-loading/app-module-loader.service.d.ts +0 -7
  536. package/src/services/module-loading/app-module-loader.service.js +0 -0
  537. package/src/services/module-loading/app-server-module-transpiler.service.d.ts +0 -24
  538. package/src/services/module-loading/app-server-module-transpiler.service.js +0 -151
  539. package/src/services/module-loading/host-module-loader-registry.d.ts +0 -4
  540. package/src/services/module-loading/host-module-loader-registry.js +0 -15
  541. package/src/services/module-loading/module-loading-types.js +0 -0
  542. package/src/services/module-loading/node-bootstrap-plugin.d.ts +0 -38
  543. package/src/services/module-loading/node-bootstrap-plugin.js +0 -215
  544. package/src/services/module-loading/page-module-import.service.d.ts +0 -95
  545. package/src/services/module-loading/page-module-import.service.js +0 -191
  546. package/src/services/module-loading/server-module-transpiler.service.d.ts +0 -63
  547. package/src/services/module-loading/server-module-transpiler.service.js +0 -64
  548. package/src/services/module-loading/source-module-support.d.ts +0 -5
  549. package/src/services/module-loading/source-module-support.js +0 -8
  550. package/src/services/runtime-state/dev-graph.service.d.ts +0 -118
  551. package/src/services/runtime-state/dev-graph.service.js +0 -162
  552. package/src/services/runtime-state/entrypoint-dependency-graph.service.d.ts +0 -41
  553. package/src/services/runtime-state/entrypoint-dependency-graph.service.js +0 -85
  554. package/src/services/runtime-state/server-invalidation-state.service.d.ts +0 -26
  555. package/src/services/runtime-state/server-invalidation-state.service.js +0 -35
  556. package/src/services/validation/schema-validation-service.d.ts +0 -122
  557. package/src/services/validation/schema-validation-service.js +0 -101
  558. package/src/services/validation/standard-schema.types.js +0 -0
  559. package/src/static-site-generator/static-site-generator.d.ts +0 -104
  560. package/src/static-site-generator/static-site-generator.js +0 -316
  561. package/src/types/internal-types.d.ts +0 -232
  562. package/src/types/internal-types.js +0 -0
  563. package/src/types/public-types.d.ts +0 -1307
  564. package/src/types/public-types.js +0 -0
  565. package/src/utils/deep-merge.d.ts +0 -14
  566. package/src/utils/deep-merge.js +0 -32
  567. package/src/utils/hash.d.ts +0 -1
  568. package/src/utils/hash.js +0 -7
  569. package/src/utils/html-escaping.d.ts +0 -7
  570. package/src/utils/html-escaping.js +0 -6
  571. package/src/utils/html.js +0 -4
  572. package/src/utils/invariant.d.ts +0 -5
  573. package/src/utils/invariant.js +0 -11
  574. package/src/utils/locals-utils.d.ts +0 -15
  575. package/src/utils/locals-utils.js +0 -24
  576. package/src/utils/parse-cli-args.d.ts +0 -27
  577. package/src/utils/parse-cli-args.js +0 -62
  578. package/src/utils/path-utils.module.d.ts +0 -5
  579. package/src/utils/path-utils.module.js +0 -14
  580. package/src/utils/resolve-work-dir.d.ts +0 -11
  581. package/src/utils/resolve-work-dir.js +0 -31
  582. package/src/utils/runtime.d.ts +0 -11
  583. package/src/utils/runtime.js +0 -40
  584. package/src/utils/server-utils.module.d.ts +0 -19
  585. package/src/utils/server-utils.module.js +0 -56
  586. package/src/watchers/project-watcher.d.ts +0 -136
  587. package/src/watchers/project-watcher.js +0 -275
  588. package/src/watchers/project-watcher.test-helpers.d.ts +0 -4
  589. package/src/watchers/project-watcher.test-helpers.js +0 -52
  590. /package/src/utils/{html.d.ts → html.ts} +0 -0
@@ -0,0 +1,219 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { addTriggerAttribute, isThenable, wrapWithScriptsInjector } from './eco.utils.ts';
3
+
4
+ const TRIGGER_ID = 'eco-trigger-abc123';
5
+
6
+ describe('addTriggerAttribute', () => {
7
+ describe('basic element injection', () => {
8
+ test('injects into a plain div', () => {
9
+ const result = addTriggerAttribute('<div>content</div>', TRIGGER_ID);
10
+ expect(result).toBe(`<div data-eco-trigger="${TRIGGER_ID}">content</div>`);
11
+ });
12
+
13
+ test('injects into a custom element', () => {
14
+ const result = addTriggerAttribute('<my-counter value="0"></my-counter>', TRIGGER_ID);
15
+ expect(result).toBe(`<my-counter data-eco-trigger="${TRIGGER_ID}" value="0"></my-counter>`);
16
+ });
17
+
18
+ test('injects into an element that already has attributes', () => {
19
+ const result = addTriggerAttribute('<div class="foo" id="bar">content</div>', TRIGGER_ID);
20
+ expect(result).toBe(`<div data-eco-trigger="${TRIGGER_ID}" class="foo" id="bar">content</div>`);
21
+ });
22
+
23
+ test('injects into a self-closing void element', () => {
24
+ const result = addTriggerAttribute('<img src="x.png" alt="" />', TRIGGER_ID);
25
+ expect(result).toBe(`<img data-eco-trigger="${TRIGGER_ID}" src="x.png" alt="" />`);
26
+ });
27
+
28
+ test('injects into an element with no attributes and immediate close', () => {
29
+ const result = addTriggerAttribute('<section></section>', TRIGGER_ID);
30
+ expect(result).toBe(`<section data-eco-trigger="${TRIGGER_ID}"></section>`);
31
+ });
32
+ });
33
+
34
+ describe('leading non-element nodes are skipped', () => {
35
+ test('skips leading whitespace and injects into the first element', () => {
36
+ const result = addTriggerAttribute(' \n <div>content</div>', TRIGGER_ID);
37
+ expect(result).toBe(` \n <div data-eco-trigger="${TRIGGER_ID}">content</div>`);
38
+ });
39
+
40
+ test('skips a leading HTML comment', () => {
41
+ const result = addTriggerAttribute('<!-- wrapper --><div>content</div>', TRIGGER_ID);
42
+ expect(result).toBe(`<!-- wrapper --><div data-eco-trigger="${TRIGGER_ID}">content</div>`);
43
+ });
44
+
45
+ test('skips multiple leading HTML comments', () => {
46
+ const result = addTriggerAttribute('<!-- a --><!-- b --><span>text</span>', TRIGGER_ID);
47
+ expect(result).toBe(`<!-- a --><!-- b --><span data-eco-trigger="${TRIGGER_ID}">text</span>`);
48
+ });
49
+
50
+ test('skips a leading doctype declaration', () => {
51
+ const result = addTriggerAttribute('<!DOCTYPE html><html lang="en"></html>', TRIGGER_ID);
52
+ expect(result).toBe(`<!DOCTYPE html><html data-eco-trigger="${TRIGGER_ID}" lang="en"></html>`);
53
+ });
54
+
55
+ test('skips a leading XML processing instruction', () => {
56
+ const result = addTriggerAttribute('<?xml version="1.0"?><root/>', TRIGGER_ID);
57
+ expect(result).toBe(`<?xml version="1.0"?><root data-eco-trigger="${TRIGGER_ID}"/>`);
58
+ });
59
+
60
+ test('skips comment then whitespace then element', () => {
61
+ const result = addTriggerAttribute('<!-- note -->\n<article>body</article>', TRIGGER_ID);
62
+ expect(result).toBe(`<!-- note -->\n<article data-eco-trigger="${TRIGGER_ID}">body</article>`);
63
+ });
64
+ });
65
+
66
+ describe('only the first element is modified', () => {
67
+ test('does not inject into sibling elements', () => {
68
+ const result = addTriggerAttribute('<div>first</div><div>second</div>', TRIGGER_ID);
69
+ expect(result).toBe(`<div data-eco-trigger="${TRIGGER_ID}">first</div><div>second</div>`);
70
+ });
71
+ });
72
+
73
+ describe('fallback when no element is found', () => {
74
+ test('preserves JSX template metadata while injecting into the first string', () => {
75
+ const strings = ['<theme-toggle class=', '></theme-toggle>'];
76
+ Object.defineProperty(strings, 'raw', {
77
+ value: ['<theme-toggle class=', '></theme-toggle>'],
78
+ });
79
+
80
+ const template = {
81
+ _$rType$: 1,
82
+ rootLocalName: 'theme-toggle',
83
+ strings,
84
+ values: ['radiant-switch'],
85
+ };
86
+
87
+ const result = addTriggerAttribute(template, TRIGGER_ID) as unknown as {
88
+ _$rType$: number;
89
+ rootLocalName: string;
90
+ strings: string[];
91
+ values: unknown[];
92
+ };
93
+
94
+ expect(result._$rType$).toBe(1);
95
+ expect(result.rootLocalName).toBe('theme-toggle');
96
+ expect(result.values).toEqual(['radiant-switch']);
97
+ expect(result.strings).toEqual([
98
+ `<theme-toggle data-eco-trigger="${TRIGGER_ID}" class=`,
99
+ '></theme-toggle>',
100
+ ]);
101
+ expect(Object.getOwnPropertyDescriptor(result.strings, 'raw')?.value).toEqual([
102
+ `<theme-toggle data-eco-trigger="${TRIGGER_ID}" class=`,
103
+ '></theme-toggle>',
104
+ ]);
105
+ });
106
+
107
+ test('preserves SSR markup node output while injecting into outerHTML', () => {
108
+ const markupNode = {
109
+ nodeType: 1,
110
+ get outerHTML() {
111
+ return '<theme-toggle class="radiant-switch"></theme-toggle>';
112
+ },
113
+ };
114
+
115
+ const result = addTriggerAttribute(markupNode, TRIGGER_ID) as typeof markupNode;
116
+
117
+ expect(result.nodeType).toBe(1);
118
+ expect(result.outerHTML).toBe(
119
+ `<theme-toggle data-eco-trigger="${TRIGGER_ID}" class="radiant-switch"></theme-toggle>`,
120
+ );
121
+ });
122
+
123
+ test('returns the original string unchanged when there is no opening tag', () => {
124
+ const input = 'just some text';
125
+ expect(addTriggerAttribute(input, TRIGGER_ID)).toBe(input);
126
+ });
127
+
128
+ test('returns the original string unchanged when input is empty', () => {
129
+ expect(addTriggerAttribute('', TRIGGER_ID)).toBe('');
130
+ });
131
+ });
132
+
133
+ describe('non-string input coercion', () => {
134
+ test('coerces a number to string before injecting', () => {
135
+ const result = addTriggerAttribute(42, TRIGGER_ID);
136
+ expect(result).toBe('42');
137
+ });
138
+
139
+ test('coerces null to the string "null"', () => {
140
+ expect(addTriggerAttribute(null, TRIGGER_ID)).toBe('null');
141
+ });
142
+ });
143
+ });
144
+
145
+ describe('isThenable', () => {
146
+ test('returns true for a native Promise', () => {
147
+ expect(isThenable(Promise.resolve())).toBe(true);
148
+ });
149
+
150
+ test('returns true for a plain object with a then function', () => {
151
+ expect(isThenable({ then: () => {} })).toBe(true);
152
+ });
153
+
154
+ test('returns false for a plain string', () => {
155
+ expect(isThenable('hello')).toBe(false);
156
+ });
157
+
158
+ test('returns false for a number', () => {
159
+ expect(isThenable(42)).toBe(false);
160
+ });
161
+
162
+ test('returns false for null', () => {
163
+ expect(isThenable(null)).toBe(false);
164
+ });
165
+
166
+ test('returns false for an object without then', () => {
167
+ expect(isThenable({ value: 1 })).toBe(false);
168
+ });
169
+
170
+ test('returns false when then is not a function', () => {
171
+ expect(isThenable({ then: 'not-a-function' })).toBe(false);
172
+ });
173
+ });
174
+
175
+ describe('wrapWithScriptsInjector', () => {
176
+ const lazyGroups = [{ lazy: { 'on:idle': true }, scripts: '/_assets/script.js' }] as const;
177
+
178
+ test('preserves JSX template metadata while wrapping content', () => {
179
+ const strings = ['<theme-toggle class=', '></theme-toggle>'];
180
+ Object.defineProperty(strings, 'raw', {
181
+ value: ['<theme-toggle class=', '></theme-toggle>'],
182
+ });
183
+
184
+ const template = {
185
+ _$rType$: 1,
186
+ rootLocalName: 'theme-toggle',
187
+ strings,
188
+ values: ['radiant-switch'],
189
+ };
190
+
191
+ const result = wrapWithScriptsInjector(template, lazyGroups) as unknown as typeof template;
192
+
193
+ expect(result._$rType$).toBe(1);
194
+ expect(result.rootLocalName).toBe('theme-toggle');
195
+ expect(result.values).toEqual(['radiant-switch']);
196
+ expect(result.strings[0]).toContain('<scripts-injector><script type="ecopages/injector-map">');
197
+ expect(result.strings[0]).toContain('<theme-toggle class=');
198
+ expect(result.strings[1]).toBe('></theme-toggle></scripts-injector>');
199
+ expect(Object.getOwnPropertyDescriptor(result.strings, 'raw')?.value[1]).toBe(
200
+ '></theme-toggle></scripts-injector>',
201
+ );
202
+ });
203
+
204
+ test('preserves markup-node-like output while wrapping content', () => {
205
+ const markupNode = {
206
+ nodeType: 1,
207
+ get outerHTML() {
208
+ return '<theme-toggle class="radiant-switch"></theme-toggle>';
209
+ },
210
+ };
211
+
212
+ const result = wrapWithScriptsInjector(markupNode, lazyGroups) as typeof markupNode;
213
+
214
+ expect(result.nodeType).toBe(1);
215
+ expect(result.outerHTML).toContain('<scripts-injector><script type="ecopages/injector-map">');
216
+ expect(result.outerHTML).toContain('<theme-toggle class="radiant-switch"></theme-toggle>');
217
+ expect(result.outerHTML).toContain('</scripts-injector>');
218
+ });
219
+ });
@@ -0,0 +1,5 @@
1
+ export {
2
+ addTriggerAttribute,
3
+ isThenable,
4
+ wrapWithScriptsInjector,
5
+ } from '../route-renderer/orchestration/render-output.utils.ts';
@@ -0,0 +1,42 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { buildGlobalInjectorBootstrapContent, buildGlobalInjectorMapScript } from './global-injector-map.ts';
3
+ import type { ResolvedLazyTrigger } from '../types/public-types.ts';
4
+
5
+ describe('buildGlobalInjectorMapScript', () => {
6
+ test('builds merged map by trigger id and escapes script closing tags', () => {
7
+ const triggers: ResolvedLazyTrigger[] = [
8
+ {
9
+ triggerId: 'eco-trigger-one',
10
+ rules: [
11
+ { 'on:interaction': { value: 'click', scripts: ['/a.js', '/b</script>.js'] } },
12
+ { 'on:idle': { scripts: ['/idle.js'] } },
13
+ ],
14
+ },
15
+ {
16
+ triggerId: 'eco-trigger-one',
17
+ rules: [{ 'on:interaction': { value: 'click', scripts: ['/a.js', '/c.js'] } }],
18
+ },
19
+ ];
20
+
21
+ const payload = buildGlobalInjectorMapScript(triggers);
22
+ expect(payload).toContain('<\\/script>');
23
+
24
+ const map = JSON.parse(payload) as Record<string, Record<string, { scripts: string[]; value?: string }>>;
25
+ expect(map['eco-trigger-one']?.['on:idle']?.scripts).toEqual(['/idle.js']);
26
+ expect(map['eco-trigger-one']?.['on:interaction']).toEqual({
27
+ value: 'click',
28
+ scripts: ['/a.js', '/b</script>.js', '/c.js'],
29
+ });
30
+ });
31
+ });
32
+
33
+ describe('buildGlobalInjectorBootstrapContent', () => {
34
+ test('binds refresh to after-swap and avoids before-swap cleanup listener', () => {
35
+ const bootstrap = buildGlobalInjectorBootstrapContent('/assets/injector-global.js');
36
+
37
+ expect(bootstrap).toContain("document.addEventListener('eco:after-swap', handleAfterSwap);");
38
+ expect(bootstrap).not.toContain("document.addEventListener('eco:before-swap'");
39
+ expect(bootstrap).not.toContain('const handleBeforeSwap');
40
+ expect(bootstrap).toContain("document.removeEventListener('eco:after-swap', handleAfterSwap);");
41
+ });
42
+ });
@@ -0,0 +1,112 @@
1
+ import type { ResolvedLazyTrigger } from '../types/public-types.ts';
2
+
3
+ type GlobalInjectorEntry = {
4
+ 'on:idle'?: { scripts: string[] };
5
+ 'on:interaction'?: { value: string; scripts: string[] };
6
+ 'on:visible'?: { value?: string; scripts: string[] };
7
+ };
8
+
9
+ type GlobalInjectorMap = Record<string, GlobalInjectorEntry>;
10
+
11
+ /**
12
+ * Converts a flat list of resolved triggers into the map structure consumed
13
+ * by the `initGlobalInjector` bootstrap. Multiple triggers sharing the same
14
+ * `triggerId` are merged so their script lists are deduplicated.
15
+ */
16
+ function buildGlobalInjectorMap(triggers: ResolvedLazyTrigger[]): GlobalInjectorMap {
17
+ const map: GlobalInjectorMap = {};
18
+
19
+ for (const { triggerId, rules } of triggers) {
20
+ const entry: GlobalInjectorEntry = map[triggerId] ?? {};
21
+
22
+ for (const rule of rules) {
23
+ if ('on:idle' in rule) {
24
+ const { scripts } = rule['on:idle'];
25
+ entry['on:idle'] = {
26
+ scripts: Array.from(new Set([...(entry['on:idle']?.scripts ?? []), ...scripts])),
27
+ };
28
+ continue;
29
+ }
30
+
31
+ if ('on:interaction' in rule) {
32
+ const { value, scripts } = rule['on:interaction'];
33
+ entry['on:interaction'] = {
34
+ value,
35
+ scripts: Array.from(new Set([...(entry['on:interaction']?.scripts ?? []), ...scripts])),
36
+ };
37
+ continue;
38
+ }
39
+
40
+ if ('on:visible' in rule) {
41
+ const { value, scripts } = rule['on:visible'];
42
+ entry['on:visible'] = {
43
+ ...(value ? { value } : {}),
44
+ scripts: Array.from(new Set([...(entry['on:visible']?.scripts ?? []), ...scripts])),
45
+ };
46
+ continue;
47
+ }
48
+ }
49
+
50
+ if (Object.keys(entry).length > 0) {
51
+ map[triggerId] = entry;
52
+ }
53
+ }
54
+
55
+ return map;
56
+ }
57
+
58
+ /**
59
+ * Serializes resolved lazy triggers into a JSON string safe for embedding
60
+ * inside an inline `<script type="ecopages/global-injector-map">` tag.
61
+ *
62
+ * The `</script` sequence is escaped because an unescaped occurrence in inline
63
+ * script content causes the HTML parser to close the script tag prematurely,
64
+ * breaking page rendering. `JSON.stringify` does not perform this escape by
65
+ * default, so a targeted replacement is applied after serialization.
66
+ */
67
+ export function buildGlobalInjectorMapScript(triggers: ResolvedLazyTrigger[]): string {
68
+ const map = buildGlobalInjectorMap(triggers);
69
+ return JSON.stringify(map).replace(/<\/script/gi, '<\\/script');
70
+ }
71
+
72
+ /**
73
+ * Builds the module source that boots the global lazy injector on the client.
74
+ * Emitted once per page alongside the `ecopages/global-injector-map` script block.
75
+ */
76
+ export function buildGlobalInjectorBootstrapContent(globalInjectorModuleSpecifier: string): string {
77
+ return `import { initGlobalInjector } from ${JSON.stringify(globalInjectorModuleSpecifier)};
78
+
79
+ function pruneStaleTriggerMaps() {
80
+ const mapScripts = Array.from(document.querySelectorAll('script[type="ecopages/global-injector-map"]'));
81
+ if (mapScripts.length <= 1) {
82
+ return;
83
+ }
84
+
85
+ const latestMapScript = mapScripts[mapScripts.length - 1];
86
+ for (const mapScript of mapScripts) {
87
+ if (mapScript !== latestMapScript) {
88
+ mapScript.remove();
89
+ }
90
+ }
91
+ }
92
+
93
+ const globalScope = window;
94
+ if (typeof globalScope.__ecoGlobalInjectorCleanup === 'function') {
95
+ globalScope.__ecoGlobalInjectorCleanup();
96
+ }
97
+
98
+ const injector = initGlobalInjector();
99
+
100
+ const handleAfterSwap = () => {
101
+ pruneStaleTriggerMaps();
102
+ injector.refresh();
103
+ };
104
+
105
+ document.addEventListener('eco:after-swap', handleAfterSwap);
106
+ pruneStaleTriggerMaps();
107
+
108
+ globalScope.__ecoGlobalInjectorCleanup = () => {
109
+ document.removeEventListener('eco:after-swap', handleAfterSwap);
110
+ injector.cleanup();
111
+ };`;
112
+ }
@@ -0,0 +1,66 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { buildInjectorMapScript } from './lazy-injector-map.ts';
3
+ import type { InjectorMapConfig } from '@ecopages/scripts-injector/types';
4
+ import type { ResolvedLazyScriptGroup } from '../types/public-types.ts';
5
+
6
+ describe('buildInjectorMapScript', () => {
7
+ test('builds injector map for mixed lazy triggers', () => {
8
+ const lazyGroups: ResolvedLazyScriptGroup[] = [
9
+ { lazy: { 'on:idle': true }, scripts: './idle-a.js, /idle-b.js' },
10
+ { lazy: { 'on:interaction': 'click' }, scripts: './int-a.js' },
11
+ { lazy: { 'on:visible': '0.5' }, scripts: '/vis-a.js' },
12
+ ];
13
+
14
+ const result = buildInjectorMapScript(lazyGroups);
15
+ const map = JSON.parse(result) as InjectorMapConfig;
16
+
17
+ expect(map['on:idle']).toEqual({ scripts: ['/idle-a.js', '/idle-b.js'] });
18
+ expect(map['on:interaction']).toEqual({
19
+ value: 'click',
20
+ scripts: ['/int-a.js'],
21
+ });
22
+ expect(map['on:visible']).toEqual({
23
+ value: '0.5',
24
+ scripts: ['/vis-a.js'],
25
+ });
26
+ });
27
+
28
+ test('dedupes scripts and merges interaction events while preserving order', () => {
29
+ const lazyGroups: ResolvedLazyScriptGroup[] = [
30
+ { lazy: { 'on:interaction': 'click,mouseenter' }, scripts: './one.js,./two.js' },
31
+ { lazy: { 'on:interaction': 'mouseenter,focusin' }, scripts: '/two.js,/three.js' },
32
+ ];
33
+
34
+ const result = buildInjectorMapScript(lazyGroups);
35
+ const map = JSON.parse(result) as InjectorMapConfig;
36
+
37
+ expect(map['on:interaction']).toEqual({
38
+ value: 'click,mouseenter,focusin',
39
+ scripts: ['/one.js', '/two.js', '/three.js'],
40
+ });
41
+ });
42
+
43
+ test('keeps existing on:visible threshold when a later boolean trigger is encountered', () => {
44
+ const lazyGroups: ResolvedLazyScriptGroup[] = [
45
+ { lazy: { 'on:visible': '100px' }, scripts: './threshold.js' },
46
+ { lazy: { 'on:visible': true }, scripts: './fallback.js' },
47
+ ];
48
+
49
+ const result = buildInjectorMapScript(lazyGroups);
50
+ const map = JSON.parse(result) as InjectorMapConfig;
51
+
52
+ expect(map['on:visible']).toEqual({
53
+ value: '100px',
54
+ scripts: ['/threshold.js', '/fallback.js'],
55
+ });
56
+ });
57
+
58
+ test('escapes closing script tags in output payload', () => {
59
+ const lazyGroups: ResolvedLazyScriptGroup[] = [
60
+ { lazy: { 'on:idle': true }, scripts: '/safe.js, /x</script>y.js' },
61
+ ];
62
+
63
+ const result = buildInjectorMapScript(lazyGroups);
64
+ expect(result).toContain('<\\/script>');
65
+ });
66
+ });
@@ -0,0 +1,120 @@
1
+ import type { InjectorMapConfig } from '@ecopages/scripts-injector/types';
2
+ import type { ResolvedLazyScriptGroup } from '../types/public-types.ts';
3
+
4
+ /**
5
+ * Normalizes a comma-separated scripts string into absolute script URLs.
6
+ *
7
+ * @param scripts Comma-separated script paths.
8
+ * @returns Normalized script path list.
9
+ */
10
+ function normalizeScripts(scripts: string): string[] {
11
+ return scripts
12
+ .split(',')
13
+ .map((scriptPath) => scriptPath.trim())
14
+ .filter(Boolean)
15
+ .map((scriptPath) => {
16
+ if (scriptPath.startsWith('/')) {
17
+ return scriptPath;
18
+ }
19
+
20
+ const normalizedRelativePath = scriptPath.replace(/^\/+/, '').replace(/^(\.\/)+/, '');
21
+ return `/${normalizedRelativePath}`;
22
+ });
23
+ }
24
+
25
+ /**
26
+ * Deduplicates comma-separated values while preserving first-seen order.
27
+ *
28
+ * @param values CSV value list.
29
+ * @returns A single normalized CSV string.
30
+ */
31
+ function dedupeCsvValues(values: string[]): string {
32
+ const seen = new Set<string>();
33
+
34
+ for (const value of values) {
35
+ for (const token of value
36
+ .split(',')
37
+ .map((part) => part.trim())
38
+ .filter(Boolean)) {
39
+ seen.add(token);
40
+ }
41
+ }
42
+
43
+ return Array.from(seen).join(',');
44
+ }
45
+
46
+ /**
47
+ * Builds a scripts-injector map config from resolved lazy script groups.
48
+ *
49
+ * @param lazyGroups Lazy script groups resolved during dependency processing.
50
+ * @returns Injector map config keyed by lazy trigger.
51
+ */
52
+ function buildInjectorMap(lazyGroups: readonly ResolvedLazyScriptGroup[]): InjectorMapConfig {
53
+ const map: InjectorMapConfig = {};
54
+
55
+ for (const group of lazyGroups) {
56
+ const scripts = normalizeScripts(group.scripts);
57
+ const lazy = group.lazy;
58
+
59
+ if ('on:idle' in lazy) {
60
+ map['on:idle'] = {
61
+ scripts: [...(map['on:idle']?.scripts ?? []), ...scripts],
62
+ };
63
+ continue;
64
+ }
65
+
66
+ if ('on:interaction' in lazy) {
67
+ const currentValue = map['on:interaction']?.value;
68
+ const nextValue = lazy['on:interaction'];
69
+
70
+ map['on:interaction'] = {
71
+ value: typeof currentValue === 'string' ? dedupeCsvValues([currentValue, nextValue]) : nextValue,
72
+ scripts: [...(map['on:interaction']?.scripts ?? []), ...scripts],
73
+ };
74
+ continue;
75
+ }
76
+
77
+ if ('on:visible' in lazy) {
78
+ const currentValue = map['on:visible']?.value;
79
+ const currentThreshold = typeof currentValue === 'string' ? currentValue : undefined;
80
+ const nextValue = lazy['on:visible'];
81
+
82
+ map['on:visible'] = {
83
+ ...(nextValue === true
84
+ ? currentThreshold
85
+ ? { value: currentThreshold }
86
+ : {}
87
+ : { value: String(nextValue) }),
88
+ scripts: [...(map['on:visible']?.scripts ?? []), ...scripts],
89
+ };
90
+ continue;
91
+ }
92
+
93
+ throw new Error(
94
+ `Invalid lazy options: must specify on:idle, on:interaction, or on:visible. Received: ${JSON.stringify(lazy)}`,
95
+ );
96
+ }
97
+
98
+ for (const key of Object.keys(map)) {
99
+ const scripts = map[key]?.scripts;
100
+ if (scripts) {
101
+ map[key] = {
102
+ ...map[key],
103
+ scripts: Array.from(new Set(scripts)),
104
+ };
105
+ }
106
+ }
107
+
108
+ return map;
109
+ }
110
+
111
+ /**
112
+ * Creates a safe JSON payload string for `<script type="ecopages/injector-map">`.
113
+ *
114
+ * @param lazyGroups Lazy script groups resolved during dependency processing.
115
+ * @returns Escaped JSON string safe for inline script embedding.
116
+ */
117
+ export function buildInjectorMapScript(lazyGroups: readonly ResolvedLazyScriptGroup[]): string {
118
+ const map = buildInjectorMap(lazyGroups);
119
+ return JSON.stringify(map).replace(/<\/script/gi, '<\\/script');
120
+ }
@@ -0,0 +1,30 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { normalizeModuleDeclarations, parseModuleDeclaration } from './module-dependencies.ts';
3
+
4
+ describe('module dependencies parser', () => {
5
+ test('parses simple module declaration', () => {
6
+ expect(parseModuleDeclaration('react-aria-components')).toEqual({
7
+ from: 'react-aria-components',
8
+ });
9
+ });
10
+
11
+ test('parses declaration with named imports', () => {
12
+ expect(parseModuleDeclaration('react-aria-components{Table,Select}')).toEqual({
13
+ from: 'react-aria-components',
14
+ imports: ['Table', 'Select'],
15
+ });
16
+ });
17
+
18
+ test('normalizes and deduplicates module declarations', () => {
19
+ expect(
20
+ normalizeModuleDeclarations([
21
+ 'react-aria-components{Table,Select}',
22
+ 'react-aria-components{Table,Select}',
23
+ 'lodash-es{debounce}',
24
+ ]),
25
+ ).toEqual([
26
+ { from: 'react-aria-components', imports: ['Table', 'Select'] },
27
+ { from: 'lodash-es', imports: ['debounce'] },
28
+ ]);
29
+ });
30
+ });
@@ -0,0 +1,75 @@
1
+ export type ModuleDependencyDeclaration = {
2
+ from: string;
3
+ imports?: string[];
4
+ };
5
+
6
+ function normalizeImports(imports: string[] | undefined): string[] | undefined {
7
+ if (!imports || imports.length === 0) {
8
+ return undefined;
9
+ }
10
+
11
+ const normalized = Array.from(new Set(imports.map((entry) => entry.trim()).filter((entry) => entry.length > 0)));
12
+
13
+ return normalized.length > 0 ? normalized : undefined;
14
+ }
15
+
16
+ /**
17
+ * Parses a module grammar declaration into normalized object form.
18
+ *
19
+ * Supported input examples:
20
+ * - `react-aria-components`
21
+ * - `react-aria-components{Table,Select}`
22
+ */
23
+ export function parseModuleDeclaration(value: string): ModuleDependencyDeclaration {
24
+ const source = value.trim();
25
+ if (source.length === 0) {
26
+ throw new Error('Module declaration cannot be empty');
27
+ }
28
+
29
+ const openBraceIndex = source.indexOf('{');
30
+ if (openBraceIndex < 0) {
31
+ return { from: source };
32
+ }
33
+
34
+ const closeBraceIndex = source.lastIndexOf('}');
35
+ if (closeBraceIndex !== source.length - 1 || closeBraceIndex <= openBraceIndex) {
36
+ throw new Error(`Invalid module declaration '${value}'`);
37
+ }
38
+
39
+ const from = source.slice(0, openBraceIndex).trim();
40
+ if (from.length === 0) {
41
+ throw new Error(`Invalid module declaration '${value}'`);
42
+ }
43
+
44
+ const importsSlice = source.slice(openBraceIndex + 1, closeBraceIndex);
45
+ const imports = normalizeImports(importsSlice.split(','));
46
+
47
+ return {
48
+ from,
49
+ imports,
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Normalizes and deduplicates module declarations from `modules`.
55
+ *
56
+ * Returns canonical object declarations suitable for downstream bundling logic.
57
+ */
58
+ export function normalizeModuleDeclarations(modules?: string[]): ModuleDependencyDeclaration[] {
59
+ const declarations = modules ?? [];
60
+
61
+ const output: ModuleDependencyDeclaration[] = [];
62
+ const seen = new Set<string>();
63
+
64
+ for (const declaration of declarations) {
65
+ const normalized = parseModuleDeclaration(declaration);
66
+ const key = `${normalized.from}::${(normalized.imports ?? []).join(',')}`;
67
+
68
+ if (!seen.has(key)) {
69
+ seen.add(key);
70
+ output.push(normalized);
71
+ }
72
+ }
73
+
74
+ return output;
75
+ }