@ecopages/core 0.2.0-alpha.4 → 0.2.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/README.md +213 -12
  2. package/package.json +100 -188
  3. package/src/adapters/README.md +39 -0
  4. package/src/adapters/bun/hmr-manager.test.ts +267 -0
  5. package/src/adapters/bun/hmr-manager.ts +181 -68
  6. package/src/adapters/bun/index.ts +1 -2
  7. package/src/adapters/bun/server-adapter.ts +41 -34
  8. package/src/adapters/bun/server-lifecycle.ts +40 -70
  9. package/src/adapters/index.ts +1 -1
  10. package/src/adapters/node/bootstrap-dependency-resolver.test.ts +282 -0
  11. package/src/adapters/node/bootstrap-dependency-resolver.ts +301 -0
  12. package/src/adapters/node/index.ts +7 -0
  13. package/src/adapters/node/node-client-bridge.test.ts +198 -0
  14. package/src/adapters/node/node-hmr-manager.test.ts +322 -0
  15. package/src/adapters/node/node-hmr-manager.ts +208 -116
  16. package/src/adapters/node/runtime-adapter.test.ts +868 -0
  17. package/src/adapters/node/runtime-adapter.ts +439 -0
  18. package/src/adapters/node/server-adapter.ts +31 -104
  19. package/src/adapters/node/static-content-server.test.ts +60 -0
  20. package/src/adapters/node/static-content-server.ts +36 -0
  21. package/src/adapters/node/write-runtime-manifest.ts +38 -0
  22. package/src/adapters/shared/api-response.test.ts +97 -0
  23. package/src/{define-api-handler.ts → adapters/shared/define-api-handler.ts} +1 -1
  24. package/src/adapters/shared/explicit-static-route-matcher.test.ts +381 -0
  25. package/src/adapters/shared/explicit-static-route-matcher.ts +7 -1
  26. package/src/adapters/shared/file-route-middleware-pipeline.test.ts +90 -0
  27. package/src/adapters/shared/file-route-middleware-pipeline.ts +6 -2
  28. package/src/adapters/shared/fs-server-response-factory.test.ts +187 -0
  29. package/src/adapters/shared/fs-server-response-matcher.test.ts +286 -0
  30. package/src/adapters/shared/fs-server-response-matcher.ts +17 -10
  31. package/src/adapters/shared/hmr-entrypoint-registrar.ts +149 -0
  32. package/src/adapters/shared/hmr-html-response.ts +52 -0
  33. package/src/adapters/shared/hmr-manager.contract.test.ts +196 -0
  34. package/src/adapters/shared/hmr-manager.dispatch.test.ts +220 -0
  35. package/src/adapters/shared/render-context.test.ts +146 -0
  36. package/src/adapters/shared/render-context.ts +21 -6
  37. package/src/adapters/shared/runtime-bootstrap.ts +79 -0
  38. package/src/adapters/shared/server-adapter.test.ts +77 -0
  39. package/src/adapters/shared/server-adapter.ts +51 -4
  40. package/src/adapters/shared/server-route-handler.test.ts +110 -0
  41. package/src/adapters/shared/server-route-handler.ts +5 -18
  42. package/src/adapters/shared/server-static-builder.test.ts +316 -0
  43. package/src/adapters/shared/server-static-builder.ts +92 -8
  44. package/src/build/README.md +101 -0
  45. package/src/build/build-adapter-serialization.test.ts +268 -0
  46. package/src/build/build-adapter.test.ts +815 -0
  47. package/src/build/build-adapter.ts +235 -6
  48. package/src/build/build-manifest.ts +54 -0
  49. package/src/build/dev-build-coordinator.ts +221 -0
  50. package/src/build/esbuild-build-adapter.ts +132 -83
  51. package/src/build/runtime-build-executor.ts +34 -0
  52. package/src/build/runtime-specifier-alias-plugin.test.ts +43 -0
  53. package/src/build/runtime-specifier-alias-plugin.ts +58 -0
  54. package/src/config/README.md +33 -0
  55. package/src/config/config-builder.test.ts +410 -0
  56. package/src/config/config-builder.ts +281 -49
  57. package/src/constants.ts +15 -0
  58. package/src/declarations.d.ts +18 -13
  59. package/src/eco/README.md +70 -16
  60. package/src/eco/component-render-context.ts +39 -17
  61. package/src/eco/eco.test.ts +678 -0
  62. package/src/eco/eco.ts +29 -8
  63. package/src/eco/eco.types.ts +20 -1
  64. package/src/eco/eco.utils.test.ts +124 -0
  65. package/src/eco/global-injector-map.test.ts +42 -0
  66. package/src/eco/lazy-injector-map.test.ts +66 -0
  67. package/src/eco/module-dependencies.test.ts +30 -0
  68. package/src/errors/http-error.test.ts +134 -0
  69. package/src/global/utils.test.ts +12 -0
  70. package/src/hmr/README.md +26 -0
  71. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-have-HMR-script-injected-in-page-1.png +0 -0
  72. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-load-fixture-app-page-1.png +0 -0
  73. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-WebSocket-Connection-should-connect-to-correct-HMR-endpoint-1.png +0 -0
  74. package/src/hmr/client/hmr-runtime.ts +38 -7
  75. package/src/hmr/hmr-strategy.test.ts +124 -0
  76. package/src/hmr/hmr.postcss.test.e2e.ts +41 -0
  77. package/src/hmr/hmr.test.e2e.ts +29 -38
  78. package/src/hmr/strategies/js-hmr-strategy.test.ts +335 -0
  79. package/src/hmr/strategies/js-hmr-strategy.ts +115 -115
  80. package/src/index.ts +1 -1
  81. package/src/integrations/ghtml/ghtml-renderer.test.ts +63 -0
  82. package/src/integrations/ghtml/ghtml-renderer.ts +4 -1
  83. package/src/internal-types.ts +39 -19
  84. package/src/plugins/README.md +34 -0
  85. package/src/plugins/alias-resolver-plugin.test.ts +41 -0
  86. package/src/plugins/alias-resolver-plugin.ts +21 -3
  87. package/src/plugins/eco-component-meta-plugin.test.ts +380 -0
  88. package/src/plugins/eco-component-meta-plugin.ts +10 -3
  89. package/src/plugins/integration-plugin.test.ts +111 -0
  90. package/src/plugins/integration-plugin.ts +45 -3
  91. package/src/plugins/processor.test.ts +148 -0
  92. package/src/plugins/processor.ts +22 -2
  93. package/src/plugins/runtime-capability.ts +14 -0
  94. package/src/public-types.ts +73 -16
  95. package/src/route-renderer/GRAPH.md +16 -20
  96. package/src/route-renderer/README.md +8 -21
  97. package/src/route-renderer/component-graph/component-graph-executor.test.ts +41 -0
  98. package/src/route-renderer/component-graph/component-graph.test.ts +63 -0
  99. package/src/route-renderer/component-graph/component-marker.test.ts +73 -0
  100. package/src/route-renderer/component-graph/component-reference.ts +29 -0
  101. package/src/route-renderer/component-graph/marker-graph-resolver.test.ts +135 -0
  102. package/src/route-renderer/{marker-graph-resolver.ts → component-graph/marker-graph-resolver.ts} +11 -9
  103. package/src/route-renderer/orchestration/integration-renderer.test.ts +936 -0
  104. package/src/route-renderer/{integration-renderer.ts → orchestration/integration-renderer.ts} +113 -19
  105. package/src/route-renderer/orchestration/render-execution.service.test.ts +97 -0
  106. package/src/route-renderer/{render-execution.service.ts → orchestration/render-execution.service.ts} +109 -37
  107. package/src/route-renderer/orchestration/render-preparation.service.test.ts +235 -0
  108. package/src/route-renderer/{render-preparation.service.ts → orchestration/render-preparation.service.ts} +127 -9
  109. package/src/route-renderer/page-loading/dependency-resolver.test.ts +345 -0
  110. package/src/route-renderer/{dependency-resolver.ts → page-loading/dependency-resolver.ts} +28 -12
  111. package/src/route-renderer/page-loading/page-module-loader.test.ts +96 -0
  112. package/src/route-renderer/{page-module-loader.ts → page-loading/page-module-loader.ts} +49 -21
  113. package/src/route-renderer/route-renderer.ts +36 -1
  114. package/src/router/README.md +26 -0
  115. package/src/router/client/link-intent.d.ts +53 -0
  116. package/src/router/client/link-intent.test.browser.ts +51 -0
  117. package/src/router/client/link-intent.ts +92 -0
  118. package/src/router/client/navigation-coordinator.test.ts +237 -0
  119. package/src/router/client/navigation-coordinator.ts +433 -0
  120. package/src/router/server/fs-router-scanner.test.ts +83 -0
  121. package/src/router/{fs-router-scanner.ts → server/fs-router-scanner.ts} +12 -10
  122. package/src/router/server/fs-router.test.ts +214 -0
  123. package/src/router/{fs-router.ts → server/fs-router.ts} +2 -2
  124. package/src/services/README.md +29 -0
  125. package/src/services/assets/asset-processing-service/asset-processing.service.test.ts +385 -0
  126. package/src/services/{asset-processing-service → assets/asset-processing-service}/asset-processing.service.ts +101 -6
  127. package/src/services/assets/asset-processing-service/asset.factory.test.ts +63 -0
  128. package/src/services/{asset-processing-service → assets/asset-processing-service}/asset.factory.ts +2 -2
  129. package/src/services/{asset-processing-service → assets/asset-processing-service}/assets.types.ts +2 -1
  130. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.test.ts +72 -0
  131. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.ts +95 -0
  132. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.test.ts +67 -0
  133. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.ts +78 -0
  134. package/src/services/{asset-processing-service → assets/asset-processing-service}/index.ts +2 -0
  135. package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.interface.ts +1 -1
  136. package/src/services/assets/asset-processing-service/processors/base/base-processor.test.ts +59 -0
  137. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-processor.ts +11 -5
  138. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-script-processor.ts +17 -27
  139. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.test.ts +286 -0
  140. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/file-script.processor.ts +3 -3
  141. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.test.ts +227 -0
  142. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/node-module-script.processor.ts +5 -4
  143. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.test.ts +199 -0
  144. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/file-stylesheet.processor.ts +4 -1
  145. package/src/services/assets/browser-bundle.service.test.ts +36 -0
  146. package/src/services/assets/browser-bundle.service.ts +53 -0
  147. package/src/services/cache/index.ts +3 -3
  148. package/src/services/cache/memory-cache-store.test.ts +225 -0
  149. package/src/services/cache/memory-cache-store.ts +1 -1
  150. package/src/services/cache/page-cache-service.test.ts +175 -0
  151. package/src/services/cache/page-cache-service.ts +3 -3
  152. package/src/services/cache/page-request-cache-coordinator.service.test.ts +79 -0
  153. package/src/services/{page-request-cache-coordinator.service.ts → cache/page-request-cache-coordinator.service.ts} +9 -6
  154. package/src/services/html/html-rewriter-provider.service.test.ts +183 -0
  155. package/src/services/html/html-rewriter-provider.service.ts +103 -0
  156. package/src/services/html/html-transformer.service.test.ts +378 -0
  157. package/src/services/html/html-transformer.service.ts +279 -0
  158. package/src/services/invalidation/development-invalidation.service.test.ts +77 -0
  159. package/src/services/invalidation/development-invalidation.service.ts +261 -0
  160. package/src/services/module-loading/app-server-module-transpiler.service.ts +52 -0
  161. package/src/services/module-loading/page-module-import.service.test.ts +253 -0
  162. package/src/services/module-loading/page-module-import.service.ts +200 -0
  163. package/src/services/module-loading/server-loader.service.test.ts +161 -0
  164. package/src/services/module-loading/server-loader.service.ts +130 -0
  165. package/src/services/module-loading/server-module-transpiler.service.test.ts +115 -0
  166. package/src/services/module-loading/server-module-transpiler.service.ts +105 -0
  167. package/src/services/runtime-manifest/node-runtime-manifest.service.test.ts +95 -0
  168. package/src/services/runtime-manifest/node-runtime-manifest.service.ts +101 -0
  169. package/src/services/runtime-state/dev-graph.service.ts +217 -0
  170. package/src/services/runtime-state/entrypoint-dependency-graph.service.ts +136 -0
  171. package/src/services/runtime-state/runtime-specifier-registry.service.ts +96 -0
  172. package/src/services/runtime-state/server-invalidation-state.service.ts +68 -0
  173. package/src/services/validation/schema-validation-service.test.ts +223 -0
  174. package/src/services/{schema-validation-service.ts → validation/schema-validation-service.ts} +1 -1
  175. package/src/static-site-generator/README.md +26 -0
  176. package/src/static-site-generator/static-site-generator.test.ts +307 -0
  177. package/src/static-site-generator/static-site-generator.ts +109 -6
  178. package/src/utils/deep-merge.test.ts +114 -0
  179. package/src/utils/invariant.test.ts +22 -0
  180. package/src/utils/path-utils.test.ts +15 -0
  181. package/src/utils/resolve-work-dir.ts +45 -0
  182. package/src/utils/server-utils.test.ts +38 -0
  183. package/src/watchers/project-watcher.integration.test.ts +337 -0
  184. package/src/watchers/project-watcher.test-helpers.ts +1 -1
  185. package/src/watchers/project-watcher.test.ts +678 -0
  186. package/src/watchers/project-watcher.ts +130 -111
  187. package/CHANGELOG.md +0 -91
  188. package/src/adapters/abstract/application-adapter.d.ts +0 -168
  189. package/src/adapters/abstract/application-adapter.js +0 -109
  190. package/src/adapters/abstract/router-adapter.d.ts +0 -26
  191. package/src/adapters/abstract/router-adapter.js +0 -5
  192. package/src/adapters/abstract/server-adapter.d.ts +0 -69
  193. package/src/adapters/abstract/server-adapter.js +0 -15
  194. package/src/adapters/bun/client-bridge.d.ts +0 -34
  195. package/src/adapters/bun/client-bridge.js +0 -48
  196. package/src/adapters/bun/create-app.d.ts +0 -60
  197. package/src/adapters/bun/create-app.js +0 -117
  198. package/src/adapters/bun/define-api-handler.d.ts +0 -61
  199. package/src/adapters/bun/define-api-handler.js +0 -15
  200. package/src/adapters/bun/define-api-handler.ts +0 -114
  201. package/src/adapters/bun/hmr-manager.d.ts +0 -85
  202. package/src/adapters/bun/hmr-manager.js +0 -240
  203. package/src/adapters/bun/index.d.ts +0 -3
  204. package/src/adapters/bun/index.js +0 -8
  205. package/src/adapters/bun/server-adapter.d.ts +0 -155
  206. package/src/adapters/bun/server-adapter.js +0 -368
  207. package/src/adapters/bun/server-lifecycle.d.ts +0 -52
  208. package/src/adapters/bun/server-lifecycle.js +0 -120
  209. package/src/adapters/index.d.ts +0 -6
  210. package/src/adapters/index.js +0 -14
  211. package/src/adapters/node/create-app.d.ts +0 -21
  212. package/src/adapters/node/create-app.js +0 -143
  213. package/src/adapters/node/index.d.ts +0 -4
  214. package/src/adapters/node/index.js +0 -8
  215. package/src/adapters/node/node-client-bridge.d.ts +0 -26
  216. package/src/adapters/node/node-client-bridge.js +0 -66
  217. package/src/adapters/node/node-hmr-manager.d.ts +0 -63
  218. package/src/adapters/node/node-hmr-manager.js +0 -237
  219. package/src/adapters/node/server-adapter.d.ts +0 -190
  220. package/src/adapters/node/server-adapter.js +0 -420
  221. package/src/adapters/node/static-content-server.d.ts +0 -24
  222. package/src/adapters/node/static-content-server.js +0 -166
  223. package/src/adapters/shared/api-response.d.ts +0 -52
  224. package/src/adapters/shared/api-response.js +0 -96
  225. package/src/adapters/shared/application-adapter.d.ts +0 -18
  226. package/src/adapters/shared/application-adapter.js +0 -90
  227. package/src/adapters/shared/explicit-static-route-matcher.d.ts +0 -38
  228. package/src/adapters/shared/explicit-static-route-matcher.js +0 -100
  229. package/src/adapters/shared/file-route-middleware-pipeline.d.ts +0 -65
  230. package/src/adapters/shared/file-route-middleware-pipeline.js +0 -98
  231. package/src/adapters/shared/fs-server-response-factory.d.ts +0 -19
  232. package/src/adapters/shared/fs-server-response-factory.js +0 -97
  233. package/src/adapters/shared/fs-server-response-matcher.d.ts +0 -71
  234. package/src/adapters/shared/fs-server-response-matcher.js +0 -155
  235. package/src/adapters/shared/render-context.d.ts +0 -14
  236. package/src/adapters/shared/render-context.js +0 -69
  237. package/src/adapters/shared/server-adapter.d.ts +0 -87
  238. package/src/adapters/shared/server-adapter.js +0 -353
  239. package/src/adapters/shared/server-route-handler.d.ts +0 -89
  240. package/src/adapters/shared/server-route-handler.js +0 -120
  241. package/src/adapters/shared/server-static-builder.d.ts +0 -38
  242. package/src/adapters/shared/server-static-builder.js +0 -46
  243. package/src/build/build-adapter.d.ts +0 -74
  244. package/src/build/build-adapter.js +0 -54
  245. package/src/build/build-types.d.ts +0 -57
  246. package/src/build/build-types.js +0 -0
  247. package/src/build/esbuild-build-adapter.d.ts +0 -69
  248. package/src/build/esbuild-build-adapter.js +0 -390
  249. package/src/config/config-builder.d.ts +0 -227
  250. package/src/config/config-builder.js +0 -392
  251. package/src/constants.d.ts +0 -32
  252. package/src/constants.js +0 -21
  253. package/src/create-app.d.ts +0 -17
  254. package/src/create-app.js +0 -66
  255. package/src/define-api-handler.d.ts +0 -25
  256. package/src/define-api-handler.js +0 -15
  257. package/src/dev/sc-server.d.ts +0 -30
  258. package/src/dev/sc-server.js +0 -111
  259. package/src/eco/component-render-context.d.ts +0 -105
  260. package/src/eco/component-render-context.js +0 -77
  261. package/src/eco/eco.d.ts +0 -9
  262. package/src/eco/eco.js +0 -110
  263. package/src/eco/eco.types.d.ts +0 -170
  264. package/src/eco/eco.types.js +0 -0
  265. package/src/eco/eco.utils.d.ts +0 -40
  266. package/src/eco/eco.utils.js +0 -40
  267. package/src/eco/global-injector-map.d.ts +0 -16
  268. package/src/eco/global-injector-map.js +0 -80
  269. package/src/eco/lazy-injector-map.d.ts +0 -8
  270. package/src/eco/lazy-injector-map.js +0 -70
  271. package/src/eco/module-dependencies.d.ts +0 -18
  272. package/src/eco/module-dependencies.js +0 -49
  273. package/src/errors/http-error.d.ts +0 -31
  274. package/src/errors/http-error.js +0 -50
  275. package/src/errors/index.d.ts +0 -2
  276. package/src/errors/index.js +0 -4
  277. package/src/errors/locals-access-error.d.ts +0 -4
  278. package/src/errors/locals-access-error.js +0 -9
  279. package/src/global/app-logger.d.ts +0 -2
  280. package/src/global/app-logger.js +0 -6
  281. package/src/hmr/client/hmr-runtime.d.ts +0 -10
  282. package/src/hmr/client/hmr-runtime.js +0 -86
  283. package/src/hmr/hmr-strategy.d.ts +0 -159
  284. package/src/hmr/hmr-strategy.js +0 -29
  285. package/src/hmr/hmr.test.e2e.d.ts +0 -1
  286. package/src/hmr/hmr.test.e2e.js +0 -50
  287. package/src/hmr/strategies/default-hmr-strategy.d.ts +0 -43
  288. package/src/hmr/strategies/default-hmr-strategy.js +0 -34
  289. package/src/hmr/strategies/js-hmr-strategy.d.ts +0 -136
  290. package/src/hmr/strategies/js-hmr-strategy.js +0 -188
  291. package/src/index.browser.d.ts +0 -3
  292. package/src/index.browser.js +0 -4
  293. package/src/index.d.ts +0 -5
  294. package/src/index.js +0 -10
  295. package/src/integrations/ghtml/ghtml-renderer.d.ts +0 -15
  296. package/src/integrations/ghtml/ghtml-renderer.js +0 -60
  297. package/src/integrations/ghtml/ghtml.plugin.d.ts +0 -20
  298. package/src/integrations/ghtml/ghtml.plugin.js +0 -21
  299. package/src/internal-types.d.ts +0 -200
  300. package/src/internal-types.js +0 -0
  301. package/src/plugins/alias-resolver-plugin.d.ts +0 -2
  302. package/src/plugins/alias-resolver-plugin.js +0 -39
  303. package/src/plugins/eco-component-meta-plugin.d.ts +0 -95
  304. package/src/plugins/eco-component-meta-plugin.js +0 -157
  305. package/src/plugins/integration-plugin.d.ts +0 -102
  306. package/src/plugins/integration-plugin.js +0 -100
  307. package/src/plugins/processor.d.ts +0 -82
  308. package/src/plugins/processor.js +0 -122
  309. package/src/public-types.d.ts +0 -1098
  310. package/src/public-types.js +0 -0
  311. package/src/route-renderer/component-graph-executor.d.ts +0 -32
  312. package/src/route-renderer/component-graph-executor.js +0 -31
  313. package/src/route-renderer/component-graph.d.ts +0 -42
  314. package/src/route-renderer/component-graph.js +0 -72
  315. package/src/route-renderer/component-marker.d.ts +0 -52
  316. package/src/route-renderer/component-marker.js +0 -46
  317. package/src/route-renderer/dependency-resolver.d.ts +0 -24
  318. package/src/route-renderer/dependency-resolver.js +0 -428
  319. package/src/route-renderer/html-post-processing.service.d.ts +0 -40
  320. package/src/route-renderer/html-post-processing.service.js +0 -86
  321. package/src/route-renderer/html-post-processing.service.ts +0 -103
  322. package/src/route-renderer/integration-renderer.d.ts +0 -339
  323. package/src/route-renderer/integration-renderer.js +0 -526
  324. package/src/route-renderer/marker-graph-resolver.d.ts +0 -76
  325. package/src/route-renderer/marker-graph-resolver.js +0 -93
  326. package/src/route-renderer/page-module-loader.d.ts +0 -61
  327. package/src/route-renderer/page-module-loader.js +0 -102
  328. package/src/route-renderer/render-execution.service.d.ts +0 -69
  329. package/src/route-renderer/render-execution.service.js +0 -91
  330. package/src/route-renderer/render-preparation.service.d.ts +0 -112
  331. package/src/route-renderer/render-preparation.service.js +0 -243
  332. package/src/route-renderer/route-renderer.d.ts +0 -26
  333. package/src/route-renderer/route-renderer.js +0 -68
  334. package/src/router/fs-router-scanner.d.ts +0 -41
  335. package/src/router/fs-router-scanner.js +0 -155
  336. package/src/router/fs-router.d.ts +0 -26
  337. package/src/router/fs-router.js +0 -100
  338. package/src/services/asset-processing-service/asset-processing.service.d.ts +0 -41
  339. package/src/services/asset-processing-service/asset-processing.service.js +0 -250
  340. package/src/services/asset-processing-service/asset.factory.d.ts +0 -17
  341. package/src/services/asset-processing-service/asset.factory.js +0 -82
  342. package/src/services/asset-processing-service/assets.types.d.ts +0 -88
  343. package/src/services/asset-processing-service/assets.types.js +0 -0
  344. package/src/services/asset-processing-service/index.d.ts +0 -3
  345. package/src/services/asset-processing-service/index.js +0 -3
  346. package/src/services/asset-processing-service/processor.interface.d.ts +0 -22
  347. package/src/services/asset-processing-service/processor.interface.js +0 -6
  348. package/src/services/asset-processing-service/processor.registry.d.ts +0 -8
  349. package/src/services/asset-processing-service/processor.registry.js +0 -15
  350. package/src/services/asset-processing-service/processors/base/base-processor.d.ts +0 -24
  351. package/src/services/asset-processing-service/processors/base/base-processor.js +0 -59
  352. package/src/services/asset-processing-service/processors/base/base-script-processor.d.ts +0 -16
  353. package/src/services/asset-processing-service/processors/base/base-script-processor.js +0 -80
  354. package/src/services/asset-processing-service/processors/index.d.ts +0 -5
  355. package/src/services/asset-processing-service/processors/index.js +0 -5
  356. package/src/services/asset-processing-service/processors/script/content-script.processor.d.ts +0 -5
  357. package/src/services/asset-processing-service/processors/script/content-script.processor.js +0 -57
  358. package/src/services/asset-processing-service/processors/script/file-script.processor.d.ts +0 -8
  359. package/src/services/asset-processing-service/processors/script/file-script.processor.js +0 -76
  360. package/src/services/asset-processing-service/processors/script/node-module-script.processor.d.ts +0 -7
  361. package/src/services/asset-processing-service/processors/script/node-module-script.processor.js +0 -74
  362. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -5
  363. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +0 -25
  364. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -9
  365. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +0 -63
  366. package/src/services/cache/cache.types.d.ts +0 -107
  367. package/src/services/cache/cache.types.js +0 -0
  368. package/src/services/cache/index.d.ts +0 -7
  369. package/src/services/cache/index.js +0 -7
  370. package/src/services/cache/memory-cache-store.d.ts +0 -42
  371. package/src/services/cache/memory-cache-store.js +0 -98
  372. package/src/services/cache/page-cache-service.d.ts +0 -70
  373. package/src/services/cache/page-cache-service.js +0 -152
  374. package/src/services/html-transformer.service.d.ts +0 -50
  375. package/src/services/html-transformer.service.js +0 -163
  376. package/src/services/html-transformer.service.ts +0 -217
  377. package/src/services/page-module-import.service.d.ts +0 -37
  378. package/src/services/page-module-import.service.js +0 -88
  379. package/src/services/page-module-import.service.ts +0 -129
  380. package/src/services/page-request-cache-coordinator.service.d.ts +0 -75
  381. package/src/services/page-request-cache-coordinator.service.js +0 -107
  382. package/src/services/schema-validation-service.d.ts +0 -122
  383. package/src/services/schema-validation-service.js +0 -101
  384. package/src/services/validation/standard-schema.types.d.ts +0 -65
  385. package/src/services/validation/standard-schema.types.js +0 -0
  386. package/src/static-site-generator/static-site-generator.d.ts +0 -57
  387. package/src/static-site-generator/static-site-generator.js +0 -272
  388. package/src/utils/css.d.ts +0 -1
  389. package/src/utils/css.js +0 -7
  390. package/src/utils/deep-merge.d.ts +0 -14
  391. package/src/utils/deep-merge.js +0 -32
  392. package/src/utils/hash.d.ts +0 -1
  393. package/src/utils/hash.js +0 -7
  394. package/src/utils/html.d.ts +0 -1
  395. package/src/utils/html.js +0 -4
  396. package/src/utils/invariant.d.ts +0 -5
  397. package/src/utils/invariant.js +0 -11
  398. package/src/utils/locals-utils.d.ts +0 -15
  399. package/src/utils/locals-utils.js +0 -24
  400. package/src/utils/parse-cli-args.d.ts +0 -24
  401. package/src/utils/parse-cli-args.js +0 -47
  402. package/src/utils/path-utils.module.d.ts +0 -5
  403. package/src/utils/path-utils.module.js +0 -14
  404. package/src/utils/runtime.d.ts +0 -11
  405. package/src/utils/runtime.js +0 -40
  406. package/src/utils/server-utils.module.d.ts +0 -19
  407. package/src/utils/server-utils.module.js +0 -56
  408. package/src/watchers/project-watcher.d.ts +0 -125
  409. package/src/watchers/project-watcher.js +0 -265
  410. package/src/watchers/project-watcher.test-helpers.d.ts +0 -4
  411. package/src/watchers/project-watcher.test-helpers.js +0 -52
  412. /package/src/route-renderer/{component-graph-executor.ts → component-graph/component-graph-executor.ts} +0 -0
  413. /package/src/route-renderer/{component-graph.ts → component-graph/component-graph.ts} +0 -0
  414. /package/src/route-renderer/{component-marker.ts → component-graph/component-marker.ts} +0 -0
  415. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.registry.ts +0 -0
  416. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/index.ts +0 -0
  417. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/content-script.processor.ts +0 -0
  418. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/content-stylesheet.processor.ts +0 -0
