@ecopages/core 0.2.0-alpha.26 → 0.2.0-alpha.27

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 (550) hide show
  1. package/README.md +63 -7
  2. package/package.json +73 -249
  3. package/src/adapters/abstract/application-adapter.test.ts +172 -0
  4. package/src/adapters/abstract/application-adapter.ts +379 -0
  5. package/src/adapters/abstract/router-adapter.ts +30 -0
  6. package/src/adapters/abstract/server-adapter.ts +79 -0
  7. package/src/adapters/bun/client-bridge.ts +62 -0
  8. package/src/adapters/bun/create-app.ts +232 -0
  9. package/src/adapters/bun/hmr-manager.test.ts +265 -0
  10. package/src/adapters/bun/hmr-manager.ts +383 -0
  11. package/src/adapters/bun/index.ts +2 -0
  12. package/src/adapters/bun/server-adapter.ts +526 -0
  13. package/src/adapters/bun/server-lifecycle.ts +124 -0
  14. package/src/adapters/create-app.test.ts +10 -0
  15. package/src/adapters/create-app.ts +91 -0
  16. package/src/adapters/index.ts +2 -0
  17. package/src/adapters/node/create-app.test.ts +53 -0
  18. package/src/adapters/node/create-app.ts +183 -0
  19. package/src/adapters/node/node-client-bridge.test.ts +198 -0
  20. package/src/adapters/node/node-client-bridge.ts +79 -0
  21. package/src/adapters/node/node-hmr-manager.test.ts +320 -0
  22. package/src/adapters/node/node-hmr-manager.ts +355 -0
  23. package/src/adapters/node/server-adapter.ts +502 -0
  24. package/src/adapters/node/static-content-server.test.ts +60 -0
  25. package/src/adapters/node/static-content-server.ts +239 -0
  26. package/src/adapters/shared/api-response.test.ts +97 -0
  27. package/src/adapters/shared/api-response.ts +104 -0
  28. package/src/adapters/shared/application-adapter.ts +199 -0
  29. package/src/adapters/shared/define-api-handler.ts +66 -0
  30. package/src/adapters/shared/explicit-static-render-preparation.ts +58 -0
  31. package/src/adapters/shared/explicit-static-route-matcher.test.ts +381 -0
  32. package/src/adapters/shared/explicit-static-route-matcher.ts +131 -0
  33. package/src/adapters/shared/file-route-middleware-pipeline.test.ts +85 -0
  34. package/src/adapters/shared/file-route-middleware-pipeline.ts +118 -0
  35. package/src/adapters/shared/fs-server-response-factory.test.ts +176 -0
  36. package/src/adapters/shared/fs-server-response-factory.ts +96 -0
  37. package/src/adapters/shared/fs-server-response-matcher.test.ts +311 -0
  38. package/src/adapters/shared/fs-server-response-matcher.ts +240 -0
  39. package/src/adapters/shared/hmr-entrypoint-registrar.ts +149 -0
  40. package/src/adapters/shared/hmr-html-response.ts +52 -0
  41. package/src/adapters/shared/hmr-manager.contract.test.ts +228 -0
  42. package/src/adapters/shared/hmr-manager.dispatch.test.ts +220 -0
  43. package/src/adapters/shared/render-context.test.ts +150 -0
  44. package/src/adapters/shared/render-context.ts +123 -0
  45. package/src/adapters/shared/runtime-bootstrap.ts +79 -0
  46. package/src/adapters/shared/server-adapter.test.ts +130 -0
  47. package/src/adapters/shared/server-adapter.ts +562 -0
  48. package/src/adapters/shared/server-route-handler.test.ts +111 -0
  49. package/src/adapters/shared/server-route-handler.ts +153 -0
  50. package/src/adapters/shared/server-static-builder.test.ts +338 -0
  51. package/src/adapters/shared/server-static-builder.ts +170 -0
  52. package/src/build/build-adapter-serialization.test.ts +281 -0
  53. package/src/build/build-adapter.test.ts +1240 -0
  54. package/src/build/build-adapter.ts +1012 -0
  55. package/src/build/build-manifest.ts +54 -0
  56. package/src/build/build-types.ts +83 -0
  57. package/src/build/dev-build-coordinator.ts +220 -0
  58. package/src/build/esbuild-build-adapter.ts +660 -0
  59. package/src/build/runtime-build-executor.test.ts +81 -0
  60. package/src/build/runtime-build-executor.ts +40 -0
  61. package/src/build/runtime-specifier-alias-plugin.test.ts +67 -0
  62. package/src/build/runtime-specifier-alias-plugin.ts +62 -0
  63. package/src/build/runtime-specifier-aliases.ts +135 -0
  64. package/src/config/README.md +1 -1
  65. package/src/config/config-builder.test.ts +442 -0
  66. package/src/config/config-builder.ts +737 -0
  67. package/src/config/config-builder.typecheck.test.ts +96 -0
  68. package/src/config/{constants.d.ts → constants.ts} +22 -13
  69. package/src/dev/host-runtime.ts +34 -0
  70. package/src/dev/sc-server.ts +143 -0
  71. package/src/eco/eco.browser.test.ts +43 -0
  72. package/src/eco/eco.browser.ts +118 -0
  73. package/src/eco/eco.test.ts +654 -0
  74. package/src/eco/eco.ts +205 -0
  75. package/src/eco/eco.types.ts +221 -0
  76. package/src/eco/eco.utils.test.ts +219 -0
  77. package/src/eco/eco.utils.ts +5 -0
  78. package/src/eco/global-injector-map.test.ts +42 -0
  79. package/src/eco/global-injector-map.ts +112 -0
  80. package/src/eco/lazy-injector-map.test.ts +66 -0
  81. package/src/eco/lazy-injector-map.ts +120 -0
  82. package/src/eco/module-dependencies.test.ts +30 -0
  83. package/src/eco/module-dependencies.ts +75 -0
  84. package/src/errors/http-error.test.ts +134 -0
  85. package/src/errors/http-error.ts +72 -0
  86. package/src/errors/index.ts +3 -0
  87. package/src/errors/locals-access-error.ts +7 -0
  88. package/src/global/app-logger.ts +4 -0
  89. package/src/global/utils.test.ts +12 -0
  90. 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
  91. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-load-fixture-app-page-1.png +0 -0
  92. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-WebSocket-Connection-should-connect-to-correct-HMR-endpoint-1.png +0 -0
  93. package/src/hmr/client/hmr-runtime.ts +162 -0
  94. package/src/hmr/hmr-strategy.test.ts +124 -0
  95. package/src/hmr/hmr-strategy.ts +177 -0
  96. package/src/hmr/hmr.postcss.test.e2e.ts +41 -0
  97. package/src/hmr/hmr.test.e2e.ts +66 -0
  98. package/src/hmr/strategies/default-hmr-strategy.ts +60 -0
  99. package/src/hmr/strategies/js-hmr-strategy.test.ts +334 -0
  100. package/src/hmr/strategies/js-hmr-strategy.ts +314 -0
  101. package/src/index.browser.ts +3 -0
  102. package/src/index.ts +15 -0
  103. package/src/integrations/ghtml/ghtml-renderer.test.ts +253 -0
  104. package/src/integrations/ghtml/ghtml-renderer.ts +87 -0
  105. package/src/integrations/ghtml/ghtml.constants.ts +1 -0
  106. package/src/integrations/ghtml/ghtml.plugin.ts +28 -0
  107. package/src/plugins/alias-resolver-plugin.test.ts +41 -0
  108. package/src/plugins/alias-resolver-plugin.ts +63 -0
  109. package/src/plugins/eco-component-meta-plugin.test.ts +406 -0
  110. package/src/plugins/eco-component-meta-plugin.ts +494 -0
  111. package/src/plugins/foreign-jsx-override-plugin.test.ts +65 -0
  112. package/src/plugins/foreign-jsx-override-plugin.ts +67 -0
  113. package/src/plugins/integration-plugin.test.ts +151 -0
  114. package/src/plugins/integration-plugin.ts +323 -0
  115. package/src/plugins/processor.test.ts +148 -0
  116. package/src/plugins/processor.ts +257 -0
  117. package/src/plugins/{runtime-capability.d.ts → runtime-capability.ts} +8 -3
  118. package/src/plugins/source-transform.test.ts +82 -0
  119. package/src/plugins/source-transform.ts +123 -0
  120. package/src/route-renderer/GRAPH.md +81 -289
  121. package/src/route-renderer/README.md +67 -105
  122. package/src/route-renderer/orchestration/component-render-context.ts +325 -0
  123. package/src/route-renderer/orchestration/declared-ownership-graph.ts +62 -0
  124. package/src/route-renderer/orchestration/foreign-subtree-execution.service.ts +383 -0
  125. package/src/route-renderer/orchestration/integration-renderer.test.ts +2085 -0
  126. package/src/route-renderer/orchestration/integration-renderer.ts +1244 -0
  127. package/src/route-renderer/orchestration/ownership-planning.service.ts +97 -0
  128. package/src/route-renderer/orchestration/ownership-validation.service.ts +76 -0
  129. package/src/route-renderer/orchestration/processed-asset-dedupe.ts +25 -0
  130. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.test.ts +324 -0
  131. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.ts +294 -0
  132. package/src/route-renderer/orchestration/render-output.utils.ts +310 -0
  133. package/src/route-renderer/orchestration/route-render-orchestrator.prepare-render-options.test.ts +644 -0
  134. package/src/route-renderer/orchestration/route-render-orchestrator.test.ts +265 -0
  135. package/src/route-renderer/orchestration/route-render-orchestrator.ts +592 -0
  136. package/src/route-renderer/orchestration/template-serialization.test.ts +110 -0
  137. package/src/route-renderer/orchestration/template-serialization.ts +117 -0
  138. package/src/route-renderer/page-loading/component-dependency-collection.ts +202 -0
  139. package/src/route-renderer/page-loading/declared-asset-collection.ts +153 -0
  140. package/src/route-renderer/page-loading/dependency-resolver.test.ts +761 -0
  141. package/src/route-renderer/page-loading/dependency-resolver.ts +144 -0
  142. package/src/route-renderer/page-loading/ecopages-virtual-imports.ts +75 -0
  143. package/src/route-renderer/page-loading/lazy-entry-collection.ts +167 -0
  144. package/src/route-renderer/page-loading/lazy-trigger-planning.ts +74 -0
  145. package/src/route-renderer/page-loading/module-declaration-aggregation.ts +60 -0
  146. package/src/route-renderer/page-loading/module-declaration-scripts.ts +16 -0
  147. package/src/route-renderer/page-loading/page-dependency-bundling.ts +244 -0
  148. package/src/route-renderer/page-loading/page-module-loader.test.ts +183 -0
  149. package/src/route-renderer/page-loading/page-module-loader.ts +184 -0
  150. package/src/route-renderer/route-renderer.ts +133 -0
  151. package/src/router/README.md +16 -19
  152. package/src/router/client/link-intent.test.browser.ts +51 -0
  153. package/src/router/client/link-intent.ts +92 -0
  154. package/src/router/client/navigation-coordinator.test.ts +237 -0
  155. package/src/router/client/navigation-coordinator.ts +453 -0
  156. package/src/router/server/route-registry.test.ts +176 -0
  157. package/src/router/server/route-registry.ts +382 -0
  158. package/src/services/README.md +1 -2
  159. package/src/services/assets/asset-processing-service/asset-dependency-keys.ts +66 -0
  160. package/src/services/assets/asset-processing-service/asset-processing.service.test.ts +473 -0
  161. package/src/services/assets/asset-processing-service/asset-processing.service.ts +344 -0
  162. package/src/services/assets/asset-processing-service/asset.factory.test.ts +63 -0
  163. package/src/services/assets/asset-processing-service/asset.factory.ts +105 -0
  164. package/src/services/assets/asset-processing-service/assets.types.ts +128 -0
  165. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.test.ts +74 -0
  166. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.ts +96 -0
  167. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.test.ts +67 -0
  168. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.ts +78 -0
  169. package/src/services/assets/asset-processing-service/grouped-content-bundles.ts +104 -0
  170. package/src/services/assets/asset-processing-service/index.ts +6 -0
  171. package/src/services/assets/asset-processing-service/page-package.test.ts +100 -0
  172. package/src/services/assets/asset-processing-service/page-package.ts +93 -0
  173. package/src/services/assets/asset-processing-service/{processor.interface.d.ts → processor.interface.ts} +10 -5
  174. package/src/services/assets/asset-processing-service/processor.registry.ts +18 -0
  175. package/src/services/assets/asset-processing-service/processors/base/base-processor.test.ts +59 -0
  176. package/src/services/assets/asset-processing-service/processors/base/base-processor.ts +83 -0
  177. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.ts +173 -0
  178. package/src/services/assets/asset-processing-service/processors/index.ts +5 -0
  179. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.test.ts +195 -0
  180. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.ts +137 -0
  181. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.test.ts +326 -0
  182. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.ts +116 -0
  183. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.test.ts +227 -0
  184. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.ts +89 -0
  185. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.test.ts +261 -0
  186. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +72 -0
  187. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +83 -0
  188. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.ts +65 -0
  189. package/src/services/assets/browser-bundle.service.test.ts +66 -0
  190. package/src/services/assets/browser-bundle.service.ts +109 -0
  191. package/src/services/cache/cache.types.ts +126 -0
  192. package/src/services/cache/index.ts +18 -0
  193. package/src/services/cache/memory-cache-store.test.ts +225 -0
  194. package/src/services/cache/memory-cache-store.ts +130 -0
  195. package/src/services/cache/page-cache-service.test.ts +175 -0
  196. package/src/services/cache/page-cache-service.ts +202 -0
  197. package/src/services/cache/page-request-cache-coordinator.service.test.ts +79 -0
  198. package/src/services/cache/page-request-cache-coordinator.service.ts +131 -0
  199. package/src/services/html/html-rewriter-provider.service.test.ts +183 -0
  200. package/src/services/html/html-rewriter-provider.service.ts +104 -0
  201. package/src/services/html/html-transformer.service.test.ts +476 -0
  202. package/src/services/html/html-transformer.service.ts +275 -0
  203. package/src/services/invalidation/development-invalidation.service.test.ts +87 -0
  204. package/src/services/invalidation/development-invalidation.service.ts +262 -0
  205. package/src/services/module-loading/app-module-loader.service.ts +9 -0
  206. package/src/services/module-loading/app-server-module-transpiler.service.test.ts +130 -0
  207. package/src/services/module-loading/app-server-module-transpiler.service.ts +141 -0
  208. package/src/services/module-loading/host-module-loader-registry.ts +15 -0
  209. package/src/services/module-loading/{module-loading-types.d.ts → module-loading-types.ts} +1 -0
  210. package/src/services/module-loading/node-bootstrap-plugin.test.ts +335 -0
  211. package/src/services/module-loading/node-bootstrap-plugin.ts +311 -0
  212. package/src/services/module-loading/page-module-import.service.test.ts +504 -0
  213. package/src/services/module-loading/page-module-import.service.ts +251 -0
  214. package/src/services/module-loading/server-module-transpiler.service.test.ts +243 -0
  215. package/src/services/module-loading/server-module-transpiler.service.ts +104 -0
  216. package/src/services/module-loading/source-module-support.ts +19 -0
  217. package/src/services/runtime-state/dev-graph.service.ts +217 -0
  218. package/src/services/runtime-state/entrypoint-dependency-graph.service.ts +136 -0
  219. package/src/services/runtime-state/server-invalidation-state.service.ts +68 -0
  220. package/src/services/validation/schema-validation-service.test.ts +223 -0
  221. package/src/services/validation/schema-validation-service.ts +204 -0
  222. package/src/services/validation/{standard-schema.types.d.ts → standard-schema.types.ts} +20 -17
  223. package/src/static-site-generator/static-site-generator.test.ts +408 -0
  224. package/src/static-site-generator/static-site-generator.ts +445 -0
  225. package/src/types/internal-types.ts +243 -0
  226. package/src/types/public-types.ts +1459 -0
  227. package/src/utils/deep-merge.test.ts +114 -0
  228. package/src/utils/deep-merge.ts +47 -0
  229. package/src/utils/hash.ts +5 -0
  230. package/src/utils/html-escaping.ts +9 -0
  231. package/src/utils/invariant.test.ts +22 -0
  232. package/src/utils/invariant.ts +15 -0
  233. package/src/utils/locals-utils.ts +37 -0
  234. package/src/utils/parse-cli-args.test.ts +69 -0
  235. package/src/utils/parse-cli-args.ts +105 -0
  236. package/src/utils/path-utils.module.ts +14 -0
  237. package/src/utils/path-utils.test.ts +15 -0
  238. package/src/utils/resolve-work-dir.ts +45 -0
  239. package/src/utils/runtime.ts +44 -0
  240. package/src/utils/server-utils.module.ts +67 -0
  241. package/src/utils/server-utils.test.ts +38 -0
  242. package/src/watchers/project-watcher.integration.test.ts +337 -0
  243. package/src/watchers/project-watcher.test-helpers.ts +42 -0
  244. package/src/watchers/project-watcher.test.ts +768 -0
  245. package/src/watchers/project-watcher.ts +357 -0
  246. package/CHANGELOG.md +0 -66
  247. package/src/adapters/abstract/application-adapter.d.ts +0 -194
  248. package/src/adapters/abstract/application-adapter.js +0 -121
  249. package/src/adapters/abstract/router-adapter.d.ts +0 -26
  250. package/src/adapters/abstract/router-adapter.js +0 -5
  251. package/src/adapters/abstract/server-adapter.d.ts +0 -69
  252. package/src/adapters/abstract/server-adapter.js +0 -15
  253. package/src/adapters/bun/client-bridge.d.ts +0 -34
  254. package/src/adapters/bun/client-bridge.js +0 -48
  255. package/src/adapters/bun/create-app.d.ts +0 -52
  256. package/src/adapters/bun/create-app.js +0 -116
  257. package/src/adapters/bun/hmr-manager.d.ts +0 -143
  258. package/src/adapters/bun/hmr-manager.js +0 -333
  259. package/src/adapters/bun/index.d.ts +0 -2
  260. package/src/adapters/bun/index.js +0 -8
  261. package/src/adapters/bun/server-adapter.d.ts +0 -155
  262. package/src/adapters/bun/server-adapter.js +0 -374
  263. package/src/adapters/bun/server-lifecycle.d.ts +0 -63
  264. package/src/adapters/bun/server-lifecycle.js +0 -92
  265. package/src/adapters/create-app.d.ts +0 -20
  266. package/src/adapters/create-app.js +0 -66
  267. package/src/adapters/index.d.ts +0 -2
  268. package/src/adapters/index.js +0 -8
  269. package/src/adapters/node/create-app.d.ts +0 -18
  270. package/src/adapters/node/create-app.js +0 -149
  271. package/src/adapters/node/node-client-bridge.d.ts +0 -26
  272. package/src/adapters/node/node-client-bridge.js +0 -66
  273. package/src/adapters/node/node-hmr-manager.d.ts +0 -133
  274. package/src/adapters/node/node-hmr-manager.js +0 -311
  275. package/src/adapters/node/server-adapter.d.ts +0 -162
  276. package/src/adapters/node/server-adapter.js +0 -368
  277. package/src/adapters/node/static-content-server.d.ts +0 -60
  278. package/src/adapters/node/static-content-server.js +0 -194
  279. package/src/adapters/shared/api-response.d.ts +0 -52
  280. package/src/adapters/shared/api-response.js +0 -96
  281. package/src/adapters/shared/application-adapter.d.ts +0 -18
  282. package/src/adapters/shared/application-adapter.js +0 -90
  283. package/src/adapters/shared/define-api-handler.d.ts +0 -25
  284. package/src/adapters/shared/define-api-handler.js +0 -15
  285. package/src/adapters/shared/explicit-static-route-matcher.d.ts +0 -38
  286. package/src/adapters/shared/explicit-static-route-matcher.js +0 -103
  287. package/src/adapters/shared/file-route-middleware-pipeline.d.ts +0 -65
  288. package/src/adapters/shared/file-route-middleware-pipeline.js +0 -99
  289. package/src/adapters/shared/fs-server-response-factory.d.ts +0 -19
  290. package/src/adapters/shared/fs-server-response-factory.js +0 -97
  291. package/src/adapters/shared/fs-server-response-matcher.d.ts +0 -67
  292. package/src/adapters/shared/fs-server-response-matcher.js +0 -147
  293. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +0 -55
  294. package/src/adapters/shared/hmr-entrypoint-registrar.js +0 -87
  295. package/src/adapters/shared/hmr-html-response.d.ts +0 -22
  296. package/src/adapters/shared/hmr-html-response.js +0 -32
  297. package/src/adapters/shared/render-context.d.ts +0 -15
  298. package/src/adapters/shared/render-context.js +0 -72
  299. package/src/adapters/shared/runtime-bootstrap.d.ts +0 -38
  300. package/src/adapters/shared/runtime-bootstrap.js +0 -43
  301. package/src/adapters/shared/server-adapter.d.ts +0 -97
  302. package/src/adapters/shared/server-adapter.js +0 -390
  303. package/src/adapters/shared/server-route-handler.d.ts +0 -89
  304. package/src/adapters/shared/server-route-handler.js +0 -111
  305. package/src/adapters/shared/server-static-builder.d.ts +0 -71
  306. package/src/adapters/shared/server-static-builder.js +0 -100
  307. package/src/build/build-adapter.d.ts +0 -239
  308. package/src/build/build-adapter.js +0 -642
  309. package/src/build/build-manifest.d.ts +0 -27
  310. package/src/build/build-manifest.js +0 -30
  311. package/src/build/build-types.d.ts +0 -57
  312. package/src/build/build-types.js +0 -0
  313. package/src/build/dev-build-coordinator.d.ts +0 -72
  314. package/src/build/dev-build-coordinator.js +0 -154
  315. package/src/build/esbuild-build-adapter.d.ts +0 -78
  316. package/src/build/esbuild-build-adapter.js +0 -505
  317. package/src/build/runtime-build-executor.d.ts +0 -14
  318. package/src/build/runtime-build-executor.js +0 -22
  319. package/src/build/runtime-specifier-alias-plugin.d.ts +0 -15
  320. package/src/build/runtime-specifier-alias-plugin.js +0 -35
  321. package/src/build/runtime-specifier-aliases.d.ts +0 -5
  322. package/src/build/runtime-specifier-aliases.js +0 -95
  323. package/src/config/config-builder.d.ts +0 -252
  324. package/src/config/config-builder.js +0 -603
  325. package/src/config/constants.js +0 -25
  326. package/src/dev/sc-server.d.ts +0 -30
  327. package/src/dev/sc-server.js +0 -111
  328. package/src/eco/eco.browser.d.ts +0 -2
  329. package/src/eco/eco.browser.js +0 -83
  330. package/src/eco/eco.d.ts +0 -9
  331. package/src/eco/eco.js +0 -85
  332. package/src/eco/eco.types.d.ts +0 -178
  333. package/src/eco/eco.types.js +0 -0
  334. package/src/eco/eco.utils.d.ts +0 -1
  335. package/src/eco/eco.utils.js +0 -10
  336. package/src/eco/global-injector-map.d.ts +0 -16
  337. package/src/eco/global-injector-map.js +0 -80
  338. package/src/eco/lazy-injector-map.d.ts +0 -8
  339. package/src/eco/lazy-injector-map.js +0 -70
  340. package/src/eco/module-dependencies.d.ts +0 -18
  341. package/src/eco/module-dependencies.js +0 -49
  342. package/src/errors/http-error.d.ts +0 -31
  343. package/src/errors/http-error.js +0 -50
  344. package/src/errors/index.d.ts +0 -2
  345. package/src/errors/index.js +0 -4
  346. package/src/errors/locals-access-error.d.ts +0 -4
  347. package/src/errors/locals-access-error.js +0 -9
  348. package/src/global/app-logger.d.ts +0 -2
  349. package/src/global/app-logger.js +0 -6
  350. package/src/hmr/client/hmr-runtime.d.ts +0 -5
  351. package/src/hmr/client/hmr-runtime.js +0 -117
  352. package/src/hmr/hmr-strategy.d.ts +0 -162
  353. package/src/hmr/hmr-strategy.js +0 -44
  354. package/src/hmr/hmr.postcss.test.e2e.d.ts +0 -1
  355. package/src/hmr/hmr.postcss.test.e2e.js +0 -31
  356. package/src/hmr/hmr.test.e2e.d.ts +0 -1
  357. package/src/hmr/hmr.test.e2e.js +0 -43
  358. package/src/hmr/strategies/default-hmr-strategy.d.ts +0 -43
  359. package/src/hmr/strategies/default-hmr-strategy.js +0 -34
  360. package/src/hmr/strategies/js-hmr-strategy.d.ts +0 -139
  361. package/src/hmr/strategies/js-hmr-strategy.js +0 -178
  362. package/src/index.browser.d.ts +0 -3
  363. package/src/index.browser.js +0 -4
  364. package/src/index.d.ts +0 -6
  365. package/src/index.js +0 -21
  366. package/src/integrations/ghtml/ghtml-renderer.d.ts +0 -20
  367. package/src/integrations/ghtml/ghtml-renderer.js +0 -63
  368. package/src/integrations/ghtml/ghtml.constants.d.ts +0 -1
  369. package/src/integrations/ghtml/ghtml.constants.js +0 -4
  370. package/src/integrations/ghtml/ghtml.plugin.d.ts +0 -16
  371. package/src/integrations/ghtml/ghtml.plugin.js +0 -20
  372. package/src/plugins/alias-resolver-plugin.d.ts +0 -2
  373. package/src/plugins/alias-resolver-plugin.js +0 -53
  374. package/src/plugins/eco-component-meta-plugin.d.ts +0 -108
  375. package/src/plugins/eco-component-meta-plugin.js +0 -163
  376. package/src/plugins/foreign-jsx-override-plugin.d.ts +0 -31
  377. package/src/plugins/foreign-jsx-override-plugin.js +0 -35
  378. package/src/plugins/integration-plugin.d.ts +0 -219
  379. package/src/plugins/integration-plugin.js +0 -196
  380. package/src/plugins/processor.d.ts +0 -95
  381. package/src/plugins/processor.js +0 -136
  382. package/src/plugins/runtime-capability.js +0 -0
  383. package/src/plugins/source-transform.d.ts +0 -46
  384. package/src/plugins/source-transform.js +0 -71
  385. package/src/route-renderer/orchestration/boundary-planning.service.d.ts +0 -25
  386. package/src/route-renderer/orchestration/boundary-planning.service.js +0 -97
  387. package/src/route-renderer/orchestration/component-render-context.d.ts +0 -83
  388. package/src/route-renderer/orchestration/component-render-context.js +0 -147
  389. package/src/route-renderer/orchestration/integration-renderer.d.ts +0 -556
  390. package/src/route-renderer/orchestration/integration-renderer.js +0 -932
  391. package/src/route-renderer/orchestration/page-packaging.service.d.ts +0 -16
  392. package/src/route-renderer/orchestration/page-packaging.service.js +0 -66
  393. package/src/route-renderer/orchestration/processed-asset-dedupe.d.ts +0 -2
  394. package/src/route-renderer/orchestration/processed-asset-dedupe.js +0 -23
  395. package/src/route-renderer/orchestration/queued-boundary-runtime.service.d.ts +0 -89
  396. package/src/route-renderer/orchestration/queued-boundary-runtime.service.js +0 -155
  397. package/src/route-renderer/orchestration/render-execution.service.d.ts +0 -43
  398. package/src/route-renderer/orchestration/render-execution.service.js +0 -106
  399. package/src/route-renderer/orchestration/render-output.utils.d.ts +0 -66
  400. package/src/route-renderer/orchestration/render-output.utils.js +0 -171
  401. package/src/route-renderer/orchestration/render-preparation.service.d.ts +0 -120
  402. package/src/route-renderer/orchestration/render-preparation.service.js +0 -364
  403. package/src/route-renderer/orchestration/route-shell-composer.service.d.ts +0 -50
  404. package/src/route-renderer/orchestration/route-shell-composer.service.js +0 -81
  405. package/src/route-renderer/orchestration/template-serialization.d.ts +0 -38
  406. package/src/route-renderer/orchestration/template-serialization.js +0 -45
  407. package/src/route-renderer/page-loading/component-dependency-collection.d.ts +0 -37
  408. package/src/route-renderer/page-loading/component-dependency-collection.js +0 -125
  409. package/src/route-renderer/page-loading/declared-asset-collection.d.ts +0 -24
  410. package/src/route-renderer/page-loading/declared-asset-collection.js +0 -106
  411. package/src/route-renderer/page-loading/dependency-resolver.d.ts +0 -35
  412. package/src/route-renderer/page-loading/dependency-resolver.js +0 -117
  413. package/src/route-renderer/page-loading/ecopages-virtual-imports.d.ts +0 -11
  414. package/src/route-renderer/page-loading/ecopages-virtual-imports.js +0 -57
  415. package/src/route-renderer/page-loading/lazy-entry-collection.d.ts +0 -45
  416. package/src/route-renderer/page-loading/lazy-entry-collection.js +0 -105
  417. package/src/route-renderer/page-loading/lazy-trigger-planning.d.ts +0 -19
  418. package/src/route-renderer/page-loading/lazy-trigger-planning.js +0 -40
  419. package/src/route-renderer/page-loading/module-declaration-aggregation.d.ts +0 -5
  420. package/src/route-renderer/page-loading/module-declaration-aggregation.js +0 -33
  421. package/src/route-renderer/page-loading/module-declaration-scripts.d.ts +0 -3
  422. package/src/route-renderer/page-loading/module-declaration-scripts.js +0 -18
  423. package/src/route-renderer/page-loading/page-dependency-bundling.d.ts +0 -13
  424. package/src/route-renderer/page-loading/page-dependency-bundling.js +0 -115
  425. package/src/route-renderer/page-loading/page-module-loader.d.ts +0 -90
  426. package/src/route-renderer/page-loading/page-module-loader.js +0 -127
  427. package/src/route-renderer/route-renderer.d.ts +0 -67
  428. package/src/route-renderer/route-renderer.js +0 -103
  429. package/src/router/client/link-intent.js +0 -34
  430. package/src/router/client/link-intent.test.browser.d.ts +0 -1
  431. package/src/router/client/link-intent.test.browser.js +0 -43
  432. package/src/router/client/navigation-coordinator.d.ts +0 -169
  433. package/src/router/client/navigation-coordinator.js +0 -215
  434. package/src/router/server/fs-router-scanner.d.ts +0 -41
  435. package/src/router/server/fs-router-scanner.js +0 -161
  436. package/src/router/server/fs-router.d.ts +0 -26
  437. package/src/router/server/fs-router.js +0 -100
  438. package/src/services/assets/asset-processing-service/asset-dependency-keys.d.ts +0 -3
  439. package/src/services/assets/asset-processing-service/asset-dependency-keys.js +0 -56
  440. package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +0 -103
  441. package/src/services/assets/asset-processing-service/asset-processing.service.js +0 -285
  442. package/src/services/assets/asset-processing-service/asset.factory.d.ts +0 -17
  443. package/src/services/assets/asset-processing-service/asset.factory.js +0 -82
  444. package/src/services/assets/asset-processing-service/assets.types.d.ts +0 -100
  445. package/src/services/assets/asset-processing-service/assets.types.js +0 -0
  446. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +0 -55
  447. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +0 -49
  448. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +0 -20
  449. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +0 -41
  450. package/src/services/assets/asset-processing-service/grouped-content-bundles.d.ts +0 -30
  451. package/src/services/assets/asset-processing-service/grouped-content-bundles.js +0 -65
  452. package/src/services/assets/asset-processing-service/index.d.ts +0 -5
  453. package/src/services/assets/asset-processing-service/index.js +0 -5
  454. package/src/services/assets/asset-processing-service/processor.interface.js +0 -6
  455. package/src/services/assets/asset-processing-service/processor.registry.d.ts +0 -8
  456. package/src/services/assets/asset-processing-service/processor.registry.js +0 -15
  457. package/src/services/assets/asset-processing-service/processors/base/base-processor.d.ts +0 -24
  458. package/src/services/assets/asset-processing-service/processors/base/base-processor.js +0 -65
  459. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +0 -22
  460. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +0 -136
  461. package/src/services/assets/asset-processing-service/processors/index.d.ts +0 -5
  462. package/src/services/assets/asset-processing-service/processors/index.js +0 -5
  463. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +0 -6
  464. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +0 -116
  465. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -9
  466. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +0 -91
  467. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.d.ts +0 -7
  468. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +0 -77
  469. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -8
  470. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +0 -58
  471. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -9
  472. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +0 -67
  473. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.d.ts +0 -18
  474. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.js +0 -45
  475. package/src/services/assets/browser-bundle.service.d.ts +0 -73
  476. package/src/services/assets/browser-bundle.service.js +0 -41
  477. package/src/services/cache/cache.types.d.ts +0 -107
  478. package/src/services/cache/cache.types.js +0 -0
  479. package/src/services/cache/index.d.ts +0 -7
  480. package/src/services/cache/index.js +0 -7
  481. package/src/services/cache/memory-cache-store.d.ts +0 -42
  482. package/src/services/cache/memory-cache-store.js +0 -98
  483. package/src/services/cache/page-cache-service.d.ts +0 -70
  484. package/src/services/cache/page-cache-service.js +0 -152
  485. package/src/services/cache/page-request-cache-coordinator.service.d.ts +0 -75
  486. package/src/services/cache/page-request-cache-coordinator.service.js +0 -109
  487. package/src/services/html/html-rewriter-provider.service.d.ts +0 -37
  488. package/src/services/html/html-rewriter-provider.service.js +0 -68
  489. package/src/services/html/html-transformer.service.d.ts +0 -87
  490. package/src/services/html/html-transformer.service.js +0 -216
  491. package/src/services/invalidation/development-invalidation.service.d.ts +0 -74
  492. package/src/services/invalidation/development-invalidation.service.js +0 -190
  493. package/src/services/module-loading/app-module-loader.service.d.ts +0 -7
  494. package/src/services/module-loading/app-module-loader.service.js +0 -0
  495. package/src/services/module-loading/app-server-module-transpiler.service.d.ts +0 -24
  496. package/src/services/module-loading/app-server-module-transpiler.service.js +0 -115
  497. package/src/services/module-loading/host-module-loader-registry.d.ts +0 -4
  498. package/src/services/module-loading/host-module-loader-registry.js +0 -15
  499. package/src/services/module-loading/module-loading-types.js +0 -0
  500. package/src/services/module-loading/node-bootstrap-plugin.d.ts +0 -42
  501. package/src/services/module-loading/node-bootstrap-plugin.js +0 -204
  502. package/src/services/module-loading/page-module-import.service.d.ts +0 -76
  503. package/src/services/module-loading/page-module-import.service.js +0 -170
  504. package/src/services/module-loading/server-module-transpiler.service.d.ts +0 -63
  505. package/src/services/module-loading/server-module-transpiler.service.js +0 -64
  506. package/src/services/module-loading/source-module-support.d.ts +0 -5
  507. package/src/services/module-loading/source-module-support.js +0 -8
  508. package/src/services/runtime-state/dev-graph.service.d.ts +0 -118
  509. package/src/services/runtime-state/dev-graph.service.js +0 -162
  510. package/src/services/runtime-state/entrypoint-dependency-graph.service.d.ts +0 -41
  511. package/src/services/runtime-state/entrypoint-dependency-graph.service.js +0 -85
  512. package/src/services/runtime-state/runtime-specifier-registry.service.d.ts +0 -69
  513. package/src/services/runtime-state/runtime-specifier-registry.service.js +0 -37
  514. package/src/services/runtime-state/server-invalidation-state.service.d.ts +0 -26
  515. package/src/services/runtime-state/server-invalidation-state.service.js +0 -35
  516. package/src/services/validation/schema-validation-service.d.ts +0 -122
  517. package/src/services/validation/schema-validation-service.js +0 -101
  518. package/src/services/validation/standard-schema.types.js +0 -0
  519. package/src/static-site-generator/static-site-generator.d.ts +0 -105
  520. package/src/static-site-generator/static-site-generator.js +0 -349
  521. package/src/types/internal-types.d.ts +0 -231
  522. package/src/types/internal-types.js +0 -0
  523. package/src/types/public-types.d.ts +0 -1257
  524. package/src/types/public-types.js +0 -0
  525. package/src/utils/deep-merge.d.ts +0 -14
  526. package/src/utils/deep-merge.js +0 -32
  527. package/src/utils/hash.d.ts +0 -1
  528. package/src/utils/hash.js +0 -7
  529. package/src/utils/html-escaping.d.ts +0 -7
  530. package/src/utils/html-escaping.js +0 -6
  531. package/src/utils/html.js +0 -4
  532. package/src/utils/invariant.d.ts +0 -5
  533. package/src/utils/invariant.js +0 -11
  534. package/src/utils/locals-utils.d.ts +0 -15
  535. package/src/utils/locals-utils.js +0 -24
  536. package/src/utils/parse-cli-args.d.ts +0 -27
  537. package/src/utils/parse-cli-args.js +0 -62
  538. package/src/utils/path-utils.module.d.ts +0 -5
  539. package/src/utils/path-utils.module.js +0 -14
  540. package/src/utils/resolve-work-dir.d.ts +0 -11
  541. package/src/utils/resolve-work-dir.js +0 -31
  542. package/src/utils/runtime.d.ts +0 -11
  543. package/src/utils/runtime.js +0 -40
  544. package/src/utils/server-utils.module.d.ts +0 -19
  545. package/src/utils/server-utils.module.js +0 -56
  546. package/src/watchers/project-watcher.d.ts +0 -136
  547. package/src/watchers/project-watcher.js +0 -275
  548. package/src/watchers/project-watcher.test-helpers.d.ts +0 -4
  549. package/src/watchers/project-watcher.test-helpers.js +0 -52
  550. /package/src/utils/{html.d.ts → html.ts} +0 -0
