@ecopages/core 0.2.0-alpha.5 → 0.2.0-alpha.7

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 +180 -47
  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 +207 -97
  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 +234 -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 -84
  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 +71 -78
  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 -11
  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 -0
  185. package/src/watchers/project-watcher.test.ts +678 -0
  186. package/src/watchers/project-watcher.ts +49 -50
  187. package/CHANGELOG.md +0 -94
  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 -79
  202. package/src/adapters/bun/hmr-manager.js +0 -222
  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 -62
  218. package/src/adapters/node/node-hmr-manager.js +0 -221
  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 -75
  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 -391
  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 -192
  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 -1094
  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 -132
  409. package/src/watchers/project-watcher.js +0 -281
  410. package/src/watchers/project-watcher.test-helpers.d.ts +0 -4
  411. package/src/watchers/project-watcher.test-helpers.js +0 -51
  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
@@ -1,8 +1,8 @@
1
1
  import path from 'node:path';
2
- import { RESOLVED_ASSETS_DIR } from '../../constants';
3
- import { appLogger } from '../../global/app-logger';
4
- import type { EcoPagesAppConfig, IHmrManager } from '../../internal-types';
5
- import { rapidhash } from '../../utils/hash';
2
+ import { RESOLVED_ASSETS_DIR } from '../../../constants';
3
+ import { appLogger } from '../../../global/app-logger';
4
+ import type { EcoPagesAppConfig, IHmrManager } from '../../../internal-types';
5
+ import { rapidhash } from '../../../utils/hash';
6
6
  import { fileSystem } from '@ecopages/file-system';
7
7
  import type { AssetDefinition, AssetKind, AssetSource, ProcessedAsset } from './assets.types';
8
8
  import { isHmrAware } from './processor.interface';
@@ -15,13 +15,28 @@ import {
15
15
  NodeModuleScriptProcessor,
16
16
  } from './processors';
17
17
 
