@ecopages/core 0.2.0-beta.31 → 0.2.0-beta.33

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 (343) hide show
  1. package/README.md +1 -0
  2. package/package.json +90 -3
  3. package/src/adapters/abstract/application-adapter.d.ts +0 -8
  4. package/src/adapters/abstract/application-adapter.js +252 -261
  5. package/src/adapters/abstract/router-adapter.js +12 -4
  6. package/src/adapters/abstract/segment-path-matcher.js +132 -134
  7. package/src/adapters/abstract/server-adapter.js +22 -14
  8. package/src/adapters/abstract/ws-pattern-matcher.js +24 -26
  9. package/src/adapters/bun/bun-user-websocket-lifecycle.js +83 -86
  10. package/src/adapters/bun/client-bridge.js +51 -50
  11. package/src/adapters/bun/create-app.js +171 -161
  12. package/src/adapters/bun/hmr-manager.js +62 -57
  13. package/src/adapters/bun/index.js +2 -31
  14. package/src/adapters/bun/runtime-host.js +61 -54
  15. package/src/adapters/bun/server-adapter.d.ts +0 -1
  16. package/src/adapters/bun/server-adapter.js +561 -561
  17. package/src/adapters/bun/static-preview-host.js +43 -46
  18. package/src/adapters/create-app.js +11 -14
  19. package/src/adapters/index.js +2 -30
  20. package/src/adapters/node/create-app.js +123 -129
  21. package/src/adapters/node/http-request-bridge.js +147 -106
  22. package/src/adapters/node/node-client-bridge.js +62 -64
  23. package/src/adapters/node/node-hmr-manager.js +58 -48
  24. package/src/adapters/node/runtime-host.js +96 -89
  25. package/src/adapters/node/server-adapter-dependencies.js +18 -21
  26. package/src/adapters/node/server-adapter.d.ts +0 -1
  27. package/src/adapters/node/server-adapter.js +347 -326
  28. package/src/adapters/node/static-content-server.js +172 -191
  29. package/src/adapters/node/static-preview-host.js +87 -78
  30. package/src/adapters/shared/hmr/dev-transform-entrypoint-registry.d.ts +16 -0
  31. package/src/adapters/shared/hmr/dev-transform-entrypoint-registry.js +32 -0
  32. package/src/adapters/shared/hmr/hmr-html-response.js +46 -32
  33. package/src/adapters/shared/hmr/shared-hmr-manager.d.ts +29 -38
  34. package/src/adapters/shared/hmr/shared-hmr-manager.js +439 -425
  35. package/src/adapters/shared/http/api-request-pipeline.js +122 -119
  36. package/src/adapters/shared/http/api-response.js +77 -77
  37. package/src/adapters/shared/http/create-body-response.js +22 -19
  38. package/src/adapters/shared/http/define-api-handler.js +41 -55
  39. package/src/adapters/shared/http/explicit-static-render-preparation.js +26 -23
  40. package/src/adapters/shared/http/explicit-static-route-matcher.js +55 -62
  41. package/src/adapters/shared/http/file-route-middleware-pipeline.js +81 -75
  42. package/src/adapters/shared/http/fs-server-response-factory.js +101 -96
  43. package/src/adapters/shared/http/fs-server-response-matcher.js +239 -257
  44. package/src/adapters/shared/http/run-middleware-chain.js +15 -15
  45. package/src/adapters/shared/runtime/application-adapter.js +72 -87
  46. package/src/adapters/shared/runtime/copy-runtime-public-dir.js +25 -22
  47. package/src/adapters/shared/runtime/port-manager.js +207 -177
  48. package/src/adapters/shared/runtime/render-context.js +94 -79
  49. package/src/adapters/shared/runtime/runtime-app-bootstrap.js +33 -38
  50. package/src/adapters/shared/runtime/runtime-host.js +1 -0
  51. package/src/adapters/shared/runtime/runtime-server-lifecycle.d.ts +2 -3
  52. package/src/adapters/shared/runtime/runtime-server-lifecycle.js +65 -51
  53. package/src/adapters/shared/runtime/server-adapter.d.ts +1 -0
  54. package/src/adapters/shared/runtime/server-adapter.js +233 -217
  55. package/src/adapters/shared/runtime/server-route-handler.js +74 -70
  56. package/src/adapters/shared/runtime/server-static-builder.js +165 -184
  57. package/src/adapters/shared/runtime/static-preview-host.js +1 -0
  58. package/src/adapters/shared/ws/node-http-websocket-upgrades.js +97 -88
  59. package/src/adapters/shared/ws/websocket-lifecycle.js +57 -50
  60. package/src/build/README.md +52 -1
  61. package/src/build/app-build-manifest-runtime.js +129 -108
  62. package/src/build/browser/browser-runtime-manifest.js +47 -50
  63. package/src/build/browser/browser-runtime-plugin-helpers.js +32 -12
  64. package/src/build/browser/browser-runtime-plugin.js +206 -160
  65. package/src/build/browser/jsx-ownership-plugins.js +51 -37
  66. package/src/build/browser/lit-static-render-worker-context.js +3 -5
  67. package/src/build/build-adapter.js +276 -139
  68. package/src/build/cache/build-input-fingerprint.js +28 -26
  69. package/src/build/cache/cache-constants.js +4 -6
  70. package/src/build/cache/cache-keys.js +64 -56
  71. package/src/build/cache/pages-unified-graph-build.js +179 -178
  72. package/src/build/cache/production-build-cache.js +47 -54
  73. package/src/build/cache/server-entry-build-cache.js +134 -146
  74. package/src/build/contracts/build-contracts.d.ts +4 -4
  75. package/src/build/contracts/build-contracts.js +1 -0
  76. package/src/build/contracts/build-manifest.js +58 -43
  77. package/src/build/contracts/build-types.js +1 -0
  78. package/src/build/rolldown/rolldown-adapter-helpers.d.ts +9 -0
  79. package/src/build/rolldown/rolldown-adapter-helpers.js +405 -298
  80. package/src/build/rolldown/rolldown-build-adapter.js +53 -61
  81. package/src/build/rolldown/rolldown-build-invocation-metrics.js +31 -35
  82. package/src/build/rolldown/rolldown-plugin-bridge.js +264 -194
  83. package/src/build/rolldown/rolldown-source-transform-pass.js +59 -50
  84. package/src/build/rolldown/runtime-build-output-normalizer.js +227 -175
  85. package/src/build/rolldown/server-side-css-shim-plugin.js +54 -31
  86. package/src/build/runtime/build-profile-options.js +36 -36
  87. package/src/build/runtime/build-request-identity.js +70 -45
  88. package/src/build/runtime/build-request-policy.js +80 -42
  89. package/src/build/runtime/build-runtime.js +64 -54
  90. package/src/build/runtime/deduping-build-executor.js +38 -32
  91. package/src/build/runtime/parallel-build-executor.js +58 -50
  92. package/src/build/runtime/serialized-build-executor.js +78 -62
  93. package/src/cache/index.js +6 -6
  94. package/src/cache/module-parse-cache.js +99 -68
  95. package/src/client/navigation-scripts/classification.js +45 -37
  96. package/src/client/navigation-scripts/index.js +3 -23
  97. package/src/client/navigation-scripts/navigation-scripts.test.browser.js +58 -62
  98. package/src/client/navigation-scripts/registry.js +15 -11
  99. package/src/client/navigation-scripts/rerun-queue.js +81 -64
  100. package/src/client/scroll.js +32 -24
  101. package/src/client/scroll.test.browser.js +27 -33
  102. package/src/client/view-transitions.js +68 -55
  103. package/src/config/config-builder.d.ts +8 -0
  104. package/src/config/config-builder.js +637 -642
  105. package/src/config/constants.js +44 -24
  106. package/src/declarations.d.ts +1 -0
  107. package/src/dev/README.md +24 -0
  108. package/src/dev/client-bridge-registry.js +7 -12
  109. package/src/dev/dev-client-ownership.js +7 -5
  110. package/src/dev/hmr-manager-registry.js +7 -12
  111. package/src/dev/host-runtime.js +25 -30
  112. package/src/dev/runtime-server-started-message.js +2 -5
  113. package/src/dev/sc-server.js +106 -103
  114. package/src/dev/transform-server/dev-transform-bundler.d.ts +24 -0
  115. package/src/dev/transform-server/dev-transform-bundler.js +79 -0
  116. package/src/dev/transform-server/dev-transform-externalize-plugin.d.ts +12 -0
  117. package/src/dev/transform-server/dev-transform-externalize-plugin.js +29 -0
  118. package/src/dev/transform-server/dev-transform-import-rewriter.d.ts +16 -0
  119. package/src/dev/transform-server/dev-transform-import-rewriter.js +110 -0
  120. package/src/dev/transform-server/dev-transform-module-kind.d.ts +13 -0
  121. package/src/dev/transform-server/dev-transform-module-kind.js +17 -0
  122. package/src/dev/transform-server/dev-transform-runtime-specifiers.d.ts +5 -0
  123. package/src/dev/transform-server/dev-transform-runtime-specifiers.js +16 -0
  124. package/src/dev/transform-server/dev-transform-server.d.ts +41 -0
  125. package/src/dev/transform-server/dev-transform-server.js +191 -0
  126. package/src/dev/transform-server/dev-transform-url.d.ts +13 -0
  127. package/src/dev/transform-server/dev-transform-url.js +58 -0
  128. package/src/dev/transform-server/dev-transform-vendor-registry.d.ts +27 -0
  129. package/src/dev/transform-server/dev-transform-vendor-registry.js +145 -0
  130. package/src/dev/transform-server/index.d.ts +6 -0
  131. package/src/dev/transform-server/index.js +4 -0
  132. package/src/dev/transform-server/types.d.ts +15 -0
  133. package/src/dev/transform-server/types.js +1 -0
  134. package/src/dev-toolbar/README.md +51 -0
  135. package/src/dev-toolbar/define-dev-tool.d.ts +21 -0
  136. package/src/dev-toolbar/define-dev-tool.js +9 -0
  137. package/src/dev-toolbar/dev-toolbar-config.d.ts +25 -0
  138. package/src/dev-toolbar/dev-toolbar-config.js +19 -0
  139. package/src/dev-toolbar/dev-toolbar-host.d.ts +49 -0
  140. package/src/dev-toolbar/dev-toolbar-host.js +117 -0
  141. package/src/dev-toolbar/dev-toolbar-html-response.d.ts +11 -0
  142. package/src/dev-toolbar/dev-toolbar-html-response.js +14 -0
  143. package/src/dev-toolbar/dev-toolbar-manifest.d.ts +15 -0
  144. package/src/dev-toolbar/dev-toolbar-manifest.js +52 -0
  145. package/src/dev-toolbar/dev-toolbar-package.d.ts +31 -0
  146. package/src/dev-toolbar/dev-toolbar-package.js +72 -0
  147. package/src/dev-toolbar/dev-toolbar-runtime-paths.d.ts +10 -0
  148. package/src/dev-toolbar/dev-toolbar-runtime-paths.js +13 -0
  149. package/src/diagnostics/request-build-dedupe.js +34 -28
  150. package/src/diagnostics/startup-trace.d.ts +10 -1
  151. package/src/diagnostics/startup-trace.js +269 -241
  152. package/src/eco/README.md +6 -0
  153. package/src/eco/eco-declared-component.js +19 -14
  154. package/src/eco/eco.browser.js +56 -69
  155. package/src/eco/eco.js +156 -96
  156. package/src/eco/eco.types.js +5 -0
  157. package/src/eco/eco.utils.js +1 -10
  158. package/src/eco/global-injector-map.js +55 -41
  159. package/src/eco/lazy-injector-map.js +90 -60
  160. package/src/eco/module-dependencies.js +52 -44
  161. package/src/eco/page-layout-normalization.js +59 -49
  162. package/src/errors/http-error.js +50 -49
  163. package/src/errors/index.js +3 -12
  164. package/src/errors/locals-access-error.js +5 -8
  165. package/src/errors/undeclared-component-dependency-error.js +15 -15
  166. package/src/global/app-logger.js +3 -6
  167. package/src/hmr/README.md +10 -0
  168. package/src/hmr/client/hmr-runtime.js +117 -113
  169. package/src/hmr/client/module-update.d.ts +13 -0
  170. package/src/hmr/client/module-update.js +39 -0
  171. package/src/hmr/hmr-asset-paths.d.ts +14 -0
  172. package/src/hmr/hmr-asset-paths.js +22 -0
  173. package/src/hmr/hmr-entrypoint-output.d.ts +11 -39
  174. package/src/hmr/hmr-entrypoint-output.js +28 -54
  175. package/src/hmr/hmr-file-change-prep.js +13 -16
  176. package/src/hmr/hmr-registered-entrypoints-context.d.ts +7 -0
  177. package/src/hmr/hmr-registered-entrypoints-context.js +1 -0
  178. package/src/hmr/hmr-runtime-paths.d.ts +10 -0
  179. package/src/hmr/hmr-runtime-paths.js +13 -0
  180. package/src/hmr/hmr-strategy.d.ts +5 -11
  181. package/src/hmr/hmr-strategy.js +113 -61
  182. package/src/hmr/strategies/default-hmr-strategy.js +55 -33
  183. package/src/hmr/strategies/js-hmr-strategy.d.ts +6 -95
  184. package/src/hmr/strategies/js-hmr-strategy.js +104 -217
  185. package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +33 -27
  186. package/src/index.browser.js +1 -4
  187. package/src/index.d.ts +1 -0
  188. package/src/index.js +6 -47
  189. package/src/integrations/ghtml/ghtml-renderer.js +12 -7
  190. package/src/integrations/ghtml/ghtml.constants.js +1 -4
  191. package/src/integrations/ghtml/ghtml.plugin.js +9 -12
  192. package/src/islands/README.md +25 -0
  193. package/src/islands/island-host.d.ts +37 -0
  194. package/src/islands/island-host.js +55 -0
  195. package/src/plugins/alias-resolver-cache.js +114 -97
  196. package/src/plugins/alias-resolver-plugin.js +33 -47
  197. package/src/plugins/define-integration.js +18 -17
  198. package/src/plugins/eco-component-meta-plugin.js +387 -145
  199. package/src/plugins/foreign-jsx-override-plugin.js +49 -35
  200. package/src/plugins/integration-plugin.js +212 -203
  201. package/src/plugins/jsx-import-source.utils.js +16 -21
  202. package/src/plugins/processor.js +159 -149
  203. package/src/plugins/runtime-capability.js +1 -0
  204. package/src/plugins/source-transform.js +109 -79
  205. package/src/plugins/tsconfig-import-resolver.d.ts +17 -0
  206. package/src/plugins/tsconfig-import-resolver.js +218 -142
  207. package/src/route-renderer/README.md +12 -1
  208. package/src/route-renderer/orchestration/document-shell/document-shell-render.service.js +143 -136
  209. package/src/route-renderer/orchestration/document-shell/layout-shell-props.service.js +33 -27
  210. package/src/route-renderer/orchestration/foreign-child/component-render-context.js +173 -126
  211. package/src/route-renderer/orchestration/foreign-child/foreign-child-output.utils.js +165 -154
  212. package/src/route-renderer/orchestration/foreign-child/foreign-subtree-execution.service.js +329 -341
  213. package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.js +33 -32
  214. package/src/route-renderer/orchestration/integration-renderer.d.ts +1 -0
  215. package/src/route-renderer/orchestration/integration-renderer.js +731 -750
  216. package/src/route-renderer/orchestration/integration-renderer.test-fixtures.js +168 -172
  217. package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.js +119 -131
  218. package/src/route-renderer/orchestration/ownership-graph/component-graph.js +82 -91
  219. package/src/route-renderer/orchestration/ownership-graph/ownership-validation.service.js +82 -76
  220. package/src/route-renderer/orchestration/page-browser-graph/global-injector-assets.service.js +29 -31
  221. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-contribution.loader.js +10 -6
  222. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.js +31 -28
  223. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.d.ts +3 -0
  224. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.js +430 -413
  225. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph.service.js +191 -212
  226. package/src/route-renderer/orchestration/page-browser-graph/processed-asset-dedupe.js +20 -24
  227. package/src/route-renderer/orchestration/route-pipeline/integration-route-render-adapter.d.ts +4 -0
  228. package/src/route-renderer/orchestration/route-pipeline/integration-route-render-adapter.js +24 -24
  229. package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.js +22 -24
  230. package/src/route-renderer/orchestration/route-pipeline/robots-meta.contribution.js +41 -34
  231. package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.d.ts +5 -0
  232. package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.js +42 -22
  233. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.builder.js +50 -48
  234. package/src/route-renderer/orchestration/route-pipeline/route-prepared-options.utils.js +29 -32
  235. package/src/route-renderer/orchestration/route-pipeline/route-render-orchestrator.js +150 -156
  236. package/src/route-renderer/orchestration/string-markup-renderer.js +48 -51
  237. package/src/route-renderer/page-loading/component-dependency-collection.js +120 -124
  238. package/src/route-renderer/page-loading/declared-asset-collection.js +66 -94
  239. package/src/route-renderer/page-loading/dependency-resolver.js +101 -104
  240. package/src/route-renderer/page-loading/ecopages-virtual-imports.js +68 -54
  241. package/src/route-renderer/page-loading/lazy-entry-collection.js +75 -98
  242. package/src/route-renderer/page-loading/lazy-trigger-planning.js +46 -36
  243. package/src/route-renderer/page-loading/module-declaration-aggregation.js +38 -31
  244. package/src/route-renderer/page-loading/module-declaration-scripts.js +10 -15
  245. package/src/route-renderer/page-loading/page-dependency-bundling.js +156 -113
  246. package/src/route-renderer/page-loading/page-module-loader.js +130 -124
  247. package/src/route-renderer/route-renderer.js +74 -76
  248. package/src/router/README.md +23 -0
  249. package/src/router/client/link-intent.js +55 -39
  250. package/src/router/client/link-intent.test.browser.js +49 -49
  251. package/src/router/client/link-navigation-policy.js +114 -93
  252. package/src/router/client/link-navigation-policy.test.browser.js +70 -80
  253. package/src/router/client/navigation-coordinator.js +235 -211
  254. package/src/router/client/navigation-lifecycle.d.ts +55 -0
  255. package/src/router/client/navigation-lifecycle.js +50 -0
  256. package/src/router/client/navigation-lifecycle.test.browser.d.ts +1 -0
  257. package/src/router/client/navigation-lifecycle.test.browser.js +118 -0
  258. package/src/router/server/route-registry.js +237 -242
  259. package/src/services/assets/asset-processing-service/asset-dependency-keys.js +64 -53
  260. package/src/services/assets/asset-processing-service/asset-processing.service.js +287 -303
  261. package/src/services/assets/asset-processing-service/asset.factory.js +78 -81
  262. package/src/services/assets/asset-processing-service/assets.types.js +1 -0
  263. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +57 -46
  264. package/src/services/assets/asset-processing-service/browser-runtime-entry-resolution.js +106 -69
  265. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +53 -53
  266. package/src/services/assets/asset-processing-service/finalize-processed-asset.js +4 -6
  267. package/src/services/assets/asset-processing-service/grouped-content-bundles.js +79 -80
  268. package/src/services/assets/asset-processing-service/index.js +8 -8
  269. package/src/services/assets/asset-processing-service/inline-content-script-body.js +22 -16
  270. package/src/services/assets/asset-processing-service/materialize-content-script-asset.js +21 -17
  271. package/src/services/assets/asset-processing-service/page-package.js +70 -72
  272. package/src/services/assets/asset-processing-service/processor.interface.js +7 -5
  273. package/src/services/assets/asset-processing-service/processor.registry.js +11 -14
  274. package/src/services/assets/asset-processing-service/processors/base/base-processor.js +59 -62
  275. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +102 -117
  276. package/src/services/assets/asset-processing-service/processors/index.js +5 -5
  277. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +110 -115
  278. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +95 -97
  279. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +136 -135
  280. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +27 -29
  281. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +34 -40
  282. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +36 -35
  283. package/src/services/assets/asset-processing-service/resolve-integration-plugin.js +14 -16
  284. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.js +27 -39
  285. package/src/services/assets/browser-bundle.service.js +52 -47
  286. package/src/services/cache/cache.types.js +5 -0
  287. package/src/services/cache/index.js +6 -7
  288. package/src/services/cache/memory-cache-store.js +101 -89
  289. package/src/services/cache/page-cache-service.js +156 -145
  290. package/src/services/cache/page-request-cache-coordinator.service.js +102 -102
  291. package/src/services/html/html-rewriter-provider.service.js +61 -61
  292. package/src/services/html/html-transformer.service.js +249 -266
  293. package/src/services/invalidation/development-invalidation.service.js +252 -241
  294. package/src/services/module-loading/app-module-loader.service.js +1 -0
  295. package/src/services/module-loading/app-server-module-transpiler.service.js +107 -101
  296. package/src/services/module-loading/host-module-loader-registry.js +6 -11
  297. package/src/services/module-loading/module-loading-types.js +1 -0
  298. package/src/services/module-loading/page-module-import.service.js +235 -243
  299. package/src/services/module-loading/route-module-build-cache-registry.js +47 -33
  300. package/src/services/module-loading/route-module-build-cache.js +3 -38
  301. package/src/services/module-loading/route-module-build-cache.store.js +195 -200
  302. package/src/services/module-loading/route-module-build-manifest.js +61 -74
  303. package/src/services/module-loading/route-module-dependency-hasher.js +136 -110
  304. package/src/services/module-loading/server-module-transpiler.service.js +68 -62
  305. package/src/services/module-loading/source-module-support.js +15 -7
  306. package/src/services/runtime-state/dev-graph.service.js +165 -157
  307. package/src/services/runtime-state/entrypoint-dependency-graph.service.js +85 -76
  308. package/src/services/runtime-state/server-invalidation-state.service.js +38 -30
  309. package/src/services/validation/schema-validation-service.js +157 -95
  310. package/src/services/validation/standard-schema.types.js +1 -0
  311. package/src/services/validation/validate-standard-schema.js +13 -13
  312. package/src/static-site-generator/production-page-browser-graph-prebuild.js +35 -19
  313. package/src/static-site-generator/sitemap-routes.js +33 -28
  314. package/src/static-site-generator/sitemap.js +38 -29
  315. package/src/static-site-generator/static-build-invalidation.js +34 -56
  316. package/src/static-site-generator/static-export-context.js +1 -0
  317. package/src/static-site-generator/static-site-generator.js +517 -553
  318. package/src/types/internal-types.d.ts +19 -3
  319. package/src/types/internal-types.js +1 -0
  320. package/src/types/public-types.d.ts +16 -46
  321. package/src/types/public-types.js +1 -0
  322. package/src/utils/deep-merge.js +39 -26
  323. package/src/utils/ecopages-route-info.js +27 -23
  324. package/src/utils/hash.js +3 -6
  325. package/src/utils/html-escaping.js +21 -8
  326. package/src/utils/html.js +1 -4
  327. package/src/utils/invariant.js +11 -10
  328. package/src/utils/locals-utils.js +32 -22
  329. package/src/utils/parse-cli-args.js +73 -65
  330. package/src/utils/path-pattern.js +38 -23
  331. package/src/utils/path-utils.module.js +8 -11
  332. package/src/utils/resolve-entry-file.js +70 -38
  333. package/src/utils/resolve-work-dir.js +23 -27
  334. package/src/utils/runtime.js +24 -33
  335. package/src/utils/server-utils.module.js +60 -52
  336. package/src/utils/static-file-extensions.js +52 -46
  337. package/src/watchers/project-watcher-ignore.js +16 -15
  338. package/src/watchers/project-watcher.js +385 -366
  339. package/src/watchers/project-watcher.test-helpers.js +45 -50
  340. package/src/adapters/shared/hmr/hmr-entrypoint-registrar.d.ts +0 -56
  341. package/src/adapters/shared/hmr/hmr-entrypoint-registrar.js +0 -106
  342. package/src/build/cache/dev-browser-script-cache.d.ts +0 -34
  343. package/src/build/cache/dev-browser-script-cache.js +0 -90