@@ -0,0 +1,133 @@
1
+ import type { EcoPagesAppConfig } from '../types/internal-types.ts';
2
+ import type { IntegrationPlugin } from '../plugins/integration-plugin.ts';
3
+ import { invariant } from '../utils/invariant.ts';
4
+ import { PathUtils } from '../utils/path-utils.module.ts';
5
+ import type { IntegrationRenderer } from './orchestration/integration-renderer.ts';
6
+
7
+ /**
8
+ * Narrow route-render contract exposed to higher-level routing code.
9
+ *
10
+ * @remarks
11
+ * Higher-level routing code only needs request execution and page-module
12
+ * loading. Returning this narrowed shape avoids a dedicated wrapper class while
13
+ * still keeping callers off the full integration renderer surface.
14
+ */
15
+ export type PageRouteRenderer = Pick<IntegrationRenderer, 'execute' | 'loadPageModule'>;
16
+
17
+ /**
18
+ * Narrow explicit-view render contract exposed to static route handling.
19
+ *
20
+ * @remarks
21
+ * Explicit static routes only need `renderToResponse()`, so the factory can
22
+ * hide the broader integration renderer surface there as well.
23
+ */
24
+ export type ExplicitViewRenderer = Pick<IntegrationRenderer, 'renderToResponse'>;
25
+
26
+ export interface PageRendererResolver {
27
+ getPageRenderer(filePath: string): PageRouteRenderer;
28
+ }
29
+
30
+ export interface ExplicitViewRendererResolver {
31
+ getExplicitViewRenderer(integrationName: string): ExplicitViewRenderer | null;
32
+ }
33
+
34
+ /**
35
+ * Combined renderer-factory contract used by static generation.
36
+ */
37
+ export type StaticGenerationRendererResolver = PageRendererResolver & ExplicitViewRendererResolver;
38
+
39
+ /**
40
+ * Selects and caches integration renderers for route files and explicit views.
41
+ *
42
+ * @remarks
43
+ * The factory owns the policy that maps a route file or explicit integration
44
+ * name to one initialized integration renderer. Renderer instances are cached by
45
+ * integration name so repeated requests do not rebuild renderer state.
46
+ */
47
+ export class RouteRendererFactory {
48
+ private appConfig: EcoPagesAppConfig;
49
+ runtimeOrigin: string;
50
+ private rendererModules?: unknown;
51
+ private rendererCache = new Map<string, IntegrationRenderer>();
52
+
53
+ /**
54
+ * Creates the route-renderer factory for one app/runtime instance.
55
+ */
56
+ constructor({
57
+ appConfig,
58
+ rendererModules,
59
+ runtimeOrigin,
60
+ }: {
61
+ appConfig: EcoPagesAppConfig;
62
+ rendererModules?: unknown;
63
+ runtimeOrigin: string;
64
+ }) {
65
+ this.appConfig = appConfig;
66
+ this.rendererModules = rendererModules;
67
+ this.runtimeOrigin = runtimeOrigin;
68
+ }
69
+
70
+ /**
71
+ * Returns a route renderer for the supplied route file.
72
+ */
73
+ getPageRenderer(filePath: string): PageRouteRenderer {
74
+ const integrationRenderer = this.getRouteRendererEngine(filePath);
75
+ invariant(!!integrationRenderer, `No integration renderer found for file: ${filePath}`);
76
+ return integrationRenderer;
77
+ }
78
+
79
+ /**
80
+ * Returns a renderer for an explicit view integration.
81
+ */
82
+ getExplicitViewRenderer(integrationName: string): ExplicitViewRenderer | null {
83
+ const integrationPlugin = this.appConfig.integrations.find((plugin) => plugin.name === integrationName);
84
+ if (!integrationPlugin) {
85
+ return null;
86
+ }
87
+
88
+ const cached = this.rendererCache.get(integrationName);
89
+ if (cached) {
90
+ return cached;
91
+ }
92
+
93
+ const renderer = integrationPlugin.initializeRenderer({
94
+ rendererModules: this.rendererModules,
95
+ });
96
+ this.rendererCache.set(integrationName, renderer);
97
+ return renderer;
98
+ }
99
+
100
+ /**
101
+ * Resolves the integration plugin that owns a given route file.
102
+ */
103
+ getIntegrationPlugin(filePath: string): IntegrationPlugin {
104
+ const templateExtension = PathUtils.getEcoTemplateExtension(filePath);
105
+ const isIntegrationPlugin = (plugin: IntegrationPlugin): boolean => {
106
+ return plugin.extensions.some((extension) => templateExtension === extension);
107
+ };
108
+ const integrationPlugin = this.appConfig.integrations.find(isIntegrationPlugin);
109
+ invariant(
110
+ !!integrationPlugin,
111
+ `No integration plugin found for template extension: ${templateExtension}, file: ${filePath}`,
112
+ );
113
+ return integrationPlugin as IntegrationPlugin;
114
+ }
115
+
116
+ /**
117
+ * Returns the cached renderer engine for the file's owning integration,
118
+ * creating it on first use.
119
+ */
120
+ private getRouteRendererEngine(filePath: string): IntegrationRenderer {
121
+ const integrationPlugin = this.getIntegrationPlugin(filePath);
122
+ const cached = this.rendererCache.get(integrationPlugin.name);
123
+ if (cached) {
124
+ return cached;
125
+ }
126
+
127
+ const renderer = integrationPlugin.initializeRenderer({
128
+ rendererModules: this.rendererModules,
129
+ });
130
+ this.rendererCache.set(integrationPlugin.name, renderer);
131
+ return renderer;
132
+ }
133
+ }
@@ -8,9 +8,9 @@ The router layer determines what route is being handled and how the client runti
8
8
 
