@ecopages/core 0.2.0-beta.30 → 0.2.0-beta.32

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 (338) hide show
  1. package/README.md +1 -0
  2. package/package.json +82 -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/client/link-intent.js +55 -39
  249. package/src/router/client/link-intent.test.browser.js +49 -49
  250. package/src/router/client/link-navigation-policy.js +114 -93
  251. package/src/router/client/link-navigation-policy.test.browser.js +70 -80
  252. package/src/router/client/navigation-coordinator.js +235 -211
  253. package/src/router/server/route-registry.js +237 -242
  254. package/src/services/assets/asset-processing-service/asset-dependency-keys.js +64 -53
  255. package/src/services/assets/asset-processing-service/asset-processing.service.js +287 -303
  256. package/src/services/assets/asset-processing-service/asset.factory.js +78 -81
  257. package/src/services/assets/asset-processing-service/assets.types.js +1 -0
  258. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +57 -46
  259. package/src/services/assets/asset-processing-service/browser-runtime-entry-resolution.js +106 -69
  260. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +53 -53
  261. package/src/services/assets/asset-processing-service/finalize-processed-asset.js +4 -6
  262. package/src/services/assets/asset-processing-service/grouped-content-bundles.js +79 -80
  263. package/src/services/assets/asset-processing-service/index.js +8 -8
  264. package/src/services/assets/asset-processing-service/inline-content-script-body.js +22 -16
  265. package/src/services/assets/asset-processing-service/materialize-content-script-asset.js +21 -17
  266. package/src/services/assets/asset-processing-service/page-package.js +70 -72
  267. package/src/services/assets/asset-processing-service/processor.interface.js +7 -5
  268. package/src/services/assets/asset-processing-service/processor.registry.js +11 -14
  269. package/src/services/assets/asset-processing-service/processors/base/base-processor.js +59 -62
  270. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +102 -117
  271. package/src/services/assets/asset-processing-service/processors/index.js +5 -5
  272. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +110 -115
  273. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +95 -97
  274. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +136 -135
  275. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +27 -29
  276. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +34 -40
  277. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +36 -35
  278. package/src/services/assets/asset-processing-service/resolve-integration-plugin.js +14 -16
  279. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.js +27 -39
  280. package/src/services/assets/browser-bundle.service.js +52 -47
  281. package/src/services/cache/cache.types.js +5 -0
  282. package/src/services/cache/index.js +6 -7
  283. package/src/services/cache/memory-cache-store.js +101 -89
  284. package/src/services/cache/page-cache-service.js +156 -145
  285. package/src/services/cache/page-request-cache-coordinator.service.js +102 -102
  286. package/src/services/html/html-rewriter-provider.service.js +61 -61
  287. package/src/services/html/html-transformer.service.js +249 -266
  288. package/src/services/invalidation/development-invalidation.service.js +252 -241
  289. package/src/services/module-loading/app-module-loader.service.js +1 -0
  290. package/src/services/module-loading/app-server-module-transpiler.service.js +107 -101
  291. package/src/services/module-loading/host-module-loader-registry.js +6 -11
  292. package/src/services/module-loading/module-loading-types.js +1 -0
  293. package/src/services/module-loading/page-module-import.service.js +235 -243
  294. package/src/services/module-loading/route-module-build-cache-registry.js +47 -33
  295. package/src/services/module-loading/route-module-build-cache.js +3 -38
  296. package/src/services/module-loading/route-module-build-cache.store.js +195 -200
  297. package/src/services/module-loading/route-module-build-manifest.js +61 -74
  298. package/src/services/module-loading/route-module-dependency-hasher.js +136 -110
  299. package/src/services/module-loading/server-module-transpiler.service.js +68 -62
  300. package/src/services/module-loading/source-module-support.js +15 -7
  301. package/src/services/runtime-state/dev-graph.service.js +165 -157
  302. package/src/services/runtime-state/entrypoint-dependency-graph.service.js +85 -76
  303. package/src/services/runtime-state/server-invalidation-state.service.js +38 -30
  304. package/src/services/validation/schema-validation-service.js +157 -95
  305. package/src/services/validation/standard-schema.types.js +1 -0
  306. package/src/services/validation/validate-standard-schema.js +13 -13
  307. package/src/static-site-generator/production-page-browser-graph-prebuild.js +35 -19
  308. package/src/static-site-generator/sitemap-routes.js +33 -28
  309. package/src/static-site-generator/sitemap.js +38 -29
  310. package/src/static-site-generator/static-build-invalidation.js +34 -56
  311. package/src/static-site-generator/static-export-context.js +1 -0
  312. package/src/static-site-generator/static-site-generator.js +517 -553
  313. package/src/types/internal-types.d.ts +19 -3
  314. package/src/types/internal-types.js +1 -0
  315. package/src/types/public-types.d.ts +16 -46
  316. package/src/types/public-types.js +1 -0
  317. package/src/utils/deep-merge.js +39 -26
  318. package/src/utils/ecopages-route-info.js +27 -23
  319. package/src/utils/hash.js +3 -6
  320. package/src/utils/html-escaping.js +21 -8
  321. package/src/utils/html.js +1 -4
  322. package/src/utils/invariant.js +11 -10
  323. package/src/utils/locals-utils.js +32 -22
  324. package/src/utils/parse-cli-args.js +73 -65
  325. package/src/utils/path-pattern.js +38 -23
  326. package/src/utils/path-utils.module.js +8 -11
  327. package/src/utils/resolve-entry-file.js +70 -38
  328. package/src/utils/resolve-work-dir.js +23 -27
  329. package/src/utils/runtime.js +24 -33
  330. package/src/utils/server-utils.module.js +60 -52
  331. package/src/utils/static-file-extensions.js +52 -46
  332. package/src/watchers/project-watcher-ignore.js +16 -15
  333. package/src/watchers/project-watcher.js +385 -366
  334. package/src/watchers/project-watcher.test-helpers.js +45 -50
  335. package/src/adapters/shared/hmr/hmr-entrypoint-registrar.d.ts +0 -56
  336. package/src/adapters/shared/hmr/hmr-entrypoint-registrar.js +0 -106
  337. package/src/build/cache/dev-browser-script-cache.d.ts +0 -34
  338. package/src/build/cache/dev-browser-script-cache.js +0 -90