@@ -1,54 +1,54 @@
1
- import { describe, expect, it } from "vitest";
2
- import { getAnchorFromNavigationEvent, isStaticAssetHref, recoverPendingNavigationHref } from "./link-intent.js";
3
- describe("getAnchorFromNavigationEvent", () => {
4
- it("returns the anchor when the event target is a text node inside it", () => {
5
- const anchor = document.createElement("a");
6
- anchor.href = "/fast";
7
- anchor.setAttribute("data-eco-link", "true");
8
- const textNode = document.createTextNode("fast-link");
9
- anchor.append(textNode);
10
- document.body.append(anchor);
11
- const event = new MouseEvent("click", { bubbles: true, cancelable: true, composed: true });
12
- Object.defineProperty(event, "target", {
13
- configurable: true,
14
- value: textNode
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getAnchorFromNavigationEvent, isStaticAssetHref, recoverPendingNavigationHref } from './link-intent.js';
3
+ describe('getAnchorFromNavigationEvent', () => {
4
+ it('returns the anchor when the event target is a text node inside it', () => {
5
+ const anchor = document.createElement('a');
6
+ anchor.href = '/fast';
7
+ anchor.setAttribute('data-eco-link', 'true');
8
+ const textNode = document.createTextNode('fast-link');
9
+ anchor.append(textNode);
10
+ document.body.append(anchor);
11
+ const event = new MouseEvent('click', { bubbles: true, cancelable: true, composed: true });
12
+ Object.defineProperty(event, 'target', {
13
+ configurable: true,
14
+ value: textNode,
15
+ });
16
+ expect(getAnchorFromNavigationEvent(event, 'a[data-eco-link]')).toBe(anchor);
15
17
  });
16
- expect(getAnchorFromNavigationEvent(event, "a[data-eco-link]")).toBe(anchor);
17
- });
18
- it("returns the closest matching anchor for nested element targets", () => {
19
- const anchor = document.createElement("a");
20
- anchor.href = "/fast";
21
- anchor.setAttribute("data-eco-link", "true");
22
- const span = document.createElement("span");
23
- span.textContent = "fast-link";
24
- anchor.append(span);
25
- document.body.append(anchor);
26
- const event = new MouseEvent("click", { bubbles: true, cancelable: true, composed: true });
27
- Object.defineProperty(event, "target", {
28
- configurable: true,
29
- value: span
18
+ it('returns the closest matching anchor for nested element targets', () => {
19
+ const anchor = document.createElement('a');
20
+ anchor.href = '/fast';
21
+ anchor.setAttribute('data-eco-link', 'true');
22
+ const span = document.createElement('span');
23
+ span.textContent = 'fast-link';
24
+ anchor.append(span);
25
+ document.body.append(anchor);
26
+ const event = new MouseEvent('click', { bubbles: true, cancelable: true, composed: true });
27
+ Object.defineProperty(event, 'target', {
28
+ configurable: true,
29
+ value: span,
30
+ });
31
+ expect(getAnchorFromNavigationEvent(event, 'a[data-eco-link]')).toBe(anchor);
30
32
  });
31
- expect(getAnchorFromNavigationEvent(event, "a[data-eco-link]")).toBe(anchor);
32
- });
33
33
  });
34
- describe("isStaticAssetHref", () => {
35
- it("returns true for known static asset paths", () => {
36
- expect(isStaticAssetHref("/skill.txt")).toBe(true);
37
- expect(isStaticAssetHref("/skill/reference/full-stack.md")).toBe(true);
38
- expect(isStaticAssetHref("/assets/logo.png")).toBe(true);
39
- });
40
- it("returns false for application routes", () => {
41
- expect(isStaticAssetHref("/docs/getting-started/introduction")).toBe(false);
42
- expect(isStaticAssetHref("/")).toBe(false);
43
- });
34
+ describe('isStaticAssetHref', () => {
35
+ it('returns true for known static asset paths', () => {
36
+ expect(isStaticAssetHref('/skill.txt')).toBe(true);
37
+ expect(isStaticAssetHref('/skill/reference/full-stack.md')).toBe(true);
38
+ expect(isStaticAssetHref('/assets/logo.png')).toBe(true);
39
+ });
40
+ it('returns false for application routes', () => {
41
+ expect(isStaticAssetHref('/docs/getting-started/introduction')).toBe(false);
42
+ expect(isStaticAssetHref('/')).toBe(false);
43
+ });
44
44
  });
45
- describe("recoverPendingNavigationHref", () => {
46
- it("returns null for stale or missing pending intent state", () => {
47
- expect(recoverPendingNavigationHref(null, true, 10)).toBeNull();
48
- expect(recoverPendingNavigationHref({ href: "/fast", timestamp: 0 }, false, 10)).toBeNull();
49
- expect(recoverPendingNavigationHref({ href: "/fast", timestamp: 0 }, true, 2e3, 1e3)).toBeNull();
50
- });
51
- it("returns the captured href while a navigation is still in flight", () => {
52
- expect(recoverPendingNavigationHref({ href: "/fast", timestamp: 10 }, true, 20, 1e3)).toBe("/fast");
53
- });
45
+ describe('recoverPendingNavigationHref', () => {
46
+ it('returns null for stale or missing pending intent state', () => {
47
+ expect(recoverPendingNavigationHref(null, true, 10)).toBeNull();
48
+ expect(recoverPendingNavigationHref({ href: '/fast', timestamp: 0 }, false, 10)).toBeNull();
49
+ expect(recoverPendingNavigationHref({ href: '/fast', timestamp: 0 }, true, 2000, 1000)).toBeNull();
50
+ });
51
+ it('returns the captured href while a navigation is still in flight', () => {
52
+ expect(recoverPendingNavigationHref({ href: '/fast', timestamp: 10 }, true, 20, 1000)).toBe('/fast');
53
+ });
54
54
  });
@@ -1,101 +1,122 @@
1
- import { isStaticAssetHref } from "./link-intent.js";
1
+ import { isStaticAssetHref } from './link-intent.js';
2
+ /**
3
+ * Shared anchor/href checks for navigation interception and prefetch eligibility.
4
+ */
2
5
  function getLinkIneligibilityReason(link, options) {
3
- if (options.noPrefetchAttribute && link.hasAttribute(options.noPrefetchAttribute)) {
4
- return "no-prefetch";
5
- }
6
- if (options.reloadAttribute && link.hasAttribute(options.reloadAttribute)) {
7
- return "explicit-reload";
8
- }
9
- if (link.hasAttribute("download")) {
10
- return "download";
11
- }
12
- const href = link.getAttribute("href");
13
- if (!href || href.startsWith("#") || href.startsWith("javascript:")) {
14
- return "invalid-href";
15
- }
16
- const url = new URL(href, window.location.origin);
17
- if (url.origin !== window.location.origin) {
18
- return "cross-origin";
19
- }
20
- if (isStaticAssetHref(href)) {
21
- return "static-asset";
22
- }
23
- return null;
6
+ if (options.noPrefetchAttribute && link.hasAttribute(options.noPrefetchAttribute)) {
7
+ return 'no-prefetch';
8
+ }
9
+ if (options.reloadAttribute && link.hasAttribute(options.reloadAttribute)) {
10
+ return 'explicit-reload';
11
+ }
12
+ if (link.hasAttribute('download')) {
13
+ return 'download';
14
+ }
15
+ const href = link.getAttribute('href');
16
+ if (!href || href.startsWith('#') || href.startsWith('javascript:')) {
17
+ return 'invalid-href';
18
+ }
19
+ const url = new URL(href, window.location.origin);
20
+ if (url.origin !== window.location.origin) {
21
+ return 'cross-origin';
22
+ }
23
+ if (isStaticAssetHref(href)) {
24
+ return 'static-asset';
25
+ }
26
+ return null;
24
27
  }
25
- function isSamePageHashNavigationHref(href) {
26
- if (!href) {
27
- return false;
28
- }
29
- const currentUrl = new URL(window.location.href);
30
- const targetUrl = new URL(href, currentUrl);
31
- return targetUrl.origin === currentUrl.origin && targetUrl.hash.length > 0 && targetUrl.pathname === currentUrl.pathname && targetUrl.search === currentUrl.search;
28
+ /**
29
+ * Returns whether an href only adds a hash fragment on the current page.
30
+ */
31
+ export function isSamePageHashNavigationHref(href) {
32
+ if (!href) {
33
+ return false;
34
+ }
35
+ const currentUrl = new URL(window.location.href);
36
+ const targetUrl = new URL(href, currentUrl);
37
+ return (targetUrl.origin === currentUrl.origin &&
38
+ targetUrl.hash.length > 0 &&
39
+ targetUrl.pathname === currentUrl.pathname &&
40
+ targetUrl.search === currentUrl.search);
32
41
  }
33
- function getLinkNavigationDecision(event, link, options) {
34
- if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
35
- return { shouldIntercept: false, reason: "modified-click" };
36
- }
37
- if (event.button !== 0) {
38
- return { shouldIntercept: false, reason: "non-left-click" };
39
- }
40
- const target = link.getAttribute("target");
41
- if (target && target !== "_self") {
42
- return { shouldIntercept: false, reason: "external-target" };
43
- }
44
- const ineligibility = getLinkIneligibilityReason(link, options);
45
- if (ineligibility) {
46
- return { shouldIntercept: false, reason: ineligibility };
47
- }
48
- const href = link.getAttribute("href");
49
- if (isSamePageHashNavigationHref(href)) {
50
- return { shouldIntercept: false, reason: "same-page-hash" };
51
- }
52
- return { shouldIntercept: true, href };
42
+ /**
43
+ * Decides whether a pointer or click on an anchor should be handled as SPA navigation.
44
+ */
45
+ export function getLinkNavigationDecision(event, link, options) {
46
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
47
+ return { shouldIntercept: false, reason: 'modified-click' };
48
+ }
49
+ if (event.button !== 0) {
50
+ return { shouldIntercept: false, reason: 'non-left-click' };
51
+ }
52
+ const target = link.getAttribute('target');
53
+ if (target && target !== '_self') {
54
+ return { shouldIntercept: false, reason: 'external-target' };
55
+ }
56
+ const ineligibility = getLinkIneligibilityReason(link, options);
57
+ if (ineligibility) {
58
+ return { shouldIntercept: false, reason: ineligibility };
59
+ }
60
+ const href = link.getAttribute('href');
61
+ if (isSamePageHashNavigationHref(href)) {
62
+ return { shouldIntercept: false, reason: 'same-page-hash' };
63
+ }
64
+ return { shouldIntercept: true, href };
53
65
  }
54
- function getNavigableHrefFromClick(event, link, options) {
55
- const decision = getLinkNavigationDecision(event, link, options);
56
- return decision.shouldIntercept ? decision.href : null;
66
+ /**
67
+ * Returns the href when SPA navigation should intercept the click, otherwise `null`.
68
+ */
69
+ export function getNavigableHrefFromClick(event, link, options) {
70
+ const decision = getLinkNavigationDecision(event, link, options);
71
+ return decision.shouldIntercept ? decision.href : null;
57
72
  }
58
- function shouldPrefetchLink(link, options) {
59
- if (getLinkIneligibilityReason(link, options)) {
60
- return false;
61
- }
62
- const href = link.getAttribute("href");
63
- try {
64
- const url = new URL(href, window.location.origin);
65
- const currentPath = window.location.pathname + window.location.search;
66
- const targetPath = url.pathname + url.search;
67
- return currentPath !== targetPath;
68
- } catch {
69
- return false;
70
- }
73
+ /**
74
+ * Returns whether a link is eligible for hover or viewport prefetch.
75
+ */
76
+ export function shouldPrefetchLink(link, options) {
77
+ if (getLinkIneligibilityReason(link, options)) {
78
+ return false;
79
+ }
80
+ const href = link.getAttribute('href');
81
+ try {
82
+ const url = new URL(href, window.location.origin);
83
+ const currentPath = window.location.pathname + window.location.search;
84
+ const targetPath = url.pathname + url.search;
85
+ return currentPath !== targetPath;
86
+ }
87
+ catch {
88
+ return false;
89
+ }
71
90
  }
72
- function isHtmlPageResponse(response) {
73
- const contentType = response.headers.get("Content-Type");
74
- if (!contentType) {
75
- return false;
76
- }
77
- const normalized = contentType.split(";")[0]?.trim().toLowerCase() ?? "";
78
- return normalized === "text/html" || normalized === "application/xhtml+xml";
91
+ /**
92
+ * @remarks
93
+ * Prefetch and SPA fetches request HTML. Only explicit `text/html` and
94
+ * `application/xhtml+xml` responses are accepted; missing or asset types are rejected.
95
+ */
96
+ export function isHtmlPageResponse(response) {
97
+ const contentType = response.headers.get('Content-Type');
98
+ if (!contentType) {
99
+ return false;
100
+ }
101
+ const normalized = contentType.split(';')[0]?.trim().toLowerCase() ?? '';
102
+ return normalized === 'text/html' || normalized === 'application/xhtml+xml';
79
103
  }
80
- async function assertHtmlPageResponse(response) {
81
- if (isHtmlPageResponse(response)) {
82
- return;
83
- }
84
- const contentType = response.headers.get("Content-Type");
85
- const normalized = contentType?.split(";")[0]?.trim().toLowerCase() ?? "";
86
- if (normalized === "text/plain" || normalized === "") {
87
- const sample = (await response.clone().text()).trimStart();
88
- if (sample.startsWith("<")) {
89
- return;
90
- }
91
- }
92
- throw new Error(`Expected HTML page response, received ${contentType ?? "unknown content type"}`);
104
+ /**
105
+ * @remarks
106
+ * Servers should send `text/html`. When the type is missing or the runtime
107
+ * defaults to `text/plain` (common in tests), a document-shaped body is accepted.
108
+ */
109
+ export async function assertHtmlPageResponse(response) {
110
+ if (isHtmlPageResponse(response)) {
111
+ return;
112
+ }
113
+ const contentType = response.headers.get('Content-Type');
114
+ const normalized = contentType?.split(';')[0]?.trim().toLowerCase() ?? '';
115
+ if (normalized === 'text/plain' || normalized === '') {
116
+ const sample = (await response.clone().text()).trimStart();
117
+ if (sample.startsWith('<')) {
118
+ return;
119
+ }
120
+ }
121
+ throw new Error(`Expected HTML page response, received ${contentType ?? 'unknown content type'}`);
93
122
  }
94
- export {
95
- assertHtmlPageResponse,
96
- getLinkNavigationDecision,
97
- getNavigableHrefFromClick,
98
- isHtmlPageResponse,
99
- isSamePageHashNavigationHref,
100
- shouldPrefetchLink
101
- };
@@ -1,92 +1,82 @@
1
- import { describe, expect, it } from "vitest";
2
- import {
3
- getLinkNavigationDecision,
4
- getNavigableHrefFromClick,
5
- isHtmlPageResponse,
6
- isSamePageHashNavigationHref,
7
- shouldPrefetchLink
8
- } from "./link-navigation-policy.js";
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getLinkNavigationDecision, getNavigableHrefFromClick, isHtmlPageResponse, isSamePageHashNavigationHref, shouldPrefetchLink, } from './link-navigation-policy.js';
9
3
  function createLink(href, attributes = {}) {
10
- const link = document.createElement("a");
11
- link.href = href;
12
- for (const [key, value] of Object.entries(attributes)) {
13
- link.setAttribute(key, value);
14
- }
15
- document.body.append(link);
16
- return link;
4
+ const link = document.createElement('a');
5
+ link.href = href;
6
+ for (const [key, value] of Object.entries(attributes)) {
7
+ link.setAttribute(key, value);
8
+ }
9
+ document.body.append(link);
10
+ return link;
17
11
  }
18
12
  function createMouseEvent(button = 0, modifiers = {}) {
19
- return new MouseEvent("click", { bubbles: true, cancelable: true, button, ...modifiers });
13
+ return new MouseEvent('click', { bubbles: true, cancelable: true, button, ...modifiers });
20
14
  }
21
- const policy = { reloadAttribute: "data-eco-reload", noPrefetchAttribute: "data-eco-no-prefetch" };
22
- describe("isSamePageHashNavigationHref", () => {
23
- it("returns true for same pathname with a new hash", () => {
24
- history.replaceState({}, "", "/docs/page");
25
- expect(isSamePageHashNavigationHref("/docs/page#section")).toBe(true);
26
- });
15
+ const policy = { reloadAttribute: 'data-eco-reload', noPrefetchAttribute: 'data-eco-no-prefetch' };
16
+ describe('isSamePageHashNavigationHref', () => {
17
+ it('returns true for same pathname with a new hash', () => {
18
+ history.replaceState({}, '', '/docs/page');
19
+ expect(isSamePageHashNavigationHref('/docs/page#section')).toBe(true);
20
+ });
27
21
  });
28
- describe("getLinkNavigationDecision", () => {
29
- it("allows same-origin page links", () => {
30
- const link = createLink("/page");
31
- const decision = getLinkNavigationDecision(createMouseEvent(), link, policy);
32
- expect(decision).toEqual({ shouldIntercept: true, href: "/page" });
33
- });
34
- it("rejects static asset links", () => {
35
- const link = createLink("/skill.txt");
36
- expect(getLinkNavigationDecision(createMouseEvent(), link, policy)).toEqual({
37
- shouldIntercept: false,
38
- reason: "static-asset"
22
+ describe('getLinkNavigationDecision', () => {
23
+ it('allows same-origin page links', () => {
24
+ const link = createLink('/page');
25
+ const decision = getLinkNavigationDecision(createMouseEvent(), link, policy);
26
+ expect(decision).toEqual({ shouldIntercept: true, href: '/page' });
27
+ });
28
+ it('rejects static asset links', () => {
29
+ const link = createLink('/skill.txt');
30
+ expect(getLinkNavigationDecision(createMouseEvent(), link, policy)).toEqual({
31
+ shouldIntercept: false,
32
+ reason: 'static-asset',
33
+ });
39
34
  });
40
- });
41
- it("rejects explicit reload links", () => {
42
- const link = createLink("/logout", { "data-eco-reload": "" });
43
- expect(getLinkNavigationDecision(createMouseEvent(), link, policy)).toEqual({
44
- shouldIntercept: false,
45
- reason: "explicit-reload"
35
+ it('rejects explicit reload links', () => {
36
+ const link = createLink('/logout', { 'data-eco-reload': '' });
37
+ expect(getLinkNavigationDecision(createMouseEvent(), link, policy)).toEqual({
38
+ shouldIntercept: false,
39
+ reason: 'explicit-reload',
40
+ });
46
41
  });
47
- });
48
42
  });
49
- describe("getNavigableHrefFromClick", () => {
50
- it("returns href when navigation should be intercepted", () => {
51
- const link = createLink("/page");
52
- expect(getNavigableHrefFromClick(createMouseEvent(), link, policy)).toBe("/page");
53
- });
54
- it("returns null for static assets", () => {
55
- const link = createLink("/llms.txt");
56
- expect(getNavigableHrefFromClick(createMouseEvent(), link, policy)).toBeNull();
57
- });
43
+ describe('getNavigableHrefFromClick', () => {
44
+ it('returns href when navigation should be intercepted', () => {
45
+ const link = createLink('/page');
46
+ expect(getNavigableHrefFromClick(createMouseEvent(), link, policy)).toBe('/page');
47
+ });
48
+ it('returns null for static assets', () => {
49
+ const link = createLink('/llms.txt');
50
+ expect(getNavigableHrefFromClick(createMouseEvent(), link, policy)).toBeNull();
51
+ });
58
52
  });
59
- describe("shouldPrefetchLink", () => {
60
- it("prefetches internal page links", () => {
61
- history.replaceState({}, "", "/");
62
- const link = createLink("/docs/intro");
63
- expect(shouldPrefetchLink(link, policy)).toBe(true);
64
- });
65
- it("skips static assets and opt-outs", () => {
66
- history.replaceState({}, "", "/");
67
- expect(shouldPrefetchLink(createLink("/skill.txt"), policy)).toBe(false);
68
- expect(shouldPrefetchLink(createLink("/page", { "data-eco-no-prefetch": "" }), policy)).toBe(false);
69
- });
53
+ describe('shouldPrefetchLink', () => {
54
+ it('prefetches internal page links', () => {
55
+ history.replaceState({}, '', '/');
56
+ const link = createLink('/docs/intro');
57
+ expect(shouldPrefetchLink(link, policy)).toBe(true);
58
+ });
59
+ it('skips static assets and opt-outs', () => {
60
+ history.replaceState({}, '', '/');
61
+ expect(shouldPrefetchLink(createLink('/skill.txt'), policy)).toBe(false);
62
+ expect(shouldPrefetchLink(createLink('/page', { 'data-eco-no-prefetch': '' }), policy)).toBe(false);
63
+ });
70
64
  });
71
- describe("isHtmlPageResponse", () => {
72
- it("accepts html content types", () => {
73
- expect(isHtmlPageResponse(new Response("", { headers: { "Content-Type": "text/html; charset=utf-8" } }))).toBe(
74
- true
75
- );
76
- });
77
- it("rejects plain text responses", () => {
78
- expect(isHtmlPageResponse(new Response("", { headers: { "Content-Type": "text/plain" } }))).toBe(false);
79
- });
65
+ describe('isHtmlPageResponse', () => {
66
+ it('accepts html content types', () => {
67
+ expect(isHtmlPageResponse(new Response('', { headers: { 'Content-Type': 'text/html; charset=utf-8' } }))).toBe(true);
68
+ });
69
+ it('rejects plain text responses', () => {
70
+ expect(isHtmlPageResponse(new Response('', { headers: { 'Content-Type': 'text/plain' } }))).toBe(false);
71
+ });
80
72
  });
81
- describe("isHtmlPageResponse", () => {
82
- it("accepts html and xhtml content types", () => {
83
- expect(isHtmlPageResponse(new Response("", { headers: { "Content-Type": "text/html" } }))).toBe(true);
84
- expect(isHtmlPageResponse(new Response("", { headers: { "Content-Type": "application/xhtml+xml" } }))).toBe(
85
- true
86
- );
87
- });
88
- it("rejects plain text and markdown responses", () => {
89
- expect(isHtmlPageResponse(new Response("text", { headers: { "Content-Type": "text/plain" } }))).toBe(false);
90
- expect(isHtmlPageResponse(new Response("# doc", { headers: { "Content-Type": "text/markdown" } }))).toBe(false);
91
- });
73
+ describe('isHtmlPageResponse', () => {
74
+ it('accepts html and xhtml content types', () => {
75
+ expect(isHtmlPageResponse(new Response('', { headers: { 'Content-Type': 'text/html' } }))).toBe(true);
76
+ expect(isHtmlPageResponse(new Response('', { headers: { 'Content-Type': 'application/xhtml+xml' } }))).toBe(true);
77
+ });
78
+ it('rejects plain text and markdown responses', () => {
79
+ expect(isHtmlPageResponse(new Response('text', { headers: { 'Content-Type': 'text/plain' } }))).toBe(false);
80
+ expect(isHtmlPageResponse(new Response('# doc', { headers: { 'Content-Type': 'text/markdown' } }))).toBe(false);
81
+ });
92
82
  });