9
9
  It is responsible for:
10
10
 
11
- - filesystem route scanning and classification (`exact`, `dynamic`, `catch-all`)
12
- - matching incoming request URLs to discovered routes
13
- - server-side static-path expansion for dynamic routes
11
+ - filesystem route discovery and classification (`exact`, `dynamic`, `catch-all`)
12
+ - matching incoming request URLs to canonical template routes
13
+ - server-side static-path expansion for dynamic template routes
14
14
  - client-side navigation ownership and cross-runtime handoff
15
15
  - keeping route discovery separate from rendering execution
16
16
 
@@ -18,9 +18,8 @@ It is responsible for:
18
18
 
19
19
  ```
20
20
  router/
21
- ├── server/ # Server-side route scanning and matching
22
- ├── fs-router-scanner.ts # Scans the filesystem and classifies routes
23
- │ └── fs-router.ts # Matches request URLs to discovered routes
21
+ ├── server/ # Server-side route discovery and matching
22
+ └── route-registry.ts # Owns template routes, request matching, static expansion, and reload
24
23
  └── client/ # Browser-side navigation coordination
25
24
  ├── navigation-coordinator.ts # Singleton runtime coordinator
26
25
  └── link-intent.ts # Shared anchor detection and intent recovery helpers
@@ -28,9 +27,9 @@ router/
28
27
 
29
28
  ## `server/`
30
29
 
31
- ### `FSRouterScanner`
30
+ ### `RouteRegistry`
32
31
 
33
- Walks the pages directory and builds a `Routes` map keyed by route pathname.
32
+ Owns the canonical set of filesystem-discovered template routes for one application.
34
33
 
35
34
  File patterns determine route kind:
36
35
 
@@ -40,13 +39,17 @@ File patterns determine route kind:
40
39
  | `[slug].tsx` | `dynamic` | `/blog/[slug]` |
41
40
  | `[...slug].tsx` | `catch-all` | `/docs/[...slug]` |
42
41
 
43
- For `dynamic` routes, the scanner checks whether the page module exports `getStaticPaths`. If present, every returned path is expanded into a concrete `exact`-style route at scan time. In build mode, both `getStaticPaths` and `getStaticProps` are required or an invariant is thrown.
42
+ The registry stores canonical template routes only. It compiles request-time matching metadata during `init()` and `reload()`, but it does not execute `staticPaths()` during discovery.
44
43
 
45
- Catch-all routes are registered but skipped during static generation with a warning.
44
+ Build-time static expansion is a separate operation. The registry invokes `staticPaths()` lazily through an injected page-module adapter and returns concrete static path expansions for the static generator.
46
45
 
47
- ### `FSRouter`
46
+ The public interface is intentionally small:
48
47
 
49
- Holds the scanned `Routes` map and exposes a `match(requestUrl)` method used by adapters.
48
+ - `templateRoutes` ordered readonly template routes
49
+ - `init()` / `reload()` — rebuild discovery state and match metadata
50
+ - `matchRequest(requestUrl)` — request-time matching result with requested pathname, matched template route, params, and query
51
+ - `listStaticPathExpansions()` — build-time expansion for dynamic routes
52
+ - `listStaticGenerationRoutes()` — build-time route planning for static generation across exact and expanded routes
50
53
 
51
54
  Match priority:
52
55
 
@@ -54,12 +57,6 @@ Match priority:
54
57
  2. `dynamic` — the clean (bracket-stripped) prefix must appear in the pathname, and the segment counts must match.
55
58
  3. `catch-all` — the clean prefix must appear in the pathname.
56
59
 
57
- Additional helpers:
58
-
59
- - `getDynamicParams(route, pathname)` — extracts named and spread parameters from a matched dynamic or catch-all route.
60
- - `getSearchParams(url)` — converts `URLSearchParams` to a plain object.
61
- - `setOnReload(cb)` / `reload()` — re-scans routes and fires an optional callback, used during development HMR.
62
-
63
60
  ## `client/`
64
61
 
65
62
  ### Navigation Coordinator (`navigation-coordinator.ts`)
@@ -69,7 +66,7 @@ A singleton browser-side runtime stored on `window.__ECO_PAGES__.navigation`.
69
66
  Access it with:
70
67
 
71
68
  ```ts
