@ecopages/core 0.2.0-beta.1 → 0.2.0-beta.11
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/package.json +107 -3
- package/src/adapters/abstract/application-adapter.d.ts +73 -1
- package/src/adapters/abstract/application-adapter.js +89 -0
- package/src/adapters/abstract/server-adapter.d.ts +3 -0
- 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 +5 -3
- package/src/adapters/bun/create-app.js +44 -39
- package/src/adapters/bun/hmr-manager.d.ts +2 -1
- package/src/adapters/bun/hmr-manager.js +2 -2
- package/src/adapters/bun/server-adapter.d.ts +81 -20
- package/src/adapters/bun/server-adapter.js +220 -78
- package/src/adapters/bun/static-preview-host.js +25 -20
- package/src/adapters/create-app.d.ts +13 -0
- package/src/adapters/create-app.js +10 -1
- package/src/adapters/node/create-app.d.ts +4 -0
- package/src/adapters/node/create-app.js +38 -9
- 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/node-hmr-manager.d.ts +2 -1
- package/src/adapters/node/node-hmr-manager.js +2 -2
- package/src/adapters/node/server-adapter-dependencies.js +2 -0
- package/src/adapters/node/server-adapter.d.ts +55 -19
- package/src/adapters/node/server-adapter.js +140 -132
- 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/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 +38 -0
- package/src/adapters/shared/runtime-server-lifecycle.js +39 -0
- package/src/adapters/shared/server-adapter.d.ts +2 -1
- package/src/adapters/shared/server-adapter.js +12 -4
- 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 +14 -29
- package/src/adapters/shared/server-static-builder.js +91 -70
- package/src/adapters/shared/shared-hmr-manager.d.ts +12 -0
- package/src/adapters/shared/shared-hmr-manager.js +64 -7
- 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 +10 -0
- package/src/build/app-build-manifest-runtime.js +90 -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/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/host-runtime.d.ts +3 -0
- package/src/dev/host-runtime.js +7 -0
- package/src/hmr/client/hmr-runtime.js +5 -2
- 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 +90 -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 +54 -0
- package/src/route-renderer/orchestration/document-shell-render.service.js +54 -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 +108 -194
- 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/ownership-validation.service.d.ts +4 -0
- package/src/route-renderer/orchestration/ownership-validation.service.js +11 -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 +24 -0
- package/src/route-renderer/orchestration/route-prepared-options.builder.js +52 -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 +5 -38
- package/src/route-renderer/orchestration/route-render-orchestrator.js +51 -459
- package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
- package/src/route-renderer/orchestration/string-markup-renderer.js +54 -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.js +32 -14
- 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 +10 -1
- package/src/services/invalidation/development-invalidation.service.js +31 -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 +4 -1
- package/src/services/module-loading/page-module-import.service.js +61 -41
- 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 +121 -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 +12 -9
- package/src/types/public-types.d.ts +87 -22
- package/src/utils/parse-cli-args.d.ts +1 -0
- package/src/utils/parse-cli-args.js +3 -0
- package/src/watchers/project-watcher.d.ts +14 -2
- package/src/watchers/project-watcher.js +50 -20
- 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.d.ts +0 -1
- package/src/hmr/hmr.postcss.test.e2e.js +0 -31
- package/src/hmr/hmr.test.e2e.d.ts +0 -1
- 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
|
@@ -4,6 +4,7 @@ import { SharedHmrManager } from '../shared/shared-hmr-manager.js';
|
|
|
4
4
|
export interface NodeHmrManagerParams {
|
|
5
5
|
appConfig: EcoPagesAppConfig;
|
|
6
6
|
bridge: IClientBridge;
|
|
7
|
+
registrationTimeoutMs?: number;
|
|
7
8
|
}
|
|
8
9
|
/**
|
|
9
10
|
* Node development HMR manager.
|
|
@@ -28,7 +29,7 @@ export declare class NodeHmrManager extends SharedHmrManager {
|
|
|
28
29
|
* actually differs: dependency-graph storage, missing-file tolerance, and how
|
|
29
30
|
* runtime bundle failures disable HMR.
|
|
30
31
|
*/
|
|
31
|
-
constructor({ appConfig, bridge }: NodeHmrManagerParams);
|
|
32
|
+
constructor({ appConfig, bridge, registrationTimeoutMs }: NodeHmrManagerParams);
|
|
32
33
|
/**
|
|
33
34
|
* Reuses the shared in-memory dependency graph when the app already has one and
|
|
34
35
|
* otherwise creates the default Node development graph.
|
|
@@ -13,8 +13,8 @@ class NodeHmrManager extends SharedHmrManager {
|
|
|
13
13
|
* actually differs: dependency-graph storage, missing-file tolerance, and how
|
|
14
14
|
* runtime bundle failures disable HMR.
|
|
15
15
|
*/
|
|
16
|
-
constructor({ appConfig, bridge }) {
|
|
17
|
-
super({ appConfig, bridge });
|
|
16
|
+
constructor({ appConfig, bridge, registrationTimeoutMs }) {
|
|
17
|
+
super({ appConfig, bridge, registrationTimeoutMs });
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Reuses the shared in-memory dependency graph when the app already has one and
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WebSocketServer } from "ws";
|
|
2
|
+
import { setAppDevClientBridge } from "../../dev/client-bridge-registry.js";
|
|
2
3
|
import { NodeClientBridge } from "./node-client-bridge.js";
|
|
3
4
|
import { NodeHmrManager } from "./node-hmr-manager.js";
|
|
4
5
|
class DefaultNodeServerDevRuntimeFactory {
|
|
@@ -6,6 +7,7 @@ class DefaultNodeServerDevRuntimeFactory {
|
|
|
6
7
|
const websocketServer = new WebSocketServer({ noServer: true });
|
|
7
8
|
const bridge = new NodeClientBridge();
|
|
8
9
|
const hmrManager = new NodeHmrManager({ appConfig: options.appConfig, bridge });
|
|
10
|
+
setAppDevClientBridge(options.appConfig, bridge);
|
|
9
11
|
return {
|
|
10
12
|
websocketServer,
|
|
11
13
|
bridge,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Server as NodeHttpServer } from 'node:http';
|
|
2
2
|
import type { EcoPagesAppConfig } from '../../types/internal-types.js';
|
|
3
|
-
import type { ApiHandler, ErrorHandler, StaticRoute } from '../../types/public-types.js';
|
|
3
|
+
import type { ApiHandler, ErrorHandler, StaticRoute, EcopagesWebSocketHandler } from '../../types/public-types.js';
|
|
4
4
|
import { SharedServerAdapter } from '../shared/server-adapter.js';
|
|
5
5
|
import type { ServerAdapterResult } from '../abstract/server-adapter.js';
|
|
6
6
|
import { NodeHttpRequestBridge } from './http-request-bridge.js';
|
|
@@ -19,9 +19,14 @@ export interface NodeServerAdapterParams {
|
|
|
19
19
|
apiHandlers?: ApiHandler[];
|
|
20
20
|
staticRoutes?: StaticRoute[];
|
|
21
21
|
errorHandler?: ErrorHandler;
|
|
22
|
+
websocketHandlers?: Map<string, EcopagesWebSocketHandler<any, any>>;
|
|
23
|
+
delegateBrowserReloadToHost?: boolean;
|
|
24
|
+
hostOwnsDevClient?: boolean;
|
|
22
25
|
options?: {
|
|
23
26
|
watch?: boolean;
|
|
24
27
|
};
|
|
28
|
+
deferRuntimeAssetSetup?: boolean;
|
|
29
|
+
allowPortFallback?: boolean;
|
|
25
30
|
previewHost?: StaticPreviewHost;
|
|
26
31
|
requestBridge?: NodeHttpRequestBridge;
|
|
27
32
|
devRuntimeFactory?: NodeServerDevRuntimeFactory;
|
|
@@ -29,6 +34,10 @@ export interface NodeServerAdapterParams {
|
|
|
29
34
|
export interface NodeServerAdapterResult extends ServerAdapterResult {
|
|
30
35
|
completeInitialization: (server: NodeServerInstance) => Promise<void>;
|
|
31
36
|
handleRequest: (request: Request) => Promise<Response>;
|
|
37
|
+
attachUserWebSocketUpgrades: (server: NodeServerInstance, options?: {
|
|
38
|
+
passthroughUnmatched?: boolean;
|
|
39
|
+
}) => void;
|
|
40
|
+
dispose: () => Promise<void>;
|
|
32
41
|
}
|
|
33
42
|
/**
|
|
34
43
|
* Node.js HTTP server adapter for the Ecopages runtime.
|
|
@@ -58,13 +67,47 @@ export declare class NodeServerAdapter extends SharedServerAdapter<NodeServerAda
|
|
|
58
67
|
private errorHandler?;
|
|
59
68
|
private bridge;
|
|
60
69
|
private hmrManager;
|
|
70
|
+
private projectWatcher;
|
|
71
|
+
private adapterDisposed;
|
|
72
|
+
private readonly deferRuntimeAssetSetup;
|
|
73
|
+
private readonly allowPortFallback;
|
|
61
74
|
private readonly previewHost;
|
|
62
75
|
private readonly requestBridge;
|
|
63
76
|
private readonly devRuntimeFactory;
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Reference to the application-level WebSocket handlers map.
|
|
79
|
+
*
|
|
80
|
+
* @remarks
|
|
81
|
+
* This is a reference to the map owned by `AbstractApplicationAdapter`,
|
|
82
|
+
* passed in via the constructor. The Node adapter reads from it to wire
|
|
83
|
+
* WebSocket upgrades for user-registered patterns.
|
|
84
|
+
*/
|
|
85
|
+
protected websocketHandlers: Map<string, EcopagesWebSocketHandler<any, any>>;
|
|
86
|
+
/**
|
|
87
|
+
* Wires user WebSocket routes onto a foreign Node HTTP server.
|
|
88
|
+
*
|
|
89
|
+
* Host integrations such as the Vite plugin call this so `app.websocket()`
|
|
90
|
+
* handlers work while HTTP is still served by the host dev server.
|
|
91
|
+
*/
|
|
92
|
+
attachUserWebSocketUpgrades(server: NodeServerInstance, options?: {
|
|
93
|
+
passthroughUnmatched?: boolean;
|
|
94
|
+
}): void;
|
|
95
|
+
private wireUserWebSocketUpgrades;
|
|
66
96
|
private maybeInjectHmrScript;
|
|
67
|
-
|
|
97
|
+
/**
|
|
98
|
+
* @remarks
|
|
99
|
+
* `previewHost`, `requestBridge`, and `devRuntimeFactory` are optional on the
|
|
100
|
+
* public {@link NodeServerAdapterParams} so factory callers can omit them, but
|
|
101
|
+
* they are mandatory by the time the concrete adapter is constructed —
|
|
102
|
+
* {@link createNodeServerAdapter} fills in Node-specific defaults first. The
|
|
103
|
+
* constructor signature makes that invariant explicit instead of relying on
|
|
104
|
+
* non-null assertions.
|
|
105
|
+
*/
|
|
106
|
+
constructor(options: NodeServerAdapterParams & {
|
|
107
|
+
previewHost: StaticPreviewHost;
|
|
108
|
+
requestBridge: NodeHttpRequestBridge;
|
|
109
|
+
devRuntimeFactory: NodeServerDevRuntimeFactory;
|
|
110
|
+
});
|
|
68
111
|
/**
|
|
69
112
|
* Prepares the adapter for use.
|
|
70
113
|
*
|
|
@@ -79,27 +122,20 @@ export declare class NodeServerAdapter extends SharedServerAdapter<NodeServerAda
|
|
|
79
122
|
* processors during their `setup()` calls.
|
|
80
123
|
*/
|
|
81
124
|
initialize(): Promise<void>;
|
|
82
|
-
private prepareRuntimePublicDir;
|
|
83
125
|
getServerOptions(): NodeServeAdapterServerOptions;
|
|
84
126
|
buildStatic(options?: {
|
|
85
127
|
preview?: boolean;
|
|
128
|
+
force?: boolean;
|
|
86
129
|
}): Promise<void>;
|
|
87
|
-
|
|
88
|
-
private getListeningServerOrigin;
|
|
130
|
+
createAdapter(): Promise<NodeServerAdapterResult>;
|
|
89
131
|
/**
|
|
90
|
-
*
|
|
132
|
+
* Releases dev-time resources owned by the adapter.
|
|
91
133
|
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* `closeAllConnections()` force-closes any lingering sockets immediately so
|
|
96
|
-
* the `close()` callback fires promptly.
|
|
97
|
-
*
|
|
98
|
-
* The `NodeClientBridge` heartbeat is also destroyed here so its `setInterval`
|
|
99
|
-
* does not prevent the Node.js process from exiting cleanly after the build.
|
|
134
|
+
* @remarks
|
|
135
|
+
* Safe to call multiple times. Does not stop the bound HTTP server — callers
|
|
136
|
+
* should shut down transport through the runtime host before disposing.
|
|
100
137
|
*/
|
|
101
|
-
|
|
102
|
-
createAdapter(): Promise<NodeServerAdapterResult>;
|
|
138
|
+
dispose(): Promise<void>;
|
|
103
139
|
/**
|
|
104
140
|
* Handles a single incoming Web `Request` and returns a Web `Response`.
|
|
105
141
|
*
|
|
@@ -123,7 +159,7 @@ export declare class NodeServerAdapter extends SharedServerAdapter<NodeServerAda
|
|
|
123
159
|
* - Shared watcher bootstrapping listens for route-level file changes and
|
|
124
160
|
* refreshes the router and response handlers when pages are added or removed.
|
|
125
161
|
*
|
|
126
|
-
* WebSocket upgrade requests that do not
|
|
162
|
+
* WebSocket upgrade requests that do not match a known path are rejected with an
|
|
127
163
|
* immediate socket destroy to prevent unhandled upgrade leaks.
|
|
128
164
|
*/
|
|
129
165
|
completeInitialization(server: NodeServerInstance): Promise<void>;
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { fileSystem } from "@ecopages/file-system";
|
|
4
|
-
import { getAppBrowserBuildPlugins, setupAppRuntimePlugins } from "../../build/build-adapter.js";
|
|
1
|
+
import {} from "node:http";
|
|
2
|
+
import { setupAppRuntimePlugins } from "../../build/build-adapter.js";
|
|
5
3
|
import { installAppRuntimeBuildExecutor } from "../../build/runtime-build-executor.js";
|
|
6
|
-
import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
|
|
7
4
|
import { appLogger } from "../../global/app-logger.js";
|
|
8
5
|
import { NodeClientBridge } from "./node-client-bridge.js";
|
|
9
6
|
import { NodeHmrManager } from "./node-hmr-manager.js";
|
|
10
7
|
import { ProjectWatcher } from "../../watchers/project-watcher.js";
|
|
8
|
+
import {
|
|
9
|
+
attachNodeHttpWebSocketUpgrades
|
|
10
|
+
} from "../shared/node-http-websocket-upgrades.js";
|
|
11
11
|
import { StaticSiteGenerator } from "../../static-site-generator/static-site-generator.js";
|
|
12
12
|
import { SharedServerAdapter } from "../shared/server-adapter.js";
|
|
13
13
|
import { ServerStaticBuilder } from "../shared/server-static-builder.js";
|
|
14
14
|
import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT } from "../../config/constants.js";
|
|
15
15
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
maybeInjectAdapterHmrHtmlResponse,
|
|
17
|
+
prepareRuntimePublicDir,
|
|
18
|
+
wireIntegrationHmrManagers,
|
|
19
|
+
disposeDevResources
|
|
20
|
+
} from "../shared/runtime-server-lifecycle.js";
|
|
20
21
|
import { resolveServeRuntimeOrigin } from "../shared/runtime-app-bootstrap.js";
|
|
21
22
|
import { NodeClientAbortError, NodeHttpRequestBridge } from "./http-request-bridge.js";
|
|
22
23
|
import { NodeStaticPreviewHost } from "./static-preview-host.js";
|
|
@@ -29,29 +30,73 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
29
30
|
errorHandler;
|
|
30
31
|
bridge = null;
|
|
31
32
|
hmrManager = null;
|
|
33
|
+
projectWatcher = null;
|
|
34
|
+
adapterDisposed = false;
|
|
35
|
+
deferRuntimeAssetSetup;
|
|
36
|
+
allowPortFallback;
|
|
32
37
|
previewHost;
|
|
33
38
|
requestBridge;
|
|
34
39
|
devRuntimeFactory;
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Reference to the application-level WebSocket handlers map.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* This is a reference to the map owned by `AbstractApplicationAdapter`,
|
|
45
|
+
* passed in via the constructor. The Node adapter reads from it to wire
|
|
46
|
+
* WebSocket upgrades for user-registered patterns.
|
|
47
|
+
*/
|
|
48
|
+
websocketHandlers = /* @__PURE__ */ new Map();
|
|
49
|
+
/**
|
|
50
|
+
* Wires user WebSocket routes onto a foreign Node HTTP server.
|
|
51
|
+
*
|
|
52
|
+
* Host integrations such as the Vite plugin call this so `app.websocket()`
|
|
53
|
+
* handlers work while HTTP is still served by the host dev server.
|
|
54
|
+
*/
|
|
55
|
+
attachUserWebSocketUpgrades(server, options) {
|
|
56
|
+
attachNodeHttpWebSocketUpgrades(server, {
|
|
57
|
+
runtimeOrigin: this.runtimeOrigin,
|
|
58
|
+
websocketHandlers: this.websocketHandlers,
|
|
59
|
+
passthroughUnmatched: options?.passthroughUnmatched
|
|
60
|
+
});
|
|
37
61
|
}
|
|
38
|
-
|
|
39
|
-
|
|
62
|
+
wireUserWebSocketUpgrades(server, preflight) {
|
|
63
|
+
attachNodeHttpWebSocketUpgrades(server, {
|
|
64
|
+
runtimeOrigin: this.runtimeOrigin,
|
|
65
|
+
websocketHandlers: this.websocketHandlers,
|
|
66
|
+
passthroughUnmatched: false,
|
|
67
|
+
preflight
|
|
68
|
+
});
|
|
40
69
|
}
|
|
41
70
|
async maybeInjectHmrScript(response) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
71
|
+
return maybeInjectAdapterHmrHtmlResponse(response, {
|
|
72
|
+
watch: this.options?.watch === true,
|
|
73
|
+
hmrManager: this.hmrManager ?? void 0,
|
|
74
|
+
hostOwnsDevClient: this.hostOwnsDevClient
|
|
75
|
+
});
|
|
46
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* @remarks
|
|
79
|
+
* `previewHost`, `requestBridge`, and `devRuntimeFactory` are optional on the
|
|
80
|
+
* public {@link NodeServerAdapterParams} so factory callers can omit them, but
|
|
81
|
+
* they are mandatory by the time the concrete adapter is constructed —
|
|
82
|
+
* {@link createNodeServerAdapter} fills in Node-specific defaults first. The
|
|
83
|
+
* constructor signature makes that invariant explicit instead of relying on
|
|
84
|
+
* non-null assertions.
|
|
85
|
+
*/
|
|
47
86
|
constructor(options) {
|
|
48
87
|
super(options);
|
|
88
|
+
this.deferRuntimeAssetSetup = options.deferRuntimeAssetSetup === true;
|
|
89
|
+
this.allowPortFallback = options.allowPortFallback !== false;
|
|
49
90
|
this.apiHandlers = options.apiHandlers || [];
|
|
50
91
|
this.staticRoutes = options.staticRoutes || [];
|
|
51
92
|
this.errorHandler = options.errorHandler;
|
|
52
93
|
this.previewHost = options.previewHost;
|
|
53
94
|
this.requestBridge = options.requestBridge;
|
|
54
95
|
this.devRuntimeFactory = options.devRuntimeFactory;
|
|
96
|
+
if (options.websocketHandlers) {
|
|
97
|
+
this.websocketHandlers = options.websocketHandlers;
|
|
98
|
+
}
|
|
99
|
+
this.hostOwnsDevClient = options.hostOwnsDevClient === true;
|
|
55
100
|
}
|
|
56
101
|
/**
|
|
57
102
|
* Prepares the adapter for use.
|
|
@@ -68,12 +113,14 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
68
113
|
*/
|
|
69
114
|
async initialize() {
|
|
70
115
|
installAppRuntimeBuildExecutor(this.appConfig);
|
|
71
|
-
this.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
116
|
+
prepareRuntimePublicDir(this.appConfig);
|
|
117
|
+
if (!this.deferRuntimeAssetSetup) {
|
|
118
|
+
await setupAppRuntimePlugins({
|
|
119
|
+
appConfig: this.appConfig,
|
|
120
|
+
runtimeOrigin: this.runtimeOrigin,
|
|
121
|
+
hmrManager: this.hmrManager ?? void 0
|
|
122
|
+
});
|
|
123
|
+
}
|
|
77
124
|
await this.initializeSharedRouteHandling({
|
|
78
125
|
staticRoutes: this.staticRoutes,
|
|
79
126
|
hmrManager: this.hmrManager ?? void 0
|
|
@@ -83,17 +130,12 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
83
130
|
appConfig: this.appConfig,
|
|
84
131
|
staticSiteGenerator: this.staticSiteGenerator,
|
|
85
132
|
serveOptions: this.serveOptions,
|
|
86
|
-
|
|
133
|
+
runtimeOrigin: this.runtimeOrigin,
|
|
134
|
+
apiHandlers: this.apiHandlers,
|
|
135
|
+
hmrManager: this.hmrManager ?? void 0
|
|
87
136
|
});
|
|
88
137
|
this.initialized = true;
|
|
89
138
|
}
|
|
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
139
|
getServerOptions() {
|
|
98
140
|
return {
|
|
99
141
|
...this.serveOptions
|
|
@@ -103,96 +145,29 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
103
145
|
if (!this.initialized) {
|
|
104
146
|
await this.initialize();
|
|
105
147
|
}
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
);
|
|
117
|
-
} finally {
|
|
118
|
-
await this.stopBuildRuntimeServer(buildServer);
|
|
119
|
-
}
|
|
148
|
+
const baseUrl = resolveServeRuntimeOrigin(this.serveOptions);
|
|
149
|
+
await this.staticBuilder.build(
|
|
150
|
+
{ baseUrl, force: options?.force },
|
|
151
|
+
{
|
|
152
|
+
router: this.router,
|
|
153
|
+
routeRendererFactory: this.routeRendererFactory,
|
|
154
|
+
staticRoutes: this.staticRoutes
|
|
155
|
+
}
|
|
156
|
+
);
|
|
120
157
|
if (!options?.preview) {
|
|
121
158
|
return;
|
|
122
159
|
}
|
|
123
|
-
await this.previewHost.start({
|
|
160
|
+
const activePreviewPort = await this.previewHost.start({
|
|
124
161
|
appConfig: this.appConfig,
|
|
125
162
|
hostname: String(this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME),
|
|
126
|
-
port: Number(this.serveOptions.port || DEFAULT_ECOPAGES_PORT)
|
|
163
|
+
port: Number(this.serveOptions.port || DEFAULT_ECOPAGES_PORT),
|
|
164
|
+
allowPortFallback: this.allowPortFallback
|
|
127
165
|
});
|
|
128
|
-
|
|
129
|
-
|
|
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");
|
|
147
|
-
}
|
|
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");
|
|
165
|
-
}
|
|
166
|
-
return `http://${hostname}:${address.port}`;
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
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.
|
|
179
|
-
*/
|
|
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();
|
|
190
|
-
});
|
|
191
|
-
if (this.serverInstance === server) {
|
|
192
|
-
this.serverInstance = null;
|
|
166
|
+
if (!activePreviewPort) {
|
|
167
|
+
return;
|
|
193
168
|
}
|
|
194
|
-
this.
|
|
195
|
-
|
|
169
|
+
const previewHostname = this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME;
|
|
170
|
+
appLogger.info(`Preview running at http://${previewHostname}:${activePreviewPort}`);
|
|
196
171
|
}
|
|
197
172
|
async createAdapter() {
|
|
198
173
|
await this.initialize();
|
|
@@ -200,9 +175,34 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
200
175
|
getServerOptions: this.getServerOptions.bind(this),
|
|
201
176
|
buildStatic: this.buildStatic.bind(this),
|
|
202
177
|
completeInitialization: this.completeInitialization.bind(this),
|
|
203
|
-
handleRequest: this.handleRequest.bind(this)
|
|
178
|
+
handleRequest: this.handleRequest.bind(this),
|
|
179
|
+
attachUserWebSocketUpgrades: this.attachUserWebSocketUpgrades.bind(this),
|
|
180
|
+
dispose: this.dispose.bind(this)
|
|
204
181
|
};
|
|
205
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Releases dev-time resources owned by the adapter.
|
|
185
|
+
*
|
|
186
|
+
* @remarks
|
|
187
|
+
* Safe to call multiple times. Does not stop the bound HTTP server — callers
|
|
188
|
+
* should shut down transport through the runtime host before disposing.
|
|
189
|
+
*/
|
|
190
|
+
async dispose() {
|
|
191
|
+
if (this.adapterDisposed) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
this.adapterDisposed = true;
|
|
195
|
+
await disposeDevResources({
|
|
196
|
+
projectWatcher: this.projectWatcher,
|
|
197
|
+
appConfig: this.appConfig,
|
|
198
|
+
hmrManager: this.hmrManager,
|
|
199
|
+
bridge: this.bridge,
|
|
200
|
+
previewHost: this.previewHost
|
|
201
|
+
});
|
|
202
|
+
this.projectWatcher = null;
|
|
203
|
+
this.hmrManager = null;
|
|
204
|
+
this.bridge = null;
|
|
205
|
+
}
|
|
206
206
|
/**
|
|
207
207
|
* Handles a single incoming Web `Request` and returns a Web `Response`.
|
|
208
208
|
*
|
|
@@ -244,11 +244,12 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
244
244
|
* - Shared watcher bootstrapping listens for route-level file changes and
|
|
245
245
|
* refreshes the router and response handlers when pages are added or removed.
|
|
246
246
|
*
|
|
247
|
-
* WebSocket upgrade requests that do not
|
|
247
|
+
* WebSocket upgrade requests that do not match a known path are rejected with an
|
|
248
248
|
* immediate socket destroy to prevent unhandled upgrade leaks.
|
|
249
249
|
*/
|
|
250
250
|
async completeInitialization(server) {
|
|
251
251
|
this.serverInstance = server;
|
|
252
|
+
const hasUserWs = this.websocketHandlers.size > 0;
|
|
252
253
|
if (this.options?.watch) {
|
|
253
254
|
const devRuntime = this.devRuntimeFactory.create({ appConfig: this.appConfig });
|
|
254
255
|
const wss = devRuntime.websocketServer;
|
|
@@ -256,23 +257,26 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
256
257
|
this.hmrManager = devRuntime.hmrManager;
|
|
257
258
|
this.hmrManager.setEnabled(true);
|
|
258
259
|
await this.hmrManager.buildRuntime();
|
|
259
|
-
|
|
260
|
+
const hmrPreflight = (req, socket, head) => {
|
|
260
261
|
const url = new URL(req.url ?? "/", this.runtimeOrigin);
|
|
261
|
-
if (url.pathname
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
262
|
+
if (url.pathname !== "/_hmr") return false;
|
|
263
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
264
|
+
this.bridge.subscribe(ws);
|
|
265
|
+
ws.on("close", () => this.bridge.unsubscribe(ws));
|
|
266
|
+
ws.on("error", (err) => appLogger.error("[HMR] WebSocket error:", err));
|
|
267
|
+
});
|
|
268
|
+
return true;
|
|
269
|
+
};
|
|
270
|
+
if (hasUserWs) {
|
|
271
|
+
this.wireUserWebSocketUpgrades(server, hmrPreflight);
|
|
272
|
+
} else {
|
|
273
|
+
server.on("upgrade", (req, socket, head) => {
|
|
274
|
+
if (!hmrPreflight(req, socket, head)) {
|
|
275
|
+
socket.destroy();
|
|
276
|
+
}
|
|
277
|
+
});
|
|
275
278
|
}
|
|
279
|
+
wireIntegrationHmrManagers(this.appConfig, this.hmrManager);
|
|
276
280
|
this.configureSharedResponseHandlers(this.staticRoutes, this.hmrManager);
|
|
277
281
|
const watcher = new ProjectWatcher({
|
|
278
282
|
config: this.appConfig,
|
|
@@ -281,9 +285,13 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
281
285
|
hmrManager: this.hmrManager
|
|
282
286
|
}),
|
|
283
287
|
hmrManager: this.hmrManager,
|
|
284
|
-
bridge: this.bridge
|
|
288
|
+
bridge: this.bridge,
|
|
289
|
+
hostOwnsDevClient: this.hostOwnsDevClient
|
|
285
290
|
});
|
|
291
|
+
this.projectWatcher = watcher;
|
|
286
292
|
await watcher.createWatcherSubscription();
|
|
293
|
+
} else if (hasUserWs) {
|
|
294
|
+
this.wireUserWebSocketUpgrades(server);
|
|
287
295
|
}
|
|
288
296
|
appLogger.debug("Node server adapter initialization completed", {
|
|
289
297
|
apiHandlers: this.apiHandlers.length,
|
|
@@ -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
|
|
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
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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
|
|
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
|
+
};
|