@@ -1,202 +1,183 @@
1
- import { createServer } from "node:http";
2
- import { extname, join, normalize, sep } from "node:path";
3
- import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT, STATUS_MESSAGE } from "../../config/constants.js";
4
- import { fileSystem } from "@ecopages/file-system";
5
- import { ServerUtils } from "../../utils/server-utils.module.js";
6
- class NodeStaticContentServer {
7
- appConfig;
8
- options;
9
- server = null;
10
- /**
11
- * Creates the Node static-content server for one built app output directory.
12
- */
13
- constructor({ appConfig, options }) {
14
- this.appConfig = appConfig;
15
- this.options = {
16
- hostname: options?.hostname ?? DEFAULT_ECOPAGES_HOSTNAME,
17
- port: options?.port ?? DEFAULT_ECOPAGES_PORT
18
- };
19
- }
20
- /**
21
- * Returns whether the given content type should be served from a pre-gzipped
22
- * companion file when available.
23
- */
24
- shouldServeGzip(contentType) {
25
- return ["text/javascript", "text/css"].includes(contentType);
26
- }
27
- /**
28
- * Normalizes a request pathname and rejects directory traversal attempts.
29
- */
30
- sanitizePath(pathname) {
31
- const withoutLeadingSlash = pathname.replace(/^\/+/, "");
32
- const normalizedPath = normalize(withoutLeadingSlash);
33
- if (normalizedPath.startsWith("..") || normalizedPath.includes(`..${sep}`)) {
34
- return null;
1
+ import { createServer } from 'node:http';
2
+ import { extname, join, normalize, sep } from 'node:path';
3
+ import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT, STATUS_MESSAGE } from '../../config/constants.js';
4
+ import { fileSystem } from '@ecopages/file-system';
5
+ import { ServerUtils } from '../../utils/server-utils.module.js';
6
+ /**
7
+ * Serves prebuilt static Ecopages output through Node's HTTP server.
8
+ *
9
+ * @remarks
10
+ * This server is used by the Node preview/build path once the app has already
11
+ * emitted its static output. It intentionally stays small: path sanitization,
12
+ * content-type selection, optional gzip serving, and 404 handling.
13
+ */
14
+ export class NodeStaticContentServer {
15
+ appConfig;
16
+ options;
17
+ server = null;
18
+ /**
19
+ * Creates the Node static-content server for one built app output directory.
20
+ */
21
+ constructor({ appConfig, options }) {
22
+ this.appConfig = appConfig;
23
+ this.options = {
24
+ hostname: options?.hostname ?? DEFAULT_ECOPAGES_HOSTNAME,
25
+ port: options?.port ?? DEFAULT_ECOPAGES_PORT,
26
+ };
35
27
  }
36
- return normalizedPath;
37
- }
38
- /**
39
- * Writes one HTTP response with the provided headers and optional body.
40
- */
41
- sendResponse(res, status, headers, body) {
42
- res.statusCode = status;
43
- for (const [key, value] of Object.entries(headers)) {
44
- res.setHeader(key, value);
28
+ /**
29
+ * Returns whether the given content type should be served from a pre-gzipped
30
+ * companion file when available.
31
+ */
32
+ shouldServeGzip(contentType) {
33
+ return ['text/javascript', 'text/css'].includes(contentType);
45
34
  }
46
- if (!body) {
47
- res.end();
48
- return;
49
- }
50
- res.end(body);
51
- }
52
- /**
53
- * Serves the generated 404 page when present, or a plain-text fallback.
54
- */
55
- sendNotFoundPage(req, res) {
56
- const error404TemplatePath = join(this.appConfig.absolutePaths.distDir, "404.html");
57
- const isHead = (req.method ?? "GET").toUpperCase() === "HEAD";
58
- if (!fileSystem.exists(error404TemplatePath)) {
59
- this.sendResponse(
60
- res,
61
- 404,
62
- { "Content-Type": "text/plain" },
63
- isHead ? void 0 : Buffer.from(STATUS_MESSAGE[404])
64
- );
65
- return;
66
- }
67
- const file = fileSystem.readFileAsBuffer(error404TemplatePath);
68
- this.sendResponse(res, 404, { "Content-Type": "text/html" }, isHead ? void 0 : file);
69
- }
70
- /**
71
- * Serves one concrete file path, honoring gzip and HEAD semantics.
72
- */
73
- serveFile(req, res, filePath, status = 200) {
74
- const contentType = ServerUtils.getContentType(extname(filePath));
75
- const acceptsGzip = req.headers["accept-encoding"]?.includes("gzip");
76
- const isHead = (req.method ?? "GET").toUpperCase() === "HEAD";
77
- if (acceptsGzip && this.shouldServeGzip(contentType)) {
78
- const gzipPath = `${filePath}.gz`;
79
- if (fileSystem.exists(gzipPath)) {
80
- const file2 = fileSystem.readFileAsBuffer(gzipPath);
81
- this.sendResponse(
82
- res,
83
- status,
84
- {
85
- "Content-Type": contentType,
86
- "Content-Encoding": "gzip",
87
- Vary: "Accept-Encoding"
88
- },
89
- isHead ? void 0 : file2
90
- );
91
- return;
92
- }
93
- }
94
- if (!fileSystem.exists(filePath)) {
95
- this.sendNotFoundPage(req, res);
96
- return;
35
+ /**
36
+ * Normalizes a request pathname and rejects directory traversal attempts.
37
+ */
38
+ sanitizePath(pathname) {
39
+ const withoutLeadingSlash = pathname.replace(/^\/+/, '');
40
+ const normalizedPath = normalize(withoutLeadingSlash);
41
+ if (normalizedPath.startsWith('..') || normalizedPath.includes(`..${sep}`)) {
42
+ return null;
43
+ }
44
+ return normalizedPath;
97
45
  }
98
- const file = fileSystem.readFileAsBuffer(filePath);
99
- this.sendResponse(res, status, { "Content-Type": contentType }, isHead ? void 0 : file);
100
- }
101
- /**
102
- * Handles one incoming Node HTTP request against the built static output tree.
103
- */
104
- handleRequest(req, res) {
105
- const method = (req.method ?? "GET").toUpperCase();
106
- const isHead = method === "HEAD";
107
- if (method !== "GET" && method !== "HEAD") {
108
- this.sendResponse(
109
- res,
110
- 405,
111
- { Allow: "GET, HEAD", "Content-Type": "text/plain" },
112
- isHead ? void 0 : Buffer.from("Method Not Allowed")
113
- );
114
- return;
46
+ /**
47
+ * Writes one HTTP response with the provided headers and optional body.
48
+ */
49
+ sendResponse(res, status, headers, body) {
50
+ res.statusCode = status;
51
+ for (const [key, value] of Object.entries(headers)) {
52
+ res.setHeader(key, value);
53
+ }
54
+ if (!body) {
55
+ res.end();
56
+ return;
57
+ }
58
+ res.end(body);
115
59
  }
116
- const url = new URL(req.url ?? "/", "http://localhost");
117
- let decodedPathname = "/";
118
- try {
119
- decodedPathname = decodeURIComponent(url.pathname);
120
- } catch {
121
- this.sendResponse(
122
- res,
123
- 400,
124
- { "Content-Type": "text/plain" },
125
- isHead ? void 0 : Buffer.from("Invalid path")
126
- );
127
- return;
60
+ /**
61
+ * Serves the generated 404 page when present, or a plain-text fallback.
62
+ */
63
+ sendNotFoundPage(req, res) {
64
+ const error404TemplatePath = join(this.appConfig.absolutePaths.distDir, '404.html');
65
+ const isHead = (req.method ?? 'GET').toUpperCase() === 'HEAD';
66
+ if (!fileSystem.exists(error404TemplatePath)) {
67
+ this.sendResponse(res, 404, { 'Content-Type': 'text/plain' }, isHead ? undefined : Buffer.from(STATUS_MESSAGE[404]));
68
+ return;
69
+ }
70
+ const file = fileSystem.readFileAsBuffer(error404TemplatePath);
71
+ this.sendResponse(res, 404, { 'Content-Type': 'text/html' }, isHead ? undefined : file);
128
72
  }
129
- const pathname = decodedPathname === "/" ? "/index.html" : decodedPathname;
130
- const relativePath = this.sanitizePath(pathname);
131
- if (!relativePath) {
132
- this.sendResponse(
133
- res,
134
- 400,
135
- { "Content-Type": "text/plain" },
136
- isHead ? void 0 : Buffer.from("Invalid path")
137
- );
138
- return;
73
+ /**
74
+ * Serves one concrete file path, honoring gzip and HEAD semantics.
75
+ */
76
+ serveFile(req, res, filePath, status = 200) {
77
+ const contentType = ServerUtils.getContentType(extname(filePath));
78
+ const acceptsGzip = req.headers['accept-encoding']?.includes('gzip');
79
+ const isHead = (req.method ?? 'GET').toUpperCase() === 'HEAD';
80
+ if (acceptsGzip && this.shouldServeGzip(contentType)) {
81
+ const gzipPath = `${filePath}.gz`;
82
+ if (fileSystem.exists(gzipPath)) {
83
+ const file = fileSystem.readFileAsBuffer(gzipPath);
84
+ this.sendResponse(res, status, {
85
+ 'Content-Type': contentType,
86
+ 'Content-Encoding': 'gzip',
87
+ Vary: 'Accept-Encoding',
88
+ }, isHead ? undefined : file);
89
+ return;
90
+ }
91
+ }
92
+ if (!fileSystem.exists(filePath)) {
93
+ this.sendNotFoundPage(req, res);
94
+ return;
95
+ }
96
+ const file = fileSystem.readFileAsBuffer(filePath);
97
+ this.sendResponse(res, status, { 'Content-Type': contentType }, isHead ? undefined : file);
139
98
  }
140
- const basePath = join(this.appConfig.absolutePaths.distDir, relativePath);
141
- if (pathname.includes(".")) {
142
- this.serveFile(req, res, basePath);
143
- return;
99
+ /**
100
+ * Handles one incoming Node HTTP request against the built static output tree.
101
+ */
102
+ handleRequest(req, res) {
103
+ const method = (req.method ?? 'GET').toUpperCase();
104
+ const isHead = method === 'HEAD';
105
+ if (method !== 'GET' && method !== 'HEAD') {
106
+ this.sendResponse(res, 405, { Allow: 'GET, HEAD', 'Content-Type': 'text/plain' }, isHead ? undefined : Buffer.from('Method Not Allowed'));
107
+ return;
108
+ }
109
+ const url = new URL(req.url ?? '/', 'http://localhost');
110
+ let decodedPathname = '/';
111
+ try {
112
+ decodedPathname = decodeURIComponent(url.pathname);
113
+ }
114
+ catch {
115
+ this.sendResponse(res, 400, { 'Content-Type': 'text/plain' }, isHead ? undefined : Buffer.from('Invalid path'));
116
+ return;
117
+ }
118
+ const pathname = decodedPathname === '/' ? '/index.html' : decodedPathname;
119
+ const relativePath = this.sanitizePath(pathname);
120
+ if (!relativePath) {
121
+ this.sendResponse(res, 400, { 'Content-Type': 'text/plain' }, isHead ? undefined : Buffer.from('Invalid path'));
122
+ return;
123
+ }
124
+ const basePath = join(this.appConfig.absolutePaths.distDir, relativePath);
125
+ if (pathname.includes('.')) {
126
+ this.serveFile(req, res, basePath);
127
+ return;
128
+ }
129
+ const htmlCandidates = [`${basePath}.html`, join(basePath, 'index.html')];
130
+ for (const candidate of htmlCandidates) {
131
+ if (fileSystem.exists(candidate)) {
132
+ this.serveFile(req, res, candidate);
133
+ return;
134
+ }
135
+ }
136
+ this.sendNotFoundPage(req, res);
144
137
  }
145
- const htmlCandidates = [`${basePath}.html`, join(basePath, "index.html")];
146
- for (const candidate of htmlCandidates) {
147
- if (fileSystem.exists(candidate)) {
148
- this.serveFile(req, res, candidate);
149
- return;
150
- }
138
+ /**
139
+ * Starts the static preview server.
140
+ */
141
+ async start() {
142
+ if (this.server) {
143
+ return this.server;
144
+ }
145
+ this.server = createServer(this.handleRequest.bind(this));
146
+ const hostname = this.options.hostname ?? DEFAULT_ECOPAGES_HOSTNAME;
147
+ const port = this.options.port ?? DEFAULT_ECOPAGES_PORT;
148
+ await new Promise((resolve, reject) => {
149
+ const activeServer = this.server;
150
+ activeServer.once('error', reject);
151
+ activeServer.listen(port, hostname, () => {
152
+ activeServer.off('error', reject);
153
+ resolve();
154
+ });
155
+ });
156
+ return this.server;
151
157
  }
152
- this.sendNotFoundPage(req, res);
153
- }
154
- /**
155
- * Starts the static preview server.
156
- */
157
- async start() {
158
- if (this.server) {
159
- return this.server;
158
+ /**
159
+ * Stops the static preview server and optionally closes active connections.
160
+ */
161
+ async stop(force = true) {
162
+ if (!this.server) {
163
+ return;
164
+ }
165
+ const activeServer = this.server;
166
+ this.server = null;
167
+ await new Promise((resolve, reject) => {
168
+ activeServer.close((error) => {
169
+ if (error) {
170
+ reject(error);
171
+ return;
172
+ }
173
+ resolve();
174
+ });
175
+ if (force) {
176
+ activeServer.closeAllConnections();
177
+ }
178
+ });
160
179
  }
161
- this.server = createServer(this.handleRequest.bind(this));
162
- const hostname = this.options.hostname ?? DEFAULT_ECOPAGES_HOSTNAME;
163
- const port = this.options.port ?? DEFAULT_ECOPAGES_PORT;
164
- await new Promise((resolve, reject) => {
165
- const activeServer = this.server;
166
- activeServer.once("error", reject);
167
- activeServer.listen(port, hostname, () => {
168
- activeServer.off("error", reject);
169
- resolve();
170
- });
171
- });
172
- return this.server;
173
- }
174
- /**
175
- * Stops the static preview server and optionally closes active connections.
176
- */
177
- async stop(force = true) {
178
- if (!this.server) {
179
- return;
180
+ async [Symbol.asyncDispose]() {
181
+ await this.stop();
180
182
  }
181
- const activeServer = this.server;
182
- this.server = null;
183
- await new Promise((resolve, reject) => {
184
- activeServer.close((error) => {
185
- if (error) {
186
- reject(error);
187
- return;
188
- }
189
- resolve();
190
- });
191
- if (force) {
192
- activeServer.closeAllConnections();
193
- }
194
- });
195
- }
196
- async [Symbol.asyncDispose]() {
197
- await this.stop();
198
- }
199
183
  }
200
- export {
201
- NodeStaticContentServer
202
- };
@@ -1,83 +1,92 @@
1
- import { appLogger } from "../../global/app-logger.js";
2
- import { PortManager } from "../shared/runtime/port-manager.js";
3
- import { NodeStaticContentServer } from "./static-content-server.js";
4
- class NodeStaticPreviewHost {
5
- /**
6
- * Creates the preview host with an injectable preview-server constructor.
7
- */
8
- constructor(previewServerFactory = NodeStaticContentServer) {
9
- this.previewServerFactory = previewServerFactory;
10
- }
11
- previewServerFactory;
12
- previewServer = null;
13
- stopPromise = null;
14
- /**
15
- * Starts the Node preview host after fully draining any previous preview server
16
- * shutdown that may still be in flight.
17
- *
18
- * @remarks
19
- * The host only publishes a new preview server after `start()` succeeds. That
20
- * keeps failed startup attempts from replacing the last known-good server with a
21
- * half-initialized instance.
22
- */
23
- async start(options) {
24
- await this.stop();
25
- const portManager = new PortManager({
26
- startOnPort: async (port) => {
27
- const previewServer = new this.previewServerFactory({
28
- appConfig: options.appConfig,
29
- options: {
30
- hostname: options.hostname,
31
- port
32
- }
1
+ import { appLogger } from '../../global/app-logger.js';
2
+ import { PortManager } from '../shared/runtime/port-manager.js';
3
+ import { NodeStaticContentServer } from './static-content-server.js';
4
+ /**
5
+ * Node preview-host wrapper that manages the lifecycle of the static preview
6
+ * server used after a build.
7
+ *
8
+ * @remarks
9
+ * The host separates preview-server construction from lifecycle control so the
10
+ * Node server adapter can restart preview serving safely across repeated build
11
+ * and preview flows.
12
+ */
13
+ export class NodeStaticPreviewHost {
14
+ previewServerFactory;
15
+ previewServer = null;
16
+ stopPromise = null;
17
+ /**
18
+ * Creates the preview host with an injectable preview-server constructor.
19
+ */
20
+ constructor(previewServerFactory = NodeStaticContentServer) {
21
+ this.previewServerFactory = previewServerFactory;
22
+ }
23
+ /**
24
+ * Starts the Node preview host after fully draining any previous preview server
25
+ * shutdown that may still be in flight.
26
+ *
27
+ * @remarks
28
+ * The host only publishes a new preview server after `start()` succeeds. That
29
+ * keeps failed startup attempts from replacing the last known-good server with a
30
+ * half-initialized instance.
31
+ */
32
+ async start(options) {
33
+ await this.stop();
34
+ const portManager = new PortManager({
35
+ startOnPort: async (port) => {
36
+ const previewServer = new this.previewServerFactory({
37
+ appConfig: options.appConfig,
38
+ options: {
39
+ hostname: options.hostname,
40
+ port,
41
+ },
42
+ });
43
+ const server = await previewServer.start();
44
+ this.previewServer = previewServer;
45
+ const address = server.address();
46
+ if (address && typeof address === 'object') {
47
+ return address.port;
48
+ }
49
+ return port;
50
+ },
51
+ warn: (message) => appLogger.warn(message),
52
+ });
53
+ const previewPort = await portManager.bind({
54
+ preferredPort: options.port,
55
+ allowPortFallback: options.allowPortFallback === true,
33
56
  });
34
- const server = await previewServer.start();
35
- this.previewServer = previewServer;
36
- const address = server.address();
37
- if (address && typeof address === "object") {
38
- return address.port;
57
+ if (!previewPort) {
58
+ this.previewServer = null;
39
59
  }
40
- return port;
41
- },
42
- warn: (message) => appLogger.warn(message)
43
- });
44
- const previewPort = await portManager.bind({
45
- preferredPort: options.port,
46
- allowPortFallback: options.allowPortFallback === true
47
- });
48
- if (!previewPort) {
49
- this.previewServer = null;
50
- }
51
- return previewPort;
52
- }
53
- /**
54
- * Stops the active preview server and coalesces overlapping stop requests onto
55
- * the same shutdown promise.
56
- *
57
- * @remarks
58
- * The host keeps the server reference until shutdown succeeds. If shutdown
59
- * fails, callers can still retry `stop()` or inspect the same live instance
60
- * instead of losing the handle during a rejected async stop.
61
- */
62
- async stop(force = true) {
63
- if (this.stopPromise) {
64
- await this.stopPromise;
65
- return;
60
+ return previewPort;
66
61
  }
67
- if (!this.previewServer) {
68
- return;
62
+ /**
63
+ * Stops the active preview server and coalesces overlapping stop requests onto
64
+ * the same shutdown promise.
65
+ *
66
+ * @remarks
67
+ * The host keeps the server reference until shutdown succeeds. If shutdown
68
+ * fails, callers can still retry `stop()` or inspect the same live instance
69
+ * instead of losing the handle during a rejected async stop.
70
+ */
71
+ async stop(force = true) {
72
+ if (this.stopPromise) {
73
+ await this.stopPromise;
74
+ return;
75
+ }
76
+ if (!this.previewServer) {
77
+ return;
78
+ }
79
+ const activePreviewServer = this.previewServer;
80
+ this.stopPromise = activePreviewServer
81
+ .stop(force)
82
+ .then(() => {
83
+ if (this.previewServer === activePreviewServer) {
84
+ this.previewServer = null;
85
+ }
86
+ })
87
+ .finally(() => {
88
+ this.stopPromise = null;
89
+ });
90
+ await this.stopPromise;
69
91
  }
70
- const activePreviewServer = this.previewServer;
71
- this.stopPromise = activePreviewServer.stop(force).then(() => {
72
- if (this.previewServer === activePreviewServer) {
73
- this.previewServer = null;
74
- }
75
- }).finally(() => {
76
- this.stopPromise = null;
77
- });
78
- await this.stopPromise;
79
- }
80
92
  }
81
- export {
82
- NodeStaticPreviewHost
83
- };
@@ -0,0 +1,16 @@
1
+ import type { ResolvedHmrEntrypoint } from '../../../hmr/hmr-entrypoint-output.js';
2
+ /**
3
+ * Tracks dev-transform entrypoints registered for HMR invalidation.
4
+ */
5
+ export declare class DevTransformEntrypointRegistry {
6
+ private readonly registered;
7
+ getRegisteredEntrypoints(): ReadonlyMap<string, ResolvedHmrEntrypoint>;
8
+ getWatchedOutputUrls(): Map<string, string>;
9
+ clearRegistration(entrypointPath: string): void;
10
+ registerTransformModule(sourcePath: string, outputUrl: string, options: {
11
+ role: 'page';
12
+ } | {
13
+ role: 'script';
14
+ }): void;
15
+ clearAll(): void;
16
+ }
@@ -0,0 +1,32 @@
1
+ import path from 'node:path';
2
+ /**
3
+ * Tracks dev-transform entrypoints registered for HMR invalidation.
4
+ */
5
+ export class DevTransformEntrypointRegistry {
6
+ registered = new Map();
7
+ getRegisteredEntrypoints() {
8
+ return this.registered;
9
+ }
10
+ getWatchedOutputUrls() {
11
+ const watchedFiles = new Map();
12
+ for (const [sourcePath, entrypoint] of this.registered) {
13
+ watchedFiles.set(sourcePath, entrypoint.outputUrl);
14
+ }
15
+ return watchedFiles;
16
+ }
17
+ clearRegistration(entrypointPath) {
18
+ this.registered.delete(path.resolve(entrypointPath));
19
+ }
20
+ registerTransformModule(sourcePath, outputUrl, options) {
21
+ const normalized = path.resolve(sourcePath);
22
+ this.registered.set(normalized, {
23
+ sourcePath: normalized,
24
+ outputPath: normalized,
25
+ outputUrl,
26
+ role: options.role,
27
+ });
28
+ }
29
+ clearAll() {
30
+ this.registered.clear();
31
+ }
32
+ }