72
- import { getEcoNavigationRuntime } from '@ecopages/core/router/client/navigation-coordinator';
69
+ import { getEcoNavigationRuntime } from '@ecopages/core/router/navigation-coordinator';
73
70
  const runtime = getEcoNavigationRuntime();
74
71
  ```
75
72
 
@@ -0,0 +1,51 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getAnchorFromNavigationEvent, recoverPendingNavigationHref } from './link-intent.ts';
3
+
4
+ describe('getAnchorFromNavigationEvent', () => {
5
+ it('returns the anchor when the event target is a text node inside it', () => {
6
+ const anchor = document.createElement('a');
7
+ anchor.href = '/fast';
8
+ anchor.setAttribute('data-eco-link', 'true');
9
+ const textNode = document.createTextNode('fast-link');
10
+ anchor.append(textNode);
11
+ document.body.append(anchor);
12
+
13
+ const event = new MouseEvent('click', { bubbles: true, cancelable: true, composed: true });
14
+ Object.defineProperty(event, 'target', {
15
+ configurable: true,
16
+ value: textNode,
17
+ });
18
+
19
+ expect(getAnchorFromNavigationEvent(event, 'a[data-eco-link]')).toBe(anchor);
20
+ });
21
+
22
+ it('returns the closest matching anchor for nested element targets', () => {
23
+ const anchor = document.createElement('a');
24
+ anchor.href = '/fast';
25
+ anchor.setAttribute('data-eco-link', 'true');
26
+ const span = document.createElement('span');
27
+ span.textContent = 'fast-link';
28
+ anchor.append(span);
29
+ document.body.append(anchor);
30
+
31
+ const event = new MouseEvent('click', { bubbles: true, cancelable: true, composed: true });
32
+ Object.defineProperty(event, 'target', {
33
+ configurable: true,
34
+ value: span,
35
+ });
36
+
37
+ expect(getAnchorFromNavigationEvent(event, 'a[data-eco-link]')).toBe(anchor);
38
+ });
39
+ });
40
+
41
+ describe('recoverPendingNavigationHref', () => {
42
+ it('returns null for stale or missing pending intent state', () => {
43
+ expect(recoverPendingNavigationHref(null, true, 10)).toBeNull();
44
+ expect(recoverPendingNavigationHref({ href: '/fast', timestamp: 0 }, false, 10)).toBeNull();
45
+ expect(recoverPendingNavigationHref({ href: '/fast', timestamp: 0 }, true, 2000, 1000)).toBeNull();
46
+ });
47
+
48
+ it('returns the captured href while a navigation is still in flight', () => {
49
+ expect(recoverPendingNavigationHref({ href: '/fast', timestamp: 10 }, true, 20, 1000)).toBe('/fast');
50
+ });
51
+ });
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Shared client-side navigation intent helpers.
3
+ *
4
+ * Browser runtimes use the same low-level mechanics to:
5
+ * - locate the anchor associated with a click, pointer, or hover event,
6
+ * - persist the last valid pointer or hover target while a navigation is in flight,
7
+ * - recover the final intended href when the DOM changes before the click lands.
8
+ *
9
+ * Keeping those mechanics here lets browser-router and react-router share one
10
+ * implementation while preserving their router-specific interception rules.
11
+ *
12
+ * @module
13
+ */
14
+
15
+ /**
16
+ * Timestamped navigation intent captured from pointer or hover activity.
17
+ */
18
+ export type EcoPendingNavigationIntent = {
19
+ href: string;
20
+ timestamp: number;
21
+ };
22
+
23
+ /**
24
+ * Finds the nearest matching anchor within an event's composed path.
25
+ *
26
+ * This works across Shadow DOM boundaries, which is required for delegated
27
+ * navigation handling when links are rendered inside custom elements.
28
+ *
29
+ * @param event - Pointer or mouse event being inspected.
30
+ * @param linkSelector - Selector that identifies navigable anchors.
31
+ * @returns The matched anchor element, or `null` when no matching anchor exists.
32
+ */
33
+ export function getAnchorFromNavigationEvent(
34
+ event: MouseEvent | PointerEvent,
35
+ linkSelector: string,
36
+ ): HTMLAnchorElement | null {
37
+ const eventTarget = event.target;
38
+
39
+ if (eventTarget instanceof HTMLAnchorElement && eventTarget.matches(linkSelector)) {
40
+ return eventTarget;
41
+ }
42
+
43
+ if (eventTarget instanceof Element) {
44
+ const closestAnchor = eventTarget.closest(linkSelector);
45
+ if (closestAnchor instanceof HTMLAnchorElement) {
46
+ return closestAnchor;
47
+ }
48
+ }
49
+
50
+ if (eventTarget instanceof Text) {
51
+ const parentAnchor = eventTarget.parentElement?.closest(linkSelector);
52
+ if (parentAnchor instanceof HTMLAnchorElement) {
53
+ return parentAnchor;
54
+ }
55
+ }
56
+
57
+ return event
58
+ .composedPath()
59
+ .find(
60
+ (target) => target instanceof HTMLAnchorElement && target.matches(linkSelector),
61
+ ) as HTMLAnchorElement | null;
62
+ }
63
+
64
+ /**
65
+ * Resolves a previously captured intent while a navigation is still in flight.
66
+ *
67
+ * Pending intents expire quickly because they are only meant to bridge the gap
68
+ * between pointer or hover capture and the later click event when the DOM or
69
+ * active runtime changes during a rapid navigation sequence.
70
+ *
71
+ * @param intent - Previously captured pointer or hover intent.
72
+ * @param hasInFlightNavigation - Whether a router navigation is still active.
73
+ * @param now - Current monotonic timestamp, usually from `performance.now()`.
74
+ * @param maxAgeMs - Maximum allowed age for the recovered intent.
75
+ * @returns The intended href when still valid, otherwise `null`.
76
+ */
77
+ export function recoverPendingNavigationHref(
78
+ intent: EcoPendingNavigationIntent | null,
79
+ hasInFlightNavigation: boolean,
80
+ now: number,
81
+ maxAgeMs = 1000,
82
+ ): string | null {
83
+ if (!intent || !hasInFlightNavigation) {
84
+ return null;
85
+ }
86
+
87
+ if (now - intent.timestamp > maxAgeMs) {
88
+ return null;
89
+ }
90
+
91
+ return intent.href;
92
+ }
@@ -0,0 +1,237 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { getEcoNavigationRuntime } from './navigation-coordinator.ts';
3
+
4
+ function createWindowLike() {
5
+ return {} as Window &
6
+ typeof globalThis & {
7
+ __ECO_PAGES__?: { navigation?: ReturnType<typeof getEcoNavigationRuntime> };
8
+ };
9
+ }
10
+
11
+ describe('getEcoNavigationRuntime', () => {
12
+ it('returns the same coordinator instance for the same window', () => {
13
+ const windowLike = createWindowLike();
14
+ const first = getEcoNavigationRuntime(windowLike);
15
+ const second = getEcoNavigationRuntime(windowLike);
16
+
17
+ expect(first).toBe(second);
18
+ });
19
+
20
+ it('tracks explicit ownership claims', () => {
21
+ const windowLike = createWindowLike();
22
+ const runtime = getEcoNavigationRuntime(windowLike);
23
+
24
+ runtime.claimOwnership('react-router');
25
+
26
+ expect(runtime.getOwnerState()).toEqual({
27
+ owner: 'react-router',
28
+ canHandleSpaNavigation: false,
29
+ });
30
+ });
31
+
32
+ it('shares one navigation transaction sequence across runtimes', () => {
33
+ const windowLike = createWindowLike();
34
+ const runtime = getEcoNavigationRuntime(windowLike);
35
+
36
+ const first = runtime.beginNavigationTransaction();
37
+ expect(runtime.hasPendingNavigationTransaction()).toBe(true);
38
+ expect(first.isCurrent()).toBe(true);
39
+ expect(first.signal.aborted).toBe(false);
40
+
41
+ const second = runtime.beginNavigationTransaction();
42
+
43
+ expect(first.isCurrent()).toBe(false);
44
+ expect(first.signal.aborted).toBe(true);
45
+ expect(second.isCurrent()).toBe(true);
46
+ expect(second.signal.aborted).toBe(false);
47
+ second.complete();
48
+ expect(runtime.hasPendingNavigationTransaction()).toBe(false);
49
+ });
50
+
51
+ it('cancels only the current navigation transaction', () => {
52
+ const windowLike = createWindowLike();
53
+ const runtime = getEcoNavigationRuntime(windowLike);
54
+
55
+ const first = runtime.beginNavigationTransaction();
56
+ const second = runtime.beginNavigationTransaction();
57
+
58
+ first.cancel();
59
+ expect(second.isCurrent()).toBe(true);
60
+ expect(second.signal.aborted).toBe(false);
61
+
62
+ second.cancel();
63
+ expect(second.isCurrent()).toBe(false);
64
+ expect(second.signal.aborted).toBe(true);
65
+ expect(runtime.hasPendingNavigationTransaction()).toBe(false);
66
+ });
67
+
68
+ it('adopts ownership from the rendered document marker', () => {
69
+ const windowLike = createWindowLike();
70
+ const runtime = getEcoNavigationRuntime(windowLike);
71
+ const documentLike = {
72
+ documentElement: {
73
+ getAttribute: vi.fn(() => 'custom-router'),
74
+ },
75
+ } as unknown as Document;
76
+
77
+ expect(runtime.adoptDocumentOwner(documentLike, 'browser-router')).toBe('custom-router');
78
+ expect(runtime.getOwnerState().owner).toBe('custom-router');
79
+ });
80
+
81
+ it('delegates navigation to another registered runtime when the source cannot handle it', async () => {
82
+ const windowLike = createWindowLike();
83
+ const runtime = getEcoNavigationRuntime(windowLike);
84
+ const navigateSpy = vi.fn(async () => true);
85
+
86
+ runtime.register({ owner: 'browser-router', navigate: navigateSpy });
87
+ runtime.register({ owner: 'react-router', navigate: vi.fn(async () => true) });
88
+ runtime.claimOwnership('react-router');
89
+
90
+ const handled = await runtime.requestNavigation({
91
+ href: '/docs',
92
+ direction: 'forward',
93
+ source: 'react-router',
94
+ });
95
+
96
+ expect(handled).toBe(true);
97
+ expect(navigateSpy).toHaveBeenCalledWith({
98
+ href: '/docs',
99
+ direction: 'forward',
100
+ source: 'react-router',
101
+ });
102
+ });
103
+
104
+ it('delegates a fetched document handoff to the targeted runtime without forcing source cleanup first', async () => {
105
+ const windowLike = createWindowLike();
106
+ const runtime = getEcoNavigationRuntime(windowLike);
107
+ const cleanupSpy = vi.fn(async () => undefined);
108
+ const handoffSpy = vi.fn(async () => true);
109
+ const documentLike = {
110
+ documentElement: {
111
+ getAttribute: vi.fn(() => null),
112
+ },
113
+ } as unknown as Document;
114
+
115
+ runtime.register({ owner: 'react-router', cleanupBeforeHandoff: cleanupSpy });
116
+ runtime.register({ owner: 'browser-router', handoffNavigation: handoffSpy });
117
+ runtime.claimOwnership('react-router');
118
+
119
+ const handled = await runtime.requestHandoff({
120
+ href: '/docs',
121
+ finalHref: '/docs',
122
+ direction: 'forward',
123
+ source: 'react-router',
124
+ targetOwner: 'browser-router',
125
+ document: documentLike,
126
+ });
127
+
128
+ expect(handled).toBe(true);
129
+ expect(cleanupSpy).not.toHaveBeenCalled();
130
+ expect(handoffSpy).toHaveBeenCalledWith({
131
+ href: '/docs',
132
+ finalHref: '/docs',
133
+ direction: 'forward',
134
+ source: 'react-router',
135
+ targetOwner: 'browser-router',
136
+ document: documentLike,
137
+ });
138
+ });
139
+
140
+ it('ignores stale handoff requests before cleaning up the active owner', async () => {
141
+ const windowLike = createWindowLike();
142
+ const runtime = getEcoNavigationRuntime(windowLike);
143
+ const cleanupSpy = vi.fn(async () => undefined);
144
+ const handoffSpy = vi.fn(async () => true);
145
+ const documentLike = {
146
+ documentElement: {
147
+ getAttribute: vi.fn(() => null),
148
+ },
149
+ } as unknown as Document;
150
+
151
+ runtime.register({ owner: 'react-router', cleanupBeforeHandoff: cleanupSpy });
152
+ runtime.register({ owner: 'browser-router', handoffNavigation: handoffSpy });
153
+ runtime.claimOwnership('react-router');
154
+
155
+ const handled = await runtime.requestHandoff({
156
+ href: '/docs',
157
+ finalHref: '/docs',
158
+ direction: 'forward',
159
+ source: 'react-router',
160
+ targetOwner: 'browser-router',
161
+ document: documentLike,
162
+ isStaleSourceNavigation: () => true,
163
+ });
164
+
165
+ expect(handled).toBe(true);
166
+ expect(cleanupSpy).not.toHaveBeenCalled();
167
+ expect(handoffSpy).not.toHaveBeenCalled();
168
+ expect(runtime.getOwnerState().owner).toBe('react-router');
169
+ });
170
+
171
+ it('reloads the current owner through its registration', async () => {
172
+ const windowLike = createWindowLike();
173
+ const runtime = getEcoNavigationRuntime(windowLike);
174
+ const reloadSpy = vi.fn(async () => undefined);
175
+
176
+ runtime.register({ owner: 'react-router', reloadCurrentPage: reloadSpy });
177
+ runtime.claimOwnership('react-router');
178
+
179
+ const handled = await runtime.reloadCurrentPage({ clearCache: true, source: 'browser-router' });
180
+
181
+ expect(handled).toBe(true);
182
+ expect(reloadSpy).toHaveBeenCalledWith({ clearCache: true, source: 'browser-router' });
183
+ });
184
+
185
+ it('reloads the current owner even when the request source matches that owner', async () => {
186
+ const windowLike = createWindowLike();
187
+ const runtime = getEcoNavigationRuntime(windowLike);
188
+ const reloadSpy = vi.fn(async () => undefined);
189
+
190
+ runtime.register({ owner: 'react-router', reloadCurrentPage: reloadSpy });
191
+ runtime.claimOwnership('react-router');
192
+
193
+ const handled = await runtime.reloadCurrentPage({ clearCache: false, source: 'react-router' });
194
+
195
+ expect(handled).toBe(true);
196
+ expect(reloadSpy).toHaveBeenCalledWith({ clearCache: false, source: 'react-router' });
197
+ });
198
+
199
+ it('cleans up an explicit owner via its registration', async () => {
200
+ const windowLike = createWindowLike();
201
+ const runtime = getEcoNavigationRuntime(windowLike);
202
+ const cleanupSpy = vi.fn();
203
+
204
+ runtime.register({ owner: 'react-router', cleanupBeforeHandoff: cleanupSpy });
205
+ runtime.claimOwnership('react-router');
206
+
207
+ await runtime.cleanupOwner('react-router');
208
+
209
+ expect(cleanupSpy).toHaveBeenCalledTimes(1);
210
+ expect(runtime.getOwnerState().owner).toBe('none');
211
+ });
212
+
213
+ it('emits events for registrations and ownership changes', () => {
214
+ const windowLike = createWindowLike();
215
+ const runtime = getEcoNavigationRuntime(windowLike);
216
+ const listener = vi.fn();
217
+ const unsubscribe = runtime.subscribe(listener);
218
+
219
+ const unregister = runtime.register({ owner: 'custom-router' });
220
+ runtime.claimOwnership('custom-router');
221
+ runtime.releaseOwnership('custom-router');
222
+ unregister();
223
+ unsubscribe();
224
+
225
+ expect(listener).toHaveBeenCalledWith({
226
+ type: 'registration-change',
227
+ owner: 'custom-router',
228
+ status: 'registered',
229
+ });
230
+ expect(listener).toHaveBeenCalledWith({
231
+ type: 'owner-change',
232
+ owner: 'custom-router',
233
+ previousOwner: 'none',
234
+ reason: 'claim',
235
+ });
236
+ });
237
+ });