@@ -0,0 +1,380 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { createEcoComponentMetaPlugin } from './eco-component-meta-plugin';
3
+ import type { EcoPagesAppConfig } from '../internal-types';
4
+ import { fileSystem } from '@ecopages/file-system';
5
+
6
+ /**
7
+ * Creates a regex pattern to match __eco injection with any id hash.
8
+ * The id is a base36 hash that varies, so we match it with a pattern.
9
+ */
10
+ function ecoMetaPattern(file: string, integration: string): RegExp {
11
+ const escapedFile = file.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
12
+ return new RegExp(`__eco: \\{ id: "[a-z0-9]+", file: "${escapedFile}", integration: "${integration}" \\}`);
13
+ }
14
+
15
+ describe('eco-component-meta-plugin', () => {
16
+ const Config = {
17
+ integrations: [
18
+ {
19
+ name: 'kitajs',
20
+ extensions: ['.kita.tsx'],
21
+ },
22
+ {
23
+ name: 'react',
24
+ extensions: ['.tsx'],
25
+ },
26
+ {
27
+ name: 'ghtml',
28
+ extensions: ['.ts', '.ghtml.ts'],
29
+ },
30
+ ],
31
+ } as EcoPagesAppConfig;
32
+
33
+ const plugin = createEcoComponentMetaPlugin({ config: Config });
34
+
35
+ async function runPluginOnContent(content: string, filePath: string) {
36
+ let regexFilter: RegExp | undefined;
37
+ let onLoadCallback: any;
38
+
39
+ const buildMock = {
40
+ onLoad: (options: { filter: RegExp }, callback: any) => {
41
+ regexFilter = options.filter;
42
+ onLoadCallback = callback;
43
+ },
44
+ };
45
+
46
+ plugin.setup(buildMock as any);
47
+
48
+ if (!onLoadCallback || !regexFilter) {
49
+ throw new Error('Plugin did not register onLoad handler');
50
+ }
51
+
52
+ if (!regexFilter.test(filePath)) {
53
+ throw new Error(`File path ${filePath} does not match plugin filter ${regexFilter}`);
54
+ }
55
+
56
+ const fileSpy = vi.spyOn(fileSystem, 'readFileSync').mockImplementation(() => content);
57
+
58
+ try {
59
+ return await onLoadCallback({ path: filePath });
60
+ } finally {
61
+ fileSpy.mockRestore();
62
+ }
63
+ }
64
+
65
+ it('should inject __eco into X.config assignment in TSX files', async () => {
66
+ const content = `
67
+ MyComponent.config = {
68
+ dependencies: {}
69
+ };
70
+ `;
71
+
72
+ const result = await runPluginOnContent(content, '/path/to/component.tsx');
73
+
74
+ expect(result).toBeDefined();
75
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/component.tsx', 'react'));
76
+ });
77
+
78
+ it('should NOT inject __eco into config patterns in non-EcoComponent files', async () => {
79
+ const content = `
80
+ export const config = {
81
+ apiUrl: 'https://api.example.com',
82
+ theme: 'dark'
83
+ };
84
+ `;
85
+
86
+ const result = await runPluginOnContent(content, '/path/to/settings.tsx');
87
+
88
+ expect(result).toBeDefined();
89
+ expect(result.contents).not.toContain('__eco:');
90
+ });
91
+
92
+ it('should inject __eco into EcoComponent-typed object with config property', async () => {
93
+ const content = `
94
+ import type { EcoComponent } from '@ecopages/core';
95
+
96
+ export const LitCounter: EcoComponent = {
97
+ config: {
98
+ dependencies: {
99
+ scripts: ['lit-counter.script.ts'] } } };
100
+ `;
101
+
102
+ const result = await runPluginOnContent(content, '/path/to/lit-counter.ts');
103
+
104
+ expect(result).toBeDefined();
105
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/lit-counter.ts', 'ghtml'));
106
+ });
107
+
108
+ it('should inject __eco into eco.component() call', async () => {
109
+ const content = `
110
+ import { eco } from '@ecopages/core';
111
+ export const Counter = eco.component${'<CounterProps>'}({
112
+ dependencies: {
113
+ scripts: ['./counter.ts'] },
114
+ render: () => '${'<div>'}Counter${'</div>'}' });
115
+ `;
116
+
117
+ const result = await runPluginOnContent(content, '/path/to/counter.tsx');
118
+
119
+ expect(result).toBeDefined();
120
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/counter.tsx', 'react'));
121
+ expect(result.contents).toContain('eco.component' + '<CounterProps>({');
122
+ });
123
+
124
+ it('should inject __eco into eco.page call', async () => {
125
+ const content = `
126
+ import { eco } from '@ecopages/core';
127
+ export default eco.page({
128
+ dependencies: {
129
+ components: [] },
130
+ render: () => '${'<main>'}Page${'</main>'}' });
131
+ `;
132
+
133
+ const result = await runPluginOnContent(content, '/path/to/pages/index.tsx');
134
+
135
+ expect(result).toBeDefined();
136
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/pages/index.tsx', 'react'));
137
+ });
138
+
139
+ it('should inject __eco into eco.layout call', async () => {
140
+ const content = `
141
+ import { eco } from '@ecopages/core';
142
+ export const MainLayout = eco.layout({
143
+ render: ({ children }) => '${'<main>'}' + children + '${'</main>'}' });
144
+ `;
145
+
146
+ const result = await runPluginOnContent(content, '/path/to/layouts/main-layout.tsx');
147
+
148
+ expect(result).toBeDefined();
149
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/layouts/main-layout.tsx', 'react'));
150
+ });
151
+
152
+ it('should inject __eco into eco.html call', async () => {
153
+ const content = `
154
+ import { eco } from '@ecopages/core';
155
+ export default eco.html({
156
+ render: ({ children }) => '${'<html><body>'}' + children + '${'</body></html>'}' });
157
+ `;
158
+
159
+ const result = await runPluginOnContent(content, '/path/to/html.tsx');
160
+
161
+ expect(result).toBeDefined();
162
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/html.tsx', 'react'));
163
+ });
164
+
165
+ it('should inject __eco into eco.component() with lazy dependencies', async () => {
166
+ const content = `
167
+ export const LazyCounter = eco.component({
168
+ dependencies: {
169
+ scripts: [{ src: './counter.ts', lazy: { 'on:interaction': 'click' } }] },
170
+ render: () => '${'<div>'}Lazy${'</div>'}' });
171
+ `;
172
+
173
+ const result = await runPluginOnContent(content, '/path/to/lazy-counter.tsx');
174
+
175
+ expect(result).toBeDefined();
176
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/lazy-counter.tsx', 'react'));
177
+ });
178
+
179
+ it('should detect kitajs integration from .kita.tsx extension', async () => {
180
+ const content = `import { eco } from '@ecopages/core';
181
+ import type { PageHeadProps } from '@ecopages/core';
182
+
183
+ export const Head = eco.component<PageHeadProps<string>>({
184
+ dependencies: {
185
+ stylesheets: ['../styles/global.css'] },
186
+ render: ({ metadata, children }) => (
187
+ <head>
188
+ <meta charset="UTF-8" />
189
+ {children}
190
+ </head>
191
+ ) });`;
192
+
193
+ const result = await runPluginOnContent(content, '/path/to/includes/head.kita.tsx');
194
+
195
+ expect(result).toBeDefined();
196
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/includes/head.kita.tsx', 'kitajs'));
197
+ });
198
+
199
+ it('should handle eco.page with complex generic types', async () => {
200
+ const content = `
201
+ import { eco } from '@ecopages/core';
202
+
203
+ export default eco.page<{ title: string; callback: (arg: string) => void }>({
204
+ staticProps: async () => ({ props: { title: 'Hello', callback: () => {} } }),
205
+ render: (props) => '<div>' + props.title + '</div>' });
206
+ `;
207
+
208
+ const result = await runPluginOnContent(content, '/path/to/pages/complex.tsx');
209
+
210
+ expect(result).toBeDefined();
211
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/pages/complex.tsx', 'react'));
212
+ });
213
+
214
+ it('should handle multiple eco.component calls in same file', async () => {
215
+ const content = `
216
+ import { eco } from '@ecopages/core';
217
+
218
+ export const Button = eco.component({
219
+ render: () => '<button>Click</button>' });
220
+
221
+ export const Input = eco.component({
222
+ render: () => '<input type="text" />' });
223
+ `;
224
+
225
+ const result = await runPluginOnContent(content, '/path/to/components.tsx');
226
+
227
+ expect(result).toBeDefined();
228
+ const matches = result.contents.match(
229
+ /__eco: \{ id: "[a-z0-9]+", file: "\/path\/to\/components\.tsx", integration: "react" \},/g,
230
+ );
231
+ expect(matches).toHaveLength(2);
232
+ });
233
+
234
+ it('should handle eco.component with empty config object', async () => {
235
+ const content = `
236
+ import { eco } from '@ecopages/core';
237
+
238
+ export const Simple = eco.component({});
239
+ `;
240
+
241
+ const result = await runPluginOnContent(content, '/path/to/simple.tsx');
242
+
243
+ expect(result).toBeDefined();
244
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/simple.tsx', 'react'));
245
+ });
246
+
247
+ it('should not inject into non-eco call expressions', async () => {
248
+ const content = `
249
+ import { other } from 'some-lib';
250
+
251
+ export const Thing = other.component({
252
+ render: () => '<div>Thing</div>' });
253
+ `;
254
+
255
+ const result = await runPluginOnContent(content, '/path/to/thing.tsx');
256
+
257
+ expect(result).toBeDefined();
258
+ expect(result.contents).not.toContain('__eco:');
259
+ });
260
+
261
+ it('should not inject into non-config variable declarations', async () => {
262
+ const content = `
263
+ const settings = {
264
+ theme: 'dark',
265
+ locale: 'en' };
266
+ `;
267
+
268
+ const result = await runPluginOnContent(content, '/path/to/settings.ts');
269
+
270
+ expect(result).toBeDefined();
271
+ expect(result.contents).not.toContain('__eco:');
272
+ });
273
+
274
+ it('should handle file paths with special characters in directory', async () => {
275
+ const content = `
276
+ import { eco } from '@ecopages/core';
277
+
278
+ export default eco.page({
279
+ render: () => '<div>Page</div>' });
280
+ `;
281
+
282
+ const result = await runPluginOnContent(content, '/path/to/my-app/pages/index.tsx');
283
+
284
+ expect(result).toBeDefined();
285
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/my-app/pages/index.tsx', 'react'));
286
+ });
287
+
288
+ it('should handle eco.component with nested object in dependencies', async () => {
289
+ const content = `
290
+ import { eco } from '@ecopages/core';
291
+
292
+ export const LazyComponent = eco.component({
293
+ dependencies: {
294
+ stylesheets: ['./style.css'],
295
+ scripts: [{ src: './script.ts', lazy: { 'on:interaction': 'click' } }],
296
+ components: [] },
297
+ render: () => '<div>Lazy</div>' });
298
+ `;
299
+
300
+ const result = await runPluginOnContent(content, '/path/to/lazy.tsx');
301
+
302
+ expect(result).toBeDefined();
303
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/lazy.tsx', 'react'));
304
+ });
305
+
306
+ it('should preserve original code structure after injection', async () => {
307
+ const content = `import { eco } from '@ecopages/core';
308
+
309
+ export const Counter = eco.component({
310
+ dependencies: {
311
+ scripts: ['./counter.ts'] },
312
+ render: () => '<button>0</button>' });`;
313
+
314
+ const result = await runPluginOnContent(content, '/path/to/counter.tsx');
315
+
316
+ expect(result).toBeDefined();
317
+ expect(result.contents).toContain("import { eco } from '@ecopages/core';");
318
+ expect(result.contents).toContain("scripts: ['./counter.ts']");
319
+ expect(result.contents).toContain("render: () => '<button>0</button>'");
320
+ });
321
+
322
+ it('should handle query string in file path for cache busting', async () => {
323
+ const content = `
324
+ import { eco } from '@ecopages/core';
325
+
326
+ export default eco.page({
327
+ render: () => '<div>Page</div>' });
328
+ `;
329
+
330
+ const result = await runPluginOnContent(content, '/path/to/pages/index.tsx?update=123456');
331
+
332
+ expect(result).toBeDefined();
333
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/pages/index.tsx', 'react'));
334
+ });
335
+
336
+ describe('Regression: eco-blog views failure', () => {
337
+ it('should inject __eco into a kitajs page with complex props and no manual __eco', async () => {
338
+ const content = `import { eco } from '@ecopages/core';
339
+ import { MainLayout } from '@/layouts/main-layout.kita';
340
+ import type { Post } from '@/lib/db';
341
+
342
+ export interface BlogListProps {
343
+ posts: Post[];
344
+ }
345
+
346
+ export const BlogList = eco.page<BlogListProps>({
347
+ layout: MainLayout,
348
+ metadata: () => ({
349
+ title: 'EcoBlog | Home',
350
+ description: 'A blog about sustainability and technology' }),
351
+ render: ({ posts }) => {
352
+ return (
353
+ <div class="max-w-3xl mx-auto space-y-12">
354
+ {/* content */}
355
+ </div>
356
+ );
357
+ } });`;
358
+
359
+ const result = await runPluginOnContent(
360
+ content,
361
+ '/path/to/playground/eco-blog/src/views/blog-list.kita.tsx',
362
+ );
363
+
364
+ expect(result).toBeDefined();
365
+ expect(result.contents).toMatch(
366
+ ecoMetaPattern('/path/to/playground/eco-blog/src/views/blog-list.kita.tsx', 'kitajs'),
367
+ );
368
+ });
369
+
370
+ it('should inject __eco even if the eco call is not at the top level', async () => {
371
+ const content = `
372
+ import { eco } from '@ecopages/core';
373
+ const createPage = () => eco.page({ render: () => 'hi' });
374
+ export default createPage();
375
+ `;
376
+ const result = await runPluginOnContent(content, '/path/to/nested.tsx');
377
+ expect(result.contents).toMatch(ecoMetaPattern('/path/to/nested.tsx', 'react'));
378
+ });
379
+ });
380
+ });
@@ -163,6 +163,8 @@ export interface EcoComponentDirPluginOptions {
163
163
  * Supported patterns:
164
164
  * - `eco.page({ ... })` - Page component declarations
165
165
  * - `eco.component({ ... })` - Reusable component declarations
166
+ * - `eco.html({ ... })` - HTML shell declarations
167
+ * - `eco.layout({ ... })` - Layout declarations
166
168
  * - `Component.config = { ... }` - Config assignment pattern
167
169
  * - `config: { ... }` - Config property in object literals
168
170
  * - `export const config = { ... }` - Exported config declarations
@@ -260,6 +262,8 @@ interface Insertion {
260
262
  * |---------|---------------|---------|------------|
261
263
  * | `eco.page({...})` | CallExpression | `export default eco.page({ render: () => 'hi' })` | All |
262
264
  * | `eco.component({...})` | CallExpression | `export const Btn = eco.component({ render: () => '<button/>' })` | All |
265
+ * | `eco.html({...})` | CallExpression | `export default eco.html({ render: () => '<html />' })` | All |
266
+ * | `eco.layout({...})` | CallExpression | `export const MainLayout = eco.layout({ render: () => '<main />' })` | All |
263
267
  * | `X.config = {...}` | AssignmentExpression | `MyComponent.config = { dependencies: [] }` | All |
264
268
  * | `config: {...}` | ObjectProperty | `const X: EcoComponent = { config: {...} }` | EcoComponent-typed only |
265
269
  *
@@ -289,7 +293,7 @@ function findInjectionPoints(
289
293
  const n = node as Record<string, unknown>;
290
294
 
291
295
  /**
292
- * Pattern 1: eco.page({...}) or eco.component({...})
296
+ * Pattern 1: eco.page({...}), eco.component({...}), eco.html({...}), or eco.layout({...})
293
297
  * AST structure: CallExpression with MemberExpression callee where object is "eco"
294
298
  */
295
299
  if (n.type === 'CallExpression') {
@@ -303,11 +307,14 @@ function findInjectionPoints(
303
307
  const obj = callee.object as Record<string, unknown> | undefined;
304
308
  const prop = callee.property as Record<string, unknown> | undefined;
305
309
 
306
- /** Check: is this `eco.page(...)` or `eco.component(...)`? */
310
+ /** Check: is this `eco.page(...)`, `eco.component(...)`, `eco.html(...)`, or `eco.layout(...)`? */
307
311
  if (
308
312
  obj?.type === 'Identifier' &&
309
313
  obj?.name === 'eco' &&
310
- (prop?.name === 'page' || prop?.name === 'component')
314
+ (prop?.name === 'page' ||
315
+ prop?.name === 'component' ||
316
+ prop?.name === 'html' ||
317
+ prop?.name === 'layout')
311
318
  ) {
312
319
  /** Get the first argument - should be an object literal {...} */
313
320
  const args = n.arguments as Array<Record<string, unknown>> | undefined;
@@ -0,0 +1,111 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { IntegrationPlugin, type IntegrationPluginConfig } from './integration-plugin';
3
+ import type { IHmrManager } from '../public-types';
4
+ import type { AssetDefinition } from '../services/assets/asset-processing-service';
5
+
6
+ class TestIntegrationPlugin extends IntegrationPlugin {
7
+ renderer = vi.fn() as any;
8
+ override setup(): Promise<void> {
9
+ return Promise.resolve();
10
+ }
11
+
12
+ override teardown(): Promise<void> {
13
+ return Promise.resolve();
14
+ }
15
+ }
16
+
17
+ describe('IntegrationPlugin', () => {
18
+ let plugin: TestIntegrationPlugin;
19
+ const config: IntegrationPluginConfig = {
20
+ name: 'test-plugin',
21
+ extensions: ['.test'],
22
+ integrationDependencies: [],
23
+ };
24
+
25
+ beforeEach(() => {
26
+ plugin = new TestIntegrationPlugin(config);
27
+ });
28
+
29
+ it('should initialize with correct config values', () => {
30
+ expect(plugin.name).toBe(config.name);
31
+ expect(plugin.extensions).toEqual(config.extensions);
32
+ expect(plugin.runtimeCapability).toBeUndefined();
33
+ expect(plugin.getResolvedIntegrationDependencies()).toEqual(
34
+ config.integrationDependencies as AssetDefinition[],
35
+ );
36
+ });
37
+
38
+ it('should retain runtime capability declarations', () => {
39
+ const pluginWithRuntimeCapability = new TestIntegrationPlugin({
40
+ name: 'runtime-capable',
41
+ extensions: ['.test'],
42
+ runtimeCapability: {
43
+ tags: ['bun-only'],
44
+ minRuntimeVersion: '1.0.0',
45
+ },
46
+ });
47
+
48
+ expect(pluginWithRuntimeCapability.runtimeCapability).toEqual({
49
+ tags: ['bun-only'],
50
+ minRuntimeVersion: '1.0.0',
51
+ });
52
+ });
53
+
54
+ it('should initialize with empty dependencies if not provided', () => {
55
+ const pluginWithoutDeps = new TestIntegrationPlugin({
56
+ name: 'test',
57
+ extensions: [],
58
+ });
59
+ expect(pluginWithoutDeps.getResolvedIntegrationDependencies()).toEqual([]);
60
+ });
61
+
62
+ it('should implement setup and teardown methods', async () => {
63
+ await expect(plugin.setup()).resolves.toBeUndefined();
64
+ await expect(plugin.teardown()).resolves.toBeUndefined();
65
+ });
66
+
67
+ it('should not defer component boundaries by default', () => {
68
+ expect(
69
+ plugin.shouldDeferComponentBoundary({
70
+ currentIntegration: 'ghtml',
71
+ targetIntegration: 'react',
72
+ component: () => '<div></div>',
73
+ }),
74
+ ).toBe(false);
75
+ });
76
+
77
+ it('should register runtime specifier maps through the base HMR setup', () => {
78
+ const registerSpecifierMap = vi.fn();
79
+ const hmrManager = {
80
+ registerSpecifierMap,
81
+ registerStrategy: vi.fn(),
82
+ registerEntrypoint: vi.fn(),
83
+ registerScriptEntrypoint: vi.fn(),
84
+ setPlugins: vi.fn(),
85
+ setEnabled: vi.fn(),
86
+ isEnabled: vi.fn(() => true),
87
+ broadcast: vi.fn(),
88
+ getOutputUrl: vi.fn(),
89
+ getWatchedFiles: vi.fn(() => new Map()),
90
+ getSpecifierMap: vi.fn(() => new Map()),
91
+ getDistDir: vi.fn(() => ''),
92
+ getPlugins: vi.fn(() => []),
93
+ getDefaultContext: vi.fn(),
94
+ handleFileChange: vi.fn(),
95
+ } satisfies IHmrManager;
96
+
97
+ const pluginWithRuntimeSpecifiers = new (class extends TestIntegrationPlugin {
98
+ override getRuntimeSpecifierMap(): Record<string, string> {
99
+ return {
100
+ 'test-runtime': '/assets/vendors/test-runtime.js',
101
+ };
102
+ }
103
+ })(config);
104
+
105
+ pluginWithRuntimeSpecifiers.setHmrManager(hmrManager);
106
+
107
+ expect(registerSpecifierMap).toHaveBeenCalledWith({
108
+ 'test-runtime': '/assets/vendors/test-runtime.js',
109
+ });
110
+ });
111
+ });
@@ -2,9 +2,12 @@ import type { EcoBuildPlugin } from '../build/build-types';
2
2
  import type { EcoPagesAppConfig, IHmrManager } from '../internal-types';
3
3
  import type { HmrStrategy } from '../hmr/hmr-strategy';
4
4
  import type { EcoComponent, EcoPagesElement } from '../public-types';
5
- import type { IntegrationRenderer } from '../route-renderer/integration-renderer';
6
- import { AssetProcessingService } from '../services/asset-processing-service/asset-processing.service';
7
- import type { AssetDefinition, ProcessedAsset } from '../services/asset-processing-service/assets.types';
5
+ import type { IntegrationRenderer } from '../route-renderer/orchestration/integration-renderer';
6
+ import { AssetProcessingService } from '../services/assets/asset-processing-service/asset-processing.service';
7
+ import type { AssetDefinition, ProcessedAsset } from '../services/assets/asset-processing-service/assets.types';
8
+ import type { RuntimeCapabilityDeclaration } from './runtime-capability.ts';
9
+
10
+ export type { RuntimeCapabilityDeclaration, RuntimeCapabilityTag } from './runtime-capability.ts';
8
11
 
9
12
  export const INTEGRATION_PLUGIN_ERRORS = {
10
13
  NOT_INITIALIZED_WITH_APP_CONFIG: 'Plugin not initialized with app config',
@@ -33,6 +36,11 @@ export interface IntegrationPluginConfig {
33
36
  * @default 'render'
34
37
  */
35
38
  staticBuildStep?: 'render' | 'fetch';
39
+ /**
40
+ * Declares runtime-specific requirements that must be satisfied before the
41
+ * app can start with this integration enabled.
42
+ */
43
+ runtimeCapability?: RuntimeCapabilityDeclaration;
36
44
  }
37
45
 
38
46
  /**
@@ -59,6 +67,7 @@ export abstract class IntegrationPlugin<C = EcoPagesElement> {
59
67
  readonly extensions: string[];
60
68
  abstract renderer: RendererClass<C>;
61
69
  readonly staticBuildStep: 'render' | 'fetch';
70
+ readonly runtimeCapability?: RuntimeCapabilityDeclaration;
62
71
 
63
72
  protected integrationDependencies: AssetDefinition[];
64
73
  protected resolvedIntegrationDependencies: ProcessedAsset[] = [];
@@ -77,6 +86,7 @@ export abstract class IntegrationPlugin<C = EcoPagesElement> {
77
86
  this.extensions = config.extensions;
78
87
  this.integrationDependencies = config.integrationDependencies || [];
79
88
  this.staticBuildStep = config.staticBuildStep || 'render';
89
+ this.runtimeCapability = config.runtimeCapability;
80
90
  }
81
91
 
82
92
  setConfig(appConfig: EcoPagesAppConfig): void {
@@ -104,8 +114,26 @@ export abstract class IntegrationPlugin<C = EcoPagesElement> {
104
114
  */
105
115
  getHmrStrategy?(): HmrStrategy | undefined;
106
116
 
117
+ /**
118
+ * Returns bare-specifier mappings that should be registered in the active
119
+ * runtime specifier registry.
120
+ *
121
+ * @remarks
122
+ * Override this when the integration owns browser runtime bundles that must
123
+ * be addressable from client-side imports through stable bare specifiers.
124
+ *
125
+ * Today these mappings are consumed by the development runtime and browser
126
+ * bundle aliasing path. They are intentionally generic enough to grow into a
127
+ * broader import-map-style facility later without moving framework-specific
128
+ * map contents into core.
129
+ */
130
+ getRuntimeSpecifierMap(): Record<string, string> {
131
+ return {};
132
+ }
133
+
107
134
  setHmrManager(hmrManager: IHmrManager) {
108
135
  this.hmrManager = hmrManager;
136
+ hmrManager.registerSpecifierMap(this.getRuntimeSpecifierMap());
109
137
 
110
138
  const strategy = this.getHmrStrategy?.();
111
139
  if (strategy) {
@@ -169,6 +197,20 @@ export abstract class IntegrationPlugin<C = EcoPagesElement> {
169
197
  return false;
170
198
  }
171
199
 
200
+ /**
201
+ * Prepares build-facing contributions before the app build manifest is sealed.
202
+ *
203
+ * @remarks
204
+ * Override this when an integration needs to materialize runtime/build plugin
205
+ * declarations ahead of runtime startup. Keep runtime-only side effects out of
206
+ * this hook; they belong in `setup()`.
207
+ */
208
+ async prepareBuildContributions(): Promise<void> {}
209
+
210
+ /**
211
+ * Performs runtime-only integration setup after config build has already
212
+ * sealed manifest contributions.
213
+ */
172
214
  async setup(): Promise<void> {
173
215
  if (this.integrationDependencies.length === 0) return;
174
216
  if (!this.assetProcessingService) throw new Error(INTEGRATION_PLUGIN_ERRORS.NOT_INITIALIZED_WITH_ASSET_SERVICE);