@ecopages/core 0.2.0-beta.26 → 0.2.0-beta.27
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 +58 -50
- package/src/adapters/bun/server-adapter.js +2 -2
- package/src/adapters/node/server-adapter.js +2 -2
- package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +10 -0
- package/src/adapters/shared/hmr-entrypoint-registrar.js +34 -10
- package/src/adapters/shared/runtime-server-lifecycle.js +1 -1
- package/src/adapters/shared/server-static-builder.d.ts +2 -1
- package/src/adapters/shared/server-static-builder.js +16 -14
- package/src/adapters/shared/shared-hmr-manager.d.ts +11 -4
- package/src/adapters/shared/shared-hmr-manager.js +22 -3
- package/src/build/README.md +92 -46
- package/src/build/app-build-manifest-runtime.d.ts +28 -2
- package/src/build/app-build-manifest-runtime.js +26 -10
- package/src/build/{browser-runtime-plugin.d.ts → browser/browser-runtime-plugin.d.ts} +1 -1
- package/src/build/{browser-runtime-plugin.js → browser/browser-runtime-plugin.js} +1 -1
- package/src/build/{jsx-ownership-plugins.d.ts → browser/jsx-ownership-plugins.d.ts} +2 -2
- package/src/build/{jsx-ownership-plugins.js → browser/jsx-ownership-plugins.js} +2 -2
- package/src/build/build-adapter.d.ts +18 -21
- package/src/build/build-adapter.js +8 -43
- package/src/build/{build-input-fingerprint.d.ts → cache/build-input-fingerprint.d.ts} +3 -3
- package/src/build/cache/cache-constants.d.ts +4 -0
- package/src/build/cache/cache-constants.js +6 -0
- package/src/build/cache/cache-keys.d.ts +22 -0
- package/src/build/cache/cache-keys.js +63 -0
- package/src/build/{dev-browser-script-cache.d.ts → cache/dev-browser-script-cache.d.ts} +2 -2
- package/src/build/{dev-browser-script-cache.js → cache/dev-browser-script-cache.js} +4 -4
- package/src/build/{pages-unified-graph-build.d.ts → cache/pages-unified-graph-build.d.ts} +1 -1
- package/src/build/{pages-unified-graph-build.js → cache/pages-unified-graph-build.js} +18 -26
- package/src/build/{production-build-cache.d.ts → cache/production-build-cache.d.ts} +1 -1
- package/src/build/{production-build-cache.js → cache/production-build-cache.js} +2 -2
- package/src/build/{server-entry-build-cache.d.ts → cache/server-entry-build-cache.d.ts} +3 -4
- package/src/build/{server-entry-build-cache.js → cache/server-entry-build-cache.js} +16 -12
- package/src/build/{build-contracts.d.ts → contracts/build-contracts.d.ts} +1 -2
- package/src/build/contracts/build-manifest.d.ts +90 -0
- package/src/build/{build-manifest.js → contracts/build-manifest.js} +2 -2
- package/src/build/{rolldown-adapter-helpers.d.ts → rolldown/rolldown-adapter-helpers.d.ts} +20 -3
- package/src/build/{rolldown-adapter-helpers.js → rolldown/rolldown-adapter-helpers.js} +26 -6
- package/src/build/{rolldown-build-adapter.d.ts → rolldown/rolldown-build-adapter.d.ts} +1 -1
- package/src/build/{rolldown-plugin-bridge.d.ts → rolldown/rolldown-plugin-bridge.d.ts} +2 -2
- package/src/build/{rolldown-plugin-bridge.js → rolldown/rolldown-plugin-bridge.js} +1 -1
- package/src/build/{rolldown-source-transform-pass.d.ts → rolldown/rolldown-source-transform-pass.d.ts} +1 -1
- package/src/build/{rolldown-source-transform-pass.js → rolldown/rolldown-source-transform-pass.js} +4 -1
- package/src/build/{runtime-build-output-normalizer.js → rolldown/runtime-build-output-normalizer.js} +2 -2
- package/src/build/{build-profile-options.d.ts → runtime/build-profile-options.d.ts} +2 -2
- package/src/build/runtime/build-request-identity.d.ts +17 -0
- package/src/build/runtime/build-request-identity.js +54 -0
- package/src/build/runtime/build-request-policy.d.ts +59 -0
- package/src/build/runtime/build-request-policy.js +46 -0
- package/src/build/{build-runtime.d.ts → runtime/build-runtime.d.ts} +8 -4
- package/src/build/{build-runtime.js → runtime/build-runtime.js} +11 -11
- package/src/build/{deduping-build-executor.d.ts → runtime/deduping-build-executor.d.ts} +2 -9
- package/src/build/runtime/deduping-build-executor.js +34 -0
- package/src/build/{parallel-build-executor.d.ts → runtime/parallel-build-executor.d.ts} +1 -1
- package/src/build/{serialized-build-executor.d.ts → runtime/serialized-build-executor.d.ts} +1 -1
- package/src/config/config-builder.d.ts +1 -1
- package/src/diagnostics/startup-trace.d.ts +49 -2
- package/src/diagnostics/startup-trace.js +140 -8
- package/src/hmr/client/hmr-runtime.js +1 -1
- package/src/hmr/hmr-file-change-prep.d.ts +10 -0
- package/src/hmr/hmr-file-change-prep.js +17 -0
- package/src/plugins/alias-resolver-plugin.d.ts +1 -1
- package/src/plugins/eco-component-meta-plugin.d.ts +1 -1
- package/src/plugins/foreign-jsx-override-plugin.d.ts +1 -1
- package/src/plugins/integration-plugin.d.ts +16 -5
- package/src/plugins/integration-plugin.js +11 -1
- package/src/plugins/processor.d.ts +28 -8
- package/src/plugins/source-transform.d.ts +1 -1
- package/src/route-renderer/GRAPH.md +13 -19
- package/src/route-renderer/README.md +1 -1
- package/src/route-renderer/orchestration/component-render-context.d.ts +4 -4
- package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +6 -2
- package/src/route-renderer/orchestration/integration-renderer.d.ts +11 -52
- package/src/route-renderer/orchestration/integration-renderer.js +38 -91
- package/src/route-renderer/orchestration/integration-route-render-adapter.d.ts +1 -8
- package/src/route-renderer/orchestration/integration-route-render-adapter.js +0 -2
- package/src/route-renderer/orchestration/page-browser-graph-session.d.ts +106 -0
- package/src/route-renderer/orchestration/page-browser-graph-session.js +436 -0
- package/src/route-renderer/orchestration/page-browser-graph.service.d.ts +9 -3
- package/src/route-renderer/orchestration/page-browser-graph.service.js +89 -40
- package/src/route-renderer/orchestration/render-output.utils.d.ts +14 -0
- package/src/route-renderer/orchestration/render-output.utils.js +30 -0
- package/src/route-renderer/orchestration/route-html-finalization.service.d.ts +0 -1
- package/src/route-renderer/orchestration/route-html-finalization.service.js +4 -9
- package/src/route-renderer/orchestration/route-prepared-options.builder.d.ts +1 -2
- package/src/route-renderer/orchestration/route-prepared-options.builder.js +1 -10
- package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +3 -12
- package/src/route-renderer/orchestration/route-render-orchestrator.js +4 -14
- package/src/services/assets/asset-processing-service/asset-processing.service.js +1 -1
- package/src/services/assets/asset-processing-service/assets.types.d.ts +1 -1
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -1
- package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +0 -2
- package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +2 -15
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +1 -1
- package/src/services/assets/browser-bundle.service.d.ts +27 -31
- package/src/services/assets/browser-bundle.service.js +12 -23
- package/src/services/module-loading/app-server-module-transpiler.service.d.ts +8 -0
- package/src/services/module-loading/app-server-module-transpiler.service.js +1 -7
- package/src/services/module-loading/page-module-import.service.d.ts +1 -1
- package/src/services/module-loading/page-module-import.service.js +40 -28
- package/src/services/module-loading/route-module-build-cache.store.js +1 -1
- package/src/services/module-loading/route-module-build-manifest.d.ts +2 -9
- package/src/services/module-loading/route-module-build-manifest.js +12 -43
- package/src/services/module-loading/server-module-transpiler.service.d.ts +1 -1
- package/src/static-site-generator/README.md +1 -1
- package/src/static-site-generator/production-page-browser-graph-prebuild.d.ts +28 -0
- package/src/static-site-generator/production-page-browser-graph-prebuild.js +22 -0
- package/src/static-site-generator/static-build-invalidation.d.ts +2 -2
- package/src/static-site-generator/static-build-invalidation.js +3 -3
- package/src/static-site-generator/static-site-generator.js +23 -1
- package/src/types/internal-types.d.ts +10 -4
- package/src/types/public-types.d.ts +58 -9
- package/src/watchers/project-watcher.js +12 -2
- package/src/build/build-manifest.d.ts +0 -33
- package/src/build/deduping-build-executor.js +0 -56
- package/src/build/runtime-build-executor.d.ts +0 -14
- package/src/build/runtime-build-executor.js +0 -16
- /package/src/build/{browser-runtime-manifest.d.ts → browser/browser-runtime-manifest.d.ts} +0 -0
- /package/src/build/{browser-runtime-manifest.js → browser/browser-runtime-manifest.js} +0 -0
- /package/src/build/{browser-runtime-plugin-helpers.d.ts → browser/browser-runtime-plugin-helpers.d.ts} +0 -0
- /package/src/build/{browser-runtime-plugin-helpers.js → browser/browser-runtime-plugin-helpers.js} +0 -0
- /package/src/build/{lit-static-render-worker-context.d.ts → browser/lit-static-render-worker-context.d.ts} +0 -0
- /package/src/build/{lit-static-render-worker-context.js → browser/lit-static-render-worker-context.js} +0 -0
- /package/src/build/{build-input-fingerprint.js → cache/build-input-fingerprint.js} +0 -0
- /package/src/build/{build-contracts.js → contracts/build-contracts.js} +0 -0
- /package/src/build/{build-types.d.ts → contracts/build-types.d.ts} +0 -0
- /package/src/build/{build-types.js → contracts/build-types.js} +0 -0
- /package/src/build/{rolldown-build-adapter.js → rolldown/rolldown-build-adapter.js} +0 -0
- /package/src/build/{rolldown-build-invocation-metrics.d.ts → rolldown/rolldown-build-invocation-metrics.d.ts} +0 -0
- /package/src/build/{rolldown-build-invocation-metrics.js → rolldown/rolldown-build-invocation-metrics.js} +0 -0
- /package/src/build/{runtime-build-output-normalizer.d.ts → rolldown/runtime-build-output-normalizer.d.ts} +0 -0
- /package/src/build/{server-side-css-shim-plugin.d.ts → rolldown/server-side-css-shim-plugin.d.ts} +0 -0
- /package/src/build/{server-side-css-shim-plugin.js → rolldown/server-side-css-shim-plugin.js} +0 -0
- /package/src/build/{build-profile-options.js → runtime/build-profile-options.js} +0 -0
- /package/src/build/{parallel-build-executor.js → runtime/parallel-build-executor.js} +0 -0
- /package/src/build/{serialized-build-executor.js → runtime/serialized-build-executor.js} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { EcoBuildPlugin } from '../build/build-types.js';
|
|
1
|
+
import type { EcoBuildPlugin } from '../build/contracts/build-types.js';
|
|
2
2
|
import type { EcoPagesAppConfig, IClientBridge } from '../types/internal-types.js';
|
|
3
3
|
import { GENERATED_BASE_PATHS } from '../config/constants.js';
|
|
4
4
|
import type { RuntimeCapabilityDeclaration } from './runtime-capability.js';
|
|
5
5
|
export type { RuntimeCapabilityDeclaration, RuntimeCapabilityTag } from './runtime-capability.js';
|
|
6
|
-
export type { EcoBuildLoader, EcoBuildOnLoadArgs, EcoBuildOnLoadResult, EcoBuildOnResolveArgs, EcoBuildOnResolveResult, EcoBuildPlugin, EcoBuildPluginBuilder, } from '../build/build-types.js';
|
|
6
|
+
export type { EcoBuildLoader, EcoBuildOnLoadArgs, EcoBuildOnLoadResult, EcoBuildOnResolveArgs, EcoBuildOnResolveResult, EcoBuildPlugin, EcoBuildPluginBuilder, } from '../build/contracts/build-types.js';
|
|
7
7
|
export declare const PROCESSOR_ERRORS: {
|
|
8
8
|
readonly CACHE_DIRECTORY_NOT_SET: "Cache directory not set in context";
|
|
9
9
|
};
|
|
@@ -57,10 +57,17 @@ export interface ProcessorContext {
|
|
|
57
57
|
cache?: string;
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
60
|
+
* Base class for content and asset processors that contribute build plugins.
|
|
61
|
+
*
|
|
62
|
+
* @remarks
|
|
63
|
+
* Processors declare plugins through two getters that map to
|
|
64
|
+
* {@link AppBuildManifest} buckets (names differ from integrations):
|
|
65
|
+
*
|
|
66
|
+
* - `plugins` → `runtimePlugins` (server **and** browser builds)
|
|
67
|
+
* - `buildPlugins` → `browserBundlePlugins` (browser bundles only)
|
|
68
|
+
*
|
|
69
|
+
* Virtual modules that must resolve during route-module transpile belong in
|
|
70
|
+
* `plugins`. Browser-only bundler hooks belong in `buildPlugins`.
|
|
64
71
|
*/
|
|
65
72
|
export declare abstract class Processor<TOptions = Record<string, unknown>> {
|
|
66
73
|
readonly name: string;
|
|
@@ -69,9 +76,22 @@ export declare abstract class Processor<TOptions = Record<string, unknown>> {
|
|
|
69
76
|
protected watchConfig?: ProcessorWatchConfig;
|
|
70
77
|
protected capabilities: ProcessorAssetCapability[];
|
|
71
78
|
readonly runtimeCapability?: RuntimeCapabilityDeclaration;
|
|
72
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* Browser-bundle-only plugins.
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* Maps to {@link AppBuildManifest.browserBundlePlugins}. Integrations name the
|
|
84
|
+
* same bucket `browserBuildPlugins`.
|
|
85
|
+
*/
|
|
73
86
|
abstract buildPlugins?: EcoBuildPlugin[];
|
|
74
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* Shared build plugins for server-oriented and browser-oriented work.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* Maps to {@link AppBuildManifest.runtimePlugins}. Despite the name, these are
|
|
92
|
+
* bundler plugins—not dev-server file processors. Runtime-only setup stays in
|
|
93
|
+
* {@link setup}.
|
|
94
|
+
*/
|
|
75
95
|
abstract plugins?: EcoBuildPlugin[];
|
|
76
96
|
constructor(config: ProcessorConfig<TOptions>);
|
|
77
97
|
setContext(appConfig: EcoPagesAppConfig): void;
|
|
@@ -42,23 +42,17 @@ flowchart TD
|
|
|
42
42
|
C --> D[ownershipValidationService.validate]
|
|
43
43
|
D --> E[resolvePageData]
|
|
44
44
|
E --> F[ownershipValidationService.validate + throwIfOwnershipInvalid]
|
|
45
|
-
F --> G[resolveDependencies]
|
|
46
|
-
G --> H[
|
|
47
|
-
H --> I
|
|
48
|
-
I
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
M -->
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
P --> Q[inspect unresolved marker artifacts]
|
|
57
|
-
Q --> R{unresolved eco-marker remains?}
|
|
58
|
-
R -- Yes --> S[throw unresolved artifact error]
|
|
59
|
-
R -- No --> T[stamp root or document attributes when needed]
|
|
60
|
-
T --> U[htmlTransformer transform]
|
|
61
|
-
U --> V[final body and cache strategy]
|
|
45
|
+
F --> G[resolveDependencies + buildPageBrowserGraph]
|
|
46
|
+
G --> H[collect injector and eager SSR lazy assets]
|
|
47
|
+
H --> I[build pagePackage and prepared render options]
|
|
48
|
+
I --> J[IntegrationRenderer.render via document shell]
|
|
49
|
+
J --> K[capture rendered body as html]
|
|
50
|
+
K --> L[inspect unresolved marker artifacts]
|
|
51
|
+
L --> M{unresolved eco-marker remains?}
|
|
52
|
+
M -- Yes --> N[throw unresolved artifact error]
|
|
53
|
+
M -- No --> O[stamp document attributes when needed]
|
|
54
|
+
O --> P[htmlTransformer transform]
|
|
55
|
+
P --> Q[final body and cache strategy]
|
|
62
56
|
```
|
|
63
57
|
|
|
64
58
|
## 3) Mixed-Integration Render Model
|
|
@@ -124,7 +118,7 @@ The most useful reading order is:
|
|
|
124
118
|
2. `orchestration/route-render-orchestrator.ts`
|
|
125
119
|
3. `orchestration/integration-renderer.ts`
|
|
126
120
|
4. `orchestration/ownership-validation.service.ts`
|
|
127
|
-
5. `orchestration/
|
|
121
|
+
5. `orchestration/component-graph.ts`
|
|
128
122
|
6. `orchestration/component-render-context.ts`
|
|
129
123
|
7. `orchestration/foreign-subtree-execution.service.ts`
|
|
130
124
|
8. `page-loading/page-module-loader.ts`
|
|
@@ -137,7 +131,7 @@ The most useful reading order is:
|
|
|
137
131
|
- `packages/core/src/route-renderer/orchestration/route-render-orchestrator.ts`
|
|
138
132
|
- `packages/core/src/route-renderer/orchestration/integration-renderer.ts`
|
|
139
133
|
- `packages/core/src/route-renderer/orchestration/ownership-validation.service.ts`
|
|
140
|
-
- `packages/core/src/route-renderer/orchestration/
|
|
134
|
+
- `packages/core/src/route-renderer/orchestration/component-graph.ts`
|
|
141
135
|
- `packages/core/src/route-renderer/orchestration/component-render-context.ts`
|
|
142
136
|
- `packages/core/src/route-renderer/orchestration/foreign-subtree-execution.service.ts`
|
|
143
137
|
- `packages/core/src/route-renderer/page-loading/page-module-loader.ts`
|
|
@@ -72,7 +72,7 @@ The route-render contract is:
|
|
|
72
72
|
3. `RouteRenderOrchestrator.prepareRenderOptions()` loads the page module, validates ownership (fail-fast), resolves page data, resolves dependencies, and builds the page browser graph.
|
|
73
73
|
4. The integration renderer performs page, layout, and document-shell rendering. When it encounters a foreign child, it delegates that child back to the owning renderer.
|
|
74
74
|
5. If a renderer needs queued handoff, it emits internal foreign-subtree tokens and resolves them before returning final HTML.
|
|
75
|
-
6. `RouteRenderOrchestrator.executePrepared()` captures the final body, rejects unresolved `<eco-marker>` artifacts, stamps
|
|
75
|
+
6. `RouteRenderOrchestrator.executePrepared()` captures the final body, rejects unresolved `<eco-marker>` artifacts, stamps document attributes when needed, and runs the HTML transformer.
|
|
76
76
|
|
|
77
77
|
Important:
|
|
78
78
|
|
|
@@ -2,16 +2,16 @@ import type { EcoComponent } from '../../types/public-types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Result returned by a renderer-owned foreign-child runtime.
|
|
4
4
|
*
|
|
5
|
-
* `inline` keeps rendering inside the current integration. `resolved`
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* `inline` keeps rendering inside the current integration. `resolved.value` is
|
|
6
|
+
* the queue transport token string allocated by `createQueuedRuntime`; callers
|
|
7
|
+
* must not treat arbitrary objects as resolved output.
|
|
8
8
|
*/
|
|
9
9
|
export type ForeignChildInterceptionResult = {
|
|
10
10
|
kind: 'inline';
|
|
11
11
|
props?: Record<string, unknown>;
|
|
12
12
|
} | {
|
|
13
13
|
kind: 'resolved';
|
|
14
|
-
value:
|
|
14
|
+
value: string;
|
|
15
15
|
} | undefined;
|
|
16
16
|
/**
|
|
17
17
|
* Foreign-child metadata passed into the active renderer-owned runtime.
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
getComponentRenderContext,
|
|
3
3
|
runWithComponentRenderContext
|
|
4
4
|
} from "./component-render-context.js";
|
|
5
|
-
import { isMarkupNodeLike } from "./render-output.utils.js";
|
|
5
|
+
import { assertForeignChildrenNotOpaque, isMarkupNodeLike } from "./render-output.utils.js";
|
|
6
6
|
function toForeignSubtreeRenderPayload(result) {
|
|
7
7
|
return {
|
|
8
8
|
html: result.html,
|
|
@@ -69,6 +69,9 @@ class ForeignSubtreeExecutionService {
|
|
|
69
69
|
props: { ...input.props }
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
+
if ("children" in input.props) {
|
|
73
|
+
assertForeignChildrenNotOpaque(input.props.children, "foreign-subtree queue");
|
|
74
|
+
}
|
|
72
75
|
runtimeContext.nextForeignSubtreeId += 1;
|
|
73
76
|
const foreignSubtreeId = runtimeContext.nextForeignSubtreeId;
|
|
74
77
|
const token = this.createForeignSubtreeToken(options.tokenPrefix, runtimeContext, foreignSubtreeId);
|
|
@@ -108,10 +111,11 @@ class ForeignSubtreeExecutionService {
|
|
|
108
111
|
return { assets: [], html: void 0 };
|
|
109
112
|
}
|
|
110
113
|
if (typeof children !== "string" && !isMarkupNodeLike(children)) {
|
|
114
|
+
assertForeignChildrenNotOpaque(children, options.queueLabel);
|
|
111
115
|
return { assets: [], children };
|
|
112
116
|
}
|
|
113
117
|
const html = await this.resolveQueuedTokens(
|
|
114
|
-
typeof children === "string" ? children : children.outerHTML ??
|
|
118
|
+
typeof children === "string" ? children : children.outerHTML ?? "",
|
|
115
119
|
queuedResolutionsByToken,
|
|
116
120
|
resolveToken
|
|
117
121
|
);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
import type { EcoPagesAppConfig, IHmrManager } from '../../types/internal-types.js';
|
|
7
|
-
import type { ComponentRenderInput, ComponentRenderResult, EcoComponent,
|
|
7
|
+
import type { ComponentRenderInput, ComponentRenderResult, EcoComponent, EcoPageFile, EcoPagesElement, BaseIntegrationContext, HtmlTemplateProps, IntegrationRendererRenderOptions, PageBrowserGraphContribution, PageBrowserGraphContributionContext, PageBrowserGraphResult, PageMetadataProps, PagePackageResult, RouteRendererBody, RouteRendererOptions, RouteRenderResult } from '../../types/public-types.js';
|
|
8
8
|
import { type AssetProcessingService, type ProcessedAsset } from '../../services/assets/asset-processing-service/index.js';
|
|
9
9
|
import { HtmlTransformerService } from '../../services/html/html-transformer.service.js';
|
|
10
10
|
import type { HtmlDocumentContribution } from '../../services/html/html-transformer.service.js';
|
|
@@ -67,6 +67,14 @@ export declare abstract class IntegrationRenderer<C = EcoPagesElement> {
|
|
|
67
67
|
private renderExclusiveChain;
|
|
68
68
|
protected DOC_TYPE: string;
|
|
69
69
|
private runRenderExclusive;
|
|
70
|
+
/**
|
|
71
|
+
* Activates the owning integration runtime on first render or graph use.
|
|
72
|
+
*/
|
|
73
|
+
protected ensureIntegrationRuntimeActivated(): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Prebuilds the production Page Browser Graph for one route file.
|
|
76
|
+
*/
|
|
77
|
+
prebuildProductionPageBrowserGraph(routeFile: string): Promise<void>;
|
|
70
78
|
/**
|
|
71
79
|
* Loads one route module through the owning renderer's import path.
|
|
72
80
|
*
|
|
@@ -170,6 +178,7 @@ export declare abstract class IntegrationRenderer<C = EcoPagesElement> {
|
|
|
170
178
|
props: P;
|
|
171
179
|
ctx: RenderToResponseContext;
|
|
172
180
|
layout?: EcoComponent;
|
|
181
|
+
transformDocumentHtml?: (html: string) => string;
|
|
173
182
|
}): Promise<Response>;
|
|
174
183
|
/**
|
|
175
184
|
* Renders a route page through optional layout and document shells.
|
|
@@ -225,16 +234,6 @@ export declare abstract class IntegrationRenderer<C = EcoPagesElement> {
|
|
|
225
234
|
rendererModules?: unknown;
|
|
226
235
|
runtimeOrigin: string;
|
|
227
236
|
});
|
|
228
|
-
/**
|
|
229
|
-
* Returns the HTML path from the provided file path.
|
|
230
|
-
* It extracts the path relative to the pages directory and removes the 'index' part if present.
|
|
231
|
-
*
|
|
232
|
-
* @param file - The file path to extract the HTML path from.
|
|
233
|
-
* @returns The extracted HTML path.
|
|
234
|
-
*/
|
|
235
|
-
protected getHtmlPath({ file }: {
|
|
236
|
-
file: string;
|
|
237
|
-
}): string;
|
|
238
237
|
/**
|
|
239
238
|
* Returns the HTML template component.
|
|
240
239
|
* It imports the HTML template from the specified path in the app configuration.
|
|
@@ -262,27 +261,6 @@ export declare abstract class IntegrationRenderer<C = EcoPagesElement> {
|
|
|
262
261
|
* @returns The resolved dependency path.
|
|
263
262
|
*/
|
|
264
263
|
protected resolveDependencyPath(componentDir: string, pathUrl: string): string;
|
|
265
|
-
/**
|
|
266
|
-
* Extracts the dependencies from the provided component configuration.
|
|
267
|
-
* It resolves the paths for scripts and stylesheets based on the component directory.
|
|
268
|
-
*
|
|
269
|
-
* @param componentDir - The component directory path.
|
|
270
|
-
* @param scripts - The scripts to extract.
|
|
271
|
-
* @param stylesheets - The stylesheets to extract.
|
|
272
|
-
* @returns The extracted dependencies.
|
|
273
|
-
*/
|
|
274
|
-
protected extractDependencies({ componentDir, scripts, stylesheets, }: {
|
|
275
|
-
componentDir: string;
|
|
276
|
-
} & EcoComponentDependencies): EcoComponentDependencies;
|
|
277
|
-
/**
|
|
278
|
-
* Resolves lazy script paths to public asset URLs.
|
|
279
|
-
* Converts source paths to their final bundled output paths.
|
|
280
|
-
*
|
|
281
|
-
* @param componentDir - The component directory path.
|
|
282
|
-
* @param scripts - The lazy script paths to resolve.
|
|
283
|
-
* @returns Comma-separated string of resolved public script paths.
|
|
284
|
-
*/
|
|
285
|
-
protected resolveLazyScripts(componentDir: string, scripts: string[]): string;
|
|
286
264
|
/**
|
|
287
265
|
* Collects the dependencies for the provided components.
|
|
288
266
|
* Combines component-specific dependencies with global integration dependencies.
|
|
@@ -312,12 +290,6 @@ export declare abstract class IntegrationRenderer<C = EcoPagesElement> {
|
|
|
312
290
|
}): Promise<{
|
|
313
291
|
resolvedDependencies: ProcessedAsset[];
|
|
314
292
|
}>;
|
|
315
|
-
protected resolveRoutePageComponentRender(input: {
|
|
316
|
-
Page: EcoComponent;
|
|
317
|
-
Layout?: EcoComponent;
|
|
318
|
-
props: Record<string, unknown>;
|
|
319
|
-
routeOptions: RouteRendererOptions;
|
|
320
|
-
}): Promise<ComponentRenderResult | undefined>;
|
|
321
293
|
protected renderRouteBody(renderOptions: IntegrationRendererRenderOptions<C>): Promise<RouteRendererBody>;
|
|
322
294
|
protected transformRouteResponse(response: Response, htmlContributions?: HtmlDocumentContribution[], pagePackage?: PagePackageResult): Promise<RouteRendererBody>;
|
|
323
295
|
/**
|
|
@@ -328,19 +300,6 @@ export declare abstract class IntegrationRenderer<C = EcoPagesElement> {
|
|
|
328
300
|
* @returns The prepared render options.
|
|
329
301
|
*/
|
|
330
302
|
protected prepareRenderOptions(options: RouteRendererOptions, adapter?: RouteRenderOrchestratorAdapter<C>): Promise<IntegrationRendererRenderOptions<C>>;
|
|
331
|
-
/**
|
|
332
|
-
* Controls whether the page root should be rendered through `renderComponent()`
|
|
333
|
-
* during route option preparation in component-capable modes.
|
|
334
|
-
*
|
|
335
|
-
* Integrations that already own page-level hydration (for example router-driven
|
|
336
|
-
* React rendering) can override this and return `false` to avoid duplicate root
|
|
337
|
-
* mount assets and competing hydration entrypoints.
|
|
338
|
-
*/
|
|
339
|
-
protected shouldRenderPageComponent(_input: {
|
|
340
|
-
Page: EcoComponent;
|
|
341
|
-
Layout?: EcoComponent;
|
|
342
|
-
options: RouteRendererOptions;
|
|
343
|
-
}): boolean;
|
|
344
303
|
/**
|
|
345
304
|
* Executes the integration renderer with the provided options.
|
|
346
305
|
*
|
|
@@ -348,7 +307,7 @@ export declare abstract class IntegrationRenderer<C = EcoPagesElement> {
|
|
|
348
307
|
* 1. Build normalized render options (`prepareRenderOptions`).
|
|
349
308
|
* 2. Render the route body once.
|
|
350
309
|
* 3. Reject unresolved route-level eco-marker artifacts.
|
|
351
|
-
* 4. Optionally apply
|
|
310
|
+
* 4. Optionally apply document attributes for integration-owned document boundaries.
|
|
352
311
|
* 5. Run HTML transformer with final dependency set.
|
|
353
312
|
*
|
|
354
313
|
* Stream-safety note: the first render result is normalized to a string once,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { createIntegrationRouteRenderAdapter } from "./integration-route-render-adapter.js";
|
|
15
15
|
import { loadPageBrowserGraphContribution } from "./page-browser-graph-contribution.loader.js";
|
|
16
16
|
import { normalizeUnresolvedMarkerArtifactHtml, isMarkupNodeLike } from "./render-output.utils.js";
|
|
17
|
+
import { ensureIntegrationRuntimeReady } from "../../build/app-build-manifest-runtime.js";
|
|
17
18
|
import {
|
|
18
19
|
ForeignSubtreeExecutionService
|
|
19
20
|
} from "./foreign-subtree-execution.service.js";
|
|
@@ -45,13 +46,33 @@ class IntegrationRenderer {
|
|
|
45
46
|
renderExclusiveChain = Promise.resolve();
|
|
46
47
|
DOC_TYPE = "<!DOCTYPE html>";
|
|
47
48
|
runRenderExclusive(operation) {
|
|
48
|
-
const run = this.renderExclusiveChain.then(
|
|
49
|
+
const run = this.renderExclusiveChain.then(async () => {
|
|
50
|
+
await this.ensureIntegrationRuntimeActivated();
|
|
51
|
+
return operation();
|
|
52
|
+
});
|
|
49
53
|
this.renderExclusiveChain = run.then(
|
|
50
54
|
() => void 0,
|
|
51
55
|
() => void 0
|
|
52
56
|
);
|
|
53
57
|
return run;
|
|
54
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Activates the owning integration runtime on first render or graph use.
|
|
61
|
+
*/
|
|
62
|
+
async ensureIntegrationRuntimeActivated() {
|
|
63
|
+
await ensureIntegrationRuntimeReady({
|
|
64
|
+
appConfig: this.appConfig,
|
|
65
|
+
integrationName: this.name,
|
|
66
|
+
runtimeOrigin: this.runtimeOrigin
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Prebuilds the production Page Browser Graph for one route file.
|
|
71
|
+
*/
|
|
72
|
+
async prebuildProductionPageBrowserGraph(routeFile) {
|
|
73
|
+
await this.ensureIntegrationRuntimeActivated();
|
|
74
|
+
await this.resolvePageBrowserGraphForFile(routeFile);
|
|
75
|
+
}
|
|
55
76
|
/**
|
|
56
77
|
* Loads one route module through the owning renderer's import path.
|
|
57
78
|
*
|
|
@@ -281,9 +302,13 @@ class IntegrationRenderer {
|
|
|
281
302
|
* @returns HTML response for the explicit view render.
|
|
282
303
|
*/
|
|
283
304
|
async renderViewWithDocumentShell(input) {
|
|
305
|
+
await this.ensureIntegrationRuntimeActivated();
|
|
284
306
|
const normalizedProps = input.props ?? {};
|
|
285
307
|
if (input.ctx.partial) {
|
|
286
|
-
return this.renderPartialViewResponse(
|
|
308
|
+
return this.renderPartialViewResponse({
|
|
309
|
+
...input,
|
|
310
|
+
transformHtml: input.transformDocumentHtml
|
|
311
|
+
});
|
|
287
312
|
}
|
|
288
313
|
await this.prepareViewDependencies(input.view, input.layout);
|
|
289
314
|
const HtmlTemplate = await this.getHtmlTemplate();
|
|
@@ -307,8 +332,9 @@ class IntegrationRenderer {
|
|
|
307
332
|
}
|
|
308
333
|
}
|
|
309
334
|
);
|
|
335
|
+
const transformedDocumentHtml = input.transformDocumentHtml ? input.transformDocumentHtml(documentHtml) : documentHtml;
|
|
310
336
|
const html = await this.finalizeResolvedHtml({
|
|
311
|
-
html: `${this.DOC_TYPE}${
|
|
337
|
+
html: `${this.DOC_TYPE}${transformedDocumentHtml}`,
|
|
312
338
|
partial: false
|
|
313
339
|
});
|
|
314
340
|
return this.createHtmlResponse(html, input.ctx);
|
|
@@ -346,7 +372,14 @@ class IntegrationRenderer {
|
|
|
346
372
|
}
|
|
347
373
|
const props = serializedChildren === void 0 ? input.props : { ...input.props, children: serializedChildren };
|
|
348
374
|
const content = await component(props);
|
|
349
|
-
|
|
375
|
+
if (typeof content !== "string") {
|
|
376
|
+
const componentFile = input.component.config?.__eco?.file ?? "unknown component";
|
|
377
|
+
const contentTag = Object.prototype.toString.call(content);
|
|
378
|
+
throw new TypeError(
|
|
379
|
+
`[ecopages] ${this.name} renderer expected a string render result for ${componentFile}, received ${contentTag}.`
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
const html = content;
|
|
350
383
|
const assets = input.component.config?.dependencies && typeof this.assetProcessingService?.processDependencies === "function" ? await this.processComponentDependencies([input.component]) : void 0;
|
|
351
384
|
return {
|
|
352
385
|
html,
|
|
@@ -435,23 +468,6 @@ class IntegrationRenderer {
|
|
|
435
468
|
ownershipValidationService: new OwnershipValidationService(appConfig)
|
|
436
469
|
});
|
|
437
470
|
}
|
|
438
|
-
/**
|
|
439
|
-
* Returns the HTML path from the provided file path.
|
|
440
|
-
* It extracts the path relative to the pages directory and removes the 'index' part if present.
|
|
441
|
-
*
|
|
442
|
-
* @param file - The file path to extract the HTML path from.
|
|
443
|
-
* @returns The extracted HTML path.
|
|
444
|
-
*/
|
|
445
|
-
getHtmlPath({ file }) {
|
|
446
|
-
const pagesDir = this.appConfig.absolutePaths.pagesDir;
|
|
447
|
-
const pagesIndex = file.indexOf(pagesDir);
|
|
448
|
-
if (pagesIndex === -1) return file;
|
|
449
|
-
const startIndex = file.indexOf(pagesDir) + pagesDir.length;
|
|
450
|
-
const endIndex = file.lastIndexOf("/");
|
|
451
|
-
const path = file.substring(startIndex, endIndex);
|
|
452
|
-
if (path === "/index") return "";
|
|
453
|
-
return path;
|
|
454
|
-
}
|
|
455
471
|
/**
|
|
456
472
|
* Returns the HTML template component.
|
|
457
473
|
* It imports the HTML template from the specified path in the app configuration.
|
|
@@ -505,46 +521,6 @@ class IntegrationRenderer {
|
|
|
505
521
|
resolveDependencyPath(componentDir, pathUrl) {
|
|
506
522
|
return this.dependencyResolverService.resolveDependencyPath(componentDir, pathUrl);
|
|
507
523
|
}
|
|
508
|
-
/**
|
|
509
|
-
* Extracts the dependencies from the provided component configuration.
|
|
510
|
-
* It resolves the paths for scripts and stylesheets based on the component directory.
|
|
511
|
-
*
|
|
512
|
-
* @param componentDir - The component directory path.
|
|
513
|
-
* @param scripts - The scripts to extract.
|
|
514
|
-
* @param stylesheets - The stylesheets to extract.
|
|
515
|
-
* @returns The extracted dependencies.
|
|
516
|
-
*/
|
|
517
|
-
extractDependencies({
|
|
518
|
-
componentDir,
|
|
519
|
-
scripts,
|
|
520
|
-
stylesheets
|
|
521
|
-
}) {
|
|
522
|
-
const scriptsPaths = [
|
|
523
|
-
...new Set(
|
|
524
|
-
(scripts ?? []).filter((script) => typeof script === "string" ? true : !script.lazy).map((script) => typeof script === "string" ? script : script.src).filter((script) => Boolean(script)).map((script) => this.resolveDependencyPath(componentDir, script))
|
|
525
|
-
)
|
|
526
|
-
];
|
|
527
|
-
const stylesheetsPaths = [
|
|
528
|
-
...new Set(
|
|
529
|
-
(stylesheets ?? []).map((style) => typeof style === "string" ? style : style.src).filter((style) => Boolean(style)).map((style) => this.resolveDependencyPath(componentDir, style))
|
|
530
|
-
)
|
|
531
|
-
];
|
|
532
|
-
return {
|
|
533
|
-
scripts: scriptsPaths,
|
|
534
|
-
stylesheets: stylesheetsPaths
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Resolves lazy script paths to public asset URLs.
|
|
539
|
-
* Converts source paths to their final bundled output paths.
|
|
540
|
-
*
|
|
541
|
-
* @param componentDir - The component directory path.
|
|
542
|
-
* @param scripts - The lazy script paths to resolve.
|
|
543
|
-
* @returns Comma-separated string of resolved public script paths.
|
|
544
|
-
*/
|
|
545
|
-
resolveLazyScripts(componentDir, scripts) {
|
|
546
|
-
return this.dependencyResolverService.resolveLazyScripts(componentDir, scripts);
|
|
547
|
-
}
|
|
548
524
|
/**
|
|
549
525
|
* Collects the dependencies for the provided components.
|
|
550
526
|
* Combines component-specific dependencies with global integration dependencies.
|
|
@@ -579,11 +555,9 @@ class IntegrationRenderer {
|
|
|
579
555
|
resolveRouteDependencies: (input) => this.resolveRouteDependencies(input),
|
|
580
556
|
importPageFile: (file) => this.importPageFile(file),
|
|
581
557
|
collectPageBrowserGraphContribution: (context) => this.collectPageBrowserGraphContribution(context),
|
|
582
|
-
resolveRoutePageComponentRender: (input) => this.resolveRoutePageComponentRender(input),
|
|
583
558
|
renderRouteBody: (renderOptions) => this.renderRouteBody(renderOptions),
|
|
584
559
|
getDocumentAttributes: (renderOptions) => this.getDocumentAttributes(renderOptions),
|
|
585
560
|
getHtmlDocumentContributions: (options) => this.getHtmlDocumentContributions(options),
|
|
586
|
-
applyAttributesToFirstBodyElement: (html, attributes) => this.applyAttributesToFirstBodyElement(html, attributes),
|
|
587
561
|
applyAttributesToHtmlElement: (html, attributes) => this.applyAttributesToHtmlElement(html, attributes),
|
|
588
562
|
transformRouteResponse: (response, htmlContributions, pagePackage) => this.transformRouteResponse(response, htmlContributions, pagePackage)
|
|
589
563
|
});
|
|
@@ -617,22 +591,6 @@ class IntegrationRenderer {
|
|
|
617
591
|
resolvedDependencies: await this.resolveDependencies(input.components)
|
|
618
592
|
};
|
|
619
593
|
}
|
|
620
|
-
async resolveRoutePageComponentRender(input) {
|
|
621
|
-
if (!this.shouldRenderPageComponent({ Page: input.Page, Layout: input.Layout, options: input.routeOptions })) {
|
|
622
|
-
return void 0;
|
|
623
|
-
}
|
|
624
|
-
return this.renderComponentWithForeignChildren({
|
|
625
|
-
component: input.Page,
|
|
626
|
-
props: {
|
|
627
|
-
...input.props,
|
|
628
|
-
params: input.routeOptions.params || {},
|
|
629
|
-
query: input.routeOptions.query || {}
|
|
630
|
-
},
|
|
631
|
-
integrationContext: {
|
|
632
|
-
componentInstanceId: "eco-page-root"
|
|
633
|
-
}
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
594
|
async renderRouteBody(renderOptions) {
|
|
637
595
|
return this.render(renderOptions);
|
|
638
596
|
}
|
|
@@ -658,17 +616,6 @@ class IntegrationRenderer {
|
|
|
658
616
|
this.htmlTransformer.setPagePackage(renderOptions.pagePackage);
|
|
659
617
|
return renderOptions;
|
|
660
618
|
}
|
|
661
|
-
/**
|
|
662
|
-
* Controls whether the page root should be rendered through `renderComponent()`
|
|
663
|
-
* during route option preparation in component-capable modes.
|
|
664
|
-
*
|
|
665
|
-
* Integrations that already own page-level hydration (for example router-driven
|
|
666
|
-
* React rendering) can override this and return `false` to avoid duplicate root
|
|
667
|
-
* mount assets and competing hydration entrypoints.
|
|
668
|
-
*/
|
|
669
|
-
shouldRenderPageComponent(_input) {
|
|
670
|
-
return true;
|
|
671
|
-
}
|
|
672
619
|
/**
|
|
673
620
|
* Executes the integration renderer with the provided options.
|
|
674
621
|
*
|
|
@@ -676,7 +623,7 @@ class IntegrationRenderer {
|
|
|
676
623
|
* 1. Build normalized render options (`prepareRenderOptions`).
|
|
677
624
|
* 2. Render the route body once.
|
|
678
625
|
* 3. Reject unresolved route-level eco-marker artifacts.
|
|
679
|
-
* 4. Optionally apply
|
|
626
|
+
* 4. Optionally apply document attributes for integration-owned document boundaries.
|
|
680
627
|
* 5. Run HTML transformer with final dependency set.
|
|
681
628
|
*
|
|
682
629
|
* Stream-safety note: the first render result is normalized to a string once,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ProcessedAsset } from '../../services/assets/asset-processing-service/index.js';
|
|
2
2
|
import type { HtmlDocumentContribution } from '../../services/html/html-transformer.service.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { EcoComponent, EcoPageFile, IntegrationRendererRenderOptions, PageBrowserGraphContribution, PageBrowserGraphContributionContext, PagePackageResult, RouteRendererBody, RouteRendererOptions } from '../../types/public-types.js';
|
|
4
4
|
import type { RouteHtmlFinalization, RouteRenderOrchestratorAdapter, RouteRenderOrchestratorResolvedInputs } from './route-render-orchestrator.js';
|
|
5
5
|
/**
|
|
6
6
|
* Host surface required to build the orchestrator adapter for one integration renderer.
|
|
@@ -15,19 +15,12 @@ export type IntegrationRouteRenderAdapterHost<C> = {
|
|
|
15
15
|
}>;
|
|
16
16
|
importPageFile(file: string): Promise<EcoPageFile>;
|
|
17
17
|
collectPageBrowserGraphContribution(context: PageBrowserGraphContributionContext): Promise<PageBrowserGraphContribution | undefined>;
|
|
18
|
-
resolveRoutePageComponentRender(input: {
|
|
19
|
-
Page: EcoComponent;
|
|
20
|
-
Layout?: EcoComponent;
|
|
21
|
-
props: Record<string, unknown>;
|
|
22
|
-
routeOptions: RouteRendererOptions;
|
|
23
|
-
}): Promise<ComponentRenderResult | undefined>;
|
|
24
18
|
renderRouteBody(renderOptions: IntegrationRendererRenderOptions<C>): Promise<RouteRendererBody>;
|
|
25
19
|
getDocumentAttributes(renderOptions: IntegrationRendererRenderOptions<C>): Record<string, string> | undefined;
|
|
26
20
|
getHtmlDocumentContributions(options: {
|
|
27
21
|
renderOptions: IntegrationRendererRenderOptions<C>;
|
|
28
22
|
partial: boolean;
|
|
29
23
|
}): HtmlDocumentContribution[] | undefined;
|
|
30
|
-
applyAttributesToFirstBodyElement(html: string, attributes: Record<string, string>): string;
|
|
31
24
|
applyAttributesToHtmlElement(html: string, attributes: Record<string, string>): string;
|
|
32
25
|
transformRouteResponse(response: Response, htmlContributions?: HtmlDocumentContribution[], pagePackage?: PagePackageResult): Promise<RouteRendererBody>;
|
|
33
26
|
};
|
|
@@ -10,13 +10,11 @@ function createIntegrationRouteRenderAdapter(host) {
|
|
|
10
10
|
(file) => host.importPageFile(file),
|
|
11
11
|
(context) => host.collectPageBrowserGraphContribution(context)
|
|
12
12
|
),
|
|
13
|
-
resolveRoutePageComponentRender: (input) => host.resolveRoutePageComponentRender(input),
|
|
14
13
|
renderRouteBody: (renderOptions) => host.renderRouteBody(renderOptions),
|
|
15
14
|
getRouteHtmlFinalization: (renderOptions) => buildRouteHtmlFinalization({
|
|
16
15
|
renderOptions,
|
|
17
16
|
getDocumentAttributes: (options) => host.getDocumentAttributes(options),
|
|
18
17
|
getHtmlDocumentContributions: (options) => host.getHtmlDocumentContributions(options),
|
|
19
|
-
applyAttributesToFirstBodyElement: (html, attributes) => host.applyAttributesToFirstBodyElement(html, attributes),
|
|
20
18
|
applyAttributesToHtmlElement: (html, attributes) => host.applyAttributesToHtmlElement(html, attributes)
|
|
21
19
|
}),
|
|
22
20
|
transformRouteResponse: (response, htmlContributions, pagePackage) => host.transformRouteResponse(response, htmlContributions, pagePackage)
|