@ecopages/core 0.2.0-beta.2 → 0.2.0-beta.21

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 (273) hide show
  1. package/README.md +1 -1
  2. package/package.json +163 -3
  3. package/src/adapters/abstract/application-adapter.d.ts +104 -5
  4. package/src/adapters/abstract/application-adapter.js +125 -1
  5. package/src/adapters/abstract/server-adapter.d.ts +6 -2
  6. package/src/adapters/abstract/ws-pattern-matcher.d.ts +60 -0
  7. package/src/adapters/abstract/ws-pattern-matcher.js +61 -0
  8. package/src/adapters/bun/client-bridge.d.ts +1 -0
  9. package/src/adapters/bun/client-bridge.js +3 -0
  10. package/src/adapters/bun/create-app.d.ts +6 -4
  11. package/src/adapters/bun/create-app.js +65 -43
  12. package/src/adapters/bun/server-adapter.d.ts +90 -22
  13. package/src/adapters/bun/server-adapter.js +266 -84
  14. package/src/adapters/bun/static-preview-host.js +25 -20
  15. package/src/adapters/create-app.d.ts +13 -11
  16. package/src/adapters/create-app.js +2 -51
  17. package/src/adapters/index.d.ts +1 -1
  18. package/src/adapters/index.js +1 -2
  19. package/src/adapters/node/create-app.d.ts +5 -1
  20. package/src/adapters/node/create-app.js +51 -12
  21. package/src/adapters/node/node-client-bridge.d.ts +1 -0
  22. package/src/adapters/node/node-client-bridge.js +3 -0
  23. package/src/adapters/node/server-adapter-dependencies.js +4 -0
  24. package/src/adapters/node/server-adapter.d.ts +62 -20
  25. package/src/adapters/node/server-adapter.js +160 -131
  26. package/src/adapters/node/static-content-server.d.ts +1 -0
  27. package/src/adapters/node/static-content-server.js +10 -2
  28. package/src/adapters/node/static-preview-host.js +27 -12
  29. package/src/adapters/shared/bun-user-websocket-lifecycle.d.ts +22 -0
  30. package/src/adapters/shared/bun-user-websocket-lifecycle.js +96 -0
  31. package/src/adapters/shared/copy-runtime-public-dir.d.ts +6 -0
  32. package/src/adapters/shared/copy-runtime-public-dir.js +24 -0
  33. package/src/adapters/shared/fs-server-response-matcher.d.ts +2 -0
  34. package/src/adapters/shared/fs-server-response-matcher.js +40 -18
  35. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +21 -30
  36. package/src/adapters/shared/hmr-entrypoint-registrar.js +49 -54
  37. package/src/adapters/shared/hmr-html-response.d.ts +1 -1
  38. package/src/adapters/shared/hmr-html-response.js +4 -1
  39. package/src/adapters/shared/node-http-websocket-upgrades.d.ts +21 -0
  40. package/src/adapters/shared/node-http-websocket-upgrades.js +100 -0
  41. package/src/adapters/shared/port-manager.d.ts +116 -0
  42. package/src/adapters/shared/port-manager.js +196 -0
  43. package/src/adapters/shared/runtime-app-bootstrap.d.ts +2 -1
  44. package/src/adapters/shared/runtime-app-bootstrap.js +3 -6
  45. package/src/adapters/shared/runtime-server-lifecycle.d.ts +46 -0
  46. package/src/adapters/shared/runtime-server-lifecycle.js +50 -0
  47. package/src/adapters/shared/server-adapter.d.ts +2 -1
  48. package/src/adapters/shared/server-adapter.js +13 -6
  49. package/src/adapters/shared/server-route-handler.d.ts +4 -1
  50. package/src/adapters/shared/server-route-handler.js +5 -2
  51. package/src/adapters/shared/server-static-builder.d.ts +23 -32
  52. package/src/adapters/shared/server-static-builder.js +100 -73
  53. package/src/adapters/shared/shared-hmr-manager.d.ts +45 -11
  54. package/src/adapters/shared/shared-hmr-manager.js +204 -58
  55. package/src/adapters/shared/static-preview-host.d.ts +5 -0
  56. package/src/adapters/shared/websocket-lifecycle.d.ts +24 -0
  57. package/src/adapters/shared/websocket-lifecycle.js +55 -0
  58. package/src/build/README.md +77 -14
  59. package/src/build/app-build-manifest-runtime.d.ts +9 -0
  60. package/src/build/app-build-manifest-runtime.js +87 -0
  61. package/src/build/build-adapter.d.ts +17 -319
  62. package/src/build/build-adapter.js +28 -94
  63. package/src/build/build-contracts.d.ts +97 -0
  64. package/src/build/build-contracts.js +0 -0
  65. package/src/build/build-input-fingerprint.d.ts +28 -0
  66. package/src/build/build-input-fingerprint.js +31 -0
  67. package/src/build/build-profile-options.d.ts +7 -0
  68. package/src/build/build-profile-options.js +37 -0
  69. package/src/build/build-runtime.d.ts +24 -0
  70. package/src/build/build-runtime.js +65 -0
  71. package/src/build/deduping-build-executor.d.ts +28 -0
  72. package/src/build/deduping-build-executor.js +56 -0
  73. package/src/build/jsx-ownership-plugins.d.ts +24 -0
  74. package/src/build/jsx-ownership-plugins.js +41 -0
  75. package/src/build/pages-unified-graph-build.d.ts +31 -0
  76. package/src/build/pages-unified-graph-build.js +206 -0
  77. package/src/build/parallel-build-executor.d.ts +21 -0
  78. package/src/build/parallel-build-executor.js +52 -0
  79. package/src/build/production-build-cache.d.ts +20 -0
  80. package/src/build/production-build-cache.js +63 -0
  81. package/src/build/rolldown-adapter-helpers.d.ts +3 -6
  82. package/src/build/rolldown-adapter-helpers.js +71 -6
  83. package/src/build/rolldown-build-adapter.d.ts +2 -6
  84. package/src/build/rolldown-build-adapter.js +3 -3
  85. package/src/build/rolldown-build-invocation-metrics.d.ts +12 -0
  86. package/src/build/rolldown-build-invocation-metrics.js +43 -0
  87. package/src/build/rolldown-plugin-bridge.d.ts +15 -1
  88. package/src/build/rolldown-plugin-bridge.js +20 -5
  89. package/src/build/rolldown-source-transform-pass.d.ts +15 -0
  90. package/src/build/rolldown-source-transform-pass.js +58 -0
  91. package/src/build/runtime-build-executor.d.ts +8 -15
  92. package/src/build/runtime-build-executor.js +12 -15
  93. package/src/build/runtime-build-output-normalizer.d.ts +7 -0
  94. package/src/build/runtime-build-output-normalizer.js +94 -2
  95. package/src/build/server-entry-build-cache.d.ts +44 -0
  96. package/src/build/server-entry-build-cache.js +161 -0
  97. package/src/client/navigation-scripts/classification.d.ts +16 -0
  98. package/src/client/navigation-scripts/classification.js +41 -0
  99. package/src/client/navigation-scripts/index.d.ts +3 -0
  100. package/src/client/navigation-scripts/index.js +23 -0
  101. package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
  102. package/src/client/navigation-scripts/registry.d.ts +11 -0
  103. package/src/client/navigation-scripts/registry.js +12 -0
  104. package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
  105. package/src/client/navigation-scripts/rerun-queue.js +73 -0
  106. package/src/client/scroll.d.ts +17 -0
  107. package/src/client/scroll.js +25 -0
  108. package/src/client/scroll.test.browser.js +37 -0
  109. package/src/client/view-transitions.d.ts +16 -0
  110. package/src/client/view-transitions.js +63 -0
  111. package/src/config/config-builder.d.ts +12 -7
  112. package/src/config/config-builder.js +12 -9
  113. package/src/dev/client-bridge-registry.d.ts +5 -0
  114. package/src/dev/client-bridge-registry.js +15 -0
  115. package/src/dev/dev-client-ownership.d.ts +7 -0
  116. package/src/dev/dev-client-ownership.js +6 -0
  117. package/src/dev/hmr-manager-registry.d.ts +8 -0
  118. package/src/dev/hmr-manager-registry.js +15 -0
  119. package/src/dev/host-runtime.d.ts +3 -0
  120. package/src/dev/host-runtime.js +7 -0
  121. package/src/dev/runtime-server-started-message.d.ts +2 -0
  122. package/src/dev/runtime-server-started-message.js +6 -0
  123. package/src/eco/README.md +11 -0
  124. package/src/eco/eco-declared-component.d.ts +14 -0
  125. package/src/eco/eco-declared-component.js +16 -0
  126. package/src/eco/eco.browser.js +5 -6
  127. package/src/eco/eco.js +5 -6
  128. package/src/eco/eco.types.d.ts +2 -2
  129. package/src/eco/page-layout-normalization.d.ts +21 -0
  130. package/src/eco/page-layout-normalization.js +59 -0
  131. package/src/errors/index.d.ts +1 -0
  132. package/src/errors/index.js +7 -1
  133. package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
  134. package/src/errors/undeclared-component-dependency-error.js +17 -0
  135. package/src/hmr/client/hmr-runtime.js +5 -2
  136. package/src/hmr/hmr-entrypoint-output.d.ts +43 -0
  137. package/src/hmr/hmr-entrypoint-output.js +53 -0
  138. package/src/hmr/hmr-strategy.d.ts +15 -0
  139. package/src/hmr/hmr-strategy.js +19 -0
  140. package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -5
  141. package/src/hmr/strategies/js-hmr-strategy.js +67 -19
  142. package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
  143. package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
  144. package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
  145. package/src/integrations/ghtml/ghtml-renderer.js +2 -51
  146. package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
  147. package/src/integrations/ghtml/ghtml.plugin.js +7 -14
  148. package/src/plugins/define-integration.d.ts +26 -0
  149. package/src/plugins/define-integration.js +19 -0
  150. package/src/plugins/eco-component-meta-plugin.js +5 -8
  151. package/src/plugins/foreign-jsx-override-plugin.js +4 -6
  152. package/src/plugins/integration-plugin.d.ts +19 -9
  153. package/src/plugins/integration-plugin.js +7 -4
  154. package/src/plugins/jsx-import-source.utils.d.ts +8 -0
  155. package/src/plugins/jsx-import-source.utils.js +26 -0
  156. package/src/plugins/processor.d.ts +19 -4
  157. package/src/plugins/processor.js +22 -4
  158. package/src/plugins/source-transform.d.ts +31 -0
  159. package/src/plugins/source-transform.js +23 -1
  160. package/src/route-renderer/GRAPH.md +8 -8
  161. package/src/route-renderer/README.md +30 -28
  162. package/src/route-renderer/orchestration/component-graph-collectors.d.ts +10 -0
  163. package/src/route-renderer/orchestration/component-graph-collectors.js +143 -0
  164. package/src/route-renderer/orchestration/component-graph.d.ts +36 -0
  165. package/src/route-renderer/orchestration/component-graph.js +98 -0
  166. package/src/route-renderer/orchestration/component-render-context.d.ts +3 -10
  167. package/src/route-renderer/orchestration/component-render-context.js +3 -1
  168. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +1 -18
  169. package/src/route-renderer/orchestration/declared-ownership-graph.js +5 -31
  170. package/src/route-renderer/orchestration/document-shell-render.service.d.ts +90 -0
  171. package/src/route-renderer/orchestration/document-shell-render.service.js +120 -0
  172. package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +59 -29
  173. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +164 -35
  174. package/src/route-renderer/orchestration/global-injector-assets.service.d.ts +7 -0
  175. package/src/route-renderer/orchestration/global-injector-assets.service.js +32 -0
  176. package/src/route-renderer/orchestration/integration-renderer.d.ts +18 -54
  177. package/src/route-renderer/orchestration/integration-renderer.js +113 -195
  178. package/src/route-renderer/orchestration/integration-route-render-adapter.d.ts +38 -0
  179. package/src/route-renderer/orchestration/integration-route-render-adapter.js +27 -0
  180. package/src/route-renderer/orchestration/layout-shell-props.service.d.ts +20 -0
  181. package/src/route-renderer/orchestration/layout-shell-props.service.js +31 -0
  182. package/src/route-renderer/orchestration/ownership-validation.service.d.ts +5 -0
  183. package/src/route-renderer/orchestration/ownership-validation.service.js +29 -1
  184. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.d.ts +9 -0
  185. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.js +7 -0
  186. package/src/route-renderer/orchestration/page-browser-graph.service.d.ts +25 -0
  187. package/src/route-renderer/orchestration/page-browser-graph.service.js +174 -0
  188. package/src/route-renderer/orchestration/render-output.utils.d.ts +2 -0
  189. package/src/route-renderer/orchestration/render-output.utils.js +4 -0
  190. package/src/route-renderer/orchestration/route-html-finalization.service.d.ts +17 -0
  191. package/src/route-renderer/orchestration/route-html-finalization.service.js +26 -0
  192. package/src/route-renderer/orchestration/route-prepared-options.builder.d.ts +26 -0
  193. package/src/route-renderer/orchestration/route-prepared-options.builder.js +54 -0
  194. package/src/route-renderer/orchestration/route-prepared-options.utils.d.ts +4 -0
  195. package/src/route-renderer/orchestration/route-prepared-options.utils.js +33 -0
  196. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +8 -39
  197. package/src/route-renderer/orchestration/route-render-orchestrator.js +53 -461
  198. package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
  199. package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
  200. package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
  201. package/src/router/client/link-intent.d.ts +11 -21
  202. package/src/router/client/link-intent.js +10 -0
  203. package/src/router/client/link-intent.test.browser.js +12 -1
  204. package/src/router/client/link-navigation-policy.d.ts +45 -0
  205. package/src/router/client/link-navigation-policy.js +101 -0
  206. package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
  207. package/src/router/client/link-navigation-policy.test.browser.js +92 -0
  208. package/src/router/client/navigation-coordinator.d.ts +1 -1
  209. package/src/router/client/navigation-coordinator.js +12 -2
  210. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -0
  211. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
  212. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
  213. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +27 -7
  214. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -1
  215. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +18 -15
  216. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
  217. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
  218. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
  219. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
  220. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
  221. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
  222. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
  223. package/src/services/assets/browser-bundle.service.d.ts +3 -1
  224. package/src/services/assets/browser-bundle.service.js +17 -5
  225. package/src/services/html/html-transformer.service.d.ts +1 -1
  226. package/src/services/html/html-transformer.service.js +4 -4
  227. package/src/services/invalidation/development-invalidation.service.d.ts +20 -2
  228. package/src/services/invalidation/development-invalidation.service.js +56 -2
  229. package/src/services/module-loading/README.md +49 -0
  230. package/src/services/module-loading/app-server-module-transpiler.service.js +5 -17
  231. package/src/services/module-loading/page-module-import.service.d.ts +5 -1
  232. package/src/services/module-loading/page-module-import.service.js +96 -45
  233. package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
  234. package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
  235. package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
  236. package/src/services/module-loading/route-module-build-cache.js +38 -0
  237. package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
  238. package/src/services/module-loading/route-module-build-cache.store.js +207 -0
  239. package/src/services/module-loading/route-module-build-manifest.d.ts +61 -0
  240. package/src/services/module-loading/route-module-build-manifest.js +116 -0
  241. package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
  242. package/src/services/module-loading/route-module-dependency-hasher.js +122 -0
  243. package/src/services/module-loading/server-module-transpiler.service.js +1 -1
  244. package/src/static-site-generator/README.md +33 -0
  245. package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
  246. package/src/static-site-generator/static-build-invalidation.js +59 -0
  247. package/src/static-site-generator/static-export-context.d.ts +22 -0
  248. package/src/static-site-generator/static-export-context.js +0 -0
  249. package/src/static-site-generator/static-site-generator.d.ts +17 -20
  250. package/src/static-site-generator/static-site-generator.js +188 -85
  251. package/src/types/internal-types.d.ts +16 -9
  252. package/src/types/public-types.d.ts +144 -40
  253. package/src/utils/parse-cli-args.d.ts +2 -0
  254. package/src/utils/parse-cli-args.js +6 -0
  255. package/src/utils/server-utils.module.d.ts +3 -2
  256. package/src/utils/server-utils.module.js +5 -6
  257. package/src/utils/static-file-extensions.d.ts +12 -0
  258. package/src/utils/static-file-extensions.js +48 -0
  259. package/src/watchers/project-watcher-ignore.d.ts +11 -0
  260. package/src/watchers/project-watcher-ignore.js +16 -0
  261. package/src/watchers/project-watcher.d.ts +26 -3
  262. package/src/watchers/project-watcher.js +132 -30
  263. package/src/watchers/project-watcher.test-helpers.js +5 -5
  264. package/src/build/rolldown-dev-build-adapter.d.ts +0 -82
  265. package/src/build/rolldown-dev-build-adapter.js +0 -166
  266. package/src/hmr/hmr.postcss.test.e2e.js +0 -31
  267. package/src/hmr/hmr.test.e2e.js +0 -43
  268. package/src/route-renderer/orchestration/ownership-planning.service.d.ts +0 -24
  269. package/src/route-renderer/orchestration/ownership-planning.service.js +0 -63
  270. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +0 -91
  271. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +0 -170
  272. /package/src/{hmr/hmr.postcss.test.e2e.d.ts → client/navigation-scripts/navigation-scripts.test.browser.d.ts} +0 -0
  273. /package/src/{hmr/hmr.test.e2e.d.ts → client/scroll.test.browser.d.ts} +0 -0
