@ecopages/core 0.2.0-alpha.25 → 0.2.0-alpha.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.
Files changed (111) hide show
  1. package/README.md +63 -7
  2. package/package.json +4 -47
  3. package/src/adapters/bun/create-app.ts +54 -2
  4. package/src/adapters/bun/hmr-manager.test.ts +0 -2
  5. package/src/adapters/bun/hmr-manager.ts +1 -24
  6. package/src/adapters/bun/server-adapter.ts +30 -4
  7. package/src/adapters/node/node-hmr-manager.test.ts +0 -2
  8. package/src/adapters/node/node-hmr-manager.ts +2 -25
  9. package/src/adapters/shared/explicit-static-render-preparation.ts +58 -0
  10. package/src/adapters/shared/explicit-static-route-matcher.test.ts +6 -6
  11. package/src/adapters/shared/explicit-static-route-matcher.ts +22 -31
  12. package/src/adapters/shared/file-route-middleware-pipeline.test.ts +5 -10
  13. package/src/adapters/shared/file-route-middleware-pipeline.ts +8 -17
  14. package/src/adapters/shared/fs-server-response-factory.test.ts +32 -43
  15. package/src/adapters/shared/fs-server-response-factory.ts +15 -37
  16. package/src/adapters/shared/fs-server-response-matcher.test.ts +65 -39
  17. package/src/adapters/shared/fs-server-response-matcher.ts +94 -43
  18. package/src/adapters/shared/hmr-manager.contract.test.ts +0 -4
  19. package/src/adapters/shared/render-context.ts +3 -3
  20. package/src/adapters/shared/server-adapter.test.ts +53 -0
  21. package/src/adapters/shared/server-adapter.ts +228 -159
  22. package/src/adapters/shared/server-route-handler.test.ts +6 -5
  23. package/src/adapters/shared/server-route-handler.ts +4 -4
  24. package/src/adapters/shared/server-static-builder.test.ts +4 -4
  25. package/src/adapters/shared/server-static-builder.ts +4 -4
  26. package/src/config/README.md +1 -1
  27. package/src/config/config-builder.test.ts +0 -1
  28. package/src/config/config-builder.ts +2 -7
  29. package/src/dev/host-runtime.ts +34 -0
  30. package/src/eco/eco.browser.test.ts +2 -2
  31. package/src/eco/eco.browser.ts +2 -2
  32. package/src/eco/eco.test.ts +6 -6
  33. package/src/eco/eco.ts +12 -12
  34. package/src/eco/eco.types.ts +3 -3
  35. package/src/errors/index.ts +1 -0
  36. package/src/hmr/client/hmr-runtime.ts +4 -2
  37. package/src/hmr/strategies/js-hmr-strategy.test.ts +0 -1
  38. package/src/hmr/strategies/js-hmr-strategy.ts +0 -6
  39. package/src/integrations/ghtml/ghtml-renderer.test.ts +7 -7
  40. package/src/integrations/ghtml/ghtml-renderer.ts +1 -11
  41. package/src/plugins/eco-component-meta-plugin.ts +0 -1
  42. package/src/plugins/integration-plugin.test.ts +9 -14
  43. package/src/plugins/integration-plugin.ts +34 -22
  44. package/src/plugins/processor.ts +17 -0
  45. package/src/route-renderer/GRAPH.md +81 -289
  46. package/src/route-renderer/README.md +67 -105
  47. package/src/route-renderer/orchestration/component-render-context.ts +45 -38
  48. package/src/route-renderer/orchestration/declared-ownership-graph.ts +62 -0
  49. package/src/route-renderer/orchestration/foreign-subtree-execution.service.ts +383 -0
  50. package/src/route-renderer/orchestration/integration-renderer.test.ts +118 -121
  51. package/src/route-renderer/orchestration/integration-renderer.ts +362 -403
  52. package/src/route-renderer/orchestration/ownership-planning.service.ts +97 -0
  53. package/src/route-renderer/orchestration/ownership-validation.service.ts +76 -0
  54. package/src/route-renderer/orchestration/processed-asset-dedupe.ts +1 -1
  55. package/src/route-renderer/orchestration/{queued-boundary-runtime.service.test.ts → queued-foreign-subtree-resolution.service.test.ts} +76 -71
  56. package/src/route-renderer/orchestration/{queued-boundary-runtime.service.ts → queued-foreign-subtree-resolution.service.ts} +68 -63
  57. package/src/route-renderer/orchestration/render-output.utils.ts +21 -13
  58. package/src/route-renderer/orchestration/{render-preparation.service.test.ts → route-render-orchestrator.prepare-render-options.test.ts} +160 -85
  59. package/src/route-renderer/orchestration/route-render-orchestrator.test.ts +265 -0
  60. package/src/route-renderer/orchestration/{render-preparation.service.ts → route-render-orchestrator.ts} +244 -160
  61. package/src/route-renderer/page-loading/component-dependency-collection.ts +9 -3
  62. package/src/route-renderer/page-loading/declared-asset-collection.ts +2 -5
  63. package/src/route-renderer/page-loading/dependency-resolver.test.ts +107 -11
  64. package/src/route-renderer/page-loading/dependency-resolver.ts +6 -12
  65. package/src/route-renderer/page-loading/ecopages-virtual-imports.ts +1 -1
  66. package/src/route-renderer/page-loading/lazy-entry-collection.ts +1 -1
  67. package/src/route-renderer/page-loading/lazy-trigger-planning.ts +1 -1
  68. package/src/route-renderer/page-loading/module-declaration-aggregation.ts +1 -1
  69. package/src/route-renderer/page-loading/module-declaration-scripts.ts +1 -1
  70. package/src/route-renderer/page-loading/page-dependency-bundling.ts +105 -66
  71. package/src/route-renderer/route-renderer.ts +28 -31
  72. package/src/router/README.md +16 -19
  73. package/src/router/server/route-registry.test.ts +176 -0
  74. package/src/router/server/route-registry.ts +382 -0
  75. package/src/services/README.md +1 -2
  76. package/src/services/assets/asset-processing-service/asset-dependency-keys.ts +1 -1
  77. package/src/services/assets/asset-processing-service/asset-processing.service.test.ts +1 -4
  78. package/src/services/assets/asset-processing-service/asset-processing.service.ts +1 -2
  79. package/src/services/assets/asset-processing-service/assets.types.ts +3 -0
  80. package/src/services/assets/asset-processing-service/grouped-content-bundles.ts +1 -1
  81. package/src/services/assets/asset-processing-service/index.ts +1 -0
  82. package/src/{route-renderer/orchestration/page-packaging.service.test.ts → services/assets/asset-processing-service/page-package.test.ts} +38 -14
  83. package/src/services/assets/asset-processing-service/page-package.ts +93 -0
  84. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.ts +4 -5
  85. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.test.ts +13 -10
  86. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.ts +3 -0
  87. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.ts +6 -0
  88. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.ts +2 -0
  89. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +1 -0
  90. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +2 -0
  91. package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.ts +1 -1
  92. package/src/services/html/html-transformer.service.test.ts +1 -4
  93. package/src/services/module-loading/app-server-module-transpiler.service.ts +1 -3
  94. package/src/services/module-loading/node-bootstrap-plugin.ts +17 -3
  95. package/src/services/module-loading/page-module-import.service.ts +0 -1
  96. package/src/services/module-loading/source-module-support.ts +1 -1
  97. package/src/static-site-generator/static-site-generator.test.ts +124 -32
  98. package/src/static-site-generator/static-site-generator.ts +168 -185
  99. package/src/types/internal-types.ts +13 -12
  100. package/src/types/public-types.ts +55 -39
  101. package/src/watchers/project-watcher.test-helpers.ts +4 -3
  102. package/src/route-renderer/orchestration/boundary-planning.service.ts +0 -146
  103. package/src/route-renderer/orchestration/page-packaging.service.ts +0 -85
  104. package/src/route-renderer/orchestration/render-execution.service.test.ts +0 -196
  105. package/src/route-renderer/orchestration/render-execution.service.ts +0 -182
  106. package/src/route-renderer/orchestration/route-shell-composer.service.ts +0 -162
  107. package/src/router/server/fs-router-scanner.test.ts +0 -83
  108. package/src/router/server/fs-router-scanner.ts +0 -224
  109. package/src/router/server/fs-router.test.ts +0 -214
  110. package/src/router/server/fs-router.ts +0 -122
  111. package/src/services/runtime-state/runtime-specifier-registry.service.ts +0 -96
