@ecopages/core 0.2.0-beta.31 → 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,589 +1,589 @@
1
- import path from "node:path";
2
- import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT } from "../../config/constants.js";
3
- import { appLogger } from "../../global/app-logger.js";
4
- import { HttpError } from "../../errors/http-error.js";
5
- import { createRequire } from "../../utils/locals-utils.js";
6
- import { findWebSocketRoute } from "../abstract/ws-pattern-matcher.js";
7
- import { fileSystem } from "@ecopages/file-system";
8
- import { setupAppRuntimePlugins } from "../../build/build-adapter.js";
9
- import { installBuildRuntime } from "../../build/runtime/build-runtime.js";
10
- import { StaticSiteGenerator } from "../../static-site-generator/static-site-generator.js";
11
- import { ProjectWatcher } from "../../watchers/project-watcher.js";
12
- import { SharedServerAdapter } from "../shared/runtime/server-adapter.js";
13
- import { ApiResponseBuilder } from "../shared/http/api-response.js";
14
- import { ServerStaticBuilder } from "../shared/runtime/server-static-builder.js";
15
- import { attachNodeHttpWebSocketUpgrades } from "../shared/ws/node-http-websocket-upgrades.js";
16
- import { createBunUserWebSocketLifecycle } from "./bun-user-websocket-lifecycle.js";
17
- import { createEcopagesSocket } from "../shared/ws/websocket-lifecycle.js";
18
- import { resolveServeRuntimeOrigin } from "../shared/runtime/runtime-app-bootstrap.js";
19
- import {
20
- attachHmrToIntegrations,
21
- disposeDevResources,
22
- prepareRuntimePublicDir,
23
- startConfiguredIntegrationRuntimePrewarm
24
- } from "../shared/runtime/runtime-server-lifecycle.js";
25
- import { ClientBridge } from "./client-bridge.js";
26
- import { setAppDevClientBridge } from "../../dev/client-bridge-registry.js";
27
- import { setAppHmrManager } from "../../dev/hmr-manager-registry.js";
28
- import { HmrManager } from "./hmr-manager.js";
29
- import { BunStaticPreviewHost } from "./static-preview-host.js";
30
- class BunServerAdapter extends SharedServerAdapter {
31
- apiHandlers;
32
- staticRoutes;
33
- errorHandler;
34
- bridge;
35
- hmrManager;
36
- initializationPromise = null;
37
- fullyInitialized = false;
38
- projectWatcher = null;
39
- adapterDisposed = false;
40
- deferRuntimeAssetSetup;
41
- allowPortFallback;
42
- previewHost;
43
- /**
44
- * Reference to the application-level WebSocket handlers map.
45
- *
46
- * @remarks
47
- * This is a reference to the map owned by `AbstractApplicationAdapter`,
48
- * passed in via the constructor. The Bun adapter reads from it to wire
49
- * WebSocket upgrades for user-registered patterns.
50
- */
51
- websocketHandlers = /* @__PURE__ */ new Map();
52
- registerBunRuntimePlugin(plugin) {
53
- Bun.plugin(plugin);
54
- }
55
- adaptBunWebSocket(ws, kind, params, search, context) {
56
- return createEcopagesSocket(
57
- {
58
- send: (data) => ws.send(data),
59
- close: (code, reason) => ws.close(code, reason)
60
- },
61
- { kind, params, search, context }
62
- );
63
- }
64
- /**
65
- * Resolves the per-connection context for a Bun user connection.
66
- *
67
- * @remarks
68
- * `context()` is invoked exactly once per accepted connection. Its
69
- * resolved value is shared by all subsequent lifecycle hooks. If
70
- * `context()` throws, the connection is closed immediately with code
71
- * 1011 (server error) and the error is logged.
72
- *
73
- * @param request - The original upgrade request (best-effort reconstructed)
74
- * @param handler - The registered handler
75
- * @param kind - The registered route pattern
76
- * @param params - Dynamic path parameters
77
- * @param search - Query string parameters
78
- * @returns The resolved per-connection context
79
- */
80
- async resolveBunContext(request, handler, kind, params, search) {
81
- if (!handler.context) {
82
- return void 0;
1
+ import path from 'node:path';
2
+ import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT } from '../../config/constants.js';
3
+ import { appLogger } from '../../global/app-logger.js';
4
+ import { HttpError } from '../../errors/http-error.js';
5
+ import { createRequire } from '../../utils/locals-utils.js';
6
+ import { findWebSocketRoute } from '../abstract/ws-pattern-matcher.js';
7
+ import { fileSystem } from '@ecopages/file-system';
8
+ import { setupAppRuntimePlugins } from '../../build/build-adapter.js';
9
+ import { installBuildRuntime } from '../../build/runtime/build-runtime.js';
10
+ import { StaticSiteGenerator } from '../../static-site-generator/static-site-generator.js';
11
+ import { ProjectWatcher } from '../../watchers/project-watcher.js';
12
+ import { SharedServerAdapter } from '../shared/runtime/server-adapter.js';
13
+ import { ApiResponseBuilder } from '../shared/http/api-response.js';
14
+ import { ServerStaticBuilder } from '../shared/runtime/server-static-builder.js';
15
+ import { attachNodeHttpWebSocketUpgrades } from '../shared/ws/node-http-websocket-upgrades.js';
16
+ import { createBunUserWebSocketLifecycle } from './bun-user-websocket-lifecycle.js';
17
+ import { createEcopagesSocket } from '../shared/ws/websocket-lifecycle.js';
18
+ import { resolveServeRuntimeOrigin } from '../shared/runtime/runtime-app-bootstrap.js';
19
+ import { attachHmrToIntegrations, disposeDevResources, prepareRuntimePublicDir, startDevWarmup, } from '../shared/runtime/runtime-server-lifecycle.js';
20
+ import { ClientBridge } from './client-bridge.js';
21
+ import { setAppDevClientBridge } from '../../dev/client-bridge-registry.js';
22
+ import { setAppHmrManager } from '../../dev/hmr-manager-registry.js';
23
+ import { HmrManager } from './hmr-manager.js';
24
+ import { BunStaticPreviewHost } from './static-preview-host.js';
25
+ /**
26
+ * Bun transport adapter that wires shared Ecopages request handling onto a live
27
+ * `Bun.serve()` runtime.
28
+ *
29
+ * @remarks
30
+ * The adapter owns Bun-specific concerns that do not exist in the shared server
31
+ * abstraction: websocket-backed HMR transport, runtime plugin registration, and
32
+ * preview-host startup for static builds. Routing, rendering, and response
33
+ * composition still delegate to the shared server adapter base.
34
+ */
35
+ export class BunServerAdapter extends SharedServerAdapter {
36
+ apiHandlers;
37
+ staticRoutes;
38
+ errorHandler;
39
+ bridge;
40
+ hmrManager;
41
+ initializationPromise = null;
42
+ fullyInitialized = false;
43
+ projectWatcher = null;
44
+ adapterDisposed = false;
45
+ deferRuntimeAssetSetup;
46
+ allowPortFallback;
47
+ previewHost;
48
+ /**
49
+ * Reference to the application-level WebSocket handlers map.
50
+ *
51
+ * @remarks
52
+ * This is a reference to the map owned by `AbstractApplicationAdapter`,
53
+ * passed in via the constructor. The Bun adapter reads from it to wire
54
+ * WebSocket upgrades for user-registered patterns.
55
+ */
56
+ websocketHandlers = new Map();
57
+ registerBunRuntimePlugin(plugin) {
58
+ Bun.plugin(plugin);
83
59
  }
84
- try {
85
- return await handler.context({ request, kind, params, search });
86
- } catch (error) {
87
- appLogger.error(`[WS:${kind}] context() failed; closing connection.`, error);
88
- throw error;
60
+ adaptBunWebSocket(ws, kind, params, search, context) {
61
+ return createEcopagesSocket({
62
+ send: (data) => ws.send(data),
63
+ close: (code, reason) => ws.close(code, reason),
64
+ }, { kind, params, search, context });
89
65
  }
90
- }
91
- /**
92
- * Creates a Bun server adapter with already-resolved runtime collaborators.
93
- *
94
- * @remarks
95
- * The public params interface keeps `hmrManager`, `bridge`, and `previewHost`
96
- * optional so factory callers can omit them. By the time the concrete adapter
97
- * is constructed, those collaborators are mandatory because the adapter cannot
98
- * initialize Bun HMR or preview flows without them.
99
- */
100
- constructor({
101
- appConfig,
102
- runtimeOrigin,
103
- serveOptions,
104
- apiHandlers,
105
- staticRoutes,
106
- errorHandler,
107
- websocketHandlers,
108
- options,
109
- hostOwnsDevClient,
110
- deferRuntimeAssetSetup,
111
- allowPortFallback,
112
- hmrManager,
113
- bridge,
114
- previewHost
115
- }) {
116
- super({ appConfig, runtimeOrigin, serveOptions, options });
117
- this.deferRuntimeAssetSetup = deferRuntimeAssetSetup === true;
118
- this.allowPortFallback = allowPortFallback !== false;
119
- this.apiHandlers = apiHandlers || [];
120
- this.staticRoutes = staticRoutes || [];
121
- this.errorHandler = errorHandler;
122
- this.bridge = bridge;
123
- this.hmrManager = hmrManager;
124
- this.previewHost = previewHost;
125
- this.hostOwnsDevClient = hostOwnsDevClient === true;
126
- if (websocketHandlers) {
127
- this.websocketHandlers = websocketHandlers;
66
+ /**
67
+ * Resolves the per-connection context for a Bun user connection.
68
+ *
69
+ * @remarks
70
+ * `context()` is invoked exactly once per accepted connection. Its
71
+ * resolved value is shared by all subsequent lifecycle hooks. If
72
+ * `context()` throws, the connection is closed immediately with code
73
+ * 1011 (server error) and the error is logged.
74
+ *
75
+ * @param request - The original upgrade request (best-effort reconstructed)
76
+ * @param handler - The registered handler
77
+ * @param kind - The registered route pattern
78
+ * @param params - Dynamic path parameters
79
+ * @param search - Query string parameters
80
+ * @returns The resolved per-connection context
81
+ */
82
+ async resolveBunContext(request, handler, kind, params, search) {
83
+ if (!handler.context) {
84
+ return undefined;
85
+ }
86
+ try {
87
+ return (await handler.context({ request, kind, params, search }));
88
+ }
89
+ catch (error) {
90
+ appLogger.error(`[WS:${kind}] context() failed; closing connection.`, error);
91
+ throw error;
92
+ }
128
93
  }
129
- }
130
- /**
131
- * Wires user WebSocket routes onto a Node HTTP server used by host integrations.
132
- */
133
- attachUserWebSocketUpgrades(server, options) {
134
- attachNodeHttpWebSocketUpgrades(server, {
135
- runtimeOrigin: this.runtimeOrigin,
136
- websocketHandlers: this.websocketHandlers,
137
- passthroughUnmatched: options?.passthroughUnmatched
138
- });
139
- }
140
- /**
141
- * Initializes the server adapter's core runtime components.
142
- */
143
- async initialize() {
144
- installBuildRuntime(this.appConfig);
145
- this.staticSiteGenerator = new StaticSiteGenerator({ appConfig: this.appConfig });
146
- prepareRuntimePublicDir(this.appConfig);
147
- const staticBuilderOptions = {
148
- appConfig: this.appConfig,
149
- staticSiteGenerator: this.staticSiteGenerator,
150
- serveOptions: this.serveOptions,
151
- runtimeOrigin: this.runtimeOrigin,
152
- needsServerBundle: this.apiHandlers.length > 0 || this.websocketHandlers.size > 0,
153
- hmrManager: this.hmrManager,
154
- onRuntimePlugin: (plugin) => {
155
- this.registerBunRuntimePlugin(plugin);
156
- }
157
- };
158
- this.staticBuilder = new ServerStaticBuilder(staticBuilderOptions);
159
- if (!this.deferRuntimeAssetSetup) {
160
- await this.initializeRuntimePlugins({ watch: this.options?.watch });
94
+ /**
95
+ * Creates a Bun server adapter with already-resolved runtime collaborators.
96
+ *
97
+ * @remarks
98
+ * The public params interface keeps `hmrManager`, `bridge`, and `previewHost`
99
+ * optional so factory callers can omit them. By the time the concrete adapter
100
+ * is constructed, those collaborators are mandatory because the adapter cannot
101
+ * initialize Bun HMR or preview flows without them.
102
+ */
103
+ constructor({ appConfig, runtimeOrigin, serveOptions, apiHandlers, staticRoutes, errorHandler, websocketHandlers, options, hostOwnsDevClient, deferRuntimeAssetSetup, allowPortFallback, hmrManager, bridge, previewHost, }) {
104
+ super({ appConfig, runtimeOrigin, serveOptions, options });
105
+ this.deferRuntimeAssetSetup = deferRuntimeAssetSetup === true;
106
+ this.allowPortFallback = allowPortFallback !== false;
107
+ this.apiHandlers = apiHandlers || [];
108
+ this.staticRoutes = staticRoutes || [];
109
+ this.errorHandler = errorHandler;
110
+ this.bridge = bridge;
111
+ this.hmrManager = hmrManager;
112
+ this.previewHost = previewHost;
113
+ this.hostOwnsDevClient = hostOwnsDevClient === true;
114
+ if (websocketHandlers) {
115
+ this.websocketHandlers = websocketHandlers;
116
+ }
161
117
  }
162
- if (this.options?.watch) {
163
- await this.hmrManager.ensureRuntimeReady();
118
+ /**
119
+ * Wires user WebSocket routes onto a Node HTTP server used by host integrations.
120
+ */
121
+ attachUserWebSocketUpgrades(server, options) {
122
+ attachNodeHttpWebSocketUpgrades(server, {
123
+ runtimeOrigin: this.runtimeOrigin,
124
+ websocketHandlers: this.websocketHandlers,
125
+ passthroughUnmatched: options?.passthroughUnmatched,
126
+ });
164
127
  }
165
- }
166
- /**
167
- * Registers runtime plugins and propagates the final HMR manager into each
168
- * integration.
169
- *
170
- * @remarks
171
- * This is where Bun's runtime-plugin registration path meets the integration
172
- * lifecycle. A failure here leaves the runtime partially bootstrapped, so the
173
- * method logs the underlying error and rethrows instead of trying to limp on.
174
- */
175
- async initializeRuntimePlugins(options) {
176
- try {
177
- this.hmrManager.setEnabled(Boolean(options?.watch));
178
- await setupAppRuntimePlugins({
179
- appConfig: this.appConfig,
180
- runtimeOrigin: this.runtimeOrigin,
181
- onRuntimePlugin: (plugin) => {
182
- this.registerBunRuntimePlugin(plugin);
128
+ /**
129
+ * Initializes the server adapter's core runtime components.
130
+ */
131
+ async initialize() {
132
+ installBuildRuntime(this.appConfig);
133
+ this.staticSiteGenerator = new StaticSiteGenerator({ appConfig: this.appConfig });
134
+ prepareRuntimePublicDir(this.appConfig);
135
+ const staticBuilderOptions = {
136
+ appConfig: this.appConfig,
137
+ staticSiteGenerator: this.staticSiteGenerator,
138
+ serveOptions: this.serveOptions,
139
+ runtimeOrigin: this.runtimeOrigin,
140
+ needsServerBundle: this.apiHandlers.length > 0 || this.websocketHandlers.size > 0,
141
+ hmrManager: this.hmrManager,
142
+ onRuntimePlugin: (plugin) => {
143
+ this.registerBunRuntimePlugin(plugin);
144
+ },
145
+ };
146
+ this.staticBuilder = new ServerStaticBuilder(staticBuilderOptions);
147
+ if (!this.deferRuntimeAssetSetup) {
148
+ await this.initializeRuntimePlugins({ watch: this.options?.watch });
149
+ }
150
+ if (this.options?.watch) {
151
+ await this.hmrManager.ensureRuntimeReady();
183
152
  }
184
- });
185
- if (options?.watch) {
186
- attachHmrToIntegrations(this.appConfig, this.hmrManager);
187
- }
188
- } catch (error) {
189
- appLogger.error(`Failed to initialize plugins: ${error instanceof Error ? error.message : String(error)}`);
190
- throw error;
191
153
  }
192
- }
193
- /**
194
- * Rebuilds the shared routing state and hot-reloads the live Bun server when a
195
- * watched route file changes.
196
- */
197
- async refreshRouterRoutes() {
198
- if (!this.serverInstance || typeof this.serverInstance.reload !== "function") {
199
- appLogger.error("Server instance is not available for reloading");
200
- return;
154
+ /**
155
+ * Registers runtime plugins and propagates the final HMR manager into each
156
+ * integration.
157
+ *
158
+ * @remarks
159
+ * This is where Bun's runtime-plugin registration path meets the integration
160
+ * lifecycle. A failure here leaves the runtime partially bootstrapped, so the
161
+ * method logs the underlying error and rethrows instead of trying to limp on.
162
+ */
163
+ async initializeRuntimePlugins(options) {
164
+ try {
165
+ this.hmrManager.setEnabled(Boolean(options?.watch));
166
+ await setupAppRuntimePlugins({
167
+ appConfig: this.appConfig,
168
+ runtimeOrigin: this.runtimeOrigin,
169
+ onRuntimePlugin: (plugin) => {
170
+ this.registerBunRuntimePlugin(plugin);
171
+ },
172
+ });
173
+ if (options?.watch) {
174
+ attachHmrToIntegrations(this.appConfig, this.hmrManager);
175
+ }
176
+ }
177
+ catch (error) {
178
+ appLogger.error(`Failed to initialize plugins: ${error instanceof Error ? error.message : String(error)}`);
179
+ throw error;
180
+ }
201
181
  }
202
- await this.createSharedWatchRefreshCallback({
203
- staticRoutes: this.staticRoutes,
204
- hmrManager: this.hmrManager,
205
- onRoutesReady: () => {
206
- const options = this.getServerOptions({ enableHmr: true });
207
- this.serverInstance.reload(options);
208
- appLogger.debug("Server routes updated with dynamic routes");
209
- },
210
- onError: (error) => {
211
- this.hmrManager.broadcast({ type: "error", message: error.message });
212
- appLogger.error("Failed to refresh router routes:", error);
213
- }
214
- })();
215
- }
216
- async watch() {
217
- const watcher = new ProjectWatcher({
218
- config: this.appConfig,
219
- refreshRouterRoutesCallback: this.refreshRouterRoutes.bind(this),
220
- hmrManager: this.hmrManager,
221
- bridge: this.bridge,
222
- hostOwnsDevClient: this.hostOwnsDevClient
223
- });
224
- this.projectWatcher = watcher;
225
- await watcher.createWatcherSubscription();
226
- }
227
- /**
228
- * Builds the `Bun.serve()` options for the current adapter state.
229
- *
230
- * @remarks
231
- * When HMR is enabled the websocket dispatcher merges HMR and user handlers,
232
- * routing by the `kind` field embedded in socket data at upgrade time.
233
- * This prevents user-registered websocket handlers from being silently overwritten
234
- * by the HMR handler in development mode.
235
- *
236
- * User WebSocket paths are intercepted in the fetch handler via the pattern matcher.
237
- * The upgrade happens implicitly — no manual GET route registration needed.
238
- */
239
- getServerOptions({ enableHmr = false } = {}) {
240
- appLogger.debug(`[BunServerAdapter] getServerOptions called with enableHmr: ${enableHmr}`);
241
- const serverOptions = this.buildServerSettings();
242
- const hasUserWs = this.websocketHandlers.size > 0;
243
- if (!enableHmr && !hasUserWs) {
244
- return serverOptions;
182
+ /**
183
+ * Rebuilds the shared routing state and hot-reloads the live Bun server when a
184
+ * watched route file changes.
185
+ */
186
+ async refreshRouterRoutes() {
187
+ if (!this.serverInstance || typeof this.serverInstance.reload !== 'function') {
188
+ appLogger.error('Server instance is not available for reloading');
189
+ return;
190
+ }
191
+ await this.createSharedWatchRefreshCallback({
192
+ staticRoutes: this.staticRoutes,
193
+ hmrManager: this.hmrManager,
194
+ onRoutesReady: () => {
195
+ const options = this.getServerOptions({ enableHmr: true });
196
+ this.serverInstance.reload(options);
197
+ appLogger.debug('Server routes updated with dynamic routes');
198
+ },
199
+ onError: (error) => {
200
+ this.hmrManager.broadcast({ type: 'error', message: error.message });
201
+ appLogger.error('Failed to refresh router routes:', error);
202
+ },
203
+ })();
245
204
  }
246
- const userLifecycle = this.createBunUserLifecycle();
247
- if (enableHmr) {
248
- serverOptions.development = true;
249
- serverOptions.websocket = this.createHmrAwareWebSocketHandler(userLifecycle);
250
- } else {
251
- serverOptions.websocket = userLifecycle;
205
+ async watch() {
206
+ const watcher = new ProjectWatcher({
207
+ config: this.appConfig,
208
+ refreshRouterRoutesCallback: this.refreshRouterRoutes.bind(this),
209
+ hmrManager: this.hmrManager,
210
+ bridge: this.bridge,
211
+ hostOwnsDevClient: this.hostOwnsDevClient,
212
+ });
213
+ this.projectWatcher = watcher;
214
+ await watcher.createWatcherSubscription();
252
215
  }
253
- serverOptions.fetch = this.wrapFetchWithWebSocketUpgrades(serverOptions.fetch, {
254
- serveHmrEndpoints: enableHmr
255
- });
256
- return serverOptions;
257
- }
258
- createBunUserLifecycle() {
259
- return createBunUserWebSocketLifecycle({
260
- runtimeOrigin: this.runtimeOrigin,
261
- userHandlers: this.websocketHandlers,
262
- resolveContext: this.resolveBunContext.bind(this),
263
- adaptSocket: (ws, kind, params, search, context) => this.adaptBunWebSocket(ws, kind, params, search, context)
264
- });
265
- }
266
- /**
267
- * @remarks
268
- * HMR and user sockets share one Bun `websocket` handler. Upgrade tags HMR
269
- * connections with `kind: '__hmr__'`; everything else routes to the user lifecycle.
270
- */
271
- createHmrAwareWebSocketHandler(userLifecycle) {
272
- const hmrHandler = this.hmrManager.getWebSocketHandler();
273
- const isHmrSocket = (ws) => (ws.data?.kind ?? "__hmr__") === "__hmr__";
274
- return {
275
- open(ws) {
276
- if (isHmrSocket(ws)) return void hmrHandler.open?.(ws);
277
- userLifecycle.open(ws);
278
- },
279
- message(ws, msg) {
280
- if (isHmrSocket(ws)) return void hmrHandler.message?.(ws, msg);
281
- userLifecycle.message(ws, msg);
282
- },
283
- close(ws, code, reason) {
284
- if (isHmrSocket(ws)) return void hmrHandler.close?.(ws, code, reason);
285
- userLifecycle.close(ws, code, reason);
286
- },
287
- error(ws, error) {
288
- if (isHmrSocket(ws)) return void appLogger.error("[HMR] WebSocket error:", error);
289
- userLifecycle.error(ws, error);
290
- }
291
- };
292
- }
293
- /**
294
- * @remarks
295
- * When `serveHmrEndpoints` is set, `/_hmr` is checked before user websocket
296
- * patterns so HMR upgrades are never captured by app routes. Runtime assets are
297
- * served by `SharedServerAdapter.handleSharedRequest` via `tryHandleAssetRequest`.
298
- * Production mode with only user handlers skips the HMR branch entirely.
299
- */
300
- wrapFetchWithWebSocketUpgrades(originalFetch, { serveHmrEndpoints }) {
301
- const matchRoute = (pathname) => findWebSocketRoute(this.websocketHandlers, pathname);
302
- return async function(request, server) {
303
- const url = new URL(request.url);
304
- if (serveHmrEndpoints) {
305
- if (url.pathname === "/_hmr") {
306
- const success = this.upgrade(request, { data: { kind: "__hmr__", params: {}, search: {} } });
307
- return success ? void 0 : new Response("WebSocket upgrade failed", { status: 400 });
216
+ /**
217
+ * Builds the `Bun.serve()` options for the current adapter state.
218
+ *
219
+ * @remarks
220
+ * When HMR is enabled the websocket dispatcher merges HMR and user handlers,
221
+ * routing by the `kind` field embedded in socket data at upgrade time.
222
+ * This prevents user-registered websocket handlers from being silently overwritten
223
+ * by the HMR handler in development mode.
224
+ *
225
+ * User WebSocket paths are intercepted in the fetch handler via the pattern matcher.
226
+ * The upgrade happens implicitly no manual GET route registration needed.
227
+ */
228
+ getServerOptions({ enableHmr = false } = {}) {
229
+ appLogger.debug(`[BunServerAdapter] getServerOptions called with enableHmr: ${enableHmr}`);
230
+ const serverOptions = this.buildServerSettings();
231
+ const hasUserWs = this.websocketHandlers.size > 0;
232
+ if (!enableHmr && !hasUserWs) {
233
+ return serverOptions;
308
234
  }
309
- }
310
- const wsMatch = matchRoute(url.pathname);
311
- if (wsMatch && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
312
- const search = Object.fromEntries(url.searchParams.entries());
313
- const success = this.upgrade(request, {
314
- data: { kind: wsMatch.kind, params: wsMatch.params, search, upgradeUrl: request.url }
235
+ const userLifecycle = this.createBunUserLifecycle();
236
+ if (enableHmr) {
237
+ serverOptions.development = true;
238
+ serverOptions.websocket = this.createHmrAwareWebSocketHandler(userLifecycle);
239
+ }
240
+ else {
241
+ serverOptions.websocket = userLifecycle;
242
+ }
243
+ serverOptions.fetch = this.wrapFetchWithWebSocketUpgrades(serverOptions.fetch, {
244
+ serveHmrEndpoints: enableHmr,
315
245
  });
316
- return success ? void 0 : new Response("WebSocket upgrade failed", { status: 400 });
317
- }
318
- if (!originalFetch) {
319
- return new Response("Not Found", { status: 404 });
320
- }
321
- const res = await originalFetch.call(this, request, server);
322
- return res instanceof Response ? res : new Response("Not Found", { status: 404 });
323
- };
324
- }
325
- /**
326
- * Composes the base Bun server settings that all runtime modes build from.
327
- *
328
- * @remarks
329
- * This method centralizes the Bun-specific error boundary. It preserves the
330
- * shared route pipeline while still allowing adapter-level custom error-handler
331
- * execution and `HttpError` passthrough.
332
- */
333
- buildServerSettings() {
334
- const serverOptions = { ...this.serveOptions };
335
- const handleNoMatch = this.handleNoMatch.bind(this);
336
- const waitForInit = this.waitForInitialization.bind(this);
337
- const handleReq = this.handleRequest.bind(this);
338
- const errorHandler = this.errorHandler;
339
- const getCacheService = () => this.getCacheService();
340
- const getRenderContext = () => this.getRenderContext();
341
- appLogger.debug(`[BunServerAdapter] Building server settings`);
342
- const finalOptions = {
343
- ...serverOptions,
344
- async fetch(request, _server) {
345
- try {
346
- await waitForInit();
347
- return await handleReq(request);
348
- } catch (error) {
349
- if (error instanceof Response) return error;
350
- if (errorHandler) {
351
- try {
352
- const locals = {};
353
- const context = {
354
- request,
355
- params: {},
356
- response: new ApiResponseBuilder(),
357
- server: _server,
358
- locals,
359
- require: createRequire(() => locals),
360
- services: {
361
- cache: getCacheService()
362
- },
363
- ...getRenderContext()
364
- };
365
- return await errorHandler(error, context);
366
- } catch (handlerError) {
367
- appLogger.error(`[ecopages] Error in custom error handler: ${handlerError}`);
246
+ return serverOptions;
247
+ }
248
+ createBunUserLifecycle() {
249
+ return createBunUserWebSocketLifecycle({
250
+ runtimeOrigin: this.runtimeOrigin,
251
+ userHandlers: this.websocketHandlers,
252
+ resolveContext: this.resolveBunContext.bind(this),
253
+ adaptSocket: (ws, kind, params, search, context) => this.adaptBunWebSocket(ws, kind, params, search, context),
254
+ });
255
+ }
256
+ /**
257
+ * @remarks
258
+ * HMR and user sockets share one Bun `websocket` handler. Upgrade tags HMR
259
+ * connections with `kind: '__hmr__'`; everything else routes to the user lifecycle.
260
+ */
261
+ createHmrAwareWebSocketHandler(userLifecycle) {
262
+ const hmrHandler = this.hmrManager.getWebSocketHandler();
263
+ const isHmrSocket = (ws) => (ws.data?.kind ?? '__hmr__') === '__hmr__';
264
+ return {
265
+ open(ws) {
266
+ if (isHmrSocket(ws))
267
+ return void hmrHandler.open?.(ws);
268
+ userLifecycle.open(ws);
269
+ },
270
+ message(ws, msg) {
271
+ if (isHmrSocket(ws))
272
+ return void hmrHandler.message?.(ws, msg);
273
+ userLifecycle.message(ws, msg);
274
+ },
275
+ close(ws, code, reason) {
276
+ if (isHmrSocket(ws))
277
+ return void hmrHandler.close?.(ws, code, reason);
278
+ userLifecycle.close(ws, code, reason);
279
+ },
280
+ error(ws, error) {
281
+ if (isHmrSocket(ws))
282
+ return void appLogger.error('[HMR] WebSocket error:', error);
283
+ userLifecycle.error(ws, error);
284
+ },
285
+ };
286
+ }
287
+ /**
288
+ * @remarks
289
+ * When `serveHmrEndpoints` is set, `/_hmr` is checked before user websocket
290
+ * patterns so HMR upgrades are never captured by app routes. Runtime assets are
291
+ * served by `SharedServerAdapter.handleSharedRequest` via `tryHandleAssetRequest`.
292
+ * Production mode with only user handlers skips the HMR branch entirely.
293
+ */
294
+ wrapFetchWithWebSocketUpgrades(originalFetch, { serveHmrEndpoints }) {
295
+ const matchRoute = (pathname) => findWebSocketRoute(this.websocketHandlers, pathname);
296
+ return async function (request, server) {
297
+ const url = new URL(request.url);
298
+ if (serveHmrEndpoints) {
299
+ if (url.pathname === '/_hmr') {
300
+ const success = this.upgrade(request, { data: { kind: '__hmr__', params: {}, search: {} } });
301
+ return success ? undefined : new Response('WebSocket upgrade failed', { status: 400 });
302
+ }
368
303
  }
369
- }
370
- if (error instanceof HttpError) return error.toResponse();
371
- appLogger.error(`[ecopages] Error handling request: ${error}`);
372
- return new Response("Internal Server Error", { status: 500 });
373
- }
374
- },
375
- error(error) {
376
- appLogger.error(`[ecopages] Error handling request: ${error}`);
377
- return handleNoMatch(new Request("http://localhost"));
378
- }
379
- };
380
- return finalOptions;
381
- }
382
- /**
383
- * Generates a static build of the site for deployment.
384
- * @param options.preview - If true, starts a preview server after build
385
- */
386
- async buildStatic(options) {
387
- if (!this.fullyInitialized) {
388
- await this.initializeSharedRouteHandling({
389
- staticRoutes: this.staticRoutes,
390
- hmrManager: this.hmrManager
391
- });
304
+ const wsMatch = matchRoute(url.pathname);
305
+ if (wsMatch && request.headers.get('upgrade')?.toLowerCase() === 'websocket') {
306
+ const search = Object.fromEntries(url.searchParams.entries());
307
+ const success = this.upgrade(request, {
308
+ data: { kind: wsMatch.kind, params: wsMatch.params, search, upgradeUrl: request.url },
309
+ });
310
+ return success ? undefined : new Response('WebSocket upgrade failed', { status: 400 });
311
+ }
312
+ if (!originalFetch) {
313
+ return new Response('Not Found', { status: 404 });
314
+ }
315
+ const res = await originalFetch.call(this, request, server);
316
+ return res instanceof Response ? res : new Response('Not Found', { status: 404 });
317
+ };
392
318
  }
393
- const buildRuntimeOrigin = resolveServeRuntimeOrigin(this.serveOptions);
394
- await this.staticBuilder.build(
395
- { baseUrl: buildRuntimeOrigin, force: options?.force },
396
- {
397
- router: this.router,
398
- routeRendererFactory: this.routeRendererFactory,
399
- staticRoutes: this.staticRoutes
400
- }
401
- );
402
- if (!options?.preview) {
403
- return void 0;
319
+ /**
320
+ * Composes the base Bun server settings that all runtime modes build from.
321
+ *
322
+ * @remarks
323
+ * This method centralizes the Bun-specific error boundary. It preserves the
324
+ * shared route pipeline while still allowing adapter-level custom error-handler
325
+ * execution and `HttpError` passthrough.
326
+ */
327
+ buildServerSettings() {
328
+ const serverOptions = { ...this.serveOptions };
329
+ const handleNoMatch = this.handleNoMatch.bind(this);
330
+ const waitForInit = this.waitForInitialization.bind(this);
331
+ const handleReq = this.handleRequest.bind(this);
332
+ const errorHandler = this.errorHandler;
333
+ const getCacheService = () => this.getCacheService();
334
+ const getRenderContext = () => this.getRenderContext();
335
+ appLogger.debug(`[BunServerAdapter] Building server settings`);
336
+ const finalOptions = {
337
+ ...serverOptions,
338
+ async fetch(request, _server) {
339
+ try {
340
+ await waitForInit();
341
+ return await handleReq(request);
342
+ }
343
+ catch (error) {
344
+ if (error instanceof Response)
345
+ return error;
346
+ if (errorHandler) {
347
+ try {
348
+ const locals = {};
349
+ const context = {
350
+ request,
351
+ params: {},
352
+ response: new ApiResponseBuilder(),
353
+ server: _server,
354
+ locals,
355
+ require: createRequire(() => locals),
356
+ services: {
357
+ cache: getCacheService(),
358
+ },
359
+ ...getRenderContext(),
360
+ };
361
+ return await errorHandler(error, context);
362
+ }
363
+ catch (handlerError) {
364
+ appLogger.error(`[ecopages] Error in custom error handler: ${handlerError}`);
365
+ }
366
+ }
367
+ if (error instanceof HttpError)
368
+ return error.toResponse();
369
+ appLogger.error(`[ecopages] Error handling request: ${error}`);
370
+ return new Response('Internal Server Error', { status: 500 });
371
+ }
372
+ },
373
+ error(error) {
374
+ appLogger.error(`[ecopages] Error handling request: ${error}`);
375
+ return handleNoMatch(new Request('http://localhost'));
376
+ },
377
+ };
378
+ return finalOptions;
404
379
  }
405
- return this.startPreviewServer();
406
- }
407
- /**
408
- * Serves an existing static export without running SSG. Used by e2e preview
409
- * launchers after a shared prewarm build.
410
- */
411
- async servePreviewOnly() {
412
- if (!this.fullyInitialized) {
413
- await this.initializeSharedRouteHandling({
414
- staticRoutes: this.staticRoutes,
415
- hmrManager: this.hmrManager
416
- });
380
+ /**
381
+ * Generates a static build of the site for deployment.
382
+ * @param options.preview - If true, starts a preview server after build
383
+ */
384
+ async buildStatic(options) {
385
+ if (!this.fullyInitialized) {
386
+ await this.initializeSharedRouteHandling({
387
+ staticRoutes: this.staticRoutes,
388
+ hmrManager: this.hmrManager,
389
+ });
390
+ }
391
+ const buildRuntimeOrigin = resolveServeRuntimeOrigin(this.serveOptions);
392
+ await this.staticBuilder.build({ baseUrl: buildRuntimeOrigin, force: options?.force }, {
393
+ router: this.router,
394
+ routeRendererFactory: this.routeRendererFactory,
395
+ staticRoutes: this.staticRoutes,
396
+ });
397
+ if (!options?.preview) {
398
+ return undefined;
399
+ }
400
+ return this.startPreviewServer();
417
401
  }
418
- const distPath = path.join(this.appConfig.rootDir, this.appConfig.distDir);
419
- if (!fileSystem.exists(distPath)) {
420
- throw new Error(
421
- `Cannot serve preview without building first: dist directory "${this.appConfig.distDir}" not found in "${this.appConfig.rootDir}".`
422
- );
402
+ /**
403
+ * Serves an existing static export without running SSG. Used by e2e preview
404
+ * launchers after a shared prewarm build.
405
+ */
406
+ async servePreviewOnly() {
407
+ if (!this.fullyInitialized) {
408
+ await this.initializeSharedRouteHandling({
409
+ staticRoutes: this.staticRoutes,
410
+ hmrManager: this.hmrManager,
411
+ });
412
+ }
413
+ const distPath = path.join(this.appConfig.rootDir, this.appConfig.distDir);
414
+ if (!fileSystem.exists(distPath)) {
415
+ throw new Error(`Cannot serve preview without building first: dist directory "${this.appConfig.distDir}" not found in "${this.appConfig.rootDir}".`);
416
+ }
417
+ return this.startPreviewServer();
423
418
  }
424
- return this.startPreviewServer();
425
- }
426
- async startPreviewServer() {
427
- const previewHostname = this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME;
428
- const previewPort = Number(this.serveOptions.port || DEFAULT_ECOPAGES_PORT);
429
- const activePreviewPort = await this.previewHost.start({
430
- appConfig: this.appConfig,
431
- hostname: String(previewHostname),
432
- port: previewPort,
433
- allowPortFallback: this.allowPortFallback
434
- });
435
- if (!activePreviewPort) {
436
- return void 0;
419
+ async startPreviewServer() {
420
+ const previewHostname = this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME;
421
+ const previewPort = Number(this.serveOptions.port || DEFAULT_ECOPAGES_PORT);
422
+ const activePreviewPort = await this.previewHost.start({
423
+ appConfig: this.appConfig,
424
+ hostname: String(previewHostname),
425
+ port: previewPort,
426
+ allowPortFallback: this.allowPortFallback,
427
+ });
428
+ if (!activePreviewPort) {
429
+ return undefined;
430
+ }
431
+ return `http://${previewHostname}:${activePreviewPort}`;
432
+ }
433
+ /**
434
+ * Initializes the server with dynamic routes after server creation.
435
+ * Must be called before handling any requests.
436
+ * @param server - The Bun server instance
437
+ */
438
+ async completeInitialization(server) {
439
+ if (this.fullyInitialized) {
440
+ if (server && !this.serverInstance) {
441
+ this.serverInstance = server;
442
+ }
443
+ return;
444
+ }
445
+ if (!this.initializationPromise) {
446
+ this.initializationPromise = this._performInitialization(server ?? null);
447
+ }
448
+ return this.initializationPromise;
437
449
  }
438
- return `http://${previewHostname}:${activePreviewPort}`;
439
- }
440
- /**
441
- * Initializes the server with dynamic routes after server creation.
442
- * Must be called before handling any requests.
443
- * @param server - The Bun server instance
444
- */
445
- async completeInitialization(server) {
446
- if (this.fullyInitialized) {
447
- if (server && !this.serverInstance) {
450
+ /**
451
+ * Performs the one-time post-bind initialization path for Bun servers.
452
+ *
453
+ * @remarks
454
+ * This is intentionally split from `initialize()` because shared route handling
455
+ * and file watching need the live server instance to exist before Bun can
456
+ * reload updated route handlers in place.
457
+ */
458
+ async _performInitialization(server) {
448
459
  this.serverInstance = server;
449
- }
450
- return;
460
+ appLogger.debug('Completing server initialization with dynamic routes');
461
+ await this.initializeSharedRouteHandling({
462
+ staticRoutes: this.staticRoutes,
463
+ hmrManager: this.hmrManager,
464
+ });
465
+ if (this.options?.watch) {
466
+ await this.hmrManager.ensureRuntimeReady();
467
+ startDevWarmup({
468
+ appConfig: this.appConfig,
469
+ runtimeOrigin: this.runtimeOrigin,
470
+ });
471
+ }
472
+ this.fullyInitialized = true;
473
+ if (this.options?.watch)
474
+ await this.watch();
475
+ if (server && typeof server.reload === 'function') {
476
+ const updatedOptions = this.getServerOptions(this.options?.watch ? { enableHmr: true } : undefined);
477
+ server.reload(updatedOptions);
478
+ appLogger.debug('Server routes updated with dynamic routes');
479
+ }
451
480
  }
452
- if (!this.initializationPromise) {
453
- this.initializationPromise = this._performInitialization(server ?? null);
481
+ /**
482
+ * Creates and initializes the Bun server adapter.
483
+ * @returns Configured adapter with server methods
484
+ */
485
+ async createAdapter() {
486
+ await this.initialize();
487
+ return {
488
+ getServerOptions: this.getServerOptions.bind(this),
489
+ buildStatic: this.buildStatic.bind(this),
490
+ servePreviewOnly: this.servePreviewOnly.bind(this),
491
+ completeInitialization: this.completeInitialization.bind(this),
492
+ handleRequest: this.handleRequest.bind(this),
493
+ attachUserWebSocketUpgrades: this.attachUserWebSocketUpgrades.bind(this),
494
+ listStaticGenerationRoutes: (input) => this.router.listStaticGenerationRoutes(input),
495
+ dispose: this.dispose.bind(this),
496
+ };
454
497
  }
455
- return this.initializationPromise;
456
- }
457
- /**
458
- * Performs the one-time post-bind initialization path for Bun servers.
459
- *
460
- * @remarks
461
- * This is intentionally split from `initialize()` because shared route handling
462
- * and file watching need the live server instance to exist before Bun can
463
- * reload updated route handlers in place.
464
- */
465
- async _performInitialization(server) {
466
- this.serverInstance = server;
467
- appLogger.debug("Completing server initialization with dynamic routes");
468
- await this.initializeSharedRouteHandling({
469
- staticRoutes: this.staticRoutes,
470
- hmrManager: this.hmrManager
471
- });
472
- if (this.options?.watch) {
473
- await this.hmrManager.ensureRuntimeReady();
474
- startConfiguredIntegrationRuntimePrewarm({
475
- appConfig: this.appConfig,
476
- runtimeOrigin: this.runtimeOrigin
477
- });
498
+ /**
499
+ * Releases dev-time resources owned by the adapter.
500
+ *
501
+ * @remarks
502
+ * Safe to call multiple times. Does not stop the bound Bun server — callers
503
+ * should shut down transport through the runtime host before disposing.
504
+ */
505
+ async dispose() {
506
+ if (this.adapterDisposed) {
507
+ return;
508
+ }
509
+ this.adapterDisposed = true;
510
+ await disposeDevResources({
511
+ projectWatcher: this.projectWatcher,
512
+ appConfig: this.appConfig,
513
+ hmrManager: this.hmrManager,
514
+ bridge: this.bridge,
515
+ previewHost: this.previewHost,
516
+ });
517
+ this.projectWatcher = null;
478
518
  }
479
- this.fullyInitialized = true;
480
- if (this.options?.watch) await this.watch();
481
- if (server && typeof server.reload === "function") {
482
- const updatedOptions = this.getServerOptions(this.options?.watch ? { enableHmr: true } : void 0);
483
- server.reload(updatedOptions);
484
- appLogger.debug("Server routes updated with dynamic routes");
519
+ /**
520
+ * Handles HTTP requests by passing them securely to the shared core router adapter.
521
+ *
522
+ * @remarks
523
+ * HMR HTML injection for API and page responses is owned by
524
+ * `SharedServerAdapter.handleSharedRequest`. This method only maps the
525
+ * request into the shared pipeline.
526
+ */
527
+ async handleRequest(request) {
528
+ const response = await this.handleSharedRequest(request, {
529
+ apiHandlers: this.apiHandlers,
530
+ errorHandler: this.errorHandler,
531
+ serverInstance: this.serverInstance,
532
+ hmrManager: this.hmrManager,
533
+ });
534
+ return response;
485
535
  }
486
- }
487
- /**
488
- * Creates and initializes the Bun server adapter.
489
- * @returns Configured adapter with server methods
490
- */
491
- async createAdapter() {
492
- await this.initialize();
493
- return {
494
- getServerOptions: this.getServerOptions.bind(this),
495
- buildStatic: this.buildStatic.bind(this),
496
- servePreviewOnly: this.servePreviewOnly.bind(this),
497
- completeInitialization: this.completeInitialization.bind(this),
498
- handleRequest: this.handleRequest.bind(this),
499
- attachUserWebSocketUpgrades: this.attachUserWebSocketUpgrades.bind(this),
500
- listStaticGenerationRoutes: (input) => this.router.listStaticGenerationRoutes(input),
501
- dispose: this.dispose.bind(this)
502
- };
503
- }
504
- /**
505
- * Releases dev-time resources owned by the adapter.
506
- *
507
- * @remarks
508
- * Safe to call multiple times. Does not stop the bound Bun server — callers
509
- * should shut down transport through the runtime host before disposing.
510
- */
511
- async dispose() {
512
- if (this.adapterDisposed) {
513
- return;
536
+ /**
537
+ * Ensures server initialization completes before request handling.
538
+ * Prevents race conditions during startup.
539
+ */
540
+ async waitForInitialization() {
541
+ if (this.fullyInitialized) {
542
+ return;
543
+ }
544
+ if (this.initializationPromise) {
545
+ return this.initializationPromise;
546
+ }
547
+ throw new Error('Server not initialized. Call completeInitialization() first.');
514
548
  }
515
- this.adapterDisposed = true;
516
- await disposeDevResources({
517
- projectWatcher: this.projectWatcher,
518
- appConfig: this.appConfig,
519
- hmrManager: this.hmrManager,
520
- bridge: this.bridge,
521
- previewHost: this.previewHost
522
- });
523
- this.projectWatcher = null;
524
- }
525
- /**
526
- * Handles HTTP requests by passing them securely to the shared core router adapter.
527
- *
528
- * @remarks
529
- * HMR HTML injection for API and page responses is owned by
530
- * `SharedServerAdapter.handleSharedRequest`. This method only maps the
531
- * request into the shared pipeline.
532
- */
533
- async handleRequest(request) {
534
- const response = await this.handleSharedRequest(request, {
535
- apiHandlers: this.apiHandlers,
536
- errorHandler: this.errorHandler,
537
- serverInstance: this.serverInstance,
538
- hmrManager: this.hmrManager
539
- });
540
- return response;
541
- }
542
- /**
543
- * Ensures server initialization completes before request handling.
544
- * Prevents race conditions during startup.
545
- */
546
- async waitForInitialization() {
547
- if (this.fullyInitialized) {
548
- return;
549
+ /**
550
+ * Handles HTTP requests from the router adapter.
551
+ */
552
+ async handleResponse(request) {
553
+ await this.waitForInitialization();
554
+ return this.routeHandler.handleResponse(request);
549
555
  }
550
- if (this.initializationPromise) {
551
- return this.initializationPromise;
556
+ /**
557
+ * Handles requests that do not match any routes.
558
+ */
559
+ async handleNoMatch(request) {
560
+ await this.waitForInitialization();
561
+ return this.routeHandler.handleNoMatch(request);
552
562
  }
553
- throw new Error("Server not initialized. Call completeInitialization() first.");
554
- }
555
- /**
556
- * Handles HTTP requests from the router adapter.
557
- */
558
- async handleResponse(request) {
559
- await this.waitForInitialization();
560
- return this.routeHandler.handleResponse(request);
561
- }
562
- /**
563
- * Handles requests that do not match any routes.
564
- */
565
- async handleNoMatch(request) {
566
- await this.waitForInitialization();
567
- return this.routeHandler.handleNoMatch(request);
568
- }
569
563
  }
570
- async function createBunServerAdapter(params) {
571
- const runtimeOrigin = params.runtimeOrigin ?? resolveServeRuntimeOrigin(params.serveOptions);
572
- const bridge = params.bridge ?? new ClientBridge();
573
- const hmrManager = params.hmrManager ?? new HmrManager({ appConfig: params.appConfig, bridge });
574
- setAppDevClientBridge(params.appConfig, bridge);
575
- setAppHmrManager(params.appConfig, hmrManager);
576
- const previewHost = params.previewHost ?? new BunStaticPreviewHost();
577
- const adapter = new BunServerAdapter({
578
- ...params,
579
- runtimeOrigin,
580
- bridge,
581
- hmrManager,
582
- previewHost
583
- });
584
- return adapter.createAdapter();
564
+ /**
565
+ * Creates the Bun server adapter and fills in the runtime-specific collaborators
566
+ * that Bun callers usually leave implicit.
567
+ *
568
+ * @remarks
569
+ * This is the canonical entry point for Bun server-adapter construction. It
570
+ * guarantees that the concrete adapter receives a Bun websocket bridge, HMR
571
+ * manager, and preview host even though those dependencies are optional on the
572
+ * public params type.
573
+ */
574
+ export async function createBunServerAdapter(params) {
575
+ const runtimeOrigin = params.runtimeOrigin ?? resolveServeRuntimeOrigin(params.serveOptions);
576
+ const bridge = params.bridge ?? new ClientBridge();
577
+ const hmrManager = params.hmrManager ?? new HmrManager({ appConfig: params.appConfig, bridge });
578
+ setAppDevClientBridge(params.appConfig, bridge);
579
+ setAppHmrManager(params.appConfig, hmrManager);
580
+ const previewHost = params.previewHost ?? new BunStaticPreviewHost();
581
+ const adapter = new BunServerAdapter({
582
+ ...params,
583
+ runtimeOrigin,
584
+ bridge,
585
+ hmrManager,
586
+ previewHost,
587
+ });
588
+ return adapter.createAdapter();
585
589
  }
586
- export {
587
- BunServerAdapter,
588
- createBunServerAdapter
589
- };