@ecopages/core 0.2.0-beta.26 → 0.2.0-beta.28
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 +98 -74
- 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/eco/eco.js +2 -2
- package/src/eco/eco.utils.d.ts +1 -1
- package/src/eco/eco.utils.js +1 -1
- package/src/hmr/client/hmr-runtime.js +2 -2
- 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 +36 -8
- package/src/plugins/source-transform.d.ts +1 -1
- package/src/route-renderer/GRAPH.md +22 -28
- package/src/route-renderer/README.md +12 -7
- package/src/route-renderer/orchestration/{document-shell-render.service.d.ts → document-shell/document-shell-render.service.d.ts} +19 -2
- package/src/route-renderer/orchestration/{document-shell-render.service.js → document-shell/document-shell-render.service.js} +28 -0
- package/src/route-renderer/orchestration/{layout-shell-props.service.d.ts → document-shell/layout-shell-props.service.d.ts} +1 -1
- package/src/route-renderer/orchestration/{component-render-context.d.ts → foreign-child/component-render-context.d.ts} +5 -5
- package/src/route-renderer/orchestration/{component-render-context.js → foreign-child/component-render-context.js} +1 -1
- package/src/route-renderer/orchestration/{render-output.utils.d.ts → foreign-child/foreign-child-output.utils.d.ts} +15 -7
- package/src/route-renderer/orchestration/{render-output.utils.js → foreign-child/foreign-child-output.utils.js} +31 -26
- package/src/route-renderer/orchestration/{foreign-subtree-execution.service.d.ts → foreign-child/foreign-subtree-execution.service.d.ts} +5 -5
- package/src/route-renderer/orchestration/{foreign-subtree-execution.service.js → foreign-child/foreign-subtree-execution.service.js} +7 -3
- package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.d.ts +19 -0
- package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.js +35 -0
- package/src/route-renderer/orchestration/integration-renderer.d.ts +14 -97
- package/src/route-renderer/orchestration/integration-renderer.js +90 -247
- package/src/route-renderer/orchestration/integration-renderer.test-fixtures.d.ts +75 -0
- package/src/route-renderer/orchestration/integration-renderer.test-fixtures.js +177 -0
- package/src/route-renderer/orchestration/{component-graph-collectors.d.ts → ownership-graph/component-graph-collectors.d.ts} +4 -4
- package/src/route-renderer/orchestration/{component-graph-collectors.js → ownership-graph/component-graph-collectors.js} +1 -1
- package/src/route-renderer/orchestration/{component-graph.d.ts → ownership-graph/component-graph.d.ts} +1 -3
- package/src/route-renderer/orchestration/{component-graph.js → ownership-graph/component-graph.js} +0 -2
- package/src/route-renderer/orchestration/{ownership-validation.service.d.ts → ownership-graph/ownership-validation.service.d.ts} +2 -2
- package/src/route-renderer/orchestration/{ownership-validation.service.js → ownership-graph/ownership-validation.service.js} +3 -4
- package/src/route-renderer/orchestration/{global-injector-assets.service.d.ts → page-browser-graph/global-injector-assets.service.d.ts} +3 -3
- package/src/route-renderer/orchestration/{global-injector-assets.service.js → page-browser-graph/global-injector-assets.service.js} +2 -2
- package/src/route-renderer/orchestration/{page-browser-graph-contribution.loader.d.ts → page-browser-graph/page-browser-graph-contribution.loader.d.ts} +1 -1
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.d.ts +12 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.js +29 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.d.ts +106 -0
- package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.js +436 -0
- package/src/route-renderer/orchestration/{page-browser-graph.service.d.ts → page-browser-graph/page-browser-graph.service.d.ts} +12 -6
- package/src/route-renderer/orchestration/{page-browser-graph.service.js → page-browser-graph/page-browser-graph.service.js} +91 -42
- package/src/route-renderer/orchestration/{processed-asset-dedupe.d.ts → page-browser-graph/processed-asset-dedupe.d.ts} +1 -1
- package/src/route-renderer/orchestration/{integration-route-render-adapter.d.ts → route-pipeline/integration-route-render-adapter.d.ts} +3 -10
- package/src/route-renderer/orchestration/{integration-route-render-adapter.js → route-pipeline/integration-route-render-adapter.js} +1 -3
- package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.d.ts +6 -0
- package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.js +27 -0
- package/src/route-renderer/orchestration/{route-html-finalization.service.d.ts → route-pipeline/route-html-finalization.service.d.ts} +2 -3
- package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.js +21 -0
- package/src/route-renderer/orchestration/{route-prepared-options.builder.d.ts → route-pipeline/route-prepared-options.builder.d.ts} +3 -4
- package/src/route-renderer/orchestration/{route-prepared-options.builder.js → route-pipeline/route-prepared-options.builder.js} +3 -12
- package/src/route-renderer/orchestration/{route-prepared-options.utils.js → route-pipeline/route-prepared-options.utils.js} +1 -1
- package/src/route-renderer/orchestration/{route-render-orchestrator.d.ts → route-pipeline/route-render-orchestrator.d.ts} +8 -17
- package/src/route-renderer/orchestration/{route-render-orchestrator.js → route-pipeline/route-render-orchestrator.js} +12 -19
- package/src/route-renderer/orchestration/string-markup-renderer.js +1 -1
- 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/html/html-transformer.service.js +1 -1
- package/src/services/invalidation/development-invalidation.service.d.ts +5 -0
- package/src/services/invalidation/development-invalidation.service.js +8 -9
- 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 +59 -10
- package/src/watchers/project-watcher.d.ts +3 -3
- package/src/watchers/project-watcher.js +15 -5
- 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/route-renderer/orchestration/declared-ownership-graph.d.ts +0 -1
- package/src/route-renderer/orchestration/declared-ownership-graph.js +0 -8
- package/src/route-renderer/orchestration/route-html-finalization.service.js +0 -26
- package/src/route-renderer/orchestration/template-serialization.d.ts +0 -38
- package/src/route-renderer/orchestration/template-serialization.js +0 -45
- /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
- /package/src/route-renderer/orchestration/{layout-shell-props.service.js → document-shell/layout-shell-props.service.js} +0 -0
- /package/src/route-renderer/orchestration/{page-browser-graph-contribution.loader.js → page-browser-graph/page-browser-graph-contribution.loader.js} +0 -0
- /package/src/route-renderer/orchestration/{processed-asset-dedupe.js → page-browser-graph/processed-asset-dedupe.js} +0 -0
- /package/src/route-renderer/orchestration/{route-prepared-options.utils.d.ts → route-pipeline/route-prepared-options.utils.d.ts} +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createBrowserRuntimeManifest
|
|
3
|
+
} from "../build/browser/browser-runtime-manifest.js";
|
|
2
4
|
import { AssetProcessingService } from "../services/assets/asset-processing-service/asset-processing.service.js";
|
|
3
5
|
import { deepMerge } from "../utils/deep-merge.js";
|
|
4
6
|
import { invariant } from "../utils/invariant.js";
|
|
@@ -23,6 +25,14 @@ class IntegrationPlugin {
|
|
|
23
25
|
appConfig;
|
|
24
26
|
assetProcessingService;
|
|
25
27
|
hmrManager;
|
|
28
|
+
/**
|
|
29
|
+
* Returns build plugins shared by server-oriented and browser-oriented builds.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* Collected into {@link AppBuildManifest.runtimePlugins} during config finalization.
|
|
33
|
+
* MDX loaders, virtual-module resolvers, and other transforms that must run during
|
|
34
|
+
* route-module transpile belong here—not in {@link browserBuildPlugins}.
|
|
35
|
+
*/
|
|
26
36
|
get plugins() {
|
|
27
37
|
return [];
|
|
28
38
|
}
|
|
@@ -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
|
};
|
|
@@ -19,6 +19,14 @@ export interface ProcessorWatchContext {
|
|
|
19
19
|
}
|
|
20
20
|
export interface ProcessorWatchConfig {
|
|
21
21
|
paths: string[];
|
|
22
|
+
/**
|
|
23
|
+
* File extensions that trigger watch callbacks (`onCreate`, `onChange`, `onDelete`).
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* Watch extensions drive notifications only. They do not declare asset ownership.
|
|
27
|
+
* Ownership requires {@link ProcessorConfig.capabilities} and controls whether dev
|
|
28
|
+
* invalidation skips server modules and HMR for processor-handled assets.
|
|
29
|
+
*/
|
|
22
30
|
extensions?: string[];
|
|
23
31
|
onCreate?: (ctx: ProcessorWatchContext) => Promise<void>;
|
|
24
32
|
onChange?: (ctx: ProcessorWatchContext) => Promise<void>;
|
|
@@ -57,10 +65,17 @@ export interface ProcessorContext {
|
|
|
57
65
|
cache?: string;
|
|
58
66
|
}
|
|
59
67
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
68
|
+
* Base class for content and asset processors that contribute build plugins.
|
|
69
|
+
*
|
|
70
|
+
* @remarks
|
|
71
|
+
* Processors declare plugins through two getters that map to
|
|
72
|
+
* {@link AppBuildManifest} buckets (names differ from integrations):
|
|
73
|
+
*
|
|
74
|
+
* - `plugins` → `runtimePlugins` (server **and** browser builds)
|
|
75
|
+
* - `buildPlugins` → `browserBundlePlugins` (browser bundles only)
|
|
76
|
+
*
|
|
77
|
+
* Virtual modules that must resolve during route-module transpile belong in
|
|
78
|
+
* `plugins`. Browser-only bundler hooks belong in `buildPlugins`.
|
|
64
79
|
*/
|
|
65
80
|
export declare abstract class Processor<TOptions = Record<string, unknown>> {
|
|
66
81
|
readonly name: string;
|
|
@@ -69,9 +84,22 @@ export declare abstract class Processor<TOptions = Record<string, unknown>> {
|
|
|
69
84
|
protected watchConfig?: ProcessorWatchConfig;
|
|
70
85
|
protected capabilities: ProcessorAssetCapability[];
|
|
71
86
|
readonly runtimeCapability?: RuntimeCapabilityDeclaration;
|
|
72
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* Browser-bundle-only plugins.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* Maps to {@link AppBuildManifest.browserBundlePlugins}. Integrations name the
|
|
92
|
+
* same bucket `browserBuildPlugins`.
|
|
93
|
+
*/
|
|
73
94
|
abstract buildPlugins?: EcoBuildPlugin[];
|
|
74
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Shared build plugins for server-oriented and browser-oriented work.
|
|
97
|
+
*
|
|
98
|
+
* @remarks
|
|
99
|
+
* Maps to {@link AppBuildManifest.runtimePlugins}. Despite the name, these are
|
|
100
|
+
* bundler plugins—not dev-server file processors. Runtime-only setup stays in
|
|
101
|
+
* {@link setup}.
|
|
102
|
+
*/
|
|
75
103
|
abstract plugins?: EcoBuildPlugin[];
|
|
76
104
|
constructor(config: ProcessorConfig<TOptions>);
|
|
77
105
|
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
|
|
@@ -91,7 +85,7 @@ flowchart TD
|
|
|
91
85
|
B -- Yes --> C[return resolved renderer-owned output]
|
|
92
86
|
B -- No --> D[queue foreign-subtree token]
|
|
93
87
|
D --> E[finish current render pass]
|
|
94
|
-
E --> F[
|
|
88
|
+
E --> F[ForeignSubtreeExecutionService resolveQueuedHtml]
|
|
95
89
|
F --> G[resolve nested queued tokens first]
|
|
96
90
|
G --> H[dispatch foreign subtree to owning renderer]
|
|
97
91
|
H --> I[merge emitted assets and root attributes]
|
|
@@ -121,12 +115,12 @@ flowchart TD
|
|
|
121
115
|
The most useful reading order is:
|
|
122
116
|
|
|
123
117
|
1. `route-renderer.ts`
|
|
124
|
-
2. `orchestration/route-render-orchestrator.ts`
|
|
118
|
+
2. `orchestration/route-pipeline/route-render-orchestrator.ts`
|
|
125
119
|
3. `orchestration/integration-renderer.ts`
|
|
126
|
-
4. `orchestration/ownership-validation.service.ts`
|
|
127
|
-
5. `orchestration/ownership-
|
|
128
|
-
6. `orchestration/component-render-context.ts`
|
|
129
|
-
7. `orchestration/foreign-subtree-execution.service.ts`
|
|
120
|
+
4. `orchestration/ownership-graph/ownership-validation.service.ts`
|
|
121
|
+
5. `orchestration/ownership-graph/component-graph.ts`
|
|
122
|
+
6. `orchestration/foreign-child/component-render-context.ts`
|
|
123
|
+
7. `orchestration/foreign-child/foreign-subtree-execution.service.ts`
|
|
130
124
|
8. `page-loading/page-module-loader.ts`
|
|
131
125
|
9. `page-loading/dependency-resolver.ts`
|
|
132
126
|
10. `eco/eco.ts`
|
|
@@ -134,12 +128,12 @@ The most useful reading order is:
|
|
|
134
128
|
## 7) Key Files
|
|
135
129
|
|
|
136
130
|
- `packages/core/src/route-renderer/route-renderer.ts`
|
|
137
|
-
- `packages/core/src/route-renderer/orchestration/route-render-orchestrator.ts`
|
|
131
|
+
- `packages/core/src/route-renderer/orchestration/route-pipeline/route-render-orchestrator.ts`
|
|
138
132
|
- `packages/core/src/route-renderer/orchestration/integration-renderer.ts`
|
|
139
|
-
- `packages/core/src/route-renderer/orchestration/ownership-validation.service.ts`
|
|
140
|
-
- `packages/core/src/route-renderer/orchestration/ownership-
|
|
141
|
-
- `packages/core/src/route-renderer/orchestration/component-render-context.ts`
|
|
142
|
-
- `packages/core/src/route-renderer/orchestration/foreign-subtree-execution.service.ts`
|
|
133
|
+
- `packages/core/src/route-renderer/orchestration/ownership-graph/ownership-validation.service.ts`
|
|
134
|
+
- `packages/core/src/route-renderer/orchestration/ownership-graph/component-graph.ts`
|
|
135
|
+
- `packages/core/src/route-renderer/orchestration/foreign-child/component-render-context.ts`
|
|
136
|
+
- `packages/core/src/route-renderer/orchestration/foreign-child/foreign-subtree-execution.service.ts`
|
|
143
137
|
- `packages/core/src/route-renderer/page-loading/page-module-loader.ts`
|
|
144
138
|
- `packages/core/src/route-renderer/page-loading/dependency-resolver.ts`
|
|
145
139
|
- `packages/core/src/eco/eco.ts`
|
|
@@ -50,13 +50,18 @@ See [`../build/README.md`](../build/README.md) for the JSX ownership helper spli
|
|
|
50
50
|
|
|
51
51
|
### `orchestration/`
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Root renderer classes:
|
|
54
|
+
|
|
54
55
|
- `integration-renderer.ts`: abstract base class for route rendering, explicit view rendering, and foreign-child delegation
|
|
55
|
-
- `
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
- `
|
|
56
|
+
- `string-markup-renderer.ts`: shared base for string-markup integrations
|
|
57
|
+
|
|
58
|
+
Domain folders:
|
|
59
|
+
|
|
60
|
+
- `ownership-graph/`: component graph walk/collect and up-front ownership validation
|
|
61
|
+
- `foreign-child/`: active render context, foreign-subtree execution, deferred template serialization
|
|
62
|
+
- `document-shell/`: shared page/layout/html shell composition and attribute stamping helpers
|
|
63
|
+
- `route-pipeline/`: route preparation, final HTML capture, marker-artifact enforcement
|
|
64
|
+
- `page-browser-graph/`: browser asset graph build, session cache, and injector assets
|
|
60
65
|
|
|
61
66
|
### `page-loading/`
|
|
62
67
|
|
|
@@ -72,7 +77,7 @@ The route-render contract is:
|
|
|
72
77
|
3. `RouteRenderOrchestrator.prepareRenderOptions()` loads the page module, validates ownership (fail-fast), resolves page data, resolves dependencies, and builds the page browser graph.
|
|
73
78
|
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
79
|
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
|
|
80
|
+
6. `RouteRenderOrchestrator.executePrepared()` captures the final body, rejects unresolved `<eco-marker>` artifacts, stamps document attributes when needed, and runs the HTML transformer.
|
|
76
81
|
|
|
77
82
|
Important:
|
|
78
83
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { BaseIntegrationContext, ComponentRenderInput, ComponentRenderResult, EcoComponent, PageMetadataProps } from '
|
|
2
|
-
import type { ProcessedAsset } from '
|
|
1
|
+
import type { BaseIntegrationContext, ComponentRenderInput, ComponentRenderResult, EcoComponent, PageMetadataProps } from '../../../types/public-types.js';
|
|
2
|
+
import type { ProcessedAsset } from '../../../services/assets/asset-processing-service/index.js';
|
|
3
|
+
import { HtmlTransformerService, type HtmlDocumentContribution } from '../../../services/html/html-transformer.service.js';
|
|
3
4
|
export type DocumentShellLayoutInput = {
|
|
4
5
|
component: EcoComponent;
|
|
5
6
|
props?: Record<string, unknown>;
|
|
@@ -88,3 +89,19 @@ export declare function applyDocumentShellAttributeStamping(html: string, stampi
|
|
|
88
89
|
* Builds the final serialized document HTML for one route page render.
|
|
89
90
|
*/
|
|
90
91
|
export declare function renderPageDocumentShell(dependencies: DocumentShellRenderDependencies, input: DocumentShellPageRenderInput, docType: string): Promise<string>;
|
|
92
|
+
/**
|
|
93
|
+
* Finalizes already-resolved HTML for explicit renderer-owned paths.
|
|
94
|
+
*
|
|
95
|
+
* @remarks
|
|
96
|
+
* Callers append renderer bootstrap dependencies before invoking this helper.
|
|
97
|
+
* Stamps document/root attributes and runs HTML transformation after nested
|
|
98
|
+
* foreign-subtree resolution without routing back through shared route execution.
|
|
99
|
+
*/
|
|
100
|
+
export declare function finalizeDocumentShellHtml(htmlTransformer: HtmlTransformerService, options: {
|
|
101
|
+
html: string;
|
|
102
|
+
partial?: boolean;
|
|
103
|
+
componentRootAttributes?: Record<string, string>;
|
|
104
|
+
documentAttributes?: Record<string, string>;
|
|
105
|
+
transformHtml?: boolean;
|
|
106
|
+
htmlContributions?: HtmlDocumentContribution[];
|
|
107
|
+
}): Promise<string>;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HtmlTransformerService
|
|
3
|
+
} from "../../../services/html/html-transformer.service.js";
|
|
1
4
|
function resolveDocumentShellLayouts(input) {
|
|
2
5
|
if (input.layouts && input.layouts.length > 0) {
|
|
3
6
|
return input.layouts;
|
|
@@ -112,9 +115,34 @@ async function renderPageDocumentShell(dependencies, input, docType) {
|
|
|
112
115
|
const documentHtml = input.transformDocumentHtml ? input.transformDocumentHtml(composedDocumentHtml) : composedDocumentHtml;
|
|
113
116
|
return `${docType}${documentHtml}`;
|
|
114
117
|
}
|
|
118
|
+
async function finalizeDocumentShellHtml(htmlTransformer, options) {
|
|
119
|
+
const html = applyDocumentShellAttributeStamping(
|
|
120
|
+
options.html,
|
|
121
|
+
{
|
|
122
|
+
applyAttributesToFirstBodyElement: (nextHtml, attributes) => htmlTransformer.applyAttributesToFirstBodyElement(nextHtml, attributes),
|
|
123
|
+
applyAttributesToHtmlElement: (nextHtml, attributes) => htmlTransformer.applyAttributesToHtmlElement(nextHtml, attributes)
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
componentRootAttributes: options.componentRootAttributes,
|
|
127
|
+
documentAttributes: options.documentAttributes
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
const shouldTransform = options.transformHtml ?? !options.partial;
|
|
131
|
+
if (!shouldTransform) {
|
|
132
|
+
return html;
|
|
133
|
+
}
|
|
134
|
+
const transformedResponse = await htmlTransformer.transform(
|
|
135
|
+
new Response(html, {
|
|
136
|
+
headers: { "Content-Type": "text/html" }
|
|
137
|
+
}),
|
|
138
|
+
options.htmlContributions
|
|
139
|
+
);
|
|
140
|
+
return await transformedResponse.text();
|
|
141
|
+
}
|
|
115
142
|
export {
|
|
116
143
|
applyDocumentShellAttributeStamping,
|
|
117
144
|
composeDocumentShell,
|
|
118
145
|
composeSequentialLayoutChildren,
|
|
146
|
+
finalizeDocumentShellHtml,
|
|
119
147
|
renderPageDocumentShell
|
|
120
148
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EcoPageLayoutEntry, LayoutPropsContext } from '
|
|
1
|
+
import type { EcoPageLayoutEntry, LayoutPropsContext } from '../../../types/public-types.js';
|
|
2
2
|
export type LayoutShellPropsContext = LayoutPropsContext & {
|
|
3
3
|
pageProps?: Record<string, unknown>;
|
|
4
4
|
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type { EcoComponent } from '
|
|
1
|
+
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.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addTriggerAttribute, isThenable, wrapWithScriptsInjector } from "./
|
|
1
|
+
import { addTriggerAttribute, isThenable, wrapWithScriptsInjector } from "./foreign-child-output.utils.js";
|
|
2
2
|
class ComponentRenderOutputRuntime {
|
|
3
3
|
finalizeComponentRender(component, content) {
|
|
4
4
|
const lazyTriggers = component.config?._resolvedLazyTriggers;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EcoComponent } from '
|
|
1
|
+
import type { EcoComponent } from '../../../types/public-types.js';
|
|
2
2
|
type ResolvedLazyScriptGroups = Readonly<NonNullable<EcoComponent['config']>['_resolvedLazyScripts']>;
|
|
3
3
|
type TemplateContentShape = {
|
|
4
4
|
strings: readonly string[];
|
|
@@ -23,6 +23,20 @@ type MarkupNodeLikeShape = {
|
|
|
23
23
|
export declare function isThenable<T>(value: unknown): value is PromiseLike<T>;
|
|
24
24
|
/** Returns whether a value looks like a DOM-like markup node from SSR integrations. */
|
|
25
25
|
export declare function isMarkupNodeLike(value: unknown): value is MarkupNodeLikeShape;
|
|
26
|
+
/**
|
|
27
|
+
* Returns whether a value is a plain opaque object that string serializers would
|
|
28
|
+
* coerce via `String(value)` rather than render as markup.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* Template results (`strings`/`values`), markup nodes, arrays, and framework
|
|
32
|
+
* element markers (`$$typeof`) are not opaque. Cross-integration children that
|
|
33
|
+
* are only plain objects must use EcoEmbed or already-serialized HTML.
|
|
34
|
+
*/
|
|
35
|
+
export declare function isOpaqueForeignChildValue(children: unknown): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Throws when foreign-path children would be coerced from an opaque object.
|
|
38
|
+
*/
|
|
39
|
+
export declare function assertForeignChildrenNotOpaque(children: unknown, context: string): void;
|
|
26
40
|
/**
|
|
27
41
|
* Injects `data-eco-trigger` into the first real HTML element opening tag of
|
|
28
42
|
* a component's rendered output string.
|
|
@@ -59,10 +73,4 @@ export declare function wrapWithScriptsInjector(content: string, lazyGroups: Res
|
|
|
59
73
|
export declare function wrapWithScriptsInjector<T extends TemplateContentShape>(content: T, lazyGroups: ResolvedLazyScriptGroups): T | string;
|
|
60
74
|
export declare function wrapWithScriptsInjector<T extends MarkupNodeLikeShape>(content: T, lazyGroups: ResolvedLazyScriptGroups): T;
|
|
61
75
|
export declare function wrapWithScriptsInjector(content: unknown, lazyGroups: ResolvedLazyScriptGroups): string | TemplateContentShape | MarkupNodeLikeShape;
|
|
62
|
-
export declare function decodeHtmlEntities(value: string): string;
|
|
63
|
-
export declare function normalizeUnresolvedMarkerArtifactHtml(html: string): string;
|
|
64
|
-
export declare function inspectUnresolvedMarkerArtifactHtml(html: string): {
|
|
65
|
-
hasUnresolvedMarkerArtifacts: boolean;
|
|
66
|
-
normalizedHtml: string;
|
|
67
|
-
};
|
|
68
76
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildInjectorMapScript } from "
|
|
1
|
+
import { buildInjectorMapScript } from "../../../eco/lazy-injector-map.js";
|
|
2
2
|
function cloneTemplateStrings(strings, firstString) {
|
|
3
3
|
const nextStrings = [...strings];
|
|
4
4
|
nextStrings[0] = firstString;
|
|
@@ -85,6 +85,34 @@ function isMarkupNodeLikeShape(value) {
|
|
|
85
85
|
function isMarkupNodeLike(value) {
|
|
86
86
|
return isMarkupNodeLikeShape(value);
|
|
87
87
|
}
|
|
88
|
+
function isOpaqueForeignChildValue(children) {
|
|
89
|
+
if (children === null || typeof children !== "object") {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (Array.isArray(children)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
if ("$$typeof" in children) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
if ("strings" in children && Array.isArray(children.strings)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (isMarkupNodeLikeShape(children)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const prototype = Object.getPrototypeOf(children);
|
|
105
|
+
return prototype === Object.prototype || prototype === null;
|
|
106
|
+
}
|
|
107
|
+
function assertForeignChildrenNotOpaque(children, context) {
|
|
108
|
+
if (!isOpaqueForeignChildValue(children)) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const childTag = Object.prototype.toString.call(children);
|
|
112
|
+
throw new TypeError(
|
|
113
|
+
`[ecopages] ${context} refused to coerce opaque foreign children (${childTag}). Use EcoEmbed for cross-integration children or pass already-serialized HTML.`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
88
116
|
function injectTriggerAttributeIntoString(content, triggerId) {
|
|
89
117
|
const str = content;
|
|
90
118
|
let i = 0;
|
|
@@ -142,34 +170,11 @@ function wrapWithScriptsInjector(content, lazyGroups) {
|
|
|
142
170
|
}
|
|
143
171
|
return wrapWithScriptsInjectorMarkup(String(content), injectorMapScript);
|
|
144
172
|
}
|
|
145
|
-
function decodeHtmlEntities(value) {
|
|
146
|
-
let decoded = value;
|
|
147
|
-
let previous;
|
|
148
|
-
do {
|
|
149
|
-
previous = decoded;
|
|
150
|
-
decoded = decoded.replaceAll(""", '"').replaceAll("'", "'").replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">").replaceAll("&", "&");
|
|
151
|
-
} while (decoded !== previous);
|
|
152
|
-
return decoded;
|
|
153
|
-
}
|
|
154
|
-
function normalizeUnresolvedMarkerArtifactHtml(html) {
|
|
155
|
-
return html.replace(
|
|
156
|
-
/&(?:amp;)?lt;eco-marker\b[\s\S]*?&(?:amp;)?gt;&(?:amp;)?lt;\/eco-marker&(?:amp;)?gt;/g,
|
|
157
|
-
(marker) => decodeHtmlEntities(marker)
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
function inspectUnresolvedMarkerArtifactHtml(html) {
|
|
161
|
-
const normalizedHtml = normalizeUnresolvedMarkerArtifactHtml(html);
|
|
162
|
-
return {
|
|
163
|
-
normalizedHtml,
|
|
164
|
-
hasUnresolvedMarkerArtifacts: normalizedHtml.includes("<eco-marker")
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
173
|
export {
|
|
168
174
|
addTriggerAttribute,
|
|
169
|
-
|
|
170
|
-
inspectUnresolvedMarkerArtifactHtml,
|
|
175
|
+
assertForeignChildrenNotOpaque,
|
|
171
176
|
isMarkupNodeLike,
|
|
177
|
+
isOpaqueForeignChildValue,
|
|
172
178
|
isThenable,
|
|
173
|
-
normalizeUnresolvedMarkerArtifactHtml,
|
|
174
179
|
wrapWithScriptsInjector
|
|
175
180
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ProcessedAsset } from '
|
|
2
|
-
import type { BaseIntegrationContext, ComponentRenderInput, ComponentRenderResult, EcoComponent, ForeignSubtreeRenderPayload } from '
|
|
1
|
+
import type { ProcessedAsset } from '../../../services/assets/asset-processing-service/index.js';
|
|
2
|
+
import type { BaseIntegrationContext, ComponentRenderInput, ComponentRenderResult, EcoComponent, ForeignSubtreeRenderPayload } from '../../../types/public-types.js';
|
|
3
3
|
import { type ForeignChildRuntime } from './component-render-context.js';
|
|
4
4
|
export type QueuedForeignChildDecisionInput = {
|
|
5
5
|
currentIntegration: string;
|
|
@@ -46,7 +46,7 @@ export interface ForeignSubtreeExecutionRenderOptions {
|
|
|
46
46
|
renderInput: ComponentRenderInput;
|
|
47
47
|
rendererCache: Map<string, ForeignSubtreeExecutionOwningRenderer>;
|
|
48
48
|
}): ForeignChildRuntime;
|
|
49
|
-
getOwningRenderer(integrationName: string, rendererCache: Map<string, ForeignSubtreeExecutionOwningRenderer>): ForeignSubtreeExecutionOwningRenderer
|
|
49
|
+
getOwningRenderer(integrationName: string, rendererCache: Map<string, ForeignSubtreeExecutionOwningRenderer>): Promise<ForeignSubtreeExecutionOwningRenderer>;
|
|
50
50
|
}
|
|
51
51
|
export interface ForeignSubtreeQueuedRuntimeOptions<TContext extends QueuedForeignSubtreeResolutionContext> {
|
|
52
52
|
renderInput: ComponentRenderInput;
|
|
@@ -61,7 +61,7 @@ export interface ForeignSubtreeStringQueuedHtmlOptions {
|
|
|
61
61
|
html: string;
|
|
62
62
|
runtimeContextKey: string;
|
|
63
63
|
queueLabel: string;
|
|
64
|
-
getOwningRenderer(integrationName: string, rendererCache: Map<string, ForeignSubtreeExecutionOwningRenderer>): ForeignSubtreeExecutionOwningRenderer
|
|
64
|
+
getOwningRenderer(integrationName: string, rendererCache: Map<string, ForeignSubtreeExecutionOwningRenderer>): Promise<ForeignSubtreeExecutionOwningRenderer>;
|
|
65
65
|
applyAttributesToFirstElement(html: string, attributes: Record<string, string>): string;
|
|
66
66
|
dedupeProcessedAssets(assets: ProcessedAsset[]): ProcessedAsset[];
|
|
67
67
|
}
|
|
@@ -75,7 +75,7 @@ export interface ForeignSubtreeQueuedHtmlOptions<TContext extends QueuedForeignS
|
|
|
75
75
|
children?: unknown;
|
|
76
76
|
html?: string;
|
|
77
77
|
}>;
|
|
78
|
-
getOwningRenderer(integrationName: string, rendererCache: Map<string, ForeignSubtreeExecutionOwningRenderer>): ForeignSubtreeExecutionOwningRenderer
|
|
78
|
+
getOwningRenderer(integrationName: string, rendererCache: Map<string, ForeignSubtreeExecutionOwningRenderer>): Promise<ForeignSubtreeExecutionOwningRenderer>;
|
|
79
79
|
applyAttributesToFirstElement(html: string, attributes: Record<string, string>): string;
|
|
80
80
|
dedupeProcessedAssets(assets: ProcessedAsset[]): ProcessedAsset[];
|
|
81
81
|
}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
getComponentRenderContext,
|
|
3
3
|
runWithComponentRenderContext
|
|
4
4
|
} from "./component-render-context.js";
|
|
5
|
-
import { isMarkupNodeLike } from "./
|
|
5
|
+
import { assertForeignChildrenNotOpaque, isMarkupNodeLike } from "./foreign-child-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
|
);
|
|
@@ -309,7 +313,7 @@ class ForeignSubtreeExecutionService {
|
|
|
309
313
|
if (!foreignOwnerIntegrationName) {
|
|
310
314
|
return void 0;
|
|
311
315
|
}
|
|
312
|
-
const owningRenderer = options.getOwningRenderer(foreignOwnerIntegrationName, options.rendererCache);
|
|
316
|
+
const owningRenderer = await options.getOwningRenderer(foreignOwnerIntegrationName, options.rendererCache);
|
|
313
317
|
if (owningRenderer.name === options.currentIntegrationName) {
|
|
314
318
|
return void 0;
|
|
315
319
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { EcoPagesAppConfig } from '../../../types/internal-types.js';
|
|
2
|
+
import type { ForeignSubtreeExecutionOwningRenderer } from './foreign-subtree-execution.service.js';
|
|
3
|
+
export type OwningRendererResolutionInput = {
|
|
4
|
+
appConfig: EcoPagesAppConfig;
|
|
5
|
+
runtimeOrigin: string;
|
|
6
|
+
currentIntegrationName: string;
|
|
7
|
+
currentRenderer: ForeignSubtreeExecutionOwningRenderer;
|
|
8
|
+
integrationName: string;
|
|
9
|
+
cache: Map<string, ForeignSubtreeExecutionOwningRenderer>;
|
|
10
|
+
};
|
|
11
|
+
export declare function getForeignSubtreeTokenPrefix(integrationName: string): string;
|
|
12
|
+
export declare function getForeignSubtreeResolutionContextKey(integrationName: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Resolves an owning integration renderer for a foreign-child handoff.
|
|
15
|
+
*
|
|
16
|
+
* Reuses the execution-scoped cache, activates the target runtime when needed,
|
|
17
|
+
* and initializes the plugin renderer once per integration name.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveOwningIntegrationRenderer(input: OwningRendererResolutionInput): Promise<ForeignSubtreeExecutionOwningRenderer>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ensureIntegrationRuntimeReady } from "../../../build/app-build-manifest-runtime.js";
|
|
2
|
+
import { invariant } from "../../../utils/invariant.js";
|
|
3
|
+
function getForeignSubtreeTokenPrefix(integrationName) {
|
|
4
|
+
return `__${integrationName}_foreign_subtree__`;
|
|
5
|
+
}
|
|
6
|
+
function getForeignSubtreeResolutionContextKey(integrationName) {
|
|
7
|
+
return `__${integrationName}_foreign_subtree_runtime__`;
|
|
8
|
+
}
|
|
9
|
+
async function resolveOwningIntegrationRenderer(input) {
|
|
10
|
+
const { integrationName, cache } = input;
|
|
11
|
+
if (cache.has(integrationName)) {
|
|
12
|
+
return cache.get(integrationName);
|
|
13
|
+
}
|
|
14
|
+
if (integrationName === input.currentIntegrationName) {
|
|
15
|
+
cache.set(integrationName, input.currentRenderer);
|
|
16
|
+
return input.currentRenderer;
|
|
17
|
+
}
|
|
18
|
+
await ensureIntegrationRuntimeReady({
|
|
19
|
+
appConfig: input.appConfig,
|
|
20
|
+
integrationName,
|
|
21
|
+
runtimeOrigin: input.runtimeOrigin
|
|
22
|
+
});
|
|
23
|
+
const integrationPlugin = input.appConfig.integrations.find((integration) => integration.name === integrationName);
|
|
24
|
+
invariant(!!integrationPlugin, `[ecopages] Integration not found for foreign owner: ${integrationName}`);
|
|
25
|
+
const renderer = integrationPlugin.initializeRenderer({
|
|
26
|
+
rendererModules: input.appConfig.runtime?.rendererModuleContext
|
|
27
|
+
});
|
|
28
|
+
cache.set(integrationName, renderer);
|
|
29
|
+
return renderer;
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
getForeignSubtreeResolutionContextKey,
|
|
33
|
+
getForeignSubtreeTokenPrefix,
|
|
34
|
+
resolveOwningIntegrationRenderer
|
|
35
|
+
};
|