@@ -2,20 +2,22 @@ import { describe, expect, it, vi } from 'vitest';
2
2
  import { eco } from '../../eco/eco.ts';
3
3
  import type { EcoPagesAppConfig } from '../../types/internal-types.ts';
4
4
  import type {
5
- BoundaryPlan,
5
+ OwnershipPlan,
6
6
  EcoComponent,
7
7
  EcoPageComponent,
8
8
  HtmlTemplateProps,
9
+ PageMetadataProps,
9
10
  RouteRendererOptions,
10
11
  } from '../../types/public-types.ts';
11
12
  import { LocalsAccessError } from '../../errors/locals-access-error.ts';
12
- import { BoundaryPlanningService } from './boundary-planning.service.ts';
13
+ import { OwnershipPlanningService } from './ownership-planning.service.ts';
13
14
  import type {
14
15
  AssetDefinition,
15
16
  AssetProcessingService,
16
17
  ProcessedAsset,
17
18
  } from '../../services/assets/asset-processing-service/index.ts';
18
- import { RenderPreparationService } from './render-preparation.service.ts';
19
+ import { OwnershipValidationService } from './ownership-validation.service.ts';
20
+ import { type RouteRenderOrchestratorAdapter, RouteRenderOrchestrator } from './route-render-orchestrator.ts';
19
21
 
