@ecopages/core 0.2.0-alpha.12 → 0.2.0-alpha.14
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/CHANGELOG.md +7 -28
- package/README.md +5 -4
- package/package.json +2 -2
- package/src/adapters/bun/hmr-manager.js +2 -2
- package/src/adapters/node/node-hmr-manager.js +2 -2
- package/src/adapters/node/server-adapter.d.ts +2 -2
- package/src/adapters/node/server-adapter.js +5 -5
- package/src/build/build-adapter.d.ts +7 -6
- package/src/build/build-adapter.js +6 -7
- package/src/eco/eco.js +15 -6
- package/src/eco/eco.utils.d.ts +1 -1
- package/src/eco/eco.utils.js +5 -1
- package/src/hmr/hmr-strategy.d.ts +2 -2
- package/src/integrations/ghtml/ghtml-renderer.d.ts +6 -1
- package/src/integrations/ghtml/ghtml-renderer.js +29 -28
- package/src/plugins/integration-plugin.d.ts +1 -24
- package/src/plugins/integration-plugin.js +0 -14
- package/src/route-renderer/GRAPH.md +54 -84
- package/src/route-renderer/README.md +11 -22
- package/src/route-renderer/orchestration/component-render-context.d.ts +33 -84
- package/src/route-renderer/orchestration/component-render-context.js +30 -108
- package/src/route-renderer/orchestration/integration-renderer.d.ts +219 -96
- package/src/route-renderer/orchestration/integration-renderer.js +416 -236
- package/src/route-renderer/orchestration/queued-boundary-runtime.service.d.ts +93 -0
- package/src/route-renderer/orchestration/queued-boundary-runtime.service.js +155 -0
- package/src/route-renderer/orchestration/render-execution.service.d.ts +8 -71
- package/src/route-renderer/orchestration/render-execution.service.js +28 -115
- package/src/route-renderer/orchestration/render-output.utils.d.ts +6 -0
- package/src/route-renderer/orchestration/render-output.utils.js +25 -0
- package/src/route-renderer/orchestration/render-preparation.service.d.ts +0 -9
- package/src/route-renderer/orchestration/render-preparation.service.js +3 -34
- package/src/route-renderer/page-loading/dependency-resolver.js +6 -1
- package/src/route-renderer/page-loading/page-module-loader.d.ts +1 -2
- package/src/route-renderer/page-loading/page-module-loader.js +0 -2
- package/src/router/client/navigation-coordinator.js +2 -2
- package/src/router/server/fs-router-scanner.js +6 -1
- package/src/services/runtime-state/dev-graph.service.d.ts +5 -5
- package/src/services/runtime-state/dev-graph.service.js +10 -10
- package/src/types/public-types.d.ts +2 -5
- package/src/eco/component-render-context.d.ts +0 -2
- package/src/eco/component-render-context.js +0 -12
- package/src/route-renderer/component-graph/component-graph-executor.d.ts +0 -33
- package/src/route-renderer/component-graph/component-graph-executor.js +0 -30
- package/src/route-renderer/component-graph/component-graph.d.ts +0 -53
- package/src/route-renderer/component-graph/component-graph.js +0 -94
- package/src/route-renderer/component-graph/component-marker.d.ts +0 -52
- package/src/route-renderer/component-graph/component-marker.js +0 -44
- package/src/route-renderer/component-graph/component-reference.d.ts +0 -10
- package/src/route-renderer/component-graph/component-reference.js +0 -34
- package/src/route-renderer/component-graph/marker-graph-resolver.d.ts +0 -79
- package/src/route-renderer/component-graph/marker-graph-resolver.js +0 -117
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Rendering Logic Graph
|
|
2
2
|
|
|
3
|
-
This document maps the end-to-end rendering logic in core, including request-time rendering, explicit route rendering, static generation, and
|
|
3
|
+
This document maps the end-to-end rendering logic in core, including request-time rendering, explicit route rendering, static generation, and deferred boundary orchestration.
|
|
4
4
|
|
|
5
5
|
## Design Principles
|
|
6
6
|
|
|
@@ -12,16 +12,14 @@ These diagrams are based on a few architectural assumptions that seem important
|
|
|
12
12
|
Adapters and route matchers decide which renderer to use; once selected, the integration renderer owns the page render pipeline.
|
|
13
13
|
- **Data resolution should happen before HTML transformation.**
|
|
14
14
|
Static props, metadata, dependency processing, and route assets are all upstream of final HTML injection.
|
|
15
|
-
- **
|
|
16
|
-
The initial integration render
|
|
17
|
-
- **
|
|
18
|
-
|
|
19
|
-
- **The marker pipeline remains generic after emission.**
|
|
20
|
-
Once markers exist, core resolves them generically through marker graph extraction, integration renderer dispatch, asset collection, and HTML replacement. The current built-in React integration is one concrete consumer of that mechanism.
|
|
15
|
+
- **Deferred boundary orchestration should stay renderer-owned.**
|
|
16
|
+
The initial integration render is responsible for handing foreign boundaries back to their owning renderer before final route HTML is returned.
|
|
17
|
+
- **Foreign boundary ownership is renderer-defined behavior.**
|
|
18
|
+
If a renderer cannot resolve a foreign boundary inside its own runtime, route execution now treats any leftover unresolved boundary artifact HTML as an error instead of attempting any route-level fallback.
|
|
21
19
|
- **Caching policy is authoritative at the page layer.**
|
|
22
20
|
Middleware, locals, and response reuse all depend on the effective page cache strategy.
|
|
23
21
|
- **Asset emission should converge into one injection stage.**
|
|
24
|
-
Route-level assets, integration assets, page-root component assets, and
|
|
22
|
+
Route-level assets, integration assets, page-root component assets, and renderer-owned boundary assets all end up in the HTML transformer.
|
|
25
23
|
|
|
26
24
|
## Entry Points
|
|
27
25
|
|
|
@@ -143,7 +141,7 @@ flowchart TD
|
|
|
143
141
|
|
|
144
142
|
### 4.2 Main execute flow via `RenderExecutionService`
|
|
145
143
|
|
|
146
|
-
Important nuance: this phase does not
|
|
144
|
+
Important nuance: this phase does not resolve mixed-integration boundaries itself anymore. Renderer-owned runtimes must finish that work before route finalization. If unresolved boundary artifact HTML survives to this phase, route execution fails fast.
|
|
147
145
|
|
|
148
146
|
```mermaid
|
|
149
147
|
flowchart TD
|
|
@@ -151,19 +149,14 @@ flowchart TD
|
|
|
151
149
|
B --> C[prepareRenderOptions]
|
|
152
150
|
C --> D[runWithComponentRenderContext then render]
|
|
153
151
|
D --> E[normalize response body to renderedHtml]
|
|
154
|
-
E --> F
|
|
155
|
-
F --> G
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
H --> J[
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
K --> L
|
|
162
|
-
L -- Yes --> M[HtmlTransformerService applyAttributesToFirstBodyElement]
|
|
163
|
-
L -- No --> N[leave html unchanged]
|
|
164
|
-
M --> O[htmlTransformer transform]
|
|
165
|
-
N --> O
|
|
166
|
-
O --> P[return body stream and cache strategy]
|
|
152
|
+
E --> F{contains unresolved boundary artifact html?}
|
|
153
|
+
F -- Yes --> G[throw unresolved boundary error]
|
|
154
|
+
F -- No --> H{root attributes attachable?}
|
|
155
|
+
H -- Yes --> I[HtmlTransformerService applyAttributesToFirstBodyElement]
|
|
156
|
+
H -- No --> J[leave html unchanged]
|
|
157
|
+
I --> K[htmlTransformer transform]
|
|
158
|
+
J --> K
|
|
159
|
+
K --> L[return body stream and cache strategy]
|
|
167
160
|
```
|
|
168
161
|
|
|
169
162
|
### 4.3 Render preparation responsibilities
|
|
@@ -189,7 +182,7 @@ flowchart LR
|
|
|
189
182
|
flowchart LR
|
|
190
183
|
A[IntegrationRenderer] --> B[RenderPreparationService]
|
|
191
184
|
A --> C[RenderExecutionService]
|
|
192
|
-
A --> D[
|
|
185
|
+
A --> D[QueuedBoundaryRuntimeService]
|
|
193
186
|
A --> F[PageModuleLoaderService]
|
|
194
187
|
A --> G[DependencyResolverService]
|
|
195
188
|
A --> H[HtmlTransformerService]
|
|
@@ -197,32 +190,32 @@ flowchart LR
|
|
|
197
190
|
B --> F
|
|
198
191
|
B --> G
|
|
199
192
|
B --> H
|
|
200
|
-
C --> D
|
|
201
193
|
C --> H
|
|
194
|
+
D --> H
|
|
202
195
|
```
|
|
203
196
|
|
|
204
|
-
## 5)
|
|
197
|
+
## 5) Boundary Tokens And Renderer-Owned Resolution
|
|
205
198
|
|
|
206
|
-
This part is architecturally interesting because
|
|
199
|
+
This part is architecturally interesting because boundaries can still emit temporary transport tokens, but renderer-owned runtimes are now responsible for resolving foreign descendants before final route HTML is returned.
|
|
207
200
|
|
|
208
201
|
If this feels complex, the simplest mental model is:
|
|
209
202
|
|
|
210
203
|
- first pass: render everything that can be rendered safely right now
|
|
211
|
-
- when a
|
|
212
|
-
-
|
|
213
|
-
- final pass: merge
|
|
204
|
+
- when a renderer supports mixed boundaries, hand foreign descendants back to the owning renderer inside that renderer's runtime
|
|
205
|
+
- if literal `<eco-marker>` boundary artifact HTML survives to route finalization, treat it as a failure instead of attempting any route-level fallback
|
|
206
|
+
- final pass: merge emitted assets and perform the normal HTML transformation
|
|
214
207
|
|
|
215
|
-
In the current implementation,
|
|
208
|
+
In the current implementation, renderer-owned runtimes use internal boundary tokens for queued nested handoff. Literal `<eco-marker>` markup remains only as a route-level failure signal when unresolved boundary artifacts escape renderer-owned resolution.
|
|
216
209
|
|
|
217
|
-
Important clarification: not every integration automatically goes through this stage.
|
|
210
|
+
Important clarification: not every integration automatically goes through this stage. Boundary queueing is conditional.
|
|
218
211
|
|
|
219
|
-
- If
|
|
220
|
-
- If
|
|
221
|
-
-
|
|
212
|
+
- If a render pass stays inside one integration, rendering continues directly to post-processing and HTML transformation.
|
|
213
|
+
- If a renderer can resolve foreign descendants inline, the boundary runtime returns resolved HTML immediately.
|
|
214
|
+
- If a renderer needs token-based nested handoff, it queues renderer-owned transport tokens and resolves them before returning final HTML.
|
|
222
215
|
|
|
223
216
|
### Why this exists
|
|
224
217
|
|
|
225
|
-
|
|
218
|
+
Renderer-owned boundary queueing exists because some component boundaries cannot always be rendered eagerly inside the current integration pass.
|
|
226
219
|
|
|
227
220
|
Typical reasons include:
|
|
228
221
|
|
|
@@ -231,62 +224,45 @@ Typical reasons include:
|
|
|
231
224
|
- the parent render needs to preserve ordering and slots before the child subtree is resolved
|
|
232
225
|
- the child render may emit its own assets or root attributes that must be merged back into the final document
|
|
233
226
|
|
|
234
|
-
So the first pass
|
|
235
|
-
|
|
236
|
-
Responsibility split:
|
|
237
|
-
|
|
238
|
-
- core resolves the deferred marker mechanically: graph shape, refs, slot relationships, and target renderer lookup
|
|
239
|
-
- the selected integration renderer resolves the actual component render once it receives `component`, `props`, and optional `children`
|
|
227
|
+
So the first pass either returns resolved renderer-owned output immediately or emits a renderer-local transport token that is resolved before the enclosing renderer returns its final HTML.
|
|
240
228
|
|
|
241
229
|
Another way to say it:
|
|
242
230
|
|
|
243
|
-
- a
|
|
244
|
-
- the
|
|
245
|
-
- the
|
|
231
|
+
- a boundary token says "this subtree belongs to another renderer, but the current renderer still owns the overall render pass"
|
|
232
|
+
- the token stores just enough information to make that later renderer-owned handoff deterministic
|
|
233
|
+
- the queue exists so nested foreign boundaries resolve from leaves to parents while preserving child insertion order and emitted assets
|
|
246
234
|
|
|
247
|
-
### 5.1
|
|
235
|
+
### 5.1 Boundary interception in `eco.component` factory
|
|
248
236
|
|
|
249
|
-
The key rule here today is:
|
|
237
|
+
The key rule here today is: boundaries are resolved by the owning renderer, not by a shared core fallback. During an active component render pass, `eco.component` asks the current render boundary context whether the next boundary should render inline or be resolved by a foreign renderer runtime.
|
|
250
238
|
|
|
251
|
-
For the current built-in integrations, this is how non-
|
|
239
|
+
For the current built-in integrations, this is how non-owning renderers hand foreign subtrees back to the owning runtime without relying on a shared core fallback.
|
|
252
240
|
|
|
253
241
|
```mermaid
|
|
254
242
|
flowchart TD
|
|
255
243
|
A[eco component render] --> B[getComponentRenderContext]
|
|
256
|
-
B --> C[
|
|
257
|
-
C --> D{
|
|
258
|
-
D -- No --> E[render component content
|
|
259
|
-
D -- Yes --> F[
|
|
260
|
-
F --> G[store props in propsByRef]
|
|
261
|
-
G --> H{children include eco-marker tokens?}
|
|
262
|
-
H -- Yes --> I[create slotRef and slotChildrenByRef links]
|
|
263
|
-
H -- No --> J[no slot links]
|
|
264
|
-
I --> K[createComponentMarker]
|
|
265
|
-
J --> K
|
|
266
|
-
K --> L[return eco marker token]
|
|
244
|
+
B --> C[boundaryRuntime interceptBoundarySync]
|
|
245
|
+
C --> D{resolved foreign boundary?}
|
|
246
|
+
D -- No --> E[render component content inline]
|
|
247
|
+
D -- Yes --> F[return renderer-owned resolved html]
|
|
267
248
|
```
|
|
268
249
|
|
|
269
|
-
### 5.2
|
|
250
|
+
### 5.2 Queued boundary execution
|
|
270
251
|
|
|
271
|
-
|
|
252
|
+
When string-first renderers queue foreign boundaries, the base renderer helper resolves queued boundary tokens directly against the shared queue service. That pass is intentionally narrow: it only resolves queued boundary tokens that the owning renderer emitted as transport artifacts for that string runtime.
|
|
272
253
|
|
|
273
|
-
This means
|
|
254
|
+
This means boundary tokens are no longer a general component-boundary contract. Core only resolves queued boundary payloads that already belong to a renderer-owned string boundary workflow.
|
|
274
255
|
|
|
275
256
|
```mermaid
|
|
276
257
|
flowchart TD
|
|
277
|
-
A[
|
|
278
|
-
B --> C[
|
|
279
|
-
C --> D[
|
|
280
|
-
D --> E[
|
|
281
|
-
E --> F[
|
|
282
|
-
F --> G[
|
|
283
|
-
G --> H[
|
|
284
|
-
H --> I[
|
|
285
|
-
I --> J[renderer.renderComponent]
|
|
286
|
-
J --> K[collect component assets]
|
|
287
|
-
K --> L[apply root attributes to first element]
|
|
288
|
-
L --> M[replace marker token in HTML]
|
|
289
|
-
M --> N[resolved html and assets]
|
|
258
|
+
A[string boundary runtime html] --> B[find queued boundary tokens]
|
|
259
|
+
B --> C[resolve nested child tokens first]
|
|
260
|
+
C --> D[dispatch boundary to owning renderer]
|
|
261
|
+
D --> E[renderer.renderComponentBoundary]
|
|
262
|
+
E --> F[collect emitted assets]
|
|
263
|
+
F --> G[apply root attributes to first element]
|
|
264
|
+
G --> H[replace queued token in html]
|
|
265
|
+
H --> I[resolved html and merged assets]
|
|
290
266
|
```
|
|
291
267
|
|
|
292
268
|
## 6) Explicit Rendering Paths (outside FS page matching)
|
|
@@ -345,15 +321,12 @@ For someone new to the rendering system, this is probably the most useful order
|
|
|
345
321
|
6. `integration-renderer.ts`
|
|
346
322
|
7. `render-preparation.service.ts`
|
|
347
323
|
8. `render-execution.service.ts`
|
|
348
|
-
9. `
|
|
324
|
+
9. `queued-boundary-runtime.service.ts`
|
|
349
325
|
10. `html-transformer.service.ts`
|
|
350
326
|
11. `page-module-loader.ts`
|
|
351
327
|
12. `dependency-resolver.ts`
|
|
352
|
-
13. `
|
|
353
|
-
14. `component-
|
|
354
|
-
15. `component-graph-executor.ts`
|
|
355
|
-
16. `eco.ts`
|
|
356
|
-
17. `component-render-context.ts`
|
|
328
|
+
13. `eco.ts`
|
|
329
|
+
14. `component-render-context.ts`
|
|
357
330
|
|
|
358
331
|
## 9) Key Files
|
|
359
332
|
|
|
@@ -368,10 +341,7 @@ For someone new to the rendering system, this is probably the most useful order
|
|
|
368
341
|
- `packages/core/src/route-renderer/orchestration/integration-renderer.ts`
|
|
369
342
|
- `packages/core/src/route-renderer/orchestration/render-preparation.service.ts`
|
|
370
343
|
- `packages/core/src/route-renderer/orchestration/render-execution.service.ts`
|
|
371
|
-
- `packages/core/src/route-renderer/
|
|
372
|
-
- `packages/core/src/route-renderer/component-graph/component-marker.ts`
|
|
373
|
-
- `packages/core/src/route-renderer/component-graph/component-graph.ts`
|
|
374
|
-
- `packages/core/src/route-renderer/component-graph/component-graph-executor.ts`
|
|
344
|
+
- `packages/core/src/route-renderer/orchestration/queued-boundary-runtime.service.ts`
|
|
375
345
|
- `packages/core/src/route-renderer/page-loading/page-module-loader.ts`
|
|
376
346
|
- `packages/core/src/route-renderer/page-loading/dependency-resolver.ts`
|
|
377
347
|
- `packages/core/src/services/module-loading/page-module-import.service.ts`
|
|
@@ -25,23 +25,18 @@ Framework-owned orchestration services and renderer base class:
|
|
|
25
25
|
|
|
26
26
|
- `integration-renderer.ts`: abstract base class that coordinates end-to-end route rendering.
|
|
27
27
|
- `render-preparation.service.ts`: page module/data/dependency preparation before render.
|
|
28
|
-
- `render-execution.service.ts`: render capture,
|
|
28
|
+
- `render-execution.service.ts`: render capture, unresolved boundary artifact enforcement, and finalization.
|
|
29
|
+
- `queued-boundary-runtime.service.ts`: shared queued foreign-boundary runtime used directly by renderer-owned helpers, including string-first renderers.
|
|
29
30
|
|
|
30
31
|
It also provides:
|
|
31
32
|
|
|
32
33
|
- `renderToResponse()` contract for explicit-route rendering.
|
|
33
34
|
- `renderComponent()` contract for component-level orchestration and artifact reporting.
|
|
34
|
-
-
|
|
35
|
+
- deferred boundary resolution for nested cross-integration component boundaries.
|
|
35
36
|
|
|
36
|
-
###
|
|
37
|
+
### Boundary Tokens
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- `createComponentMarker()` for canonical `<eco-marker ...></eco-marker>` generation.
|
|
41
|
-
- `parseComponentMarkers()` for marker extraction from rendered HTML.
|
|
42
|
-
- node collection by marker id.
|
|
43
|
-
- parent/child edges from slot reference registry.
|
|
44
|
-
- topological levels for bottom-up execution.
|
|
39
|
+
Renderer-owned runtimes may emit internal boundary tokens while they resolve foreign descendants before returning final HTML. If literal `<eco-marker ...></eco-marker>` markup survives to route finalization, it is treated as an unresolved boundary artifact rather than a normal transport mechanism.
|
|
45
40
|
|
|
46
41
|
### `page-loading/`
|
|
47
42
|
|
|
@@ -61,7 +56,7 @@ Builds processed assets from component dependency declarations:
|
|
|
61
56
|
|
|
62
57
|
Default behavior:
|
|
63
58
|
|
|
64
|
-
-
|
|
59
|
+
- renderer-owned component-boundary orchestration + component render artifacts.
|
|
65
60
|
- global lazy trigger map + global injector bootstrap.
|
|
66
61
|
|
|
67
62
|
Global injector lifecycle notes:
|
|
@@ -87,15 +82,10 @@ Current base orchestration behavior:
|
|
|
87
82
|
- Merges returned `assets` into processed dependencies.
|
|
88
83
|
- Applies returned `rootAttributes` to the first element under `<body>`.
|
|
89
84
|
|
|
90
|
-
When rendered output contains
|
|
85
|
+
When rendered output still contains unresolved boundary artifact HTML:
|
|
91
86
|
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
- builds marker graph using `componentGraphContext` (`propsByRef`, `slotChildrenByRef`) from integration-specific page module exports, including nested deferred child markers captured inside serialized `children` props.
|
|
95
|
-
- resolves markers bottom-up through integration-specific `renderComponent()` calls.
|
|
96
|
-
- core decodes markers and selects the target renderer; the integration renderer only performs the reconstructed component render.
|
|
97
|
-
- fails fast when marker component refs or props refs are missing.
|
|
98
|
-
- merges marker-rendered assets back into the dependency pipeline with deduplication.
|
|
87
|
+
- route execution now fails fast instead of attempting any route-level unresolved-boundary fallback.
|
|
88
|
+
- renderer-owned boundary runtimes are responsible for resolving foreign nested components before final route HTML is returned.
|
|
99
89
|
|
|
100
90
|
This enables island-style hydration assets (for example React/Lit/Kita integration outputs) to be emitted through the normal dependency injection pipeline.
|
|
101
91
|
|
|
@@ -122,6 +112,5 @@ This enables island-style hydration assets (for example React/Lit/Kita integrati
|
|
|
122
112
|
|
|
123
113
|
If you are reading this file to understand today's contract, you can stop at the output pipeline above. The items below describe areas still evolving rather than required behavior.
|
|
124
114
|
|
|
125
|
-
- Deep multi-level
|
|
126
|
-
-
|
|
127
|
-
- Graph execution still resolves nodes one boundary at a time; batching by integration per level remains a possible follow-up if repeated renderer calls become a measurable cost.
|
|
115
|
+
- Deep multi-level mixed-integration trees now rely on renderer-owned boundary runtimes rather than a shared post-render graph resolver.
|
|
116
|
+
- Each renderer still decides how to hand off foreign boundaries, so specialized runtimes remain appropriate where child serialization or hydration contracts differ.
|
|
@@ -1,99 +1,52 @@
|
|
|
1
1
|
import type { EcoComponent } from '../../types/public-types.js';
|
|
2
|
-
import type { MarkerNodeId } from '../component-graph/component-marker.js';
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
3
|
+
* Result returned by a renderer-owned boundary runtime.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
5
|
+
* `inline` keeps rendering inside the current integration. `resolved` returns a
|
|
6
|
+
* renderer-owned value immediately, which can be final HTML or a renderer-local
|
|
7
|
+
* transport token for later queue resolution.
|
|
8
8
|
*/
|
|
9
|
-
export type
|
|
9
|
+
export type ComponentBoundaryInterceptionResult = {
|
|
10
|
+
kind: 'inline';
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'resolved';
|
|
13
|
+
value: unknown;
|
|
14
|
+
};
|
|
10
15
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* This keeps `eco.component()` decoupled from concrete integration/plugin
|
|
14
|
-
* objects while still giving policy enough information to decide whether the
|
|
15
|
-
* boundary should render immediately or be deferred.
|
|
16
|
+
* Boundary metadata passed into the active renderer-owned runtime.
|
|
16
17
|
*/
|
|
17
|
-
export type
|
|
18
|
+
export type ComponentBoundaryInterceptionInput = {
|
|
18
19
|
currentIntegration: string;
|
|
19
20
|
targetIntegration?: string;
|
|
20
21
|
component: EcoComponent;
|
|
22
|
+
props: Record<string, unknown>;
|
|
21
23
|
};
|
|
22
24
|
/**
|
|
23
|
-
* Narrow
|
|
24
|
-
*
|
|
25
|
-
* The boundary context is intentionally small so component rendering can remain
|
|
26
|
-
* unaware of integration registries, plugin instances, or renderer lifecycles.
|
|
27
|
-
*/
|
|
28
|
-
export type ComponentRenderBoundaryContext = {
|
|
29
|
-
/**
|
|
30
|
-
* Decides whether the next component boundary should render inline or defer to
|
|
31
|
-
* the marker graph stage.
|
|
32
|
-
*
|
|
33
|
-
* @param input Boundary metadata for the current render pass.
|
|
34
|
-
* @returns Boundary rendering mode for the target component.
|
|
35
|
-
*/
|
|
36
|
-
decideBoundaryRender(input: BoundaryRenderDecisionInput): BoundaryRenderMode;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* Integration-owned hook for serializing framework-specific deferred child payloads.
|
|
40
|
-
*
|
|
41
|
-
* Core handles primitive values, generic template transport shapes, and node-like
|
|
42
|
-
* objects directly. Integrations can provide this callback to teach the boundary
|
|
43
|
-
* runtime about richer payloads such as framework template sentinels that should
|
|
44
|
-
* survive marker deferral as HTML rather than as opaque objects.
|
|
45
|
-
*
|
|
46
|
-
* Returning `undefined` tells core that the value is not recognized by the
|
|
47
|
-
* integration-specific serializer.
|
|
48
|
-
*/
|
|
49
|
-
type DeferredValueSerializer = (value: unknown, serializeValue: (value: unknown) => string | undefined) => string | undefined;
|
|
50
|
-
/**
|
|
51
|
-
* Minimal boundary payload needed to emit one deferred marker.
|
|
25
|
+
* Narrow renderer-owned boundary runtime injected into one active render
|
|
26
|
+
* context.
|
|
52
27
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* current integration's render stack.
|
|
28
|
+
* Integrations implement this contract when foreign boundaries must be handed
|
|
29
|
+
* off inside the renderer instead of being left for route-level reconciliation.
|
|
56
30
|
*/
|
|
57
|
-
|
|
31
|
+
export interface ComponentBoundaryRuntime {
|
|
32
|
+
interceptBoundary?(input: ComponentBoundaryInterceptionInput): ComponentBoundaryInterceptionResult | Promise<ComponentBoundaryInterceptionResult>;
|
|
33
|
+
interceptBoundarySync?(input: ComponentBoundaryInterceptionInput): ComponentBoundaryInterceptionResult;
|
|
34
|
+
}
|
|
35
|
+
type ComponentBoundaryRenderInput = {
|
|
58
36
|
component: EcoComponent;
|
|
59
37
|
props: Record<string, unknown>;
|
|
60
38
|
targetIntegration?: string;
|
|
61
39
|
};
|
|
62
40
|
/**
|
|
63
|
-
* Per-render mutable state used while
|
|
64
|
-
*
|
|
65
|
-
* Counters generate deterministic ids within one render execution.
|
|
41
|
+
* Per-render mutable state used while applying boundary interception and lazy
|
|
42
|
+
* output wrapping.
|
|
66
43
|
*/
|
|
67
44
|
export type ComponentRenderContext = {
|
|
68
45
|
currentIntegration: string;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
serializeDeferredValue?: DeferredValueSerializer;
|
|
72
|
-
/** Monotonic counter for stable marker node ids within one render pass. */
|
|
73
|
-
nextNodeId: number;
|
|
74
|
-
/** Monotonic counter for stable props references within one render pass. */
|
|
75
|
-
nextPropsRefId: number;
|
|
76
|
-
/** Monotonic counter for stable slot references within one render pass. */
|
|
77
|
-
nextSlotRefId: number;
|
|
78
|
-
/** Captured props for deferred boundaries, keyed by `propsRef`. */
|
|
79
|
-
propsByRef: Record<string, Record<string, unknown>>;
|
|
80
|
-
/** Nested child marker ids keyed by the parent boundary slot reference. */
|
|
81
|
-
slotChildrenByRef: Record<string, MarkerNodeId[]>;
|
|
82
|
-
tryRenderDeferredBoundary<E>(input: DeferredBoundaryRenderInput): E | undefined;
|
|
46
|
+
boundaryRuntime?: ComponentBoundaryRuntime;
|
|
47
|
+
interceptBoundary(input: ComponentBoundaryRenderInput): Promise<unknown | undefined> | unknown | undefined;
|
|
83
48
|
finalizeComponentRender<T>(component: EcoComponent, content: T): T;
|
|
84
49
|
};
|
|
85
|
-
/**
|
|
86
|
-
* Serializable graph context captured from one render execution.
|
|
87
|
-
*
|
|
88
|
-
* This payload is merged with explicit page-module graph context before marker
|
|
89
|
-
* resolution in the route renderer.
|
|
90
|
-
*/
|
|
91
|
-
export type ComponentGraphContext = {
|
|
92
|
-
/** Deferred boundary props keyed by marker `propsRef`. */
|
|
93
|
-
propsByRef: Record<string, Record<string, unknown>>;
|
|
94
|
-
/** Nested child marker ids keyed by marker `slotRef`. */
|
|
95
|
-
slotChildrenByRef: Record<string, MarkerNodeId[]>;
|
|
96
|
-
};
|
|
97
50
|
/**
|
|
98
51
|
* Returns the current component render context, if one is active.
|
|
99
52
|
*
|
|
@@ -101,12 +54,11 @@ export type ComponentGraphContext = {
|
|
|
101
54
|
*/
|
|
102
55
|
export declare function getComponentRenderContext(): ComponentRenderContext | undefined;
|
|
103
56
|
/**
|
|
104
|
-
*
|
|
57
|
+
* Runs boundary interception for one component boundary.
|
|
105
58
|
*
|
|
106
|
-
*
|
|
107
|
-
* lets the caller render inline instead.
|
|
59
|
+
* The active runtime may resolve the boundary immediately or keep it inline.
|
|
108
60
|
*/
|
|
109
|
-
export declare function
|
|
61
|
+
export declare function interceptComponentBoundary(input: ComponentBoundaryRenderInput): Promise<unknown | undefined> | unknown | undefined;
|
|
110
62
|
/**
|
|
111
63
|
* Applies lazy trigger or injector wrapping to completed component output.
|
|
112
64
|
*
|
|
@@ -115,20 +67,17 @@ export declare function tryRenderDeferredBoundary<E>(input: DeferredBoundaryRend
|
|
|
115
67
|
*/
|
|
116
68
|
export declare function finalizeComponentRender<T>(component: EcoComponent, content: T): T;
|
|
117
69
|
/**
|
|
118
|
-
* Runs render work under a fresh component render context and returns
|
|
119
|
-
*
|
|
120
|
-
* - captured graph reference maps for downstream marker resolution
|
|
70
|
+
* Runs render work under a fresh component render context and returns the
|
|
71
|
+
* resulting value.
|
|
121
72
|
*
|
|
122
73
|
* @param input Execution metadata for current integration and boundary policy.
|
|
123
74
|
* @param render Async render function to execute inside the context.
|
|
124
|
-
* @returns Render result
|
|
75
|
+
* @returns Render result value.
|
|
125
76
|
*/
|
|
126
77
|
export declare function runWithComponentRenderContext<T>(input: {
|
|
127
78
|
currentIntegration: string;
|
|
128
|
-
|
|
129
|
-
serializeDeferredValue?: DeferredValueSerializer;
|
|
79
|
+
boundaryRuntime?: ComponentBoundaryRuntime;
|
|
130
80
|
}, render: () => Promise<T>): Promise<{
|
|
131
81
|
value: T;
|
|
132
|
-
graphContext: ComponentGraphContext;
|
|
133
82
|
}>;
|
|
134
83
|
export {};
|