@@ -1,22 +1,25 @@
1
- import { createServer } from "node:http";
1
+ import {} from "node:http";
2
2
  import path from "node:path";
3
3
  import { fileSystem } from "@ecopages/file-system";
4
- import { getAppBrowserBuildPlugins, setupAppRuntimePlugins } from "../../build/build-adapter.js";
4
+ import { setupAppRuntimePlugins } from "../../build/build-adapter.js";
5
5
  import { installAppRuntimeBuildExecutor } from "../../build/runtime-build-executor.js";
6
- import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
7
6
  import { appLogger } from "../../global/app-logger.js";
8
7
  import { NodeClientBridge } from "./node-client-bridge.js";
9
8
  import { NodeHmrManager } from "./node-hmr-manager.js";
10
9
  import { ProjectWatcher } from "../../watchers/project-watcher.js";
10
+ import {
11
+ attachNodeHttpWebSocketUpgrades
12
+ } from "../shared/node-http-websocket-upgrades.js";
11
13
  import { StaticSiteGenerator } from "../../static-site-generator/static-site-generator.js";
12
14
  import { SharedServerAdapter } from "../shared/server-adapter.js";
13
15
  import { ServerStaticBuilder } from "../shared/server-static-builder.js";
14
16
  import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT } from "../../config/constants.js";
