@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
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { createServer as createNetServer } from "node:net";
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
function isPortInUseError(error) {
|
|
4
|
+
if (!(error instanceof Error) && (typeof error !== "object" || error === null)) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
const maybeErr = error;
|
|
8
|
+
const code = typeof maybeErr.code === "string" || typeof maybeErr.code === "number" ? String(maybeErr.code) : void 0;
|
|
9
|
+
const syscall = typeof maybeErr.syscall === "string" ? maybeErr.syscall : void 0;
|
|
10
|
+
const message = error instanceof Error ? error.message : String(maybeErr.message ?? "");
|
|
11
|
+
if (code === "EADDRINUSE") {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (message.includes("EADDRINUSE")) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
if (syscall === "listen" && /is port \d+ in use\??/i.test(message)) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
function sleep(ms) {
|
|
23
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
24
|
+
}
|
|
25
|
+
function isPortAvailable(port, hostname = "127.0.0.1") {
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
const tester = createNetServer();
|
|
28
|
+
tester.once("error", () => resolve(false));
|
|
29
|
+
tester.once("listening", () => {
|
|
30
|
+
tester.close(() => resolve(true));
|
|
31
|
+
});
|
|
32
|
+
tester.listen(port, hostname);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function createDefaultPrompt(stdin, stdout) {
|
|
36
|
+
return async (message, timeoutMs) => {
|
|
37
|
+
stdout.write(`${message} `);
|
|
38
|
+
return await new Promise((resolve) => {
|
|
39
|
+
const rl = createInterface({ input: stdin, output: void 0, terminal: false });
|
|
40
|
+
let settled = false;
|
|
41
|
+
const finish = (value) => {
|
|
42
|
+
if (settled) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
settled = true;
|
|
46
|
+
clearTimeout(timer);
|
|
47
|
+
rl.close();
|
|
48
|
+
stdout.write("\n");
|
|
49
|
+
resolve(value);
|
|
50
|
+
};
|
|
51
|
+
const timer = setTimeout(() => finish(true), timeoutMs);
|
|
52
|
+
rl.once("line", (line) => {
|
|
53
|
+
const answer = line.trim().toLowerCase();
|
|
54
|
+
if (answer === "" || answer === "y" || answer === "yes") {
|
|
55
|
+
finish(true);
|
|
56
|
+
} else {
|
|
57
|
+
finish(false);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
rl.once("close", () => finish(true));
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const PREVIEW_PORT_RELEASE_RACE_RETRIES = 2;
|
|
65
|
+
const PREVIEW_PORT_FALLBACK_ATTEMPTS = 20;
|
|
66
|
+
const PREVIEW_PORT_RELEASE_RACE_DELAY_MS = 100;
|
|
67
|
+
const PREVIEW_PORT_AUTO_APPROVE_MS = 1e4;
|
|
68
|
+
class PortManager {
|
|
69
|
+
startOnPort;
|
|
70
|
+
warn;
|
|
71
|
+
probePort;
|
|
72
|
+
prompt;
|
|
73
|
+
interactive;
|
|
74
|
+
autoApproveMs;
|
|
75
|
+
maxPortOffset;
|
|
76
|
+
releaseRaceRetries;
|
|
77
|
+
releaseRaceDelayMs;
|
|
78
|
+
constructor(options) {
|
|
79
|
+
this.startOnPort = options.startOnPort;
|
|
80
|
+
this.warn = options.warn;
|
|
81
|
+
this.probePort = options.probePort ?? isPortAvailable;
|
|
82
|
+
this.maxPortOffset = options.maxPortOffset ?? PREVIEW_PORT_FALLBACK_ATTEMPTS - 1;
|
|
83
|
+
this.releaseRaceRetries = options.releaseRaceRetries ?? PREVIEW_PORT_RELEASE_RACE_RETRIES;
|
|
84
|
+
this.releaseRaceDelayMs = options.releaseRaceDelayMs ?? PREVIEW_PORT_RELEASE_RACE_DELAY_MS;
|
|
85
|
+
this.autoApproveMs = options.autoApproveMs ?? PREVIEW_PORT_AUTO_APPROVE_MS;
|
|
86
|
+
this.interactive = typeof options.interactive === "boolean" ? options.interactive : Boolean(typeof process !== "undefined" && process.stdin?.isTTY && process.stdout?.isTTY);
|
|
87
|
+
if (options.prompt) {
|
|
88
|
+
this.prompt = options.prompt;
|
|
89
|
+
} else if (this.interactive) {
|
|
90
|
+
this.prompt = createDefaultPrompt(process.stdin, process.stdout);
|
|
91
|
+
} else {
|
|
92
|
+
this.prompt = void 0;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Binds the preview server to the preferred port.
|
|
97
|
+
*
|
|
98
|
+
* @remarks
|
|
99
|
+
* When the preferred port is free, binds it directly — no prompt, no
|
|
100
|
+
* fallback. The interactive prompt only fires on a genuine EADDRINUSE
|
|
101
|
+
* collision (TTY runs), and auto-approves after
|
|
102
|
+
* {@link PortManagerOptions.autoApproveMs}. In non-interactive (CI) runs,
|
|
103
|
+
* the manager falls back silently only when
|
|
104
|
+
* {@link BindPortOptions.allowPortFallback} is true (the default-port
|
|
105
|
+
* path); pinned ports rethrow EADDRINUSE so Docker-style fixed-port
|
|
106
|
+
* deployments fail loudly instead of silently moving.
|
|
107
|
+
*/
|
|
108
|
+
async bind(options) {
|
|
109
|
+
const preferredPort = options.preferredPort;
|
|
110
|
+
const firstAttempt = await this.tryPort(preferredPort);
|
|
111
|
+
if (firstAttempt.status === "bound") {
|
|
112
|
+
return firstAttempt.boundPort;
|
|
113
|
+
}
|
|
114
|
+
if (firstAttempt.status === "factory-refused") {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
await this.shouldFallback(preferredPort, options.allowPortFallback, firstAttempt.error);
|
|
118
|
+
return await this.fallForward(preferredPort);
|
|
119
|
+
}
|
|
120
|
+
async shouldFallback(preferredPort, allowPortFallback, error) {
|
|
121
|
+
if (this.interactive && this.prompt) {
|
|
122
|
+
const nextFree = await this.findNextFreePort(preferredPort);
|
|
123
|
+
const nextFreeSuffix = typeof nextFree === "number" ? ` (next free: ${nextFree})` : "";
|
|
124
|
+
const autoApproveHint = `auto-yes in ${Math.round(this.autoApproveMs / 1e3)}s`;
|
|
125
|
+
const message = `[@ecopages/core] Port ${preferredPort} is already in use${nextFreeSuffix}. Bind there instead? [Y/n] (${autoApproveHint})`;
|
|
126
|
+
const accepted = await this.prompt(message, this.autoApproveMs);
|
|
127
|
+
if (!accepted) {
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (!allowPortFallback) {
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async fallForward(preferredPort) {
|
|
137
|
+
for (let offset = 1; offset <= this.maxPortOffset; offset += 1) {
|
|
138
|
+
const candidatePort = preferredPort + offset;
|
|
139
|
+
const attempt = await this.tryPort(candidatePort);
|
|
140
|
+
if (attempt.status === "bound") {
|
|
141
|
+
this.warn?.(
|
|
142
|
+
`Port ${preferredPort} is in use; preview serving on port ${attempt.boundPort} instead. Pin the preview port with --port or ECOPAGES_PORT when a fixed binding is required.`
|
|
143
|
+
);
|
|
144
|
+
return attempt.boundPort;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Attempts to bind via {@link PortManagerOptions.startOnPort} on `port`,
|
|
151
|
+
* retrying EADDRINUSE collisions up to
|
|
152
|
+
* {@link PortManagerOptions.releaseRaceRetries} to ride through TIME_WAIT
|
|
153
|
+
* race release.
|
|
154
|
+
*
|
|
155
|
+
* @remarks
|
|
156
|
+
* Only EADDRINUSE is retryable. Any other error is rethrown synchronously
|
|
157
|
+
* rather than swallowed as a soft "port taken" result, so a misconfigured
|
|
158
|
+
* factory surfaces loudly instead of causing a silent fallback. A `null`
|
|
159
|
+
* return from the factory (no throw) is reported as `factory-refused`, not
|
|
160
|
+
* conflated with a real collision.
|
|
161
|
+
*/
|
|
162
|
+
async tryPort(port) {
|
|
163
|
+
for (let attempt = 0; attempt < this.releaseRaceRetries; attempt += 1) {
|
|
164
|
+
try {
|
|
165
|
+
const bound = await this.startOnPort(port);
|
|
166
|
+
if (bound) {
|
|
167
|
+
return { status: "bound", boundPort: bound };
|
|
168
|
+
}
|
|
169
|
+
return { status: "factory-refused" };
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (!isPortInUseError(error)) {
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
if (attempt === this.releaseRaceRetries - 1) {
|
|
175
|
+
return { status: "port-in-use", error };
|
|
176
|
+
}
|
|
177
|
+
await sleep(this.releaseRaceDelayMs);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return { status: "factory-refused" };
|
|
181
|
+
}
|
|
182
|
+
async findNextFreePort(startPort) {
|
|
183
|
+
for (let offset = 1; offset <= this.maxPortOffset; offset += 1) {
|
|
184
|
+
const candidate = startPort + offset;
|
|
185
|
+
if (await this.probePort(candidate)) {
|
|
186
|
+
return candidate;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
export {
|
|
193
|
+
PortManager,
|
|
194
|
+
isPortAvailable,
|
|
195
|
+
isPortInUseError
|
|
196
|
+
};
|
|
@@ -6,9 +6,10 @@ export type RuntimeBinding = {
|
|
|
6
6
|
runtimeOrigin: string;
|
|
7
7
|
serveOptions: Record<string, unknown>;
|
|
8
8
|
watch: boolean;
|
|
9
|
+
/** Whether preview may bind to the next free port when the preferred port is busy. */
|
|
10
|
+
allowPortFallback: boolean;
|
|
9
11
|
};
|
|
10
12
|
export type StaticRuntimeMode = {
|
|
11
|
-
requiresFetchRuntime: boolean;
|
|
12
13
|
canBuildWithoutRuntimeServer: boolean;
|
|
13
14
|
};
|
|
14
15
|
export declare function resolveServeRuntimeOrigin(serveOptions: {
|
|
@@ -12,11 +12,13 @@ function resolveServeRuntimeOrigin(serveOptions) {
|
|
|
12
12
|
}
|
|
13
13
|
function resolveRuntimeBinding(options) {
|
|
14
14
|
const env = options.env ?? process.env;
|
|
15
|
+
const portExplicitlyConfigured = options.cliArgs.port !== void 0 || Boolean(env.ECOPAGES_PORT) || options.serverOptions?.port !== void 0;
|
|
15
16
|
const preferredPort = options.cliArgs.port ?? (env.ECOPAGES_PORT ? Number(env.ECOPAGES_PORT) : void 0) ?? DEFAULT_ECOPAGES_PORT;
|
|
16
17
|
const preferredHostname = options.cliArgs.hostname ?? env.ECOPAGES_HOSTNAME ?? DEFAULT_ECOPAGES_HOSTNAME;
|
|
17
18
|
return {
|
|
18
19
|
preferredPort,
|
|
19
20
|
preferredHostname,
|
|
21
|
+
allowPortFallback: !portExplicitlyConfigured,
|
|
20
22
|
runtimeOrigin: resolveServeRuntimeOrigin({
|
|
21
23
|
hostname: preferredHostname,
|
|
22
24
|
port: preferredPort
|
|
@@ -30,13 +32,8 @@ function resolveRuntimeBinding(options) {
|
|
|
30
32
|
};
|
|
31
33
|
}
|
|
32
34
|
function resolveStaticRuntimeMode(options) {
|
|
33
|
-
const requiresFetchRuntime = options.appConfig.integrations.some(
|
|
34
|
-
(integration) => integration.staticBuildStep === "fetch"
|
|
35
|
-
);
|
|
36
|
-
const canBuildWithoutRuntimeServer = (options.cliArgs.build || options.cliArgs.preview) && !requiresFetchRuntime;
|
|
37
35
|
return {
|
|
38
|
-
|
|
39
|
-
canBuildWithoutRuntimeServer
|
|
36
|
+
canBuildWithoutRuntimeServer: options.cliArgs.build || options.cliArgs.preview
|
|
40
37
|
};
|
|
41
38
|
}
|
|
42
39
|
export {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { EcoPagesAppConfig } from '../../types/internal-types.js';
|
|
2
|
+
import type { IHmrManager } from '../../types/public-types.js';
|
|
3
|
+
import type { ProjectWatcher } from '../../watchers/project-watcher.js';
|
|
4
|
+
/**
|
|
5
|
+
* Copies source `public/` into dist and ensures the resolved assets directory exists.
|
|
6
|
+
*/
|
|
7
|
+
export declare function prepareRuntimePublicDir(appConfig: EcoPagesAppConfig): void;
|
|
8
|
+
/**
|
|
9
|
+
* Attaches the shared HMR manager to every integration exactly once per app config.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* Runtime plugin setup must not call `integration.setHmrManager()` directly. Adapters invoke
|
|
13
|
+
* this after the manager is enabled so late plugin init cannot double-bind integrations.
|
|
14
|
+
*/
|
|
15
|
+
export declare function attachHmrToIntegrations(appConfig: EcoPagesAppConfig, hmrManager: IHmrManager): void;
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated Use {@link attachHmrToIntegrations} instead.
|
|
18
|
+
*/
|
|
19
|
+
export declare function wireIntegrationHmrManagers(appConfig: EcoPagesAppConfig, hmrManager: IHmrManager): void;
|
|
20
|
+
/**
|
|
21
|
+
* Injects the dev HMR runtime into adapter-level HTML responses when watch mode is active.
|
|
22
|
+
*/
|
|
23
|
+
export declare function maybeInjectAdapterHmrHtmlResponse(response: Response, options: {
|
|
24
|
+
watch: boolean;
|
|
25
|
+
hmrManager?: Pick<IHmrManager, 'isEnabled'>;
|
|
26
|
+
hostOwnsDevClient: boolean;
|
|
27
|
+
}): Promise<Response>;
|
|
28
|
+
/**
|
|
29
|
+
* Releases shared dev resources in a consistent order across server adapters.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* Bun calls `buildRuntime()` during `initialize()` when watch is enabled; Node defers
|
|
33
|
+
* runtime creation to `completeInitialization()`. Transport-specific setup stays in
|
|
34
|
+
* each adapter — only shared teardown lives here.
|
|
35
|
+
*/
|
|
36
|
+
export declare function disposeDevResources(options: {
|
|
37
|
+
projectWatcher: ProjectWatcher | null | undefined;
|
|
38
|
+
appConfig: EcoPagesAppConfig;
|
|
39
|
+
hmrManager: IHmrManager | null | undefined;
|
|
40
|
+
bridge: {
|
|
41
|
+
destroy(): void;
|
|
42
|
+
} | null | undefined;
|
|
43
|
+
previewHost: {
|
|
44
|
+
stop(): Promise<void>;
|
|
45
|
+
};
|
|
46
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileSystem } from "@ecopages/file-system";
|
|
3
|
+
import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
|
|
4
|
+
import { disposeAppBuildRuntime } from "../../build/build-runtime.js";
|
|
5
|
+
import { copyRuntimePublicDirIfChanged } from "./copy-runtime-public-dir.js";
|
|
6
|
+
import { clearAppDevClientBridge } from "../../dev/client-bridge-registry.js";
|
|
7
|
+
import { clearAppHmrManager } from "../../dev/hmr-manager-registry.js";
|
|
8
|
+
import { injectHmrRuntimeIntoHtmlResponse, isHtmlResponse, shouldInjectHmrHtmlResponse } from "./hmr-html-response.js";
|
|
9
|
+
function prepareRuntimePublicDir(appConfig) {
|
|
10
|
+
const srcPublicDir = path.join(appConfig.rootDir, appConfig.srcDir, appConfig.publicDir);
|
|
11
|
+
if (fileSystem.exists(srcPublicDir)) {
|
|
12
|
+
copyRuntimePublicDirIfChanged(srcPublicDir, path.join(appConfig.rootDir, appConfig.distDir));
|
|
13
|
+
}
|
|
14
|
+
fileSystem.ensureDir(path.join(appConfig.absolutePaths.distDir, RESOLVED_ASSETS_DIR));
|
|
15
|
+
}
|
|
16
|
+
const attachedHmrApps = /* @__PURE__ */ new WeakSet();
|
|
17
|
+
function attachHmrToIntegrations(appConfig, hmrManager) {
|
|
18
|
+
if (attachedHmrApps.has(appConfig)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
attachedHmrApps.add(appConfig);
|
|
22
|
+
for (const integration of appConfig.integrations) {
|
|
23
|
+
integration.setHmrManager(hmrManager);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function wireIntegrationHmrManagers(appConfig, hmrManager) {
|
|
27
|
+
attachHmrToIntegrations(appConfig, hmrManager);
|
|
28
|
+
}
|
|
29
|
+
async function maybeInjectAdapterHmrHtmlResponse(response, options) {
|
|
30
|
+
if (shouldInjectHmrHtmlResponse(options.watch, options.hmrManager, options.hostOwnsDevClient) && isHtmlResponse(response)) {
|
|
31
|
+
return injectHmrRuntimeIntoHtmlResponse(response);
|
|
32
|
+
}
|
|
33
|
+
return response;
|
|
34
|
+
}
|
|
35
|
+
async function disposeDevResources(options) {
|
|
36
|
+
await options.projectWatcher?.close();
|
|
37
|
+
await disposeAppBuildRuntime(options.appConfig);
|
|
38
|
+
options.hmrManager?.stop();
|
|
39
|
+
options.bridge?.destroy();
|
|
40
|
+
clearAppDevClientBridge(options.appConfig);
|
|
41
|
+
clearAppHmrManager(options.appConfig);
|
|
42
|
+
await options.previewHost.stop();
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
attachHmrToIntegrations,
|
|
46
|
+
disposeDevResources,
|
|
47
|
+
maybeInjectAdapterHmrHtmlResponse,
|
|
48
|
+
prepareRuntimePublicDir,
|
|
49
|
+
wireIntegrationHmrManagers
|
|
50
|
+
};
|
|
@@ -21,7 +21,8 @@ export declare abstract class SharedServerAdapter<TOptions extends ServerAdapter
|
|
|
21
21
|
protected routeHandler: ServerRouteHandler;
|
|
22
22
|
protected staticSiteGenerator: StaticSiteGenerator;
|
|
23
23
|
protected staticBuilder: ServerStaticBuilder;
|
|
24
|
-
protected
|
|
24
|
+
protected schemaValidator: SchemaValidationService;
|
|
25
|
+
protected hostOwnsDevClient: boolean;
|
|
25
26
|
protected initializeSharedRouteHandling(options: {
|
|
26
27
|
staticRoutes: StaticRoute[];
|
|
27
28
|
hmrManager?: any;
|
|
@@ -27,6 +27,7 @@ class SharedServerAdapter extends AbstractServerAdapter {
|
|
|
27
27
|
staticSiteGenerator;
|
|
28
28
|
staticBuilder;
|
|
29
29
|
schemaValidator = new SchemaValidationService();
|
|
30
|
+
hostOwnsDevClient = false;
|
|
30
31
|
async initializeSharedRouteHandling(options) {
|
|
31
32
|
await this.initSharedRouter();
|
|
32
33
|
this.configureSharedResponseHandlers(options.staticRoutes, options.hmrManager);
|
|
@@ -76,7 +77,7 @@ class SharedServerAdapter extends AbstractServerAdapter {
|
|
|
76
77
|
const module = await serverModuleTranspiler.importModule({
|
|
77
78
|
filePath,
|
|
78
79
|
outdir: path.join(resolveInternalExecutionDir(this.appConfig), ".server-route-modules"),
|
|
79
|
-
externalPackages:
|
|
80
|
+
externalPackages: true,
|
|
80
81
|
transpileErrorMessage: (details) => `Error transpiling route module: ${details}`,
|
|
81
82
|
noOutputMessage: (targetFilePath) => `No transpiled output generated for route module: ${targetFilePath}`
|
|
82
83
|
});
|
|
@@ -115,7 +116,8 @@ class SharedServerAdapter extends AbstractServerAdapter {
|
|
|
115
116
|
fileSystemResponseMatcher: this.fileSystemResponseMatcher,
|
|
116
117
|
explicitStaticRouteMatcher,
|
|
117
118
|
watch: !!this.options?.watch,
|
|
118
|
-
hmrManager
|
|
119
|
+
hmrManager,
|
|
120
|
+
hostOwnsDevClient: this.hostOwnsDevClient
|
|
119
121
|
});
|
|
120
122
|
}
|
|
121
123
|
createSharedResponseHandlerDependencies(staticRoutes) {
|
|
@@ -164,8 +166,7 @@ class SharedServerAdapter extends AbstractServerAdapter {
|
|
|
164
166
|
importServerModule: async (filePath) => await serverModuleTranspiler.importModule({
|
|
165
167
|
filePath,
|
|
166
168
|
outdir: path.join(resolveInternalExecutionDir(this.appConfig), ".server-modules"),
|
|
167
|
-
externalPackages: true
|
|
168
|
-
bypassCache: this.options?.watch === true
|
|
169
|
+
externalPackages: true
|
|
169
170
|
})
|
|
170
171
|
});
|
|
171
172
|
}
|
|
@@ -380,7 +381,10 @@ class SharedServerAdapter extends AbstractServerAdapter {
|
|
|
380
381
|
const runtimePath = context.hmrManager.getRuntimePath();
|
|
381
382
|
if (fileSystem.exists(runtimePath)) {
|
|
382
383
|
return new Response(fileSystem.readFileAsBuffer(runtimePath), {
|
|
383
|
-
headers: {
|
|
384
|
+
headers: {
|
|
385
|
+
"Content-Type": "application/javascript",
|
|
386
|
+
"Cache-Control": "no-store, must-revalidate"
|
|
387
|
+
}
|
|
384
388
|
});
|
|
385
389
|
}
|
|
386
390
|
}
|
|
@@ -389,7 +393,10 @@ class SharedServerAdapter extends AbstractServerAdapter {
|
|
|
389
393
|
const assetPath = path.join(context.hmrManager.getDistDir(), relativePath);
|
|
390
394
|
if (fileSystem.exists(assetPath)) {
|
|
391
395
|
return new Response(fileSystem.readFileAsBuffer(assetPath), {
|
|
392
|
-
headers: {
|
|
396
|
+
headers: {
|
|
397
|
+
"Content-Type": "application/javascript",
|
|
398
|
+
"Cache-Control": "no-store, must-revalidate"
|
|
399
|
+
}
|
|
393
400
|
});
|
|
394
401
|
}
|
|
395
402
|
}
|
|
@@ -16,6 +16,8 @@ export interface ServerRouteHandlerParams {
|
|
|
16
16
|
watch?: boolean;
|
|
17
17
|
/** HMR manager for broadcasting hot module reload events in development. */
|
|
18
18
|
hmrManager?: IHmrManager;
|
|
19
|
+
/** When true, the host dev server owns browser dev-client bootstrap. */
|
|
20
|
+
hostOwnsDevClient?: boolean;
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* Handles HTTP requests and routing for the server.
|
|
@@ -33,12 +35,13 @@ export declare class ServerRouteHandler {
|
|
|
33
35
|
private readonly explicitStaticRouteMatcher?;
|
|
34
36
|
private readonly watch;
|
|
35
37
|
private readonly hmrManager?;
|
|
38
|
+
private readonly hostOwnsDevClient;
|
|
36
39
|
/**
|
|
37
40
|
* Creates a new ServerRouteHandler instance.
|
|
38
41
|
*
|
|
39
42
|
* @param params - Configuration parameters
|
|
40
43
|
*/
|
|
41
|
-
constructor({ router, fileSystemResponseMatcher, explicitStaticRouteMatcher, watch, hmrManager, }: ServerRouteHandlerParams);
|
|
44
|
+
constructor({ router, fileSystemResponseMatcher, explicitStaticRouteMatcher, watch, hmrManager, hostOwnsDevClient, }: ServerRouteHandlerParams);
|
|
42
45
|
/**
|
|
43
46
|
* Determines if HMR script should be injected.
|
|
44
47
|
*
|
|
@@ -7,6 +7,7 @@ class ServerRouteHandler {
|
|
|
7
7
|
explicitStaticRouteMatcher;
|
|
8
8
|
watch;
|
|
9
9
|
hmrManager;
|
|
10
|
+
hostOwnsDevClient;
|
|
10
11
|
/**
|
|
11
12
|
* Creates a new ServerRouteHandler instance.
|
|
12
13
|
*
|
|
@@ -17,13 +18,15 @@ class ServerRouteHandler {
|
|
|
17
18
|
fileSystemResponseMatcher,
|
|
18
19
|
explicitStaticRouteMatcher,
|
|
19
20
|
watch = false,
|
|
20
|
-
hmrManager
|
|
21
|
+
hmrManager,
|
|
22
|
+
hostOwnsDevClient = false
|
|
21
23
|
}) {
|
|
22
24
|
this.router = router;
|
|
23
25
|
this.fileSystemResponseMatcher = fileSystemResponseMatcher;
|
|
24
26
|
this.explicitStaticRouteMatcher = explicitStaticRouteMatcher;
|
|
25
27
|
this.watch = watch;
|
|
26
28
|
this.hmrManager = hmrManager;
|
|
29
|
+
this.hostOwnsDevClient = hostOwnsDevClient;
|
|
27
30
|
}
|
|
28
31
|
/**
|
|
29
32
|
* Determines if HMR script should be injected.
|
|
@@ -31,7 +34,7 @@ class ServerRouteHandler {
|
|
|
31
34
|
* @returns true if in watch mode and HMR manager is enabled
|
|
32
35
|
*/
|
|
33
36
|
shouldInjectHmrScript() {
|
|
34
|
-
return shouldInjectHmrHtmlResponse(this.watch, this.hmrManager);
|
|
37
|
+
return shouldInjectHmrHtmlResponse(this.watch, this.hmrManager, this.hostOwnsDevClient);
|
|
35
38
|
}
|
|
36
39
|
/**
|
|
37
40
|
* Checks if a response contains HTML content.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { EcoPagesAppConfig } from '../../types/internal-types.js';
|
|
2
|
-
import type {
|
|
1
|
+
import type { EcoPagesAppConfig, IHmrManager } from '../../types/internal-types.js';
|
|
2
|
+
import type { EcoBuildPlugin } from '../../build/build-types.js';
|
|
3
|
+
import type { StaticRoute } from '../../types/public-types.js';
|
|
3
4
|
import type { RouteRegistry } from '../../router/server/route-registry.js';
|
|
4
5
|
import type { StaticSiteGenerator } from '../../static-site-generator/static-site-generator.js';
|
|
5
6
|
import type { StaticGenerationRendererResolver } from '../../route-renderer/route-renderer.js';
|
|
6
7
|
export interface StaticBuildOptions {
|
|
7
|
-
preview?: boolean;
|
|
8
8
|
baseUrl?: string;
|
|
9
|
+
force?: boolean;
|
|
9
10
|
}
|
|
10
11
|
export interface ServeOptions {
|
|
11
12
|
hostname?: string;
|
|
@@ -15,10 +16,17 @@ export interface ServerStaticBuilderParams {
|
|
|
15
16
|
appConfig: EcoPagesAppConfig;
|
|
16
17
|
staticSiteGenerator: StaticSiteGenerator;
|
|
17
18
|
serveOptions: ServeOptions;
|
|
18
|
-
|
|
19
|
+
runtimeOrigin: string;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the app requires a server entry bundle for production use.
|
|
22
|
+
* When `true`, the build step bundles the server entry file for `ecopages start`.
|
|
23
|
+
* Defaults to `false` (static-only build, no server needed).
|
|
24
|
+
*/
|
|
25
|
+
needsServerBundle?: boolean;
|
|
19
26
|
logger?: ServerStaticBuilderLogger;
|
|
20
|
-
previewServerFactory?: ServerStaticPreviewServerFactory;
|
|
21
27
|
entryFile?: string;
|
|
28
|
+
hmrManager?: IHmrManager;
|
|
29
|
+
onRuntimePlugin?: (plugin: EcoBuildPlugin) => void;
|
|
22
30
|
}
|
|
23
31
|
/**
|
|
24
32
|
* Minimal logger dependency used by the static builder.
|
|
@@ -29,50 +37,34 @@ export interface ServerStaticBuilderLogger {
|
|
|
29
37
|
error(message: string): unknown;
|
|
30
38
|
}
|
|
31
39
|
/**
|
|
32
|
-
*
|
|
33
|
-
*/
|
|
34
|
-
export interface ServerStaticPreviewServerFactory {
|
|
35
|
-
createServer(args: {
|
|
36
|
-
appConfig: EcoPagesAppConfig;
|
|
37
|
-
options: {
|
|
38
|
-
port: number;
|
|
39
|
-
};
|
|
40
|
-
}): {
|
|
41
|
-
server?: {
|
|
42
|
-
port?: number;
|
|
43
|
-
} | null;
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Handles static site generation and previews.
|
|
40
|
+
* Handles static site generation.
|
|
48
41
|
*/
|
|
49
42
|
export declare class ServerStaticBuilder {
|
|
50
43
|
private readonly appConfig;
|
|
51
44
|
private readonly staticSiteGenerator;
|
|
52
45
|
private readonly serveOptions;
|
|
53
|
-
private readonly
|
|
46
|
+
private readonly runtimeOrigin;
|
|
47
|
+
private readonly needsServerBundle;
|
|
54
48
|
private readonly logger;
|
|
55
|
-
private readonly previewServerFactory;
|
|
56
49
|
private readonly entryFile;
|
|
57
|
-
|
|
58
|
-
private
|
|
50
|
+
private readonly hmrManager?;
|
|
51
|
+
private readonly onRuntimePlugin?;
|
|
52
|
+
constructor({ appConfig, staticSiteGenerator, serveOptions, runtimeOrigin, needsServerBundle, logger, entryFile, hmrManager, onRuntimePlugin, }: ServerStaticBuilderParams);
|
|
59
53
|
private prepareExportDirectory;
|
|
60
54
|
private refreshRuntimeAssets;
|
|
61
55
|
/**
|
|
62
56
|
* Bundles the server entry file for production use.
|
|
63
57
|
*
|
|
64
58
|
* @remarks
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* `ecopages start` in production.
|
|
59
|
+
* Only invoked when the app requires a runtime server (API handlers,
|
|
60
|
+
* websocket handlers, etc.). Static-only apps skip this step entirely.
|
|
61
|
+
* Incremental builds may skip Rolldown when the `.eco/.server-entry`
|
|
62
|
+
* cache is still valid.
|
|
70
63
|
*
|
|
71
64
|
* Package imports remain external so native addons and runtime-owned
|
|
72
65
|
* dependencies continue to load through the app's installed
|
|
73
66
|
* `node_modules` tree. Only the app entry graph is bundled.
|
|
74
67
|
*
|
|
75
|
-
* Skips silently when no API endpoints are registered (static-only site).
|
|
76
68
|
* Throws if the build adapter is unavailable, is owned by a host
|
|
77
69
|
* runtime, or bundling fails.
|
|
78
70
|
*
|
|
@@ -81,7 +73,6 @@ export declare class ServerStaticBuilder {
|
|
|
81
73
|
private bundleServerEntry;
|
|
82
74
|
/**
|
|
83
75
|
* Generates a static build of the site for deployment.
|
|
84
|
-
* @param options.preview - If true, starts a preview server after build
|
|
85
76
|
* @param dependencies.router - The initialized router
|
|
86
77
|
* @param dependencies.routeRendererFactory - The route renderer factory
|
|
87
78
|
* @param dependencies.staticRoutes - Explicit static routes registered via app.static()
|