18
+ /**
19
+ * Processes declared component and page asset dependencies for one app instance.
20
+ *
21
+ * @remarks
22
+ * This service is the shared bridge between dependency declarations and emitted
23
+ * runtime-ready assets. It owns deduplication, processor dispatch, cache reuse,
24
+ * output URL normalization, and production gzip preparation so route rendering
25
+ * and HMR flows do not need to understand processor-specific behavior.
26
+ */
18
27
  export class AssetProcessingService {
19
28
  static readonly RESOLVED_ASSETS_DIR = RESOLVED_ASSETS_DIR;
20
29
  private registry = new ProcessorRegistry();
21
30
  private hmrManager?: IHmrManager;
22
31
  private cache = new Map<string, { asset: ProcessedAsset }>();
32
+ private readonly config: EcoPagesAppConfig;
23
33
 
24
- constructor(private readonly config: EcoPagesAppConfig) {}
34
+ /**
35
+ * Creates the asset-processing service bound to one finalized app config.
36
+ */
37
+ constructor(config: EcoPagesAppConfig) {
38
+ this.config = config;
39
+ }
25
40
 
26
41
  /**
27
42
  * Set the HMR manager for the asset processing service.
@@ -54,6 +69,14 @@ export class AssetProcessingService {
54
69
  this.registry.register(kind, variant, processor);
55
70
  }
56
71
 
72
+ /**
73
+ * Processes one dependency list into normalized emitted assets.
74
+ *
75
+ * @remarks
76
+ * Dependencies are deduplicated before processor execution so repeated
77
+ * declarations across the render tree reuse the same emitted outputs and cache
78
+ * entries.
79
+ */
57
80
  async processDependencies(deps: AssetDefinition[], key: string): Promise<ProcessedAsset[]> {
58
81
  const depsDir = path.join(this.config.absolutePaths.distDir, RESOLVED_ASSETS_DIR);
59
82
  fileSystem.ensureDir(depsDir);
@@ -65,6 +88,9 @@ export class AssetProcessingService {
65
88
  return results;
66
89
  }
67
90
 
91
+ /**
92
+ * Removes duplicate dependency declarations while preserving first-seen order.
93
+ */
68
94
  private deduplicateDependencies(deps: AssetDefinition[]): AssetDefinition[] {
69
95
  const seen = new Map<string, AssetDefinition>();
70
96
 
@@ -78,6 +104,10 @@ export class AssetProcessingService {
78
104
  return Array.from(seen.values());
79
105
  }
80
106
 
107
+ /**
108
+ * Builds the cache signature fragment for script dependencies that can vary by
109
+ * bundling policy.
110
+ */
81
111
  private getScriptDependencyBuildSignature(dep: AssetDefinition): string | undefined {
82
112
  if (dep.kind !== 'script') {
83
113
  return undefined;
@@ -97,6 +127,9 @@ export class AssetProcessingService {
97
127
  return this.generateHash(JSON.stringify(signature));
98
128
  }
99
129
 
130
+ /**
131
+ * Derives the stable cache key for one dependency declaration.
132
+ */
100
133
  private getDependencyKey(dep: AssetDefinition): string {
101
134
  const parts: string[] = [dep.kind, dep.source];
102
135
 
@@ -120,10 +153,21 @@ export class AssetProcessingService {
120
153
  return parts.join(':');
121
154
  }
122
155
 
156
+ /**
157
+ * Hashes content used in dependency cache and signature keys.
158
+ */
123
159
  private generateHash(content: string): string {
124
160
  return rapidhash(content).toString();
125
161
  }
126
162
 
163
+ /**
164
+ * Processes deduplicated dependencies grouped by processor type.
165
+ *
166
+ * @remarks
167
+ * Grouping keeps cache and processor behavior isolated by asset kind/source
168
+ * pair, while still allowing the overall dependency set to resolve in
169
+ * parallel.
170
+ */
127
171
  private async processDependenciesParallel(deps: AssetDefinition[], key: string): Promise<ProcessedAsset[]> {
128
172
  const grouped = this.groupDependenciesByType(deps);
129
173
 
@@ -182,6 +226,9 @@ export class AssetProcessingService {
182
226
  return allTypeResults.flat();
183
227
  }
184
228
 
229
+ /**
230
+ * Groups dependencies by processor bucket.
231
+ */
185
232
  private groupDependenciesByType(deps: AssetDefinition[]): Record<string, AssetDefinition[]> {
186
233
  return deps.reduce(
187
234
  (acc, dep) => {
@@ -194,6 +241,9 @@ export class AssetProcessingService {
194
241
  );
195
242
  }
196
243
 
244
+ /**
245
+ * Converts a dist-local file path into its public URL.
246
+ */
197
247
  private getSrcUrl(filepath: string): string | undefined {
198
248
  const distDir = this.config.absolutePaths.distDir;
199
249
  if (!filepath.startsWith(distDir)) return undefined;
@@ -203,6 +253,9 @@ export class AssetProcessingService {
203
253
  return urlPath.replace(/\\/g, '/');
204
254
  }
205
255
 
256
+ /**
257
+ * Normalizes the public source URL for one processed asset.
258
+ */
206
259
  private resolveProcessedAssetSrcUrl(processed: ProcessedAsset): string | undefined {
207
260
  if (processed.srcUrl) {
208
261
  if (this.isFilesystemPath(processed.srcUrl)) {
@@ -220,6 +273,10 @@ export class AssetProcessingService {
220
273
  return undefined;
221
274
  }
222
275
 
276
+ /**
277
+ * Returns whether a value should be interpreted as a filesystem path instead
278
+ * of an already-public URL.
279
+ */
223
280
  private isFilesystemPath(value: string): boolean {
224
281
  if (value.startsWith('http://') || value.startsWith('https://') || value.startsWith('//')) {
225
282
  return false;
@@ -237,6 +294,13 @@ export class AssetProcessingService {
237
294
  return /^[A-Za-z]:\\/.test(value);
238
295
  }
239
296
 
297
+ /**
298
+ * Applies post-processing for emitted production assets.
299
+ *
300
+ * @remarks
301
+ * Current optimization is intentionally conservative: only generated CSS and
302
+ * JavaScript files inside the app dist directory are gzipped.
303
+ */
240
304
  private async optimizeDependencies(processedAssets: ProcessedAsset[]): Promise<void> {
241
305
  if (process.env.NODE_ENV !== 'production') {
242
306
  return;
@@ -266,19 +330,44 @@ export class AssetProcessingService {
266
330
  }
267
331
  }
268
332
 
333
+ /**
334
+ * Returns the cached processed asset for a dependency key when available.
335
+ */
269
336
  private getCachedAsset(dep: AssetDefinition, depKey: string): ProcessedAsset | null {
337
+ if (process.env.NODE_ENV !== 'production' && dep.source === 'file' && dep.kind === 'stylesheet') {
338
+ return null;
339
+ }
340
+
270
341
  const cached = this.cache.get(depKey);
271
- return cached?.asset ?? null;
342
+ if (!cached) {
343
+ return null;
344
+ }
345
+
346
+ if (cached.asset.filepath && !fileSystem.exists(cached.asset.filepath)) {
347
+ this.cache.delete(depKey);
348
+ return null;
349
+ }
350
+
351
+ return cached.asset;
272
352
  }
273
353
 
354
+ /**
355
+ * Stores one processed asset in the dependency cache.
356
+ */
274
357
  private setCachedAsset(dep: AssetDefinition, depKey: string, asset: ProcessedAsset): void {
275
358
  this.cache.set(depKey, { asset });
276
359
  }
277
360
 
361
+ /**
362
+ * Clears all cached processed assets.
363
+ */
278
364
  clearCache(): void {
279
365
  this.cache.clear();
280
366
  }
281
367
 
368
+ /**
369
+ * Removes cached assets that were produced from the given file path.
370
+ */
282
371
  invalidateCacheForFile(filepath: string): void {
283
372
  for (const [key, value] of this.cache.entries()) {
284
373
  if (value.asset.filepath === filepath) {
@@ -287,6 +376,9 @@ export class AssetProcessingService {
287
376
  }
288
377
  }
289
378
 
379
+ /**
380
+ * Creates a service prewired with the default core processors.
381
+ */
290
382
  static createWithDefaultProcessors(appConfig: EcoPagesAppConfig): AssetProcessingService {
291
383
  const service = new AssetProcessingService(appConfig);
292
384
 
@@ -300,6 +392,9 @@ export class AssetProcessingService {
300
392
  return service;
301
393
  }
302
394
 
395
+ /**
396
+ * Returns the processor registry owned by this service.
397
+ */
303
398
  getRegistry(): ProcessorRegistry {
304
399
  return this.registry;
305
400
  }
@@ -0,0 +1,63 @@
1
+ import { expect, test } from 'vitest';
2
+ import { AssetFactory } from './asset.factory';
3
+
4
+ test('AssetFactory - createInlineScriptAsset', () => {
5
+ const asset = AssetFactory.createInlineContentScript({
6
+ content: 'console.log("test")',
7
+ });
8
+ expect(asset.kind).toBe('script');
9
+ expect(asset.source).toBe('content');
10
+ expect(asset.inline).toBe(true);
11
+ expect(asset.position).toBe('body');
12
+ });
13
+
14
+ test('AssetFactory - createSrcScriptAsset', () => {
15
+ const asset = AssetFactory.createFileScript({
16
+ filepath: 'https://test.com/script.js',
17
+ });
18
+ expect(asset.kind).toBe('script');
19
+ expect(asset.source).toBe('file');
20
+ });
21
+
22
+ test('AssetFactory - createJsonAssetScript', () => {
23
+ const asset = AssetFactory.createJsonScript({
24
+ content: '{"test": true}',
25
+ });
26
+ expect(asset.kind).toBe('script');
27
+ expect(asset.source).toBe('content');
28
+ expect(asset.attributes?.type).toBe('application/json');
29
+ });
30
+
31
+ test('AssetFactory - createInlineStylesheetAsset', () => {
32
+ const asset = AssetFactory.createInlineContentStylesheet({
33
+ content: 'body { color: red; }',
34
+ });
35
+ expect(asset.kind).toBe('stylesheet');
36
+ expect(asset.source).toBe('content');
37
+ expect(asset.position).toBe('head');
38
+ });
39
+
40
+ test('AssetFactory - createContentScript', () => {
41
+ const asset = AssetFactory.createContentScript({
42
+ content: 'console.log("test")',
43
+ });
44
+ expect(asset.kind).toBe('script');
45
+ expect(asset.source).toBe('content');
46
+ expect(asset.position).toBe('body');
47
+ });
48
+
49
+ test('AssetFactory - createInlineContentScript', () => {
50
+ const asset = AssetFactory.createInlineContentScript({
51
+ content: 'console.log("test")',
52
+ });
53
+ expect(asset.inline).toBe(true);
54
+ expect(asset.source).toBe('content');
55
+ });
56
+
57
+ test('AssetFactory - createFileScript', () => {
58
+ const asset = AssetFactory.createFileScript({
59
+ filepath: '/path/to/script.js',
60
+ });
61
+ expect(asset.kind).toBe('script');
62
+ expect(asset.source).toBe('file');
63
+ });
@@ -1,5 +1,5 @@
1
- import { RESOLVED_ASSETS_DIR, RESOLVED_ASSETS_VENDORS_DIR } from '../../constants';
2
- import { deepMerge } from '../../utils/deep-merge';
1
+ import { RESOLVED_ASSETS_DIR, RESOLVED_ASSETS_VENDORS_DIR } from '../../../constants';
2
+ import { deepMerge } from '../../../utils/deep-merge';
3
3
  import type {
4
4
  ContentScriptAsset,
5
5
  ContentStylesheetAsset,
@@ -1,4 +1,4 @@
1
- import type { EcoBuildPlugin } from '../../build/build-types.ts';
1
+ import type { EcoBuildPlugin } from '../../../build/build-types.ts';
2
2
 
3
3
  export type AssetSource = 'content' | 'file' | 'node-module';
4
4
  export type AssetKind = 'script' | 'stylesheet';
@@ -16,6 +16,7 @@ export interface ScriptAsset extends BaseAsset {
16
16
  inline?: boolean;
17
17
  bundle?: boolean;
18
18
  bundleOptions?: {
19
+ define?: Record<string, string>;
19
20
  minify?: boolean;
20
21
  external?: string[];
21
22
  naming?: string;
@@ -0,0 +1,72 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { test } from 'vitest';
6
+ import {
7
+ BROWSER_RUNTIME_SCRIPT_ATTRIBUTES,
8
+ buildBrowserRuntimeAssetUrl,
9
+ createBrowserRuntimeModuleAsset,
10
+ createBrowserRuntimeScriptAsset,
11
+ } from './browser-runtime-asset.factory.ts';
12
+
13
+ test('buildBrowserRuntimeAssetUrl uses the vendors asset directory', () => {
14
+ assert.equal(buildBrowserRuntimeAssetUrl('react.js'), '/assets/vendors/react.js');
15
+ });
16
+
17
+ test('createBrowserRuntimeScriptAsset creates a hidden head runtime bundle asset', () => {
18
+ const plugin = { name: 'runtime-plugin', setup() {} };
19
+ const asset = createBrowserRuntimeScriptAsset({
20
+ importPath: '/tmp/react-entry.mjs',
21
+ name: 'react',
22
+ fileName: 'react.js',
23
+ bundleOptions: {
24
+ plugins: [plugin],
25
+ },
26
+ });
27
+
28
+ assert.deepEqual(asset, {
29
+ kind: 'script',
30
+ source: 'node-module',
31
+ position: 'head',
32
+ importPath: '/tmp/react-entry.mjs',
33
+ name: 'react',
34
+ excludeFromHtml: true,
35
+ bundleOptions: {
36
+ naming: 'react.js',
37
+ plugins: [plugin],
38
+ },
39
+ attributes: BROWSER_RUNTIME_SCRIPT_ATTRIBUTES,
40
+ });
41
+ });
42
+
43
+ test('createBrowserRuntimeModuleAsset creates an entry module and hidden runtime asset together', () => {
44
+ const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), 'eco-browser-runtime-asset-'));
45
+ fs.writeFileSync(path.join(rootDir, 'package.json'), '{}', 'utf8');
46
+ fs.mkdirSync(path.join(rootDir, 'node_modules', 'runtime-a'), { recursive: true });
47
+ fs.writeFileSync(
48
+ path.join(rootDir, 'node_modules', 'runtime-a', 'index.js'),
49
+ "module.exports = { default: 'runtime-a', alpha: 'a' };",
50
+ 'utf8',
51
+ );
52
+
53
+ try {
54
+ const asset = createBrowserRuntimeModuleAsset({
55
+ rootDir,
56
+ cacheDirName: 'ecopages-browser-runtime-test',
57
+ modules: [{ specifier: 'runtime-a', defaultExport: true }],
58
+ name: 'runtime-a',
59
+ fileName: 'runtime-a.js',
60
+ });
61
+
62
+ assert.equal(asset.source, 'node-module');
63
+ assert.equal(
64
+ asset.importPath.endsWith(path.join('ecopages-browser-runtime-test', 'runtime-a-entry.mjs')),
65
+ true,
66
+ );
67
+ assert.equal(asset.bundleOptions?.naming, 'runtime-a.js');
68
+ assert.equal(asset.excludeFromHtml, true);
69
+ } finally {
70
+ fs.rmSync(rootDir, { recursive: true, force: true });
71
+ }
72
+ });
@@ -0,0 +1,95 @@
1
+ import type { EcoBuildPlugin } from '../../../build/build-types.ts';
2
+ import { AssetFactory } from './asset.factory.ts';
3
+ import type { AssetDefinition } from './assets.types.ts';
4
+ import {
5
+ createBrowserRuntimeEntryModule,
6
+ type BrowserRuntimeEntryModuleConfig,
7
+ } from './browser-runtime-entry.factory.ts';
8
+
9
+ export const BROWSER_RUNTIME_SCRIPT_ATTRIBUTES = {
10
+ type: 'module',
11
+ defer: '',
12
+ } as const;
13
+
14
+ /**
15
+ * Builds the public vendor URL used for generated browser runtime assets.
16
+ */
17
+ export function buildBrowserRuntimeAssetUrl(fileName: string): string {
18
+ return `/${AssetFactory.RESOLVED_ASSETS_VENDORS_DIR}/${fileName}`;
19
+ }
20
+
21
+ /**
22
+ * Declares a browser runtime script asset backed by one importable module.
23
+ *
24
+ * @remarks
25
+ * Runtime assets are emitted as excluded head scripts because integrations often
26
+ * need the bundler output and specifier registration without injecting the raw
27
+ * asset directly into HTML during dependency resolution.
28
+ */
29
+ export function createBrowserRuntimeScriptAsset(options: {
30
+ importPath: string;
31
+ name: string;
32
+ fileName: string;
33
+ bundleOptions?: {
34
+ define?: Record<string, string>;
35
+ minify?: boolean;
36
+ external?: string[];
37
+ naming?: string;
38
+ plugins?: EcoBuildPlugin[];
39
+ };
40
+ attributes?: Record<string, string>;
41
+ }): AssetDefinition {
42
+ return AssetFactory.createNodeModuleScript({
43
+ position: 'head',
44
+ importPath: options.importPath,
45
+ name: options.name,
46
+ excludeFromHtml: true,
47
+ bundleOptions: {
48
+ naming: options.fileName,
49
+ ...options.bundleOptions,
50
+ },
51
+ attributes: {
52
+ ...BROWSER_RUNTIME_SCRIPT_ATTRIBUTES,
53
+ ...(options.attributes ?? {}),
54
+ },
55
+ });
56
+ }
57
+
58
+ /**
59
+ * Creates a browser runtime asset from a generated re-export entry module.
60
+ *
61
+ * @remarks
62
+ * This is the shared "module list -> generated entry file -> runtime asset"
63
+ * path used by integrations that need browser-side runtime bundles without
64
+ * owning bespoke entry-file generation logic.
65
+ */
66
+ export function createBrowserRuntimeModuleAsset(options: {
67
+ modules: BrowserRuntimeEntryModuleConfig[];
68
+ name: string;
69
+ fileName: string;
70
+ cacheDirName?: string;
71
+ rootDir?: string;
72
+ bundleOptions?: {
73
+ define?: Record<string, string>;
74
+ minify?: boolean;
75
+ external?: string[];
76
+ naming?: string;
77
+ plugins?: EcoBuildPlugin[];
78
+ };
79
+ attributes?: Record<string, string>;
80
+ }): AssetDefinition {
81
+ const importPath = createBrowserRuntimeEntryModule({
82
+ modules: options.modules,
83
+ fileName: `${options.name}-entry.mjs`,
84
+ rootDir: options.rootDir,
85
+ cacheDirName: options.cacheDirName,
86
+ });
87
+
88
+ return createBrowserRuntimeScriptAsset({
89
+ importPath,
90
+ name: options.name,
91
+ fileName: options.fileName,
92
+ bundleOptions: options.bundleOptions,
93
+ attributes: options.attributes,
94
+ });
95
+ }
@@ -0,0 +1,67 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { test } from 'vitest';
6
+ import { createBrowserRuntimeEntryModule } from './browser-runtime-entry.factory.ts';
7
+
8
+ test('createBrowserRuntimeEntryModule writes a shared runtime entry file', () => {
9
+ const rootDir = fs.mkdtempSync(path.join(tmpdir(), 'eco-browser-runtime-entry-'));
10
+ fs.writeFileSync(path.join(rootDir, 'package.json'), '{}', 'utf8');
11
+
12
+ try {
13
+ const filePath = createBrowserRuntimeEntryModule({
14
+ rootDir,
15
+ cacheDirName: 'ecopages-react-runtime-test',
16
+ fileName: 'runtime-entry.mjs',
17
+ modules: [{ specifier: 'node:path' }, { specifier: 'node:fs' }],
18
+ });
19
+
20
+ assert.equal(path.basename(filePath), 'runtime-entry.mjs');
21
+ assert.equal(
22
+ filePath,
23
+ path.join(rootDir, 'node_modules', '.cache', 'ecopages-react-runtime-test', 'runtime-entry.mjs'),
24
+ );
25
+
26
+ const contents = fs.readFileSync(filePath, 'utf8');
27
+ assert.match(contents, /export \{ .*basename.* \} from 'node:path';/);
28
+ assert.match(contents, /export \{ .*readFileSync.* \} from 'node:fs';/);
29
+ } finally {
30
+ fs.rmSync(rootDir, { recursive: true, force: true });
31
+ }
32
+ });
33
+
34
+ test('createBrowserRuntimeEntryModule preserves a default export and deduplicates named exports', () => {
35
+ const rootDir = fs.mkdtempSync(path.join(tmpdir(), 'eco-browser-runtime-entry-'));
36
+ fs.writeFileSync(path.join(rootDir, 'package.json'), '{}', 'utf8');
37
+ fs.mkdirSync(path.join(rootDir, 'node_modules', 'runtime-a'), { recursive: true });
38
+ fs.mkdirSync(path.join(rootDir, 'node_modules', 'runtime-b'), { recursive: true });
39
+ fs.writeFileSync(
40
+ path.join(rootDir, 'node_modules', 'runtime-a', 'index.js'),
41
+ "module.exports = { default: 'runtime-a', alpha: 'a', shared: 'shared-a' };",
42
+ 'utf8',
43
+ );
44
+ fs.writeFileSync(
45
+ path.join(rootDir, 'node_modules', 'runtime-b', 'index.js'),
46
+ "module.exports = { beta: 'b', shared: 'shared-b' };",
47
+ 'utf8',
48
+ );
49
+
50
+ try {
51
+ const filePath = createBrowserRuntimeEntryModule({
52
+ rootDir,
53
+ cacheDirName: 'ecopages-react-runtime-test',
54
+ fileName: 'runtime-entry.mjs',
55
+ modules: [{ specifier: 'runtime-a', defaultExport: true }, { specifier: 'runtime-b' }],
56
+ });
57
+
58
+ const contents = fs.readFileSync(filePath, 'utf8');
59
+ assert.match(contents, /import __ecopages_default_export__ from 'runtime-a';/);
60
+ assert.match(contents, /export default __ecopages_default_export__;/);
61
+ assert.match(contents, /export \{ alpha, shared \} from 'runtime-a';/);
62
+ assert.match(contents, /export \{ beta \} from 'runtime-b';/);
63
+ assert.doesNotMatch(contents, /export \{ .*shared.* \} from 'runtime-b';/);
64
+ } finally {
65
+ fs.rmSync(rootDir, { recursive: true, force: true });
66
+ }
67
+ });
@@ -0,0 +1,78 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createRequire } from 'node:module';
4
+
5
+ export type BrowserRuntimeEntryModuleConfig = {
6
+ specifier: string;
7
+ defaultExport?: boolean;
8
+ };
9
+
10
+ /**
11
+ * Creates a generated ESM entry module that re-exports runtime modules through
12
+ * one stable file.
13
+ *
14
+ * @remarks
15
+ * Integrations use this helper when they need a browser runtime asset composed
16
+ * from multiple bare specifiers but do not want to own temporary file assembly
17
+ * logic themselves. The generated file lives under a cache directory inside the
18
+ * consuming app root so repeated runs can reuse the same location.
19
+ */
20
+ export function createBrowserRuntimeEntryModule(options: {
21
+ modules: BrowserRuntimeEntryModuleConfig[];
22
+ fileName: string;
23
+ rootDir?: string;
24
+ cacheDirName?: string;
25
+ }): string {
26
+ const rootDir = options.rootDir ?? process.cwd();
27
+ const artifactsDir = path.join(
28
+ rootDir,
29
+ 'node_modules',
30
+ '.cache',
31
+ options.cacheDirName ?? 'ecopages-browser-runtime',
32
+ );
33
+ fs.mkdirSync(artifactsDir, { recursive: true });
34
+
35
+ const requireFromRoot = createRequire(path.join(rootDir, 'package.json'));
36
+ const seenExports = new Set<string>();
37
+ const statements: string[] = [];
38
+
39
+ for (const module of options.modules) {
40
+ if (module.defaultExport) {
41
+ statements.push(`import __ecopages_default_export__ from '${module.specifier}';`);
42
+ statements.push('export default __ecopages_default_export__;');
43
+ }
44
+
45
+ const exportNames = getModuleExportNames(module.specifier, requireFromRoot).filter(
46
+ (name) => !seenExports.has(name),
47
+ );
48
+
49
+ if (exportNames.length > 0) {
50
+ statements.push(`export { ${exportNames.join(', ')} } from '${module.specifier}';`);
51
+ for (const exportName of exportNames) {
52
+ seenExports.add(exportName);
53
+ }
54
+ }
55
+ }
56
+
57
+ const filePath = path.join(artifactsDir, options.fileName);
58
+ fs.writeFileSync(filePath, statements.join('\n'), 'utf-8');
59
+ return filePath;
60
+ }
61
+
62
+ /**
63
+ * Reads the named runtime exports that should be re-exported from a generated
64
+ * runtime entry module.
65
+ *
66
+ * @remarks
67
+ * Default exports are handled separately because generated runtime entry files
68
+ * need to emit a synthetic default binding only when the caller explicitly asks
69
+ * for it.
70
+ */
71
+ function getModuleExportNames(specifier: string, requireFromRoot: ReturnType<typeof createRequire>): string[] {
72
+ const moduleExports = requireFromRoot(specifier);
73
+
74
+ return Object.keys(moduleExports)
75
+ .filter((name) => name !== '__esModule' && name !== 'default')
76
+ .filter((name) => /^[$A-Z_a-z][$\w]*$/.test(name))
77
+ .sort();
78
+ }
@@ -1,3 +1,5 @@
1
1
  export * from './asset.factory';
2
2
  export * from './asset-processing.service';
3
3
  export * from './assets.types';
4
+ export * from './browser-runtime-asset.factory';
5
+ export * from './browser-runtime-entry.factory';
@@ -1,4 +1,4 @@
1
- import type { IHmrManager } from '../../internal-types';
1
+ import type { IHmrManager } from '../../../internal-types';
2
2
  import type { AssetDefinition, ProcessedAsset } from './assets.types';
3
3
 
4
4
  /**