15
17
  import {
16
- injectHmrRuntimeIntoHtmlResponse,
17
- isHtmlResponse,
18
- shouldInjectHmrHtmlResponse
19
- } from "../shared/hmr-html-response.js";
18
+ attachHmrToIntegrations,
19
+ disposeDevResources,
20
+ maybeInjectAdapterHmrHtmlResponse,
21
+ prepareRuntimePublicDir
22
+ } from "../shared/runtime-server-lifecycle.js";
20
23
  import { resolveServeRuntimeOrigin } from "../shared/runtime-app-bootstrap.js";
21
24
  import { NodeClientAbortError, NodeHttpRequestBridge } from "./http-request-bridge.js";
22
25
  import { NodeStaticPreviewHost } from "./static-preview-host.js";
@@ -29,29 +32,73 @@ class NodeServerAdapter extends SharedServerAdapter {
29
32
  errorHandler;
30
33
  bridge = null;
31
34
  hmrManager = null;
35
+ projectWatcher = null;
36
+ adapterDisposed = false;
37
+ deferRuntimeAssetSetup;
38
+ allowPortFallback;
32
39
  previewHost;
33
40
  requestBridge;
34
41
  devRuntimeFactory;
35
- shouldInjectHmrScript() {
36
- return shouldInjectHmrHtmlResponse(this.options?.watch === true, this.hmrManager ?? void 0);
42
+ /**
43
+ * Reference to the application-level WebSocket handlers map.
44
+ *
45
+ * @remarks
46
+ * This is a reference to the map owned by `AbstractApplicationAdapter`,
47
+ * passed in via the constructor. The Node adapter reads from it to wire
48
+ * WebSocket upgrades for user-registered patterns.
49
+ */
50
+ websocketHandlers = /* @__PURE__ */ new Map();
51
+ /**
52
+ * Wires user WebSocket routes onto a foreign Node HTTP server.
53
+ *
54
+ * Host integrations such as the Vite plugin call this so `app.websocket()`
55
+ * handlers work while HTTP is still served by the host dev server.
56
+ */
57
+ attachUserWebSocketUpgrades(server, options) {
58
+ attachNodeHttpWebSocketUpgrades(server, {
59
+ runtimeOrigin: this.runtimeOrigin,
60
+ websocketHandlers: this.websocketHandlers,
61
+ passthroughUnmatched: options?.passthroughUnmatched
62
+ });
37
63
  }
38
- isHtmlResponse(response) {
39
- return isHtmlResponse(response);
64
+ wireUserWebSocketUpgrades(server, preflight) {
65
+ attachNodeHttpWebSocketUpgrades(server, {
66
+ runtimeOrigin: this.runtimeOrigin,
67
+ websocketHandlers: this.websocketHandlers,
68
+ passthroughUnmatched: false,
69
+ preflight
70
+ });
40
71
  }
41
72
  async maybeInjectHmrScript(response) {
42
- if (this.shouldInjectHmrScript() && this.isHtmlResponse(response)) {
43
- return injectHmrRuntimeIntoHtmlResponse(response);
44
- }
45
- return response;
73
+ return maybeInjectAdapterHmrHtmlResponse(response, {
74
+ watch: this.options?.watch === true,
75
+ hmrManager: this.hmrManager ?? void 0,
76
+ hostOwnsDevClient: this.hostOwnsDevClient
77
+ });
46
78
  }
79
+ /**
80
+ * @remarks
81
+ * `previewHost`, `requestBridge`, and `devRuntimeFactory` are optional on the
82
+ * public {@link NodeServerAdapterParams} so factory callers can omit them, but
83
+ * they are mandatory by the time the concrete adapter is constructed —
84
+ * {@link createNodeServerAdapter} fills in Node-specific defaults first. The
85
+ * constructor signature makes that invariant explicit instead of relying on
86
+ * non-null assertions.
87
+ */
47
88
  constructor(options) {
48
89
  super(options);
90
+ this.deferRuntimeAssetSetup = options.deferRuntimeAssetSetup === true;
91
+ this.allowPortFallback = options.allowPortFallback !== false;
49
92
  this.apiHandlers = options.apiHandlers || [];
50
93
  this.staticRoutes = options.staticRoutes || [];
51
94
  this.errorHandler = options.errorHandler;
52
95
  this.previewHost = options.previewHost;
53
96
  this.requestBridge = options.requestBridge;
54
97
  this.devRuntimeFactory = options.devRuntimeFactory;
98
+ if (options.websocketHandlers) {
99
+ this.websocketHandlers = options.websocketHandlers;
100
+ }
101
+ this.hostOwnsDevClient = options.hostOwnsDevClient === true;
55
102
  }
56
103
  /**
57
104
  * Prepares the adapter for use.
@@ -68,12 +115,13 @@ class NodeServerAdapter extends SharedServerAdapter {
68
115
  */
69
116
  async initialize() {
70
117
  installAppRuntimeBuildExecutor(this.appConfig);
71
- this.prepareRuntimePublicDir();
72
- await setupAppRuntimePlugins({
73
- appConfig: this.appConfig,
74
- runtimeOrigin: this.runtimeOrigin,
75
- hmrManager: this.hmrManager ?? void 0
76
- });
118
+ prepareRuntimePublicDir(this.appConfig);
119
+ if (!this.deferRuntimeAssetSetup) {
120
+ await setupAppRuntimePlugins({
121
+ appConfig: this.appConfig,
122
+ runtimeOrigin: this.runtimeOrigin
123
+ });
124
+ }
77
125
  await this.initializeSharedRouteHandling({
78
126
  staticRoutes: this.staticRoutes,
79
127
  hmrManager: this.hmrManager ?? void 0
@@ -83,17 +131,12 @@ class NodeServerAdapter extends SharedServerAdapter {
83
131
  appConfig: this.appConfig,
84
132
  staticSiteGenerator: this.staticSiteGenerator,
85
133
  serveOptions: this.serveOptions,
86
- apiHandlers: this.apiHandlers
134
+ runtimeOrigin: this.runtimeOrigin,
135
+ needsServerBundle: this.apiHandlers.length > 0 || this.websocketHandlers.size > 0,
136
+ hmrManager: this.hmrManager ?? void 0
87
137
  });
88
138
  this.initialized = true;
89
139
  }
90
- prepareRuntimePublicDir() {
91
- const srcPublicDir = path.join(this.appConfig.rootDir, this.appConfig.srcDir, this.appConfig.publicDir);
92
- if (fileSystem.exists(srcPublicDir)) {
93
- fileSystem.copyDir(srcPublicDir, path.join(this.appConfig.rootDir, this.appConfig.distDir));
94
- }
95
- fileSystem.ensureDir(path.join(this.appConfig.absolutePaths.distDir, RESOLVED_ASSETS_DIR));
96
- }
97
140
  getServerOptions() {
98
141
  return {
99
142
  ...this.serveOptions
@@ -103,106 +146,84 @@ class NodeServerAdapter extends SharedServerAdapter {
103
146
  if (!this.initialized) {
104
147
  await this.initialize();
105
148
  }
106
- const buildServer = await this.startBuildRuntimeServer();
107
- const buildRuntimeOrigin = this.getListeningServerOrigin(buildServer);
108
- try {
109
- await this.staticBuilder.build(
110
- { preview: false, baseUrl: buildRuntimeOrigin },
111
- {
112
- router: this.router,
113
- routeRendererFactory: this.routeRendererFactory,
114
- staticRoutes: this.staticRoutes
115
- }
116
- );
117
- } finally {
118
- await this.stopBuildRuntimeServer(buildServer);
119
- }
120
- if (!options?.preview) {
121
- return;
122
- }
123
- await this.previewHost.start({
124
- appConfig: this.appConfig,
125
- hostname: String(this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME),
126
- port: Number(this.serveOptions.port || DEFAULT_ECOPAGES_PORT)
127
- });
128
- const previewHostname = this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME;
129
- const previewPort = this.serveOptions.port || DEFAULT_ECOPAGES_PORT;
130
- appLogger.info(`Preview running at http://${previewHostname}:${previewPort}`);
131
- }
132
- async startBuildRuntimeServer() {
133
- const hostname = String(this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME);
134
- const port = 0;
135
- const server = createServer(async (req, res) => {
136
- try {
137
- const webRequest = this.requestBridge.createWebRequest(req, this.runtimeOrigin);
138
- const response = await this.handleRequest(webRequest);
139
- await this.requestBridge.sendNodeResponse(res, response);
140
- } catch (error) {
141
- if (error instanceof NodeClientAbortError) {
142
- return;
143
- }
144
- appLogger.error("Node static build runtime request failed", error);
145
- res.statusCode = 500;
146
- res.end("Internal Server Error");
149
+ const baseUrl = resolveServeRuntimeOrigin(this.serveOptions);
150
+ await this.staticBuilder.build(
151
+ { baseUrl, force: options?.force },
152
+ {
153
+ router: this.router,
154
+ routeRendererFactory: this.routeRendererFactory,
155
+ staticRoutes: this.staticRoutes
147
156
  }
148
- });
149
- await new Promise((resolve, reject) => {
150
- server.once("error", reject);
151
- server.listen(port, hostname, () => {
152
- server.off("error", reject);
153
- resolve();
154
- });
155
- });
156
- this.serverInstance = server;
157
- appLogger.info(`Server running at ${this.getListeningServerOrigin(server)}`);
158
- return server;
159
- }
160
- getListeningServerOrigin(server) {
161
- const address = server.address();
162
- const hostname = String(this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME);
163
- if (!address || typeof address === "string") {
164
- throw new Error("Build runtime server did not expose a numeric listening port");
157
+ );
158
+ if (!options?.preview) {
159
+ return void 0;
165
160
  }
166
- return `http://${hostname}:${address.port}`;
161
+ return this.startPreviewServer();
167
162
  }
168
163
  /**
169
- * Gracefully shuts down the ephemeral build runtime server.
170
- *
171
- * `closeAllConnections()` is called *before* `close()` because `server.close()`
172
- * only stops accepting new connections — it waits for existing keep-alive
173
- * connections to finish naturally, which can stall the build indefinitely.
174
- * `closeAllConnections()` force-closes any lingering sockets immediately so
175
- * the `close()` callback fires promptly.
176
- *
177
- * The `NodeClientBridge` heartbeat is also destroyed here so its `setInterval`
178
- * does not prevent the Node.js process from exiting cleanly after the build.
164
+ * Serves an existing static export without running SSG. Used by e2e preview
165
+ * launchers after a shared prewarm build.
179
166
  */
180
- async stopBuildRuntimeServer(server) {
181
- await new Promise((resolve, reject) => {
182
- server.close((error) => {
183
- if (error) {
184
- reject(error);
185
- return;
186
- }
187
- resolve();
188
- });
189
- server.closeAllConnections();
167
+ async servePreviewOnly() {
168
+ if (!this.initialized) {
169
+ await this.initialize();
170
+ }
171
+ const distPath = path.join(this.appConfig.rootDir, this.appConfig.distDir);
172
+ if (!fileSystem.exists(distPath)) {
173
+ throw new Error(
174
+ `Cannot serve preview without building first: dist directory "${this.appConfig.distDir}" not found in "${this.appConfig.rootDir}".`
175
+ );
176
+ }
177
+ return this.startPreviewServer();
178
+ }
179
+ async startPreviewServer() {
180
+ const activePreviewPort = await this.previewHost.start({
181
+ appConfig: this.appConfig,
182
+ hostname: String(this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME),
183
+ port: Number(this.serveOptions.port || DEFAULT_ECOPAGES_PORT),
184
+ allowPortFallback: this.allowPortFallback
190
185
  });
191
- if (this.serverInstance === server) {
192
- this.serverInstance = null;
186
+ if (!activePreviewPort) {
187
+ return void 0;
193
188
  }
194
- this.bridge?.destroy();
195
- this.bridge = null;
189
+ const previewHostname = this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME;
190
+ return `http://${previewHostname}:${activePreviewPort}`;
196
191
  }
197
192
  async createAdapter() {
198
193
  await this.initialize();
199
194
  return {
200
195
  getServerOptions: this.getServerOptions.bind(this),
201
196
  buildStatic: this.buildStatic.bind(this),
197
+ servePreviewOnly: this.servePreviewOnly.bind(this),
202
198
  completeInitialization: this.completeInitialization.bind(this),
203
- handleRequest: this.handleRequest.bind(this)
199
+ handleRequest: this.handleRequest.bind(this),
200
+ attachUserWebSocketUpgrades: this.attachUserWebSocketUpgrades.bind(this),
201
+ dispose: this.dispose.bind(this)
204
202
  };
205
203
  }
204
+ /**
205
+ * Releases dev-time resources owned by the adapter.
206
+ *
207
+ * @remarks
208
+ * Safe to call multiple times. Does not stop the bound HTTP server — callers
209
+ * should shut down transport through the runtime host before disposing.
210
+ */
211
+ async dispose() {
212
+ if (this.adapterDisposed) {
213
+ return;
214
+ }
215
+ this.adapterDisposed = true;
216
+ await disposeDevResources({
217
+ projectWatcher: this.projectWatcher,
218
+ appConfig: this.appConfig,
219
+ hmrManager: this.hmrManager,
220
+ bridge: this.bridge,
221
+ previewHost: this.previewHost
222
+ });
223
+ this.projectWatcher = null;
224
+ this.hmrManager = null;
225
+ this.bridge = null;
226
+ }
206
227
  /**
207
228
  * Handles a single incoming Web `Request` and returns a Web `Response`.
208
229
  *
@@ -244,35 +265,39 @@ class NodeServerAdapter extends SharedServerAdapter {
244
265
  * - Shared watcher bootstrapping listens for route-level file changes and
245
266
  * refreshes the router and response handlers when pages are added or removed.
246
267
  *
247
- * WebSocket upgrade requests that do not target `/_hmr` are rejected with an
268
+ * WebSocket upgrade requests that do not match a known path are rejected with an
248
269
  * immediate socket destroy to prevent unhandled upgrade leaks.
249
270
  */
250
271
  async completeInitialization(server) {
251
272
  this.serverInstance = server;
273
+ const hasUserWs = this.websocketHandlers.size > 0;
252
274
  if (this.options?.watch) {
253
275
  const devRuntime = this.devRuntimeFactory.create({ appConfig: this.appConfig });
254
276
  const wss = devRuntime.websocketServer;
255
277
  this.bridge = devRuntime.bridge;
256
278
  this.hmrManager = devRuntime.hmrManager;
257
279
  this.hmrManager.setEnabled(true);
258
- await this.hmrManager.buildRuntime();
259
- server.on("upgrade", (req, socket, head) => {
280
+ await this.hmrManager.ensureRuntimeReady();
281
+ const hmrPreflight = (req, socket, head) => {
260
282
  const url = new URL(req.url ?? "/", this.runtimeOrigin);
261
- if (url.pathname === "/_hmr") {
262
- wss.handleUpgrade(req, socket, head, (ws) => {
263
- this.bridge.subscribe(ws);
264
- ws.on("close", () => this.bridge.unsubscribe(ws));
265
- ws.on("error", (err) => appLogger.error("[HMR] WebSocket error:", err));
266
- });
267
- } else {
268
- socket.destroy();
269
- }
270
- });
271
- const browserBuildPlugins = getAppBrowserBuildPlugins(this.appConfig);
272
- this.hmrManager.setPlugins(browserBuildPlugins);
273
- for (const integration of this.appConfig.integrations) {
274
- integration.setHmrManager(this.hmrManager);
283
+ if (url.pathname !== "/_hmr") return false;
284
+ wss.handleUpgrade(req, socket, head, (ws) => {
285
+ this.bridge.subscribe(ws);
286
+ ws.on("close", () => this.bridge.unsubscribe(ws));
287
+ ws.on("error", (err) => appLogger.error("[HMR] WebSocket error:", err));
288
+ });
289
+ return true;
290
+ };
291
+ if (hasUserWs) {
292
+ this.wireUserWebSocketUpgrades(server, hmrPreflight);
293
+ } else {
294
+ server.on("upgrade", (req, socket, head) => {
295
+ if (!hmrPreflight(req, socket, head)) {
296
+ socket.destroy();
297
+ }
298
+ });
275
299
  }
300
+ attachHmrToIntegrations(this.appConfig, this.hmrManager);
276
301
  this.configureSharedResponseHandlers(this.staticRoutes, this.hmrManager);
277
302
  const watcher = new ProjectWatcher({
278
303
  config: this.appConfig,
@@ -281,9 +306,13 @@ class NodeServerAdapter extends SharedServerAdapter {
281
306
  hmrManager: this.hmrManager
282
307
  }),
283
308
  hmrManager: this.hmrManager,
284
- bridge: this.bridge
309
+ bridge: this.bridge,
310
+ hostOwnsDevClient: this.hostOwnsDevClient
285
311
  });
312
+ this.projectWatcher = watcher;
286
313
  await watcher.createWatcherSubscription();
314
+ } else if (hasUserWs) {
315
+ this.wireUserWebSocketUpgrades(server);
287
316
  }
288
317
  appLogger.debug("Node server adapter initialization completed", {
289
318
  apiHandlers: this.apiHandlers.length,
@@ -56,5 +56,6 @@ export declare class NodeStaticContentServer {
56
56
  * Stops the static preview server and optionally closes active connections.
57
57
  */
58
58
  stop(force?: boolean): Promise<void>;
59
+ [Symbol.asyncDispose](): Promise<void>;
59
60
  }
60
61
  export {};
@@ -161,8 +161,13 @@ class NodeStaticContentServer {
161
161
  this.server = createServer(this.handleRequest.bind(this));
162
162
  const hostname = this.options.hostname ?? DEFAULT_ECOPAGES_HOSTNAME;
163
163
  const port = this.options.port ?? DEFAULT_ECOPAGES_PORT;
164
- await new Promise((resolve) => {
165
- this.server.listen(port, hostname, () => resolve());
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
+ });
166
171
  });
167
172
  return this.server;
168
173
  }
@@ -188,6 +193,9 @@ class NodeStaticContentServer {
188
193
  }
189
194
  });
190
195
  }
196
+ async [Symbol.asyncDispose]() {
197
+ await this.stop();
198
+ }
191
199
  }
192
200
  export {
193
201
  NodeStaticContentServer
@@ -1,3 +1,5 @@
1
+ import { appLogger } from "../../global/app-logger.js";
2
+ import { PortManager } from "../shared/port-manager.js";
1
3
  import { NodeStaticContentServer } from "./static-content-server.js";
2
4
  class NodeStaticPreviewHost {
3
5
  /**
@@ -20,20 +22,33 @@ class NodeStaticPreviewHost {
20
22
  */
21
23
  async start(options) {
22
24
  await this.stop();
23
- const previewServer = new this.previewServerFactory({
24
- appConfig: options.appConfig,
25
- options: {
26
- hostname: options.hostname,
27
- port: options.port
28
- }
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
+ }
33
+ });
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;
39
+ }
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
29
47
  });
30
- const server = await previewServer.start();
31
- this.previewServer = previewServer;
32
- const address = server.address();
33
- if (address && typeof address === "object") {
34
- return address.port;
48
+ if (!previewPort) {
49
+ this.previewServer = null;
35
50
  }
36
- return options.port;
51
+ return previewPort;
37
52
  }
38
53
  /**
39
54
  * Stops the active preview server and coalesces overlapping stop requests onto
@@ -0,0 +1,22 @@
1
+ import type { ServerWebSocket } from 'bun';
2
+ import type { EcopagesSocket, EcopagesWebSocketHandler } from '../../types/public-types.js';
3
+ export type BunUserWebSocketData = {
4
+ kind: string;
5
+ params: Record<string, string>;
6
+ search: Record<string, string>;
7
+ upgradeUrl?: string;
8
+ context?: unknown;
9
+ [key: string]: unknown;
10
+ };
11
+ export type BunUserWebSocketLifecycleDeps<TWsData extends BunUserWebSocketData> = {
12
+ runtimeOrigin: string;
13
+ userHandlers: Map<string, EcopagesWebSocketHandler<any, any>>;
14
+ resolveContext: <TContext, TParams extends Record<string, string>>(request: Request, handler: EcopagesWebSocketHandler<TContext, TParams>, kind: string, params: TParams, search: Record<string, string>) => Promise<TContext>;
15
+ adaptSocket: <TContext, TParams extends Record<string, string>>(ws: ServerWebSocket<TWsData>, kind: string, params: TParams, search: Record<string, string>, context: TContext) => EcopagesSocket<TContext, TParams>;
16
+ };
17
+ export declare function createBunUserWebSocketLifecycle<TWsData extends BunUserWebSocketData>(deps: BunUserWebSocketLifecycleDeps<TWsData>): {
18
+ open(ws: ServerWebSocket<TWsData>): void;
19
+ message(ws: ServerWebSocket<TWsData>, msg: string | Buffer): void;
20
+ close(ws: ServerWebSocket<TWsData>, code: number, reason: string): void;
21
+ error(ws: ServerWebSocket<TWsData>, error: Error): void;
22
+ };
@@ -0,0 +1,96 @@
1
+ import { appLogger } from "../../global/app-logger.js";
2
+ import { invokeWebSocketHandlerHook, toWebSocketCloseInfo } from "./websocket-lifecycle.js";
3
+ function toUpgradeRequest(ws, runtimeOrigin) {
4
+ const upgradeUrl = ws.data?.upgradeUrl;
5
+ if (upgradeUrl) {
6
+ return new Request(upgradeUrl);
7
+ }
8
+ return new Request(runtimeOrigin);
9
+ }
10
+ async function runUserWebSocketOpen(ws, kind, deps) {
11
+ const handler = deps.userHandlers.get(kind);
12
+ if (!handler) {
13
+ return;
14
+ }
15
+ const params = ws.data?.params ?? {};
16
+ const search = ws.data?.search ?? {};
17
+ const request = toUpgradeRequest(ws, deps.runtimeOrigin);
18
+ let context;
19
+ try {
20
+ context = await deps.resolveContext(request, handler, kind, params, search);
21
+ } catch {
22
+ ws.close(1011, "context initialization failed");
23
+ return;
24
+ }
25
+ ws.data.context = context;
26
+ const socket = deps.adaptSocket(ws, kind, params, search, context);
27
+ try {
28
+ await handler.onConnect?.(socket);
29
+ } catch (error) {
30
+ appLogger.error(`[WS:${kind}] onConnect failed:`, error);
31
+ ws.close(1011, "onConnect failed");
32
+ }
33
+ }
34
+ function createBunUserWebSocketLifecycle(deps) {
35
+ const resolveSocketForEvent = (ws) => {
36
+ const kind = ws.data?.kind;
37
+ if (!kind) {
38
+ return void 0;
39
+ }
40
+ const handler = deps.userHandlers.get(kind);
41
+ if (!handler) {
42
+ return void 0;
43
+ }
44
+ const params = ws.data?.params ?? {};
45
+ const search = ws.data?.search ?? {};
46
+ const socket = deps.adaptSocket(ws, kind, params, search, ws.data?.context);
47
+ return { kind, handler, socket };
48
+ };
49
+ return {
50
+ open(ws) {
51
+ const kind = ws.data?.kind;
52
+ if (!kind) {
53
+ return;
54
+ }
55
+ void runUserWebSocketOpen(ws, kind, deps).catch((error) => {
56
+ appLogger.error(`[WS:${kind}] open failed:`, error);
57
+ ws.close(1011, "internal error");
58
+ });
59
+ },
60
+ message(ws, msg) {
61
+ const resolved = resolveSocketForEvent(ws);
62
+ if (!resolved) {
63
+ return;
64
+ }
65
+ if (ws.data?.context === void 0 && resolved.handler.context) {
66
+ appLogger.warn(`[WS:${resolved.kind}] message received before context resolved; dropping.`);
67
+ return;
68
+ }
69
+ const message = typeof msg === "string" ? { kind: "text", text: msg } : { kind: "binary", data: new Uint8Array(msg.buffer, msg.byteOffset, msg.byteLength) };
70
+ invokeWebSocketHandlerHook(
71
+ resolved.kind,
72
+ "onMessage",
73
+ resolved.handler.onMessage?.(resolved.socket, message)
74
+ );
75
+ },
76
+ close(ws, code, reason) {
77
+ const resolved = resolveSocketForEvent(ws);
78
+ if (!resolved) {
79
+ return;
80
+ }
81
+ const event = toWebSocketCloseInfo(code, reason);
82
+ invokeWebSocketHandlerHook(resolved.kind, "onClose", resolved.handler.onClose?.(resolved.socket, event));
83
+ },
84
+ error(ws, error) {
85
+ const resolved = resolveSocketForEvent(ws);
86
+ if (!resolved) {
87
+ return;
88
+ }
89
+ appLogger.error(`[WS:${resolved.kind}] error:`, error);
90
+ invokeWebSocketHandlerHook(resolved.kind, "onError", resolved.handler.onError?.(resolved.socket, error));
91
+ }
92
+ };
93
+ }
94
+ export {
95
+ createBunUserWebSocketLifecycle
96
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copies a source public directory into the runtime dist dir, skipping unchanged files.
3
+ *
4
+ * Dev restarts call this on every boot; byte comparison avoids rewriting identical assets.
5
+ */
6
+ export declare function copyRuntimePublicDirIfChanged(sourceDir: string, destinationDir: string): void;
@@ -0,0 +1,24 @@
1
+ import { readdirSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { fileSystem } from "@ecopages/file-system";
4
+ function copyRuntimePublicDirIfChanged(sourceDir, destinationDir) {
5
+ fileSystem.ensureDir(destinationDir);
6
+ for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {
7
+ const sourcePath = path.join(sourceDir, entry.name);
8
+ const destinationPath = path.join(destinationDir, entry.name);
9
+ if (entry.isDirectory()) {
10
+ copyRuntimePublicDirIfChanged(sourcePath, destinationPath);
11
+ continue;
12
+ }
13
+ if (!entry.isFile()) {
14
+ continue;
15
+ }
16
+ if (fileSystem.exists(destinationPath) && Buffer.compare(fileSystem.readFileAsBuffer(sourcePath), fileSystem.readFileAsBuffer(destinationPath)) === 0) {
17
+ continue;
18
+ }
19
+ fileSystem.copyFile(sourcePath, destinationPath);
20
+ }
21
+ }
22
+ export {
23
+ copyRuntimePublicDirIfChanged
24
+ };
@@ -55,6 +55,8 @@ export declare class FileSystemResponseMatcher {
55
55
  * when the page template cannot be resolved.
56
56
  */
57
57
  private renderCustomNotFoundResponse;
58
+ private renderCustomNotFoundResponseOrServerError;
59
+ private createInternalServerErrorResponse;
58
60
  private createExecutionPlan;
59
61
  /**
60
62
  * Loads the matched page module for request-time inspection.