20
22
  declare module '../../types/public-types.ts' {
21
23
  interface RequestLocals {
@@ -24,7 +26,81 @@ declare module '../../types/public-types.ts' {
24
26
  }
25
27
  }
26
28
 
27
- describe('RenderPreparationService', () => {
29
+ function createFlowAdapter<C>(input: {
30
+ resolvePageModule: (file: string) => Promise<{
31
+ Page: EcoPageComponent<any> | EcoComponent;
32
+ getStaticProps?: unknown;
33
+ getMetadata?: unknown;
34
+ integrationSpecificProps: Record<string, unknown>;
35
+ }>;
36
+ getHtmlTemplate: () => Promise<EcoComponent<HtmlTemplateProps>>;
37
+ resolvePageData: (
38
+ pageModule: {
39
+ getStaticProps?: unknown;
40
+ getMetadata?: unknown;
41
+ },
42
+ routeOptions: RouteRendererOptions,
43
+ ) => Promise<{ props: Record<string, unknown>; metadata: PageMetadataProps }>;
44
+ resolveDependencies: (components: (EcoComponent | Partial<EcoComponent>)[]) => Promise<ProcessedAsset[]>;
45
+ buildPageBrowserGraph: (file: string) => Promise<{ assets: ProcessedAsset[] } | undefined>;
46
+ shouldRenderPageComponent: (input: {
47
+ Page: EcoComponent;
48
+ Layout?: EcoComponent;
49
+ options: RouteRendererOptions;
50
+ }) => boolean;
51
+ renderPageComponent: (input: {
52
+ Page: EcoComponent;
53
+ Layout?: EcoComponent;
54
+ props: Record<string, unknown>;
55
+ routeOptions: RouteRendererOptions;
56
+ }) => Promise<any>;
57
+ }): RouteRenderOrchestratorAdapter<C> {
58
+ return {
59
+ name: 'ghtml',
60
+ resolveRouteRenderInputs: async (routeOptions) => {
61
+ const pageModule = await input.resolvePageModule(routeOptions.file);
62
+ const HtmlTemplate = await input.getHtmlTemplate();
63
+ const Layout = pageModule.Page.config?.layout;
64
+ const { props, metadata } = await input.resolvePageData(pageModule, routeOptions);
65
+
66
+ return {
67
+ Page: pageModule.Page,
68
+ HtmlTemplate,
69
+ Layout,
70
+ props,
71
+ metadata,
72
+ integrationSpecificProps: pageModule.integrationSpecificProps,
73
+ shouldRenderPageComponent: input.shouldRenderPageComponent({
74
+ Page: pageModule.Page as EcoComponent,
75
+ Layout,
76
+ options: routeOptions,
77
+ }),
78
+ };
79
+ },
80
+ resolveRouteAssets: async ({ routeOptions, components }) => ({
81
+ resolvedDependencies: await input.resolveDependencies(components),
82
+ pageBrowserGraph: await input.buildPageBrowserGraph(routeOptions.file),
83
+ }),
84
+ resolveRoutePageComponentRender: async (renderInput) => {
85
+ if (
86
+ !input.shouldRenderPageComponent({
87
+ Page: renderInput.Page,
88
+ Layout: renderInput.Layout,
89
+ options: renderInput.routeOptions,
90
+ })
91
+ ) {
92
+ return undefined;
93
+ }
94
+
95
+ return await input.renderPageComponent(renderInput);
96
+ },
97
+ renderRouteBody: async () => '',
98
+ getRouteHtmlFinalization: () => ({}),
99
+ transformRouteResponse: async (response) => await response.text(),
100
+ };
101
+ }
102
+
103
+ describe('RouteRenderOrchestrator prepareRenderOptions', () => {
28
104
  it('should prepare dynamic render options and merge renderer-owned assets', async () => {
29
105
  const integrationDependency = {
30
106
  kind: 'script',
@@ -59,7 +135,7 @@ describe('RenderPreparationService', () => {
59
135
  },
60
136
  ],
61
137
  } as unknown as EcoPagesAppConfig;
62
- const service = new RenderPreparationService(appConfig, assetProcessingService);
138
+ const flow = new RouteRenderOrchestrator(appConfig, assetProcessingService);
63
139
  const HtmlTemplate = (() => '<html></html>') as EcoComponent<HtmlTemplateProps>;
64
140
  const Nested = (() => '<aside>Nested</aside>') as EcoComponent<Record<string, unknown>>;
65
141
  Nested.config = {
@@ -79,27 +155,30 @@ describe('RenderPreparationService', () => {
79
155
  query: { preview: '1' },
80
156
  locals: { user: 'andee' },
81
157
  } as unknown as RouteRendererOptions;
82
- const result = await service.prepare(routeOptions, 'ghtml', {
83
- resolvePageModule: async () => ({
84
- Page,
85
- integrationSpecificProps: { layoutMode: 'full' },
86
- }),
87
- getHtmlTemplate: async () => HtmlTemplate,
88
- resolvePageData: async () => ({
89
- props: { title: 'Hello' },
90
- metadata: { title: 'Hello', description: 'Hello description' },
91
- }),
92
- resolveDependencies: async () => [resolvedDependency],
93
- buildRouteRenderAssets: async () => [pageDependency],
94
- shouldRenderPageComponent: () => true,
95
- renderPageComponent: async () => ({
96
- html: '<main>Page</main>',
97
- canAttachAttributes: true,
98
- rootTag: 'main',
99
- integrationName: 'ghtml',
100
- assets: [componentAsset],
158
+ const result = await flow.prepareRenderOptions(
159
+ routeOptions,
160
+ createFlowAdapter({
161
+ resolvePageModule: async () => ({
162
+ Page,
163
+ integrationSpecificProps: { layoutMode: 'full' },
164
+ }),
165
+ getHtmlTemplate: async () => HtmlTemplate,
166
+ resolvePageData: async () => ({
167
+ props: { title: 'Hello' },
168
+ metadata: { title: 'Hello', description: 'Hello description' },
169
+ }),
170
+ resolveDependencies: async () => [resolvedDependency],
171
+ buildPageBrowserGraph: async () => ({ assets: [pageDependency] }),
172
+ shouldRenderPageComponent: () => true,
173
+ renderPageComponent: async () => ({
174
+ html: '<main>Page</main>',
175
+ canAttachAttributes: true,
176
+ rootTag: 'main',
177
+ integrationName: 'ghtml',
178
+ assets: [componentAsset],
179
+ }),
101
180
  }),
102
- });
181
+ );
103
182
 
104
183
  expect(result.locals).toEqual({ user: 'andee' });
105
184
  expect(result.pageLocals).toEqual({ user: 'andee' });
@@ -121,7 +200,7 @@ describe('RenderPreparationService', () => {
121
200
  cache: { defaultStrategy: 'static' },
122
201
  integrations: [],
123
202
  } as unknown as EcoPagesAppConfig;
124
- const service = new RenderPreparationService(appConfig, assetProcessingService);
203
+ const flow = new RouteRenderOrchestrator(appConfig, assetProcessingService);
125
204
  const HtmlTemplate = (() => '<html></html>') as EcoComponent<HtmlTemplateProps>;
126
205
  const DeferredChild = eco.component<{}, string>({
127
206
  integration: 'react',
@@ -129,10 +208,9 @@ describe('RenderPreparationService', () => {
129
208
  });
130
209
  const Page = (() => '<main>Page</main>') as unknown as EcoPageComponent<any>;
131
210
 
132
- const result = await service.prepare(
211
+ const result = await flow.prepareRenderOptions(
133
212
  { file: '/app/pages/index.tsx', params: {}, query: {} } as unknown as RouteRendererOptions,
134
- 'ghtml',
135
- {
213
+ createFlowAdapter({
136
214
  resolvePageModule: async () => ({
137
215
  Page,
138
216
  integrationSpecificProps: {},
@@ -143,7 +221,7 @@ describe('RenderPreparationService', () => {
143
221
  metadata: { title: 'Page', description: 'Page description' },
144
222
  }),
145
223
  resolveDependencies: async () => [],
146
- buildRouteRenderAssets: async () => [],
224
+ buildPageBrowserGraph: async () => ({ assets: [] }),
147
225
  shouldRenderPageComponent: () => true,
148
226
  renderPageComponent: async () => ({
149
227
  html: DeferredChild({}),
@@ -151,7 +229,7 @@ describe('RenderPreparationService', () => {
151
229
  rootTag: 'span',
152
230
  integrationName: 'ghtml',
153
231
  }),
154
- },
232
+ }),
155
233
  );
156
234
 
157
235
  expect(result.componentRender).toEqual(
@@ -165,9 +243,8 @@ describe('RenderPreparationService', () => {
165
243
  });
166
244
 
167
245
  it('inlines the global injector bootstrap when resolved lazy triggers are present', async () => {
168
- const processDependencies = vi
169
- .fn<AssetProcessingService['processDependencies']>()
170
- .mockImplementation(async (dependencies) =>
246
+ const processDependencies = vi.fn<AssetProcessingService['processDependencies']>().mockImplementation(
247
+ async (dependencies) =>
171
248
  dependencies.map((dependency) => ({
172
249
  kind: dependency.kind,
173
250
  position: dependency.position,
@@ -176,7 +253,7 @@ describe('RenderPreparationService', () => {
176
253
  inline: dependency.inline,
177
254
  packageRole: dependency.packageRole,
178
255
  })) as ProcessedAsset[],
179
- );
256
+ );
180
257
  const assetProcessingService = {
181
258
  processDependencies,
182
259
  } as unknown as AssetProcessingService;
@@ -184,7 +261,7 @@ describe('RenderPreparationService', () => {
184
261
  cache: { defaultStrategy: 'static' },
185
262
  integrations: [],
186
263
  } as unknown as EcoPagesAppConfig;
187
- const service = new RenderPreparationService(appConfig, assetProcessingService);
264
+ const flow = new RouteRenderOrchestrator(appConfig, assetProcessingService);
188
265
  const HtmlTemplate = (() => '<html></html>') as EcoComponent<HtmlTemplateProps>;
189
266
  const Page = (() => '<main>Page</main>') as unknown as EcoPageComponent<any>;
190
267
  Page.config = {
@@ -196,10 +273,9 @@ describe('RenderPreparationService', () => {
196
273
  ],
197
274
  };
198
275
 
199
- await service.prepare(
276
+ await flow.prepareRenderOptions(
200
277
  { file: '/app/pages/index.tsx', params: {}, query: {} } as unknown as RouteRendererOptions,
201
- 'ghtml',
202
- {
278
+ createFlowAdapter({
203
279
  resolvePageModule: async () => ({
204
280
  Page,
205
281
  integrationSpecificProps: {},
@@ -210,10 +286,10 @@ describe('RenderPreparationService', () => {
210
286
  metadata: { title: 'Page', description: 'Page description' },
211
287
  }),
212
288
  resolveDependencies: async () => [],
213
- buildRouteRenderAssets: async () => [],
289
+ buildPageBrowserGraph: async () => ({ assets: [] }),
214
290
  shouldRenderPageComponent: () => false,
215
291
  renderPageComponent: vi.fn(),
216
- },
292
+ }),
217
293
  );
218
294
 
219
295
  expect(processDependencies).toHaveBeenCalledOnce();
@@ -238,20 +314,19 @@ describe('RenderPreparationService', () => {
238
314
  cache: { defaultStrategy: 'static' },
239
315
  integrations: [],
240
316
  } as unknown as EcoPagesAppConfig;
241
- const service = new RenderPreparationService(appConfig, assetProcessingService);
317
+ const flow = new RouteRenderOrchestrator(appConfig, assetProcessingService);
242
318
  const HtmlTemplate = (() => '<html></html>') as EcoComponent<HtmlTemplateProps>;
243
319
  const Page = (() => '<main>Page</main>') as unknown as EcoPageComponent<any>;
244
320
  const renderPageComponent = vi.fn();
245
321
 
246
- const result = await service.prepare(
322
+ const result = await flow.prepareRenderOptions(
247
323
  {
248
324
  file: '/app/pages/index.tsx',
249
325
  params: {},
250
326
  query: {},
251
327
  locals: { hidden: true },
252
328
  } as unknown as RouteRendererOptions,
253
- 'ghtml',
254
- {
329
+ createFlowAdapter({
255
330
  resolvePageModule: async () => ({
256
331
  Page,
257
332
  integrationSpecificProps: {},
@@ -262,10 +337,10 @@ describe('RenderPreparationService', () => {
262
337
  metadata: { title: 'Static page', description: 'Static page description' },
263
338
  }),
264
339
  resolveDependencies: async () => [],
265
- buildRouteRenderAssets: async () => [],
340
+ buildPageBrowserGraph: async () => ({ assets: [] }),
266
341
  shouldRenderPageComponent: () => false,
267
342
  renderPageComponent,
268
- },
343
+ }),
269
344
  );
270
345
 
271
346
  expect(result.locals).toBeUndefined();
@@ -299,7 +374,7 @@ describe('RenderPreparationService', () => {
299
374
  cache: { defaultStrategy: 'static' },
300
375
  integrations: [],
301
376
  } as unknown as EcoPagesAppConfig;
302
- const service = new RenderPreparationService(appConfig, assetProcessingService);
377
+ const flow = new RouteRenderOrchestrator(appConfig, assetProcessingService);
303
378
  const HtmlTemplate = (() => '<html></html>') as EcoComponent<HtmlTemplateProps>;
304
379
  const LitCounter = (() => '<lit-counter count="0"></lit-counter>') as unknown as EcoComponent<object>;
305
380
  LitCounter.config = {
@@ -315,10 +390,9 @@ describe('RenderPreparationService', () => {
315
390
  },
316
391
  };
317
392
 
318
- await service.prepare(
393
+ await flow.prepareRenderOptions(
319
394
  { file: '/app/pages/index.tsx', params: {}, query: {} } as unknown as RouteRendererOptions,
320
- 'ghtml',
321
- {
395
+ createFlowAdapter({
322
396
  resolvePageModule: async () => ({
323
397
  Page,
324
398
  integrationSpecificProps: {},
@@ -329,10 +403,10 @@ describe('RenderPreparationService', () => {
329
403
  metadata: { title: 'Static page', description: 'Static page description' },
330
404
  }),
331
405
  resolveDependencies: async () => [],
332
- buildRouteRenderAssets: async () => [],
406
+ buildPageBrowserGraph: async () => ({ assets: [] }),
333
407
  shouldRenderPageComponent: () => false,
334
408
  renderPageComponent: vi.fn(),
335
- },
409
+ }),
336
410
  );
337
411
 
338
412
  expect(processDependencies).toHaveBeenCalledOnce();
@@ -373,7 +447,7 @@ describe('RenderPreparationService', () => {
373
447
  cache: { defaultStrategy: 'static' },
374
448
  integrations: [],
375
449
  } as unknown as EcoPagesAppConfig;
376
- const service = new RenderPreparationService(appConfig, assetProcessingService);
450
+ const flow = new RouteRenderOrchestrator(appConfig, assetProcessingService);
377
451
  const HtmlTemplate = (() => '<html></html>') as EcoComponent<HtmlTemplateProps>;
378
452
  const LitCounter = (() => '<lit-counter count="0"></lit-counter>') as unknown as EcoComponent<object>;
379
453
  LitCounter.config = {
@@ -389,10 +463,9 @@ describe('RenderPreparationService', () => {
389
463
  },
390
464
  };
391
465
 
392
- const result = await service.prepare(
466
+ const result = await flow.prepareRenderOptions(
393
467
  { file: '/app/pages/index.tsx', params: {}, query: {} } as unknown as RouteRendererOptions,
394
- 'ghtml',
395
- {
468
+ createFlowAdapter({
396
469
  resolvePageModule: async () => ({
397
470
  Page,
398
471
  integrationSpecificProps: {},
@@ -403,10 +476,10 @@ describe('RenderPreparationService', () => {
403
476
  metadata: { title: 'Static page', description: 'Static page description' },
404
477
  }),
405
478
  resolveDependencies: async () => [],
406
- buildRouteRenderAssets: async () => [],
479
+ buildPageBrowserGraph: async () => ({ assets: [] }),
407
480
  shouldRenderPageComponent: () => false,
408
481
  renderPageComponent: vi.fn(),
409
- },
482
+ }),
410
483
  );
411
484
 
412
485
  expect(result.pagePackage).toEqual(
@@ -435,7 +508,7 @@ describe('RenderPreparationService', () => {
435
508
  },
436
509
  ],
437
510
  } as unknown as EcoPagesAppConfig;
438
- const service = new RenderPreparationService(appConfig, assetProcessingService);
511
+ const flow = new RouteRenderOrchestrator(appConfig, assetProcessingService);
439
512
  const HtmlTemplate = (() => '<html></html>') as EcoComponent<HtmlTemplateProps>;
440
513
  const Nested = (() => '<aside>Nested</aside>') as EcoComponent<Record<string, unknown>>;
441
514
  Nested.config = {
@@ -449,10 +522,9 @@ describe('RenderPreparationService', () => {
449
522
  },
450
523
  };
451
524
  await expect(
452
- service.prepare(
525
+ flow.prepareRenderOptions(
453
526
  { file: '/app/pages/404.tsx', params: {}, query: {} } as unknown as RouteRendererOptions,
454
- 'ghtml',
455
- {
527
+ createFlowAdapter({
456
528
  resolvePageModule: async () => ({
457
529
  Page,
458
530
  integrationSpecificProps: {},
@@ -463,10 +535,10 @@ describe('RenderPreparationService', () => {
463
535
  metadata: { title: '404', description: 'Not found' },
464
536
  }),
465
537
  resolveDependencies: async () => [],
466
- buildRouteRenderAssets: async () => [],
538
+ buildPageBrowserGraph: async () => ({ assets: [] }),
467
539
  shouldRenderPageComponent: () => false,
468
540
  renderPageComponent: vi.fn(),
469
- },
541
+ }),
470
542
  ),
471
543
  ).resolves.toEqual(
472
544
  expect.objectContaining({
@@ -474,10 +546,9 @@ describe('RenderPreparationService', () => {
474
546
  }),
475
547
  );
476
548
 
477
- const result = await service.prepare(
549
+ const result = await flow.prepareRenderOptions(
478
550
  { file: '/app/pages/404.tsx', params: {}, query: {} } as unknown as RouteRendererOptions,
479
- 'ghtml',
480
- {
551
+ createFlowAdapter({
481
552
  resolvePageModule: async () => ({
482
553
  Page,
483
554
  integrationSpecificProps: {},
@@ -488,10 +559,10 @@ describe('RenderPreparationService', () => {
488
559
  metadata: { title: '404', description: 'Not found' },
489
560
  }),
490
561
  resolveDependencies: async () => [],
491
- buildRouteRenderAssets: async () => [],
562
+ buildPageBrowserGraph: async () => ({ assets: [] }),
492
563
  shouldRenderPageComponent: () => false,
493
564
  renderPageComponent: vi.fn(),
494
- },
565
+ }),
495
566
  );
496
567
 
497
568
  expect(result.pagePackage).toEqual(
@@ -501,7 +572,7 @@ describe('RenderPreparationService', () => {
501
572
  );
502
573
  });
503
574
 
504
- it('uses an injected boundary planning service when provided', async () => {
575
+ it('uses an injected ownership planning service when provided', async () => {
505
576
  const assetProcessingService = {
506
577
  processDependencies: vi.fn(async () => []),
507
578
  } as unknown as AssetProcessingService;
@@ -509,7 +580,7 @@ describe('RenderPreparationService', () => {
509
580
  cache: { defaultStrategy: 'static' },
510
581
  integrations: [],
511
582
  } as unknown as EcoPagesAppConfig;
512
- const boundaryPlan = {
583
+ const ownershipPlan = {
513
584
  root: {
514
585
  id: 'route:/app/pages/index.tsx',
515
586
  source: 'route',
@@ -527,20 +598,23 @@ describe('RenderPreparationService', () => {
527
598
  foreignEdgeCount: 0,
528
599
  hasValidationErrors: false,
529
600
  validationErrors: [],
530
- } satisfies BoundaryPlan;
531
- const injectedBoundaryPlanningService = {
532
- buildPlan: vi.fn(() => boundaryPlan),
533
- } as unknown as BoundaryPlanningService;
534
- const service = new RenderPreparationService(appConfig, assetProcessingService, {
535
- boundaryPlanningService: injectedBoundaryPlanningService,
601
+ } satisfies OwnershipPlan;
602
+ const injectedOwnershipPlanningService = {
603
+ buildPlan: vi.fn(() => ownershipPlan),
604
+ } as unknown as OwnershipPlanningService;
605
+ const injectedOwnershipValidationService = {
606
+ validate: vi.fn(() => []),
607
+ } as unknown as OwnershipValidationService;
608
+ const flow = new RouteRenderOrchestrator(appConfig, assetProcessingService, {
609
+ ownershipPlanningService: injectedOwnershipPlanningService,
610
+ ownershipValidationService: injectedOwnershipValidationService,
536
611
  });
537
612
  const HtmlTemplate = (() => '<html></html>') as EcoComponent<HtmlTemplateProps>;
538
613
  const Page = (() => '<main>Page</main>') as unknown as EcoPageComponent<any>;
539
614
 
540
- const result = await service.prepare(
615
+ const result = await flow.prepareRenderOptions(
541
616
  { file: '/app/pages/index.tsx', params: {}, query: {} } as unknown as RouteRendererOptions,
542
- 'ghtml',
543
- {
617
+ createFlowAdapter({
544
618
  resolvePageModule: async () => ({
545
619
  Page,
546
620
  integrationSpecificProps: {},
@@ -551,19 +625,20 @@ describe('RenderPreparationService', () => {
551
625
  metadata: { title: 'Page', description: 'Page description' },
552
626
  }),
553
627
  resolveDependencies: async () => [],
554
- buildRouteRenderAssets: async () => [],
628
+ buildPageBrowserGraph: async () => ({ assets: [] }),
555
629
  shouldRenderPageComponent: () => false,
556
630
  renderPageComponent: vi.fn(),
557
- },
631
+ }),
558
632
  );
559
633
 
560
- expect(injectedBoundaryPlanningService.buildPlan).toHaveBeenCalledWith({
634
+ expect(injectedOwnershipPlanningService.buildPlan).toHaveBeenCalledWith({
561
635
  routeFile: '/app/pages/index.tsx',
562
636
  currentIntegrationName: 'ghtml',
563
637
  HtmlTemplate,
564
638
  Layout: undefined,
565
639
  Page,
640
+ validationErrors: [],
566
641
  });
567
- expect(result.boundaryPlan).toBe(boundaryPlan);
642
+ expect(result.ownershipPlan).toBe(ownershipPlan);
568
643
  });
569
644
  });