@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.
- package/README.md +1 -1
- package/package.json +163 -3
- package/src/adapters/abstract/application-adapter.d.ts +104 -5
- package/src/adapters/abstract/application-adapter.js +125 -1
- package/src/adapters/abstract/server-adapter.d.ts +6 -2
- package/src/adapters/abstract/ws-pattern-matcher.d.ts +60 -0
- package/src/adapters/abstract/ws-pattern-matcher.js +61 -0
- package/src/adapters/bun/client-bridge.d.ts +1 -0
- package/src/adapters/bun/client-bridge.js +3 -0
- package/src/adapters/bun/create-app.d.ts +6 -4
- package/src/adapters/bun/create-app.js +65 -43
- package/src/adapters/bun/server-adapter.d.ts +90 -22
- package/src/adapters/bun/server-adapter.js +266 -84
- package/src/adapters/bun/static-preview-host.js +25 -20
- package/src/adapters/create-app.d.ts +13 -11
- package/src/adapters/create-app.js +2 -51
- package/src/adapters/index.d.ts +1 -1
- package/src/adapters/index.js +1 -2
- package/src/adapters/node/create-app.d.ts +5 -1
- package/src/adapters/node/create-app.js +51 -12
- package/src/adapters/node/node-client-bridge.d.ts +1 -0
- package/src/adapters/node/node-client-bridge.js +3 -0
- package/src/adapters/node/server-adapter-dependencies.js +4 -0
- package/src/adapters/node/server-adapter.d.ts +62 -20
- package/src/adapters/node/server-adapter.js +160 -131
- package/src/adapters/node/static-content-server.d.ts +1 -0
- package/src/adapters/node/static-content-server.js +10 -2
- package/src/adapters/node/static-preview-host.js +27 -12
- package/src/adapters/shared/bun-user-websocket-lifecycle.d.ts +22 -0
- package/src/adapters/shared/bun-user-websocket-lifecycle.js +96 -0
- package/src/adapters/shared/copy-runtime-public-dir.d.ts +6 -0
- package/src/adapters/shared/copy-runtime-public-dir.js +24 -0
- package/src/adapters/shared/fs-server-response-matcher.d.ts +2 -0
- package/src/adapters/shared/fs-server-response-matcher.js +40 -18
- package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +21 -30
- package/src/adapters/shared/hmr-entrypoint-registrar.js +49 -54
- package/src/adapters/shared/hmr-html-response.d.ts +1 -1
- package/src/adapters/shared/hmr-html-response.js +4 -1
- package/src/adapters/shared/node-http-websocket-upgrades.d.ts +21 -0
- package/src/adapters/shared/node-http-websocket-upgrades.js +100 -0
- package/src/adapters/shared/port-manager.d.ts +116 -0
- package/src/adapters/shared/port-manager.js +196 -0
- package/src/adapters/shared/runtime-app-bootstrap.d.ts +2 -1
- package/src/adapters/shared/runtime-app-bootstrap.js +3 -6
- package/src/adapters/shared/runtime-server-lifecycle.d.ts +46 -0
- package/src/adapters/shared/runtime-server-lifecycle.js +50 -0
- package/src/adapters/shared/server-adapter.d.ts +2 -1
- package/src/adapters/shared/server-adapter.js +13 -6
- package/src/adapters/shared/server-route-handler.d.ts +4 -1
- package/src/adapters/shared/server-route-handler.js +5 -2
- package/src/adapters/shared/server-static-builder.d.ts +23 -32
- package/src/adapters/shared/server-static-builder.js +100 -73
- package/src/adapters/shared/shared-hmr-manager.d.ts +45 -11
- package/src/adapters/shared/shared-hmr-manager.js +204 -58
- package/src/adapters/shared/static-preview-host.d.ts +5 -0
- package/src/adapters/shared/websocket-lifecycle.d.ts +24 -0
- package/src/adapters/shared/websocket-lifecycle.js +55 -0
- package/src/build/README.md +77 -14
- package/src/build/app-build-manifest-runtime.d.ts +9 -0
- package/src/build/app-build-manifest-runtime.js +87 -0
- package/src/build/build-adapter.d.ts +17 -319
- package/src/build/build-adapter.js +28 -94
- package/src/build/build-contracts.d.ts +97 -0
- package/src/build/build-contracts.js +0 -0
- package/src/build/build-input-fingerprint.d.ts +28 -0
- package/src/build/build-input-fingerprint.js +31 -0
- package/src/build/build-profile-options.d.ts +7 -0
- package/src/build/build-profile-options.js +37 -0
- package/src/build/build-runtime.d.ts +24 -0
- package/src/build/build-runtime.js +65 -0
- package/src/build/deduping-build-executor.d.ts +28 -0
- package/src/build/deduping-build-executor.js +56 -0
- package/src/build/jsx-ownership-plugins.d.ts +24 -0
- package/src/build/jsx-ownership-plugins.js +41 -0
- package/src/build/pages-unified-graph-build.d.ts +31 -0
- package/src/build/pages-unified-graph-build.js +206 -0
- package/src/build/parallel-build-executor.d.ts +21 -0
- package/src/build/parallel-build-executor.js +52 -0
- package/src/build/production-build-cache.d.ts +20 -0
- package/src/build/production-build-cache.js +63 -0
- package/src/build/rolldown-adapter-helpers.d.ts +3 -6
- package/src/build/rolldown-adapter-helpers.js +71 -6
- package/src/build/rolldown-build-adapter.d.ts +2 -6
- package/src/build/rolldown-build-adapter.js +3 -3
- package/src/build/rolldown-build-invocation-metrics.d.ts +12 -0
- package/src/build/rolldown-build-invocation-metrics.js +43 -0
- package/src/build/rolldown-plugin-bridge.d.ts +15 -1
- package/src/build/rolldown-plugin-bridge.js +20 -5
- package/src/build/rolldown-source-transform-pass.d.ts +15 -0
- package/src/build/rolldown-source-transform-pass.js +58 -0
- package/src/build/runtime-build-executor.d.ts +8 -15
- package/src/build/runtime-build-executor.js +12 -15
- package/src/build/runtime-build-output-normalizer.d.ts +7 -0
- package/src/build/runtime-build-output-normalizer.js +94 -2
- package/src/build/server-entry-build-cache.d.ts +44 -0
- package/src/build/server-entry-build-cache.js +161 -0
- package/src/client/navigation-scripts/classification.d.ts +16 -0
- package/src/client/navigation-scripts/classification.js +41 -0
- package/src/client/navigation-scripts/index.d.ts +3 -0
- package/src/client/navigation-scripts/index.js +23 -0
- package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
- package/src/client/navigation-scripts/registry.d.ts +11 -0
- package/src/client/navigation-scripts/registry.js +12 -0
- package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
- package/src/client/navigation-scripts/rerun-queue.js +73 -0
- package/src/client/scroll.d.ts +17 -0
- package/src/client/scroll.js +25 -0
- package/src/client/scroll.test.browser.js +37 -0
- package/src/client/view-transitions.d.ts +16 -0
- package/src/client/view-transitions.js +63 -0
- package/src/config/config-builder.d.ts +12 -7
- package/src/config/config-builder.js +12 -9
- package/src/dev/client-bridge-registry.d.ts +5 -0
- package/src/dev/client-bridge-registry.js +15 -0
- package/src/dev/dev-client-ownership.d.ts +7 -0
- package/src/dev/dev-client-ownership.js +6 -0
- package/src/dev/hmr-manager-registry.d.ts +8 -0
- package/src/dev/hmr-manager-registry.js +15 -0
- package/src/dev/host-runtime.d.ts +3 -0
- package/src/dev/host-runtime.js +7 -0
- package/src/dev/runtime-server-started-message.d.ts +2 -0
- package/src/dev/runtime-server-started-message.js +6 -0
- package/src/eco/README.md +11 -0
- package/src/eco/eco-declared-component.d.ts +14 -0
- package/src/eco/eco-declared-component.js +16 -0
- package/src/eco/eco.browser.js +5 -6
- package/src/eco/eco.js +5 -6
- package/src/eco/eco.types.d.ts +2 -2
- package/src/eco/page-layout-normalization.d.ts +21 -0
- package/src/eco/page-layout-normalization.js +59 -0
- package/src/errors/index.d.ts +1 -0
- package/src/errors/index.js +7 -1
- package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
- package/src/errors/undeclared-component-dependency-error.js +17 -0
- package/src/hmr/client/hmr-runtime.js +5 -2
- package/src/hmr/hmr-entrypoint-output.d.ts +43 -0
- package/src/hmr/hmr-entrypoint-output.js +53 -0
- package/src/hmr/hmr-strategy.d.ts +15 -0
- package/src/hmr/hmr-strategy.js +19 -0
- package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -5
- package/src/hmr/strategies/js-hmr-strategy.js +67 -19
- package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
- package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
- package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
- package/src/integrations/ghtml/ghtml-renderer.js +2 -51
- package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
- package/src/integrations/ghtml/ghtml.plugin.js +7 -14
- package/src/plugins/define-integration.d.ts +26 -0
- package/src/plugins/define-integration.js +19 -0
- package/src/plugins/eco-component-meta-plugin.js +5 -8
- package/src/plugins/foreign-jsx-override-plugin.js +4 -6
- package/src/plugins/integration-plugin.d.ts +19 -9
- package/src/plugins/integration-plugin.js +7 -4
- package/src/plugins/jsx-import-source.utils.d.ts +8 -0
- package/src/plugins/jsx-import-source.utils.js +26 -0
- package/src/plugins/processor.d.ts +19 -4
- package/src/plugins/processor.js +22 -4
- package/src/plugins/source-transform.d.ts +31 -0
- package/src/plugins/source-transform.js +23 -1
- package/src/route-renderer/GRAPH.md +8 -8
- package/src/route-renderer/README.md +30 -28
- package/src/route-renderer/orchestration/component-graph-collectors.d.ts +10 -0
- package/src/route-renderer/orchestration/component-graph-collectors.js +143 -0
- package/src/route-renderer/orchestration/component-graph.d.ts +36 -0
- package/src/route-renderer/orchestration/component-graph.js +98 -0
- package/src/route-renderer/orchestration/component-render-context.d.ts +3 -10
- package/src/route-renderer/orchestration/component-render-context.js +3 -1
- package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +1 -18
- package/src/route-renderer/orchestration/declared-ownership-graph.js +5 -31
- package/src/route-renderer/orchestration/document-shell-render.service.d.ts +90 -0
- package/src/route-renderer/orchestration/document-shell-render.service.js +120 -0
- package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +59 -29
- package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +164 -35
- package/src/route-renderer/orchestration/global-injector-assets.service.d.ts +7 -0
- package/src/route-renderer/orchestration/global-injector-assets.service.js +32 -0
- package/src/route-renderer/orchestration/integration-renderer.d.ts +18 -54
- package/src/route-renderer/orchestration/integration-renderer.js +113 -195
- package/src/route-renderer/orchestration/integration-route-render-adapter.d.ts +38 -0
- package/src/route-renderer/orchestration/integration-route-render-adapter.js +27 -0
- package/src/route-renderer/orchestration/layout-shell-props.service.d.ts +20 -0
- package/src/route-renderer/orchestration/layout-shell-props.service.js +31 -0
- package/src/route-renderer/orchestration/ownership-validation.service.d.ts +5 -0
- package/src/route-renderer/orchestration/ownership-validation.service.js +29 -1
- package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.d.ts +9 -0
- package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.js +7 -0
- package/src/route-renderer/orchestration/page-browser-graph.service.d.ts +25 -0
- package/src/route-renderer/orchestration/page-browser-graph.service.js +174 -0
- package/src/route-renderer/orchestration/render-output.utils.d.ts +2 -0
- package/src/route-renderer/orchestration/render-output.utils.js +4 -0
- package/src/route-renderer/orchestration/route-html-finalization.service.d.ts +17 -0
- package/src/route-renderer/orchestration/route-html-finalization.service.js +26 -0
- package/src/route-renderer/orchestration/route-prepared-options.builder.d.ts +26 -0
- package/src/route-renderer/orchestration/route-prepared-options.builder.js +54 -0
- package/src/route-renderer/orchestration/route-prepared-options.utils.d.ts +4 -0
- package/src/route-renderer/orchestration/route-prepared-options.utils.js +33 -0
- package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +8 -39
- package/src/route-renderer/orchestration/route-render-orchestrator.js +53 -461
- package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
- package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
- package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
- package/src/router/client/link-intent.d.ts +11 -21
- package/src/router/client/link-intent.js +10 -0
- package/src/router/client/link-intent.test.browser.js +12 -1
- package/src/router/client/link-navigation-policy.d.ts +45 -0
- package/src/router/client/link-navigation-policy.js +101 -0
- package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
- package/src/router/client/link-navigation-policy.test.browser.js +92 -0
- package/src/router/client/navigation-coordinator.d.ts +1 -1
- package/src/router/client/navigation-coordinator.js +12 -2
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -0
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +27 -7
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -1
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +18 -15
- package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
- package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
- package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
- package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
- package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
- package/src/services/assets/browser-bundle.service.d.ts +3 -1
- package/src/services/assets/browser-bundle.service.js +17 -5
- package/src/services/html/html-transformer.service.d.ts +1 -1
- package/src/services/html/html-transformer.service.js +4 -4
- package/src/services/invalidation/development-invalidation.service.d.ts +20 -2
- package/src/services/invalidation/development-invalidation.service.js +56 -2
- package/src/services/module-loading/README.md +49 -0
- package/src/services/module-loading/app-server-module-transpiler.service.js +5 -17
- package/src/services/module-loading/page-module-import.service.d.ts +5 -1
- package/src/services/module-loading/page-module-import.service.js +96 -45
- package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
- package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
- package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
- package/src/services/module-loading/route-module-build-cache.js +38 -0
- package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
- package/src/services/module-loading/route-module-build-cache.store.js +207 -0
- package/src/services/module-loading/route-module-build-manifest.d.ts +61 -0
- package/src/services/module-loading/route-module-build-manifest.js +116 -0
- package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
- package/src/services/module-loading/route-module-dependency-hasher.js +122 -0
- package/src/services/module-loading/server-module-transpiler.service.js +1 -1
- package/src/static-site-generator/README.md +33 -0
- package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
- package/src/static-site-generator/static-build-invalidation.js +59 -0
- package/src/static-site-generator/static-export-context.d.ts +22 -0
- package/src/static-site-generator/static-export-context.js +0 -0
- package/src/static-site-generator/static-site-generator.d.ts +17 -20
- package/src/static-site-generator/static-site-generator.js +188 -85
- package/src/types/internal-types.d.ts +16 -9
- package/src/types/public-types.d.ts +144 -40
- package/src/utils/parse-cli-args.d.ts +2 -0
- package/src/utils/parse-cli-args.js +6 -0
- package/src/utils/server-utils.module.d.ts +3 -2
- package/src/utils/server-utils.module.js +5 -6
- package/src/utils/static-file-extensions.d.ts +12 -0
- package/src/utils/static-file-extensions.js +48 -0
- package/src/watchers/project-watcher-ignore.d.ts +11 -0
- package/src/watchers/project-watcher-ignore.js +16 -0
- package/src/watchers/project-watcher.d.ts +26 -3
- package/src/watchers/project-watcher.js +132 -30
- package/src/watchers/project-watcher.test-helpers.js +5 -5
- package/src/build/rolldown-dev-build-adapter.d.ts +0 -82
- package/src/build/rolldown-dev-build-adapter.js +0 -166
- package/src/hmr/hmr.postcss.test.e2e.js +0 -31
- package/src/hmr/hmr.test.e2e.js +0 -43
- package/src/route-renderer/orchestration/ownership-planning.service.d.ts +0 -24
- package/src/route-renderer/orchestration/ownership-planning.service.js +0 -63
- package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +0 -91
- package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +0 -170
- /package/src/{hmr/hmr.postcss.test.e2e.d.ts → client/navigation-scripts/navigation-scripts.test.browser.d.ts} +0 -0
- /package/src/{hmr/hmr.test.e2e.d.ts → client/scroll.test.browser.d.ts} +0 -0
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT } from "../../config/constants.js";
|
|
3
|
-
import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
|
|
4
3
|
import { appLogger } from "../../global/app-logger.js";
|
|
5
4
|
import { HttpError } from "../../errors/http-error.js";
|
|
6
5
|
import { createRequire } from "../../utils/locals-utils.js";
|
|
6
|
+
import { findWebSocketRoute } from "../abstract/ws-pattern-matcher.js";
|
|
7
7
|
import { fileSystem } from "@ecopages/file-system";
|
|
8
|
-
import {
|
|
8
|
+
import { setupAppRuntimePlugins } from "../../build/build-adapter.js";
|
|
9
9
|
import { installAppRuntimeBuildExecutor } from "../../build/runtime-build-executor.js";
|
|
10
10
|
import { StaticSiteGenerator } from "../../static-site-generator/static-site-generator.js";
|
|
11
11
|
import { ProjectWatcher } from "../../watchers/project-watcher.js";
|
|
12
12
|
import { SharedServerAdapter } from "../shared/server-adapter.js";
|
|
13
13
|
import { ApiResponseBuilder } from "../shared/api-response.js";
|
|
14
14
|
import { ServerStaticBuilder } from "../shared/server-static-builder.js";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
shouldInjectHmrHtmlResponse
|
|
19
|
-
} from "../shared/hmr-html-response.js";
|
|
15
|
+
import { attachNodeHttpWebSocketUpgrades } from "../shared/node-http-websocket-upgrades.js";
|
|
16
|
+
import { createBunUserWebSocketLifecycle } from "../shared/bun-user-websocket-lifecycle.js";
|
|
17
|
+
import { createEcopagesSocket } from "../shared/websocket-lifecycle.js";
|
|
20
18
|
import { resolveServeRuntimeOrigin } from "../shared/runtime-app-bootstrap.js";
|
|
19
|
+
import {
|
|
20
|
+
attachHmrToIntegrations,
|
|
21
|
+
disposeDevResources,
|
|
22
|
+
maybeInjectAdapterHmrHtmlResponse,
|
|
23
|
+
prepareRuntimePublicDir
|
|
24
|
+
} from "../shared/runtime-server-lifecycle.js";
|
|
21
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";
|
|
22
28
|
import { HmrManager } from "./hmr-manager.js";
|
|
23
29
|
import { BunStaticPreviewHost } from "./static-preview-host.js";
|
|
24
30
|
class BunServerAdapter extends SharedServerAdapter {
|
|
@@ -29,7 +35,59 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
29
35
|
hmrManager;
|
|
30
36
|
initializationPromise = null;
|
|
31
37
|
fullyInitialized = false;
|
|
38
|
+
projectWatcher = null;
|
|
39
|
+
adapterDisposed = false;
|
|
40
|
+
deferRuntimeAssetSetup;
|
|
41
|
+
allowPortFallback;
|
|
32
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;
|
|
83
|
+
}
|
|
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;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
33
91
|
/**
|
|
34
92
|
* Creates a Bun server adapter with already-resolved runtime collaborators.
|
|
35
93
|
*
|
|
@@ -46,18 +104,38 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
46
104
|
apiHandlers,
|
|
47
105
|
staticRoutes,
|
|
48
106
|
errorHandler,
|
|
107
|
+
websocketHandlers,
|
|
49
108
|
options,
|
|
109
|
+
hostOwnsDevClient,
|
|
110
|
+
deferRuntimeAssetSetup,
|
|
111
|
+
allowPortFallback,
|
|
50
112
|
hmrManager,
|
|
51
113
|
bridge,
|
|
52
114
|
previewHost
|
|
53
115
|
}) {
|
|
54
116
|
super({ appConfig, runtimeOrigin, serveOptions, options });
|
|
117
|
+
this.deferRuntimeAssetSetup = deferRuntimeAssetSetup === true;
|
|
118
|
+
this.allowPortFallback = allowPortFallback !== false;
|
|
55
119
|
this.apiHandlers = apiHandlers || [];
|
|
56
120
|
this.staticRoutes = staticRoutes || [];
|
|
57
121
|
this.errorHandler = errorHandler;
|
|
58
122
|
this.bridge = bridge;
|
|
59
123
|
this.hmrManager = hmrManager;
|
|
60
124
|
this.previewHost = previewHost;
|
|
125
|
+
this.hostOwnsDevClient = hostOwnsDevClient === true;
|
|
126
|
+
if (websocketHandlers) {
|
|
127
|
+
this.websocketHandlers = websocketHandlers;
|
|
128
|
+
}
|
|
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
|
+
});
|
|
61
139
|
}
|
|
62
140
|
/**
|
|
63
141
|
* Returns whether adapter-level HTML responses still need HMR runtime injection.
|
|
@@ -67,25 +145,12 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
67
145
|
* adapter-level check exists for explicit API handlers that return HTML and
|
|
68
146
|
* would otherwise bypass the route wrapper entirely.
|
|
69
147
|
*/
|
|
70
|
-
shouldInjectHmrScript() {
|
|
71
|
-
return shouldInjectHmrHtmlResponse(this.options?.watch === true, this.hmrManager);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Delegates the HTML-response test to the shared response helper used by both
|
|
75
|
-
* adapters.
|
|
76
|
-
*/
|
|
77
|
-
isHtmlResponse(response) {
|
|
78
|
-
return isHtmlResponse(response);
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Injects HMR script into HTML responses in development mode.
|
|
82
|
-
* Ensures explicit API handlers that return HTML get auto-reload capability.
|
|
83
|
-
*/
|
|
84
148
|
async maybeInjectHmrScript(response) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
149
|
+
return maybeInjectAdapterHmrHtmlResponse(response, {
|
|
150
|
+
watch: this.options?.watch === true,
|
|
151
|
+
hmrManager: this.hmrManager,
|
|
152
|
+
hostOwnsDevClient: this.hostOwnsDevClient
|
|
153
|
+
});
|
|
89
154
|
}
|
|
90
155
|
/**
|
|
91
156
|
* Initializes the server adapter's core runtime components.
|
|
@@ -93,27 +158,25 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
93
158
|
async initialize() {
|
|
94
159
|
installAppRuntimeBuildExecutor(this.appConfig);
|
|
95
160
|
this.staticSiteGenerator = new StaticSiteGenerator({ appConfig: this.appConfig });
|
|
96
|
-
|
|
97
|
-
this.prepareRuntimePublicDir();
|
|
161
|
+
prepareRuntimePublicDir(this.appConfig);
|
|
98
162
|
const staticBuilderOptions = {
|
|
99
163
|
appConfig: this.appConfig,
|
|
100
164
|
staticSiteGenerator: this.staticSiteGenerator,
|
|
101
165
|
serveOptions: this.serveOptions,
|
|
102
|
-
|
|
166
|
+
runtimeOrigin: this.runtimeOrigin,
|
|
167
|
+
needsServerBundle: this.apiHandlers.length > 0 || this.websocketHandlers.size > 0,
|
|
168
|
+
hmrManager: this.hmrManager,
|
|
169
|
+
onRuntimePlugin: (plugin) => {
|
|
170
|
+
this.registerBunRuntimePlugin(plugin);
|
|
171
|
+
}
|
|
103
172
|
};
|
|
104
173
|
this.staticBuilder = new ServerStaticBuilder(staticBuilderOptions);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
*/
|
|
111
|
-
prepareRuntimePublicDir() {
|
|
112
|
-
const srcPublicDir = path.join(this.appConfig.rootDir, this.appConfig.srcDir, this.appConfig.publicDir);
|
|
113
|
-
if (fileSystem.exists(srcPublicDir)) {
|
|
114
|
-
fileSystem.copyDir(srcPublicDir, path.join(this.appConfig.rootDir, this.appConfig.distDir));
|
|
174
|
+
if (!this.deferRuntimeAssetSetup) {
|
|
175
|
+
await this.initializeRuntimePlugins({ watch: this.options?.watch });
|
|
176
|
+
}
|
|
177
|
+
if (this.options?.watch) {
|
|
178
|
+
await this.hmrManager.ensureRuntimeReady();
|
|
115
179
|
}
|
|
116
|
-
fileSystem.ensureDir(path.join(this.appConfig.absolutePaths.distDir, RESOLVED_ASSETS_DIR));
|
|
117
180
|
}
|
|
118
181
|
/**
|
|
119
182
|
* Registers runtime plugins and propagates the final HMR manager into each
|
|
@@ -130,15 +193,12 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
130
193
|
await setupAppRuntimePlugins({
|
|
131
194
|
appConfig: this.appConfig,
|
|
132
195
|
runtimeOrigin: this.runtimeOrigin,
|
|
133
|
-
hmrManager: this.hmrManager,
|
|
134
196
|
onRuntimePlugin: (plugin) => {
|
|
135
|
-
|
|
197
|
+
this.registerBunRuntimePlugin(plugin);
|
|
136
198
|
}
|
|
137
199
|
});
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
for (const integration of this.appConfig.integrations) {
|
|
141
|
-
integration.setHmrManager(this.hmrManager);
|
|
200
|
+
if (options?.watch) {
|
|
201
|
+
attachHmrToIntegrations(this.appConfig, this.hmrManager);
|
|
142
202
|
}
|
|
143
203
|
} catch (error) {
|
|
144
204
|
appLogger.error(`Failed to initialize plugins: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -173,54 +233,124 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
173
233
|
config: this.appConfig,
|
|
174
234
|
refreshRouterRoutesCallback: this.refreshRouterRoutes.bind(this),
|
|
175
235
|
hmrManager: this.hmrManager,
|
|
176
|
-
bridge: this.bridge
|
|
236
|
+
bridge: this.bridge,
|
|
237
|
+
hostOwnsDevClient: this.hostOwnsDevClient
|
|
177
238
|
});
|
|
239
|
+
this.projectWatcher = watcher;
|
|
178
240
|
await watcher.createWatcherSubscription();
|
|
179
241
|
}
|
|
180
242
|
/**
|
|
181
243
|
* Builds the `Bun.serve()` options for the current adapter state.
|
|
182
244
|
*
|
|
183
245
|
* @remarks
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
246
|
+
* When HMR is enabled the websocket dispatcher merges HMR and user handlers,
|
|
247
|
+
* routing by the `kind` field embedded in socket data at upgrade time.
|
|
248
|
+
* This prevents user-registered websocket handlers from being silently overwritten
|
|
249
|
+
* by the HMR handler in development mode.
|
|
250
|
+
*
|
|
251
|
+
* User WebSocket paths are intercepted in the fetch handler via the pattern matcher.
|
|
252
|
+
* The upgrade happens implicitly — no manual GET route registration needed.
|
|
187
253
|
*/
|
|
188
254
|
getServerOptions({ enableHmr = false } = {}) {
|
|
189
255
|
appLogger.debug(`[BunServerAdapter] getServerOptions called with enableHmr: ${enableHmr}`);
|
|
190
256
|
const serverOptions = this.buildServerSettings();
|
|
257
|
+
const hasUserWs = this.websocketHandlers.size > 0;
|
|
258
|
+
if (!enableHmr && !hasUserWs) {
|
|
259
|
+
return serverOptions;
|
|
260
|
+
}
|
|
261
|
+
const userLifecycle = this.createBunUserLifecycle();
|
|
191
262
|
if (enableHmr) {
|
|
192
|
-
const originalFetch = serverOptions.fetch;
|
|
193
|
-
const hmrHandler = this.hmrManager.getWebSocketHandler();
|
|
194
|
-
const hmrManager = this.hmrManager;
|
|
195
263
|
serverOptions.development = true;
|
|
196
|
-
serverOptions.websocket =
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
264
|
+
serverOptions.websocket = this.createHmrAwareWebSocketHandler(userLifecycle);
|
|
265
|
+
} else {
|
|
266
|
+
serverOptions.websocket = userLifecycle;
|
|
267
|
+
}
|
|
268
|
+
serverOptions.fetch = this.wrapFetchWithWebSocketUpgrades(serverOptions.fetch, {
|
|
269
|
+
serveHmrEndpoints: enableHmr
|
|
270
|
+
});
|
|
271
|
+
return serverOptions;
|
|
272
|
+
}
|
|
273
|
+
createBunUserLifecycle() {
|
|
274
|
+
return createBunUserWebSocketLifecycle({
|
|
275
|
+
runtimeOrigin: this.runtimeOrigin,
|
|
276
|
+
userHandlers: this.websocketHandlers,
|
|
277
|
+
resolveContext: this.resolveBunContext.bind(this),
|
|
278
|
+
adaptSocket: (ws, kind, params, search, context) => this.adaptBunWebSocket(ws, kind, params, search, context)
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* @remarks
|
|
283
|
+
* HMR and user sockets share one Bun `websocket` handler. Upgrade tags HMR
|
|
284
|
+
* connections with `kind: '__hmr__'`; everything else routes to the user lifecycle.
|
|
285
|
+
*/
|
|
286
|
+
createHmrAwareWebSocketHandler(userLifecycle) {
|
|
287
|
+
const hmrHandler = this.hmrManager.getWebSocketHandler();
|
|
288
|
+
const isHmrSocket = (ws) => (ws.data?.kind ?? "__hmr__") === "__hmr__";
|
|
289
|
+
return {
|
|
290
|
+
open(ws) {
|
|
291
|
+
if (isHmrSocket(ws)) return void hmrHandler.open?.(ws);
|
|
292
|
+
userLifecycle.open(ws);
|
|
293
|
+
},
|
|
294
|
+
message(ws, msg) {
|
|
295
|
+
if (isHmrSocket(ws)) return void hmrHandler.message?.(ws, msg);
|
|
296
|
+
userLifecycle.message(ws, msg);
|
|
297
|
+
},
|
|
298
|
+
close(ws, code, reason) {
|
|
299
|
+
if (isHmrSocket(ws)) return void hmrHandler.close?.(ws, code, reason);
|
|
300
|
+
userLifecycle.close(ws, code, reason);
|
|
301
|
+
},
|
|
302
|
+
error(ws, error) {
|
|
303
|
+
if (isHmrSocket(ws)) return void appLogger.error("[HMR] WebSocket error:", error);
|
|
304
|
+
userLifecycle.error(ws, error);
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* @remarks
|
|
310
|
+
* When `serveHmrEndpoints` is set, `/_hmr` and `/_hmr_runtime.js` are checked
|
|
311
|
+
* before user websocket patterns so HMR upgrades are never captured by app routes.
|
|
312
|
+
* Production mode with only user handlers skips the HMR branch entirely.
|
|
313
|
+
*/
|
|
314
|
+
wrapFetchWithWebSocketUpgrades(originalFetch, { serveHmrEndpoints }) {
|
|
315
|
+
const matchRoute = (pathname) => findWebSocketRoute(this.websocketHandlers, pathname);
|
|
316
|
+
const hmrManager = this.hmrManager;
|
|
317
|
+
const waitForInit = this.waitForInitialization.bind(this);
|
|
318
|
+
return async function(request, server) {
|
|
319
|
+
const url = new URL(request.url);
|
|
320
|
+
if (serveHmrEndpoints) {
|
|
200
321
|
if (url.pathname === "/_hmr") {
|
|
201
|
-
const success = this.upgrade(request, {
|
|
202
|
-
|
|
203
|
-
});
|
|
204
|
-
if (success) return;
|
|
205
|
-
return new Response("WebSocket upgrade failed", { status: 400 });
|
|
322
|
+
const success = this.upgrade(request, { data: { kind: "__hmr__", params: {}, search: {} } });
|
|
323
|
+
return success ? void 0 : new Response("WebSocket upgrade failed", { status: 400 });
|
|
206
324
|
}
|
|
207
325
|
if (url.pathname === "/_hmr_runtime.js") {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
326
|
+
await waitForInit();
|
|
327
|
+
const runtimeReady = await hmrManager.ensureRuntimeReady();
|
|
328
|
+
const runtimePath = hmrManager.getRuntimePath();
|
|
329
|
+
if (runtimeReady && fileSystem.exists(runtimePath)) {
|
|
330
|
+
return new Response(fileSystem.readFileAsBuffer(runtimePath), {
|
|
331
|
+
headers: { "Content-Type": "application/javascript" }
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
appLogger.warn(
|
|
335
|
+
`[HMR] Runtime script not found at ${runtimePath}; the HMR runtime build likely failed during startup.`
|
|
336
|
+
);
|
|
337
|
+
return new Response("Not Found", { status: 404 });
|
|
219
338
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
339
|
+
}
|
|
340
|
+
const wsMatch = matchRoute(url.pathname);
|
|
341
|
+
if (wsMatch && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
342
|
+
const search = Object.fromEntries(url.searchParams.entries());
|
|
343
|
+
const success = this.upgrade(request, {
|
|
344
|
+
data: { kind: wsMatch.kind, params: wsMatch.params, search, upgradeUrl: request.url }
|
|
345
|
+
});
|
|
346
|
+
return success ? void 0 : new Response("WebSocket upgrade failed", { status: 400 });
|
|
347
|
+
}
|
|
348
|
+
if (!originalFetch) {
|
|
349
|
+
return new Response("Not Found", { status: 404 });
|
|
350
|
+
}
|
|
351
|
+
const res = await originalFetch.call(this, request, server);
|
|
352
|
+
return res instanceof Response ? res : new Response("Not Found", { status: 404 });
|
|
353
|
+
};
|
|
224
354
|
}
|
|
225
355
|
/**
|
|
226
356
|
* Helper method to retrieve and parse the request body.
|
|
@@ -306,9 +436,9 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
306
436
|
hmrManager: this.hmrManager
|
|
307
437
|
});
|
|
308
438
|
}
|
|
309
|
-
const buildRuntimeOrigin = this.
|
|
439
|
+
const buildRuntimeOrigin = resolveServeRuntimeOrigin(this.serveOptions);
|
|
310
440
|
await this.staticBuilder.build(
|
|
311
|
-
{
|
|
441
|
+
{ baseUrl: buildRuntimeOrigin, force: options?.force },
|
|
312
442
|
{
|
|
313
443
|
router: this.router,
|
|
314
444
|
routeRendererFactory: this.routeRendererFactory,
|
|
@@ -316,19 +446,42 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
316
446
|
}
|
|
317
447
|
);
|
|
318
448
|
if (!options?.preview) {
|
|
319
|
-
return;
|
|
449
|
+
return void 0;
|
|
450
|
+
}
|
|
451
|
+
return this.startPreviewServer();
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Serves an existing static export without running SSG. Used by e2e preview
|
|
455
|
+
* launchers after a shared prewarm build.
|
|
456
|
+
*/
|
|
457
|
+
async servePreviewOnly() {
|
|
458
|
+
if (!this.fullyInitialized) {
|
|
459
|
+
await this.initializeSharedRouteHandling({
|
|
460
|
+
staticRoutes: this.staticRoutes,
|
|
461
|
+
hmrManager: this.hmrManager
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
const distPath = path.join(this.appConfig.rootDir, this.appConfig.distDir);
|
|
465
|
+
if (!fileSystem.exists(distPath)) {
|
|
466
|
+
throw new Error(
|
|
467
|
+
`Cannot serve preview without building first: dist directory "${this.appConfig.distDir}" not found in "${this.appConfig.rootDir}".`
|
|
468
|
+
);
|
|
320
469
|
}
|
|
470
|
+
return this.startPreviewServer();
|
|
471
|
+
}
|
|
472
|
+
async startPreviewServer() {
|
|
321
473
|
const previewHostname = this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME;
|
|
322
474
|
const previewPort = Number(this.serveOptions.port || DEFAULT_ECOPAGES_PORT);
|
|
323
475
|
const activePreviewPort = await this.previewHost.start({
|
|
324
476
|
appConfig: this.appConfig,
|
|
325
477
|
hostname: String(previewHostname),
|
|
326
|
-
port: previewPort
|
|
478
|
+
port: previewPort,
|
|
479
|
+
allowPortFallback: this.allowPortFallback
|
|
327
480
|
});
|
|
328
|
-
if (activePreviewPort) {
|
|
329
|
-
|
|
330
|
-
return;
|
|
481
|
+
if (!activePreviewPort) {
|
|
482
|
+
return void 0;
|
|
331
483
|
}
|
|
484
|
+
return `http://${previewHostname}:${activePreviewPort}`;
|
|
332
485
|
}
|
|
333
486
|
/**
|
|
334
487
|
* Initializes the server with dynamic routes after server creation.
|
|
@@ -362,6 +515,9 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
362
515
|
staticRoutes: this.staticRoutes,
|
|
363
516
|
hmrManager: this.hmrManager
|
|
364
517
|
});
|
|
518
|
+
if (this.options?.watch) {
|
|
519
|
+
await this.hmrManager.ensureRuntimeReady();
|
|
520
|
+
}
|
|
365
521
|
this.fullyInitialized = true;
|
|
366
522
|
if (this.options?.watch) await this.watch();
|
|
367
523
|
if (server && typeof server.reload === "function") {
|
|
@@ -379,10 +535,34 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
379
535
|
return {
|
|
380
536
|
getServerOptions: this.getServerOptions.bind(this),
|
|
381
537
|
buildStatic: this.buildStatic.bind(this),
|
|
538
|
+
servePreviewOnly: this.servePreviewOnly.bind(this),
|
|
382
539
|
completeInitialization: this.completeInitialization.bind(this),
|
|
383
|
-
handleRequest: this.handleRequest.bind(this)
|
|
540
|
+
handleRequest: this.handleRequest.bind(this),
|
|
541
|
+
attachUserWebSocketUpgrades: this.attachUserWebSocketUpgrades.bind(this),
|
|
542
|
+
dispose: this.dispose.bind(this)
|
|
384
543
|
};
|
|
385
544
|
}
|
|
545
|
+
/**
|
|
546
|
+
* Releases dev-time resources owned by the adapter.
|
|
547
|
+
*
|
|
548
|
+
* @remarks
|
|
549
|
+
* Safe to call multiple times. Does not stop the bound Bun server — callers
|
|
550
|
+
* should shut down transport through the runtime host before disposing.
|
|
551
|
+
*/
|
|
552
|
+
async dispose() {
|
|
553
|
+
if (this.adapterDisposed) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
this.adapterDisposed = true;
|
|
557
|
+
await disposeDevResources({
|
|
558
|
+
projectWatcher: this.projectWatcher,
|
|
559
|
+
appConfig: this.appConfig,
|
|
560
|
+
hmrManager: this.hmrManager,
|
|
561
|
+
bridge: this.bridge,
|
|
562
|
+
previewHost: this.previewHost
|
|
563
|
+
});
|
|
564
|
+
this.projectWatcher = null;
|
|
565
|
+
}
|
|
386
566
|
/**
|
|
387
567
|
* Handles HTTP requests by passing them securely to the shared core router adapter.
|
|
388
568
|
*
|
|
@@ -434,6 +614,8 @@ async function createBunServerAdapter(params) {
|
|
|
434
614
|
const runtimeOrigin = params.runtimeOrigin ?? resolveServeRuntimeOrigin(params.serveOptions);
|
|
435
615
|
const bridge = params.bridge ?? new ClientBridge();
|
|
436
616
|
const hmrManager = params.hmrManager ?? new HmrManager({ appConfig: params.appConfig, bridge });
|
|
617
|
+
setAppDevClientBridge(params.appConfig, bridge);
|
|
618
|
+
setAppHmrManager(params.appConfig, hmrManager);
|
|
437
619
|
const previewHost = params.previewHost ?? new BunStaticPreviewHost();
|
|
438
620
|
const adapter = new BunServerAdapter({
|
|
439
621
|
...params,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StaticContentServer } from "../../dev/sc-server.js";
|
|
2
2
|
import { appLogger } from "../../global/app-logger.js";
|
|
3
|
+
import { PortManager } from "../shared/port-manager.js";
|
|
3
4
|
class BunStaticPreviewHost {
|
|
4
5
|
constructor(previewServerFactory = StaticContentServer, logger = appLogger) {
|
|
5
6
|
this.previewServerFactory = previewServerFactory;
|
|
@@ -10,30 +11,34 @@ class BunStaticPreviewHost {
|
|
|
10
11
|
previewServer = null;
|
|
11
12
|
async start(options) {
|
|
12
13
|
await this.stop();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
let previewServer = null;
|
|
15
|
+
const portManager = new PortManager({
|
|
16
|
+
startOnPort: async (port) => {
|
|
17
|
+
const candidate = this.previewServerFactory.createServer({
|
|
17
18
|
appConfig: options.appConfig,
|
|
18
|
-
options: { port
|
|
19
|
+
options: { port }
|
|
19
20
|
});
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
|
|
21
|
+
const boundPort = candidate.server?.port ?? null;
|
|
22
|
+
if (!boundPort) {
|
|
23
|
+
candidate.stop();
|
|
24
|
+
return null;
|
|
23
25
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
previewServer = candidate;
|
|
27
|
+
return boundPort;
|
|
28
|
+
},
|
|
29
|
+
warn: (message) => appLogger.warn(message)
|
|
30
|
+
});
|
|
31
|
+
const previewPort = await portManager.bind({
|
|
32
|
+
preferredPort: options.port,
|
|
33
|
+
allowPortFallback: options.allowPortFallback === true
|
|
34
|
+
});
|
|
35
|
+
if (!previewPort) {
|
|
36
|
+
this.previewServer = null;
|
|
37
|
+
this.logger.error("Failed to start preview server");
|
|
38
|
+
return null;
|
|
34
39
|
}
|
|
35
|
-
this.
|
|
36
|
-
return
|
|
40
|
+
this.previewServer = previewServer;
|
|
41
|
+
return previewPort;
|
|
37
42
|
}
|
|
38
43
|
async stop() {
|
|
39
44
|
this.previewServer?.stop();
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import type { EcoPagesAppConfig } from '../types/internal-types.js';
|
|
2
2
|
import { AbstractApplicationAdapter } from './abstract/application-adapter.js';
|
|
3
3
|
import type { ApplicationAdapterOptions } from './abstract/application-adapter.js';
|
|
4
|
-
|
|
4
|
+
export type { OnAppStartCallback, AppStartInfo, StartCallback, ListenCallback, ApplicationListeningCallback, ApplicationListeningInfo, } from './abstract/application-adapter.js';
|
|
5
|
+
export type EcopagesRuntimeAdapter = 'auto' | 'node' | 'bun';
|
|
5
6
|
export interface EcopagesAppOptions extends ApplicationAdapterOptions {
|
|
6
7
|
appConfig: EcoPagesAppConfig;
|
|
8
|
+
/**
|
|
9
|
+
* Selects the runtime adapter used by the universal `createApp()` entrypoint.
|
|
10
|
+
*
|
|
11
|
+
* @default 'auto'
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* This is separate from `runtime`, which configures embedded host behavior.
|
|
15
|
+
* Use `auto` to select Bun when the current process exposes `globalThis.Bun`
|
|
16
|
+
* and Node otherwise.
|
|
17
|
+
*/
|
|
18
|
+
adapter?: EcopagesRuntimeAdapter;
|
|
7
19
|
serverOptions?: Record<string, any>;
|
|
8
20
|
}
|
|
9
21
|
export type UniversalEcopagesApp = AbstractApplicationAdapter<EcopagesAppOptions, unknown, Request>;
|
|
10
22
|
export declare function createApp<WebSocketData = undefined>(options: EcopagesAppOptions): Promise<UniversalEcopagesApp>;
|
|
11
|
-
export declare class EcopagesApp extends SharedApplicationAdapter<EcopagesAppOptions, unknown, Request> {
|
|
12
|
-
private readonly appOptions;
|
|
13
|
-
private runtimeApp;
|
|
14
|
-
private runtimeAppPromise;
|
|
15
|
-
constructor(options: EcopagesAppOptions);
|
|
16
|
-
private getRuntimeApp;
|
|
17
|
-
protected initializeServerAdapter(): Promise<UniversalEcopagesApp>;
|
|
18
|
-
start(): Promise<unknown>;
|
|
19
|
-
fetch(request: Request): Promise<Response>;
|
|
20
|
-
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AbstractApplicationAdapter } from "./abstract/application-adapter.js";
|
|
2
|
-
import { SharedApplicationAdapter } from "./shared/application-adapter.js";
|
|
3
2
|
import { createApp as createBunApp } from "./bun/create-app.js";
|
|
4
3
|
import { createNodeApp } from "./node/create-app.js";
|
|
5
4
|
async function createRuntimeApp(options) {
|
|
5
|
+
const adapter = options.adapter ?? "auto";
|
|
6
6
|
const bun = globalThis.Bun;
|
|
7
|
-
if (bun) {
|
|
7
|
+
if (adapter === "bun" || adapter === "auto" && bun) {
|
|
8
8
|
return await createBunApp(options);
|
|
9
9
|
}
|
|
10
10
|
return await createNodeApp(options);
|
|
@@ -12,55 +12,6 @@ async function createRuntimeApp(options) {
|
|
|
12
12
|
async function createApp(options) {
|
|
13
13
|
return createRuntimeApp(options);
|
|
14
14
|
}
|
|
15
|
-
class EcopagesApp extends SharedApplicationAdapter {
|
|
16
|
-
appOptions;
|
|
17
|
-
runtimeApp = null;
|
|
18
|
-
runtimeAppPromise = null;
|
|
19
|
-
constructor(options) {
|
|
20
|
-
super(options);
|
|
21
|
-
this.appOptions = options;
|
|
22
|
-
}
|
|
23
|
-
async getRuntimeApp() {
|
|
24
|
-
if (this.runtimeApp) {
|
|
25
|
-
return this.runtimeApp;
|
|
26
|
-
}
|
|
27
|
-
if (!this.runtimeAppPromise) {
|
|
28
|
-
this.runtimeAppPromise = createRuntimeApp({
|
|
29
|
-
...this.appOptions,
|
|
30
|
-
clearOutput: false
|
|
31
|
-
}).then((app) => {
|
|
32
|
-
for (const handler of this.apiHandlers) {
|
|
33
|
-
app.add(handler);
|
|
34
|
-
}
|
|
35
|
-
for (const route of this.staticRoutes) {
|
|
36
|
-
app.static(route.path, route.loader);
|
|
37
|
-
}
|
|
38
|
-
if (this.errorHandler) {
|
|
39
|
-
app.onError(this.errorHandler);
|
|
40
|
-
}
|
|
41
|
-
this.runtimeApp = app;
|
|
42
|
-
return app;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return this.runtimeAppPromise;
|
|
46
|
-
}
|
|
47
|
-
async initializeServerAdapter() {
|
|
48
|
-
return this.getRuntimeApp();
|
|
49
|
-
}
|
|
50
|
-
async start() {
|
|
51
|
-
const runtimeApp = await this.getRuntimeApp();
|
|
52
|
-
return runtimeApp.start();
|
|
53
|
-
}
|
|
54
|
-
async fetch(request) {
|
|
55
|
-
const runtimeApp = await this.getRuntimeApp();
|
|
56
|
-
const candidate = runtimeApp;
|
|
57
|
-
if (!candidate.fetch) {
|
|
58
|
-
throw new Error("The selected runtime adapter does not expose fetch()");
|
|
59
|
-
}
|
|
60
|
-
return candidate.fetch(request);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
15
|
export {
|
|
64
|
-
EcopagesApp,
|
|
65
16
|
createApp
|
|
66
17
|
};
|
package/src/adapters/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createApp } from './create-app.js';
|
|
2
2
|
export { defineApiHandler, defineGroupHandler, type GroupHandler } from './shared/define-api-handler.js';
|
package/src/adapters/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createApp } from "./create-app.js";
|
|
2
2
|
import { defineApiHandler, defineGroupHandler } from "./shared/define-api-handler.js";
|
|
3
3
|
export {
|
|
4
|
-
EcopagesApp,
|
|
5
4
|
createApp,
|
|
6
5
|
defineApiHandler,
|
|
7
6
|
defineGroupHandler
|